<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Claude Code Documentation</title>
<link>https://code.claude.com/docs/en/overview</link>
<description>Claude Code AI coding assistant documentation</description>
<language>en</language>
<lastBuildDate>Mon, 18 May 2026 03:12:37 +0000</lastBuildDate>
<generator>ForgeRSS</generator>
<atom:link href="https://code.claude.com/docs/en/overview" rel="self" type="application/rss+xml"/>
<image>
  <url>https://code.claude.com/favicon.ico</url>
  <title>Claude Code Documentation</title>
  <link>https://code.claude.com/docs/en/overview</link>
</image>
<item>
  <title>Push events into a running session with channels</title>
  <link>https://code.claude.com/docs/en/channels</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/channels</guid>
  <pubDate>Mon, 30 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Push events into a running session with channels
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Laun...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Push events into a running session with channels
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require Claude Code v2.1.80 or later. They require Anthropic authentication through claude.ai or a Console API key, and are not available on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Team and Enterprise organizations must
explicitly enable them
.
A channel is an MCP server that pushes events into your running Claude Code session, so Claude can react to things that happen while you’re not at the terminal. Channels can be two-way: Claude reads the event and replies back through the same channel, like a chat bridge. Events only arrive while the session is open, so for an always-on setup you run Claude in a background process or persistent terminal.
Unlike integrations that spawn a fresh cloud session or wait to be polled, the event arrives in the session you already have open: see
how channels compare
.
You install a channel as a plugin and configure it with your own credentials. Telegram, Discord, and iMessage are included in the research preview.
When Claude replies through a channel, you see the inbound message in your terminal but not the reply text. The terminal shows the tool call and a confirmation (like “sent”), and the actual reply appears on the other platform.
This page covers:
Supported channels
: Telegram, Discord, and iMessage setup
Install and run a channel
with fakechat, a localhost demo
Who can push messages
: sender allowlists and how you pair
Enable channels for your organization
if you manage a Team, Enterprise, or Console org
How channels compare
to web sessions, Slack, MCP, and Remote Control
To build your own channel, see the
Channels reference
.
​
Supported channels
Each supported channel is a plugin that requires
Bun
. For a hands-on demo of the plugin flow before connecting a real platform, try the
fakechat quickstart
.
Telegram
Discord
iMessage
View the full
Telegram plugin source
.
1
Create a Telegram bot
Open
BotFather
in Telegram and send
/newbot
. Give it a display name and a unique username ending in
bot
. Copy the token BotFather returns.
2
Install the plugin
In Claude Code, run:
/plugin install telegram@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
After installing, run
/reload-plugins
to activate the plugin’s configure command.
3
Configure your token
Run the configure command with the token from BotFather:
/telegram:configure <token>
This saves it to
~/.claude/channels/telegram/.env
. You can also set
TELEGRAM_BOT_TOKEN
in your shell environment before launching Claude Code.
4
Restart with channels enabled
Exit Claude Code and restart with the channel flag. This starts the Telegram plugin, which begins polling for messages from your bot:
claude
--channels
plugin:telegram@claude-plugins-official
5
Pair your account
Open Telegram and send any message to your bot. The bot replies with a pairing code.
If your bot doesn’t respond, make sure Claude Code is running with
--channels
from the previous step. The bot can only reply while the channel is active.
Back in Claude Code, run:
/telegram:access pair <code>
Then lock down access so only your account can send messages:
/telegram:access policy allowlist
View the full
Discord plugin source
.
1
Create a Discord bot
Go to the
Discord Developer Portal
, click
New Application
, and name it. In the
Bot
section, create a username, then click
Reset Token
and copy the token.
2
Enable Message Content Intent
In your bot’s settings, scroll to
Privileged Gateway Intents
and enable
Message Content Intent
.
3
Invite the bot to your server
Go to
OAuth2 > URL Generator
. Select the
bot
scope and enable these permissions:
View Channels
Send Messages
Send Messages in Threads
Read Message History
Attach Files
Add Reactions
Open the generated URL to add the bot to your server.
4
Install the plugin
In Claude Code, run:
/plugin install discord@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
After installing, run
/reload-plugins
to activate the plugin’s configure command.
5
Configure your token
Run the configure command with the bot token you copied:
/discord:configure <token>
This saves it to
~/.claude/channels/discord/.env
. You can also set
DISCORD_BOT_TOKEN
in your shell environment before launching Claude Code.
6
Restart with channels enabled
Exit Claude Code and restart with the channel flag. This connects the Discord plugin so your bot can receive and respond to messages:
claude
--channels
plugin:discord@claude-plugins-official
7
Pair your account
DM your bot on Discord. The bot replies with a pairing code.
If your bot doesn’t respond, make sure Claude Code is running with
--channels
from the previous step. The bot can only reply while the channel is active.
Back in Claude Code, run:
/discord:access pair <code>
Then lock down access so only your account can send messages:
/discord:access policy allowlist
View the full
iMessage plugin source
.
The iMessage channel reads your Messages database directly and sends replies through AppleScript. It requires macOS and needs no bot token or external service.
1
Grant Full Disk Access
The Messages database at
~/Library/Messages/chat.db
is protected by macOS. The first time the server reads it, macOS prompts for access: click
Allow
. The prompt names whichever app launched Bun, such as Terminal, iTerm, or your IDE.
If the prompt doesn’t appear or you clicked Don’t Allow, grant access manually under
System Settings > Privacy & Security > Full Disk Access
and add your terminal. Without this, the server exits immediately with
authorization denied
.
2
Install the plugin
In Claude Code, run:
/plugin install imessage@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
3
Restart with channels enabled
Exit Claude Code and restart with the channel flag:
claude
--channels
plugin:imessage@claude-plugins-official
4
Text yourself
Open Messages on any device signed into your Apple ID and send a message to yourself. It reaches Claude immediately: self-chat bypasses access control with no setup.
The first reply Claude sends triggers a macOS Automation prompt asking if your terminal can control Messages. Click
OK
.
5
Allow other senders
By default, only your own messages pass through. To let another contact reach Claude, add their handle:
/imessage:access allow +15551234567
Handles are phone numbers in
+country
format or Apple ID emails like
user@example.com
.
You can also
build your own channel
for systems that don’t have a plugin yet.
​
Quickstart
Fakechat is an officially supported demo channel that runs a chat UI on localhost, with nothing to authenticate and no external service to configure.
Once you install and enable fakechat, you can type in the browser and the message arrives in your Claude Code session. Claude replies, and the reply shows up back in the browser. After you’ve tested the fakechat interface, try out
Telegram
,
Discord
, or
iMessage
.
To try the fakechat demo, you’ll need:
Claude Code
installed and authenticated
with a claude.ai account or a Claude Console API key
Bun
installed. The pre-built channel plugins are Bun scripts. Check with
bun --version
; if that fails,
install Bun
.
Team, Enterprise, or managed Console org
: your admin must
enable channels
in managed settings
1
Install the fakechat channel plugin
Start a Claude Code session and run the install command:
/plugin install fakechat@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
2
Restart with the channel enabled
Exit Claude Code, then restart with
--channels
and pass the fakechat plugin you installed:
claude
--channels
plugin:fakechat@claude-plugins-official
The fakechat server starts automatically.
You can pass several plugins to
--channels
, space-separated.
3
Push a message in
Open the fakechat UI at
http://localhost:8787
and type a message:
hey, what's in my working directory?
The message arrives in your Claude Code session as a
<channel source="fakechat">
event. Claude reads it, does the work, and calls fakechat’s
reply
tool. The answer shows up in the chat UI.
If Claude hits a permission prompt while you’re away from the terminal, the session pauses until you respond. Channel servers that declare the
permission relay capability
can forward these prompts to you so you can approve or deny remotely. For unattended use,
--dangerously-skip-permissions
bypasses prompts entirely, but only use it in environments you trust.
When you run channels in non-interactive mode with
-p
, tools that need terminal input, such as multiple-choice questions and plan mode approval, are disabled so the session never stalls waiting for input.
​
Security
Every approved channel plugin maintains a sender allowlist: only IDs you’ve added can push messages, and everyone else is silently dropped.
Telegram and Discord bootstrap the list by pairing:
Find your bot in Telegram or Discord and send it any message
The bot replies with a pairing code
In your Claude Code session, approve the code when prompted
Your sender ID is added to the allowlist
iMessage works differently: texting yourself bypasses the gate automatically, and you add other contacts by handle with
/imessage:access allow
.
On top of that, you control which servers are enabled each session with
--channels
, and your organization controls availability with
channelsEnabled
on claude.ai Team and Enterprise plans and on Console organizations that deploy managed settings.
Being in
.mcp.json
isn’t enough to push messages: a server also has to be named in
--channels
.
The allowlist also gates
permission relay
if the channel declares it. Anyone who can reply through the channel can approve or deny tool use in your session, so only allowlist senders you trust with that authority.
​
Enterprise controls
Admins control availability through two
managed settings
that users cannot override. The default depends on how you authenticate:
claude.ai Team and Enterprise
: channels are blocked until an admin enables them.
Anthropic Console with API key authentication
: channels are permitted by default. You only need this setting if your organization deploys managed settings.
In all cases, no channel runs until a user opts it in for the session with
--channels
.
Setting
Purpose
When not configured
channelsEnabled
Master switch. Must be
true
for any channel to deliver messages. Set via the
claude.ai Admin console
toggle or directly in managed settings. Blocks all channels including the development flag when off.
claude.ai Team and Enterprise: channels blocked. Console: channels allowed unless your organization deploys managed settings, in which case channels are blocked until this key is set
allowedChannelPlugins
Which plugins can register once channels are enabled. Replaces the Anthropic-maintained list when set. Only applies when
channelsEnabled
is
true
.
Anthropic default list applies
Pro and Max users without an organization skip these checks entirely: channels are available and users opt in per session with
--channels
.
​
Enable channels for your organization
Admins can enable channels from
claude.ai → Admin settings → Claude Code → Channels
, or by setting
channelsEnabled
to
true
in managed settings.
Once enabled, users in your organization can use
--channels
to opt channel servers into individual sessions. If the setting is disabled or unset, the MCP server still connects and its tools work, but channel messages won’t arrive. A startup warning tells the user to have an admin enable the setting.
​
Restrict which channel plugins can run
By default, any plugin on the Anthropic-maintained allowlist can register as a channel. Admins on Team and Enterprise plans can replace that allowlist with their own by setting
allowedChannelPlugins
in managed settings. Use this to restrict which official plugins are allowed, approve channels from your own internal marketplace, or both. Each entry names a plugin and the marketplace it comes from:
{
"channelsEnabled"
:
true
,
"allowedChannelPlugins"
: [
{
"marketplace"
:
"claude-plugins-official"
,
"plugin"
:
"telegram"
},
{
"marketplace"
:
"claude-plugins-official"
,
"plugin"
:
"discord"
},
{
"marketplace"
:
"acme-corp-plugins"
,
"plugin"
:
"internal-alerts"
}
]
}
When
allowedChannelPlugins
is set, it replaces the Anthropic allowlist entirely: only the listed plugins can register. Leave it unset to fall back to the default Anthropic allowlist. An empty array blocks all channel plugins from the allowlist, but
--dangerously-load-development-channels
can still bypass it for local testing. To block channels entirely including the development flag, leave
channelsEnabled
unset instead.
This setting requires
channelsEnabled: true
. If a user passes a plugin to
--channels
that isn’t on your list, Claude Code starts normally but the channel doesn’t register, and the startup notice explains that the plugin isn’t on the organization’s approved list.
​
Research preview
Channels are a research preview feature. Availability is rolling out gradually, and the
--channels
flag syntax and protocol contract may change based on feedback.
During the preview,
--channels
only accepts plugins from an Anthropic-maintained allowlist, or from your organization’s allowlist if an admin has set
allowedChannelPlugins
. The channel plugins in
claude-plugins-official
are the default approved set. If you pass something that isn’t on the effective allowlist, Claude Code starts normally but the channel doesn’t register, and the startup notice tells you why.
To test a channel you’re building, use
--dangerously-load-development-channels
. See
Test during the research preview
for information about testing custom channels that you build.
Report issues or feedback on the
Claude Code GitHub repository
.
​
How channels compare
Several Claude Code features connect to systems outside the terminal, each suited to a different kind of work:
Feature
What it does
Good for
Claude Code on the web
Runs tasks in a fresh cloud sandbox, cloned from GitHub
Delegating self-contained async work you check on later
Claude in Slack
Spawns a web session from an
@Claude
mention in a channel or thread
Starting tasks directly from team conversation context
Standard
MCP server
Claude queries it during a task; nothing is pushed to the session
Giving Claude on-demand access to read or query a system
Remote Control
You drive your local session from claude.ai or the Claude mobile app
Steering an in-progress session while away from your desk
Channels fill the gap in that list by pushing events from non-Claude sources into your already-running local session.
Chat bridge
: ask Claude something from your phone via Telegram, Discord, or iMessage, and the answer comes back in the same chat while the work runs on your machine against your real files.
Webhook receiver
: a webhook from CI, your error tracker, a deploy pipeline, or other external service arrives where Claude already has your files open and remembers what you were debugging.
​
Next steps
Once you have a channel running, explore these related features:
Build your own channel
for systems that don’t have plugins yet
Remote Control
to drive a local session from your phone instead of forwarding events into it
Scheduled tasks
to poll on a timer instead of reacting to pushed events
Was this page helpful?
Yes
No
Automate with hooks
Run prompts on a schedule
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/channels" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Push events into a running session with channels
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Laun...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Push events into a running session with channels
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require Claude Code v2.1.80 or later. They require Anthropic authentication through claude.ai or a Console API key, and are not available on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Team and Enterprise organizations must
explicitly enable them
.
A channel is an MCP server that pushes events into your running Claude Code session, so Claude can react to things that happen while you’re not at the terminal. Channels can be two-way: Claude reads the event and replies back through the same channel, like a chat bridge. Events only arrive while the session is open, so for an always-on setup you run Claude in a background process or persistent terminal.
Unlike integrations that spawn a fresh cloud session or wait to be polled, the event arrives in the session you already have open: see
how channels compare
.
You install a channel as a plugin and configure it with your own credentials. Telegram, Discord, and iMessage are included in the research preview.
When Claude replies through a channel, you see the inbound message in your terminal but not the reply text. The terminal shows the tool call and a confirmation (like “sent”), and the actual reply appears on the other platform.
This page covers:
Supported channels
: Telegram, Discord, and iMessage setup
Install and run a channel
with fakechat, a localhost demo
Who can push messages
: sender allowlists and how you pair
Enable channels for your organization
if you manage a Team, Enterprise, or Console org
How channels compare
to web sessions, Slack, MCP, and Remote Control
To build your own channel, see the
Channels reference
.
​
Supported channels
Each supported channel is a plugin that requires
Bun
. For a hands-on demo of the plugin flow before connecting a real platform, try the
fakechat quickstart
.
Telegram
Discord
iMessage
View the full
Telegram plugin source
.
1
Create a Telegram bot
Open
BotFather
in Telegram and send
/newbot
. Give it a display name and a unique username ending in
bot
. Copy the token BotFather returns.
2
Install the plugin
In Claude Code, run:
/plugin install telegram@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
After installing, run
/reload-plugins
to activate the plugin’s configure command.
3
Configure your token
Run the configure command with the token from BotFather:
/telegram:configure <token>
This saves it to
~/.claude/channels/telegram/.env
. You can also set
TELEGRAM_BOT_TOKEN
in your shell environment before launching Claude Code.
4
Restart with channels enabled
Exit Claude Code and restart with the channel flag. This starts the Telegram plugin, which begins polling for messages from your bot:
claude
--channels
plugin:telegram@claude-plugins-official
5
Pair your account
Open Telegram and send any message to your bot. The bot replies with a pairing code.
If your bot doesn’t respond, make sure Claude Code is running with
--channels
from the previous step. The bot can only reply while the channel is active.
Back in Claude Code, run:
/telegram:access pair <code>
Then lock down access so only your account can send messages:
/telegram:access policy allowlist
View the full
Discord plugin source
.
1
Create a Discord bot
Go to the
Discord Developer Portal
, click
New Application
, and name it. In the
Bot
section, create a username, then click
Reset Token
and copy the token.
2
Enable Message Content Intent
In your bot’s settings, scroll to
Privileged Gateway Intents
and enable
Message Content Intent
.
3
Invite the bot to your server
Go to
OAuth2 > URL Generator
. Select the
bot
scope and enable these permissions:
View Channels
Send Messages
Send Messages in Threads
Read Message History
Attach Files
Add Reactions
Open the generated URL to add the bot to your server.
4
Install the plugin
In Claude Code, run:
/plugin install discord@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
After installing, run
/reload-plugins
to activate the plugin’s configure command.
5
Configure your token
Run the configure command with the bot token you copied:
/discord:configure <token>
This saves it to
~/.claude/channels/discord/.env
. You can also set
DISCORD_BOT_TOKEN
in your shell environment before launching Claude Code.
6
Restart with channels enabled
Exit Claude Code and restart with the channel flag. This connects the Discord plugin so your bot can receive and respond to messages:
claude
--channels
plugin:discord@claude-plugins-official
7
Pair your account
DM your bot on Discord. The bot replies with a pairing code.
If your bot doesn’t respond, make sure Claude Code is running with
--channels
from the previous step. The bot can only reply while the channel is active.
Back in Claude Code, run:
/discord:access pair <code>
Then lock down access so only your account can send messages:
/discord:access policy allowlist
View the full
iMessage plugin source
.
The iMessage channel reads your Messages database directly and sends replies through AppleScript. It requires macOS and needs no bot token or external service.
1
Grant Full Disk Access
The Messages database at
~/Library/Messages/chat.db
is protected by macOS. The first time the server reads it, macOS prompts for access: click
Allow
. The prompt names whichever app launched Bun, such as Terminal, iTerm, or your IDE.
If the prompt doesn’t appear or you clicked Don’t Allow, grant access manually under
System Settings > Privacy & Security > Full Disk Access
and add your terminal. Without this, the server exits immediately with
authorization denied
.
2
Install the plugin
In Claude Code, run:
/plugin install imessage@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
3
Restart with channels enabled
Exit Claude Code and restart with the channel flag:
claude
--channels
plugin:imessage@claude-plugins-official
4
Text yourself
Open Messages on any device signed into your Apple ID and send a message to yourself. It reaches Claude immediately: self-chat bypasses access control with no setup.
The first reply Claude sends triggers a macOS Automation prompt asking if your terminal can control Messages. Click
OK
.
5
Allow other senders
By default, only your own messages pass through. To let another contact reach Claude, add their handle:
/imessage:access allow +15551234567
Handles are phone numbers in
+country
format or Apple ID emails like
user@example.com
.
You can also
build your own channel
for systems that don’t have a plugin yet.
​
Quickstart
Fakechat is an officially supported demo channel that runs a chat UI on localhost, with nothing to authenticate and no external service to configure.
Once you install and enable fakechat, you can type in the browser and the message arrives in your Claude Code session. Claude replies, and the reply shows up back in the browser. After you’ve tested the fakechat interface, try out
Telegram
,
Discord
, or
iMessage
.
To try the fakechat demo, you’ll need:
Claude Code
installed and authenticated
with a claude.ai account or a Claude Console API key
Bun
installed. The pre-built channel plugins are Bun scripts. Check with
bun --version
; if that fails,
install Bun
.
Team, Enterprise, or managed Console org
: your admin must
enable channels
in managed settings
1
Install the fakechat channel plugin
Start a Claude Code session and run the install command:
/plugin install fakechat@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
2
Restart with the channel enabled
Exit Claude Code, then restart with
--channels
and pass the fakechat plugin you installed:
claude
--channels
plugin:fakechat@claude-plugins-official
The fakechat server starts automatically.
You can pass several plugins to
--channels
, space-separated.
3
Push a message in
Open the fakechat UI at
http://localhost:8787
and type a message:
hey, what's in my working directory?
The message arrives in your Claude Code session as a
<channel source="fakechat">
event. Claude reads it, does the work, and calls fakechat’s
reply
tool. The answer shows up in the chat UI.
If Claude hits a permission prompt while you’re away from the terminal, the session pauses until you respond. Channel servers that declare the
permission relay capability
can forward these prompts to you so you can approve or deny remotely. For unattended use,
--dangerously-skip-permissions
bypasses prompts entirely, but only use it in environments you trust.
When you run channels in non-interactive mode with
-p
, tools that need terminal input, such as multiple-choice questions and plan mode approval, are disabled so the session never stalls waiting for input.
​
Security
Every approved channel plugin maintains a sender allowlist: only IDs you’ve added can push messages, and everyone else is silently dropped.
Telegram and Discord bootstrap the list by pairing:
Find your bot in Telegram or Discord and send it any message
The bot replies with a pairing code
In your Claude Code session, approve the code when prompted
Your sender ID is added to the allowlist
iMessage works differently: texting yourself bypasses the gate automatically, and you add other contacts by handle with
/imessage:access allow
.
On top of that, you control which servers are enabled each session with
--channels
, and your organization controls availability with
channelsEnabled
on claude.ai Team and Enterprise plans and on Console organizations that deploy managed settings.
Being in
.mcp.json
isn’t enough to push messages: a server also has to be named in
--channels
.
The allowlist also gates
permission relay
if the channel declares it. Anyone who can reply through the channel can approve or deny tool use in your session, so only allowlist senders you trust with that authority.
​
Enterprise controls
Admins control availability through two
managed settings
that users cannot override. The default depends on how you authenticate:
claude.ai Team and Enterprise
: channels are blocked until an admin enables them.
Anthropic Console with API key authentication
: channels are permitted by default. You only need this setting if your organization deploys managed settings.
In all cases, no channel runs until a user opts it in for the session with
--channels
.
Setting
Purpose
When not configured
channelsEnabled
Master switch. Must be
true
for any channel to deliver messages. Set via the
claude.ai Admin console
toggle or directly in managed settings. Blocks all channels including the development flag when off.
claude.ai Team and Enterprise: channels blocked. Console: channels allowed unless your organization deploys managed settings, in which case channels are blocked until this key is set
allowedChannelPlugins
Which plugins can register once channels are enabled. Replaces the Anthropic-maintained list when set. Only applies when
channelsEnabled
is
true
.
Anthropic default list applies
Pro and Max users without an organization skip these checks entirely: channels are available and users opt in per session with
--channels
.
​
Enable channels for your organization
Admins can enable channels from
claude.ai → Admin settings → Claude Code → Channels
, or by setting
channelsEnabled
to
true
in managed settings.
Once enabled, users in your organization can use
--channels
to opt channel servers into individual sessions. If the setting is disabled or unset, the MCP server still connects and its tools work, but channel messages won’t arrive. A startup warning tells the user to have an admin enable the setting.
​
Restrict which channel plugins can run
By default, any plugin on the Anthropic-maintained allowlist can register as a channel. Admins on Team and Enterprise plans can replace that allowlist with their own by setting
allowedChannelPlugins
in managed settings. Use this to restrict which official plugins are allowed, approve channels from your own internal marketplace, or both. Each entry names a plugin and the marketplace it comes from:
{
"channelsEnabled"
:
true
,
"allowedChannelPlugins"
: [
{
"marketplace"
:
"claude-plugins-official"
,
"plugin"
:
"telegram"
},
{
"marketplace"
:
"claude-plugins-official"
,
"plugin"
:
"discord"
},
{
"marketplace"
:
"acme-corp-plugins"
,
"plugin"
:
"internal-alerts"
}
]
}
When
allowedChannelPlugins
is set, it replaces the Anthropic allowlist entirely: only the listed plugins can register. Leave it unset to fall back to the default Anthropic allowlist. An empty array blocks all channel plugins from the allowlist, but
--dangerously-load-development-channels
can still bypass it for local testing. To block channels entirely including the development flag, leave
channelsEnabled
unset instead.
This setting requires
channelsEnabled: true
. If a user passes a plugin to
--channels
that isn’t on your list, Claude Code starts normally but the channel doesn’t register, and the startup notice explains that the plugin isn’t on the organization’s approved list.
​
Research preview
Channels are a research preview feature. Availability is rolling out gradually, and the
--channels
flag syntax and protocol contract may change based on feedback.
During the preview,
--channels
only accepts plugins from an Anthropic-maintained allowlist, or from your organization’s allowlist if an admin has set
allowedChannelPlugins
. The channel plugins in
claude-plugins-official
are the default approved set. If you pass something that isn’t on the effective allowlist, Claude Code starts normally but the channel doesn’t register, and the startup notice tells you why.
To test a channel you’re building, use
--dangerously-load-development-channels
. See
Test during the research preview
for information about testing custom channels that you build.
Report issues or feedback on the
Claude Code GitHub repository
.
​
How channels compare
Several Claude Code features connect to systems outside the terminal, each suited to a different kind of work:
Feature
What it does
Good for
Claude Code on the web
Runs tasks in a fresh cloud sandbox, cloned from GitHub
Delegating self-contained async work you check on later
Claude in Slack
Spawns a web session from an
@Claude
mention in a channel or thread
Starting tasks directly from team conversation context
Standard
MCP server
Claude queries it during a task; nothing is pushed to the session
Giving Claude on-demand access to read or query a system
Remote Control
You drive your local session from claude.ai or the Claude mobile app
Steering an in-progress session while away from your desk
Channels fill the gap in that list by pushing events from non-Claude sources into your already-running local session.
Chat bridge
: ask Claude something from your phone via Telegram, Discord, or iMessage, and the answer comes back in the same chat while the work runs on your machine against your real files.
Webhook receiver
: a webhook from CI, your error tracker, a deploy pipeline, or other external service arrives where Claude already has your files open and remembers what you were debugging.
​
Next steps
Once you have a channel running, explore these related features:
Build your own channel
for systems that don’t have plugins yet
Remote Control
to drive a local session from your phone instead of forwarding events into it
Scheduled tasks
to poll on a timer instead of reacting to pushed events
Was this page helpful?
Yes
No
Automate with hooks
Run prompts on a schedule
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/channels" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Continue local sessions from any device with Remote Control</title>
  <link>https://code.claude.com/docs/en/remote-control</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/remote-control</guid>
  <pubDate>Tue, 24 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Continue local sessions from any device with Remote Control
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Clau...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Continue local sessions from any device with Remote Control
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Remote Control is in research preview and available on all plans. On Team and Enterprise, it is off by default until an admin enables the Remote Control toggle in
Claude Code admin settings
.
Remote Control connects
claude.ai/code
or the Claude app for
iOS
and
Android
to a Claude Code session running on your machine. Start a task at your desk, then pick it up from your phone on the couch or a browser on another computer.
When you start a Remote Control session on your machine, Claude keeps running locally the entire time, so nothing moves to the cloud. With Remote Control you can:
Use your full local environment remotely
: your filesystem,
MCP servers
, tools, and project configuration all stay available, and typing
@
autocompletes file paths from your local project
Work from both surfaces at once
: the conversation stays in sync across all connected devices, so you can send messages from your terminal, browser, and phone interchangeably
Survive interruptions
: if your laptop sleeps or your network drops, the session reconnects automatically when your machine comes back online
Unlike
Claude Code on the web
, which runs on cloud infrastructure, Remote Control sessions run directly on your machine and interact with your local filesystem. The web and mobile interfaces are just a window into that local session.
Remote Control requires Claude Code v2.1.51 or later. Check your version with
claude --version
.
This page covers setup, how to start and connect to sessions, and how Remote Control compares to Claude Code on the web.
​
Requirements
Before using Remote Control, confirm that your environment meets these conditions:
Subscription
: available on Pro, Max, Team, and Enterprise plans. API keys are not supported. On Team and Enterprise, an admin must first enable the Remote Control toggle in
Claude Code admin settings
.
Authentication
: run
claude
and use
/login
to sign in through claude.ai if you haven’t already.
Workspace trust
: run
claude
in your project directory at least once to accept the workspace trust dialog.
​
Start a Remote Control session
You can start a Remote Control session from the CLI or the VS Code extension. The CLI offers three invocation modes; VS Code uses the
/remote-control
command.
Server mode
Interactive session
From an existing session
VS Code
Navigate to your project directory and run:
claude
remote-control
The process stays running in your terminal in server mode, waiting for remote connections. It displays a session URL you can use to
connect from another device
, and you can press spacebar to show a QR code for quick access from your phone. While a remote session is active, the terminal shows connection status and tool activity.
Available flags:
Flag
Description
--name "My Project"
Set a custom session title visible in the session list at claude.ai/code.
--remote-control-session-name-prefix <prefix>
Prefix for auto-generated session names when no explicit name is set. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. Set
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
for the same effect.
--spawn <mode>
How the server creates sessions.
•
same-dir
(default): all sessions share the current working directory, so they can conflict if editing the same files.
•
worktree
: each on-demand session gets its own
git worktree
. Requires a git repository.
•
session
: single-session mode. Serves exactly one session and rejects additional connections. Set at startup only.
Press
w
at runtime to toggle between
same-dir
and
worktree
.
--capacity <N>
Maximum number of concurrent sessions. Default is 32. Cannot be used with
--spawn=session
.
--verbose
Show detailed connection and session logs.
--sandbox
/
--no-sandbox
Enable or disable
sandboxing
for filesystem and network isolation. Off by default.
To start a normal interactive Claude Code session with Remote Control enabled, use the
--remote-control
flag (or
--rc
):
claude
--remote-control
Optionally pass a name for the session:
claude
--remote-control
"My Project"
This gives you a full interactive session in your terminal that you can also control from claude.ai or the Claude app. Unlike
claude remote-control
(server mode), you can type messages locally while the session is also available remotely.
If you’re already in a Claude Code session and want to continue it remotely, use the
/remote-control
(or
/rc
) command:
/remote-control
Pass a name as an argument to set a custom session title:
/remote-control My Project
This starts a Remote Control session that carries over your current conversation history and displays a session URL and QR code you can use to
connect from another device
. The
--verbose
,
--sandbox
, and
--no-sandbox
flags are not available with this command.
In the
Claude Code VS Code extension
, type
/remote-control
or
/rc
in the prompt box, or open the command menu with
/
and select it. Requires Claude Code v2.1.79 or later.
/remote-control
A banner appears above the prompt box showing connection status. Once connected, click
Open in browser
in the banner to go directly to the session, or find it in the session list at
claude.ai/code
. The session URL is also posted in the conversation.
To disconnect, click the close icon on the banner or run
/remote-control
again.
Unlike the CLI, the VS Code command does not accept a name argument or display a QR code. The session title is derived from your conversation history or first prompt.
​
Connect from another device
Once a Remote Control session is active, you have a few ways to connect from another device:
Open the session URL
in any browser to go directly to the session on
claude.ai/code
.
Scan the QR code
shown alongside the session URL to open it directly in the Claude app. With
claude remote-control
, press spacebar to toggle the QR code display.
Open
claude.ai/code
or the Claude app
and find the session by name in the session list. In the Claude mobile app, tap
Code
in the navigation to reach the session list. Remote Control sessions show a computer icon with a green status dot when online.
The remote session title is chosen in this order:
The name you passed to
--name
,
--remote-control
, or
/remote-control
The title you set with
/rename
The last meaningful message in existing conversation history
An auto-generated name like
myhost-graceful-unicorn
, where
myhost
is your machine’s hostname or the prefix you set with
--remote-control-session-name-prefix
If you didn’t set an explicit name, the title updates to reflect your prompt once you send one.
If the environment already has an active session, you’ll be asked whether to continue it or start a new one.
If you don’t have the Claude app yet, use the
/mobile
command inside Claude Code to display a download QR code for
iOS
or
Android
.
​
Enable Remote Control for all sessions
By default, Remote Control only activates when you explicitly run
claude remote-control
,
claude --remote-control
, or
/remote-control
. To enable it automatically for every interactive session, run
/config
inside Claude Code and set
Enable Remote Control for all sessions
to
true
. Set it back to
false
to disable. In the Desktop app, you can also toggle this from
Settings → Claude Code → Enable remote control by default
.
With this setting on, each interactive Claude Code process registers one remote session. If you run multiple instances, each one gets its own environment and session. To run multiple concurrent sessions from a single process, use
server mode
instead.
​
Connection and security
Your local Claude Code session makes outbound HTTPS requests only and never opens inbound ports on your machine. When you start Remote Control, it registers with the Anthropic API and polls for work. When you connect from another device, the server routes messages between the web or mobile client and your local session over a streaming connection.
All traffic travels through the Anthropic API over TLS, the same transport security as any Claude Code session. The connection uses multiple short-lived credentials, each scoped to a single purpose and expiring independently.
​
Remote Control vs Claude Code on the web
Remote Control and
Claude Code on the web
both use the claude.ai/code interface. The key difference is where the session runs: Remote Control executes on your machine, so your local MCP servers, tools, and project configuration stay available. Claude Code on the web executes in Anthropic-managed cloud infrastructure.
Use Remote Control when you’re in the middle of local work and want to keep going from another device. Use Claude Code on the web when you want to kick off a task without any local setup, work on a repo you don’t have cloned, or run multiple tasks in parallel.
​
Mobile push notifications
When Remote Control is active, Claude can send push notifications to your phone.
Claude decides when to push. It typically sends one when a long-running task finishes or when it needs a decision from you to continue. You can also request a push in your prompt, for example
notify me when the tests finish
. Beyond the on/off toggle below, there is no per-event configuration.
Mobile push notifications require Claude Code v2.1.110 or later.
To set up mobile push notifications:
1
Install the Claude mobile app
Download the Claude app for
iOS
or
Android
.
2
Sign in with your Claude Code account
Use the same account and organization you use for Claude Code in the terminal.
3
Allow notifications
Accept the notification permission prompt from the operating system.
4
Enable push in Claude Code
In your terminal, run
/config
and enable
Push when Claude decides
.
If notifications don’t arrive:
If
/config
shows
No mobile registered
, open the Claude app on your phone so it can refresh its push token. The warning clears the next time Remote Control connects.
On iOS, Focus modes and notification summaries can suppress or delay pushes. Check Settings → Notifications → Claude.
On Android, aggressive battery optimization can delay delivery. Exempt the Claude app from battery optimization in system settings.
​
Limitations
One remote session per interactive process
: outside of server mode, each Claude Code instance supports one remote session at a time. Use
server mode
to run multiple concurrent sessions from a single process.
Local process must keep running
: Remote Control runs as a local process. If you close the terminal, quit VS Code, or otherwise stop the
claude
process, the session ends.
Extended network outage
: if your machine is awake but unable to reach the network for more than roughly 10 minutes, the session times out and the process exits. Run
claude remote-control
again to start a new session.
Ultraplan disconnects Remote Control
: starting an
ultraplan
session disconnects any active Remote Control session because both features occupy the claude.ai/code interface and only one can be connected at a time.
Some commands are local-only
: commands that open an interactive picker in the terminal, such as
/mcp
,
/plugin
, or
/resume
, work only from the local CLI. Commands that produce text output, including
/compact
,
/clear
,
/context
,
/usage
,
/exit
,
/extra-usage
,
/recap
, and
/reload-plugins
, work from mobile and web.
​
Troubleshooting
​
”Remote Control requires a claude.ai subscription”
You’re not authenticated with a claude.ai account. Run
claude auth login
and choose the claude.ai option. If
ANTHROPIC_API_KEY
is set in your environment, unset it first.
​
”Remote Control requires a full-scope login token”
You’re authenticated with a long-lived token from
claude setup-token
or the
CLAUDE_CODE_OAUTH_TOKEN
environment variable. These tokens are limited to inference-only and cannot establish Remote Control sessions. Run
claude auth login
to authenticate with a full-scope session token instead.
​
”Unable to determine your organization for Remote Control eligibility”
Your cached account information is stale or incomplete. Run
claude auth login
to refresh it.
​
”Remote Control is not yet enabled for your account”
The eligibility check can fail with certain environment variables present:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
or
DISABLE_TELEMETRY
: unset them and try again.
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_VERTEX
, or
CLAUDE_CODE_USE_FOUNDRY
: Remote Control requires claude.ai authentication and does not work with third-party providers.
If none of these are set, run
/logout
then
/login
to refresh.
​
”Remote Control is disabled by your organization’s policy”
This error has four distinct causes. Run
/status
first to see which login method and subscription you’re using.
You’re authenticated with an API key or Console account
: Remote Control requires claude.ai OAuth. Run
/login
and choose the claude.ai option. If
ANTHROPIC_API_KEY
is set in your environment, unset it.
Your Team or Enterprise admin hasn’t enabled it
: Remote Control is off by default on these plans. An admin can enable it at
claude.ai/admin-settings/claude-code
by turning on the
Remote Control
toggle. This toggle is a server-side organization setting.
The admin toggle is grayed out
: your organization has a data retention or compliance configuration that is incompatible with Remote Control. This cannot be changed from the admin panel. Contact Anthropic support to discuss options.
The error mentions
disableRemoteControl
: your IT administrator has disabled Remote Control on this device through
managed settings
, independent of the organization-wide toggle.
​
”Remote credentials fetch failed”
Claude Code could not obtain a short-lived credential from the Anthropic API to establish the connection. Re-run with
--verbose
to see the full error:
claude
remote-control
--verbose
Common causes:
Not signed in: run
claude
and use
/login
to authenticate with your claude.ai account. API key authentication is not supported for Remote Control.
Network or proxy issue: a firewall or proxy may be blocking the outbound HTTPS request. Remote Control requires access to the Anthropic API on port 443.
Session creation failed: if you also see
Session creation failed — see debug log
, the failure happened earlier in setup. Check that your subscription is active.
​
Choose the right approach
Claude Code offers several ways to work when you’re not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.
Trigger
Claude runs on
Setup
Best for
Dispatch
Message a task from the Claude mobile app
Your machine (Desktop)
Pair the mobile app with Desktop
Delegating work while you’re away, minimal setup
Remote Control
Drive a running session from
claude.ai/code
or the Claude mobile app
Your machine (CLI or VS Code)
Run
claude remote-control
Steering in-progress work from another device
Channels
Push events from a chat app like Telegram or Discord, or your own server
Your machine (CLI)
Install a channel plugin
or
build your own
Reacting to external events like CI failures or chat messages
Slack
Mention
@Claude
in a team channel
Anthropic cloud
Install the Slack app
with
Claude Code on the web
enabled
PRs and reviews from team chat
Scheduled tasks
Set a schedule
CLI
,
Desktop
, or
cloud
Pick a frequency
Recurring automation like daily reviews
​
Related resources
Claude Code on the web
: run sessions in Anthropic-managed cloud environments instead of on your machine
Ultraplan
: launch a cloud planning session from your terminal and review the plan in your browser
Channels
: forward Telegram, Discord, or iMessage into a session so Claude reacts to messages while you’re away
Dispatch
: message a task from your phone and it can spawn a Desktop session to handle it
Authentication
: set up
/login
and manage credentials for claude.ai
CLI reference
: full list of flags and commands including
claude remote-control
Security
: how Remote Control sessions fit into the Claude Code security model
Data usage
: what data flows through the Anthropic API during local and remote sessions
Was this page helpful?
Yes
No
Overview
Get started
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/remote-control" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Continue local sessions from any device with Remote Control
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Clau...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Continue local sessions from any device with Remote Control
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Remote Control is in research preview and available on all plans. On Team and Enterprise, it is off by default until an admin enables the Remote Control toggle in
Claude Code admin settings
.
Remote Control connects
claude.ai/code
or the Claude app for
iOS
and
Android
to a Claude Code session running on your machine. Start a task at your desk, then pick it up from your phone on the couch or a browser on another computer.
When you start a Remote Control session on your machine, Claude keeps running locally the entire time, so nothing moves to the cloud. With Remote Control you can:
Use your full local environment remotely
: your filesystem,
MCP servers
, tools, and project configuration all stay available, and typing
@
autocompletes file paths from your local project
Work from both surfaces at once
: the conversation stays in sync across all connected devices, so you can send messages from your terminal, browser, and phone interchangeably
Survive interruptions
: if your laptop sleeps or your network drops, the session reconnects automatically when your machine comes back online
Unlike
Claude Code on the web
, which runs on cloud infrastructure, Remote Control sessions run directly on your machine and interact with your local filesystem. The web and mobile interfaces are just a window into that local session.
Remote Control requires Claude Code v2.1.51 or later. Check your version with
claude --version
.
This page covers setup, how to start and connect to sessions, and how Remote Control compares to Claude Code on the web.
​
Requirements
Before using Remote Control, confirm that your environment meets these conditions:
Subscription
: available on Pro, Max, Team, and Enterprise plans. API keys are not supported. On Team and Enterprise, an admin must first enable the Remote Control toggle in
Claude Code admin settings
.
Authentication
: run
claude
and use
/login
to sign in through claude.ai if you haven’t already.
Workspace trust
: run
claude
in your project directory at least once to accept the workspace trust dialog.
​
Start a Remote Control session
You can start a Remote Control session from the CLI or the VS Code extension. The CLI offers three invocation modes; VS Code uses the
/remote-control
command.
Server mode
Interactive session
From an existing session
VS Code
Navigate to your project directory and run:
claude
remote-control
The process stays running in your terminal in server mode, waiting for remote connections. It displays a session URL you can use to
connect from another device
, and you can press spacebar to show a QR code for quick access from your phone. While a remote session is active, the terminal shows connection status and tool activity.
Available flags:
Flag
Description
--name "My Project"
Set a custom session title visible in the session list at claude.ai/code.
--remote-control-session-name-prefix <prefix>
Prefix for auto-generated session names when no explicit name is set. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. Set
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
for the same effect.
--spawn <mode>
How the server creates sessions.
•
same-dir
(default): all sessions share the current working directory, so they can conflict if editing the same files.
•
worktree
: each on-demand session gets its own
git worktree
. Requires a git repository.
•
session
: single-session mode. Serves exactly one session and rejects additional connections. Set at startup only.
Press
w
at runtime to toggle between
same-dir
and
worktree
.
--capacity <N>
Maximum number of concurrent sessions. Default is 32. Cannot be used with
--spawn=session
.
--verbose
Show detailed connection and session logs.
--sandbox
/
--no-sandbox
Enable or disable
sandboxing
for filesystem and network isolation. Off by default.
To start a normal interactive Claude Code session with Remote Control enabled, use the
--remote-control
flag (or
--rc
):
claude
--remote-control
Optionally pass a name for the session:
claude
--remote-control
"My Project"
This gives you a full interactive session in your terminal that you can also control from claude.ai or the Claude app. Unlike
claude remote-control
(server mode), you can type messages locally while the session is also available remotely.
If you’re already in a Claude Code session and want to continue it remotely, use the
/remote-control
(or
/rc
) command:
/remote-control
Pass a name as an argument to set a custom session title:
/remote-control My Project
This starts a Remote Control session that carries over your current conversation history and displays a session URL and QR code you can use to
connect from another device
. The
--verbose
,
--sandbox
, and
--no-sandbox
flags are not available with this command.
In the
Claude Code VS Code extension
, type
/remote-control
or
/rc
in the prompt box, or open the command menu with
/
and select it. Requires Claude Code v2.1.79 or later.
/remote-control
A banner appears above the prompt box showing connection status. Once connected, click
Open in browser
in the banner to go directly to the session, or find it in the session list at
claude.ai/code
. The session URL is also posted in the conversation.
To disconnect, click the close icon on the banner or run
/remote-control
again.
Unlike the CLI, the VS Code command does not accept a name argument or display a QR code. The session title is derived from your conversation history or first prompt.
​
Connect from another device
Once a Remote Control session is active, you have a few ways to connect from another device:
Open the session URL
in any browser to go directly to the session on
claude.ai/code
.
Scan the QR code
shown alongside the session URL to open it directly in the Claude app. With
claude remote-control
, press spacebar to toggle the QR code display.
Open
claude.ai/code
or the Claude app
and find the session by name in the session list. In the Claude mobile app, tap
Code
in the navigation to reach the session list. Remote Control sessions show a computer icon with a green status dot when online.
The remote session title is chosen in this order:
The name you passed to
--name
,
--remote-control
, or
/remote-control
The title you set with
/rename
The last meaningful message in existing conversation history
An auto-generated name like
myhost-graceful-unicorn
, where
myhost
is your machine’s hostname or the prefix you set with
--remote-control-session-name-prefix
If you didn’t set an explicit name, the title updates to reflect your prompt once you send one.
If the environment already has an active session, you’ll be asked whether to continue it or start a new one.
If you don’t have the Claude app yet, use the
/mobile
command inside Claude Code to display a download QR code for
iOS
or
Android
.
​
Enable Remote Control for all sessions
By default, Remote Control only activates when you explicitly run
claude remote-control
,
claude --remote-control
, or
/remote-control
. To enable it automatically for every interactive session, run
/config
inside Claude Code and set
Enable Remote Control for all sessions
to
true
. Set it back to
false
to disable. In the Desktop app, you can also toggle this from
Settings → Claude Code → Enable remote control by default
.
With this setting on, each interactive Claude Code process registers one remote session. If you run multiple instances, each one gets its own environment and session. To run multiple concurrent sessions from a single process, use
server mode
instead.
​
Connection and security
Your local Claude Code session makes outbound HTTPS requests only and never opens inbound ports on your machine. When you start Remote Control, it registers with the Anthropic API and polls for work. When you connect from another device, the server routes messages between the web or mobile client and your local session over a streaming connection.
All traffic travels through the Anthropic API over TLS, the same transport security as any Claude Code session. The connection uses multiple short-lived credentials, each scoped to a single purpose and expiring independently.
​
Remote Control vs Claude Code on the web
Remote Control and
Claude Code on the web
both use the claude.ai/code interface. The key difference is where the session runs: Remote Control executes on your machine, so your local MCP servers, tools, and project configuration stay available. Claude Code on the web executes in Anthropic-managed cloud infrastructure.
Use Remote Control when you’re in the middle of local work and want to keep going from another device. Use Claude Code on the web when you want to kick off a task without any local setup, work on a repo you don’t have cloned, or run multiple tasks in parallel.
​
Mobile push notifications
When Remote Control is active, Claude can send push notifications to your phone.
Claude decides when to push. It typically sends one when a long-running task finishes or when it needs a decision from you to continue. You can also request a push in your prompt, for example
notify me when the tests finish
. Beyond the on/off toggle below, there is no per-event configuration.
Mobile push notifications require Claude Code v2.1.110 or later.
To set up mobile push notifications:
1
Install the Claude mobile app
Download the Claude app for
iOS
or
Android
.
2
Sign in with your Claude Code account
Use the same account and organization you use for Claude Code in the terminal.
3
Allow notifications
Accept the notification permission prompt from the operating system.
4
Enable push in Claude Code
In your terminal, run
/config
and enable
Push when Claude decides
.
If notifications don’t arrive:
If
/config
shows
No mobile registered
, open the Claude app on your phone so it can refresh its push token. The warning clears the next time Remote Control connects.
On iOS, Focus modes and notification summaries can suppress or delay pushes. Check Settings → Notifications → Claude.
On Android, aggressive battery optimization can delay delivery. Exempt the Claude app from battery optimization in system settings.
​
Limitations
One remote session per interactive process
: outside of server mode, each Claude Code instance supports one remote session at a time. Use
server mode
to run multiple concurrent sessions from a single process.
Local process must keep running
: Remote Control runs as a local process. If you close the terminal, quit VS Code, or otherwise stop the
claude
process, the session ends.
Extended network outage
: if your machine is awake but unable to reach the network for more than roughly 10 minutes, the session times out and the process exits. Run
claude remote-control
again to start a new session.
Ultraplan disconnects Remote Control
: starting an
ultraplan
session disconnects any active Remote Control session because both features occupy the claude.ai/code interface and only one can be connected at a time.
Some commands are local-only
: commands that open an interactive picker in the terminal, such as
/mcp
,
/plugin
, or
/resume
, work only from the local CLI. Commands that produce text output, including
/compact
,
/clear
,
/context
,
/usage
,
/exit
,
/extra-usage
,
/recap
, and
/reload-plugins
, work from mobile and web.
​
Troubleshooting
​
”Remote Control requires a claude.ai subscription”
You’re not authenticated with a claude.ai account. Run
claude auth login
and choose the claude.ai option. If
ANTHROPIC_API_KEY
is set in your environment, unset it first.
​
”Remote Control requires a full-scope login token”
You’re authenticated with a long-lived token from
claude setup-token
or the
CLAUDE_CODE_OAUTH_TOKEN
environment variable. These tokens are limited to inference-only and cannot establish Remote Control sessions. Run
claude auth login
to authenticate with a full-scope session token instead.
​
”Unable to determine your organization for Remote Control eligibility”
Your cached account information is stale or incomplete. Run
claude auth login
to refresh it.
​
”Remote Control is not yet enabled for your account”
The eligibility check can fail with certain environment variables present:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
or
DISABLE_TELEMETRY
: unset them and try again.
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_VERTEX
, or
CLAUDE_CODE_USE_FOUNDRY
: Remote Control requires claude.ai authentication and does not work with third-party providers.
If none of these are set, run
/logout
then
/login
to refresh.
​
”Remote Control is disabled by your organization’s policy”
This error has four distinct causes. Run
/status
first to see which login method and subscription you’re using.
You’re authenticated with an API key or Console account
: Remote Control requires claude.ai OAuth. Run
/login
and choose the claude.ai option. If
ANTHROPIC_API_KEY
is set in your environment, unset it.
Your Team or Enterprise admin hasn’t enabled it
: Remote Control is off by default on these plans. An admin can enable it at
claude.ai/admin-settings/claude-code
by turning on the
Remote Control
toggle. This toggle is a server-side organization setting.
The admin toggle is grayed out
: your organization has a data retention or compliance configuration that is incompatible with Remote Control. This cannot be changed from the admin panel. Contact Anthropic support to discuss options.
The error mentions
disableRemoteControl
: your IT administrator has disabled Remote Control on this device through
managed settings
, independent of the organization-wide toggle.
​
”Remote credentials fetch failed”
Claude Code could not obtain a short-lived credential from the Anthropic API to establish the connection. Re-run with
--verbose
to see the full error:
claude
remote-control
--verbose
Common causes:
Not signed in: run
claude
and use
/login
to authenticate with your claude.ai account. API key authentication is not supported for Remote Control.
Network or proxy issue: a firewall or proxy may be blocking the outbound HTTPS request. Remote Control requires access to the Anthropic API on port 443.
Session creation failed: if you also see
Session creation failed — see debug log
, the failure happened earlier in setup. Check that your subscription is active.
​
Choose the right approach
Claude Code offers several ways to work when you’re not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.
Trigger
Claude runs on
Setup
Best for
Dispatch
Message a task from the Claude mobile app
Your machine (Desktop)
Pair the mobile app with Desktop
Delegating work while you’re away, minimal setup
Remote Control
Drive a running session from
claude.ai/code
or the Claude mobile app
Your machine (CLI or VS Code)
Run
claude remote-control
Steering in-progress work from another device
Channels
Push events from a chat app like Telegram or Discord, or your own server
Your machine (CLI)
Install a channel plugin
or
build your own
Reacting to external events like CI failures or chat messages
Slack
Mention
@Claude
in a team channel
Anthropic cloud
Install the Slack app
with
Claude Code on the web
enabled
PRs and reviews from team chat
Scheduled tasks
Set a schedule
CLI
,
Desktop
, or
cloud
Pick a frequency
Recurring automation like daily reviews
​
Related resources
Claude Code on the web
: run sessions in Anthropic-managed cloud environments instead of on your machine
Ultraplan
: launch a cloud planning session from your terminal and review the plan in your browser
Channels
: forward Telegram, Discord, or iMessage into a session so Claude reacts to messages while you’re away
Dispatch
: message a task from your phone and it can spawn a Desktop session to handle it
Authentication
: set up
/login
and manage credentials for claude.ai
CLI reference
: full list of flags and commands including
claude remote-control
Security
: how Remote Control sessions fit into the Claude Code security model
Data usage
: what data flows through the Anthropic API during local and remote sessions
Was this page helpful?
Yes
No
Overview
Get started
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/remote-control" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Voice dictation</title>
  <link>https://code.claude.com/docs/en/voice-dictation</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/voice-dictation</guid>
  <pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Voice dictation
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover a...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Voice dictation
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Speak your prompts instead of typing them in the Claude Code CLI. Your speech is transcribed live into the prompt input, so you can mix voice and typing in the same message. Enable dictation with
/voice
, then either hold a key while you speak or tap once to start and again to send.
Voice dictation requires Claude Code v2.1.69 or later. Tap mode requires v2.1.116 or later. Check your version with
claude --version
.
​
Requirements
Voice dictation streams your recorded audio to Anthropic’s servers for transcription. Audio is not processed locally. The speech-to-text service is only available when you authenticate with a Claude.ai account, and is not available when Claude Code is configured to use an Anthropic API key directly, Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Transcription does not consume Claude messages or tokens and does not count toward the limits shown in
/usage
. See
data usage
for how Anthropic handles your data.
Voice dictation also needs local microphone access, so it does not work in remote environments such as
Claude Code on the web
or SSH sessions. In WSL, voice dictation requires WSLg for audio access. WSLg is included with WSL2 when installed from the Microsoft Store on Windows 10 or 11. If WSLg is not available, for example on WSL1, run Claude Code in native Windows instead.
Audio recording uses a built-in native module on macOS, Linux, and Windows. On Linux, if the native module cannot load, Claude Code falls back to
arecord
from ALSA utils or
rec
from SoX. If neither is available,
/voice
prints an install command for your package manager.
The Claude Code
VS Code extension
also supports voice dictation with the same Claude.ai account requirement. It is not available in VS Code Remote sessions, including SSH, Dev Containers, and Codespaces, because the microphone is on your local machine and the extension runs on the remote host.
​
Enable voice dictation
Run
/voice
to enable dictation. The first time you enable it, Claude Code runs a microphone check. On macOS, this triggers the system microphone permission prompt for your terminal if it has never been granted.
/voice
Voice mode enabled (hold). Hold Space to record. Dictation language: en (/config to change).
/voice
accepts an optional mode argument:
Command
Effect
/voice
Toggle on or off, keep the current mode
/voice hold
Enable in
hold mode
/voice tap
Enable in
tap mode
/voice off
Disable
Voice dictation persists across sessions. Set it directly in your
user settings file
instead of running
/voice
:
{
"voice"
: {
"enabled"
:
true
,
"mode"
:
"tap"
}
}
While voice dictation is enabled, the input footer shows a
hold Space to speak
hint when the prompt is empty. The hint reflects your current
voice:pushToTalk
binding and updates if you
rebind the dictation key
. The hint text is the same in both modes, and it does not appear if you have a
custom status line
configured.
Transcription is tuned for coding vocabulary in both modes. Common development terms like
regex
,
OAuth
,
JSON
, and
localhost
are recognized correctly, and your current project name and git branch name are added as recognition hints automatically.
​
Hold to record
Hold mode is push-to-talk: recording runs while you hold the key and stops when you release it. This is the default mode.
Hold
Space
to start recording. Claude Code detects a held key by watching for rapid key-repeat events from your terminal, so there is a brief warmup before recording begins. The footer shows
keep holding…
during warmup, then switches to a live waveform once recording is active.
The first couple of key-repeat characters type into the input during warmup and are removed automatically when recording activates. A single
Space
tap still types a space, since hold detection only triggers on rapid repeat.
To skip the warmup, switch to
tap mode
with
/voice tap
, or
rebind to a modifier combination
like
meta+k
. Modifier combos start recording on the first keypress.
Your speech appears in the prompt as you speak, dimmed until the transcript is finalized. Release
Space
to stop recording and finalize the text. The transcript is inserted at your cursor position and the cursor stays at the end of the inserted text, so you can mix typing and dictation in any order. Hold
Space
again to append another recording, or move the cursor first to insert speech elsewhere in the prompt:
> refactor the auth middleware to ▮
# hold Space, speak "use the new token validation helper"
> refactor the auth middleware to use the new token validation helper▮
By default, releasing the key inserts the transcript and waits for you to press
Enter
. Set
"autoSubmit": true
in the
voice
settings object to send the prompt automatically when you release the key, as long as the transcript is at least three words long.
​
Tap to record and send
Tap mode toggles recording with a single keypress: tap once to start, speak, then tap again to send the prompt. There is no warmup, and you do not need to keep the key held.
Enable tap mode with
/voice tap
. With the prompt input empty, tap
Space
to start recording. The footer shows a live waveform while recording. Tap
Space
again to stop. Claude Code inserts the transcript and submits the prompt automatically when the transcript is at least three words long. Shorter transcripts are inserted but not submitted, so an accidental tap does not send a stray word.
The first tap only starts recording when the prompt input is empty, so you can still type spaces normally while composing a message. The second tap stops recording regardless of input contents. Recording also stops automatically after 15 seconds of silence or two minutes total.
​
Change the dictation language
Voice dictation uses the same
language
setting
that controls Claude’s response language. If that setting is empty, dictation defaults to English. In the VS Code extension, if
language
is empty, dictation uses VS Code’s
accessibility.voice.speechLanguage
setting before defaulting to English.
Supported dictation languages
Language
Code
Czech
cs
Danish
da
Dutch
nl
English
en
French
fr
German
de
Greek
el
Hindi
hi
Indonesian
id
Italian
it
Japanese
ja
Korean
ko
Norwegian
no
Polish
pl
Portuguese
pt
Russian
ru
Spanish
es
Swedish
sv
Turkish
tr
Ukrainian
uk
Set the language in
/config
or directly in settings. You can use either the
BCP 47 language code
or the language name:
{
"language"
:
"japanese"
}
If your
language
setting is not in the supported list,
/voice
warns you on enable and falls back to English for dictation. Claude’s text responses are not affected by this fallback.
​
Rebind the dictation key
The dictation key is bound to
voice:pushToTalk
in the
Chat
context and defaults to
Space
. The same binding controls both hold and tap modes. Rebind it in
~/.claude/keybindings.json
:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"meta+k"
:
"voice:pushToTalk"
,
"space"
:
null
}
}
]
}
Setting
"space": null
removes the default binding. Omit it if you want both keys active.
In hold mode, avoid binding a bare letter key like
v
since hold detection relies on key-repeat and the letter types into the prompt during warmup. Use
Space
, or use a modifier combination like
meta+k
to start recording on the first keypress with no warmup. Tap mode has no warmup, so most keys work.
Some keys are not delivered to terminal applications and cannot be bound at all. For example,
Caps Lock
shows an error if you try to bind it. See
customize keyboard shortcuts
for the full keybinding syntax and the list of reserved shortcuts.
​
Troubleshooting
Common issues when voice dictation does not activate or record:
Voice mode requires a Claude.ai account
: you are authenticated with an API key or a third-party provider. Run
/login
to sign in with a Claude.ai account.
Microphone access is denied
: grant microphone permission to your terminal in system settings. On macOS, go to System Settings → Privacy & Security → Microphone and enable your terminal app, then run
/voice
again. On Windows, go to Settings → Privacy & security → Microphone and turn on microphone access for desktop apps, then run
/voice
again. If your terminal isn’t listed in the macOS settings, see
Terminal not listed in macOS Microphone settings
.
No audio recording tool found
on Linux
: the native audio module could not load and no fallback is installed. Install SoX with the command shown in the error message, for example
sudo apt-get install sox
.
Voice mode could not find a working audio recorder in WSL
: WSLg routes audio through PulseAudio rather than an ALSA device, so SoX needs its PulseAudio backend installed explicitly. Run
sudo apt install sox libsox-fmt-pulse
. Installing
sox
alone pulls in the ALSA backend, which cannot record on WSL because there is no
/dev/snd
device.
Voice input is failing repeatedly and has been paused
: voice dictation hit several start-up failures in a row and stopped attempting new sessions until one succeeds. This usually means the microphone or audio stack on this host can’t capture audio, for example a headless server, a remote shell with no audio passthrough, or a denied microphone permission. Confirm a working input device, fix the underlying cause from the entries above, then trigger voice again.
Nothing happens when holding
Space
in hold mode
: watch the prompt input while you hold. If spaces keep accumulating, voice dictation is likely off; run
/voice hold
to enable it. If only one or two spaces appear and then nothing, voice dictation is on but hold detection is not triggering. Hold detection requires your terminal to send key-repeat events, so it cannot detect a held key if key-repeat is disabled at the OS level. Switch to tap mode with
/voice tap
to avoid the key-repeat requirement.
Tapping
Space
types a space instead of recording in tap mode
: the first tap only starts recording when the prompt input is empty. Clear the input first, or check that you are in tap mode by running
/voice tap
.
No audio detected from microphone
: recording started but captured silence. Confirm the correct input device is set as the system default and that its input level is not muted or near zero. On Windows, open Settings → System → Sound → Input and select your microphone. On macOS, open System Settings → Sound → Input.
No speech detected
: audio reached the transcription service but no words were recognized. Speak closer to the microphone, reduce background noise, and confirm your
dictation language
matches the language you are speaking.
Transcription is garbled or in the wrong language
: dictation defaults to English. If you are dictating in another language, set it in
/config
first. See
Change the dictation language
.
​
Terminal not listed in macOS Microphone settings
If your terminal app does not appear under System Settings → Privacy & Security → Microphone, there is no toggle you can enable. Reset the permission state for your terminal so the next
/voice
run triggers a fresh macOS permission prompt.
1
Reset the microphone permission for your terminal
Run
tccutil reset Microphone <bundle-id>
, replacing
<bundle-id>
with your terminal’s identifier:
com.apple.Terminal
for the built-in Terminal, or
com.googlecode.iterm2
for iTerm2. For other terminals, look up the identifier with
osascript -e 'id of app "AppName"'
.
You can run
tccutil reset Microphone
without a bundle ID, but it revokes microphone access from every app on your Mac, including apps like Zoom or Slack. Each app will need to re-request access on next use, so don’t run it during an active call.
2
Quit and relaunch your terminal
macOS won’t re-prompt a process that is already running. Quit the terminal app with Cmd+Q, not just close its windows, then open it again.
3
Trigger a fresh prompt
Start Claude Code and run
/voice
. macOS prompts for microphone access; allow it.
​
See also
Customize keyboard shortcuts
: rebind
voice:pushToTalk
and other CLI keyboard actions
Configure settings
: full reference for
voice
,
language
, and other settings keys
Interactive mode
: keyboard shortcuts, input modes, and session controls
Commands
: reference for
/voice
,
/config
, and all other commands
Was this page helpful?
Yes
No
Fullscreen rendering
Customize status line
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/voice-dictation" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Voice dictation
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover a...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Voice dictation
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Speak your prompts instead of typing them in the Claude Code CLI. Your speech is transcribed live into the prompt input, so you can mix voice and typing in the same message. Enable dictation with
/voice
, then either hold a key while you speak or tap once to start and again to send.
Voice dictation requires Claude Code v2.1.69 or later. Tap mode requires v2.1.116 or later. Check your version with
claude --version
.
​
Requirements
Voice dictation streams your recorded audio to Anthropic’s servers for transcription. Audio is not processed locally. The speech-to-text service is only available when you authenticate with a Claude.ai account, and is not available when Claude Code is configured to use an Anthropic API key directly, Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Transcription does not consume Claude messages or tokens and does not count toward the limits shown in
/usage
. See
data usage
for how Anthropic handles your data.
Voice dictation also needs local microphone access, so it does not work in remote environments such as
Claude Code on the web
or SSH sessions. In WSL, voice dictation requires WSLg for audio access. WSLg is included with WSL2 when installed from the Microsoft Store on Windows 10 or 11. If WSLg is not available, for example on WSL1, run Claude Code in native Windows instead.
Audio recording uses a built-in native module on macOS, Linux, and Windows. On Linux, if the native module cannot load, Claude Code falls back to
arecord
from ALSA utils or
rec
from SoX. If neither is available,
/voice
prints an install command for your package manager.
The Claude Code
VS Code extension
also supports voice dictation with the same Claude.ai account requirement. It is not available in VS Code Remote sessions, including SSH, Dev Containers, and Codespaces, because the microphone is on your local machine and the extension runs on the remote host.
​
Enable voice dictation
Run
/voice
to enable dictation. The first time you enable it, Claude Code runs a microphone check. On macOS, this triggers the system microphone permission prompt for your terminal if it has never been granted.
/voice
Voice mode enabled (hold). Hold Space to record. Dictation language: en (/config to change).
/voice
accepts an optional mode argument:
Command
Effect
/voice
Toggle on or off, keep the current mode
/voice hold
Enable in
hold mode
/voice tap
Enable in
tap mode
/voice off
Disable
Voice dictation persists across sessions. Set it directly in your
user settings file
instead of running
/voice
:
{
"voice"
: {
"enabled"
:
true
,
"mode"
:
"tap"
}
}
While voice dictation is enabled, the input footer shows a
hold Space to speak
hint when the prompt is empty. The hint reflects your current
voice:pushToTalk
binding and updates if you
rebind the dictation key
. The hint text is the same in both modes, and it does not appear if you have a
custom status line
configured.
Transcription is tuned for coding vocabulary in both modes. Common development terms like
regex
,
OAuth
,
JSON
, and
localhost
are recognized correctly, and your current project name and git branch name are added as recognition hints automatically.
​
Hold to record
Hold mode is push-to-talk: recording runs while you hold the key and stops when you release it. This is the default mode.
Hold
Space
to start recording. Claude Code detects a held key by watching for rapid key-repeat events from your terminal, so there is a brief warmup before recording begins. The footer shows
keep holding…
during warmup, then switches to a live waveform once recording is active.
The first couple of key-repeat characters type into the input during warmup and are removed automatically when recording activates. A single
Space
tap still types a space, since hold detection only triggers on rapid repeat.
To skip the warmup, switch to
tap mode
with
/voice tap
, or
rebind to a modifier combination
like
meta+k
. Modifier combos start recording on the first keypress.
Your speech appears in the prompt as you speak, dimmed until the transcript is finalized. Release
Space
to stop recording and finalize the text. The transcript is inserted at your cursor position and the cursor stays at the end of the inserted text, so you can mix typing and dictation in any order. Hold
Space
again to append another recording, or move the cursor first to insert speech elsewhere in the prompt:
> refactor the auth middleware to ▮
# hold Space, speak "use the new token validation helper"
> refactor the auth middleware to use the new token validation helper▮
By default, releasing the key inserts the transcript and waits for you to press
Enter
. Set
"autoSubmit": true
in the
voice
settings object to send the prompt automatically when you release the key, as long as the transcript is at least three words long.
​
Tap to record and send
Tap mode toggles recording with a single keypress: tap once to start, speak, then tap again to send the prompt. There is no warmup, and you do not need to keep the key held.
Enable tap mode with
/voice tap
. With the prompt input empty, tap
Space
to start recording. The footer shows a live waveform while recording. Tap
Space
again to stop. Claude Code inserts the transcript and submits the prompt automatically when the transcript is at least three words long. Shorter transcripts are inserted but not submitted, so an accidental tap does not send a stray word.
The first tap only starts recording when the prompt input is empty, so you can still type spaces normally while composing a message. The second tap stops recording regardless of input contents. Recording also stops automatically after 15 seconds of silence or two minutes total.
​
Change the dictation language
Voice dictation uses the same
language
setting
that controls Claude’s response language. If that setting is empty, dictation defaults to English. In the VS Code extension, if
language
is empty, dictation uses VS Code’s
accessibility.voice.speechLanguage
setting before defaulting to English.
Supported dictation languages
Language
Code
Czech
cs
Danish
da
Dutch
nl
English
en
French
fr
German
de
Greek
el
Hindi
hi
Indonesian
id
Italian
it
Japanese
ja
Korean
ko
Norwegian
no
Polish
pl
Portuguese
pt
Russian
ru
Spanish
es
Swedish
sv
Turkish
tr
Ukrainian
uk
Set the language in
/config
or directly in settings. You can use either the
BCP 47 language code
or the language name:
{
"language"
:
"japanese"
}
If your
language
setting is not in the supported list,
/voice
warns you on enable and falls back to English for dictation. Claude’s text responses are not affected by this fallback.
​
Rebind the dictation key
The dictation key is bound to
voice:pushToTalk
in the
Chat
context and defaults to
Space
. The same binding controls both hold and tap modes. Rebind it in
~/.claude/keybindings.json
:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"meta+k"
:
"voice:pushToTalk"
,
"space"
:
null
}
}
]
}
Setting
"space": null
removes the default binding. Omit it if you want both keys active.
In hold mode, avoid binding a bare letter key like
v
since hold detection relies on key-repeat and the letter types into the prompt during warmup. Use
Space
, or use a modifier combination like
meta+k
to start recording on the first keypress with no warmup. Tap mode has no warmup, so most keys work.
Some keys are not delivered to terminal applications and cannot be bound at all. For example,
Caps Lock
shows an error if you try to bind it. See
customize keyboard shortcuts
for the full keybinding syntax and the list of reserved shortcuts.
​
Troubleshooting
Common issues when voice dictation does not activate or record:
Voice mode requires a Claude.ai account
: you are authenticated with an API key or a third-party provider. Run
/login
to sign in with a Claude.ai account.
Microphone access is denied
: grant microphone permission to your terminal in system settings. On macOS, go to System Settings → Privacy & Security → Microphone and enable your terminal app, then run
/voice
again. On Windows, go to Settings → Privacy & security → Microphone and turn on microphone access for desktop apps, then run
/voice
again. If your terminal isn’t listed in the macOS settings, see
Terminal not listed in macOS Microphone settings
.
No audio recording tool found
on Linux
: the native audio module could not load and no fallback is installed. Install SoX with the command shown in the error message, for example
sudo apt-get install sox
.
Voice mode could not find a working audio recorder in WSL
: WSLg routes audio through PulseAudio rather than an ALSA device, so SoX needs its PulseAudio backend installed explicitly. Run
sudo apt install sox libsox-fmt-pulse
. Installing
sox
alone pulls in the ALSA backend, which cannot record on WSL because there is no
/dev/snd
device.
Voice input is failing repeatedly and has been paused
: voice dictation hit several start-up failures in a row and stopped attempting new sessions until one succeeds. This usually means the microphone or audio stack on this host can’t capture audio, for example a headless server, a remote shell with no audio passthrough, or a denied microphone permission. Confirm a working input device, fix the underlying cause from the entries above, then trigger voice again.
Nothing happens when holding
Space
in hold mode
: watch the prompt input while you hold. If spaces keep accumulating, voice dictation is likely off; run
/voice hold
to enable it. If only one or two spaces appear and then nothing, voice dictation is on but hold detection is not triggering. Hold detection requires your terminal to send key-repeat events, so it cannot detect a held key if key-repeat is disabled at the OS level. Switch to tap mode with
/voice tap
to avoid the key-repeat requirement.
Tapping
Space
types a space instead of recording in tap mode
: the first tap only starts recording when the prompt input is empty. Clear the input first, or check that you are in tap mode by running
/voice tap
.
No audio detected from microphone
: recording started but captured silence. Confirm the correct input device is set as the system default and that its input level is not muted or near zero. On Windows, open Settings → System → Sound → Input and select your microphone. On macOS, open System Settings → Sound → Input.
No speech detected
: audio reached the transcription service but no words were recognized. Speak closer to the microphone, reduce background noise, and confirm your
dictation language
matches the language you are speaking.
Transcription is garbled or in the wrong language
: dictation defaults to English. If you are dictating in another language, set it in
/config
first. See
Change the dictation language
.
​
Terminal not listed in macOS Microphone settings
If your terminal app does not appear under System Settings → Privacy & Security → Microphone, there is no toggle you can enable. Reset the permission state for your terminal so the next
/voice
run triggers a fresh macOS permission prompt.
1
Reset the microphone permission for your terminal
Run
tccutil reset Microphone <bundle-id>
, replacing
<bundle-id>
with your terminal’s identifier:
com.apple.Terminal
for the built-in Terminal, or
com.googlecode.iterm2
for iTerm2. For other terminals, look up the identifier with
osascript -e 'id of app "AppName"'
.
You can run
tccutil reset Microphone
without a bundle ID, but it revokes microphone access from every app on your Mac, including apps like Zoom or Slack. Each app will need to re-request access on next use, so don’t run it during an active call.
2
Quit and relaunch your terminal
macOS won’t re-prompt a process that is already running. Quit the terminal app with Cmd+Q, not just close its windows, then open it again.
3
Trigger a fresh prompt
Start Claude Code and run
/voice
. macOS prompts for microphone access; allow it.
​
See also
Customize keyboard shortcuts
: rebind
voice:pushToTalk
and other CLI keyboard actions
Configure settings
: full reference for
voice
,
language
, and other settings keys
Interactive mode
: keyboard shortcuts, input modes, and session controls
Commands
: reference for
/voice
,
/config
, and all other commands
Was this page helpful?
Yes
No
Fullscreen rendering
Customize status line
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/voice-dictation" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Checkpointing</title>
  <link>https://code.claude.com/docs/en/checkpointing</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/checkpointing</guid>
  <pubDate>Thu, 19 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Checkpointing
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code automatically tracks Claude’s file edi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Checkpointing
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code automatically tracks Claude’s file edits as you work, allowing you to quickly undo changes and rewind to previous states if anything gets off track.
​
How checkpoints work
As you work with Claude, checkpointing automatically captures the state of your code before each edit. This safety net lets you pursue ambitious, wide-scale tasks knowing you can always return to a prior code state.
​
Automatic tracking
Claude Code tracks all changes made by its file editing tools:
Every user prompt creates a new checkpoint
Checkpoints persist across sessions, so you can access them in resumed conversations
Automatically cleaned up along with sessions after 30 days (configurable)
​
Rewind and summarize
Press
Esc
twice (
Esc
+
Esc
) or use the
/rewind
command to open the rewind menu. A scrollable list shows each of your prompts from the session. Select the point you want to act on, then choose an action:
Restore code and conversation
: revert both code and conversation to that point
Restore conversation
: rewind to that message while keeping current code
Restore code
: revert file changes while keeping the conversation
Summarize from here
: compress the conversation from this point forward into a summary, freeing context window space
Summarize up to here
: compress the conversation before this point into a summary, keeping later messages intact
Never mind
: return to the message list without making changes
After restoring the conversation or choosing Summarize from here, the original prompt from the selected message is restored into the input field so you can re-send or edit it.
Choosing Summarize up to here leaves you at the end of the conversation with the input empty.
​
Restore vs. summarize
The restore options revert state: they undo code changes, conversation history, or both. The summarize options compress part of the conversation into an AI-generated summary without changing files on disk:
Summarize from here
: messages before the selected message stay intact. The selected message and everything after it are replaced with a summary. Use this to discard a side discussion while keeping early context in full detail.
Summarize up to here
: messages before the selected message are replaced with a summary. The selected message and everything after it stay intact, and you remain at the end of the conversation. Use this to compress early setup discussion while keeping recent work in full detail.
In both cases the original messages are preserved in the session transcript, so Claude can reference the details if needed. You can type optional instructions to guide what the summary focuses on. This is similar to
/compact
, but targeted: instead of summarizing the entire conversation, you choose which side of the selected message to compress.
Summarize keeps you in the same session and compresses context. If you want to branch off and try a different approach while preserving the original session intact, use
fork
instead (
claude --continue --fork-session
).
​
Common use cases
Checkpoints are particularly useful when:
Exploring alternatives
: try different implementation approaches without losing your starting point
Recovering from mistakes
: quickly undo changes that introduced bugs or broke functionality
Iterating on features
: experiment with variations knowing you can revert to working states
Freeing context space
: summarize a verbose debugging session from the midpoint forward, keeping your initial instructions intact
​
Limitations
​
Bash command changes not tracked
Checkpointing does not track files modified by bash commands. For example, if Claude Code runs:
rm
file.txt
mv
old.txt
new.txt
cp
source.txt
dest.txt
These file modifications cannot be undone through rewind. Only direct file edits made through Claude’s file editing tools are tracked.
​
External changes not tracked
Checkpointing only tracks files that have been edited within the current session. Manual changes you make to files outside of Claude Code and edits from other concurrent sessions are normally not captured, unless they happen to modify the same files as the current session.
​
Not a replacement for version control
Checkpoints are designed for quick, session-level recovery. For permanent version history and collaboration:
Continue using version control (ex. Git) for commits, branches, and long-term history
Checkpoints complement but don’t replace proper version control
Think of checkpoints as “local undo” and Git as “permanent history”
​
See also
Interactive mode
- Keyboard shortcuts and session controls
Commands
- Accessing checkpoints using
/rewind
CLI reference
- Command-line options
Was this page helpful?
Yes
No
Interactive mode
Hooks reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/checkpointing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Checkpointing
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code automatically tracks Claude’s file edi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Checkpointing
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code automatically tracks Claude’s file edits as you work, allowing you to quickly undo changes and rewind to previous states if anything gets off track.
​
How checkpoints work
As you work with Claude, checkpointing automatically captures the state of your code before each edit. This safety net lets you pursue ambitious, wide-scale tasks knowing you can always return to a prior code state.
​
Automatic tracking
Claude Code tracks all changes made by its file editing tools:
Every user prompt creates a new checkpoint
Checkpoints persist across sessions, so you can access them in resumed conversations
Automatically cleaned up along with sessions after 30 days (configurable)
​
Rewind and summarize
Press
Esc
twice (
Esc
+
Esc
) or use the
/rewind
command to open the rewind menu. A scrollable list shows each of your prompts from the session. Select the point you want to act on, then choose an action:
Restore code and conversation
: revert both code and conversation to that point
Restore conversation
: rewind to that message while keeping current code
Restore code
: revert file changes while keeping the conversation
Summarize from here
: compress the conversation from this point forward into a summary, freeing context window space
Summarize up to here
: compress the conversation before this point into a summary, keeping later messages intact
Never mind
: return to the message list without making changes
After restoring the conversation or choosing Summarize from here, the original prompt from the selected message is restored into the input field so you can re-send or edit it.
Choosing Summarize up to here leaves you at the end of the conversation with the input empty.
​
Restore vs. summarize
The restore options revert state: they undo code changes, conversation history, or both. The summarize options compress part of the conversation into an AI-generated summary without changing files on disk:
Summarize from here
: messages before the selected message stay intact. The selected message and everything after it are replaced with a summary. Use this to discard a side discussion while keeping early context in full detail.
Summarize up to here
: messages before the selected message are replaced with a summary. The selected message and everything after it stay intact, and you remain at the end of the conversation. Use this to compress early setup discussion while keeping recent work in full detail.
In both cases the original messages are preserved in the session transcript, so Claude can reference the details if needed. You can type optional instructions to guide what the summary focuses on. This is similar to
/compact
, but targeted: instead of summarizing the entire conversation, you choose which side of the selected message to compress.
Summarize keeps you in the same session and compresses context. If you want to branch off and try a different approach while preserving the original session intact, use
fork
instead (
claude --continue --fork-session
).
​
Common use cases
Checkpoints are particularly useful when:
Exploring alternatives
: try different implementation approaches without losing your starting point
Recovering from mistakes
: quickly undo changes that introduced bugs or broke functionality
Iterating on features
: experiment with variations knowing you can revert to working states
Freeing context space
: summarize a verbose debugging session from the midpoint forward, keeping your initial instructions intact
​
Limitations
​
Bash command changes not tracked
Checkpointing does not track files modified by bash commands. For example, if Claude Code runs:
rm
file.txt
mv
old.txt
new.txt
cp
source.txt
dest.txt
These file modifications cannot be undone through rewind. Only direct file edits made through Claude’s file editing tools are tracked.
​
External changes not tracked
Checkpointing only tracks files that have been edited within the current session. Manual changes you make to files outside of Claude Code and edits from other concurrent sessions are normally not captured, unless they happen to modify the same files as the current session.
​
Not a replacement for version control
Checkpoints are designed for quick, session-level recovery. For permanent version history and collaboration:
Continue using version control (ex. Git) for commits, branches, and long-term history
Checkpoints complement but don’t replace proper version control
Think of checkpoints as “local undo” and Git as “permanent history”
​
See also
Interactive mode
- Keyboard shortcuts and session controls
Commands
- Accessing checkpoints using
/rewind
CLI reference
- Command-line options
Was this page helpful?
Yes
No
Interactive mode
Hooks reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/checkpointing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Interactive mode</title>
  <link>https://code.claude.com/docs/en/interactive-mode</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/interactive-mode</guid>
  <pubDate>Tue, 17 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Interactive mode
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Keyboard shortcuts
Keyboard shortcuts may var...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Interactive mode
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Keyboard shortcuts
Keyboard shortcuts may vary by platform and terminal. In
fullscreen rendering
, press
?
in the transcript viewer to see available shortcuts there.
macOS users
: Option/Alt key shortcuts (
Alt+B
,
Alt+F
,
Alt+Y
,
Alt+M
,
Alt+P
) require configuring Option as Meta in your terminal:
iTerm2
: Settings → Profiles → Keys → General → set Left/Right Option key to “Esc+”
Apple Terminal
: Settings → Profiles → Keyboard → check “Use Option as Meta Key”
VS Code
: set
"terminal.integrated.macOptionIsMeta": true
in VS Code settings
See
Terminal configuration
for details.
​
General controls
Shortcut
Description
Context
Ctrl+C
Cancel current input or generation
Standard interrupt
Ctrl+X Ctrl+K
Kill all running
background subagents
in this session. Press twice within 3 seconds to confirm
Subagent control
Ctrl+D
Exit Claude Code session
EOF signal
Ctrl+G
or
Ctrl+X Ctrl+E
Open in default text editor
Edit your prompt or custom response in your default text editor.
Ctrl+X Ctrl+E
is the readline-native binding. Turn on Show last response in external editor in
/config
to prepend Claude’s previous reply as
#
-commented context above your prompt; the comment block is stripped when you save
Ctrl+L
Redraw screen
Forces a full terminal redraw. Input and conversation history are kept. Use this to recover if the display becomes garbled or partially blank
Ctrl+O
Toggle transcript viewer
Shows detailed tool usage and execution. Also expands MCP calls, which collapse to a single line like “Called slack 3 times” by default
Ctrl+R
Reverse search command history
Search through previous commands interactively
Ctrl+V
or
Cmd+V
(iTerm2) or
Alt+V
(Windows)
Paste image from clipboard
Inserts an
[Image #N]
chip at the cursor so you can reference it positionally in your prompt
Ctrl+B
Background running tasks
Backgrounds bash commands and agents. Tmux users press twice
Ctrl+T
Toggle task list
Show or hide the
task list
in the terminal status area
Left/Right arrows
Cycle through dialog tabs
Navigate between tabs in permission dialogs and menus
Up/Down arrows
or
Ctrl+P
/
Ctrl+N
Move cursor or navigate command history
In multiline input, first moves the cursor within the prompt. Once the cursor is already on the top or bottom edge, pressing again navigates command history
Esc
Interrupt Claude
Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far
Esc
+
Esc
Rewind or summarize
Restore code and/or conversation to a previous point, or summarize from a selected message
Shift+Tab
or
Alt+M
(some configurations)
Cycle permission modes
Cycle through
default
,
acceptEdits
,
plan
, and any modes you have enabled, such as
auto
or
bypassPermissions
. See
permission modes
.
Option+P
(macOS) or
Alt+P
(Windows/Linux)
Switch model
Switch models without clearing your prompt
Option+T
(macOS) or
Alt+T
(Windows/Linux)
Toggle extended thinking
Enable or disable extended thinking mode. As of v2.1.132 this shortcut works on macOS without configuring Option as Meta
Option+O
(macOS) or
Alt+O
(Windows/Linux)
Toggle fast mode
Enable or disable
fast mode
​
Text editing
Shortcut
Description
Context
Ctrl+A
Move cursor to start of current line
In multiline input, moves to the start of the current logical line
Ctrl+E
Move cursor to end of current line
In multiline input, moves to the end of the current logical line
Ctrl+K
Delete to end of line
Stores deleted text for pasting
Ctrl+U
Delete from cursor to line start
Stores deleted text for pasting. Repeat to clear across lines in multiline input. On macOS, terminal emulators including iTerm2 and Terminal.app map
Cmd+Backspace
to this shortcut
Ctrl+W
Delete previous word
Stores deleted text for pasting. On Windows,
Ctrl+Backspace
also deletes the previous word
Ctrl+Y
Paste deleted text
Paste text deleted with
Ctrl+K
,
Ctrl+U
, or
Ctrl+W
Alt+Y
(after
Ctrl+Y
)
Cycle paste history
After pasting, cycle through previously deleted text. Requires
Option as Meta
on macOS
Alt+B
Move cursor back one word
Word navigation. Requires
Option as Meta
on macOS
Alt+F
Move cursor forward one word
Word navigation. Requires
Option as Meta
on macOS
​
Theme and display
Shortcut
Description
Context
Ctrl+T
Toggle syntax highlighting for code blocks
Only works inside the
/theme
picker menu. Controls whether code in Claude’s responses uses syntax coloring
​
Multiline input
Method
Shortcut
Context
Quick escape
\
+
Enter
Works in all terminals
Option key
Option+Enter
After enabling
Option as Meta
on macOS
Shift+Enter
Shift+Enter
Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, Windows Terminal
Control sequence
Ctrl+J
Works in any terminal without configuration
Paste mode
Paste directly
For code blocks, logs
Shift+Enter works without configuration in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, and Windows Terminal. For VS Code, Cursor, Windsurf, Alacritty, and Zed, run
/terminal-setup
to install the binding.
​
Quick commands
Shortcut
Description
Notes
/
at start
Command or skill
See
commands
and
skills
!
at start
Shell mode
Run commands directly and add execution output to the session
@
File path mention
Trigger file path autocomplete
​
Transcript viewer
When the transcript viewer is open (toggled with
Ctrl+O
), these shortcuts are available. In
fullscreen rendering
, press
?
to show the full shortcut reference panel inside the viewer.
Ctrl+E
can be rebound via
transcript:toggleShowAll
.
Shortcut
Description
?
Toggle the keyboard shortcut help panel. Requires
fullscreen rendering
{
/
}
Jump to the previous or next user prompt, like vim paragraph motion. Requires
fullscreen rendering
Ctrl+E
Toggle show all content
[
Write the full conversation to your terminal’s native scrollback so
Cmd+F
, tmux copy mode, and other native tools can search it. Requires
fullscreen rendering
v
Write the conversation to a temporary file and open it in
$VISUAL
or
$EDITOR
. Requires
fullscreen rendering
q
,
Ctrl+C
,
Esc
Exit transcript view. All three can be rebound via
transcript:exit
​
Voice input
Shortcut
Description
Notes
Hold or tap
Space
Voice dictation
Requires
voice dictation
to be enabled. Hold to record, or run
/voice tap
for tap-to-toggle.
Rebindable
​
Commands
Type
/
in Claude Code to see all available commands, or type
/
followed by any letters to filter. The
/
menu shows everything you can invoke: built-in commands, bundled and user-authored
skills
, and commands contributed by
plugins
and
MCP servers
. Not all built-in commands are visible to every user since some depend on your platform or plan.
See the
commands reference
for the full list of commands included in Claude Code.
​
Vim editor mode
Enable vim-style editing via
/config
→ Editor mode.
​
Mode switching
Command
Action
From mode
Esc
Enter NORMAL mode
INSERT, VISUAL
i
Insert before cursor
NORMAL
I
Insert at beginning of line
NORMAL
a
Insert after cursor
NORMAL
A
Insert at end of line
NORMAL
o
Open line below
NORMAL
O
Open line above
NORMAL
v
Start character-wise visual selection
NORMAL
V
Start line-wise visual selection
NORMAL
​
Navigation (NORMAL mode)
Command
Action
h
/
j
/
k
/
l
Move left/down/up/right
Space
Move right
w
Next word
e
End of word
b
Previous word
0
Beginning of line
$
End of line
^
First non-blank character
gg
Beginning of input
G
End of input
f{char}
Jump to next occurrence of character
F{char}
Jump to previous occurrence of character
t{char}
Jump to just before next occurrence of character
T{char}
Jump to just after previous occurrence of character
;
Repeat last f/F/t/T motion
,
Repeat last f/F/t/T motion in reverse
In vim normal mode, if the cursor is at the beginning or end of input and cannot move further,
j
/
k
and the arrow keys navigate command history instead.
​
Editing (NORMAL mode)
Command
Action
x
Delete character
dd
Delete line
D
Delete to end of line
dw
/
de
/
db
Delete word/to end/back
cc
Change line
C
Change to end of line
cw
/
ce
/
cb
Change word/to end/back
yy
/
Y
Yank (copy) line
yw
/
ye
/
yb
Yank word/to end/back
p
Paste after cursor
P
Paste before cursor
>>
Indent line
<<
Dedent line
J
Join lines
u
Undo
.
Repeat last change
​
Text objects (NORMAL mode)
Text objects work with operators like
d
,
c
, and
y
:
Command
Action
iw
/
aw
Inner/around word
iW
/
aW
Inner/around WORD (whitespace-delimited)
i"
/
a"
Inner/around double quotes
i'
/
a'
Inner/around single quotes
i(
/
a(
Inner/around parentheses
i[
/
a[
Inner/around brackets
i{
/
a{
Inner/around braces
​
Visual mode
Press
v
for character-wise selection or
V
for line-wise selection. Motions extend the selection, and operators act on it directly.
Command
Action
d
/
x
Delete selection
y
Yank selection
c
/
s
Change selection
p
Replace selection with register contents
r{char}
Replace every selected character with
{char}
~
/
u
/
U
Toggle, lowercase, or uppercase selection
>
/
<
Indent or dedent selected lines
J
Join selected lines
o
Swap cursor and anchor
iw
/
aw
/
i"
/…
Select a text object
v
/
V
Toggle between character-wise and line-wise, or exit
Block-wise visual mode with
Ctrl+V
is not supported.
​
Command history
Claude Code maintains command history for the current session:
Input history is stored per working directory
Input history resets when you run
/clear
to start a new session. The previous session’s conversation is preserved and can be resumed.
Use Up/Down arrows to navigate (see keyboard shortcuts above)
Note
: history expansion (
!
) is disabled by default
​
Reverse search with Ctrl+R
Press
Ctrl+R
to interactively search through your command history:
Start search
: press
Ctrl+R
to activate reverse history search
Type query
: enter text to search for in previous commands. The search term is highlighted in matching results
Navigate matches
: press
Ctrl+R
again to cycle through older matches
Change scope
: search defaults to prompts from all projects. Press
Ctrl+S
to cycle the scope through this session, this project, and all projects
Accept match
:
Press
Tab
or
Esc
to accept the current match and continue editing
Press
Enter
to accept and execute the command immediately
Cancel search
:
Press
Ctrl+C
to cancel and restore your original input
Press
Backspace
on empty search to cancel
The search displays matching commands with the search term highlighted, so you can find and reuse previous inputs.
​
Background bash commands
Claude Code supports running bash commands in the background, allowing you to continue working while long-running processes execute.
​
How backgrounding works
When Claude Code runs a command in the background, it runs the command asynchronously and immediately returns a background task ID. Claude Code can respond to new prompts while the command continues executing in the background.
To run commands in the background, you can either:
Prompt Claude Code to run a command in the background
Press Ctrl+B to move a regular Bash tool invocation to the background. (Tmux users must press Ctrl+B twice due to tmux’s prefix key.)
Key features:
Output is written to a file and Claude can retrieve it using the Read tool
Background tasks have unique IDs for tracking and output retrieval
Background tasks are automatically cleaned up when Claude Code exits
Background tasks are automatically terminated if output exceeds 5GB, with a note in stderr explaining why
To disable all background task functionality, set the
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
environment variable to
1
. See
Environment variables
for details.
Common backgrounded commands:
Build tools (webpack, vite, make)
Package managers (npm, yarn, pnpm)
Test runners (jest, pytest)
Development servers
Long-running processes (docker, terraform)
​
Shell mode with
!
prefix
Run shell commands directly without going through Claude by prefixing your input with
!
:
!
npm
test
!
git
status
!
ls
-la
Shell mode:
Adds the command and its output to the conversation context
Shows real-time progress and output
Supports the same
Ctrl+B
backgrounding for long-running commands
Does not require Claude to interpret or approve the command
Supports history-based autocomplete: type a partial command and press
Tab
to complete from previous
!
commands in the current project
Exit with
Escape
,
Backspace
, or
Ctrl+U
on an empty prompt
Pasting text that starts with
!
into an empty prompt enters shell mode automatically, matching typed
!
behavior
This is useful for quick shell operations while maintaining conversation context.
​
Prompt suggestions
When you first open a session, a grayed-out example command appears in the prompt input to help you get started. Claude Code picks this from your project’s git history, so it reflects files you’ve been working on recently.
After Claude responds, suggestions continue to appear based on your conversation history, such as a follow-up step from a multi-part request or a natural continuation of your workflow.
Press
Tab
or
Right arrow
to place the suggestion in the prompt input, then
Enter
to submit
Start typing to dismiss it
The suggestion runs as a background request that reuses the parent conversation’s prompt cache, so the additional cost is minimal. Claude Code skips suggestion generation when the cache is cold to avoid unnecessary cost.
Suggestions are automatically skipped after the first turn of a conversation, in non-interactive mode, and in plan mode.
To disable prompt suggestions entirely, set the environment variable or toggle the setting in
/config
:
export
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION
=
false
​
Side questions with /btw
Use
/btw
to ask a quick question about your current work without adding to the conversation history. This is useful when you want a fast answer but don’t want to clutter the main context or derail Claude from a long-running task.
/btw what was the name of that config file again?
Side questions have full visibility into the current conversation, so you can ask about code Claude has already read, decisions it made earlier, or anything else from the session. The question and answer are ephemeral: they appear in a dismissible overlay and never enter the conversation history.
Available while Claude is working
: you can run
/btw
even while Claude is processing a response. The side question runs independently and does not interrupt the main turn.
No tool access
: side questions answer only from what is already in context. Claude cannot read files, run commands, or search when answering a side question.
Single response
: there are no follow-up turns. If you need a back-and-forth, use a normal prompt instead.
Low cost
: the side question reuses the parent conversation’s prompt cache, so the additional cost is minimal.
Press
Space
,
Enter
, or
Escape
to dismiss the answer and return to the prompt.
/btw
is the inverse of a
subagent
: it sees your full conversation but has no tools, while a subagent has full tools but starts with an empty context. Use
/btw
to ask about what Claude already knows from this session; use a subagent to go find out something new.
​
Task list
When working on complex, multi-step work, Claude creates a task list to track progress. Tasks appear in the status area of your terminal with indicators showing what’s pending, in progress, or complete.
Press
Ctrl+T
to toggle the task list view. The display shows up to 5 tasks at a time
To see all tasks or clear them, ask Claude directly: “show me all tasks” or “clear all tasks”
Tasks persist across context compactions, helping Claude stay organized on larger projects
To share a task list across sessions, set
CLAUDE_CODE_TASK_LIST_ID
to use a named directory in
~/.claude/tasks/
:
CLAUDE_CODE_TASK_LIST_ID=my-project claude
​
Session recap
When you return to the terminal after stepping away, Claude Code shows a one-line recap of what happened in the session so far. The recap generates in the background once at least three minutes have passed since the last completed turn and the terminal is unfocused, so it’s ready when you switch back. Recaps only appear once the session has at least three turns, and never twice in a row.
Run
/recap
to generate a summary on demand. To turn automatic recaps off, open
/config
and disable
Session recap
.
Session recap is on by default for every plan and provider. The recap is always skipped in non-interactive mode.
​
PR review status
When working on a branch with an open pull request, Claude Code displays a clickable PR link in the footer (for example, “PR #446”). The link has a colored underline indicating the review state:
Green: approved
Yellow: pending review
Red: changes requested
Gray: draft
Purple: merged
Cmd+click
(Mac) or
Ctrl+click
(Windows/Linux) the link to open the pull request in your browser. The status updates automatically every 60 seconds.
PR status requires the
gh
CLI to be installed and authenticated (
gh auth login
).
​
See also
Skills
- Custom prompts and workflows
Checkpointing
- Rewind Claude’s edits and restore previous states
CLI reference
- Command-line flags and options
Settings
- Configuration options
Memory management
- Managing CLAUDE.md files
Was this page helpful?
Yes
No
Tools reference
Checkpointing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/interactive-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Interactive mode
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Keyboard shortcuts
Keyboard shortcuts may var...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Interactive mode
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Keyboard shortcuts
Keyboard shortcuts may vary by platform and terminal. In
fullscreen rendering
, press
?
in the transcript viewer to see available shortcuts there.
macOS users
: Option/Alt key shortcuts (
Alt+B
,
Alt+F
,
Alt+Y
,
Alt+M
,
Alt+P
) require configuring Option as Meta in your terminal:
iTerm2
: Settings → Profiles → Keys → General → set Left/Right Option key to “Esc+”
Apple Terminal
: Settings → Profiles → Keyboard → check “Use Option as Meta Key”
VS Code
: set
"terminal.integrated.macOptionIsMeta": true
in VS Code settings
See
Terminal configuration
for details.
​
General controls
Shortcut
Description
Context
Ctrl+C
Cancel current input or generation
Standard interrupt
Ctrl+X Ctrl+K
Kill all running
background subagents
in this session. Press twice within 3 seconds to confirm
Subagent control
Ctrl+D
Exit Claude Code session
EOF signal
Ctrl+G
or
Ctrl+X Ctrl+E
Open in default text editor
Edit your prompt or custom response in your default text editor.
Ctrl+X Ctrl+E
is the readline-native binding. Turn on Show last response in external editor in
/config
to prepend Claude’s previous reply as
#
-commented context above your prompt; the comment block is stripped when you save
Ctrl+L
Redraw screen
Forces a full terminal redraw. Input and conversation history are kept. Use this to recover if the display becomes garbled or partially blank
Ctrl+O
Toggle transcript viewer
Shows detailed tool usage and execution. Also expands MCP calls, which collapse to a single line like “Called slack 3 times” by default
Ctrl+R
Reverse search command history
Search through previous commands interactively
Ctrl+V
or
Cmd+V
(iTerm2) or
Alt+V
(Windows)
Paste image from clipboard
Inserts an
[Image #N]
chip at the cursor so you can reference it positionally in your prompt
Ctrl+B
Background running tasks
Backgrounds bash commands and agents. Tmux users press twice
Ctrl+T
Toggle task list
Show or hide the
task list
in the terminal status area
Left/Right arrows
Cycle through dialog tabs
Navigate between tabs in permission dialogs and menus
Up/Down arrows
or
Ctrl+P
/
Ctrl+N
Move cursor or navigate command history
In multiline input, first moves the cursor within the prompt. Once the cursor is already on the top or bottom edge, pressing again navigates command history
Esc
Interrupt Claude
Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far
Esc
+
Esc
Rewind or summarize
Restore code and/or conversation to a previous point, or summarize from a selected message
Shift+Tab
or
Alt+M
(some configurations)
Cycle permission modes
Cycle through
default
,
acceptEdits
,
plan
, and any modes you have enabled, such as
auto
or
bypassPermissions
. See
permission modes
.
Option+P
(macOS) or
Alt+P
(Windows/Linux)
Switch model
Switch models without clearing your prompt
Option+T
(macOS) or
Alt+T
(Windows/Linux)
Toggle extended thinking
Enable or disable extended thinking mode. As of v2.1.132 this shortcut works on macOS without configuring Option as Meta
Option+O
(macOS) or
Alt+O
(Windows/Linux)
Toggle fast mode
Enable or disable
fast mode
​
Text editing
Shortcut
Description
Context
Ctrl+A
Move cursor to start of current line
In multiline input, moves to the start of the current logical line
Ctrl+E
Move cursor to end of current line
In multiline input, moves to the end of the current logical line
Ctrl+K
Delete to end of line
Stores deleted text for pasting
Ctrl+U
Delete from cursor to line start
Stores deleted text for pasting. Repeat to clear across lines in multiline input. On macOS, terminal emulators including iTerm2 and Terminal.app map
Cmd+Backspace
to this shortcut
Ctrl+W
Delete previous word
Stores deleted text for pasting. On Windows,
Ctrl+Backspace
also deletes the previous word
Ctrl+Y
Paste deleted text
Paste text deleted with
Ctrl+K
,
Ctrl+U
, or
Ctrl+W
Alt+Y
(after
Ctrl+Y
)
Cycle paste history
After pasting, cycle through previously deleted text. Requires
Option as Meta
on macOS
Alt+B
Move cursor back one word
Word navigation. Requires
Option as Meta
on macOS
Alt+F
Move cursor forward one word
Word navigation. Requires
Option as Meta
on macOS
​
Theme and display
Shortcut
Description
Context
Ctrl+T
Toggle syntax highlighting for code blocks
Only works inside the
/theme
picker menu. Controls whether code in Claude’s responses uses syntax coloring
​
Multiline input
Method
Shortcut
Context
Quick escape
\
+
Enter
Works in all terminals
Option key
Option+Enter
After enabling
Option as Meta
on macOS
Shift+Enter
Shift+Enter
Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, Windows Terminal
Control sequence
Ctrl+J
Works in any terminal without configuration
Paste mode
Paste directly
For code blocks, logs
Shift+Enter works without configuration in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, and Windows Terminal. For VS Code, Cursor, Windsurf, Alacritty, and Zed, run
/terminal-setup
to install the binding.
​
Quick commands
Shortcut
Description
Notes
/
at start
Command or skill
See
commands
and
skills
!
at start
Shell mode
Run commands directly and add execution output to the session
@
File path mention
Trigger file path autocomplete
​
Transcript viewer
When the transcript viewer is open (toggled with
Ctrl+O
), these shortcuts are available. In
fullscreen rendering
, press
?
to show the full shortcut reference panel inside the viewer.
Ctrl+E
can be rebound via
transcript:toggleShowAll
.
Shortcut
Description
?
Toggle the keyboard shortcut help panel. Requires
fullscreen rendering
{
/
}
Jump to the previous or next user prompt, like vim paragraph motion. Requires
fullscreen rendering
Ctrl+E
Toggle show all content
[
Write the full conversation to your terminal’s native scrollback so
Cmd+F
, tmux copy mode, and other native tools can search it. Requires
fullscreen rendering
v
Write the conversation to a temporary file and open it in
$VISUAL
or
$EDITOR
. Requires
fullscreen rendering
q
,
Ctrl+C
,
Esc
Exit transcript view. All three can be rebound via
transcript:exit
​
Voice input
Shortcut
Description
Notes
Hold or tap
Space
Voice dictation
Requires
voice dictation
to be enabled. Hold to record, or run
/voice tap
for tap-to-toggle.
Rebindable
​
Commands
Type
/
in Claude Code to see all available commands, or type
/
followed by any letters to filter. The
/
menu shows everything you can invoke: built-in commands, bundled and user-authored
skills
, and commands contributed by
plugins
and
MCP servers
. Not all built-in commands are visible to every user since some depend on your platform or plan.
See the
commands reference
for the full list of commands included in Claude Code.
​
Vim editor mode
Enable vim-style editing via
/config
→ Editor mode.
​
Mode switching
Command
Action
From mode
Esc
Enter NORMAL mode
INSERT, VISUAL
i
Insert before cursor
NORMAL
I
Insert at beginning of line
NORMAL
a
Insert after cursor
NORMAL
A
Insert at end of line
NORMAL
o
Open line below
NORMAL
O
Open line above
NORMAL
v
Start character-wise visual selection
NORMAL
V
Start line-wise visual selection
NORMAL
​
Navigation (NORMAL mode)
Command
Action
h
/
j
/
k
/
l
Move left/down/up/right
Space
Move right
w
Next word
e
End of word
b
Previous word
0
Beginning of line
$
End of line
^
First non-blank character
gg
Beginning of input
G
End of input
f{char}
Jump to next occurrence of character
F{char}
Jump to previous occurrence of character
t{char}
Jump to just before next occurrence of character
T{char}
Jump to just after previous occurrence of character
;
Repeat last f/F/t/T motion
,
Repeat last f/F/t/T motion in reverse
In vim normal mode, if the cursor is at the beginning or end of input and cannot move further,
j
/
k
and the arrow keys navigate command history instead.
​
Editing (NORMAL mode)
Command
Action
x
Delete character
dd
Delete line
D
Delete to end of line
dw
/
de
/
db
Delete word/to end/back
cc
Change line
C
Change to end of line
cw
/
ce
/
cb
Change word/to end/back
yy
/
Y
Yank (copy) line
yw
/
ye
/
yb
Yank word/to end/back
p
Paste after cursor
P
Paste before cursor
>>
Indent line
<<
Dedent line
J
Join lines
u
Undo
.
Repeat last change
​
Text objects (NORMAL mode)
Text objects work with operators like
d
,
c
, and
y
:
Command
Action
iw
/
aw
Inner/around word
iW
/
aW
Inner/around WORD (whitespace-delimited)
i"
/
a"
Inner/around double quotes
i'
/
a'
Inner/around single quotes
i(
/
a(
Inner/around parentheses
i[
/
a[
Inner/around brackets
i{
/
a{
Inner/around braces
​
Visual mode
Press
v
for character-wise selection or
V
for line-wise selection. Motions extend the selection, and operators act on it directly.
Command
Action
d
/
x
Delete selection
y
Yank selection
c
/
s
Change selection
p
Replace selection with register contents
r{char}
Replace every selected character with
{char}
~
/
u
/
U
Toggle, lowercase, or uppercase selection
>
/
<
Indent or dedent selected lines
J
Join selected lines
o
Swap cursor and anchor
iw
/
aw
/
i"
/…
Select a text object
v
/
V
Toggle between character-wise and line-wise, or exit
Block-wise visual mode with
Ctrl+V
is not supported.
​
Command history
Claude Code maintains command history for the current session:
Input history is stored per working directory
Input history resets when you run
/clear
to start a new session. The previous session’s conversation is preserved and can be resumed.
Use Up/Down arrows to navigate (see keyboard shortcuts above)
Note
: history expansion (
!
) is disabled by default
​
Reverse search with Ctrl+R
Press
Ctrl+R
to interactively search through your command history:
Start search
: press
Ctrl+R
to activate reverse history search
Type query
: enter text to search for in previous commands. The search term is highlighted in matching results
Navigate matches
: press
Ctrl+R
again to cycle through older matches
Change scope
: search defaults to prompts from all projects. Press
Ctrl+S
to cycle the scope through this session, this project, and all projects
Accept match
:
Press
Tab
or
Esc
to accept the current match and continue editing
Press
Enter
to accept and execute the command immediately
Cancel search
:
Press
Ctrl+C
to cancel and restore your original input
Press
Backspace
on empty search to cancel
The search displays matching commands with the search term highlighted, so you can find and reuse previous inputs.
​
Background bash commands
Claude Code supports running bash commands in the background, allowing you to continue working while long-running processes execute.
​
How backgrounding works
When Claude Code runs a command in the background, it runs the command asynchronously and immediately returns a background task ID. Claude Code can respond to new prompts while the command continues executing in the background.
To run commands in the background, you can either:
Prompt Claude Code to run a command in the background
Press Ctrl+B to move a regular Bash tool invocation to the background. (Tmux users must press Ctrl+B twice due to tmux’s prefix key.)
Key features:
Output is written to a file and Claude can retrieve it using the Read tool
Background tasks have unique IDs for tracking and output retrieval
Background tasks are automatically cleaned up when Claude Code exits
Background tasks are automatically terminated if output exceeds 5GB, with a note in stderr explaining why
To disable all background task functionality, set the
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
environment variable to
1
. See
Environment variables
for details.
Common backgrounded commands:
Build tools (webpack, vite, make)
Package managers (npm, yarn, pnpm)
Test runners (jest, pytest)
Development servers
Long-running processes (docker, terraform)
​
Shell mode with
!
prefix
Run shell commands directly without going through Claude by prefixing your input with
!
:
!
npm
test
!
git
status
!
ls
-la
Shell mode:
Adds the command and its output to the conversation context
Shows real-time progress and output
Supports the same
Ctrl+B
backgrounding for long-running commands
Does not require Claude to interpret or approve the command
Supports history-based autocomplete: type a partial command and press
Tab
to complete from previous
!
commands in the current project
Exit with
Escape
,
Backspace
, or
Ctrl+U
on an empty prompt
Pasting text that starts with
!
into an empty prompt enters shell mode automatically, matching typed
!
behavior
This is useful for quick shell operations while maintaining conversation context.
​
Prompt suggestions
When you first open a session, a grayed-out example command appears in the prompt input to help you get started. Claude Code picks this from your project’s git history, so it reflects files you’ve been working on recently.
After Claude responds, suggestions continue to appear based on your conversation history, such as a follow-up step from a multi-part request or a natural continuation of your workflow.
Press
Tab
or
Right arrow
to place the suggestion in the prompt input, then
Enter
to submit
Start typing to dismiss it
The suggestion runs as a background request that reuses the parent conversation’s prompt cache, so the additional cost is minimal. Claude Code skips suggestion generation when the cache is cold to avoid unnecessary cost.
Suggestions are automatically skipped after the first turn of a conversation, in non-interactive mode, and in plan mode.
To disable prompt suggestions entirely, set the environment variable or toggle the setting in
/config
:
export
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION
=
false
​
Side questions with /btw
Use
/btw
to ask a quick question about your current work without adding to the conversation history. This is useful when you want a fast answer but don’t want to clutter the main context or derail Claude from a long-running task.
/btw what was the name of that config file again?
Side questions have full visibility into the current conversation, so you can ask about code Claude has already read, decisions it made earlier, or anything else from the session. The question and answer are ephemeral: they appear in a dismissible overlay and never enter the conversation history.
Available while Claude is working
: you can run
/btw
even while Claude is processing a response. The side question runs independently and does not interrupt the main turn.
No tool access
: side questions answer only from what is already in context. Claude cannot read files, run commands, or search when answering a side question.
Single response
: there are no follow-up turns. If you need a back-and-forth, use a normal prompt instead.
Low cost
: the side question reuses the parent conversation’s prompt cache, so the additional cost is minimal.
Press
Space
,
Enter
, or
Escape
to dismiss the answer and return to the prompt.
/btw
is the inverse of a
subagent
: it sees your full conversation but has no tools, while a subagent has full tools but starts with an empty context. Use
/btw
to ask about what Claude already knows from this session; use a subagent to go find out something new.
​
Task list
When working on complex, multi-step work, Claude creates a task list to track progress. Tasks appear in the status area of your terminal with indicators showing what’s pending, in progress, or complete.
Press
Ctrl+T
to toggle the task list view. The display shows up to 5 tasks at a time
To see all tasks or clear them, ask Claude directly: “show me all tasks” or “clear all tasks”
Tasks persist across context compactions, helping Claude stay organized on larger projects
To share a task list across sessions, set
CLAUDE_CODE_TASK_LIST_ID
to use a named directory in
~/.claude/tasks/
:
CLAUDE_CODE_TASK_LIST_ID=my-project claude
​
Session recap
When you return to the terminal after stepping away, Claude Code shows a one-line recap of what happened in the session so far. The recap generates in the background once at least three minutes have passed since the last completed turn and the terminal is unfocused, so it’s ready when you switch back. Recaps only appear once the session has at least three turns, and never twice in a row.
Run
/recap
to generate a summary on demand. To turn automatic recaps off, open
/config
and disable
Session recap
.
Session recap is on by default for every plan and provider. The recap is always skipped in non-interactive mode.
​
PR review status
When working on a branch with an open pull request, Claude Code displays a clickable PR link in the footer (for example, “PR #446”). The link has a colored underline indicating the review state:
Green: approved
Yellow: pending review
Red: changes requested
Gray: draft
Purple: merged
Cmd+click
(Mac) or
Ctrl+click
(Windows/Linux) the link to open the pull request in your browser. The status updates automatically every 60 seconds.
PR status requires the
gh
CLI to be installed and authenticated (
gh auth login
).
​
See also
Skills
- Custom prompts and workflows
Checkpointing
- Rewind Claude’s edits and restore previous states
CLI reference
- Command-line flags and options
Settings
- Configuration options
Memory management
- Managing CLAUDE.md files
Was this page helpful?
Yes
No
Tools reference
Checkpointing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/interactive-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Streaming Input</title>
  <link>https://code.claude.com/docs/en/agent-sdk/streaming-vs-single-mode</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/streaming-vs-single-mode</guid>
  <pubDate>Sat, 14 Dec 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Streaming Input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Streaming Input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
The Claude Agent SDK supports two distinct input modes for interacting with agents:
Streaming Input Mode
(Default & Recommended) - A persistent, interactive session
Single Message Input
- One-shot queries that use session state and resuming
This guide explains the differences, benefits, and use cases for each mode to help you choose the right approach for your application.
​
Streaming Input Mode (Recommended)
Streaming input mode is the
preferred
way to use the Claude Agent SDK. It provides full access to the agent’s capabilities and enables rich, interactive experiences.
It allows the agent to operate as a long lived process that takes in user input, handles interruptions, surfaces permission requests, and handles session management.
​
How It Works
Environment/
File System
Tools/Hooks
Claude Agent
Your Application
Environment/
File System
Tools/Hooks
Claude Agent
Your Application
Session stays alive
Persistent file system
state maintained
Initialize with AsyncGenerator
Yield Message 1
Execute tools
Read files
File contents
Write/Edit files
Success/Error
Stream partial response
Stream more content...
Complete Message 1
Yield Message 2 + Image
Process image & execute
Access filesystem
Operation results
Stream response 2
Queue Message 3
Interrupt/Cancel
Handle interruption
​
Benefits
Image Uploads
Attach images directly to messages for visual analysis and understanding
Queued Messages
Send multiple messages that process sequentially, with ability to interrupt
Tool Integration
Full access to all tools and custom MCP servers during the session
Hooks Support
Use lifecycle hooks to customize behavior at various points
Real-time Feedback
See responses as they’re generated, not just final results
Context Persistence
Maintain conversation context across multiple turns naturally
​
Implementation Example
TypeScript
Python
import
{
query
,
type
SDKUserMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
{
readFile
}
from
"fs/promises"
;
async
function*
generateMessages
()
:
AsyncGenerator
<
SDKUserMessage
> {
// First message
yield
{
type:
"user"
,
message:
{
role:
"user"
,
content:
"Analyze this codebase for security issues"
},
parent_tool_use_id:
null
};
// Wait for conditions or user input
await
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
2000
));
// Follow-up with image
yield
{
type:
"user"
,
message:
{
role:
"user"
,
content:
[
{
type:
"text"
,
text:
"Review this architecture diagram"
},
{
type:
"image"
,
source:
{
type:
"base64"
,
media_type:
"image/png"
,
data:
await
readFile
(
"diagram.png"
,
"base64"
)
}
}
]
},
parent_tool_use_id:
null
};
}
// Process streaming responses
for
await
(
const
message
of
query
({
prompt:
generateMessages
(),
options:
{
maxTurns:
10
,
allowedTools:
[
"Read"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Single Message Input
Single message input is simpler but more limited.
​
When to Use Single Message Input
Use single message input when:
You need a one-shot response
You do not need image attachments, hooks, etc.
You need to operate in a stateless environment, such as a lambda function
​
Limitations
Single message input mode does
not
support:
Direct image attachments in messages
Dynamic message queueing
Real-time interruption
Hook integration
Natural multi-turn conversations
​
Implementation Example
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Simple one-shot query
for
await
(
const
message
of
query
({
prompt:
"Explain the authentication flow"
,
options:
{
maxTurns:
1
,
allowedTools:
[
"Read"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
// Continue conversation with session management
for
await
(
const
message
of
query
({
prompt:
"Now explain the authorization process"
,
options:
{
continue:
true
,
maxTurns:
1
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
Was this page helpful?
Yes
No
Work with sessions
Handle approvals and user input
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/streaming-vs-single-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Streaming Input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Streaming Input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
The Claude Agent SDK supports two distinct input modes for interacting with agents:
Streaming Input Mode
(Default & Recommended) - A persistent, interactive session
Single Message Input
- One-shot queries that use session state and resuming
This guide explains the differences, benefits, and use cases for each mode to help you choose the right approach for your application.
​
Streaming Input Mode (Recommended)
Streaming input mode is the
preferred
way to use the Claude Agent SDK. It provides full access to the agent’s capabilities and enables rich, interactive experiences.
It allows the agent to operate as a long lived process that takes in user input, handles interruptions, surfaces permission requests, and handles session management.
​
How It Works
Environment/
File System
Tools/Hooks
Claude Agent
Your Application
Environment/
File System
Tools/Hooks
Claude Agent
Your Application
Session stays alive
Persistent file system
state maintained
Initialize with AsyncGenerator
Yield Message 1
Execute tools
Read files
File contents
Write/Edit files
Success/Error
Stream partial response
Stream more content...
Complete Message 1
Yield Message 2 + Image
Process image & execute
Access filesystem
Operation results
Stream response 2
Queue Message 3
Interrupt/Cancel
Handle interruption
​
Benefits
Image Uploads
Attach images directly to messages for visual analysis and understanding
Queued Messages
Send multiple messages that process sequentially, with ability to interrupt
Tool Integration
Full access to all tools and custom MCP servers during the session
Hooks Support
Use lifecycle hooks to customize behavior at various points
Real-time Feedback
See responses as they’re generated, not just final results
Context Persistence
Maintain conversation context across multiple turns naturally
​
Implementation Example
TypeScript
Python
import
{
query
,
type
SDKUserMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
{
readFile
}
from
"fs/promises"
;
async
function*
generateMessages
()
:
AsyncGenerator
<
SDKUserMessage
> {
// First message
yield
{
type:
"user"
,
message:
{
role:
"user"
,
content:
"Analyze this codebase for security issues"
},
parent_tool_use_id:
null
};
// Wait for conditions or user input
await
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
2000
));
// Follow-up with image
yield
{
type:
"user"
,
message:
{
role:
"user"
,
content:
[
{
type:
"text"
,
text:
"Review this architecture diagram"
},
{
type:
"image"
,
source:
{
type:
"base64"
,
media_type:
"image/png"
,
data:
await
readFile
(
"diagram.png"
,
"base64"
)
}
}
]
},
parent_tool_use_id:
null
};
}
// Process streaming responses
for
await
(
const
message
of
query
({
prompt:
generateMessages
(),
options:
{
maxTurns:
10
,
allowedTools:
[
"Read"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Single Message Input
Single message input is simpler but more limited.
​
When to Use Single Message Input
Use single message input when:
You need a one-shot response
You do not need image attachments, hooks, etc.
You need to operate in a stateless environment, such as a lambda function
​
Limitations
Single message input mode does
not
support:
Direct image attachments in messages
Dynamic message queueing
Real-time interruption
Hook integration
Natural multi-turn conversations
​
Implementation Example
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Simple one-shot query
for
await
(
const
message
of
query
({
prompt:
"Explain the authentication flow"
,
options:
{
maxTurns:
1
,
allowedTools:
[
"Read"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
// Continue conversation with session management
for
await
(
const
message
of
query
({
prompt:
"Now explain the authorization process"
,
options:
{
continue:
true
,
maxTurns:
1
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
Was this page helpful?
Yes
No
Work with sessions
Handle approvals and user input
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/streaming-vs-single-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Customize keyboard shortcuts</title>
  <link>https://code.claude.com/docs/en/keybindings</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/keybindings</guid>
  <pubDate>Sat, 14 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize keyboard shortcuts
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize keyboard shortcuts
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Customizable keyboard shortcuts require Claude Code v2.1.18 or later. Check your version with
claude --version
.
Claude Code supports customizable keyboard shortcuts. Run
/keybindings
to create or open your configuration file at
~/.claude/keybindings.json
.
​
Configuration file
The keybindings configuration file is an object with a
bindings
array. Each block specifies a context and a map of keystrokes to actions.
Changes to the keybindings file are automatically detected and applied without restarting Claude Code.
Field
Description
$schema
Optional JSON Schema URL for editor autocompletion
$docs
Optional documentation URL
bindings
Array of binding blocks by context
This example binds
Ctrl+E
to open an external editor in the chat context, and unbinds
Ctrl+U
:
{
"$schema"
:
"https://www.schemastore.org/claude-code-keybindings.json"
,
"$docs"
:
"https://code.claude.com/docs/en/keybindings"
,
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+e"
:
"chat:externalEditor"
,
"ctrl+u"
:
null
}
}
]
}
​
Contexts
Each binding block specifies a
context
where the bindings apply:
Context
Description
Global
Applies everywhere in the app
Chat
Main chat input area
Autocomplete
Autocomplete menu is open
Settings
Settings menu
Confirmation
Permission and confirmation dialogs
Tabs
Tab navigation components
Help
Help menu is visible
Transcript
Transcript viewer
HistorySearch
History search mode (Ctrl+R)
Task
Background task is running
ThemePicker
Theme picker dialog
Attachments
Image attachment navigation in select dialogs
Footer
Footer indicator navigation (tasks, teams, diff)
MessageSelector
Rewind and summarize dialog message selection
DiffDialog
Diff viewer navigation
ModelPicker
Model picker effort level
Select
Generic select/list components
Plugin
Plugin dialog (browse, discover, manage)
Scroll
Conversation scrolling and text selection in fullscreen mode
Doctor
/doctor
diagnostics screen
​
Available actions
Actions follow a
namespace:action
format, such as
chat:submit
to send a message or
app:toggleTodos
to show the task list. Each context has specific actions available.
​
App actions
Actions available in the
Global
context:
Action
Default
Description
app:interrupt
Ctrl+C
Cancel current operation
app:exit
Ctrl+D
Exit Claude Code
app:redraw
(unbound)
Force terminal redraw
app:toggleTodos
Ctrl+T
Toggle task list visibility
app:toggleTranscript
Ctrl+O
Toggle verbose transcript
​
History actions
Actions for navigating command history:
Action
Default
Description
history:search
Ctrl+R
Open history search
history:previous
Up
Previous history item
history:next
Down
Next history item
​
Chat actions
Actions available in the
Chat
context:
Action
Default
Description
chat:cancel
Escape
Cancel current input
chat:clearInput
Ctrl+L
Force a full screen redraw, preserving input. In
fullscreen rendering
, press twice within two seconds to run
/clear
chat:clearScreen
Cmd+K
In
fullscreen rendering
, press twice within two seconds to run
/clear
chat:killAgents
Ctrl+X Ctrl+K
Kill all running
background subagents
in this session
chat:cycleMode
Shift+Tab*
Cycle permission modes
chat:modelPicker
Meta+P
Open model picker
chat:fastMode
Meta+O
Toggle fast mode
chat:thinkingToggle
Meta+T
Toggle extended thinking
chat:submit
Enter
Submit message
chat:newline
Ctrl+J
Insert a newline without submitting
chat:undo
Ctrl+_, Ctrl+Shift+-
Undo last action
chat:externalEditor
Ctrl+G, Ctrl+X Ctrl+E
Open in external editor
chat:stash
Ctrl+S
Stash current prompt
chat:imagePaste
Ctrl+V (Alt+V on Windows)
Paste image
*On Windows without VT mode (Node <24.2.0/<22.17.0, Bun <1.2.23), defaults to Meta+M.
​
Autocomplete actions
Actions available in the
Autocomplete
context:
Action
Default
Description
autocomplete:accept
Tab
Accept suggestion
autocomplete:dismiss
Escape
Dismiss menu
autocomplete:previous
Up
Previous suggestion
autocomplete:next
Down
Next suggestion
​
Confirmation actions
Actions available in the
Confirmation
context:
Action
Default
Description
confirm:yes
Y, Enter
Confirm action
confirm:no
N, Escape
Decline action
confirm:previous
Up
Previous option
confirm:next
Down
Next option
confirm:nextField
Tab
Next field
confirm:previousField
(unbound)
Previous field
confirm:toggle
Space
Toggle selection
confirm:cycleMode
Shift+Tab
Cycle permission modes
confirm:toggleExplanation
Ctrl+E
Toggle permission explanation
​
Permission actions
Actions available in the
Confirmation
context for permission dialogs:
Action
Default
Description
permission:toggleDebug
Ctrl+D
Toggle permission debug info
​
Transcript actions
Actions available in the
Transcript
context:
Action
Default
Description
transcript:toggleShowAll
Ctrl+E
Toggle show all content
transcript:exit
q, Ctrl+C, Escape
Exit transcript view
​
History search actions
Actions available in the
HistorySearch
context:
Action
Default
Description
historySearch:next
Ctrl+R
Next match
historySearch:accept
Escape, Tab
Accept selection
historySearch:cancel
Ctrl+C
Cancel search
historySearch:execute
Enter
Execute selected command
historySearch:cycleScope
Ctrl+S
Cycle scope: session, project, everywhere
​
Task actions
Actions available in the
Task
context:
Action
Default
Description
task:background
Ctrl+B
Background current task
​
Theme actions
Actions available in the
ThemePicker
context:
Action
Default
Description
theme:toggleSyntaxHighlighting
Ctrl+T
Toggle syntax highlighting
​
Help actions
Actions available in the
Help
context:
Action
Default
Description
help:dismiss
Escape
Close help menu
​
Tabs actions
Actions available in the
Tabs
context:
Action
Default
Description
tabs:next
Tab, Right
Next tab
tabs:previous
Shift+Tab, Left
Previous tab
​
Attachments actions
Actions available in the
Attachments
context:
Action
Default
Description
attachments:next
Right
Next attachment
attachments:previous
Left
Previous attachment
attachments:remove
Backspace, Delete
Remove selected attachment
attachments:exit
Down, Escape
Exit attachment navigation
​
Footer actions
Actions available in the
Footer
context:
Action
Default
Description
footer:next
Right
Next footer item
footer:previous
Left
Previous footer item
footer:up
Up
Navigate up in footer (deselects at top)
footer:down
Down
Navigate down in footer
footer:openSelected
Enter
Open selected footer item
footer:clearSelection
Escape
Clear footer selection
​
Message selector actions
Actions available in the
MessageSelector
context:
Action
Default
Description
messageSelector:up
Up, K, Ctrl+P
Move up in list
messageSelector:down
Down, J, Ctrl+N
Move down in list
messageSelector:top
Ctrl+Up, Shift+Up, Meta+Up, Shift+K
Jump to top
messageSelector:bottom
Ctrl+Down, Shift+Down, Meta+Down, Shift+J
Jump to bottom
messageSelector:select
Enter
Select message
​
Diff actions
Actions available in the
DiffDialog
context:
Action
Default
Description
diff:dismiss
Escape
Close diff viewer
diff:previousSource
Left
Previous diff source
diff:nextSource
Right
Next diff source
diff:previousFile
Up
Previous file in diff
diff:nextFile
Down
Next file in diff
diff:viewDetails
Enter
View diff details
diff:back
(context-specific)
Go back in diff viewer
​
Model picker actions
Actions available in the
ModelPicker
context:
Action
Default
Description
modelPicker:decreaseEffort
Left
Decrease effort level
modelPicker:increaseEffort
Right
Increase effort level
​
Select actions
Actions available in the
Select
context:
Action
Default
Description
select:next
Down, J, Ctrl+N
Next option
select:previous
Up, K, Ctrl+P
Previous option
select:accept
Enter
Accept selection
select:cancel
Escape
Cancel selection
​
Plugin actions
Actions available in the
Plugin
context:
Action
Default
Description
plugin:toggle
Space
Toggle plugin selection
plugin:install
I
Install selected plugins
plugin:favorite
F
Favorite the selected plugin so it sorts near the top of the Installed tab
​
Settings actions
Actions available in the
Settings
context:
Action
Default
Description
settings:search
/
Enter search mode
settings:retry
R
Retry loading usage data (on error)
settings:close
Enter
Save changes and close the config panel. Escape discards changes and closes
​
Doctor actions
Actions available in the
Doctor
context:
Action
Default
Description
doctor:fix
F
Send the diagnostics report to Claude to fix the reported issues. Only active when issues are found
​
Voice actions
Actions available in the
Chat
context when
voice dictation
is enabled:
Action
Default
Description
voice:pushToTalk
Space
Dictate a prompt. Hold or tap depending on
/voice
mode
​
Scroll actions
Actions available in the
Scroll
context when
fullscreen rendering
is enabled:
Action
Default
Description
scroll:lineUp
(unbound)
Scroll up one line. Mouse wheel scrolling triggers this action
scroll:lineDown
(unbound)
Scroll down one line. Mouse wheel scrolling triggers this action
scroll:pageUp
PageUp
Scroll up half the viewport height
scroll:pageDown
PageDown
Scroll down half the viewport height
scroll:top
Ctrl+Home
Jump to the start of the conversation
scroll:bottom
Ctrl+End
Jump to the latest message and re-enable auto-follow
scroll:halfPageUp
(unbound)
Scroll up half the viewport height. Same behavior as
scroll:pageUp
, provided for vi-style rebinds
scroll:halfPageDown
(unbound)
Scroll down half the viewport height. Same behavior as
scroll:pageDown
, provided for vi-style rebinds
scroll:fullPageUp
(unbound)
Scroll up the full viewport height
scroll:fullPageDown
(unbound)
Scroll down the full viewport height
selection:copy
Ctrl+Shift+C / Cmd+C
Copy the selected text to the clipboard
selection:clear
(unbound)
Clear the active text selection
selection:extendLeft
Shift+Left
Extend the active selection one column left
selection:extendRight
Shift+Right
Extend the active selection one column right
selection:extendUp
Shift+Up
Extend the active selection one row up. Scrolls the viewport when the selection reaches the top edge
selection:extendDown
Shift+Down
Extend the active selection one row down. Scrolls the viewport when the selection reaches the bottom edge
selection:extendLineStart
Shift+Home
Extend the active selection to the start of the line
selection:extendLineEnd
Shift+End
Extend the active selection to the end of the line
​
Keystroke syntax
​
Modifiers
Use modifier keys with the
+
separator:
ctrl
or
control
- Control key
shift
- Shift key
alt
,
opt
,
option
, or
meta
- Alt key on Windows and Linux, Option key on macOS
cmd
,
command
,
super
, or
win
- Command key on macOS, Windows key on Windows, Super key on Linux
The
cmd
group is only detected in terminals that report the Super modifier, such as those supporting the Kitty keyboard protocol or xterm’s
modifyOtherKeys
mode. Most terminals do not send it, so use
ctrl
or
meta
for bindings you want to work everywhere.
For example:
ctrl+k          Ctrl + K
shift+tab       Shift + Tab
meta+p          Option + P on macOS, Alt + P elsewhere
ctrl+shift+c    Multiple modifiers
​
Uppercase letters
A standalone uppercase letter implies Shift. For example,
K
is equivalent to
shift+k
. This is useful for vim-style bindings where uppercase and lowercase keys have different meanings.
Uppercase letters with modifiers (e.g.,
ctrl+K
) are treated as stylistic and do
not
imply Shift:
ctrl+K
is the same as
ctrl+k
.
​
Chords
Chords are sequences of keystrokes separated by spaces:
ctrl+k ctrl+s   Press Ctrl+K, release, then Ctrl+S
​
Special keys
escape
or
esc
- Escape key
enter
or
return
- Enter key
tab
- Tab key
space
- Space bar
up
,
down
,
left
,
right
- Arrow keys
backspace
,
delete
- Delete keys
​
Unbind default shortcuts
Set an action to
null
to unbind a default shortcut:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+s"
:
null
}
}
]
}
This also works for chord bindings. Unbinding every chord that shares a prefix frees that prefix for use as a single-key binding:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+x ctrl+k"
:
null
,
"ctrl+x ctrl+e"
:
null
,
"ctrl+x"
:
"chat:newline"
}
}
]
}
If you unbind some but not all chords on a prefix, pressing the prefix still enters chord-wait mode for the remaining bindings.
​
Reserved shortcuts
These shortcuts cannot be rebound:
Shortcut
Reason
Ctrl+C
Hardcoded interrupt/cancel
Ctrl+D
Hardcoded exit
Ctrl+M
Identical to Enter in terminals (both send CR)
Caps Lock
Not delivered to terminal applications
​
Terminal conflicts
Some shortcuts may conflict with terminal multiplexers:
Shortcut
Conflict
Ctrl+B
tmux prefix (press twice to send)
Ctrl+A
GNU screen prefix
Ctrl+Z
Unix process suspend (SIGTSTP)
​
Vim mode interaction
When vim mode is enabled via
/config
→ Editor mode, keybindings and vim mode operate independently:
Vim mode
handles input at the text input level (cursor movement, modes, motions)
Keybindings
handle actions at the component level (toggle todos, submit, etc.)
The Escape key in vim mode switches INSERT to NORMAL mode; it does not trigger
chat:cancel
Most Ctrl+key shortcuts pass through vim mode to the keybinding system
In vim NORMAL mode,
?
shows the help menu (vim behavior)
​
Validation
Claude Code validates your keybindings and shows warnings for:
Parse errors (invalid JSON or structure)
Invalid context names
Reserved shortcut conflicts
Terminal multiplexer conflicts
Duplicate bindings in the same context
Run
/doctor
to see any keybinding warnings.
Was this page helpful?
Yes
No
Customize status line
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/keybindings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize keyboard shortcuts
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize keyboard shortcuts
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Customizable keyboard shortcuts require Claude Code v2.1.18 or later. Check your version with
claude --version
.
Claude Code supports customizable keyboard shortcuts. Run
/keybindings
to create or open your configuration file at
~/.claude/keybindings.json
.
​
Configuration file
The keybindings configuration file is an object with a
bindings
array. Each block specifies a context and a map of keystrokes to actions.
Changes to the keybindings file are automatically detected and applied without restarting Claude Code.
Field
Description
$schema
Optional JSON Schema URL for editor autocompletion
$docs
Optional documentation URL
bindings
Array of binding blocks by context
This example binds
Ctrl+E
to open an external editor in the chat context, and unbinds
Ctrl+U
:
{
"$schema"
:
"https://www.schemastore.org/claude-code-keybindings.json"
,
"$docs"
:
"https://code.claude.com/docs/en/keybindings"
,
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+e"
:
"chat:externalEditor"
,
"ctrl+u"
:
null
}
}
]
}
​
Contexts
Each binding block specifies a
context
where the bindings apply:
Context
Description
Global
Applies everywhere in the app
Chat
Main chat input area
Autocomplete
Autocomplete menu is open
Settings
Settings menu
Confirmation
Permission and confirmation dialogs
Tabs
Tab navigation components
Help
Help menu is visible
Transcript
Transcript viewer
HistorySearch
History search mode (Ctrl+R)
Task
Background task is running
ThemePicker
Theme picker dialog
Attachments
Image attachment navigation in select dialogs
Footer
Footer indicator navigation (tasks, teams, diff)
MessageSelector
Rewind and summarize dialog message selection
DiffDialog
Diff viewer navigation
ModelPicker
Model picker effort level
Select
Generic select/list components
Plugin
Plugin dialog (browse, discover, manage)
Scroll
Conversation scrolling and text selection in fullscreen mode
Doctor
/doctor
diagnostics screen
​
Available actions
Actions follow a
namespace:action
format, such as
chat:submit
to send a message or
app:toggleTodos
to show the task list. Each context has specific actions available.
​
App actions
Actions available in the
Global
context:
Action
Default
Description
app:interrupt
Ctrl+C
Cancel current operation
app:exit
Ctrl+D
Exit Claude Code
app:redraw
(unbound)
Force terminal redraw
app:toggleTodos
Ctrl+T
Toggle task list visibility
app:toggleTranscript
Ctrl+O
Toggle verbose transcript
​
History actions
Actions for navigating command history:
Action
Default
Description
history:search
Ctrl+R
Open history search
history:previous
Up
Previous history item
history:next
Down
Next history item
​
Chat actions
Actions available in the
Chat
context:
Action
Default
Description
chat:cancel
Escape
Cancel current input
chat:clearInput
Ctrl+L
Force a full screen redraw, preserving input. In
fullscreen rendering
, press twice within two seconds to run
/clear
chat:clearScreen
Cmd+K
In
fullscreen rendering
, press twice within two seconds to run
/clear
chat:killAgents
Ctrl+X Ctrl+K
Kill all running
background subagents
in this session
chat:cycleMode
Shift+Tab*
Cycle permission modes
chat:modelPicker
Meta+P
Open model picker
chat:fastMode
Meta+O
Toggle fast mode
chat:thinkingToggle
Meta+T
Toggle extended thinking
chat:submit
Enter
Submit message
chat:newline
Ctrl+J
Insert a newline without submitting
chat:undo
Ctrl+_, Ctrl+Shift+-
Undo last action
chat:externalEditor
Ctrl+G, Ctrl+X Ctrl+E
Open in external editor
chat:stash
Ctrl+S
Stash current prompt
chat:imagePaste
Ctrl+V (Alt+V on Windows)
Paste image
*On Windows without VT mode (Node <24.2.0/<22.17.0, Bun <1.2.23), defaults to Meta+M.
​
Autocomplete actions
Actions available in the
Autocomplete
context:
Action
Default
Description
autocomplete:accept
Tab
Accept suggestion
autocomplete:dismiss
Escape
Dismiss menu
autocomplete:previous
Up
Previous suggestion
autocomplete:next
Down
Next suggestion
​
Confirmation actions
Actions available in the
Confirmation
context:
Action
Default
Description
confirm:yes
Y, Enter
Confirm action
confirm:no
N, Escape
Decline action
confirm:previous
Up
Previous option
confirm:next
Down
Next option
confirm:nextField
Tab
Next field
confirm:previousField
(unbound)
Previous field
confirm:toggle
Space
Toggle selection
confirm:cycleMode
Shift+Tab
Cycle permission modes
confirm:toggleExplanation
Ctrl+E
Toggle permission explanation
​
Permission actions
Actions available in the
Confirmation
context for permission dialogs:
Action
Default
Description
permission:toggleDebug
Ctrl+D
Toggle permission debug info
​
Transcript actions
Actions available in the
Transcript
context:
Action
Default
Description
transcript:toggleShowAll
Ctrl+E
Toggle show all content
transcript:exit
q, Ctrl+C, Escape
Exit transcript view
​
History search actions
Actions available in the
HistorySearch
context:
Action
Default
Description
historySearch:next
Ctrl+R
Next match
historySearch:accept
Escape, Tab
Accept selection
historySearch:cancel
Ctrl+C
Cancel search
historySearch:execute
Enter
Execute selected command
historySearch:cycleScope
Ctrl+S
Cycle scope: session, project, everywhere
​
Task actions
Actions available in the
Task
context:
Action
Default
Description
task:background
Ctrl+B
Background current task
​
Theme actions
Actions available in the
ThemePicker
context:
Action
Default
Description
theme:toggleSyntaxHighlighting
Ctrl+T
Toggle syntax highlighting
​
Help actions
Actions available in the
Help
context:
Action
Default
Description
help:dismiss
Escape
Close help menu
​
Tabs actions
Actions available in the
Tabs
context:
Action
Default
Description
tabs:next
Tab, Right
Next tab
tabs:previous
Shift+Tab, Left
Previous tab
​
Attachments actions
Actions available in the
Attachments
context:
Action
Default
Description
attachments:next
Right
Next attachment
attachments:previous
Left
Previous attachment
attachments:remove
Backspace, Delete
Remove selected attachment
attachments:exit
Down, Escape
Exit attachment navigation
​
Footer actions
Actions available in the
Footer
context:
Action
Default
Description
footer:next
Right
Next footer item
footer:previous
Left
Previous footer item
footer:up
Up
Navigate up in footer (deselects at top)
footer:down
Down
Navigate down in footer
footer:openSelected
Enter
Open selected footer item
footer:clearSelection
Escape
Clear footer selection
​
Message selector actions
Actions available in the
MessageSelector
context:
Action
Default
Description
messageSelector:up
Up, K, Ctrl+P
Move up in list
messageSelector:down
Down, J, Ctrl+N
Move down in list
messageSelector:top
Ctrl+Up, Shift+Up, Meta+Up, Shift+K
Jump to top
messageSelector:bottom
Ctrl+Down, Shift+Down, Meta+Down, Shift+J
Jump to bottom
messageSelector:select
Enter
Select message
​
Diff actions
Actions available in the
DiffDialog
context:
Action
Default
Description
diff:dismiss
Escape
Close diff viewer
diff:previousSource
Left
Previous diff source
diff:nextSource
Right
Next diff source
diff:previousFile
Up
Previous file in diff
diff:nextFile
Down
Next file in diff
diff:viewDetails
Enter
View diff details
diff:back
(context-specific)
Go back in diff viewer
​
Model picker actions
Actions available in the
ModelPicker
context:
Action
Default
Description
modelPicker:decreaseEffort
Left
Decrease effort level
modelPicker:increaseEffort
Right
Increase effort level
​
Select actions
Actions available in the
Select
context:
Action
Default
Description
select:next
Down, J, Ctrl+N
Next option
select:previous
Up, K, Ctrl+P
Previous option
select:accept
Enter
Accept selection
select:cancel
Escape
Cancel selection
​
Plugin actions
Actions available in the
Plugin
context:
Action
Default
Description
plugin:toggle
Space
Toggle plugin selection
plugin:install
I
Install selected plugins
plugin:favorite
F
Favorite the selected plugin so it sorts near the top of the Installed tab
​
Settings actions
Actions available in the
Settings
context:
Action
Default
Description
settings:search
/
Enter search mode
settings:retry
R
Retry loading usage data (on error)
settings:close
Enter
Save changes and close the config panel. Escape discards changes and closes
​
Doctor actions
Actions available in the
Doctor
context:
Action
Default
Description
doctor:fix
F
Send the diagnostics report to Claude to fix the reported issues. Only active when issues are found
​
Voice actions
Actions available in the
Chat
context when
voice dictation
is enabled:
Action
Default
Description
voice:pushToTalk
Space
Dictate a prompt. Hold or tap depending on
/voice
mode
​
Scroll actions
Actions available in the
Scroll
context when
fullscreen rendering
is enabled:
Action
Default
Description
scroll:lineUp
(unbound)
Scroll up one line. Mouse wheel scrolling triggers this action
scroll:lineDown
(unbound)
Scroll down one line. Mouse wheel scrolling triggers this action
scroll:pageUp
PageUp
Scroll up half the viewport height
scroll:pageDown
PageDown
Scroll down half the viewport height
scroll:top
Ctrl+Home
Jump to the start of the conversation
scroll:bottom
Ctrl+End
Jump to the latest message and re-enable auto-follow
scroll:halfPageUp
(unbound)
Scroll up half the viewport height. Same behavior as
scroll:pageUp
, provided for vi-style rebinds
scroll:halfPageDown
(unbound)
Scroll down half the viewport height. Same behavior as
scroll:pageDown
, provided for vi-style rebinds
scroll:fullPageUp
(unbound)
Scroll up the full viewport height
scroll:fullPageDown
(unbound)
Scroll down the full viewport height
selection:copy
Ctrl+Shift+C / Cmd+C
Copy the selected text to the clipboard
selection:clear
(unbound)
Clear the active text selection
selection:extendLeft
Shift+Left
Extend the active selection one column left
selection:extendRight
Shift+Right
Extend the active selection one column right
selection:extendUp
Shift+Up
Extend the active selection one row up. Scrolls the viewport when the selection reaches the top edge
selection:extendDown
Shift+Down
Extend the active selection one row down. Scrolls the viewport when the selection reaches the bottom edge
selection:extendLineStart
Shift+Home
Extend the active selection to the start of the line
selection:extendLineEnd
Shift+End
Extend the active selection to the end of the line
​
Keystroke syntax
​
Modifiers
Use modifier keys with the
+
separator:
ctrl
or
control
- Control key
shift
- Shift key
alt
,
opt
,
option
, or
meta
- Alt key on Windows and Linux, Option key on macOS
cmd
,
command
,
super
, or
win
- Command key on macOS, Windows key on Windows, Super key on Linux
The
cmd
group is only detected in terminals that report the Super modifier, such as those supporting the Kitty keyboard protocol or xterm’s
modifyOtherKeys
mode. Most terminals do not send it, so use
ctrl
or
meta
for bindings you want to work everywhere.
For example:
ctrl+k          Ctrl + K
shift+tab       Shift + Tab
meta+p          Option + P on macOS, Alt + P elsewhere
ctrl+shift+c    Multiple modifiers
​
Uppercase letters
A standalone uppercase letter implies Shift. For example,
K
is equivalent to
shift+k
. This is useful for vim-style bindings where uppercase and lowercase keys have different meanings.
Uppercase letters with modifiers (e.g.,
ctrl+K
) are treated as stylistic and do
not
imply Shift:
ctrl+K
is the same as
ctrl+k
.
​
Chords
Chords are sequences of keystrokes separated by spaces:
ctrl+k ctrl+s   Press Ctrl+K, release, then Ctrl+S
​
Special keys
escape
or
esc
- Escape key
enter
or
return
- Enter key
tab
- Tab key
space
- Space bar
up
,
down
,
left
,
right
- Arrow keys
backspace
,
delete
- Delete keys
​
Unbind default shortcuts
Set an action to
null
to unbind a default shortcut:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+s"
:
null
}
}
]
}
This also works for chord bindings. Unbinding every chord that shares a prefix frees that prefix for use as a single-key binding:
{
"bindings"
: [
{
"context"
:
"Chat"
,
"bindings"
: {
"ctrl+x ctrl+k"
:
null
,
"ctrl+x ctrl+e"
:
null
,
"ctrl+x"
:
"chat:newline"
}
}
]
}
If you unbind some but not all chords on a prefix, pressing the prefix still enters chord-wait mode for the remaining bindings.
​
Reserved shortcuts
These shortcuts cannot be rebound:
Shortcut
Reason
Ctrl+C
Hardcoded interrupt/cancel
Ctrl+D
Hardcoded exit
Ctrl+M
Identical to Enter in terminals (both send CR)
Caps Lock
Not delivered to terminal applications
​
Terminal conflicts
Some shortcuts may conflict with terminal multiplexers:
Shortcut
Conflict
Ctrl+B
tmux prefix (press twice to send)
Ctrl+A
GNU screen prefix
Ctrl+Z
Unix process suspend (SIGTSTP)
​
Vim mode interaction
When vim mode is enabled via
/config
→ Editor mode, keybindings and vim mode operate independently:
Vim mode
handles input at the text input level (cursor movement, modes, motions)
Keybindings
handle actions at the component level (toggle todos, submit, etc.)
The Escape key in vim mode switches INSERT to NORMAL mode; it does not trigger
chat:cancel
Most Ctrl+key shortcuts pass through vim mode to the keybinding system
In vim NORMAL mode,
?
shows the help menu (vim behavior)
​
Validation
Claude Code validates your keybindings and shows warnings for:
Parse errors (invalid JSON or structure)
Invalid context names
Reserved shortcut conflicts
Terminal multiplexer conflicts
Duplicate bindings in the same context
Run
/doctor
to see any keybinding warnings.
Was this page helpful?
Yes
No
Customize status line
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/keybindings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Run Claude Code programmatically</title>
  <link>https://code.claude.com/docs/en/headless</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/headless</guid>
  <pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run Claude Code programmatically
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run Claude Code programmatically
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
The
Agent SDK
gives you the same tools, agent loop, and context management that power Claude Code. It’s available as a CLI for scripts and CI/CD, or as
Python
and
TypeScript
packages for full programmatic control.
To run Claude Code in non-interactive mode, pass
-p
with your prompt and any
CLI options
:
claude
-p
"Find and fix the bug in auth.py"
--allowedTools
"Read,Edit,Bash"
This page covers using the Agent SDK via the CLI (
claude -p
). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the
full Agent SDK documentation
.
​
Basic usage
Add the
-p
(or
--print
) flag to any
claude
command to run it non-interactively. All
CLI options
work with
-p
, including:
--continue
for
continuing conversations
--allowedTools
for
auto-approving tools
--output-format
for
structured output
This example asks Claude a question about your codebase and prints the response:
claude
-p
"What does the auth module do?"
​
Start faster with bare mode
Add
--bare
to reduce startup time by skipping auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Without it,
claude -p
loads the same
context
an interactive session would, including anything configured in the working directory or
~/.claude
.
Bare mode is useful for CI and scripts where you need the same result on every machine. A hook in a teammate’s
~/.claude
or an MCP server in the project’s
.mcp.json
won’t run, because bare mode never reads them. Only flags you pass explicitly take effect.
This example runs a one-off summarize task in bare mode and pre-approves the Read tool so the call completes without a permission prompt:
claude
--bare
-p
"Summarize this file"
--allowedTools
"Read"
In bare mode Claude has access to the Bash, file read, and file edit tools. Pass any context you need with a flag:
To load
Use
System prompt additions
--append-system-prompt
,
--append-system-prompt-file
Settings
--settings <file-or-json>
MCP servers
--mcp-config <file-or-json>
Custom agents
--agents <json>
A plugin
--plugin-dir <path>
,
--plugin-url <url>
Bare mode skips OAuth and keychain reads. Anthropic authentication must come from
ANTHROPIC_API_KEY
or an
apiKeyHelper
in the JSON passed to
--settings
. Bedrock, Vertex, and Foundry use their usual provider credentials.
--bare
is the recommended mode for scripted and SDK calls, and will become the default for
-p
in a future release.
​
Examples
These examples highlight common CLI patterns. For CI and other scripted calls, add
--bare
so they don’t pick up whatever happens to be configured locally.
​
Pipe data through Claude
Non-interactive mode reads stdin, so you can pipe data in and redirect the response out like any other command-line tool.
This example pipes a build log into Claude and writes the explanation to a file:
cat
build-error.txt
|
claude
-p
'concisely explain the root cause of this build error'
>
output.txt
With
--output-format json
, the response payload includes
total_cost_usd
and a per-model cost breakdown, so scripted callers can track spend per invocation without consulting the
usage dashboard
.
As of Claude Code v2.1.128, piped stdin is capped at 10MB. If you exceed the cap, Claude Code exits with a clear error and a non-zero status. To work with larger inputs, write the content to a file and reference the file path in your prompt instead of piping it.
​
Add Claude to a build script
You can wrap a non-interactive call in a script to use Claude as a project-specific linter or reviewer.
This
package.json
script pipes the diff against
main
into Claude and asks it to report typos. Piping the diff means Claude doesn’t need Bash permission to read it, and the escaped double quotes keep the script portable to Windows:
{
"scripts"
: {
"lint:claude"
:
"git diff main | claude -p
\"
you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.
\"
"
}
}
​
Get structured output
Use
--output-format
to control how responses are returned:
text
(default): plain text output
json
: structured JSON with result, session ID, and metadata
stream-json
: newline-delimited JSON for real-time streaming
This example returns a project summary as JSON with session metadata, with the text result in the
result
field:
claude
-p
"Summarize this project"
--output-format
json
To get output conforming to a specific schema, use
--output-format json
with
--json-schema
and a
JSON Schema
definition. The response includes metadata about the request (session ID, usage, etc.) with the structured output in the
structured_output
field.
This example extracts function names and returns them as an array of strings:
claude
-p
"Extract the main function names from auth.py"
\
--output-format
json
\
--json-schema
'{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
Use a tool like
jq
to parse the response and extract specific fields:
# Extract the text result
claude
-p
"Summarize this project"
--output-format
json
|
jq
-r
'.result'
# Extract structured output
claude
-p
"Extract function names from auth.py"
\
--output-format
json
\
--json-schema
'{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
\
|
jq
'.structured_output'
​
Stream responses
Use
--output-format stream-json
with
--verbose
and
--include-partial-messages
to receive tokens as they’re generated. Each line is a JSON object representing an event:
claude
-p
"Explain recursion"
--output-format
stream-json
--verbose
--include-partial-messages
The following example uses
jq
to filter for text deltas and display just the streaming text. The
-r
flag outputs raw strings (no quotes) and
-j
joins without newlines so tokens stream continuously:
claude
-p
"Write a poem"
--output-format
stream-json
--verbose
--include-partial-messages
|
\
jq
-rj
'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
When an API request fails with a retryable error, Claude Code emits a
system/api_retry
event before retrying. You can use this to surface retry progress or implement custom backoff logic.
Field
Type
Description
type
"system"
message type
subtype
"api_retry"
identifies this as a retry event
attempt
integer
current attempt number, starting at 1
max_retries
integer
total retries permitted
retry_delay_ms
integer
milliseconds until the next attempt
error_status
integer or null
HTTP status code, or
null
for connection errors with no HTTP response
error
string
error category:
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
rate_limit
,
invalid_request
,
server_error
,
max_output_tokens
, or
unknown
uuid
string
unique event identifier
session_id
string
session the event belongs to
The
system/init
event reports session metadata including the model, tools, MCP servers, and loaded plugins. It is the first event in the stream unless
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, in which case
plugin_install
events precede it. Use the plugin fields to fail CI when a plugin did not load:
Field
Type
Description
plugins
array
plugins that loaded successfully, each with
name
and
path
plugin_errors
array
plugin load-time errors, each with
plugin
,
type
, and
message
. Includes unsatisfied dependency versions and
--plugin-dir
load failures such as a missing path or invalid archive. Affected plugins are demoted and absent from
plugins
. The key is omitted when there are no errors
When
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, Claude Code emits
system/plugin_install
events while marketplace plugins install before the first turn. Use these to surface install progress in your own UI.
Field
Type
Description
type
"system"
message type
subtype
"plugin_install"
identifies this as a plugin install event
status
"started"
,
"installed"
,
"failed"
, or
"completed"
started
and
completed
bracket the overall install;
installed
and
failed
report individual marketplaces
name
string, optional
marketplace name, present on
installed
and
failed
error
string, optional
failure message, present on
failed
uuid
string
unique event identifier
session_id
string
session the event belongs to
For programmatic streaming with callbacks and message objects, see
Stream responses in real-time
in the Agent SDK documentation.
​
Auto-approve tools
Use
--allowedTools
to let Claude use certain tools without prompting. This example runs a test suite and fixes failures, allowing Claude to execute Bash commands and read/edit files without asking for permission:
claude
-p
"Run the test suite and fix any failures"
\
--allowedTools
"Bash,Read,Edit"
To set a baseline for the whole session instead of listing individual tools, pass a
permission mode
.
dontAsk
denies anything not in your
permissions.allow
rules or the
read-only command set
, which is useful for locked-down CI runs.
acceptEdits
lets Claude write files without prompting and also auto-approves common filesystem commands such as
mkdir
,
touch
,
mv
, and
cp
. Other shell commands and network requests still need an
--allowedTools
entry or a
permissions.allow
rule, otherwise the run aborts when one is attempted:
claude
-p
"Apply the lint fixes"
--permission-mode
acceptEdits
​
Create a commit
This example reviews staged changes and creates a commit with an appropriate message:
claude
-p
"Look at my staged changes and create an appropriate commit"
\
--allowedTools
"Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
The
--allowedTools
flag uses
permission rule syntax
. The trailing
*
enables prefix matching, so
Bash(git diff *)
allows any command starting with
git diff
. The space before
*
is important: without it,
Bash(git diff*)
would also match
git diff-index
.
User-invoked
skills
like
/commit
and
built-in commands
are only available in interactive mode. In
-p
mode, describe the task you want to accomplish instead.
​
Customize the system prompt
Use
--append-system-prompt
to add instructions while keeping Claude Code’s default behavior. This example pipes a PR diff to Claude and instructs it to review for security vulnerabilities:
gh
pr
diff
"
$1
"
|
claude
-p
\
--append-system-prompt
"You are a security engineer. Review for vulnerabilities."
\
--output-format
json
See
system prompt flags
for more options including
--system-prompt
to fully replace the default prompt.
​
Continue conversations
Use
--continue
to continue the most recent conversation, or
--resume
with a session ID to continue a specific conversation. This example runs a review, then sends follow-up prompts:
# First request
claude
-p
"Review this codebase for performance issues"
# Continue the most recent conversation
claude
-p
"Now focus on the database queries"
--continue
claude
-p
"Generate a summary of all issues found"
--continue
If you’re running multiple conversations, capture the session ID to resume a specific one:
session_id
=
$(
claude
-p
"Start a review"
--output-format
json
|
jq
-r
'.session_id'
)
claude
-p
"Continue that review"
--resume
"
$session_id
"
​
Next steps
Agent SDK quickstart
: build your first agent with Python or TypeScript
CLI reference
: all CLI flags and options
GitHub Actions
: use the Agent SDK in GitHub workflows
GitLab CI/CD
: use the Agent SDK in GitLab pipelines
Was this page helpful?
Yes
No
Goals
Launch sessions from links
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/headless" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run Claude Code programmatically
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run Claude Code programmatically
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
The
Agent SDK
gives you the same tools, agent loop, and context management that power Claude Code. It’s available as a CLI for scripts and CI/CD, or as
Python
and
TypeScript
packages for full programmatic control.
To run Claude Code in non-interactive mode, pass
-p
with your prompt and any
CLI options
:
claude
-p
"Find and fix the bug in auth.py"
--allowedTools
"Read,Edit,Bash"
This page covers using the Agent SDK via the CLI (
claude -p
). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the
full Agent SDK documentation
.
​
Basic usage
Add the
-p
(or
--print
) flag to any
claude
command to run it non-interactively. All
CLI options
work with
-p
, including:
--continue
for
continuing conversations
--allowedTools
for
auto-approving tools
--output-format
for
structured output
This example asks Claude a question about your codebase and prints the response:
claude
-p
"What does the auth module do?"
​
Start faster with bare mode
Add
--bare
to reduce startup time by skipping auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Without it,
claude -p
loads the same
context
an interactive session would, including anything configured in the working directory or
~/.claude
.
Bare mode is useful for CI and scripts where you need the same result on every machine. A hook in a teammate’s
~/.claude
or an MCP server in the project’s
.mcp.json
won’t run, because bare mode never reads them. Only flags you pass explicitly take effect.
This example runs a one-off summarize task in bare mode and pre-approves the Read tool so the call completes without a permission prompt:
claude
--bare
-p
"Summarize this file"
--allowedTools
"Read"
In bare mode Claude has access to the Bash, file read, and file edit tools. Pass any context you need with a flag:
To load
Use
System prompt additions
--append-system-prompt
,
--append-system-prompt-file
Settings
--settings <file-or-json>
MCP servers
--mcp-config <file-or-json>
Custom agents
--agents <json>
A plugin
--plugin-dir <path>
,
--plugin-url <url>
Bare mode skips OAuth and keychain reads. Anthropic authentication must come from
ANTHROPIC_API_KEY
or an
apiKeyHelper
in the JSON passed to
--settings
. Bedrock, Vertex, and Foundry use their usual provider credentials.
--bare
is the recommended mode for scripted and SDK calls, and will become the default for
-p
in a future release.
​
Examples
These examples highlight common CLI patterns. For CI and other scripted calls, add
--bare
so they don’t pick up whatever happens to be configured locally.
​
Pipe data through Claude
Non-interactive mode reads stdin, so you can pipe data in and redirect the response out like any other command-line tool.
This example pipes a build log into Claude and writes the explanation to a file:
cat
build-error.txt
|
claude
-p
'concisely explain the root cause of this build error'
>
output.txt
With
--output-format json
, the response payload includes
total_cost_usd
and a per-model cost breakdown, so scripted callers can track spend per invocation without consulting the
usage dashboard
.
As of Claude Code v2.1.128, piped stdin is capped at 10MB. If you exceed the cap, Claude Code exits with a clear error and a non-zero status. To work with larger inputs, write the content to a file and reference the file path in your prompt instead of piping it.
​
Add Claude to a build script
You can wrap a non-interactive call in a script to use Claude as a project-specific linter or reviewer.
This
package.json
script pipes the diff against
main
into Claude and asks it to report typos. Piping the diff means Claude doesn’t need Bash permission to read it, and the escaped double quotes keep the script portable to Windows:
{
"scripts"
: {
"lint:claude"
:
"git diff main | claude -p
\"
you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.
\"
"
}
}
​
Get structured output
Use
--output-format
to control how responses are returned:
text
(default): plain text output
json
: structured JSON with result, session ID, and metadata
stream-json
: newline-delimited JSON for real-time streaming
This example returns a project summary as JSON with session metadata, with the text result in the
result
field:
claude
-p
"Summarize this project"
--output-format
json
To get output conforming to a specific schema, use
--output-format json
with
--json-schema
and a
JSON Schema
definition. The response includes metadata about the request (session ID, usage, etc.) with the structured output in the
structured_output
field.
This example extracts function names and returns them as an array of strings:
claude
-p
"Extract the main function names from auth.py"
\
--output-format
json
\
--json-schema
'{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
Use a tool like
jq
to parse the response and extract specific fields:
# Extract the text result
claude
-p
"Summarize this project"
--output-format
json
|
jq
-r
'.result'
# Extract structured output
claude
-p
"Extract function names from auth.py"
\
--output-format
json
\
--json-schema
'{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
\
|
jq
'.structured_output'
​
Stream responses
Use
--output-format stream-json
with
--verbose
and
--include-partial-messages
to receive tokens as they’re generated. Each line is a JSON object representing an event:
claude
-p
"Explain recursion"
--output-format
stream-json
--verbose
--include-partial-messages
The following example uses
jq
to filter for text deltas and display just the streaming text. The
-r
flag outputs raw strings (no quotes) and
-j
joins without newlines so tokens stream continuously:
claude
-p
"Write a poem"
--output-format
stream-json
--verbose
--include-partial-messages
|
\
jq
-rj
'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
When an API request fails with a retryable error, Claude Code emits a
system/api_retry
event before retrying. You can use this to surface retry progress or implement custom backoff logic.
Field
Type
Description
type
"system"
message type
subtype
"api_retry"
identifies this as a retry event
attempt
integer
current attempt number, starting at 1
max_retries
integer
total retries permitted
retry_delay_ms
integer
milliseconds until the next attempt
error_status
integer or null
HTTP status code, or
null
for connection errors with no HTTP response
error
string
error category:
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
rate_limit
,
invalid_request
,
server_error
,
max_output_tokens
, or
unknown
uuid
string
unique event identifier
session_id
string
session the event belongs to
The
system/init
event reports session metadata including the model, tools, MCP servers, and loaded plugins. It is the first event in the stream unless
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, in which case
plugin_install
events precede it. Use the plugin fields to fail CI when a plugin did not load:
Field
Type
Description
plugins
array
plugins that loaded successfully, each with
name
and
path
plugin_errors
array
plugin load-time errors, each with
plugin
,
type
, and
message
. Includes unsatisfied dependency versions and
--plugin-dir
load failures such as a missing path or invalid archive. Affected plugins are demoted and absent from
plugins
. The key is omitted when there are no errors
When
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, Claude Code emits
system/plugin_install
events while marketplace plugins install before the first turn. Use these to surface install progress in your own UI.
Field
Type
Description
type
"system"
message type
subtype
"plugin_install"
identifies this as a plugin install event
status
"started"
,
"installed"
,
"failed"
, or
"completed"
started
and
completed
bracket the overall install;
installed
and
failed
report individual marketplaces
name
string, optional
marketplace name, present on
installed
and
failed
error
string, optional
failure message, present on
failed
uuid
string
unique event identifier
session_id
string
session the event belongs to
For programmatic streaming with callbacks and message objects, see
Stream responses in real-time
in the Agent SDK documentation.
​
Auto-approve tools
Use
--allowedTools
to let Claude use certain tools without prompting. This example runs a test suite and fixes failures, allowing Claude to execute Bash commands and read/edit files without asking for permission:
claude
-p
"Run the test suite and fix any failures"
\
--allowedTools
"Bash,Read,Edit"
To set a baseline for the whole session instead of listing individual tools, pass a
permission mode
.
dontAsk
denies anything not in your
permissions.allow
rules or the
read-only command set
, which is useful for locked-down CI runs.
acceptEdits
lets Claude write files without prompting and also auto-approves common filesystem commands such as
mkdir
,
touch
,
mv
, and
cp
. Other shell commands and network requests still need an
--allowedTools
entry or a
permissions.allow
rule, otherwise the run aborts when one is attempted:
claude
-p
"Apply the lint fixes"
--permission-mode
acceptEdits
​
Create a commit
This example reviews staged changes and creates a commit with an appropriate message:
claude
-p
"Look at my staged changes and create an appropriate commit"
\
--allowedTools
"Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
The
--allowedTools
flag uses
permission rule syntax
. The trailing
*
enables prefix matching, so
Bash(git diff *)
allows any command starting with
git diff
. The space before
*
is important: without it,
Bash(git diff*)
would also match
git diff-index
.
User-invoked
skills
like
/commit
and
built-in commands
are only available in interactive mode. In
-p
mode, describe the task you want to accomplish instead.
​
Customize the system prompt
Use
--append-system-prompt
to add instructions while keeping Claude Code’s default behavior. This example pipes a PR diff to Claude and instructs it to review for security vulnerabilities:
gh
pr
diff
"
$1
"
|
claude
-p
\
--append-system-prompt
"You are a security engineer. Review for vulnerabilities."
\
--output-format
json
See
system prompt flags
for more options including
--system-prompt
to fully replace the default prompt.
​
Continue conversations
Use
--continue
to continue the most recent conversation, or
--resume
with a session ID to continue a specific conversation. This example runs a review, then sends follow-up prompts:
# First request
claude
-p
"Review this codebase for performance issues"
# Continue the most recent conversation
claude
-p
"Now focus on the database queries"
--continue
claude
-p
"Generate a summary of all issues found"
--continue
If you’re running multiple conversations, capture the session ID to resume a specific one:
session_id
=
$(
claude
-p
"Start a review"
--output-format
json
|
jq
-r
'.session_id'
)
claude
-p
"Continue that review"
--resume
"
$session_id
"
​
Next steps
Agent SDK quickstart
: build your first agent with Python or TypeScript
CLI reference
: all CLI flags and options
GitHub Actions
: use the Agent SDK in GitHub workflows
GitLab CI/CD
: use the Agent SDK in GitLab pipelines
Was this page helpful?
Yes
No
Goals
Launch sessions from links
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/headless" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Authentication</title>
  <link>https://code.claude.com/docs/en/authentication</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/authentication</guid>
  <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Authentication
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Authentication
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports multiple authentication methods depending on your setup. Individual users can log in with a Claude.ai account, while teams can use Claude for Teams or Enterprise, the Claude Console, or a cloud provider like Amazon Bedrock, Google Vertex AI, or Microsoft Foundry.
​
Log in to Claude Code
After
installing Claude Code
, run
claude
in your terminal. On first launch, Claude Code opens a browser window for you to log in.
If the browser doesn’t open automatically, press
c
to copy the login URL to your clipboard, then paste it into your browser.
If your browser shows a login code instead of redirecting back after you sign in, paste it into the terminal at the
Paste code here if prompted
prompt. This happens when the browser can’t reach Claude Code’s local callback server, which is common in WSL2, SSH sessions, and containers.
You can authenticate with any of these account types:
Claude Pro or Max subscription
: log in with your Claude.ai account. Subscribe at
claude.com/pricing
.
Claude for Teams or Enterprise
: log in with the Claude.ai account your team admin invited you to.
Claude Console
: log in with your Console credentials. Your admin must have
invited you
first.
Cloud providers
: if your organization uses
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
, set the required environment variables before running
claude
. No browser login is needed.
To log out and re-authenticate, type
/logout
at the Claude Code prompt.
If you’re having trouble logging in, see
authentication troubleshooting
.
​
Set up team authentication
For teams and organizations, you can configure Claude Code access in one of these ways:
Claude for Teams or Enterprise
, recommended for most teams
Claude Console
Amazon Bedrock
Google Vertex AI
Microsoft Foundry
​
Claude for Teams or Enterprise
Claude for Teams
and
Claude for Enterprise
provide the best experience for organizations using Claude Code. Team members get access to both Claude Code and Claude on the web with centralized billing and team management.
Claude for Teams
: self-service plan with collaboration features, admin tools, and billing management. Best for smaller teams.
Claude for Enterprise
: adds SSO, domain capture, role-based permissions, compliance API, and managed policy settings for organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.
1
Subscribe
Subscribe to
Claude for Teams
or contact sales for
Claude for Enterprise
.
2
Invite team members
Invite team members from the admin dashboard.
3
Install and log in
Team members install Claude Code and log in with their Claude.ai accounts.
​
Claude Console authentication
For organizations that prefer API-based billing, you can set up access through the Claude Console.
1
Create or use a Console account
Use your existing Claude Console account or create a new one.
2
Add users
You can add users through either method:
Bulk invite users from within the Console: Settings -> Members -> Invite
Set up SSO
3
Assign roles
When inviting users, assign one of:
Claude Code
role: users can only create Claude Code API keys
Developer
role: users can create any kind of API key
4
Users complete setup
Each invited user needs to:
Accept the Console invite
Check system requirements
Install Claude Code
Log in with Console account credentials
​
Cloud provider authentication
For teams using Amazon Bedrock, Google Vertex AI, or Microsoft Foundry:
1
Follow provider setup
Follow the
Bedrock docs
,
Vertex docs
, or
Microsoft Foundry docs
.
2
Distribute configuration
Distribute the environment variables and instructions for generating cloud credentials to your users. Read more about how to
manage configuration here
.
3
Install Claude Code
Users can
install Claude Code
.
​
Credential management
Claude Code securely manages your authentication credentials:
Storage location
:
On macOS, credentials are stored in the encrypted macOS Keychain.
On Linux, credentials are stored in
~/.claude/.credentials.json
with file mode
0600
.
On Windows, credentials are stored in
%USERPROFILE%\.claude\.credentials.json
and inherit the access controls of your user profile directory, which restricts the file to your user account by default.
If you’ve set the
CLAUDE_CONFIG_DIR
environment variable on Linux or Windows, the
.credentials.json
file lives under that directory instead.
Claude Code manages
.credentials.json
through
/login
and
/logout
. To route requests through a custom API endpoint, set the
ANTHROPIC_BASE_URL
environment variable instead.
Supported authentication types
: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, and Vertex Auth.
Custom credential scripts
: the
apiKeyHelper
setting can be configured to run a shell script that returns an API key.
Refresh intervals
: by default,
apiKeyHelper
is called after 5 minutes or on HTTP 401 response. Set
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
environment variable for custom refresh intervals.
Slow helper notice
: if
apiKeyHelper
takes longer than 10 seconds to return a key, Claude Code displays a warning notice in the prompt bar showing the elapsed time. If you see this notice regularly, check whether your credential script can be optimized.
apiKeyHelper
,
ANTHROPIC_API_KEY
, and
ANTHROPIC_AUTH_TOKEN
apply to terminal CLI sessions only. Claude Desktop and remote sessions use OAuth exclusively and do not call
apiKeyHelper
or read API key environment variables.
​
Authentication precedence
When multiple credentials are present, Claude Code chooses one in this order:
Cloud provider credentials, when
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_VERTEX
, or
CLAUDE_CODE_USE_FOUNDRY
is set. See
third-party integrations
for setup.
ANTHROPIC_AUTH_TOKEN
environment variable. Sent as the
Authorization: Bearer
header. Use this when routing through an
LLM gateway or proxy
that authenticates with bearer tokens rather than Anthropic API keys.
ANTHROPIC_API_KEY
environment variable. Sent as the
X-Api-Key
header. Use this for direct Anthropic API access with a key from the
Claude Console
. In interactive mode, you are prompted once to approve or decline the key, and your choice is remembered. To change it later, use the “Use custom API key” toggle in
/config
. In non-interactive mode (
-p
), the key is always used when present.
apiKeyHelper
script output. Use this for dynamic or rotating credentials, such as short-lived tokens fetched from a vault.
CLAUDE_CODE_OAUTH_TOKEN
environment variable. A long-lived OAuth token generated by
claude setup-token
. Use this for CI pipelines and scripts where browser login isn’t available.
Subscription OAuth credentials from
/login
. This is the default for Claude Pro, Max, Team, and Enterprise users.
If you have an active Claude subscription but also have
ANTHROPIC_API_KEY
set in your environment, the API key takes precedence once approved. This can cause authentication failures if the key belongs to a disabled or expired organization. Run
unset ANTHROPIC_API_KEY
to fall back to your subscription, and check
/status
to confirm which method is active.
Claude Code on the Web
always uses your subscription credentials.
ANTHROPIC_API_KEY
and
ANTHROPIC_AUTH_TOKEN
in the sandbox environment do not override them.
​
Generate a long-lived token
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
For CI pipelines, scripts, or other environments where interactive browser login isn’t available, generate a one-year OAuth token with
claude setup-token
:
claude
setup-token
The command walks you through OAuth authorization and prints a token to the terminal. It does not save the token anywhere; copy it and set it as the
CLAUDE_CODE_OAUTH_TOKEN
environment variable wherever you want to authenticate:
export
CLAUDE_CODE_OAUTH_TOKEN
=
your-token
This token authenticates with your Claude subscription and requires a Pro, Max, Team, or Enterprise plan. It is scoped to inference only and cannot establish
Remote Control
sessions.
Bare mode
does not read
CLAUDE_CODE_OAUTH_TOKEN
. If your script passes
--bare
, authenticate with
ANTHROPIC_API_KEY
or an
apiKeyHelper
instead.
Was this page helpful?
Yes
No
Advanced setup
Server-managed settings
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/authentication" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Authentication
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Authentication
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports multiple authentication methods depending on your setup. Individual users can log in with a Claude.ai account, while teams can use Claude for Teams or Enterprise, the Claude Console, or a cloud provider like Amazon Bedrock, Google Vertex AI, or Microsoft Foundry.
​
Log in to Claude Code
After
installing Claude Code
, run
claude
in your terminal. On first launch, Claude Code opens a browser window for you to log in.
If the browser doesn’t open automatically, press
c
to copy the login URL to your clipboard, then paste it into your browser.
If your browser shows a login code instead of redirecting back after you sign in, paste it into the terminal at the
Paste code here if prompted
prompt. This happens when the browser can’t reach Claude Code’s local callback server, which is common in WSL2, SSH sessions, and containers.
You can authenticate with any of these account types:
Claude Pro or Max subscription
: log in with your Claude.ai account. Subscribe at
claude.com/pricing
.
Claude for Teams or Enterprise
: log in with the Claude.ai account your team admin invited you to.
Claude Console
: log in with your Console credentials. Your admin must have
invited you
first.
Cloud providers
: if your organization uses
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
, set the required environment variables before running
claude
. No browser login is needed.
To log out and re-authenticate, type
/logout
at the Claude Code prompt.
If you’re having trouble logging in, see
authentication troubleshooting
.
​
Set up team authentication
For teams and organizations, you can configure Claude Code access in one of these ways:
Claude for Teams or Enterprise
, recommended for most teams
Claude Console
Amazon Bedrock
Google Vertex AI
Microsoft Foundry
​
Claude for Teams or Enterprise
Claude for Teams
and
Claude for Enterprise
provide the best experience for organizations using Claude Code. Team members get access to both Claude Code and Claude on the web with centralized billing and team management.
Claude for Teams
: self-service plan with collaboration features, admin tools, and billing management. Best for smaller teams.
Claude for Enterprise
: adds SSO, domain capture, role-based permissions, compliance API, and managed policy settings for organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.
1
Subscribe
Subscribe to
Claude for Teams
or contact sales for
Claude for Enterprise
.
2
Invite team members
Invite team members from the admin dashboard.
3
Install and log in
Team members install Claude Code and log in with their Claude.ai accounts.
​
Claude Console authentication
For organizations that prefer API-based billing, you can set up access through the Claude Console.
1
Create or use a Console account
Use your existing Claude Console account or create a new one.
2
Add users
You can add users through either method:
Bulk invite users from within the Console: Settings -> Members -> Invite
Set up SSO
3
Assign roles
When inviting users, assign one of:
Claude Code
role: users can only create Claude Code API keys
Developer
role: users can create any kind of API key
4
Users complete setup
Each invited user needs to:
Accept the Console invite
Check system requirements
Install Claude Code
Log in with Console account credentials
​
Cloud provider authentication
For teams using Amazon Bedrock, Google Vertex AI, or Microsoft Foundry:
1
Follow provider setup
Follow the
Bedrock docs
,
Vertex docs
, or
Microsoft Foundry docs
.
2
Distribute configuration
Distribute the environment variables and instructions for generating cloud credentials to your users. Read more about how to
manage configuration here
.
3
Install Claude Code
Users can
install Claude Code
.
​
Credential management
Claude Code securely manages your authentication credentials:
Storage location
:
On macOS, credentials are stored in the encrypted macOS Keychain.
On Linux, credentials are stored in
~/.claude/.credentials.json
with file mode
0600
.
On Windows, credentials are stored in
%USERPROFILE%\.claude\.credentials.json
and inherit the access controls of your user profile directory, which restricts the file to your user account by default.
If you’ve set the
CLAUDE_CONFIG_DIR
environment variable on Linux or Windows, the
.credentials.json
file lives under that directory instead.
Claude Code manages
.credentials.json
through
/login
and
/logout
. To route requests through a custom API endpoint, set the
ANTHROPIC_BASE_URL
environment variable instead.
Supported authentication types
: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, and Vertex Auth.
Custom credential scripts
: the
apiKeyHelper
setting can be configured to run a shell script that returns an API key.
Refresh intervals
: by default,
apiKeyHelper
is called after 5 minutes or on HTTP 401 response. Set
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
environment variable for custom refresh intervals.
Slow helper notice
: if
apiKeyHelper
takes longer than 10 seconds to return a key, Claude Code displays a warning notice in the prompt bar showing the elapsed time. If you see this notice regularly, check whether your credential script can be optimized.
apiKeyHelper
,
ANTHROPIC_API_KEY
, and
ANTHROPIC_AUTH_TOKEN
apply to terminal CLI sessions only. Claude Desktop and remote sessions use OAuth exclusively and do not call
apiKeyHelper
or read API key environment variables.
​
Authentication precedence
When multiple credentials are present, Claude Code chooses one in this order:
Cloud provider credentials, when
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_VERTEX
, or
CLAUDE_CODE_USE_FOUNDRY
is set. See
third-party integrations
for setup.
ANTHROPIC_AUTH_TOKEN
environment variable. Sent as the
Authorization: Bearer
header. Use this when routing through an
LLM gateway or proxy
that authenticates with bearer tokens rather than Anthropic API keys.
ANTHROPIC_API_KEY
environment variable. Sent as the
X-Api-Key
header. Use this for direct Anthropic API access with a key from the
Claude Console
. In interactive mode, you are prompted once to approve or decline the key, and your choice is remembered. To change it later, use the “Use custom API key” toggle in
/config
. In non-interactive mode (
-p
), the key is always used when present.
apiKeyHelper
script output. Use this for dynamic or rotating credentials, such as short-lived tokens fetched from a vault.
CLAUDE_CODE_OAUTH_TOKEN
environment variable. A long-lived OAuth token generated by
claude setup-token
. Use this for CI pipelines and scripts where browser login isn’t available.
Subscription OAuth credentials from
/login
. This is the default for Claude Pro, Max, Team, and Enterprise users.
If you have an active Claude subscription but also have
ANTHROPIC_API_KEY
set in your environment, the API key takes precedence once approved. This can cause authentication failures if the key belongs to a disabled or expired organization. Run
unset ANTHROPIC_API_KEY
to fall back to your subscription, and check
/status
to confirm which method is active.
Claude Code on the Web
always uses your subscription credentials.
ANTHROPIC_API_KEY
and
ANTHROPIC_AUTH_TOKEN
in the sandbox environment do not override them.
​
Generate a long-lived token
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
For CI pipelines, scripts, or other environments where interactive browser login isn’t available, generate a one-year OAuth token with
claude setup-token
:
claude
setup-token
The command walks you through OAuth authorization and prints a token to the terminal. It does not save the token anywhere; copy it and set it as the
CLAUDE_CODE_OAUTH_TOKEN
environment variable wherever you want to authenticate:
export
CLAUDE_CODE_OAUTH_TOKEN
=
your-token
This token authenticates with your Claude subscription and requires a Pro, Max, Team, or Enterprise plan. It is scoped to inference only and cannot establish
Remote Control
sessions.
Bare mode
does not read
CLAUDE_CODE_OAUTH_TOKEN
. If your script passes
--bare
, authenticate with
ANTHROPIC_API_KEY
or an
apiKeyHelper
instead.
Was this page helpful?
Yes
No
Advanced setup
Server-managed settings
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/authentication" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>LLM gateway configuration</title>
  <link>https://code.claude.com/docs/en/llm-gateway</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/llm-gateway</guid>
  <pubDate>Thu, 05 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
LLM gateway configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
LLM gateway configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
LLM gateways provide a centralized proxy layer between Claude Code and model providers, often providing:
Centralized authentication
- Single point for API key management
Usage tracking
- Monitor usage across teams and projects
Cost controls
- Implement budgets and rate limits
Audit logging
- Track all model interactions for compliance
Model routing
- Switch between providers without code changes
​
Gateway requirements
For an LLM gateway to work with Claude Code, it must meet the following requirements:
API format
The gateway must expose to clients at least one of the following API formats:
Anthropic Messages
:
/v1/messages
,
/v1/messages/count_tokens
Must forward request headers:
anthropic-beta
,
anthropic-version
Bedrock InvokeModel
:
/invoke
,
/invoke-with-response-stream
Must preserve request body fields:
anthropic_beta
,
anthropic_version
Vertex rawPredict
:
:rawPredict
,
:streamRawPredict
,
/count-tokens:rawPredict
Must forward request headers:
anthropic-beta
,
anthropic-version
Failure to forward headers or preserve body fields may result in reduced functionality or inability to use Claude Code features.
Claude Code determines which features to enable based on the API format. When using the Anthropic Messages format with Bedrock or Vertex, you may need to set environment variable
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
.
Request headers
Claude Code includes the following headers on API requests:
Header
Description
X-Claude-Code-Session-Id
A unique identifier for the current Claude Code session. Proxies can use this to aggregate all API requests from a single session without parsing the request body.
X-Claude-Code-Agent-Id
Identifier of the subagent or teammate that issued the request. Your proxy can use this to attribute API cost to individual parallel subagents within a session, without parsing the request body. Present only for requests made by an in-process subagent or teammate.
X-Claude-Code-Parent-Agent-Id
Identifier of the agent that spawned the agent making the request. Use this with
X-Claude-Code-Agent-Id
to attribute API costs across nested agents in your proxy. Present only when the requesting agent was itself spawned by another agent.
Both agent ID headers are ephemeral per-spawn identifiers, not persistent user or device IDs.
Claude Code also prepends a short attribution block to the system prompt containing the client version and a fingerprint derived from the conversation. The Anthropic API strips this block before processing, so it does not affect first-party prompt caching. If your gateway implements its own prompt cache keyed on the full request body, set
CLAUDE_CODE_ATTRIBUTION_HEADER=0
to omit it.
​
Configuration
​
Model selection
By default, Claude Code uses standard model names for the selected API format.
When
ANTHROPIC_BASE_URL
points at a gateway that exposes the Anthropic Messages format, Claude Code can query the gateway’s
/v1/models
endpoint at startup and add the returned models to the
/model
picker. Set
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
to enable this. Discovery is off by default so that gateways backed by a shared API key do not surface every model the key can access to every user. Each discovered entry is labeled “From gateway” and uses the
display_name
field from the response when one is provided. This requires Claude Code v2.1.129 or later.
Discovery applies only to the Anthropic Messages format. It does not run for Bedrock or Vertex pass-through endpoints, and it does not run when
ANTHROPIC_BASE_URL
is unset or points at
api.anthropic.com
.
The discovery request authenticates the same way as inference requests: it sends
ANTHROPIC_AUTH_TOKEN
as a bearer token, or
ANTHROPIC_API_KEY
as the
x-api-key
header when no auth token is set, along with any headers from
ANTHROPIC_CUSTOM_HEADERS
. Only models whose ID begins with
claude
or
anthropic
are added to the picker. Results are cached to
~/.claude/cache/gateway-models.json
and refreshed on each startup. If the request fails or the gateway does not implement
/v1/models
, the picker falls back to the cached list from the previous startup or to the built-in model list.
If your gateway uses model names that do not match the discovery filter, use the environment variables documented in
Model configuration
to add them manually.
​
LiteLLM configuration
LiteLLM PyPI versions 1.82.7 and 1.82.8 were compromised with credential-stealing malware. Do not install these versions. If you have already installed them:
Remove the package
Rotate all credentials on affected systems
Follow the remediation steps in
BerriAI/litellm#24518
LiteLLM is a third-party proxy service. Anthropic doesn’t endorse, maintain, or audit LiteLLM’s security or functionality. This guide is provided for informational purposes and may become outdated. Use at your own discretion.
​
Prerequisites
Claude Code updated to the latest version
LiteLLM Proxy Server deployed and accessible
Access to Claude models through your chosen provider
​
Basic LiteLLM setup
Configure Claude Code
:
​
Authentication methods
Static API key
Simplest method using a fixed API key:
# Set in environment
export
ANTHROPIC_AUTH_TOKEN
=
sk-litellm-static-key
# Or in Claude Code settings
{
"env"
:
{
"ANTHROPIC_AUTH_TOKEN"
:
"sk-litellm-static-key"
}
}
This value will be sent as the
Authorization
header.
Dynamic API key with helper
For rotating keys or per-user authentication:
Create an API key helper script:
#!/bin/bash
# ~/bin/get-litellm-key.sh
# Example: Fetch key from vault
vault
kv
get
-field=api_key
secret/litellm/claude-code
# Example: Generate JWT token
jwt
encode
\
--secret=
"${
JWT_SECRET
}"
\
--exp=
"+1h"
\
'{"user":"'
${
USER
}
'","team":"engineering"}'
Configure Claude Code settings to use the helper:
{
"apiKeyHelper"
:
"~/bin/get-litellm-key.sh"
}
Set token refresh interval:
# Refresh every hour (3600000 ms)
export
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
=
3600000
This value will be sent as
Authorization
and
X-Api-Key
headers. The
apiKeyHelper
has lower precedence than
ANTHROPIC_AUTH_TOKEN
or
ANTHROPIC_API_KEY
.
​
Unified endpoint (recommended)
Using LiteLLM’s
Anthropic format endpoint
:
export
ANTHROPIC_BASE_URL
=
https
://
litellm-server
:
4000
Benefits of the unified endpoint over pass-through endpoints:
Load balancing
Fallbacks
Consistent support for cost tracking and end-user tracking
​
Provider-specific pass-through endpoints (alternative)
Claude API through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_BASE_URL
=
https
://
litellm-server
:
4000
/
anthropic
Amazon Bedrock through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_BEDROCK_BASE_URL
=
https
://
litellm-server
:
4000
/
bedrock
export
CLAUDE_CODE_SKIP_BEDROCK_AUTH
=
1
export
CLAUDE_CODE_USE_BEDROCK
=
1
Google Vertex AI through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_VERTEX_BASE_URL
=
https
://
litellm-server
:
4000
/
vertex_ai
/
v1
export
ANTHROPIC_VERTEX_PROJECT_ID
=
your-gcp-project-id
export
CLAUDE_CODE_SKIP_VERTEX_AUTH
=
1
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
us-east5
Claude Platform on AWS through a gateway
Route to a gateway that forwards to the
Claude Platform on AWS
endpoint:
export
ANTHROPIC_AWS_BASE_URL
=
https
://
litellm-server
:
4000
/
anthropic-aws
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
=
1
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
For more detailed information, refer to the
LiteLLM documentation
.
​
Additional resources
LiteLLM documentation
Claude Code settings
Enterprise network configuration
Third-party integrations overview
Was this page helpful?
Yes
No
Network configuration
Development containers
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/llm-gateway" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
LLM gateway configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
LLM gateway configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
LLM gateways provide a centralized proxy layer between Claude Code and model providers, often providing:
Centralized authentication
- Single point for API key management
Usage tracking
- Monitor usage across teams and projects
Cost controls
- Implement budgets and rate limits
Audit logging
- Track all model interactions for compliance
Model routing
- Switch between providers without code changes
​
Gateway requirements
For an LLM gateway to work with Claude Code, it must meet the following requirements:
API format
The gateway must expose to clients at least one of the following API formats:
Anthropic Messages
:
/v1/messages
,
/v1/messages/count_tokens
Must forward request headers:
anthropic-beta
,
anthropic-version
Bedrock InvokeModel
:
/invoke
,
/invoke-with-response-stream
Must preserve request body fields:
anthropic_beta
,
anthropic_version
Vertex rawPredict
:
:rawPredict
,
:streamRawPredict
,
/count-tokens:rawPredict
Must forward request headers:
anthropic-beta
,
anthropic-version
Failure to forward headers or preserve body fields may result in reduced functionality or inability to use Claude Code features.
Claude Code determines which features to enable based on the API format. When using the Anthropic Messages format with Bedrock or Vertex, you may need to set environment variable
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
.
Request headers
Claude Code includes the following headers on API requests:
Header
Description
X-Claude-Code-Session-Id
A unique identifier for the current Claude Code session. Proxies can use this to aggregate all API requests from a single session without parsing the request body.
X-Claude-Code-Agent-Id
Identifier of the subagent or teammate that issued the request. Your proxy can use this to attribute API cost to individual parallel subagents within a session, without parsing the request body. Present only for requests made by an in-process subagent or teammate.
X-Claude-Code-Parent-Agent-Id
Identifier of the agent that spawned the agent making the request. Use this with
X-Claude-Code-Agent-Id
to attribute API costs across nested agents in your proxy. Present only when the requesting agent was itself spawned by another agent.
Both agent ID headers are ephemeral per-spawn identifiers, not persistent user or device IDs.
Claude Code also prepends a short attribution block to the system prompt containing the client version and a fingerprint derived from the conversation. The Anthropic API strips this block before processing, so it does not affect first-party prompt caching. If your gateway implements its own prompt cache keyed on the full request body, set
CLAUDE_CODE_ATTRIBUTION_HEADER=0
to omit it.
​
Configuration
​
Model selection
By default, Claude Code uses standard model names for the selected API format.
When
ANTHROPIC_BASE_URL
points at a gateway that exposes the Anthropic Messages format, Claude Code can query the gateway’s
/v1/models
endpoint at startup and add the returned models to the
/model
picker. Set
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
to enable this. Discovery is off by default so that gateways backed by a shared API key do not surface every model the key can access to every user. Each discovered entry is labeled “From gateway” and uses the
display_name
field from the response when one is provided. This requires Claude Code v2.1.129 or later.
Discovery applies only to the Anthropic Messages format. It does not run for Bedrock or Vertex pass-through endpoints, and it does not run when
ANTHROPIC_BASE_URL
is unset or points at
api.anthropic.com
.
The discovery request authenticates the same way as inference requests: it sends
ANTHROPIC_AUTH_TOKEN
as a bearer token, or
ANTHROPIC_API_KEY
as the
x-api-key
header when no auth token is set, along with any headers from
ANTHROPIC_CUSTOM_HEADERS
. Only models whose ID begins with
claude
or
anthropic
are added to the picker. Results are cached to
~/.claude/cache/gateway-models.json
and refreshed on each startup. If the request fails or the gateway does not implement
/v1/models
, the picker falls back to the cached list from the previous startup or to the built-in model list.
If your gateway uses model names that do not match the discovery filter, use the environment variables documented in
Model configuration
to add them manually.
​
LiteLLM configuration
LiteLLM PyPI versions 1.82.7 and 1.82.8 were compromised with credential-stealing malware. Do not install these versions. If you have already installed them:
Remove the package
Rotate all credentials on affected systems
Follow the remediation steps in
BerriAI/litellm#24518
LiteLLM is a third-party proxy service. Anthropic doesn’t endorse, maintain, or audit LiteLLM’s security or functionality. This guide is provided for informational purposes and may become outdated. Use at your own discretion.
​
Prerequisites
Claude Code updated to the latest version
LiteLLM Proxy Server deployed and accessible
Access to Claude models through your chosen provider
​
Basic LiteLLM setup
Configure Claude Code
:
​
Authentication methods
Static API key
Simplest method using a fixed API key:
# Set in environment
export
ANTHROPIC_AUTH_TOKEN
=
sk-litellm-static-key
# Or in Claude Code settings
{
"env"
:
{
"ANTHROPIC_AUTH_TOKEN"
:
"sk-litellm-static-key"
}
}
This value will be sent as the
Authorization
header.
Dynamic API key with helper
For rotating keys or per-user authentication:
Create an API key helper script:
#!/bin/bash
# ~/bin/get-litellm-key.sh
# Example: Fetch key from vault
vault
kv
get
-field=api_key
secret/litellm/claude-code
# Example: Generate JWT token
jwt
encode
\
--secret=
"${
JWT_SECRET
}"
\
--exp=
"+1h"
\
'{"user":"'
${
USER
}
'","team":"engineering"}'
Configure Claude Code settings to use the helper:
{
"apiKeyHelper"
:
"~/bin/get-litellm-key.sh"
}
Set token refresh interval:
# Refresh every hour (3600000 ms)
export
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
=
3600000
This value will be sent as
Authorization
and
X-Api-Key
headers. The
apiKeyHelper
has lower precedence than
ANTHROPIC_AUTH_TOKEN
or
ANTHROPIC_API_KEY
.
​
Unified endpoint (recommended)
Using LiteLLM’s
Anthropic format endpoint
:
export
ANTHROPIC_BASE_URL
=
https
://
litellm-server
:
4000
Benefits of the unified endpoint over pass-through endpoints:
Load balancing
Fallbacks
Consistent support for cost tracking and end-user tracking
​
Provider-specific pass-through endpoints (alternative)
Claude API through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_BASE_URL
=
https
://
litellm-server
:
4000
/
anthropic
Amazon Bedrock through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_BEDROCK_BASE_URL
=
https
://
litellm-server
:
4000
/
bedrock
export
CLAUDE_CODE_SKIP_BEDROCK_AUTH
=
1
export
CLAUDE_CODE_USE_BEDROCK
=
1
Google Vertex AI through LiteLLM
Using
pass-through endpoint
:
export
ANTHROPIC_VERTEX_BASE_URL
=
https
://
litellm-server
:
4000
/
vertex_ai
/
v1
export
ANTHROPIC_VERTEX_PROJECT_ID
=
your-gcp-project-id
export
CLAUDE_CODE_SKIP_VERTEX_AUTH
=
1
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
us-east5
Claude Platform on AWS through a gateway
Route to a gateway that forwards to the
Claude Platform on AWS
endpoint:
export
ANTHROPIC_AWS_BASE_URL
=
https
://
litellm-server
:
4000
/
anthropic-aws
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
=
1
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
For more detailed information, refer to the
LiteLLM documentation
.
​
Additional resources
LiteLLM documentation
Claude Code settings
Enterprise network configuration
Third-party integrations overview
Was this page helpful?
Yes
No
Network configuration
Development containers
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/llm-gateway" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code GitLab CI/CD</title>
  <link>https://code.claude.com/docs/en/gitlab-ci-cd</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/gitlab-ci-cd</guid>
  <pubDate>Tue, 03 Dec 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code GitLab CI/CD
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code GitLab CI/CD
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code for GitLab CI/CD is currently in beta. Features and functionality may evolve as we refine the experience.
This integration is maintained by GitLab. For support, see the following
GitLab issue
.
This integration is built on top of the
Claude Code CLI and Agent SDK
, enabling programmatic use of Claude in your CI/CD jobs and custom automation workflows.
​
Why use Claude Code with GitLab?
Instant MR creation
: Describe what you need, and Claude proposes a complete MR with changes and explanation
Automated implementation
: Turn issues into working code with a single command or mention
Project-aware
: Claude follows your
CLAUDE.md
guidelines and existing code patterns
Simple setup
: Add one job to
.gitlab-ci.yml
and a masked CI/CD variable
Enterprise-ready
: Choose Claude API, Amazon Bedrock, or Google Vertex AI to meet data residency and procurement needs
Secure by default
: Runs in your GitLab runners with your branch protection and approvals
​
How it works
Claude Code uses GitLab CI/CD to run AI tasks in isolated jobs and commit results back via MRs:
Event-driven orchestration
: GitLab listens for your chosen triggers (for example, a comment that mentions
@claude
in an issue, MR, or review thread). The job collects context from the thread and repository, builds prompts from that input, and runs Claude Code.
Provider abstraction
: Use the provider that fits your environment:
Claude API (SaaS)
Amazon Bedrock (IAM-based access, cross-region options)
Google Vertex AI (GCP-native, Workload Identity Federation)
Sandboxed execution
: Each interaction runs in a container with strict network and filesystem rules. Claude Code enforces workspace-scoped permissions to constrain writes. Every change flows through an MR so reviewers see the diff and approvals still apply.
Pick regional endpoints to reduce latency and meet data-sovereignty requirements while using existing cloud agreements.
​
What can Claude do?
Claude Code enables powerful CI/CD workflows that transform how you work with code:
Create and update MRs from issue descriptions or comments
Analyze performance regressions and propose optimizations
Implement features directly in a branch, then open an MR
Fix bugs and regressions identified by tests or comments
Respond to follow-up comments to iterate on requested changes
​
Setup
​
Quick setup
The fastest way to get started is to add a minimal job to your
.gitlab-ci.yml
and set your API key as a masked variable.
Add a masked CI/CD variable
Go to
Settings
→
CI/CD
→
Variables
Add
ANTHROPIC_API_KEY
(masked, protected as needed)
Add a Claude job to
.gitlab-ci.yml
stages
:
-
ai
claude
:
stage
:
ai
image
:
node:24-alpine3.21
# Adjust rules to fit how you want to trigger the job:
# - manual runs
# - merge request events
# - web/API triggers when a comment contains '@claude'
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
-
if
:
'$CI_PIPELINE_SOURCE == "merge_request_event"'
variables
:
GIT_STRATEGY
:
fetch
before_script
:
-
apk update
-
apk add --no-cache git curl bash
-
curl -fsSL https://claude.ai/install.sh | bash
script
:
# Optional: start a GitLab MCP server if your setup provides one
-
/bin/gitlab-mcp-server || true
# Use AI_FLOW_* variables when invoking via web/API triggers with context payloads
-
echo "$AI_FLOW_INPUT for $AI_FLOW_CONTEXT on $AI_FLOW_EVENT"
-
>
claude
-p "${AI_FLOW_INPUT:-'Review this MR and implement the requested changes'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
After adding the job and your
ANTHROPIC_API_KEY
variable, test by running the job manually from
CI/CD
→
Pipelines
, or trigger it from an MR to let Claude propose updates in a branch and open an MR if needed.
To run on Amazon Bedrock or Google Vertex AI instead of the Claude API, see the
Using with Amazon Bedrock & Google Vertex AI
section below for authentication and environment setup.
​
Manual setup (recommended for production)
If you prefer a more controlled setup or need enterprise providers:
Configure provider access
:
Claude API
: Create and store
ANTHROPIC_API_KEY
as a masked CI/CD variable
Amazon Bedrock
:
Configure GitLab
→
AWS OIDC
and create an IAM role for Bedrock
Google Vertex AI
:
Configure Workload Identity Federation for GitLab
→
GCP
Add project credentials for GitLab API operations
:
Use
CI_JOB_TOKEN
by default, or create a Project Access Token with
api
scope
Store as
GITLAB_ACCESS_TOKEN
(masked) if using a PAT
Add the Claude job to
.gitlab-ci.yml
(see examples below)
(Optional) Enable mention-driven triggers
:
Add a project webhook for “Comments (notes)” to your event listener (if you use one)
Have the listener call the pipeline trigger API with variables like
AI_FLOW_INPUT
and
AI_FLOW_CONTEXT
when a comment contains
@claude
​
Example use cases
​
Turn issues into MRs
In an issue comment:
@claude implement this feature based on the issue description
Claude analyzes the issue and codebase, writes changes in a branch, and opens an MR for review.
​
Get implementation help
In an MR discussion:
@claude suggest a concrete approach to cache the results of this API call
Claude proposes changes, adds code with appropriate caching, and updates the MR.
​
Fix bugs quickly
In an issue or MR comment:
@claude fix the TypeError in the user dashboard component
Claude locates the bug, implements a fix, and updates the branch or opens a new MR.
​
Using with Amazon Bedrock & Google Vertex AI
For enterprise environments, you can run Claude Code entirely on your cloud infrastructure with the same developer experience.
Amazon Bedrock
Google Vertex AI
​
Prerequisites
Before setting up Claude Code with Amazon Bedrock, you need:
An AWS account with Amazon Bedrock access to the desired Claude models
GitLab configured as an OIDC identity provider in AWS IAM
An IAM role with Bedrock permissions and a trust policy restricted to your GitLab project/refs
GitLab CI/CD variables for role assumption:
AWS_ROLE_TO_ASSUME
(role ARN)
AWS_REGION
(Bedrock region)
​
Setup instructions
Configure AWS to allow GitLab CI jobs to assume an IAM role via OIDC (no static keys).
Required setup:
Enable Amazon Bedrock and request access to your target Claude models
Create an IAM OIDC provider for GitLab if not already present
Create an IAM role trusted by the GitLab OIDC provider, restricted to your project and protected refs
Attach least-privilege permissions for Bedrock invoke APIs
Required values to store in CI/CD variables:
AWS_ROLE_TO_ASSUME
AWS_REGION
Add variables in Settings → CI/CD → Variables:
# For Amazon Bedrock:
-
AWS_ROLE_TO_ASSUME
-
AWS_REGION
Use the Amazon Bedrock job example above to exchange the GitLab job token for temporary AWS credentials at runtime.
​
Prerequisites
Before setting up Claude Code with Google Vertex AI, you need:
A Google Cloud project with:
Vertex AI API enabled
Workload Identity Federation configured to trust GitLab OIDC
A dedicated service account with only the required Vertex AI roles
GitLab CI/CD variables for WIF:
GCP_WORKLOAD_IDENTITY_PROVIDER
(full resource name)
GCP_SERVICE_ACCOUNT
(service account email)
​
Setup instructions
Configure Google Cloud to allow GitLab CI jobs to impersonate a service account via Workload Identity Federation.
Required setup:
Enable IAM Credentials API, STS API, and Vertex AI API
Create a Workload Identity Pool and provider for GitLab OIDC
Create a dedicated service account with Vertex AI roles
Grant the WIF principal permission to impersonate the service account
Required values to store in CI/CD variables:
GCP_WORKLOAD_IDENTITY_PROVIDER
GCP_SERVICE_ACCOUNT
Add variables in Settings → CI/CD → Variables:
# For Google Vertex AI:
-
GCP_WORKLOAD_IDENTITY_PROVIDER
-
GCP_SERVICE_ACCOUNT
-
CLOUD_ML_REGION (for example, us-east5)
Use the Google Vertex AI job example above to authenticate without storing keys.
​
Configuration examples
Below are ready-to-use snippets you can adapt to your pipeline.
​
Basic .gitlab-ci.yml (Claude API)
stages
:
-
ai
claude
:
stage
:
ai
image
:
node:24-alpine3.21
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
-
if
:
'$CI_PIPELINE_SOURCE == "merge_request_event"'
variables
:
GIT_STRATEGY
:
fetch
before_script
:
-
apk update
-
apk add --no-cache git curl bash
-
curl -fsSL https://claude.ai/install.sh | bash
script
:
-
/bin/gitlab-mcp-server || true
-
>
claude
-p "${AI_FLOW_INPUT:-'Summarize recent changes and suggest improvements'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
# Claude Code will use ANTHROPIC_API_KEY from CI/CD variables
​
Amazon Bedrock job example (OIDC)
Prerequisites:
Amazon Bedrock enabled with access to your chosen Claude model(s)
GitLab OIDC configured in AWS with a role that trusts your GitLab project and refs
IAM role with Bedrock permissions (least privilege recommended)
Required CI/CD variables:
AWS_ROLE_TO_ASSUME
: ARN of the IAM role for Bedrock access
AWS_REGION
: Bedrock region (for example,
us-west-2
)
claude-bedrock
:
stage
:
ai
image
:
node:24-alpine3.21
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
before_script
:
-
apk add --no-cache bash curl jq git python3 py3-pip
-
pip install --no-cache-dir awscli
-
curl -fsSL https://claude.ai/install.sh | bash
# Exchange GitLab OIDC token for AWS credentials
-
export AWS_WEB_IDENTITY_TOKEN_FILE="${CI_JOB_JWT_FILE:-/tmp/oidc_token}"
-
if [ -n "${CI_JOB_JWT_V2}" ]; then printf "%s" "$CI_JOB_JWT_V2" > "$AWS_WEB_IDENTITY_TOKEN_FILE"; fi
-
>
aws sts assume-role-with-web-identity
--role-arn "$AWS_ROLE_TO_ASSUME"
--role-session-name "gitlab-claude-$(date +%s)"
--web-identity-token "file://$AWS_WEB_IDENTITY_TOKEN_FILE"
--duration-seconds 3600 > /tmp/aws_creds.json
-
export AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId /tmp/aws_creds.json)"
-
export AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey /tmp/aws_creds.json)"
-
export AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken /tmp/aws_creds.json)"
script
:
-
/bin/gitlab-mcp-server || true
-
>
claude
-p "${AI_FLOW_INPUT:-'Implement the requested changes and open an MR'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
variables
:
AWS_REGION
:
"us-west-2"
Model IDs for Bedrock include region-specific prefixes (for example,
us.anthropic.claude-sonnet-4-6
). Pass the desired model via your job configuration or prompt if your workflow supports it.
​
Google Vertex AI job example (Workload Identity Federation)
Prerequisites:
Vertex AI API enabled in your GCP project
Workload Identity Federation configured to trust GitLab OIDC
A service account with Vertex AI permissions
Required CI/CD variables:
GCP_WORKLOAD_IDENTITY_PROVIDER
: Full provider resource name
GCP_SERVICE_ACCOUNT
: Service account email
CLOUD_ML_REGION
: Vertex region (for example,
us-east5
)
claude-vertex
:
stage
:
ai
image
:
gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
before_script
:
-
apt-get update && apt-get install -y git && apt-get clean
-
curl -fsSL https://claude.ai/install.sh | bash
# Authenticate to Google Cloud via WIF (no downloaded keys)
-
>
gcloud auth login --cred-file=<(cat <<EOF
{
"type": "external_account",
"audience": "${GCP_WORKLOAD_IDENTITY_PROVIDER}",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${GCP_SERVICE_ACCOUNT}:generateAccessToken",
"token_url": "https://sts.googleapis.com/v1/token"
}
EOF
)
-
gcloud config set project "$(gcloud projects list --format='value(projectId)' --filter="name:${CI_PROJECT_NAMESPACE}" | head -n1)" || true
script
:
-
/bin/gitlab-mcp-server || true
-
>
CLOUD_ML_REGION="${CLOUD_ML_REGION:-us-east5}"
claude
-p "${AI_FLOW_INPUT:-'Review and update code as requested'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
variables
:
CLOUD_ML_REGION
:
"us-east5"
With Workload Identity Federation, you do not need to store service account keys. Use repository-specific trust conditions and least-privilege service accounts.
​
Best practices
​
CLAUDE.md configuration
Create a
CLAUDE.md
file at the repository root to define coding standards, review criteria, and project-specific rules. Claude reads this file during runs and follows your conventions when proposing changes.
​
Security considerations
Never commit API keys or cloud credentials to your repository
. Always use GitLab CI/CD variables:
Add
ANTHROPIC_API_KEY
as a masked variable (and protect it if needed)
Use provider-specific OIDC where possible (no long-lived keys)
Limit job permissions and network egress
Review Claude’s MRs like any other contributor
​
Optimizing performance
Keep
CLAUDE.md
focused and concise
Provide clear issue/MR descriptions to reduce iterations
Configure sensible job timeouts to avoid runaway runs
Cache npm and package installs in runners where possible
​
CI costs
When using Claude Code with GitLab CI/CD, be aware of associated costs:
GitLab Runner time
:
Claude runs on your GitLab runners and consumes compute minutes
See your GitLab plan’s runner billing for details
API costs
:
Each Claude interaction consumes tokens based on prompt and response size
Token usage varies by task complexity and codebase size
See
Anthropic pricing
for details
Cost optimization tips
:
Use specific
@claude
commands to reduce unnecessary turns
Set appropriate
max_turns
and job timeout values
Limit concurrency to control parallel runs
​
Security and governance
Each job runs in an isolated container with restricted network access
Claude’s changes flow through MRs so reviewers see every diff
Branch protection and approval rules apply to AI-generated code
Claude Code uses workspace-scoped permissions to constrain writes
Costs remain under your control because you bring your own provider credentials
​
Troubleshooting
​
Claude not responding to @claude commands
Verify your pipeline is being triggered (manually, MR event, or via a note event listener/webhook)
Ensure CI/CD variables (
ANTHROPIC_API_KEY
or cloud provider settings) are present and unmasked
Check that the comment contains
@claude
(not
/claude
) and that your mention trigger is configured
​
Job can’t write comments or open MRs
Ensure
CI_JOB_TOKEN
has sufficient permissions for the project, or use a Project Access Token with
api
scope
Check the
mcp__gitlab
tool is enabled in
--allowedTools
Confirm the job runs in the context of the MR or has enough context via
AI_FLOW_*
variables
​
Authentication errors
For Claude API
: Confirm
ANTHROPIC_API_KEY
is valid and unexpired
For Bedrock/Vertex
: Verify OIDC/WIF configuration, role impersonation, and secret names; confirm region and model availability
​
Advanced configuration
​
Common parameters and variables
Claude Code supports these commonly used inputs:
prompt
/
prompt_file
: Provide instructions inline (
-p
) or via a file
max_turns
: Limit the number of back-and-forth iterations
timeout_minutes
: Limit total execution time
ANTHROPIC_API_KEY
: Required for the Claude API (not used for Bedrock/Vertex)
Provider-specific environment:
AWS_REGION
, project/region vars for Vertex
Exact flags and parameters may vary by version of
@anthropic-ai/claude-code
. Run
claude --help
in your job to see supported options.
​
Customizing Claude’s behavior
You can guide Claude in two primary ways:
CLAUDE.md
: Define coding standards, security requirements, and project conventions. Claude reads this during runs and follows your rules.
Custom prompts
: Pass task-specific instructions via
prompt
/
prompt_file
in the job. Use different prompts for different jobs (for example, review, implement, refactor).
Was this page helpful?
Yes
No
GitHub Enterprise Server
Claude Code in Slack
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/gitlab-ci-cd" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code GitLab CI/CD
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code GitLab CI/CD
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code for GitLab CI/CD is currently in beta. Features and functionality may evolve as we refine the experience.
This integration is maintained by GitLab. For support, see the following
GitLab issue
.
This integration is built on top of the
Claude Code CLI and Agent SDK
, enabling programmatic use of Claude in your CI/CD jobs and custom automation workflows.
​
Why use Claude Code with GitLab?
Instant MR creation
: Describe what you need, and Claude proposes a complete MR with changes and explanation
Automated implementation
: Turn issues into working code with a single command or mention
Project-aware
: Claude follows your
CLAUDE.md
guidelines and existing code patterns
Simple setup
: Add one job to
.gitlab-ci.yml
and a masked CI/CD variable
Enterprise-ready
: Choose Claude API, Amazon Bedrock, or Google Vertex AI to meet data residency and procurement needs
Secure by default
: Runs in your GitLab runners with your branch protection and approvals
​
How it works
Claude Code uses GitLab CI/CD to run AI tasks in isolated jobs and commit results back via MRs:
Event-driven orchestration
: GitLab listens for your chosen triggers (for example, a comment that mentions
@claude
in an issue, MR, or review thread). The job collects context from the thread and repository, builds prompts from that input, and runs Claude Code.
Provider abstraction
: Use the provider that fits your environment:
Claude API (SaaS)
Amazon Bedrock (IAM-based access, cross-region options)
Google Vertex AI (GCP-native, Workload Identity Federation)
Sandboxed execution
: Each interaction runs in a container with strict network and filesystem rules. Claude Code enforces workspace-scoped permissions to constrain writes. Every change flows through an MR so reviewers see the diff and approvals still apply.
Pick regional endpoints to reduce latency and meet data-sovereignty requirements while using existing cloud agreements.
​
What can Claude do?
Claude Code enables powerful CI/CD workflows that transform how you work with code:
Create and update MRs from issue descriptions or comments
Analyze performance regressions and propose optimizations
Implement features directly in a branch, then open an MR
Fix bugs and regressions identified by tests or comments
Respond to follow-up comments to iterate on requested changes
​
Setup
​
Quick setup
The fastest way to get started is to add a minimal job to your
.gitlab-ci.yml
and set your API key as a masked variable.
Add a masked CI/CD variable
Go to
Settings
→
CI/CD
→
Variables
Add
ANTHROPIC_API_KEY
(masked, protected as needed)
Add a Claude job to
.gitlab-ci.yml
stages
:
-
ai
claude
:
stage
:
ai
image
:
node:24-alpine3.21
# Adjust rules to fit how you want to trigger the job:
# - manual runs
# - merge request events
# - web/API triggers when a comment contains '@claude'
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
-
if
:
'$CI_PIPELINE_SOURCE == "merge_request_event"'
variables
:
GIT_STRATEGY
:
fetch
before_script
:
-
apk update
-
apk add --no-cache git curl bash
-
curl -fsSL https://claude.ai/install.sh | bash
script
:
# Optional: start a GitLab MCP server if your setup provides one
-
/bin/gitlab-mcp-server || true
# Use AI_FLOW_* variables when invoking via web/API triggers with context payloads
-
echo "$AI_FLOW_INPUT for $AI_FLOW_CONTEXT on $AI_FLOW_EVENT"
-
>
claude
-p "${AI_FLOW_INPUT:-'Review this MR and implement the requested changes'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
After adding the job and your
ANTHROPIC_API_KEY
variable, test by running the job manually from
CI/CD
→
Pipelines
, or trigger it from an MR to let Claude propose updates in a branch and open an MR if needed.
To run on Amazon Bedrock or Google Vertex AI instead of the Claude API, see the
Using with Amazon Bedrock & Google Vertex AI
section below for authentication and environment setup.
​
Manual setup (recommended for production)
If you prefer a more controlled setup or need enterprise providers:
Configure provider access
:
Claude API
: Create and store
ANTHROPIC_API_KEY
as a masked CI/CD variable
Amazon Bedrock
:
Configure GitLab
→
AWS OIDC
and create an IAM role for Bedrock
Google Vertex AI
:
Configure Workload Identity Federation for GitLab
→
GCP
Add project credentials for GitLab API operations
:
Use
CI_JOB_TOKEN
by default, or create a Project Access Token with
api
scope
Store as
GITLAB_ACCESS_TOKEN
(masked) if using a PAT
Add the Claude job to
.gitlab-ci.yml
(see examples below)
(Optional) Enable mention-driven triggers
:
Add a project webhook for “Comments (notes)” to your event listener (if you use one)
Have the listener call the pipeline trigger API with variables like
AI_FLOW_INPUT
and
AI_FLOW_CONTEXT
when a comment contains
@claude
​
Example use cases
​
Turn issues into MRs
In an issue comment:
@claude implement this feature based on the issue description
Claude analyzes the issue and codebase, writes changes in a branch, and opens an MR for review.
​
Get implementation help
In an MR discussion:
@claude suggest a concrete approach to cache the results of this API call
Claude proposes changes, adds code with appropriate caching, and updates the MR.
​
Fix bugs quickly
In an issue or MR comment:
@claude fix the TypeError in the user dashboard component
Claude locates the bug, implements a fix, and updates the branch or opens a new MR.
​
Using with Amazon Bedrock & Google Vertex AI
For enterprise environments, you can run Claude Code entirely on your cloud infrastructure with the same developer experience.
Amazon Bedrock
Google Vertex AI
​
Prerequisites
Before setting up Claude Code with Amazon Bedrock, you need:
An AWS account with Amazon Bedrock access to the desired Claude models
GitLab configured as an OIDC identity provider in AWS IAM
An IAM role with Bedrock permissions and a trust policy restricted to your GitLab project/refs
GitLab CI/CD variables for role assumption:
AWS_ROLE_TO_ASSUME
(role ARN)
AWS_REGION
(Bedrock region)
​
Setup instructions
Configure AWS to allow GitLab CI jobs to assume an IAM role via OIDC (no static keys).
Required setup:
Enable Amazon Bedrock and request access to your target Claude models
Create an IAM OIDC provider for GitLab if not already present
Create an IAM role trusted by the GitLab OIDC provider, restricted to your project and protected refs
Attach least-privilege permissions for Bedrock invoke APIs
Required values to store in CI/CD variables:
AWS_ROLE_TO_ASSUME
AWS_REGION
Add variables in Settings → CI/CD → Variables:
# For Amazon Bedrock:
-
AWS_ROLE_TO_ASSUME
-
AWS_REGION
Use the Amazon Bedrock job example above to exchange the GitLab job token for temporary AWS credentials at runtime.
​
Prerequisites
Before setting up Claude Code with Google Vertex AI, you need:
A Google Cloud project with:
Vertex AI API enabled
Workload Identity Federation configured to trust GitLab OIDC
A dedicated service account with only the required Vertex AI roles
GitLab CI/CD variables for WIF:
GCP_WORKLOAD_IDENTITY_PROVIDER
(full resource name)
GCP_SERVICE_ACCOUNT
(service account email)
​
Setup instructions
Configure Google Cloud to allow GitLab CI jobs to impersonate a service account via Workload Identity Federation.
Required setup:
Enable IAM Credentials API, STS API, and Vertex AI API
Create a Workload Identity Pool and provider for GitLab OIDC
Create a dedicated service account with Vertex AI roles
Grant the WIF principal permission to impersonate the service account
Required values to store in CI/CD variables:
GCP_WORKLOAD_IDENTITY_PROVIDER
GCP_SERVICE_ACCOUNT
Add variables in Settings → CI/CD → Variables:
# For Google Vertex AI:
-
GCP_WORKLOAD_IDENTITY_PROVIDER
-
GCP_SERVICE_ACCOUNT
-
CLOUD_ML_REGION (for example, us-east5)
Use the Google Vertex AI job example above to authenticate without storing keys.
​
Configuration examples
Below are ready-to-use snippets you can adapt to your pipeline.
​
Basic .gitlab-ci.yml (Claude API)
stages
:
-
ai
claude
:
stage
:
ai
image
:
node:24-alpine3.21
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
-
if
:
'$CI_PIPELINE_SOURCE == "merge_request_event"'
variables
:
GIT_STRATEGY
:
fetch
before_script
:
-
apk update
-
apk add --no-cache git curl bash
-
curl -fsSL https://claude.ai/install.sh | bash
script
:
-
/bin/gitlab-mcp-server || true
-
>
claude
-p "${AI_FLOW_INPUT:-'Summarize recent changes and suggest improvements'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
# Claude Code will use ANTHROPIC_API_KEY from CI/CD variables
​
Amazon Bedrock job example (OIDC)
Prerequisites:
Amazon Bedrock enabled with access to your chosen Claude model(s)
GitLab OIDC configured in AWS with a role that trusts your GitLab project and refs
IAM role with Bedrock permissions (least privilege recommended)
Required CI/CD variables:
AWS_ROLE_TO_ASSUME
: ARN of the IAM role for Bedrock access
AWS_REGION
: Bedrock region (for example,
us-west-2
)
claude-bedrock
:
stage
:
ai
image
:
node:24-alpine3.21
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
before_script
:
-
apk add --no-cache bash curl jq git python3 py3-pip
-
pip install --no-cache-dir awscli
-
curl -fsSL https://claude.ai/install.sh | bash
# Exchange GitLab OIDC token for AWS credentials
-
export AWS_WEB_IDENTITY_TOKEN_FILE="${CI_JOB_JWT_FILE:-/tmp/oidc_token}"
-
if [ -n "${CI_JOB_JWT_V2}" ]; then printf "%s" "$CI_JOB_JWT_V2" > "$AWS_WEB_IDENTITY_TOKEN_FILE"; fi
-
>
aws sts assume-role-with-web-identity
--role-arn "$AWS_ROLE_TO_ASSUME"
--role-session-name "gitlab-claude-$(date +%s)"
--web-identity-token "file://$AWS_WEB_IDENTITY_TOKEN_FILE"
--duration-seconds 3600 > /tmp/aws_creds.json
-
export AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId /tmp/aws_creds.json)"
-
export AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey /tmp/aws_creds.json)"
-
export AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken /tmp/aws_creds.json)"
script
:
-
/bin/gitlab-mcp-server || true
-
>
claude
-p "${AI_FLOW_INPUT:-'Implement the requested changes and open an MR'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
variables
:
AWS_REGION
:
"us-west-2"
Model IDs for Bedrock include region-specific prefixes (for example,
us.anthropic.claude-sonnet-4-6
). Pass the desired model via your job configuration or prompt if your workflow supports it.
​
Google Vertex AI job example (Workload Identity Federation)
Prerequisites:
Vertex AI API enabled in your GCP project
Workload Identity Federation configured to trust GitLab OIDC
A service account with Vertex AI permissions
Required CI/CD variables:
GCP_WORKLOAD_IDENTITY_PROVIDER
: Full provider resource name
GCP_SERVICE_ACCOUNT
: Service account email
CLOUD_ML_REGION
: Vertex region (for example,
us-east5
)
claude-vertex
:
stage
:
ai
image
:
gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
rules
:
-
if
:
'$CI_PIPELINE_SOURCE == "web"'
before_script
:
-
apt-get update && apt-get install -y git && apt-get clean
-
curl -fsSL https://claude.ai/install.sh | bash
# Authenticate to Google Cloud via WIF (no downloaded keys)
-
>
gcloud auth login --cred-file=<(cat <<EOF
{
"type": "external_account",
"audience": "${GCP_WORKLOAD_IDENTITY_PROVIDER}",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${GCP_SERVICE_ACCOUNT}:generateAccessToken",
"token_url": "https://sts.googleapis.com/v1/token"
}
EOF
)
-
gcloud config set project "$(gcloud projects list --format='value(projectId)' --filter="name:${CI_PROJECT_NAMESPACE}" | head -n1)" || true
script
:
-
/bin/gitlab-mcp-server || true
-
>
CLOUD_ML_REGION="${CLOUD_ML_REGION:-us-east5}"
claude
-p "${AI_FLOW_INPUT:-'Review and update code as requested'}"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write mcp__gitlab"
--debug
variables
:
CLOUD_ML_REGION
:
"us-east5"
With Workload Identity Federation, you do not need to store service account keys. Use repository-specific trust conditions and least-privilege service accounts.
​
Best practices
​
CLAUDE.md configuration
Create a
CLAUDE.md
file at the repository root to define coding standards, review criteria, and project-specific rules. Claude reads this file during runs and follows your conventions when proposing changes.
​
Security considerations
Never commit API keys or cloud credentials to your repository
. Always use GitLab CI/CD variables:
Add
ANTHROPIC_API_KEY
as a masked variable (and protect it if needed)
Use provider-specific OIDC where possible (no long-lived keys)
Limit job permissions and network egress
Review Claude’s MRs like any other contributor
​
Optimizing performance
Keep
CLAUDE.md
focused and concise
Provide clear issue/MR descriptions to reduce iterations
Configure sensible job timeouts to avoid runaway runs
Cache npm and package installs in runners where possible
​
CI costs
When using Claude Code with GitLab CI/CD, be aware of associated costs:
GitLab Runner time
:
Claude runs on your GitLab runners and consumes compute minutes
See your GitLab plan’s runner billing for details
API costs
:
Each Claude interaction consumes tokens based on prompt and response size
Token usage varies by task complexity and codebase size
See
Anthropic pricing
for details
Cost optimization tips
:
Use specific
@claude
commands to reduce unnecessary turns
Set appropriate
max_turns
and job timeout values
Limit concurrency to control parallel runs
​
Security and governance
Each job runs in an isolated container with restricted network access
Claude’s changes flow through MRs so reviewers see every diff
Branch protection and approval rules apply to AI-generated code
Claude Code uses workspace-scoped permissions to constrain writes
Costs remain under your control because you bring your own provider credentials
​
Troubleshooting
​
Claude not responding to @claude commands
Verify your pipeline is being triggered (manually, MR event, or via a note event listener/webhook)
Ensure CI/CD variables (
ANTHROPIC_API_KEY
or cloud provider settings) are present and unmasked
Check that the comment contains
@claude
(not
/claude
) and that your mention trigger is configured
​
Job can’t write comments or open MRs
Ensure
CI_JOB_TOKEN
has sufficient permissions for the project, or use a Project Access Token with
api
scope
Check the
mcp__gitlab
tool is enabled in
--allowedTools
Confirm the job runs in the context of the MR or has enough context via
AI_FLOW_*
variables
​
Authentication errors
For Claude API
: Confirm
ANTHROPIC_API_KEY
is valid and unexpired
For Bedrock/Vertex
: Verify OIDC/WIF configuration, role impersonation, and secret names; confirm region and model availability
​
Advanced configuration
​
Common parameters and variables
Claude Code supports these commonly used inputs:
prompt
/
prompt_file
: Provide instructions inline (
-p
) or via a file
max_turns
: Limit the number of back-and-forth iterations
timeout_minutes
: Limit total execution time
ANTHROPIC_API_KEY
: Required for the Claude API (not used for Bedrock/Vertex)
Provider-specific environment:
AWS_REGION
, project/region vars for Vertex
Exact flags and parameters may vary by version of
@anthropic-ai/claude-code
. Run
claude --help
in your job to see supported options.
​
Customizing Claude’s behavior
You can guide Claude in two primary ways:
CLAUDE.md
: Define coding standards, security requirements, and project conventions. Claude reads this during runs and follows your rules.
Custom prompts
: Pass task-specific instructions via
prompt
/
prompt_file
in the job. Use different prompts for different jobs (for example, review, implement, refactor).
Was this page helpful?
Yes
No
GitHub Enterprise Server
Claude Code in Slack
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/gitlab-ci-cd" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Code Review</title>
  <link>https://code.claude.com/docs/en/code-review</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/code-review</guid>
  <pubDate>Fri, 29 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Code Review
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Code Review
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Code Review is in research preview, available for
Team and Enterprise
subscriptions. It is not available for organizations with
Zero Data Retention
enabled.
Code Review analyzes your GitHub pull requests and posts findings as inline comments on the lines of code where it found issues. A fleet of specialized agents examine the code changes in the context of your full codebase, looking for logic errors, security vulnerabilities, broken edge cases, and subtle regressions.
Findings are tagged by severity and don’t approve or block your PR, so existing review workflows stay intact. You can tune what Claude flags by adding a
CLAUDE.md
or
REVIEW.md
file to your repository.
To run Claude in your own CI infrastructure instead of this managed service, see
GitHub Actions
or
GitLab CI/CD
. For repositories on a self-hosted GitHub instance, see
GitHub Enterprise Server
.
This page covers:
How reviews work
Setup
Triggering reviews manually
with
@claude review
and
@claude review once
Customizing reviews
with
CLAUDE.md
and
REVIEW.md
Pricing
Troubleshooting
failed runs and missing comments
​
How reviews work
Once an admin
enables Code Review
for your organization, reviews trigger when a PR opens, on every push, or when manually requested, depending on the repository’s configured behavior. Commenting
@claude review
starts reviews on a PR
in any mode.
When a review runs, multiple agents analyze the diff and surrounding code in parallel on Anthropic infrastructure. Each agent looks for a different class of issue, then a verification step checks candidates against actual code behavior to filter out false positives. The results are deduplicated, ranked by severity, and posted as inline comments on the specific lines where issues were found, with a summary in the review body. If no issues are found, Claude posts a short confirmation comment on the PR.
Reviews scale in cost with PR size and complexity, completing in 20 minutes on average. Admins can monitor review activity and spend via the
analytics dashboard
.
​
Severity levels
Each finding is tagged with a severity level:
Marker
Severity
Meaning
🔴
Important
A bug that should be fixed before merging
🟡
Nit
A minor issue, worth fixing but not blocking
🟣
Pre-existing
A bug that exists in the codebase but was not introduced by this PR
Findings include a collapsible extended reasoning section you can expand to understand why Claude flagged the issue and how it verified the problem.
​
Rate and reply to findings
Each review comment from Claude arrives with 👍 and 👎 already attached so both buttons appear in the GitHub UI for one-click rating. Click 👍 if the finding was useful or 👎 if it was wrong or noisy. Anthropic collects reaction counts after the PR merges and uses them to tune the reviewer. Reactions do not trigger a re-review or change anything on the PR.
Replying to an inline comment does not prompt Claude to respond or update the PR. To act on a finding, fix the code and push. If the PR is subscribed to push-triggered reviews, the next run resolves the thread when the issue is fixed. To request a fresh review without pushing, comment
@claude review once
as a
top-level PR comment
.
​
Check run output
Beyond the inline review comments, each review populates the
Claude Code Review
check run that appears alongside your CI checks. Expand its
Details
link to see a summary of every finding in one place, sorted by severity:
Severity
File:Line
Issue
🔴 Important
src/auth/session.ts:142
Token refresh races with logout, leaving stale sessions active
🟡 Nit
src/auth/session.ts:88
parseExpiry
silently returns 0 on malformed input
Each finding also appears as an annotation in the
Files changed
tab, marked directly on the relevant diff lines. Important findings render with a red marker, nits with a yellow warning, and pre-existing bugs with a gray notice. Annotations and the severity table are written to the check run independently of inline review comments, so they remain available even if GitHub rejects an inline comment on a line that moved.
The check run always completes with a neutral conclusion so it never blocks merging through branch protection rules. If you want to gate merges on Code Review findings, read the severity breakdown from the check run output in your own CI. The last line of the Details text is a machine-readable comment your workflow can parse with
gh
and jq:
gh
api
repos/OWNER/REPO/check-runs/CHECK_RUN_ID
\
--jq
'.output.text | split("bughunter-severity: ")[1] | split(" -->")[0] | fromjson'
This returns a JSON object with counts per severity, for example
{"normal": 2, "nit": 1, "pre_existing": 0}
. The
normal
key holds the count of Important findings; a non-zero value means Claude found at least one bug worth fixing before merge.
​
What Code Review checks
By default, Code Review focuses on correctness: bugs that would break production, not formatting preferences or missing test coverage. You can expand what it checks by
adding guidance files
to your repository.
​
Set up Code Review
An admin enables Code Review once for the organization and selects which repositories to include.
1
Open Claude Code admin settings
Go to
claude.ai/admin-settings/claude-code
and find the Code Review section. You need admin access to your Claude organization and permission to install GitHub Apps in your GitHub organization.
2
Start setup
Click
Setup
. This begins the GitHub App installation flow.
3
Install the Claude GitHub App
Follow the prompts to install the Claude GitHub App to your GitHub organization. The app requests these repository permissions:
Contents
: read and write
Issues
: read and write
Pull requests
: read and write
Code Review uses read access to contents and write access to pull requests. The broader permission set also supports
GitHub Actions
if you enable that later.
4
Select repositories
Choose which repositories to enable for Code Review. If you don’t see a repository, make sure you gave the Claude GitHub App access to it during installation. You can add more repositories later.
5
Set review triggers per repo
After setup completes, the Code Review section shows your repositories in a table. For each repository, use the
Review Behavior
dropdown to choose when reviews run:
Once after PR creation
: review runs once when a PR is opened or marked ready for review
After every push
: review runs on every push to the PR branch, catching new issues as the PR evolves and auto-resolving threads when you fix flagged issues
Manual
: reviews start only when someone
comments
@claude review
or
@claude review once
on a PR
;
@claude review
also subscribes the PR to reviews on subsequent pushes
Reviewing on every push runs the most reviews and costs the most. Manual mode is useful for high-traffic repos where you want to opt specific PRs into review, or to only start reviewing your PRs once they’re ready.
The repositories table also shows the average cost per review for each repo based on recent activity. Use the row actions menu to turn Code Review on or off per repository, or to remove a repository entirely.
To verify setup, open a test PR. If you chose an automatic trigger, a check run named
Claude Code Review
appears within a few minutes. If you chose Manual, comment
@claude review
on the PR to start the first review. If no check run appears, confirm the repository is listed in your admin settings and the Claude GitHub App has access to it.
​
Manually trigger reviews
Two comment commands start a review on demand. Both work regardless of the repository’s configured trigger, so you can use them to opt specific PRs into review in Manual mode or to get an immediate re-review in other modes.
Command
What it does
@claude review
Starts a review and subscribes the PR to push-triggered reviews going forward
@claude review once
Starts a single review without subscribing the PR to future pushes
Use
@claude review once
when you want feedback on the current state of a PR but don’t want every subsequent push to incur a review. This is useful for long-running PRs with frequent pushes, or when you want a one-off second opinion without changing the PR’s review behavior.
For either command to trigger a review:
Post it as a top-level PR comment, not an inline comment on a diff line
Put the command at the start of the comment, with
once
on the same line if you’re using the one-shot form
You must have owner, member, or collaborator access to the repository
The PR must be open
Unlike automatic triggers, manual triggers run on draft PRs, since an explicit request signals you want the review now regardless of draft status.
If a review is already running on that PR, the request is queued until the in-progress review completes. You can monitor progress via the check run on the PR.
​
Customize reviews
Code Review reads two files from your repository to guide what it flags. They differ in how strongly they influence the review:
CLAUDE.md
: shared project instructions that Claude Code uses for all tasks, not just reviews. Code Review reads it as project context and flags newly introduced violations as nits.
REVIEW.md
: review-only instructions, injected directly into every agent in the review pipeline as highest priority. Use it to change what gets flagged, at what severity, and how findings are reported.
​
CLAUDE.md
Code Review reads your repository’s
CLAUDE.md
files and treats newly introduced violations as
nit-level
findings. This works bidirectionally: if your PR changes code in a way that makes a
CLAUDE.md
statement outdated, Claude flags that the docs need updating too.
Claude reads
CLAUDE.md
files at every level of your directory hierarchy, so rules in a subdirectory’s
CLAUDE.md
apply only to files under that path. See the
memory documentation
for more on how
CLAUDE.md
works.
For review-specific guidance that you don’t want applied to general Claude Code sessions, use
REVIEW.md
instead.
​
REVIEW.md
REVIEW.md
is a file at your repository root that overrides how Code Review behaves on your repo. Its contents are injected into the system prompt of every agent in the review pipeline as the highest-priority instruction block, taking precedence over the default review guidance.
Because it’s pasted verbatim,
REVIEW.md
is plain instructions:
@
import syntax
is not expanded, and referenced files are not read into the prompt. Put the rules you want enforced directly in the file.
​
What you can tune
REVIEW.md
is freeform markdown, so anything you can express as a review instruction is in scope. The patterns below have the most impact in practice.
Severity
: redefine what 🔴 Important means for your repo. The default calibration targets production code; a docs repo, a config repo, or a prototype might want a much narrower definition. State explicitly which classes of finding are Important and which are Nit at most. You can also escalate in the other direction, for example treating any
CLAUDE.md
violation as Important rather than the default nit.
Nit volume
: cap how many 🟡 Nit comments a single review posts. Prose and config files can be polished forever. A cap like “report at most five nits, mention the rest as a count in the summary” keeps reviews actionable.
Skip rules
: list paths, branch patterns, and finding categories where Claude should post no findings. Common candidates are generated code, lockfiles, vendored dependencies, and machine-authored branches, along with anything your CI already enforces like linting or spellcheck. For paths that warrant some review but not full scrutiny, set a higher bar instead of skipping entirely: “in
scripts/
, only report if near-certain and severe.”
Repo-specific checks
: add rules you want flagged on every PR, like “new API routes must have an integration test.” Because
REVIEW.md
is injected as highest priority, these land more reliably than the same rules in a long
CLAUDE.md
.
Verification bar
: require evidence before a class of finding is posted. For example, “behavior claims need a
file:line
citation in the source, not an inference from naming” cuts false positives that would otherwise cost the author a round trip.
Re-review convergence
: tell Claude how to behave when a PR has already been reviewed. A rule like “after the first review, suppress new nits and post Important findings only” stops a one-line fix from reaching round seven on style alone.
Summary shape
: ask for the review body to open with a one-line tally such as
2 factual, 4 style
, and to lead with “no factual issues” when that’s the case. The author wants to know the shape of the work before the details.
​
Example
This
REVIEW.md
recalibrates severity for a backend service, caps nits, skips generated files, and adds repo-specific checks.
# Review instructions
## What Important means here
Reserve Important for findings that would break behavior, leak data,
or block a rollback: incorrect logic, unscoped database queries, PII
in logs or error messages, and migrations that aren't backward
compatible. Style, naming, and refactoring suggestions are Nit at
most.
## Cap the nits
Report at most five Nits per review. If you found more, say "plus N
similar items" in the summary instead of posting them inline. If
everything you found is a Nit, lead the summary with "No blocking
issues."
## Do not report
-
Anything CI already enforces: lint, formatting, type errors
-
Generated files under
`src/gen/`
and any
`*.lock`
file
-
Test-only code that intentionally violates production rules
## Always check
-
New API routes have an integration test
-
Log lines don't include email addresses, user IDs, or request bodies
-
Database queries are scoped to the caller's tenant
​
Keep it focused
Length has a cost: a long
REVIEW.md
dilutes the rules that matter most. Keep it to instructions that change review behavior, and leave general project context in
CLAUDE.md
.
​
View usage
Go to
claude.ai/analytics/code-review
to see Code Review activity across your organization. The dashboard shows:
Section
What it shows
PRs reviewed
Daily count of pull requests reviewed over the selected time range
Cost weekly
Weekly spend on Code Review
Feedback
Count of review comments that were auto-resolved because a developer addressed the issue
Repository breakdown
Per-repo counts of PRs reviewed and comments resolved
The repositories table in admin settings also shows average cost per review for each repo. Dashboard cost figures are estimates for monitoring activity; for invoice-accurate spend, refer to your Anthropic bill.
​
Pricing
Code Review is billed based on token usage. Each review averages $15-25 in cost, scaling with PR size, codebase complexity, and how many issues require verification. Code Review usage is billed separately through
extra usage
and does not count against your plan’s included usage.
The review trigger you choose affects total cost:
Once after PR creation
: runs once per PR
After every push
: runs on each push, multiplying cost by the number of pushes
Manual
: no reviews until someone comments
@claude review
on a PR
In any mode, commenting
@claude review
opts the PR into push-triggered reviews
, so additional cost accrues per push after that comment. To run a single review without subscribing to future pushes, comment
@claude review once
instead.
Costs appear on your Anthropic bill regardless of whether your organization uses Amazon Bedrock or Google Vertex AI for other Claude Code features. To set a monthly spend cap for Code Review, go to
claude.ai/admin-settings/usage
and configure the limit for the Claude Code Review service.
Monitor spend via the weekly cost chart in
analytics
or the per-repo average cost column in admin settings.
​
Troubleshooting
Review runs are best-effort. A failed run never blocks your PR, but it also doesn’t retry on its own. This section covers how to recover from a failed run and where to look when the check run reports issues you can’t find.
​
Retrigger a failed or timed-out review
When the review infrastructure hits an internal error or exceeds its time limit, the check run completes with a title of
Code review encountered an error
or
Code review timed out
. The conclusion is still neutral, so nothing blocks your merge, but no findings are posted.
To run the review again, comment
@claude review once
on the PR. This starts a fresh review without subscribing the PR to future pushes. If the PR is already subscribed to push-triggered reviews, pushing a new commit also starts a new review.
The
Re-run
button in GitHub’s Checks tab does not retrigger Code Review. Use the comment command or a new push instead.
​
Review didn’t run and the PR shows a spend-cap message
When your organization’s monthly spend cap is reached, Code Review posts a single comment on the PR explaining that the review was skipped. Reviews resume automatically at the start of the next billing period, or immediately when an admin raises the cap at
claude.ai/admin-settings/usage
.
​
Find issues that aren’t showing as inline comments
If the check run title says issues were found but you don’t see inline review comments on the diff, look in these other locations where findings are surfaced:
Check run Details
: click
Details
next to the Claude Code Review check in the Checks tab. The severity table lists every finding with its file, line, and summary regardless of whether the inline comment was accepted.
Files changed annotations
: open the
Files changed
tab on the PR. Findings render as annotations attached directly to the diff lines, separate from review comments.
Review body
: if you pushed to the PR while a review was running, some findings may reference lines that no longer exist in the current diff. Those appear under an
Additional findings
heading in the review body text rather than as inline comments.
​
Related resources
Code Review is designed to work alongside the rest of Claude Code. If you want to run reviews locally before opening a PR, need a self-hosted setup, or want to go deeper on how
CLAUDE.md
shapes Claude’s behavior across tools, these pages are good next stops:
Plugins
: browse the plugin marketplace, including a
code-review
plugin for running on-demand reviews locally before pushing
GitHub Actions
: run Claude in your own GitHub Actions workflows for custom automation beyond code review
GitLab CI/CD
: self-hosted Claude integration for GitLab pipelines
Memory
: how
CLAUDE.md
files work across Claude Code
Analytics
: track Claude Code usage beyond code review
Was this page helpful?
Yes
No
JetBrains IDEs
GitHub Actions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/code-review" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Code Review
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Code Review
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Code Review is in research preview, available for
Team and Enterprise
subscriptions. It is not available for organizations with
Zero Data Retention
enabled.
Code Review analyzes your GitHub pull requests and posts findings as inline comments on the lines of code where it found issues. A fleet of specialized agents examine the code changes in the context of your full codebase, looking for logic errors, security vulnerabilities, broken edge cases, and subtle regressions.
Findings are tagged by severity and don’t approve or block your PR, so existing review workflows stay intact. You can tune what Claude flags by adding a
CLAUDE.md
or
REVIEW.md
file to your repository.
To run Claude in your own CI infrastructure instead of this managed service, see
GitHub Actions
or
GitLab CI/CD
. For repositories on a self-hosted GitHub instance, see
GitHub Enterprise Server
.
This page covers:
How reviews work
Setup
Triggering reviews manually
with
@claude review
and
@claude review once
Customizing reviews
with
CLAUDE.md
and
REVIEW.md
Pricing
Troubleshooting
failed runs and missing comments
​
How reviews work
Once an admin
enables Code Review
for your organization, reviews trigger when a PR opens, on every push, or when manually requested, depending on the repository’s configured behavior. Commenting
@claude review
starts reviews on a PR
in any mode.
When a review runs, multiple agents analyze the diff and surrounding code in parallel on Anthropic infrastructure. Each agent looks for a different class of issue, then a verification step checks candidates against actual code behavior to filter out false positives. The results are deduplicated, ranked by severity, and posted as inline comments on the specific lines where issues were found, with a summary in the review body. If no issues are found, Claude posts a short confirmation comment on the PR.
Reviews scale in cost with PR size and complexity, completing in 20 minutes on average. Admins can monitor review activity and spend via the
analytics dashboard
.
​
Severity levels
Each finding is tagged with a severity level:
Marker
Severity
Meaning
🔴
Important
A bug that should be fixed before merging
🟡
Nit
A minor issue, worth fixing but not blocking
🟣
Pre-existing
A bug that exists in the codebase but was not introduced by this PR
Findings include a collapsible extended reasoning section you can expand to understand why Claude flagged the issue and how it verified the problem.
​
Rate and reply to findings
Each review comment from Claude arrives with 👍 and 👎 already attached so both buttons appear in the GitHub UI for one-click rating. Click 👍 if the finding was useful or 👎 if it was wrong or noisy. Anthropic collects reaction counts after the PR merges and uses them to tune the reviewer. Reactions do not trigger a re-review or change anything on the PR.
Replying to an inline comment does not prompt Claude to respond or update the PR. To act on a finding, fix the code and push. If the PR is subscribed to push-triggered reviews, the next run resolves the thread when the issue is fixed. To request a fresh review without pushing, comment
@claude review once
as a
top-level PR comment
.
​
Check run output
Beyond the inline review comments, each review populates the
Claude Code Review
check run that appears alongside your CI checks. Expand its
Details
link to see a summary of every finding in one place, sorted by severity:
Severity
File:Line
Issue
🔴 Important
src/auth/session.ts:142
Token refresh races with logout, leaving stale sessions active
🟡 Nit
src/auth/session.ts:88
parseExpiry
silently returns 0 on malformed input
Each finding also appears as an annotation in the
Files changed
tab, marked directly on the relevant diff lines. Important findings render with a red marker, nits with a yellow warning, and pre-existing bugs with a gray notice. Annotations and the severity table are written to the check run independently of inline review comments, so they remain available even if GitHub rejects an inline comment on a line that moved.
The check run always completes with a neutral conclusion so it never blocks merging through branch protection rules. If you want to gate merges on Code Review findings, read the severity breakdown from the check run output in your own CI. The last line of the Details text is a machine-readable comment your workflow can parse with
gh
and jq:
gh
api
repos/OWNER/REPO/check-runs/CHECK_RUN_ID
\
--jq
'.output.text | split("bughunter-severity: ")[1] | split(" -->")[0] | fromjson'
This returns a JSON object with counts per severity, for example
{"normal": 2, "nit": 1, "pre_existing": 0}
. The
normal
key holds the count of Important findings; a non-zero value means Claude found at least one bug worth fixing before merge.
​
What Code Review checks
By default, Code Review focuses on correctness: bugs that would break production, not formatting preferences or missing test coverage. You can expand what it checks by
adding guidance files
to your repository.
​
Set up Code Review
An admin enables Code Review once for the organization and selects which repositories to include.
1
Open Claude Code admin settings
Go to
claude.ai/admin-settings/claude-code
and find the Code Review section. You need admin access to your Claude organization and permission to install GitHub Apps in your GitHub organization.
2
Start setup
Click
Setup
. This begins the GitHub App installation flow.
3
Install the Claude GitHub App
Follow the prompts to install the Claude GitHub App to your GitHub organization. The app requests these repository permissions:
Contents
: read and write
Issues
: read and write
Pull requests
: read and write
Code Review uses read access to contents and write access to pull requests. The broader permission set also supports
GitHub Actions
if you enable that later.
4
Select repositories
Choose which repositories to enable for Code Review. If you don’t see a repository, make sure you gave the Claude GitHub App access to it during installation. You can add more repositories later.
5
Set review triggers per repo
After setup completes, the Code Review section shows your repositories in a table. For each repository, use the
Review Behavior
dropdown to choose when reviews run:
Once after PR creation
: review runs once when a PR is opened or marked ready for review
After every push
: review runs on every push to the PR branch, catching new issues as the PR evolves and auto-resolving threads when you fix flagged issues
Manual
: reviews start only when someone
comments
@claude review
or
@claude review once
on a PR
;
@claude review
also subscribes the PR to reviews on subsequent pushes
Reviewing on every push runs the most reviews and costs the most. Manual mode is useful for high-traffic repos where you want to opt specific PRs into review, or to only start reviewing your PRs once they’re ready.
The repositories table also shows the average cost per review for each repo based on recent activity. Use the row actions menu to turn Code Review on or off per repository, or to remove a repository entirely.
To verify setup, open a test PR. If you chose an automatic trigger, a check run named
Claude Code Review
appears within a few minutes. If you chose Manual, comment
@claude review
on the PR to start the first review. If no check run appears, confirm the repository is listed in your admin settings and the Claude GitHub App has access to it.
​
Manually trigger reviews
Two comment commands start a review on demand. Both work regardless of the repository’s configured trigger, so you can use them to opt specific PRs into review in Manual mode or to get an immediate re-review in other modes.
Command
What it does
@claude review
Starts a review and subscribes the PR to push-triggered reviews going forward
@claude review once
Starts a single review without subscribing the PR to future pushes
Use
@claude review once
when you want feedback on the current state of a PR but don’t want every subsequent push to incur a review. This is useful for long-running PRs with frequent pushes, or when you want a one-off second opinion without changing the PR’s review behavior.
For either command to trigger a review:
Post it as a top-level PR comment, not an inline comment on a diff line
Put the command at the start of the comment, with
once
on the same line if you’re using the one-shot form
You must have owner, member, or collaborator access to the repository
The PR must be open
Unlike automatic triggers, manual triggers run on draft PRs, since an explicit request signals you want the review now regardless of draft status.
If a review is already running on that PR, the request is queued until the in-progress review completes. You can monitor progress via the check run on the PR.
​
Customize reviews
Code Review reads two files from your repository to guide what it flags. They differ in how strongly they influence the review:
CLAUDE.md
: shared project instructions that Claude Code uses for all tasks, not just reviews. Code Review reads it as project context and flags newly introduced violations as nits.
REVIEW.md
: review-only instructions, injected directly into every agent in the review pipeline as highest priority. Use it to change what gets flagged, at what severity, and how findings are reported.
​
CLAUDE.md
Code Review reads your repository’s
CLAUDE.md
files and treats newly introduced violations as
nit-level
findings. This works bidirectionally: if your PR changes code in a way that makes a
CLAUDE.md
statement outdated, Claude flags that the docs need updating too.
Claude reads
CLAUDE.md
files at every level of your directory hierarchy, so rules in a subdirectory’s
CLAUDE.md
apply only to files under that path. See the
memory documentation
for more on how
CLAUDE.md
works.
For review-specific guidance that you don’t want applied to general Claude Code sessions, use
REVIEW.md
instead.
​
REVIEW.md
REVIEW.md
is a file at your repository root that overrides how Code Review behaves on your repo. Its contents are injected into the system prompt of every agent in the review pipeline as the highest-priority instruction block, taking precedence over the default review guidance.
Because it’s pasted verbatim,
REVIEW.md
is plain instructions:
@
import syntax
is not expanded, and referenced files are not read into the prompt. Put the rules you want enforced directly in the file.
​
What you can tune
REVIEW.md
is freeform markdown, so anything you can express as a review instruction is in scope. The patterns below have the most impact in practice.
Severity
: redefine what 🔴 Important means for your repo. The default calibration targets production code; a docs repo, a config repo, or a prototype might want a much narrower definition. State explicitly which classes of finding are Important and which are Nit at most. You can also escalate in the other direction, for example treating any
CLAUDE.md
violation as Important rather than the default nit.
Nit volume
: cap how many 🟡 Nit comments a single review posts. Prose and config files can be polished forever. A cap like “report at most five nits, mention the rest as a count in the summary” keeps reviews actionable.
Skip rules
: list paths, branch patterns, and finding categories where Claude should post no findings. Common candidates are generated code, lockfiles, vendored dependencies, and machine-authored branches, along with anything your CI already enforces like linting or spellcheck. For paths that warrant some review but not full scrutiny, set a higher bar instead of skipping entirely: “in
scripts/
, only report if near-certain and severe.”
Repo-specific checks
: add rules you want flagged on every PR, like “new API routes must have an integration test.” Because
REVIEW.md
is injected as highest priority, these land more reliably than the same rules in a long
CLAUDE.md
.
Verification bar
: require evidence before a class of finding is posted. For example, “behavior claims need a
file:line
citation in the source, not an inference from naming” cuts false positives that would otherwise cost the author a round trip.
Re-review convergence
: tell Claude how to behave when a PR has already been reviewed. A rule like “after the first review, suppress new nits and post Important findings only” stops a one-line fix from reaching round seven on style alone.
Summary shape
: ask for the review body to open with a one-line tally such as
2 factual, 4 style
, and to lead with “no factual issues” when that’s the case. The author wants to know the shape of the work before the details.
​
Example
This
REVIEW.md
recalibrates severity for a backend service, caps nits, skips generated files, and adds repo-specific checks.
# Review instructions
## What Important means here
Reserve Important for findings that would break behavior, leak data,
or block a rollback: incorrect logic, unscoped database queries, PII
in logs or error messages, and migrations that aren't backward
compatible. Style, naming, and refactoring suggestions are Nit at
most.
## Cap the nits
Report at most five Nits per review. If you found more, say "plus N
similar items" in the summary instead of posting them inline. If
everything you found is a Nit, lead the summary with "No blocking
issues."
## Do not report
-
Anything CI already enforces: lint, formatting, type errors
-
Generated files under
`src/gen/`
and any
`*.lock`
file
-
Test-only code that intentionally violates production rules
## Always check
-
New API routes have an integration test
-
Log lines don't include email addresses, user IDs, or request bodies
-
Database queries are scoped to the caller's tenant
​
Keep it focused
Length has a cost: a long
REVIEW.md
dilutes the rules that matter most. Keep it to instructions that change review behavior, and leave general project context in
CLAUDE.md
.
​
View usage
Go to
claude.ai/analytics/code-review
to see Code Review activity across your organization. The dashboard shows:
Section
What it shows
PRs reviewed
Daily count of pull requests reviewed over the selected time range
Cost weekly
Weekly spend on Code Review
Feedback
Count of review comments that were auto-resolved because a developer addressed the issue
Repository breakdown
Per-repo counts of PRs reviewed and comments resolved
The repositories table in admin settings also shows average cost per review for each repo. Dashboard cost figures are estimates for monitoring activity; for invoice-accurate spend, refer to your Anthropic bill.
​
Pricing
Code Review is billed based on token usage. Each review averages $15-25 in cost, scaling with PR size, codebase complexity, and how many issues require verification. Code Review usage is billed separately through
extra usage
and does not count against your plan’s included usage.
The review trigger you choose affects total cost:
Once after PR creation
: runs once per PR
After every push
: runs on each push, multiplying cost by the number of pushes
Manual
: no reviews until someone comments
@claude review
on a PR
In any mode, commenting
@claude review
opts the PR into push-triggered reviews
, so additional cost accrues per push after that comment. To run a single review without subscribing to future pushes, comment
@claude review once
instead.
Costs appear on your Anthropic bill regardless of whether your organization uses Amazon Bedrock or Google Vertex AI for other Claude Code features. To set a monthly spend cap for Code Review, go to
claude.ai/admin-settings/usage
and configure the limit for the Claude Code Review service.
Monitor spend via the weekly cost chart in
analytics
or the per-repo average cost column in admin settings.
​
Troubleshooting
Review runs are best-effort. A failed run never blocks your PR, but it also doesn’t retry on its own. This section covers how to recover from a failed run and where to look when the check run reports issues you can’t find.
​
Retrigger a failed or timed-out review
When the review infrastructure hits an internal error or exceeds its time limit, the check run completes with a title of
Code review encountered an error
or
Code review timed out
. The conclusion is still neutral, so nothing blocks your merge, but no findings are posted.
To run the review again, comment
@claude review once
on the PR. This starts a fresh review without subscribing the PR to future pushes. If the PR is already subscribed to push-triggered reviews, pushing a new commit also starts a new review.
The
Re-run
button in GitHub’s Checks tab does not retrigger Code Review. Use the comment command or a new push instead.
​
Review didn’t run and the PR shows a spend-cap message
When your organization’s monthly spend cap is reached, Code Review posts a single comment on the PR explaining that the review was skipped. Reviews resume automatically at the start of the next billing period, or immediately when an admin raises the cap at
claude.ai/admin-settings/usage
.
​
Find issues that aren’t showing as inline comments
If the check run title says issues were found but you don’t see inline review comments on the diff, look in these other locations where findings are surfaced:
Check run Details
: click
Details
next to the Claude Code Review check in the Checks tab. The severity table lists every finding with its file, line, and summary regardless of whether the inline comment was accepted.
Files changed annotations
: open the
Files changed
tab on the PR. Findings render as annotations attached directly to the diff lines, separate from review comments.
Review body
: if you pushed to the PR while a review was running, some findings may reference lines that no longer exist in the current diff. Those appear under an
Additional findings
heading in the review body text rather than as inline comments.
​
Related resources
Code Review is designed to work alongside the rest of Claude Code. If you want to run reviews locally before opening a PR, need a self-hosted setup, or want to go deeper on how
CLAUDE.md
shapes Claude’s behavior across tools, these pages are good next stops:
Plugins
: browse the plugin marketplace, including a
code-review
plugin for running on-demand reviews locally before pushing
GitHub Actions
: run Claude in your own GitHub Actions workflows for custom automation beyond code review
GitLab CI/CD
: self-hosted Claude integration for GitLab pipelines
Memory
: how
CLAUDE.md
files work across Claude Code
Analytics
: track Claude Code usage beyond code review
Was this page helpful?
Yes
No
JetBrains IDEs
GitHub Actions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/code-review" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 14 · March 30 – April 3, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w14</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w14</guid>
  <pubDate>Fri, 29 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 14 · March 30 – April 3, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.86 → v2.1.91
5 fea...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 14 · March 30 – April 3, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.86 → v2.1.91
5 features · March 30 – April 3
Computer use in the CLI
research preview
Last week computer use landed in the Desktop app. This week it’s in the CLI: Claude can open native apps, click through UI, test its own changes, and fix what breaks, all from your terminal. Web apps already had verification loops; native iOS, macOS, and other GUI-only apps didn’t. Now they do. Best for closing the loop on apps and tools where there’s no API to call. Still early; expect rough edges.
Run
/mcp
, find
computer-use
, and toggle it on. Then ask Claude to verify a change end to end:
Claude Code
> Open the iOS simulator, tap through onboarding, and screenshot each step
Computer use guide
/powerup
v2.1.90
Interactive lessons that teach Claude Code features through animated demos, right inside your terminal. Claude Code releases frequently, and features that would have changed how you work last month can slip by. Run
/powerup
once and you’ll know what’s there.
Run it:
Claude Code
> /powerup
Commands reference
Flicker-free rendering
v2.1.89
Opt into a new alt-screen renderer with virtualized scrollback. The prompt input stays pinned to the bottom, mouse selection works across long conversations, and the flicker on redraw is gone. Unset
CLAUDE_CODE_NO_FLICKER
to roll back.
Set the env var and restart Claude Code:
export
CLAUDE_CODE_NO_FLICKER
=
1
claude
Fullscreen rendering
MCP result-size override
v2.1.91
MCP server authors can now raise the truncation cap on a specific tool by setting
anthropic/maxResultSizeChars
in the tool’s
tools/list
entry, up to a hard ceiling of 500K characters. The cap used to be global, so tools that occasionally returned inherently large payloads like database schemas or full file trees hit the default limit and got persisted to disk with a file reference. Per-tool overrides keep those results inline when the tool really needs them.
Annotate the tool in your server’s
tools/list
response:
{
"name"
:
"get_schema"
,
"description"
:
"Returns the full database schema"
,
"_meta"
: {
"anthropic/maxResultSizeChars"
:
500000
}
}
MCP reference
Plugin executables on PATH
v2.1.91
Place an executable in a
bin/
directory at your plugin root and Claude Code adds that directory to the Bash tool’s
PATH
while the plugin is enabled. Claude can then invoke the binary as a bare command from any Bash tool call, with no absolute path or wrapper script needed. Handy for packaging CLI helpers next to the commands, agents, and hooks that call them.
Add a
bin/
directory at the plugin root:
my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── bin/
└── my-tool
Plugins reference
Other wins
Auto mode follow-ups: new
PermissionDenied
hook fires on classifier denials (return
retry: true
to let Claude try a different approach), and
/permissions
→ Recent lets you retry manually with
r
New
defer
value for
permissionDecision
in
PreToolUse
hooks:
-p
sessions pause at a tool call and exit with a
deferred_tool_use
payload so an SDK app or custom UI can surface it, then resume with
—resume
/buddy
: hatch a small creature that watches you code (April 1st)
disableSkillShellExecution
setting blocks inline shell from skills, slash commands, and plugin commands
Edit tool now works on files viewed via
cat
or
sed -n
without a separate Read
Hook output over 50K saved to disk with a path + preview instead of injected into context
Thinking summaries off by default in interactive sessions (
showThinkingSummaries: true
to restore)
Voice mode: push-to-talk modifier combos, Windows WebSocket, macOS Apple Silicon mic permission
claude-cli://
deep links accept multi-line prompts (encoded
%0A
)
Full changelog for v2.1.86–v2.1.91 →
Was this page helpful?
Yes
No
Week 15 · Apr 6–10
Week 13 · Mar 23–27
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w14" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 14 · March 30 – April 3, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.86 → v2.1.91
5 fea...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 14 · March 30 – April 3, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.86 → v2.1.91
5 features · March 30 – April 3
Computer use in the CLI
research preview
Last week computer use landed in the Desktop app. This week it’s in the CLI: Claude can open native apps, click through UI, test its own changes, and fix what breaks, all from your terminal. Web apps already had verification loops; native iOS, macOS, and other GUI-only apps didn’t. Now they do. Best for closing the loop on apps and tools where there’s no API to call. Still early; expect rough edges.
Run
/mcp
, find
computer-use
, and toggle it on. Then ask Claude to verify a change end to end:
Claude Code
> Open the iOS simulator, tap through onboarding, and screenshot each step
Computer use guide
/powerup
v2.1.90
Interactive lessons that teach Claude Code features through animated demos, right inside your terminal. Claude Code releases frequently, and features that would have changed how you work last month can slip by. Run
/powerup
once and you’ll know what’s there.
Run it:
Claude Code
> /powerup
Commands reference
Flicker-free rendering
v2.1.89
Opt into a new alt-screen renderer with virtualized scrollback. The prompt input stays pinned to the bottom, mouse selection works across long conversations, and the flicker on redraw is gone. Unset
CLAUDE_CODE_NO_FLICKER
to roll back.
Set the env var and restart Claude Code:
export
CLAUDE_CODE_NO_FLICKER
=
1
claude
Fullscreen rendering
MCP result-size override
v2.1.91
MCP server authors can now raise the truncation cap on a specific tool by setting
anthropic/maxResultSizeChars
in the tool’s
tools/list
entry, up to a hard ceiling of 500K characters. The cap used to be global, so tools that occasionally returned inherently large payloads like database schemas or full file trees hit the default limit and got persisted to disk with a file reference. Per-tool overrides keep those results inline when the tool really needs them.
Annotate the tool in your server’s
tools/list
response:
{
"name"
:
"get_schema"
,
"description"
:
"Returns the full database schema"
,
"_meta"
: {
"anthropic/maxResultSizeChars"
:
500000
}
}
MCP reference
Plugin executables on PATH
v2.1.91
Place an executable in a
bin/
directory at your plugin root and Claude Code adds that directory to the Bash tool’s
PATH
while the plugin is enabled. Claude can then invoke the binary as a bare command from any Bash tool call, with no absolute path or wrapper script needed. Handy for packaging CLI helpers next to the commands, agents, and hooks that call them.
Add a
bin/
directory at the plugin root:
my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── bin/
└── my-tool
Plugins reference
Other wins
Auto mode follow-ups: new
PermissionDenied
hook fires on classifier denials (return
retry: true
to let Claude try a different approach), and
/permissions
→ Recent lets you retry manually with
r
New
defer
value for
permissionDecision
in
PreToolUse
hooks:
-p
sessions pause at a tool call and exit with a
deferred_tool_use
payload so an SDK app or custom UI can surface it, then resume with
—resume
/buddy
: hatch a small creature that watches you code (April 1st)
disableSkillShellExecution
setting blocks inline shell from skills, slash commands, and plugin commands
Edit tool now works on files viewed via
cat
or
sed -n
without a separate Read
Hook output over 50K saved to disk with a path + preview instead of injected into context
Thinking summaries off by default in interactive sessions (
showThinkingSummaries: true
to restore)
Voice mode: push-to-talk modifier combos, Windows WebSocket, macOS Apple Silicon mic permission
claude-cli://
deep links accept multi-line prompts (encoded
%0A
)
Full changelog for v2.1.86–v2.1.91 →
Was this page helpful?
Yes
No
Week 15 · Apr 6–10
Week 13 · Mar 23–27
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w14" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Orchestrate teams of Claude Code sessions</title>
  <link>https://code.claude.com/docs/en/agent-teams</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-teams</guid>
  <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Orchestrate teams of Claude Code sessions
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usa...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Orchestrate teams of Claude Code sessions
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Agent teams are experimental and disabled by default. Enable them by adding
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
to your
settings.json
or environment. Agent teams have
known limitations
around session resumption, task coordination, and shutdown behavior.
Agent teams let you coordinate multiple Claude Code instances working together. One session acts as the team lead, coordinating work, assigning tasks, and synthesizing results. Teammates work independently, each in its own context window, and communicate directly with each other.
Unlike
subagents
, which run within a single session and can only report back to the main agent, you can also interact with individual teammates directly without going through the lead.
Agent teams require Claude Code v2.1.32 or later. Check your version with
claude --version
.
This page covers:
When to use agent teams
, including best use cases and how they compare with subagents
Starting a team
Controlling teammates
, including display modes, task assignment, and delegation
Best practices for parallel work
​
When to use agent teams
Agent teams are most effective for tasks where parallel exploration adds real value. See
use case examples
for full scenarios. The strongest use cases are:
Research and review
: multiple teammates can investigate different aspects of a problem simultaneously, then share and challenge each other’s findings
New modules or features
: teammates can each own a separate piece without stepping on each other
Debugging with competing hypotheses
: teammates test different theories in parallel and converge on the answer faster
Cross-layer coordination
: changes that span frontend, backend, and tests, each owned by a different teammate
Agent teams add coordination overhead and use significantly more tokens than a single session. They work best when teammates can operate independently. For sequential tasks, same-file edits, or work with many dependencies, a single session or
subagents
are more effective.
​
Compare with subagents
Both agent teams and
subagents
let you parallelize work, but they operate differently. Choose based on whether your workers need to communicate with each other:
Subagents only report results back to the main agent and never talk to each other. In agent teams, teammates share a task list, claim work, and communicate directly with each other.
Subagents
Agent teams
Context
Own context window; results return to the caller
Own context window; fully independent
Communication
Report results back to the main agent only
Teammates message each other directly
Coordination
Main agent manages all work
Shared task list with self-coordination
Best for
Focused tasks where only the result matters
Complex work requiring discussion and collaboration
Token cost
Lower: results summarized back to main context
Higher: each teammate is a separate Claude instance
Use subagents when you need quick, focused workers that report back. Use agent teams when teammates need to share findings, challenge each other, and coordinate on their own.
​
Enable agent teams
Agent teams are disabled by default. Enable them by setting the
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
environment variable to
1
, either in your shell environment or through
settings.json
:
settings.json
{
"env"
: {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS"
:
"1"
}
}
​
Start your first agent team
After enabling agent teams, tell Claude to create an agent team and describe the task and the team structure you want in natural language. Claude creates the team, spawns teammates, and coordinates work based on your prompt.
This example works well because the three roles are independent and can explore the problem without waiting on each other:
I'm designing a CLI tool that helps developers track TODO comments across
their codebase. Create an agent team to explore this from different angles: one
teammate on UX, one on technical architecture, one playing devil's advocate.
From there, Claude creates a team with a
shared task list
, spawns teammates for each perspective, has them explore the problem, synthesizes findings, and attempts to
clean up the team
when finished.
The lead’s terminal lists all teammates and what they’re working on. Use Shift+Down to cycle through teammates and message them directly. After the last teammate, Shift+Down wraps back to the lead.
If you want each teammate in its own split pane, see
Choose a display mode
.
​
Control your agent team
Tell the lead what you want in natural language. It handles team coordination, task assignment, and delegation based on your instructions.
​
Choose a display mode
Agent teams support two display modes:
In-process
: all teammates run inside your main terminal. Use Shift+Down to cycle through teammates and type to message them directly. Works in any terminal, no extra setup required.
Split panes
: each teammate gets its own pane. You can see everyone’s output at once and click into a pane to interact directly. Requires tmux, or iTerm2.
tmux
has known limitations on certain operating systems and traditionally works best on macOS. Using
tmux -CC
in iTerm2 is the suggested entrypoint into
tmux
.
The default is
"auto"
, which uses split panes if you’re already running inside a tmux session, and in-process otherwise. The
"tmux"
setting enables split-pane mode and auto-detects whether to use tmux or iTerm2 based on your terminal. To override, set
teammateMode
in
~/.claude/settings.json
:
{
"teammateMode"
:
"in-process"
}
To force in-process mode for a single session, pass it as a flag:
claude
--teammate-mode
in-process
Split-pane mode requires either
tmux
or iTerm2 with the
it2
CLI
. To install manually:
tmux
: install through your system’s package manager. See the
tmux wiki
for platform-specific instructions.
iTerm2
: install the
it2
CLI
, then enable the Python API in
iTerm2 → Settings → General → Magic → Enable Python API
.
​
Specify teammates and models
Claude decides the number of teammates to spawn based on your task, or you can specify exactly what you want:
Create a team with 4 teammates to refactor these modules in parallel.
Use Sonnet for each teammate.
Teammates don’t inherit the lead’s
/model
selection by default. To change the model used when the prompt doesn’t specify one, set
Default teammate model
in
/config
. Pick
Default (leader’s model)
to have teammates follow the lead’s current model.
​
Require plan approval for teammates
For complex or risky tasks, you can require teammates to plan before implementing. The teammate works in read-only plan mode until the lead approves their approach:
Spawn an architect teammate to refactor the authentication module.
Require plan approval before they make any changes.
When a teammate finishes planning, it sends a plan approval request to the lead. The lead reviews the plan and either approves it or rejects it with feedback. If rejected, the teammate stays in plan mode, revises based on the feedback, and resubmits. Once approved, the teammate exits plan mode and begins implementation.
The lead makes approval decisions autonomously. To influence the lead’s judgment, give it criteria in your prompt, such as “only approve plans that include test coverage” or “reject plans that modify the database schema.”
​
Talk to teammates directly
Each teammate is a full, independent Claude Code session. You can message any teammate directly to give additional instructions, ask follow-up questions, or redirect their approach.
In-process mode
: use Shift+Down to cycle through teammates, then type to send them a message. Press Enter to view a teammate’s session, then Escape to interrupt their current turn. Press Ctrl+T to toggle the task list.
Split-pane mode
: click into a teammate’s pane to interact with their session directly. Each teammate has a full view of their own terminal.
​
Assign and claim tasks
The shared task list coordinates work across the team. The lead creates tasks and teammates work through them. Tasks have three states: pending, in progress, and completed. Tasks can also depend on other tasks: a pending task with unresolved dependencies cannot be claimed until those dependencies are completed.
The lead can assign tasks explicitly, or teammates can self-claim:
Lead assigns
: tell the lead which task to give to which teammate
Self-claim
: after finishing a task, a teammate picks up the next unassigned, unblocked task on its own
Task claiming uses file locking to prevent race conditions when multiple teammates try to claim the same task simultaneously.
​
Shut down teammates
To gracefully end a teammate’s session:
Ask the researcher teammate to shut down
The lead sends a shutdown request. The teammate can approve, exiting gracefully, or reject with an explanation.
​
Clean up the team
When you’re done, ask the lead to clean up:
Clean up the team
This removes the shared team resources. When the lead runs cleanup, it checks for active teammates and fails if any are still running, so shut them down first.
Always use the lead to clean up. Teammates should not run cleanup because their team context may not resolve correctly, potentially leaving resources in an inconsistent state.
​
Enforce quality gates with hooks
Use
hooks
to enforce rules when teammates finish work or tasks are created or completed:
TeammateIdle
: runs when a teammate is about to go idle. Exit with code 2 to send feedback and keep the teammate working.
TaskCreated
: runs when a task is being created. Exit with code 2 to prevent creation and send feedback.
TaskCompleted
: runs when a task is being marked complete. Exit with code 2 to prevent completion and send feedback.
​
How agent teams work
This section covers the architecture and mechanics behind agent teams. If you want to start using them, see
Control your agent team
above.
​
How Claude starts agent teams
There are two ways agent teams get started:
You request a team
: give Claude a task that benefits from parallel work and explicitly ask for an agent team. Claude creates one based on your instructions.
Claude proposes a team
: if Claude determines your task would benefit from parallel work, it may suggest creating a team. You confirm before it proceeds.
In both cases, you stay in control. Claude won’t create a team without your approval.
​
Architecture
An agent team consists of:
Component
Role
Team lead
The main Claude Code session that creates the team, spawns teammates, and coordinates work
Teammates
Separate Claude Code instances that each work on assigned tasks
Task list
Shared list of work items that teammates claim and complete
Mailbox
Messaging system for communication between agents
See
Choose a display mode
for display configuration options. Teammate messages arrive at the lead automatically.
The system manages task dependencies automatically. When a teammate completes a task that other tasks depend on, blocked tasks unblock without manual intervention.
Teams and tasks are stored locally:
Team config
:
~/.claude/teams/{team-name}/config.json
Task list
:
~/.claude/tasks/{team-name}/
Claude Code generates both of these automatically when you create a team and updates them as teammates join, go idle, or leave. The team config holds runtime state such as session IDs and tmux pane IDs, so don’t edit it by hand or pre-author it: your changes are overwritten on the next state update.
To define reusable teammate roles, use
subagent definitions
instead.
The team config contains a
members
array with each teammate’s name, agent ID, and agent type. Teammates can read this file to discover other team members.
There is no project-level equivalent of the team config. A file like
.claude/teams/teams.json
in your project directory is not recognized as configuration; Claude treats it as an ordinary file.
​
Use subagent definitions for teammates
When spawning a teammate, you can reference a
subagent
type from any
subagent scope
: project, user, plugin, or CLI-defined. This lets you define a role once, such as a security-reviewer or test-runner, and reuse it both as a delegated subagent and as an agent team teammate.
To use a subagent definition, mention it by name when asking Claude to spawn the teammate:
Spawn a teammate using the security-reviewer agent type to audit the auth module.
The teammate honors that definition’s
tools
allowlist and
model
, and the definition’s body is appended to the teammate’s system prompt as additional instructions rather than replacing it. Team coordination tools such as
SendMessage
and the task management tools are always available to a teammate even when
tools
restricts other tools.
The
skills
and
mcpServers
frontmatter fields in a subagent definition are not applied when that definition runs as a teammate. Teammates load skills and MCP servers from your project and user settings, the same as a regular session.
​
Permissions
Teammates start with the lead’s permission settings. If the lead runs with
--dangerously-skip-permissions
, all teammates do too. After spawning, you can change individual teammate modes, but you can’t set per-teammate modes at spawn time.
​
Context and communication
Each teammate has its own context window. When spawned, a teammate loads the same project context as a regular session: CLAUDE.md, MCP servers, and skills. It also receives the spawn prompt from the lead. The lead’s conversation history does not carry over.
How teammates share information:
Automatic message delivery
: when teammates send messages, they’re delivered automatically to recipients. The lead doesn’t need to poll for updates.
Idle notifications
: when a teammate finishes and stops, they automatically notify the lead.
Shared task list
: all agents can see task status and claim available work.
Teammate messaging
: send a message to one specific teammate by name. To reach everyone, send one message per recipient.
The lead assigns every teammate a name when it spawns them, and any teammate can message any other by that name. To get predictable names you can reference in later prompts, tell the lead what to call each teammate in your spawn instruction.
​
Token usage
Agent teams use significantly more tokens than a single session. Each teammate has its own context window, and token usage scales with the number of active teammates. For research, review, and new feature work, the extra tokens are usually worthwhile. For routine tasks, a single session is more cost-effective. See
agent team token costs
for usage guidance.
​
Use case examples
These examples show how agent teams handle tasks where parallel exploration adds value.
​
Run a parallel code review
A single reviewer tends to gravitate toward one type of issue at a time. Splitting review criteria into independent domains means security, performance, and test coverage all get thorough attention simultaneously. The prompt assigns each teammate a distinct lens so they don’t overlap:
Create an agent team to review PR #142. Spawn three reviewers:
- One focused on security implications
- One checking performance impact
- One validating test coverage
Have them each review and report findings.
Each reviewer works from the same PR but applies a different filter. The lead synthesizes findings across all three after they finish.
​
Investigate with competing hypotheses
When the root cause is unclear, a single agent tends to find one plausible explanation and stop looking. The prompt fights this by making teammates explicitly adversarial: each one’s job is not only to investigate its own theory but to challenge the others’.
Users report the app exits after one message instead of staying connected.
Spawn 5 agent teammates to investigate different hypotheses. Have them talk to
each other to try to disprove each other's theories, like a scientific
debate. Update the findings doc with whatever consensus emerges.
The debate structure is the key mechanism here. Sequential investigation suffers from anchoring: once one theory is explored, subsequent investigation is biased toward it.
With multiple independent investigators actively trying to disprove each other, the theory that survives is much more likely to be the actual root cause.
​
Best practices
​
Give teammates enough context
Teammates load project context automatically, including CLAUDE.md, MCP servers, and skills, but they don’t inherit the lead’s conversation history. See
Context and communication
for details. Include task-specific details in the spawn prompt:
Spawn a security reviewer teammate with the prompt: "Review the authentication module
at src/auth/ for security vulnerabilities. Focus on token handling, session
management, and input validation. The app uses JWT tokens stored in
httpOnly cookies. Report any issues with severity ratings."
​
Choose an appropriate team size
There’s no hard limit on the number of teammates, but practical constraints apply:
Token costs scale linearly
: each teammate has its own context window and consumes tokens independently. See
agent team token costs
for details.
Coordination overhead increases
: more teammates means more communication, task coordination, and potential for conflicts
Diminishing returns
: beyond a certain point, additional teammates don’t speed up work proportionally
Start with 3-5 teammates for most workflows. This balances parallel work with manageable coordination. The examples in this guide use 3-5 teammates because that range works well across different task types.
Having 5-6
tasks
per teammate keeps everyone productive without excessive context switching. If you have 15 independent tasks, 3 teammates is a good starting point.
Scale up only when the work genuinely benefits from having teammates work simultaneously. Three focused teammates often outperform five scattered ones.
​
Size tasks appropriately
Too small
: coordination overhead exceeds the benefit
Too large
: teammates work too long without check-ins, increasing risk of wasted effort
Just right
: self-contained units that produce a clear deliverable, such as a function, a test file, or a review
The lead breaks work into tasks and assigns them to teammates automatically. If it isn’t creating enough tasks, ask it to split the work into smaller pieces. Having 5-6 tasks per teammate keeps everyone productive and lets the lead reassign work if someone gets stuck.
​
Wait for teammates to finish
Sometimes the lead starts implementing tasks itself instead of waiting for teammates. If you notice this:
Wait for your teammates to complete their tasks before proceeding
​
Start with research and review
If you’re new to agent teams, start with tasks that have clear boundaries and don’t require writing code: reviewing a PR, researching a library, or investigating a bug. These tasks show the value of parallel exploration without the coordination challenges that come with parallel implementation.
​
Avoid file conflicts
Two teammates editing the same file leads to overwrites. Break the work so each teammate owns a different set of files.
​
Monitor and steer
Check in on teammates’ progress, redirect approaches that aren’t working, and synthesize findings as they come in. Letting a team run unattended for too long increases the risk of wasted effort.
​
Troubleshooting
​
Teammates not appearing
If teammates aren’t appearing after you ask Claude to create a team:
In in-process mode, teammates may already be running but not visible. Press Shift+Down to cycle through active teammates.
Check that the task you gave Claude was complex enough to warrant a team. Claude decides whether to spawn teammates based on the task.
If you explicitly requested split panes, ensure tmux is installed and available in your PATH:
which
tmux
For iTerm2, verify the
it2
CLI is installed and the Python API is enabled in iTerm2 preferences.
​
Too many permission prompts
Teammate permission requests bubble up to the lead, which can create friction. Pre-approve common operations in your
permission settings
before spawning teammates to reduce interruptions.
​
Teammates stopping on errors
Teammates may stop after encountering errors instead of recovering. Check their output using Shift+Down in in-process mode or by clicking the pane in split mode, then either:
Give them additional instructions directly
Spawn a replacement teammate to continue the work
​
Lead shuts down before work is done
The lead may decide the team is finished before all tasks are actually complete. If this happens, tell it to keep going. You can also tell the lead to wait for teammates to finish before proceeding if it starts doing work instead of delegating.
​
Orphaned tmux sessions
If a tmux session persists after the team ends, it may not have been fully cleaned up. List sessions and kill the one created by the team:
tmux
ls
tmux
kill-session
-t
<
session-nam
e
>
​
Limitations
Agent teams are experimental. Current limitations to be aware of:
No session resumption with in-process teammates
:
/resume
and
/rewind
do not restore in-process teammates. After resuming a session, the lead may attempt to message teammates that no longer exist. If this happens, tell the lead to spawn new teammates.
Task status can lag
: teammates sometimes fail to mark tasks as completed, which blocks dependent tasks. If a task appears stuck, check whether the work is actually done and update the task status manually or tell the lead to nudge the teammate.
Shutdown can be slow
: teammates finish their current request or tool call before shutting down, which can take time.
One team at a time
: a lead can only manage one team. Clean up the current team before creating a new one.
No nested teams
: teammates cannot spawn their own teams or teammates. Only the lead can manage the team.
Lead is fixed
: the session that creates the team is the lead for its lifetime. You can’t promote a teammate to lead or transfer leadership.
Permissions set at spawn
: all teammates start with the lead’s permission mode. You can change individual teammate modes after spawning, but you can’t set per-teammate modes at spawn time.
Split panes require tmux or iTerm2
: the default in-process mode works in any terminal. Split-pane mode isn’t supported in VS Code’s integrated terminal, Windows Terminal, or Ghostty.
CLAUDE.md
works normally
: teammates read
CLAUDE.md
files from their working directory. Use this to provide project-specific guidance to all teammates.
​
Next steps
Explore related approaches for parallel work and delegation:
Lightweight delegation
:
subagents
spawn helper agents for research or verification within your session, better for tasks that don’t need inter-agent coordination
Manual parallel sessions
:
Git worktrees
let you run multiple Claude Code sessions yourself without automated team coordination
Compare approaches
: see the
subagent vs agent team
comparison for a side-by-side breakdown
Was this page helpful?
Yes
No
Agent view
Isolate sessions with worktrees
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-teams" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Orchestrate teams of Claude Code sessions
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usa...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Orchestrate teams of Claude Code sessions
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Agent teams are experimental and disabled by default. Enable them by adding
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
to your
settings.json
or environment. Agent teams have
known limitations
around session resumption, task coordination, and shutdown behavior.
Agent teams let you coordinate multiple Claude Code instances working together. One session acts as the team lead, coordinating work, assigning tasks, and synthesizing results. Teammates work independently, each in its own context window, and communicate directly with each other.
Unlike
subagents
, which run within a single session and can only report back to the main agent, you can also interact with individual teammates directly without going through the lead.
Agent teams require Claude Code v2.1.32 or later. Check your version with
claude --version
.
This page covers:
When to use agent teams
, including best use cases and how they compare with subagents
Starting a team
Controlling teammates
, including display modes, task assignment, and delegation
Best practices for parallel work
​
When to use agent teams
Agent teams are most effective for tasks where parallel exploration adds real value. See
use case examples
for full scenarios. The strongest use cases are:
Research and review
: multiple teammates can investigate different aspects of a problem simultaneously, then share and challenge each other’s findings
New modules or features
: teammates can each own a separate piece without stepping on each other
Debugging with competing hypotheses
: teammates test different theories in parallel and converge on the answer faster
Cross-layer coordination
: changes that span frontend, backend, and tests, each owned by a different teammate
Agent teams add coordination overhead and use significantly more tokens than a single session. They work best when teammates can operate independently. For sequential tasks, same-file edits, or work with many dependencies, a single session or
subagents
are more effective.
​
Compare with subagents
Both agent teams and
subagents
let you parallelize work, but they operate differently. Choose based on whether your workers need to communicate with each other:
Subagents only report results back to the main agent and never talk to each other. In agent teams, teammates share a task list, claim work, and communicate directly with each other.
Subagents
Agent teams
Context
Own context window; results return to the caller
Own context window; fully independent
Communication
Report results back to the main agent only
Teammates message each other directly
Coordination
Main agent manages all work
Shared task list with self-coordination
Best for
Focused tasks where only the result matters
Complex work requiring discussion and collaboration
Token cost
Lower: results summarized back to main context
Higher: each teammate is a separate Claude instance
Use subagents when you need quick, focused workers that report back. Use agent teams when teammates need to share findings, challenge each other, and coordinate on their own.
​
Enable agent teams
Agent teams are disabled by default. Enable them by setting the
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
environment variable to
1
, either in your shell environment or through
settings.json
:
settings.json
{
"env"
: {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS"
:
"1"
}
}
​
Start your first agent team
After enabling agent teams, tell Claude to create an agent team and describe the task and the team structure you want in natural language. Claude creates the team, spawns teammates, and coordinates work based on your prompt.
This example works well because the three roles are independent and can explore the problem without waiting on each other:
I'm designing a CLI tool that helps developers track TODO comments across
their codebase. Create an agent team to explore this from different angles: one
teammate on UX, one on technical architecture, one playing devil's advocate.
From there, Claude creates a team with a
shared task list
, spawns teammates for each perspective, has them explore the problem, synthesizes findings, and attempts to
clean up the team
when finished.
The lead’s terminal lists all teammates and what they’re working on. Use Shift+Down to cycle through teammates and message them directly. After the last teammate, Shift+Down wraps back to the lead.
If you want each teammate in its own split pane, see
Choose a display mode
.
​
Control your agent team
Tell the lead what you want in natural language. It handles team coordination, task assignment, and delegation based on your instructions.
​
Choose a display mode
Agent teams support two display modes:
In-process
: all teammates run inside your main terminal. Use Shift+Down to cycle through teammates and type to message them directly. Works in any terminal, no extra setup required.
Split panes
: each teammate gets its own pane. You can see everyone’s output at once and click into a pane to interact directly. Requires tmux, or iTerm2.
tmux
has known limitations on certain operating systems and traditionally works best on macOS. Using
tmux -CC
in iTerm2 is the suggested entrypoint into
tmux
.
The default is
"auto"
, which uses split panes if you’re already running inside a tmux session, and in-process otherwise. The
"tmux"
setting enables split-pane mode and auto-detects whether to use tmux or iTerm2 based on your terminal. To override, set
teammateMode
in
~/.claude/settings.json
:
{
"teammateMode"
:
"in-process"
}
To force in-process mode for a single session, pass it as a flag:
claude
--teammate-mode
in-process
Split-pane mode requires either
tmux
or iTerm2 with the
it2
CLI
. To install manually:
tmux
: install through your system’s package manager. See the
tmux wiki
for platform-specific instructions.
iTerm2
: install the
it2
CLI
, then enable the Python API in
iTerm2 → Settings → General → Magic → Enable Python API
.
​
Specify teammates and models
Claude decides the number of teammates to spawn based on your task, or you can specify exactly what you want:
Create a team with 4 teammates to refactor these modules in parallel.
Use Sonnet for each teammate.
Teammates don’t inherit the lead’s
/model
selection by default. To change the model used when the prompt doesn’t specify one, set
Default teammate model
in
/config
. Pick
Default (leader’s model)
to have teammates follow the lead’s current model.
​
Require plan approval for teammates
For complex or risky tasks, you can require teammates to plan before implementing. The teammate works in read-only plan mode until the lead approves their approach:
Spawn an architect teammate to refactor the authentication module.
Require plan approval before they make any changes.
When a teammate finishes planning, it sends a plan approval request to the lead. The lead reviews the plan and either approves it or rejects it with feedback. If rejected, the teammate stays in plan mode, revises based on the feedback, and resubmits. Once approved, the teammate exits plan mode and begins implementation.
The lead makes approval decisions autonomously. To influence the lead’s judgment, give it criteria in your prompt, such as “only approve plans that include test coverage” or “reject plans that modify the database schema.”
​
Talk to teammates directly
Each teammate is a full, independent Claude Code session. You can message any teammate directly to give additional instructions, ask follow-up questions, or redirect their approach.
In-process mode
: use Shift+Down to cycle through teammates, then type to send them a message. Press Enter to view a teammate’s session, then Escape to interrupt their current turn. Press Ctrl+T to toggle the task list.
Split-pane mode
: click into a teammate’s pane to interact with their session directly. Each teammate has a full view of their own terminal.
​
Assign and claim tasks
The shared task list coordinates work across the team. The lead creates tasks and teammates work through them. Tasks have three states: pending, in progress, and completed. Tasks can also depend on other tasks: a pending task with unresolved dependencies cannot be claimed until those dependencies are completed.
The lead can assign tasks explicitly, or teammates can self-claim:
Lead assigns
: tell the lead which task to give to which teammate
Self-claim
: after finishing a task, a teammate picks up the next unassigned, unblocked task on its own
Task claiming uses file locking to prevent race conditions when multiple teammates try to claim the same task simultaneously.
​
Shut down teammates
To gracefully end a teammate’s session:
Ask the researcher teammate to shut down
The lead sends a shutdown request. The teammate can approve, exiting gracefully, or reject with an explanation.
​
Clean up the team
When you’re done, ask the lead to clean up:
Clean up the team
This removes the shared team resources. When the lead runs cleanup, it checks for active teammates and fails if any are still running, so shut them down first.
Always use the lead to clean up. Teammates should not run cleanup because their team context may not resolve correctly, potentially leaving resources in an inconsistent state.
​
Enforce quality gates with hooks
Use
hooks
to enforce rules when teammates finish work or tasks are created or completed:
TeammateIdle
: runs when a teammate is about to go idle. Exit with code 2 to send feedback and keep the teammate working.
TaskCreated
: runs when a task is being created. Exit with code 2 to prevent creation and send feedback.
TaskCompleted
: runs when a task is being marked complete. Exit with code 2 to prevent completion and send feedback.
​
How agent teams work
This section covers the architecture and mechanics behind agent teams. If you want to start using them, see
Control your agent team
above.
​
How Claude starts agent teams
There are two ways agent teams get started:
You request a team
: give Claude a task that benefits from parallel work and explicitly ask for an agent team. Claude creates one based on your instructions.
Claude proposes a team
: if Claude determines your task would benefit from parallel work, it may suggest creating a team. You confirm before it proceeds.
In both cases, you stay in control. Claude won’t create a team without your approval.
​
Architecture
An agent team consists of:
Component
Role
Team lead
The main Claude Code session that creates the team, spawns teammates, and coordinates work
Teammates
Separate Claude Code instances that each work on assigned tasks
Task list
Shared list of work items that teammates claim and complete
Mailbox
Messaging system for communication between agents
See
Choose a display mode
for display configuration options. Teammate messages arrive at the lead automatically.
The system manages task dependencies automatically. When a teammate completes a task that other tasks depend on, blocked tasks unblock without manual intervention.
Teams and tasks are stored locally:
Team config
:
~/.claude/teams/{team-name}/config.json
Task list
:
~/.claude/tasks/{team-name}/
Claude Code generates both of these automatically when you create a team and updates them as teammates join, go idle, or leave. The team config holds runtime state such as session IDs and tmux pane IDs, so don’t edit it by hand or pre-author it: your changes are overwritten on the next state update.
To define reusable teammate roles, use
subagent definitions
instead.
The team config contains a
members
array with each teammate’s name, agent ID, and agent type. Teammates can read this file to discover other team members.
There is no project-level equivalent of the team config. A file like
.claude/teams/teams.json
in your project directory is not recognized as configuration; Claude treats it as an ordinary file.
​
Use subagent definitions for teammates
When spawning a teammate, you can reference a
subagent
type from any
subagent scope
: project, user, plugin, or CLI-defined. This lets you define a role once, such as a security-reviewer or test-runner, and reuse it both as a delegated subagent and as an agent team teammate.
To use a subagent definition, mention it by name when asking Claude to spawn the teammate:
Spawn a teammate using the security-reviewer agent type to audit the auth module.
The teammate honors that definition’s
tools
allowlist and
model
, and the definition’s body is appended to the teammate’s system prompt as additional instructions rather than replacing it. Team coordination tools such as
SendMessage
and the task management tools are always available to a teammate even when
tools
restricts other tools.
The
skills
and
mcpServers
frontmatter fields in a subagent definition are not applied when that definition runs as a teammate. Teammates load skills and MCP servers from your project and user settings, the same as a regular session.
​
Permissions
Teammates start with the lead’s permission settings. If the lead runs with
--dangerously-skip-permissions
, all teammates do too. After spawning, you can change individual teammate modes, but you can’t set per-teammate modes at spawn time.
​
Context and communication
Each teammate has its own context window. When spawned, a teammate loads the same project context as a regular session: CLAUDE.md, MCP servers, and skills. It also receives the spawn prompt from the lead. The lead’s conversation history does not carry over.
How teammates share information:
Automatic message delivery
: when teammates send messages, they’re delivered automatically to recipients. The lead doesn’t need to poll for updates.
Idle notifications
: when a teammate finishes and stops, they automatically notify the lead.
Shared task list
: all agents can see task status and claim available work.
Teammate messaging
: send a message to one specific teammate by name. To reach everyone, send one message per recipient.
The lead assigns every teammate a name when it spawns them, and any teammate can message any other by that name. To get predictable names you can reference in later prompts, tell the lead what to call each teammate in your spawn instruction.
​
Token usage
Agent teams use significantly more tokens than a single session. Each teammate has its own context window, and token usage scales with the number of active teammates. For research, review, and new feature work, the extra tokens are usually worthwhile. For routine tasks, a single session is more cost-effective. See
agent team token costs
for usage guidance.
​
Use case examples
These examples show how agent teams handle tasks where parallel exploration adds value.
​
Run a parallel code review
A single reviewer tends to gravitate toward one type of issue at a time. Splitting review criteria into independent domains means security, performance, and test coverage all get thorough attention simultaneously. The prompt assigns each teammate a distinct lens so they don’t overlap:
Create an agent team to review PR #142. Spawn three reviewers:
- One focused on security implications
- One checking performance impact
- One validating test coverage
Have them each review and report findings.
Each reviewer works from the same PR but applies a different filter. The lead synthesizes findings across all three after they finish.
​
Investigate with competing hypotheses
When the root cause is unclear, a single agent tends to find one plausible explanation and stop looking. The prompt fights this by making teammates explicitly adversarial: each one’s job is not only to investigate its own theory but to challenge the others’.
Users report the app exits after one message instead of staying connected.
Spawn 5 agent teammates to investigate different hypotheses. Have them talk to
each other to try to disprove each other's theories, like a scientific
debate. Update the findings doc with whatever consensus emerges.
The debate structure is the key mechanism here. Sequential investigation suffers from anchoring: once one theory is explored, subsequent investigation is biased toward it.
With multiple independent investigators actively trying to disprove each other, the theory that survives is much more likely to be the actual root cause.
​
Best practices
​
Give teammates enough context
Teammates load project context automatically, including CLAUDE.md, MCP servers, and skills, but they don’t inherit the lead’s conversation history. See
Context and communication
for details. Include task-specific details in the spawn prompt:
Spawn a security reviewer teammate with the prompt: "Review the authentication module
at src/auth/ for security vulnerabilities. Focus on token handling, session
management, and input validation. The app uses JWT tokens stored in
httpOnly cookies. Report any issues with severity ratings."
​
Choose an appropriate team size
There’s no hard limit on the number of teammates, but practical constraints apply:
Token costs scale linearly
: each teammate has its own context window and consumes tokens independently. See
agent team token costs
for details.
Coordination overhead increases
: more teammates means more communication, task coordination, and potential for conflicts
Diminishing returns
: beyond a certain point, additional teammates don’t speed up work proportionally
Start with 3-5 teammates for most workflows. This balances parallel work with manageable coordination. The examples in this guide use 3-5 teammates because that range works well across different task types.
Having 5-6
tasks
per teammate keeps everyone productive without excessive context switching. If you have 15 independent tasks, 3 teammates is a good starting point.
Scale up only when the work genuinely benefits from having teammates work simultaneously. Three focused teammates often outperform five scattered ones.
​
Size tasks appropriately
Too small
: coordination overhead exceeds the benefit
Too large
: teammates work too long without check-ins, increasing risk of wasted effort
Just right
: self-contained units that produce a clear deliverable, such as a function, a test file, or a review
The lead breaks work into tasks and assigns them to teammates automatically. If it isn’t creating enough tasks, ask it to split the work into smaller pieces. Having 5-6 tasks per teammate keeps everyone productive and lets the lead reassign work if someone gets stuck.
​
Wait for teammates to finish
Sometimes the lead starts implementing tasks itself instead of waiting for teammates. If you notice this:
Wait for your teammates to complete their tasks before proceeding
​
Start with research and review
If you’re new to agent teams, start with tasks that have clear boundaries and don’t require writing code: reviewing a PR, researching a library, or investigating a bug. These tasks show the value of parallel exploration without the coordination challenges that come with parallel implementation.
​
Avoid file conflicts
Two teammates editing the same file leads to overwrites. Break the work so each teammate owns a different set of files.
​
Monitor and steer
Check in on teammates’ progress, redirect approaches that aren’t working, and synthesize findings as they come in. Letting a team run unattended for too long increases the risk of wasted effort.
​
Troubleshooting
​
Teammates not appearing
If teammates aren’t appearing after you ask Claude to create a team:
In in-process mode, teammates may already be running but not visible. Press Shift+Down to cycle through active teammates.
Check that the task you gave Claude was complex enough to warrant a team. Claude decides whether to spawn teammates based on the task.
If you explicitly requested split panes, ensure tmux is installed and available in your PATH:
which
tmux
For iTerm2, verify the
it2
CLI is installed and the Python API is enabled in iTerm2 preferences.
​
Too many permission prompts
Teammate permission requests bubble up to the lead, which can create friction. Pre-approve common operations in your
permission settings
before spawning teammates to reduce interruptions.
​
Teammates stopping on errors
Teammates may stop after encountering errors instead of recovering. Check their output using Shift+Down in in-process mode or by clicking the pane in split mode, then either:
Give them additional instructions directly
Spawn a replacement teammate to continue the work
​
Lead shuts down before work is done
The lead may decide the team is finished before all tasks are actually complete. If this happens, tell it to keep going. You can also tell the lead to wait for teammates to finish before proceeding if it starts doing work instead of delegating.
​
Orphaned tmux sessions
If a tmux session persists after the team ends, it may not have been fully cleaned up. List sessions and kill the one created by the team:
tmux
ls
tmux
kill-session
-t
<
session-nam
e
>
​
Limitations
Agent teams are experimental. Current limitations to be aware of:
No session resumption with in-process teammates
:
/resume
and
/rewind
do not restore in-process teammates. After resuming a session, the lead may attempt to message teammates that no longer exist. If this happens, tell the lead to spawn new teammates.
Task status can lag
: teammates sometimes fail to mark tasks as completed, which blocks dependent tasks. If a task appears stuck, check whether the work is actually done and update the task status manually or tell the lead to nudge the teammate.
Shutdown can be slow
: teammates finish their current request or tool call before shutting down, which can take time.
One team at a time
: a lead can only manage one team. Clean up the current team before creating a new one.
No nested teams
: teammates cannot spawn their own teams or teammates. Only the lead can manage the team.
Lead is fixed
: the session that creates the team is the lead for its lifetime. You can’t promote a teammate to lead or transfer leadership.
Permissions set at spawn
: all teammates start with the lead’s permission mode. You can change individual teammate modes after spawning, but you can’t set per-teammate modes at spawn time.
Split panes require tmux or iTerm2
: the default in-process mode works in any terminal. Split-pane mode isn’t supported in VS Code’s integrated terminal, Windows Terminal, or Ghostty.
CLAUDE.md
works normally
: teammates read
CLAUDE.md
files from their working directory. Use this to provide project-specific guidance to all teammates.
​
Next steps
Explore related approaches for parallel work and delegation:
Lightweight delegation
:
subagents
spawn helper agents for research or verification within your session, better for tasks that don’t need inter-agent coordination
Manual parallel sessions
:
Git worktrees
let you run multiple Claude Code sessions yourself without automated team coordination
Compare approaches
: see the
subagent vs agent team
comparison for a side-by-side breakdown
Was this page helpful?
Yes
No
Agent view
Isolate sessions with worktrees
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-teams" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Explore the context window</title>
  <link>https://code.claude.com/docs/en/context-window</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/context-window</guid>
  <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the context window
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Com...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the context window
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code’s context window holds everything Claude knows about your session: your instructions, the files it reads, its own responses, and content that never appears in your terminal. The timeline below walks through what loads and when. See
the written breakdown
for the same content as a list.
This interactive timeline works best on a larger screen. See
the written breakdown below
for the same concepts.
Explore the context window
A simulated session showing what enters context and what it costs
~0
tokens
/ 200K · illustrative
System
CLAUDE.md
Memory
Skills
MCP
Rules
You
Files
Output
Claude
Hooks
= appears in your terminal
$
claude
▶
Start session
Watch what loads into context, from the moment you run
claude
through a full conversation.
👁
Hover or click any event
Hover to preview. Click to pin so you can scroll.
Key takeaway
A lot loads before you type anything. CLAUDE.md, memory, skills, and MCP tools are all in context before your first prompt.
In your terminal you see
The input box, waiting for your first message. Everything above loads silently before you type anything.
▶
0%
⛶
​
What the timeline shows
The session walks through a realistic flow with representative token counts:
Before you type anything
: CLAUDE.md, auto memory, MCP tool names, and skill descriptions all load into context. Your own setup may add more here, like an
output style
or text from
--append-system-prompt
, which both go into the system prompt the same way.
As Claude works
: each file read adds to context,
path-scoped rules
load automatically alongside matching files, and a
PostToolUse hook
fires after each edit.
The follow-up prompt
: a
subagent
handles the research in its own separate context window, so the large file reads stay out of yours. Only the summary and a small metadata trailer come back.
At the end
:
/compact
replaces the conversation with a structured summary. Most startup content reloads automatically; the table below shows what happens to each mechanism.
​
What survives compaction
When a long session compacts, Claude Code summarizes the conversation history to fit the context window. What happens to your instructions depends on how they were loaded:
Mechanism
After compaction
System prompt and output style
Unchanged; not part of message history
Project-root CLAUDE.md and unscoped rules
Re-injected from disk
Auto memory
Re-injected from disk
Rules with
paths:
frontmatter
Lost until a matching file is read again
Nested CLAUDE.md in subdirectories
Lost until a file in that subdirectory is read again
Invoked skill bodies
Re-injected, capped at 5,000 tokens per skill and 25,000 tokens total; oldest dropped first
Hooks
Not applicable; hooks run as code, not context
Path-scoped rules and nested CLAUDE.md files load into message history when their trigger file is read, so compaction summarizes them away with everything else. They reload the next time Claude reads a matching file. If a rule must persist across compaction, drop the
paths:
frontmatter or move it to the project-root CLAUDE.md.
Skill bodies are re-injected after compaction, but large skills are truncated to fit the per-skill cap, and the oldest invoked skills are dropped once the total budget is exceeded. Truncation keeps the start of the file, so put the most important instructions near the top of
SKILL.md
.
​
Check your own session
The visualization uses representative numbers. To see your actual context usage at any point, run
/context
for a live breakdown by category with optimization suggestions. Run
/memory
to check which CLAUDE.md and auto memory files loaded at startup.
​
Related resources
For deeper coverage of the features shown in the timeline, see these pages:
Extend Claude Code
: when to use CLAUDE.md vs skills vs rules vs hooks vs MCP
Store instructions and memories
: CLAUDE.md hierarchy and auto memory
Subagents
: delegate research to a separate context window
Best practices
: managing context as your primary constraint
Reduce token usage
: strategies for keeping context usage low
Was this page helpful?
Yes
No
Explore the .claude directory
Store instructions and memories
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/context-window" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the context window
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Com...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the context window
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code’s context window holds everything Claude knows about your session: your instructions, the files it reads, its own responses, and content that never appears in your terminal. The timeline below walks through what loads and when. See
the written breakdown
for the same content as a list.
This interactive timeline works best on a larger screen. See
the written breakdown below
for the same concepts.
Explore the context window
A simulated session showing what enters context and what it costs
~0
tokens
/ 200K · illustrative
System
CLAUDE.md
Memory
Skills
MCP
Rules
You
Files
Output
Claude
Hooks
= appears in your terminal
$
claude
▶
Start session
Watch what loads into context, from the moment you run
claude
through a full conversation.
👁
Hover or click any event
Hover to preview. Click to pin so you can scroll.
Key takeaway
A lot loads before you type anything. CLAUDE.md, memory, skills, and MCP tools are all in context before your first prompt.
In your terminal you see
The input box, waiting for your first message. Everything above loads silently before you type anything.
▶
0%
⛶
​
What the timeline shows
The session walks through a realistic flow with representative token counts:
Before you type anything
: CLAUDE.md, auto memory, MCP tool names, and skill descriptions all load into context. Your own setup may add more here, like an
output style
or text from
--append-system-prompt
, which both go into the system prompt the same way.
As Claude works
: each file read adds to context,
path-scoped rules
load automatically alongside matching files, and a
PostToolUse hook
fires after each edit.
The follow-up prompt
: a
subagent
handles the research in its own separate context window, so the large file reads stay out of yours. Only the summary and a small metadata trailer come back.
At the end
:
/compact
replaces the conversation with a structured summary. Most startup content reloads automatically; the table below shows what happens to each mechanism.
​
What survives compaction
When a long session compacts, Claude Code summarizes the conversation history to fit the context window. What happens to your instructions depends on how they were loaded:
Mechanism
After compaction
System prompt and output style
Unchanged; not part of message history
Project-root CLAUDE.md and unscoped rules
Re-injected from disk
Auto memory
Re-injected from disk
Rules with
paths:
frontmatter
Lost until a matching file is read again
Nested CLAUDE.md in subdirectories
Lost until a file in that subdirectory is read again
Invoked skill bodies
Re-injected, capped at 5,000 tokens per skill and 25,000 tokens total; oldest dropped first
Hooks
Not applicable; hooks run as code, not context
Path-scoped rules and nested CLAUDE.md files load into message history when their trigger file is read, so compaction summarizes them away with everything else. They reload the next time Claude reads a matching file. If a rule must persist across compaction, drop the
paths:
frontmatter or move it to the project-root CLAUDE.md.
Skill bodies are re-injected after compaction, but large skills are truncated to fit the per-skill cap, and the oldest invoked skills are dropped once the total budget is exceeded. Truncation keeps the start of the file, so put the most important instructions near the top of
SKILL.md
.
​
Check your own session
The visualization uses representative numbers. To see your actual context usage at any point, run
/context
for a live breakdown by category with optimization suggestions. Run
/memory
to check which CLAUDE.md and auto memory files loaded at startup.
​
Related resources
For deeper coverage of the features shown in the timeline, see these pages:
Extend Claude Code
: when to use CLAUDE.md vs skills vs rules vs hooks vs MCP
Store instructions and memories
: CLAUDE.md hierarchy and auto memory
Subagents
: delegate research to a separate context window
Best practices
: managing context as your primary constraint
Reduce token usage
: strategies for keeping context usage low
Was this page helpful?
Yes
No
Explore the .claude directory
Store instructions and memories
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/context-window" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 17 · April 20–24, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w17</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w17</guid>
  <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 17 · April 20–24, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.114 → v2.1.119
4 features...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 17 · April 20–24, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.114 → v2.1.119
4 features · April 20–24
/ultrareview
research preview
Now in public research preview. Ultrareview runs a fleet of bug-hunting agents in the cloud against your branch or a PR, and findings land back in the CLI or Desktop automatically. Run it before merging critical changes such as auth or data migrations.
Review the branch you’re on:
Claude Code
> /ultrareview
Or point it at a PR:
Claude Code
> /ultrareview 1234
Ultrareview guide
Session recap
CLI
Switch focus away from a session and come back to a one-line recap of what happened while you were gone. Helpful for staying in flow while running several Claude sessions at once.
Generate a recap on demand, or turn the automatic one off from
/config
:
Claude Code
> /recap
Interactive mode: session recap
Custom themes
v2.1.118
Build and switch between named color themes from
/theme
, or hand-edit JSON files in
~/.claude/themes/
. Each theme picks a base preset and overrides only the tokens you care about. Plugins can ship themes too.
Open the theme picker and create a new one:
Claude Code
> /theme
Terminal config: create a custom theme
Claude Code on the web
web
A new look for
claude.ai/code
that matches the redesigned desktop app: sessions sidebar, drag-and-drop layout, and a refreshed routines view. Key parts were rebuilt for quicker responses and a more reliable experience.
Claude Code on the web
Other wins
Vim visual mode
: press
v
for character selection or
V
for line selection in the prompt input, with operators and visual feedback
Hooks can now call MCP tools directly via
type: “mcp_tool”
, so a hook can hit an already-connected server without spawning a process
/cost
and
/stats
are merged into
/usage
; the old names still work as typing shortcuts that open the relevant tab
/config
changes (theme, editor mode, verbose, and similar) now persist to
~/.claude/settings.json
and follow the same project/local/policy precedence as other
settings
Forked subagents
can be enabled on external builds with
CLAUDE_CODE_FORK_SUBAGENT=1
: a fork inherits your full conversation context instead of starting fresh
Default
effort level
for Pro and Max subscribers on Opus 4.6 and Sonnet 4.6 is now
high
(was
medium
)
Native macOS and Linux builds replace the
Glob
and
Grep
tools with embedded
bfs
and
ugrep
available through Bash, for faster searches without a separate tool round-trip
—from-pr
now accepts GitLab merge request, Bitbucket pull request, and GitHub Enterprise PR URLs in addition to github.com
Auto mode: include
“$defaults”
in
autoMode.allow
,
soft_deny
, or
environment
to add custom rules alongside the built-in list instead of replacing it
New
claude plugin tag
command creates release git tags for plugins with version validation
Opus 4.7 sessions now compute against the model’s native 1M context window, fixing inflated
/context
percentages and premature autocompaction
/resume
on large sessions is up to 67% faster and now offers to summarize stale, large sessions before re-reading them
Full changelog for v2.1.114–v2.1.119 →
Was this page helpful?
Yes
No
Week 18 · Apr 27 – May 1
Week 16 · Apr 13–17
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w17" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 17 · April 20–24, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.114 → v2.1.119
4 features...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 17 · April 20–24, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.114 → v2.1.119
4 features · April 20–24
/ultrareview
research preview
Now in public research preview. Ultrareview runs a fleet of bug-hunting agents in the cloud against your branch or a PR, and findings land back in the CLI or Desktop automatically. Run it before merging critical changes such as auth or data migrations.
Review the branch you’re on:
Claude Code
> /ultrareview
Or point it at a PR:
Claude Code
> /ultrareview 1234
Ultrareview guide
Session recap
CLI
Switch focus away from a session and come back to a one-line recap of what happened while you were gone. Helpful for staying in flow while running several Claude sessions at once.
Generate a recap on demand, or turn the automatic one off from
/config
:
Claude Code
> /recap
Interactive mode: session recap
Custom themes
v2.1.118
Build and switch between named color themes from
/theme
, or hand-edit JSON files in
~/.claude/themes/
. Each theme picks a base preset and overrides only the tokens you care about. Plugins can ship themes too.
Open the theme picker and create a new one:
Claude Code
> /theme
Terminal config: create a custom theme
Claude Code on the web
web
A new look for
claude.ai/code
that matches the redesigned desktop app: sessions sidebar, drag-and-drop layout, and a refreshed routines view. Key parts were rebuilt for quicker responses and a more reliable experience.
Claude Code on the web
Other wins
Vim visual mode
: press
v
for character selection or
V
for line selection in the prompt input, with operators and visual feedback
Hooks can now call MCP tools directly via
type: “mcp_tool”
, so a hook can hit an already-connected server without spawning a process
/cost
and
/stats
are merged into
/usage
; the old names still work as typing shortcuts that open the relevant tab
/config
changes (theme, editor mode, verbose, and similar) now persist to
~/.claude/settings.json
and follow the same project/local/policy precedence as other
settings
Forked subagents
can be enabled on external builds with
CLAUDE_CODE_FORK_SUBAGENT=1
: a fork inherits your full conversation context instead of starting fresh
Default
effort level
for Pro and Max subscribers on Opus 4.6 and Sonnet 4.6 is now
high
(was
medium
)
Native macOS and Linux builds replace the
Glob
and
Grep
tools with embedded
bfs
and
ugrep
available through Bash, for faster searches without a separate tool round-trip
—from-pr
now accepts GitLab merge request, Bitbucket pull request, and GitHub Enterprise PR URLs in addition to github.com
Auto mode: include
“$defaults”
in
autoMode.allow
,
soft_deny
, or
environment
to add custom rules alongside the built-in list instead of replacing it
New
claude plugin tag
command creates release git tags for plugins with version validation
Opus 4.7 sessions now compute against the model’s native 1M context window, fixing inflated
/context
percentages and premature autocompaction
/resume
on large sessions is up to 67% faster and now offers to summarize stale, large sessions before re-reading them
Full changelog for v2.1.114–v2.1.119 →
Was this page helpful?
Yes
No
Week 18 · Apr 27 – May 1
Week 16 · Apr 13–17
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w17" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Fullscreen rendering</title>
  <link>https://code.claude.com/docs/en/fullscreen</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/fullscreen</guid>
  <pubDate>Sun, 24 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Fullscreen rendering
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to disco...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Fullscreen rendering
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Fullscreen rendering is an opt-in
research preview
and requires Claude Code v2.1.89 or later. Run
/tui fullscreen
to switch in your current conversation, or set
CLAUDE_CODE_NO_FLICKER=1
on versions before v2.1.110. Behavior may change based on feedback.
Fullscreen rendering is an alternative rendering path for the Claude Code CLI that eliminates flicker, keeps memory usage flat in long conversations, and adds mouse support. It draws the interface on the terminal’s alternate screen buffer, like
vim
or
htop
, and only renders messages that are currently visible. This reduces the amount of data sent to your terminal on each update.
The difference is most noticeable in terminal emulators where rendering throughput is the bottleneck, such as the VS Code integrated terminal, tmux, and iTerm2. If your terminal scroll position jumps to the top while Claude is working, or the screen flashes as tool output streams in, this mode addresses those.
The term fullscreen describes how Claude Code takes over the terminal’s drawing surface, the way
vim
does. It has nothing to do with maximizing your terminal window, and works at any window size.
​
Enable fullscreen rendering
Run
/tui fullscreen
inside any Claude Code conversation. The CLI saves the
tui
setting
and relaunches into fullscreen with your conversation intact, so you can switch mid-session without losing context. Run
/tui
with no argument to print which renderer is active.
You can also set the
CLAUDE_CODE_NO_FLICKER
environment variable before starting Claude Code:
CLAUDE_CODE_NO_FLICKER
=
1
claude
The
tui
setting and the environment variable are equivalent. The
/tui
command clears
CLAUDE_CODE_NO_FLICKER
from the relaunched process so the setting it writes takes effect.
​
What changes
Fullscreen rendering changes how the CLI draws to your terminal. The input box stays fixed at the bottom of the screen instead of moving as output streams in. If the input stays put while Claude is working, fullscreen rendering is active. Only visible messages are kept in the render tree, so memory stays constant regardless of conversation length.
Because the conversation lives in the alternate screen buffer instead of your terminal’s scrollback, a few things work differently:
Before
Now
Details
Cmd+f
or tmux search to find text
Ctrl+o
for transcript mode, then
/
to search or
[
to write to scrollback
Search and review the conversation
Terminal’s native click-and-drag to select and copy
In-app selection, copies automatically on mouse release
Use the mouse
Cmd
-click to open a URL
Click the URL
Use the mouse
If mouse capture interferes with your workflow, you can
turn it off
while keeping the flicker-free rendering.
​
Use the mouse
Fullscreen rendering captures mouse events and handles them inside Claude Code:
Click in the prompt input
to position your cursor anywhere in the text you’re typing.
Click a collapsed tool result
to expand it and see the full output. Click again to collapse. The tool call and its result expand together. Only messages that have more to show are clickable.
Click a URL or file path
to open it. File paths in tool output, like the ones printed after an Edit or Write, open in your default application. Plain
http://
and
https://
URLs open in your browser. In most terminals this replaces native
Cmd
-click or
Ctrl
-click, which mouse capture intercepts. In the VS Code integrated terminal and similar xterm.js-based terminals, keep using
Cmd
-click. Claude Code defers to the terminal’s own link handler there to avoid opening links twice.
Click and drag
to select text anywhere in the conversation. Double-click selects a word, matching iTerm2’s word boundaries so a file path selects as one unit. Triple-click selects the line.
Scroll with the mouse wheel
to move through the conversation.
Selected text copies to your clipboard automatically on mouse release. To turn this off, toggle Copy on select in
/config
. With it off, press
Ctrl+Shift+c
to copy manually. On terminals that support the kitty keyboard protocol, such as kitty, WezTerm, Ghostty, and iTerm2,
Cmd+c
also works. If you have a selection active,
Ctrl+c
copies instead of cancelling.
With a selection active, hold
Shift
and press the arrow keys to extend it from the keyboard.
Shift+↑
and
Shift+↓
scroll the viewport when the selection reaches the top or bottom edge.
Shift+Home
and
Shift+End
extend to the start or end of the current line.
​
Scroll the conversation
Fullscreen rendering handles scrolling inside the app. Use these shortcuts to navigate:
Shortcut
Action
PgUp
/
PgDn
Scroll up or down by half a screen
Ctrl+Home
Jump to the start of the conversation
Ctrl+End
Jump to the latest message and re-enable auto-follow
Mouse wheel
Scroll a few lines at a time
On keyboards without dedicated
PgUp
,
PgDn
,
Home
, or
End
keys, like MacBook keyboards, hold
Fn
with the arrow keys:
Fn+↑
sends
PgUp
,
Fn+↓
sends
PgDn
,
Fn+←
sends
Home
, and
Fn+→
sends
End
. That makes
Ctrl+Fn+→
the jump-to-bottom shortcut. If that feels awkward, scroll to the bottom with the mouse wheel to resume following, or rebind
scroll:bottom
to something reachable.
These actions are rebindable. See
Scroll actions
for the full list of action names, including half-page and full-page variants that have no default binding.
​
Auto-follow
Scrolling up pauses auto-follow so new output does not pull you back to the bottom. Press
Ctrl+End
or scroll to the bottom to resume following.
To turn auto-follow off entirely so the view stays where you leave it, open
/config
and set Auto-scroll to off. With auto-scroll disabled, the view never jumps to the bottom on its own. Permission prompts and other dialogs that need a response still scroll into view regardless of this setting.
​
Mouse wheel scrolling
Mouse wheel scrolling requires your terminal to forward mouse events to Claude Code. Most terminals do this whenever an application requests it. iTerm2 makes it a per-profile setting: if the wheel does nothing but
PgUp
and
PgDn
work, open Settings → Profiles → Terminal and turn on Enable mouse reporting. The same setting is also required for click-to-expand and text selection to work.
If mouse wheel scrolling feels slow, your terminal may be sending one scroll event per physical notch with no multiplier. Some terminals, like Ghostty and iTerm2 with faster scrolling enabled, already amplify wheel events. Others, including the VS Code integrated terminal, send exactly one event per notch. Claude Code cannot detect which.
Set
CLAUDE_CODE_SCROLL_SPEED
to multiply the base scroll distance:
export
CLAUDE_CODE_SCROLL_SPEED
=
3
A value of
3
matches the default in
vim
and similar applications. The setting accepts values from 1 to 20.
To adjust scroll speed interactively, run
/scroll-speed
. The dialog shows a ruler you can scroll while it is open so you can feel the change immediately. Press
←
and
→
to adjust,
r
to reset to the auto-detected default, and
Enter
to save. The command writes the same value the
CLAUDE_CODE_SCROLL_SPEED
environment variable sets, persisted to
~/.claude/settings.json
. The command is not available in the JetBrains IDE terminal.
​
Scroll in the JetBrains IDE terminal
In the JetBrains IDE terminal, Claude Code applies its own scroll handling and ignores
CLAUDE_CODE_SCROLL_SPEED
. The terminal sends scroll events at a much higher rate than other emulators, so a multiplier tuned elsewhere overshoots here.
In 2025.2, the terminal also has scroll-wheel bugs that produce spurious arrow keys and wrong-direction events. Claude Code detects these at runtime and mitigates them automatically, so trackpad and mouse wheel scrolling work without configuration. For the best scroll experience, upgrade to 2025.3 or later. Claude Code shows a hint the first time you scroll if it detects the bug.
​
Search and review the conversation
Ctrl+o
toggles between the normal prompt and transcript mode. For a quieter view that shows only your last prompt, a one-line summary of tool calls with edit diffstats, and the final response, run
/focus
. The setting persists across sessions. Run
/focus
again to turn it off.
Transcript mode gains
less
-style navigation and search:
Key
Action
/
Open search. Type to find matches,
Enter
to accept,
Esc
to cancel and restore your scroll position
n
/
N
Jump to next or previous match. Works after you’ve closed the search bar
j
/
k
or
↑
/
↓
Scroll one line
g
/
G
or
Home
/
End
Jump to top or bottom
Ctrl+u
/
Ctrl+d
Scroll half a page
Ctrl+b
/
Ctrl+f
or
Space
/
b
Scroll a full page
Ctrl+o
,
Esc
, or
q
Exit transcript mode and return to the prompt
Your terminal’s
Cmd+f
and tmux search don’t see the conversation because it lives in the alternate screen buffer, not the native scrollback. To hand the content back to your terminal, press
Ctrl+o
to enter transcript mode first, then:
[
: writes the full conversation into your terminal’s native scrollback buffer, with all tool output expanded. The conversation is now ordinary text in your terminal, so
Cmd+f
, tmux copy mode, and any other native tool can search or select it. Long sessions may pause for a moment while this happens. This lasts until you exit transcript mode with
Esc
or
q
, which returns you to fullscreen rendering. The next
Ctrl+o
starts fresh.
v
: writes the conversation to a temporary file and opens it in
$VISUAL
or
$EDITOR
.
Press
Esc
or
q
to return to the prompt.
​
Clear the conversation
Press
Ctrl+L
twice within two seconds to run
/clear
and start a new conversation. The first press redraws the screen and shows a hint; the second press clears the conversation. On macOS, double-pressing
Cmd+K
also runs
/clear
.
​
Use with tmux
Fullscreen rendering works inside tmux, with three caveats.
Mouse wheel scrolling requires tmux’s mouse mode. If your
~/.tmux.conf
does not already enable it, add this line and reload your config:
set
-g
mouse
on
Without mouse mode, wheel events go to tmux instead of Claude Code. Keyboard scrolling with
PgUp
and
PgDn
works either way. Claude Code prints a one-time hint at startup if it detects tmux with mouse mode off.
Fullscreen rendering is incompatible with iTerm2’s tmux integration mode, which is the mode you enter with
tmux -CC
. In integration mode, iTerm2 renders each tmux pane as a native split rather than letting tmux draw to the terminal. The alternate screen buffer and mouse tracking do not work correctly there: the mouse wheel does nothing, and double-click can corrupt the terminal state. Don’t enable fullscreen rendering in
tmux -CC
sessions. Regular tmux inside iTerm2, without
-CC
, works fine.
tmux does not support synchronized output, so you may see more flicker during redraws than when running Claude Code directly in your terminal. If the flicker is noticeable, especially over SSH, run Claude Code in its own terminal tab outside tmux.
​
Keep native text selection
Mouse capture is the most common friction point, especially over SSH or inside tmux. When Claude Code captures mouse events, your terminal’s native copy-on-select stops working. The selection you make with click-and-drag exists inside Claude Code, not in your terminal’s selection buffer, so tmux copy mode, Kitty hints, and similar tools don’t see it.
Claude Code tries to write the selection to your clipboard, but the path it uses depends on your setup. Inside tmux it writes to the tmux paste buffer. Over SSH it falls back to OSC 52 escape sequences, which some terminals block by default. iTerm2 blocks them until you turn on Settings → General → Selection → Applications in terminal may access clipboard. Running
/terminal-setup
in iTerm2 enables this for you. Claude Code prints a toast after each copy telling you which path it used.
For a one-off native selection, hold your terminal’s bypass modifier while you click and drag:
Option
in iTerm2, or
Shift
in most Linux and Windows terminals. The modifier tells your terminal to handle the selection itself instead of forwarding mouse events to Claude Code, so
Cmd+C
and your terminal’s other copy shortcuts work on it.
If you rely on native selection all the time, set
CLAUDE_CODE_DISABLE_MOUSE=1
to opt out of mouse capture while keeping the flicker-free rendering and flat memory:
CLAUDE_CODE_NO_FLICKER
=
1
CLAUDE_CODE_DISABLE_MOUSE
=
1
claude
With mouse capture disabled, keyboard scrolling with
PgUp
,
PgDn
,
Ctrl+Home
, and
Ctrl+End
still works, and your terminal handles selection natively. You lose click-to-position-cursor, click-to-expand tool output, URL clicking, and wheel scrolling inside Claude Code.
​
Research preview
Fullscreen rendering is a research preview feature. It has been tested on common terminal emulators, but you may encounter rendering issues on less common terminals or unusual configurations.
If you encounter a problem, run
/feedback
inside Claude Code to report it, or open an issue on the
claude-code GitHub repo
. Include your terminal emulator name and version.
To turn fullscreen rendering off, run
/tui default
, or unset
CLAUDE_CODE_NO_FLICKER
if you enabled it that way. To force the classic renderer regardless of the saved
tui
setting, set
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1
. The classic renderer keeps the conversation in your terminal’s native scrollback so
Cmd+f
and tmux copy mode work as usual.
Was this page helpful?
Yes
No
Terminal configuration
Voice dictation
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/fullscreen" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Fullscreen rendering
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to disco...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Fullscreen rendering
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Fullscreen rendering is an opt-in
research preview
and requires Claude Code v2.1.89 or later. Run
/tui fullscreen
to switch in your current conversation, or set
CLAUDE_CODE_NO_FLICKER=1
on versions before v2.1.110. Behavior may change based on feedback.
Fullscreen rendering is an alternative rendering path for the Claude Code CLI that eliminates flicker, keeps memory usage flat in long conversations, and adds mouse support. It draws the interface on the terminal’s alternate screen buffer, like
vim
or
htop
, and only renders messages that are currently visible. This reduces the amount of data sent to your terminal on each update.
The difference is most noticeable in terminal emulators where rendering throughput is the bottleneck, such as the VS Code integrated terminal, tmux, and iTerm2. If your terminal scroll position jumps to the top while Claude is working, or the screen flashes as tool output streams in, this mode addresses those.
The term fullscreen describes how Claude Code takes over the terminal’s drawing surface, the way
vim
does. It has nothing to do with maximizing your terminal window, and works at any window size.
​
Enable fullscreen rendering
Run
/tui fullscreen
inside any Claude Code conversation. The CLI saves the
tui
setting
and relaunches into fullscreen with your conversation intact, so you can switch mid-session without losing context. Run
/tui
with no argument to print which renderer is active.
You can also set the
CLAUDE_CODE_NO_FLICKER
environment variable before starting Claude Code:
CLAUDE_CODE_NO_FLICKER
=
1
claude
The
tui
setting and the environment variable are equivalent. The
/tui
command clears
CLAUDE_CODE_NO_FLICKER
from the relaunched process so the setting it writes takes effect.
​
What changes
Fullscreen rendering changes how the CLI draws to your terminal. The input box stays fixed at the bottom of the screen instead of moving as output streams in. If the input stays put while Claude is working, fullscreen rendering is active. Only visible messages are kept in the render tree, so memory stays constant regardless of conversation length.
Because the conversation lives in the alternate screen buffer instead of your terminal’s scrollback, a few things work differently:
Before
Now
Details
Cmd+f
or tmux search to find text
Ctrl+o
for transcript mode, then
/
to search or
[
to write to scrollback
Search and review the conversation
Terminal’s native click-and-drag to select and copy
In-app selection, copies automatically on mouse release
Use the mouse
Cmd
-click to open a URL
Click the URL
Use the mouse
If mouse capture interferes with your workflow, you can
turn it off
while keeping the flicker-free rendering.
​
Use the mouse
Fullscreen rendering captures mouse events and handles them inside Claude Code:
Click in the prompt input
to position your cursor anywhere in the text you’re typing.
Click a collapsed tool result
to expand it and see the full output. Click again to collapse. The tool call and its result expand together. Only messages that have more to show are clickable.
Click a URL or file path
to open it. File paths in tool output, like the ones printed after an Edit or Write, open in your default application. Plain
http://
and
https://
URLs open in your browser. In most terminals this replaces native
Cmd
-click or
Ctrl
-click, which mouse capture intercepts. In the VS Code integrated terminal and similar xterm.js-based terminals, keep using
Cmd
-click. Claude Code defers to the terminal’s own link handler there to avoid opening links twice.
Click and drag
to select text anywhere in the conversation. Double-click selects a word, matching iTerm2’s word boundaries so a file path selects as one unit. Triple-click selects the line.
Scroll with the mouse wheel
to move through the conversation.
Selected text copies to your clipboard automatically on mouse release. To turn this off, toggle Copy on select in
/config
. With it off, press
Ctrl+Shift+c
to copy manually. On terminals that support the kitty keyboard protocol, such as kitty, WezTerm, Ghostty, and iTerm2,
Cmd+c
also works. If you have a selection active,
Ctrl+c
copies instead of cancelling.
With a selection active, hold
Shift
and press the arrow keys to extend it from the keyboard.
Shift+↑
and
Shift+↓
scroll the viewport when the selection reaches the top or bottom edge.
Shift+Home
and
Shift+End
extend to the start or end of the current line.
​
Scroll the conversation
Fullscreen rendering handles scrolling inside the app. Use these shortcuts to navigate:
Shortcut
Action
PgUp
/
PgDn
Scroll up or down by half a screen
Ctrl+Home
Jump to the start of the conversation
Ctrl+End
Jump to the latest message and re-enable auto-follow
Mouse wheel
Scroll a few lines at a time
On keyboards without dedicated
PgUp
,
PgDn
,
Home
, or
End
keys, like MacBook keyboards, hold
Fn
with the arrow keys:
Fn+↑
sends
PgUp
,
Fn+↓
sends
PgDn
,
Fn+←
sends
Home
, and
Fn+→
sends
End
. That makes
Ctrl+Fn+→
the jump-to-bottom shortcut. If that feels awkward, scroll to the bottom with the mouse wheel to resume following, or rebind
scroll:bottom
to something reachable.
These actions are rebindable. See
Scroll actions
for the full list of action names, including half-page and full-page variants that have no default binding.
​
Auto-follow
Scrolling up pauses auto-follow so new output does not pull you back to the bottom. Press
Ctrl+End
or scroll to the bottom to resume following.
To turn auto-follow off entirely so the view stays where you leave it, open
/config
and set Auto-scroll to off. With auto-scroll disabled, the view never jumps to the bottom on its own. Permission prompts and other dialogs that need a response still scroll into view regardless of this setting.
​
Mouse wheel scrolling
Mouse wheel scrolling requires your terminal to forward mouse events to Claude Code. Most terminals do this whenever an application requests it. iTerm2 makes it a per-profile setting: if the wheel does nothing but
PgUp
and
PgDn
work, open Settings → Profiles → Terminal and turn on Enable mouse reporting. The same setting is also required for click-to-expand and text selection to work.
If mouse wheel scrolling feels slow, your terminal may be sending one scroll event per physical notch with no multiplier. Some terminals, like Ghostty and iTerm2 with faster scrolling enabled, already amplify wheel events. Others, including the VS Code integrated terminal, send exactly one event per notch. Claude Code cannot detect which.
Set
CLAUDE_CODE_SCROLL_SPEED
to multiply the base scroll distance:
export
CLAUDE_CODE_SCROLL_SPEED
=
3
A value of
3
matches the default in
vim
and similar applications. The setting accepts values from 1 to 20.
To adjust scroll speed interactively, run
/scroll-speed
. The dialog shows a ruler you can scroll while it is open so you can feel the change immediately. Press
←
and
→
to adjust,
r
to reset to the auto-detected default, and
Enter
to save. The command writes the same value the
CLAUDE_CODE_SCROLL_SPEED
environment variable sets, persisted to
~/.claude/settings.json
. The command is not available in the JetBrains IDE terminal.
​
Scroll in the JetBrains IDE terminal
In the JetBrains IDE terminal, Claude Code applies its own scroll handling and ignores
CLAUDE_CODE_SCROLL_SPEED
. The terminal sends scroll events at a much higher rate than other emulators, so a multiplier tuned elsewhere overshoots here.
In 2025.2, the terminal also has scroll-wheel bugs that produce spurious arrow keys and wrong-direction events. Claude Code detects these at runtime and mitigates them automatically, so trackpad and mouse wheel scrolling work without configuration. For the best scroll experience, upgrade to 2025.3 or later. Claude Code shows a hint the first time you scroll if it detects the bug.
​
Search and review the conversation
Ctrl+o
toggles between the normal prompt and transcript mode. For a quieter view that shows only your last prompt, a one-line summary of tool calls with edit diffstats, and the final response, run
/focus
. The setting persists across sessions. Run
/focus
again to turn it off.
Transcript mode gains
less
-style navigation and search:
Key
Action
/
Open search. Type to find matches,
Enter
to accept,
Esc
to cancel and restore your scroll position
n
/
N
Jump to next or previous match. Works after you’ve closed the search bar
j
/
k
or
↑
/
↓
Scroll one line
g
/
G
or
Home
/
End
Jump to top or bottom
Ctrl+u
/
Ctrl+d
Scroll half a page
Ctrl+b
/
Ctrl+f
or
Space
/
b
Scroll a full page
Ctrl+o
,
Esc
, or
q
Exit transcript mode and return to the prompt
Your terminal’s
Cmd+f
and tmux search don’t see the conversation because it lives in the alternate screen buffer, not the native scrollback. To hand the content back to your terminal, press
Ctrl+o
to enter transcript mode first, then:
[
: writes the full conversation into your terminal’s native scrollback buffer, with all tool output expanded. The conversation is now ordinary text in your terminal, so
Cmd+f
, tmux copy mode, and any other native tool can search or select it. Long sessions may pause for a moment while this happens. This lasts until you exit transcript mode with
Esc
or
q
, which returns you to fullscreen rendering. The next
Ctrl+o
starts fresh.
v
: writes the conversation to a temporary file and opens it in
$VISUAL
or
$EDITOR
.
Press
Esc
or
q
to return to the prompt.
​
Clear the conversation
Press
Ctrl+L
twice within two seconds to run
/clear
and start a new conversation. The first press redraws the screen and shows a hint; the second press clears the conversation. On macOS, double-pressing
Cmd+K
also runs
/clear
.
​
Use with tmux
Fullscreen rendering works inside tmux, with three caveats.
Mouse wheel scrolling requires tmux’s mouse mode. If your
~/.tmux.conf
does not already enable it, add this line and reload your config:
set
-g
mouse
on
Without mouse mode, wheel events go to tmux instead of Claude Code. Keyboard scrolling with
PgUp
and
PgDn
works either way. Claude Code prints a one-time hint at startup if it detects tmux with mouse mode off.
Fullscreen rendering is incompatible with iTerm2’s tmux integration mode, which is the mode you enter with
tmux -CC
. In integration mode, iTerm2 renders each tmux pane as a native split rather than letting tmux draw to the terminal. The alternate screen buffer and mouse tracking do not work correctly there: the mouse wheel does nothing, and double-click can corrupt the terminal state. Don’t enable fullscreen rendering in
tmux -CC
sessions. Regular tmux inside iTerm2, without
-CC
, works fine.
tmux does not support synchronized output, so you may see more flicker during redraws than when running Claude Code directly in your terminal. If the flicker is noticeable, especially over SSH, run Claude Code in its own terminal tab outside tmux.
​
Keep native text selection
Mouse capture is the most common friction point, especially over SSH or inside tmux. When Claude Code captures mouse events, your terminal’s native copy-on-select stops working. The selection you make with click-and-drag exists inside Claude Code, not in your terminal’s selection buffer, so tmux copy mode, Kitty hints, and similar tools don’t see it.
Claude Code tries to write the selection to your clipboard, but the path it uses depends on your setup. Inside tmux it writes to the tmux paste buffer. Over SSH it falls back to OSC 52 escape sequences, which some terminals block by default. iTerm2 blocks them until you turn on Settings → General → Selection → Applications in terminal may access clipboard. Running
/terminal-setup
in iTerm2 enables this for you. Claude Code prints a toast after each copy telling you which path it used.
For a one-off native selection, hold your terminal’s bypass modifier while you click and drag:
Option
in iTerm2, or
Shift
in most Linux and Windows terminals. The modifier tells your terminal to handle the selection itself instead of forwarding mouse events to Claude Code, so
Cmd+C
and your terminal’s other copy shortcuts work on it.
If you rely on native selection all the time, set
CLAUDE_CODE_DISABLE_MOUSE=1
to opt out of mouse capture while keeping the flicker-free rendering and flat memory:
CLAUDE_CODE_NO_FLICKER
=
1
CLAUDE_CODE_DISABLE_MOUSE
=
1
claude
With mouse capture disabled, keyboard scrolling with
PgUp
,
PgDn
,
Ctrl+Home
, and
Ctrl+End
still works, and your terminal handles selection natively. You lose click-to-position-cursor, click-to-expand tool output, URL clicking, and wheel scrolling inside Claude Code.
​
Research preview
Fullscreen rendering is a research preview feature. It has been tested on common terminal emulators, but you may encounter rendering issues on less common terminals or unusual configurations.
If you encounter a problem, run
/feedback
inside Claude Code to report it, or open an issue on the
claude-code GitHub repo
. Include your terminal emulator name and version.
To turn fullscreen rendering off, run
/tui default
, or unset
CLAUDE_CODE_NO_FLICKER
if you enabled it that way. To force the classic renderer regardless of the saved
tui
setting, set
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1
. The classic renderer keeps the conversation in your terminal’s native scrollback so
Cmd+f
and tmux copy mode work as usual.
Was this page helpful?
Yes
No
Terminal configuration
Voice dictation
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/fullscreen" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code with GitHub Enterprise Server</title>
  <link>https://code.claude.com/docs/en/github-enterprise-server</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/github-enterprise-server</guid>
  <pubDate>Fri, 22 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code with GitHub Enterprise Server
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code with GitHub Enterprise Server
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
GitHub Enterprise Server support is available for Team and Enterprise plans.
GitHub Enterprise Server (GHES) support lets your organization use Claude Code with repositories hosted on your self-managed GitHub instance instead of github.com. Once an admin connects your GHES instance, developers can run web sessions, get automated code reviews, and install plugins from internal marketplaces without any per-repository configuration.
For repositories on github.com, see
Claude Code on the web
and
Code Review
. To run Claude in your own CI infrastructure, see
GitHub Actions
.
​
What works with GitHub Enterprise Server
The table below shows which Claude Code features support GHES and any differences from github.com behavior.
Feature
GHES support
Notes
Claude Code on the web
✅ Supported
Admin connects the GHES instance once; developers use
claude --remote
or
claude.ai/code
as usual
Code Review
✅ Supported
Same automated PR reviews as github.com
Teleport sessions
✅ Supported
Move sessions between web and terminal with
--teleport
Plugin marketplaces
✅ Supported
Use full git URLs instead of
owner/repo
shorthand
Contribution metrics
✅ Supported
Delivered via webhooks to the
analytics dashboard
GitHub Actions
✅ Supported
Requires manual workflow setup;
/install-github-app
is github.com only
GitHub MCP server
❌ Not supported
The GitHub MCP server does not work with GHES instances
​
Admin setup
An admin connects your GHES instance to Claude Code once. After that, developers in your organization can use GHES repositories without any additional configuration. You need admin access to your Claude organization and permission to create GitHub Apps on your GHES instance.
The guided setup generates a GitHub App manifest and redirects you to your GHES instance to create the app in one click. If your environment blocks the redirect flow, an
alternative manual setup
is available.
1
Open Claude Code admin settings
Go to
claude.ai/admin-settings/claude-code
and find the GitHub Enterprise Server section.
2
Start the guided setup
Click
Connect
. Enter a display name for the connection and your GHES hostname, for example
github.example.com
. If your GHES instance uses a self-signed or private certificate authority, paste the CA certificate in the optional field.
3
Create the GitHub App
Click
Continue to GitHub Enterprise
. Your browser redirects to your GHES instance with a pre-filled app manifest. Review the configuration and click
Create GitHub App
. GHES redirects you back to Claude with the app credentials stored automatically.
4
Install the app on your repositories
From the GitHub App page on your GHES instance, install the app on the repositories or organizations you want Claude to access. You can start with a subset and add more later.
5
Enable features
Return to
claude.ai/admin-settings/claude-code
and enable
Code Review
and
contribution metrics
for your GHES repositories using the same configuration as github.com.
​
GitHub App permissions
The manifest configures the GitHub App with the permissions and webhook events Claude needs across web sessions, Code Review, and contribution metrics:
Permission
Access
Used for
Contents
Read and write
Cloning repositories and pushing branches
Pull requests
Read and write
Creating PRs and posting review comments
Issues
Read and write
Responding to issue mentions
Checks
Read and write
Posting Code Review check runs
Actions
Read
Reading CI status for auto-fix
Repository hooks
Read and write
Receiving webhooks for contribution metrics
Metadata
Read
Required by GitHub for all apps
The app subscribes to
pull_request
,
issue_comment
,
pull_request_review_comment
,
pull_request_review
, and
check_run
events.
​
Manual setup
If the guided redirect flow is blocked by your network configuration, click
Add manually
instead of Connect. Create a GitHub App on your GHES instance with the
permissions and events above
, then enter the app credentials in the form: hostname, OAuth client ID and secret, GitHub App ID, client ID, client secret, webhook secret, and private key.
​
Network requirements
Your GHES instance must be reachable from Anthropic infrastructure so Claude can clone repositories and post review comments. If your GHES instance is behind a firewall, allowlist the
Anthropic API IP addresses
.
​
Developer workflow
Once your admin has connected the GHES instance, no developer-side configuration is needed. Claude Code detects your GHES hostname automatically from the git remote in your working directory.
Clone a repository from your GHES instance as you normally would:
git
clone
git@github.example.com:platform/api-service.git
cd
api-service
Then start a web session. Claude detects the GHES host from your git remote and routes the session through your organization’s configured instance:
claude
--remote
"Add retry logic to the payment webhook handler"
The session runs on Anthropic infrastructure, clones your repository from GHES, and pushes changes back to a branch. Monitor progress with
/tasks
or at
claude.ai/code
. See
Claude Code on the web
for the full remote session workflow including diff review, auto-fix, and routines.
​
Teleport sessions to your terminal
Pull a web session into your local terminal with
claude --teleport
. Teleport verifies you’re in a checkout of the same GHES repository before fetching the branch and loading the session history. See
teleport requirements
for details.
​
Plugin marketplaces on GHES
Host plugin marketplaces on your GHES instance to distribute internal tooling across your organization. The marketplace structure is identical to github.com-hosted marketplaces; the only difference is how you reference them.
​
Add a GHES marketplace
The
owner/repo
shorthand always resolves to github.com. For GHES-hosted marketplaces, use the full git URL:
/plugin
marketplace
add
git@github.example.com:platform/claude-plugins.git
HTTPS URLs work as well:
/plugin
marketplace
add
https://github.example.com/platform/claude-plugins.git
See
Create and distribute a plugin marketplace
for the full guide to building marketplaces.
​
Allowlist GHES marketplaces in managed settings
If your organization uses
managed settings
to restrict which marketplaces developers can add, use the
hostPattern
source type to allow all marketplaces from your GHES instance without enumerating each repository:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
You can also pre-register marketplaces for developers so they appear without manual setup. This example makes an internal tools marketplace available organization-wide:
{
"extraKnownMarketplaces"
: {
"internal-tools"
: {
"source"
: {
"source"
:
"git"
,
"url"
:
"git@github.example.com:platform/claude-plugins.git"
}
}
}
}
See the
strictKnownMarketplaces
and
extraKnownMarketplaces
settings reference for the complete schema.
​
Limitations
A few features behave differently on GHES than on github.com. The
feature table
summarizes support; this section covers the workarounds.
/install-github-app
command
: follow the
admin setup
flow on claude.ai instead. If you also want GitHub Actions workflows on GHES, adapt the
example workflow
manually.
GitHub MCP server
: use the
gh
CLI configured for your GHES host instead. Run
gh auth login --hostname github.example.com
to authenticate, then Claude can use
gh
commands in sessions.
​
Troubleshooting
​
Web session fails to clone repository
If
claude --remote
fails with a clone error, verify that your admin has completed setup for your GHES instance and that the GitHub App is installed on the repository you’re working in. Check with your admin that the instance hostname registered in Claude settings matches the hostname in your git remote.
​
Marketplace add fails with a policy error
If
/plugin marketplace add
is blocked for your GHES URL, your organization has restricted marketplace sources. Ask your admin to add a
hostPattern
entry for your GHES hostname in
managed settings
.
​
GHES instance not reachable
If reviews or web sessions time out, your GHES instance may not be reachable from Anthropic infrastructure. Confirm your firewall allows inbound connections from the
Anthropic API IP addresses
.
​
Related resources
These pages cover the features referenced throughout this guide in more depth:
Claude Code on the web
: run Claude Code sessions on cloud infrastructure
Code Review
: automated PR reviews
Plugin marketplaces
: build and distribute plugin catalogs
Analytics
: track usage and contribution metrics
Managed settings
: organization-wide policy configuration
Network configuration
: firewall and IP allowlist requirements
Was this page helpful?
Yes
No
GitHub Actions
GitLab CI/CD
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/github-enterprise-server" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code with GitHub Enterprise Server
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code with GitHub Enterprise Server
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
GitHub Enterprise Server support is available for Team and Enterprise plans.
GitHub Enterprise Server (GHES) support lets your organization use Claude Code with repositories hosted on your self-managed GitHub instance instead of github.com. Once an admin connects your GHES instance, developers can run web sessions, get automated code reviews, and install plugins from internal marketplaces without any per-repository configuration.
For repositories on github.com, see
Claude Code on the web
and
Code Review
. To run Claude in your own CI infrastructure, see
GitHub Actions
.
​
What works with GitHub Enterprise Server
The table below shows which Claude Code features support GHES and any differences from github.com behavior.
Feature
GHES support
Notes
Claude Code on the web
✅ Supported
Admin connects the GHES instance once; developers use
claude --remote
or
claude.ai/code
as usual
Code Review
✅ Supported
Same automated PR reviews as github.com
Teleport sessions
✅ Supported
Move sessions between web and terminal with
--teleport
Plugin marketplaces
✅ Supported
Use full git URLs instead of
owner/repo
shorthand
Contribution metrics
✅ Supported
Delivered via webhooks to the
analytics dashboard
GitHub Actions
✅ Supported
Requires manual workflow setup;
/install-github-app
is github.com only
GitHub MCP server
❌ Not supported
The GitHub MCP server does not work with GHES instances
​
Admin setup
An admin connects your GHES instance to Claude Code once. After that, developers in your organization can use GHES repositories without any additional configuration. You need admin access to your Claude organization and permission to create GitHub Apps on your GHES instance.
The guided setup generates a GitHub App manifest and redirects you to your GHES instance to create the app in one click. If your environment blocks the redirect flow, an
alternative manual setup
is available.
1
Open Claude Code admin settings
Go to
claude.ai/admin-settings/claude-code
and find the GitHub Enterprise Server section.
2
Start the guided setup
Click
Connect
. Enter a display name for the connection and your GHES hostname, for example
github.example.com
. If your GHES instance uses a self-signed or private certificate authority, paste the CA certificate in the optional field.
3
Create the GitHub App
Click
Continue to GitHub Enterprise
. Your browser redirects to your GHES instance with a pre-filled app manifest. Review the configuration and click
Create GitHub App
. GHES redirects you back to Claude with the app credentials stored automatically.
4
Install the app on your repositories
From the GitHub App page on your GHES instance, install the app on the repositories or organizations you want Claude to access. You can start with a subset and add more later.
5
Enable features
Return to
claude.ai/admin-settings/claude-code
and enable
Code Review
and
contribution metrics
for your GHES repositories using the same configuration as github.com.
​
GitHub App permissions
The manifest configures the GitHub App with the permissions and webhook events Claude needs across web sessions, Code Review, and contribution metrics:
Permission
Access
Used for
Contents
Read and write
Cloning repositories and pushing branches
Pull requests
Read and write
Creating PRs and posting review comments
Issues
Read and write
Responding to issue mentions
Checks
Read and write
Posting Code Review check runs
Actions
Read
Reading CI status for auto-fix
Repository hooks
Read and write
Receiving webhooks for contribution metrics
Metadata
Read
Required by GitHub for all apps
The app subscribes to
pull_request
,
issue_comment
,
pull_request_review_comment
,
pull_request_review
, and
check_run
events.
​
Manual setup
If the guided redirect flow is blocked by your network configuration, click
Add manually
instead of Connect. Create a GitHub App on your GHES instance with the
permissions and events above
, then enter the app credentials in the form: hostname, OAuth client ID and secret, GitHub App ID, client ID, client secret, webhook secret, and private key.
​
Network requirements
Your GHES instance must be reachable from Anthropic infrastructure so Claude can clone repositories and post review comments. If your GHES instance is behind a firewall, allowlist the
Anthropic API IP addresses
.
​
Developer workflow
Once your admin has connected the GHES instance, no developer-side configuration is needed. Claude Code detects your GHES hostname automatically from the git remote in your working directory.
Clone a repository from your GHES instance as you normally would:
git
clone
git@github.example.com:platform/api-service.git
cd
api-service
Then start a web session. Claude detects the GHES host from your git remote and routes the session through your organization’s configured instance:
claude
--remote
"Add retry logic to the payment webhook handler"
The session runs on Anthropic infrastructure, clones your repository from GHES, and pushes changes back to a branch. Monitor progress with
/tasks
or at
claude.ai/code
. See
Claude Code on the web
for the full remote session workflow including diff review, auto-fix, and routines.
​
Teleport sessions to your terminal
Pull a web session into your local terminal with
claude --teleport
. Teleport verifies you’re in a checkout of the same GHES repository before fetching the branch and loading the session history. See
teleport requirements
for details.
​
Plugin marketplaces on GHES
Host plugin marketplaces on your GHES instance to distribute internal tooling across your organization. The marketplace structure is identical to github.com-hosted marketplaces; the only difference is how you reference them.
​
Add a GHES marketplace
The
owner/repo
shorthand always resolves to github.com. For GHES-hosted marketplaces, use the full git URL:
/plugin
marketplace
add
git@github.example.com:platform/claude-plugins.git
HTTPS URLs work as well:
/plugin
marketplace
add
https://github.example.com/platform/claude-plugins.git
See
Create and distribute a plugin marketplace
for the full guide to building marketplaces.
​
Allowlist GHES marketplaces in managed settings
If your organization uses
managed settings
to restrict which marketplaces developers can add, use the
hostPattern
source type to allow all marketplaces from your GHES instance without enumerating each repository:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
You can also pre-register marketplaces for developers so they appear without manual setup. This example makes an internal tools marketplace available organization-wide:
{
"extraKnownMarketplaces"
: {
"internal-tools"
: {
"source"
: {
"source"
:
"git"
,
"url"
:
"git@github.example.com:platform/claude-plugins.git"
}
}
}
}
See the
strictKnownMarketplaces
and
extraKnownMarketplaces
settings reference for the complete schema.
​
Limitations
A few features behave differently on GHES than on github.com. The
feature table
summarizes support; this section covers the workarounds.
/install-github-app
command
: follow the
admin setup
flow on claude.ai instead. If you also want GitHub Actions workflows on GHES, adapt the
example workflow
manually.
GitHub MCP server
: use the
gh
CLI configured for your GHES host instead. Run
gh auth login --hostname github.example.com
to authenticate, then Claude can use
gh
commands in sessions.
​
Troubleshooting
​
Web session fails to clone repository
If
claude --remote
fails with a clone error, verify that your admin has completed setup for your GHES instance and that the GitHub App is installed on the repository you’re working in. Check with your admin that the instance hostname registered in Claude settings matches the hostname in your git remote.
​
Marketplace add fails with a policy error
If
/plugin marketplace add
is blocked for your GHES URL, your organization has restricted marketplace sources. Ask your admin to add a
hostPattern
entry for your GHES hostname in
managed settings
.
​
GHES instance not reachable
If reviews or web sessions time out, your GHES instance may not be reachable from Anthropic infrastructure. Confirm your firewall allows inbound connections from the
Anthropic API IP addresses
.
​
Related resources
These pages cover the features referenced throughout this guide in more depth:
Claude Code on the web
: run Claude Code sessions on cloud infrastructure
Code Review
: automated PR reviews
Plugin marketplaces
: build and distribute plugin catalogs
Analytics
: track usage and contribution metrics
Managed settings
: organization-wide policy configuration
Network configuration
: firewall and IP allowlist requirements
Was this page helpful?
Yes
No
GitHub Actions
GitLab CI/CD
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/github-enterprise-server" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>What&apos;s new</title>
  <link>https://code.claude.com/docs/en/whats-new/index</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/index</guid>
  <pubDate>Sat, 16 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
What&apos;s new
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The weekly dev digest highlights the features most likel...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
What's new
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The weekly dev digest highlights the features most likely to change how you work. Each entry includes runnable code, a short demo, and a link to the full docs. For every bug fix and minor improvement, see the
changelog
.
​
Week 19
v2.1.128–v2.1.136
May 4–8, 2026
Plugins load from
.zip
archives and URLs
:
--plugin-dir
now accepts
.zip
files, and
--plugin-url
fetches a plugin archive for the current session.
Also this week:
worktree.baseRef
chooses whether new worktrees branch from the remote default or local
HEAD
;
auto mode hard deny rules
block actions unconditionally regardless of allow exceptions; and
hooks see the active effort level
via
effort.level
and
$CLAUDE_EFFORT
.
Read the Week 19 digest →
​
Week 18
v2.1.120–v2.1.126
April 27 – May 1, 2026
Windows without Git Bash
: Git for Windows is no longer required, and Claude Code uses PowerShell as the shell tool when Bash is absent.
Also this week:
claude ultrareview
brings cloud code review to CI and scripts;
claude project purge
cleans up local state for a project; and pasting a
PR URL into
/resume
finds the session that created it.
Read the Week 18 digest →
​
Week 17
v2.1.114–v2.1.119
April 20–24, 2026
/ultrareview
opens as a public research preview: a fleet of bug-hunting agents runs in the cloud and findings land back in your CLI or Desktop automatically.
Also this week:
session recap
shows you what happened while a terminal was unfocused;
custom themes
let you build and ship color palettes from
/theme
or a plugin; and
Claude Code on the web
gets a redesign with a new sessions sidebar and drag-and-drop layout.
Read the Week 17 digest →
​
Week 16
v2.1.105–v2.1.113
April 13–17, 2026
Claude Opus 4.7
lands as the new default on Max and Team Premium, with a new
xhigh
effort level that’s the recommended setting for most coding work and an interactive
/effort
slider to dial it in.
Also this week:
Routines
on Claude Code on the web fire templated cloud agents from a schedule, GitHub event, or API call;
mobile push notifications
ping your phone when a long task finishes or Claude needs you;
/usage
shows what’s driving your limits; and the CLI moves to native binaries.
Read the Week 16 digest →
​
Week 15
v2.1.92–v2.1.101
April 6–10, 2026
Ultraplan
enters early preview: draft a plan in the cloud from your CLI, review and comment on it in a web editor, then run it remotely or pull it back local. The first run now auto-creates a cloud environment for you.
Also this week: the
Monitor
tool streams background events into the conversation so Claude can tail logs and react live,
/loop
self-paces when you omit the interval,
/team-onboarding
packages your setup into a replayable guide, and
/autofix-pr
turns on PR auto-fix from your terminal.
Read the Week 15 digest →
​
Week 14
v2.1.86–v2.1.91
March 30 – April 3, 2026
Computer use
comes to the CLI in research preview: Claude can open native apps, click through UI, and verify changes from your terminal. Best for closing the loop on things only a GUI can verify.
Also this week:
/powerup
interactive lessons, flicker-free alt-screen rendering, a per-tool MCP result-size override up to 500K, and plugin executables on the Bash tool’s
PATH
.
Read the Week 14 digest →
​
Week 13
v2.1.83–v2.1.85
March 23–27, 2026
Auto mode
lands in research preview: a classifier handles your permission prompts so safe actions run without interruption and risky ones get blocked. The middle ground between approving everything and
--dangerously-skip-permissions
.
Also this week: computer use in the Desktop app, PR auto-fix on Web, transcript search with
/
, a native PowerShell tool for Windows, and conditional
if
hooks.
Read the Week 13 digest →
Was this page helpful?
Yes
No
Week 19 · May 4–8
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/index" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
What&apos;s new
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The weekly dev digest highlights the features most likel...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
What's new
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The weekly dev digest highlights the features most likely to change how you work. Each entry includes runnable code, a short demo, and a link to the full docs. For every bug fix and minor improvement, see the
changelog
.
​
Week 19
v2.1.128–v2.1.136
May 4–8, 2026
Plugins load from
.zip
archives and URLs
:
--plugin-dir
now accepts
.zip
files, and
--plugin-url
fetches a plugin archive for the current session.
Also this week:
worktree.baseRef
chooses whether new worktrees branch from the remote default or local
HEAD
;
auto mode hard deny rules
block actions unconditionally regardless of allow exceptions; and
hooks see the active effort level
via
effort.level
and
$CLAUDE_EFFORT
.
Read the Week 19 digest →
​
Week 18
v2.1.120–v2.1.126
April 27 – May 1, 2026
Windows without Git Bash
: Git for Windows is no longer required, and Claude Code uses PowerShell as the shell tool when Bash is absent.
Also this week:
claude ultrareview
brings cloud code review to CI and scripts;
claude project purge
cleans up local state for a project; and pasting a
PR URL into
/resume
finds the session that created it.
Read the Week 18 digest →
​
Week 17
v2.1.114–v2.1.119
April 20–24, 2026
/ultrareview
opens as a public research preview: a fleet of bug-hunting agents runs in the cloud and findings land back in your CLI or Desktop automatically.
Also this week:
session recap
shows you what happened while a terminal was unfocused;
custom themes
let you build and ship color palettes from
/theme
or a plugin; and
Claude Code on the web
gets a redesign with a new sessions sidebar and drag-and-drop layout.
Read the Week 17 digest →
​
Week 16
v2.1.105–v2.1.113
April 13–17, 2026
Claude Opus 4.7
lands as the new default on Max and Team Premium, with a new
xhigh
effort level that’s the recommended setting for most coding work and an interactive
/effort
slider to dial it in.
Also this week:
Routines
on Claude Code on the web fire templated cloud agents from a schedule, GitHub event, or API call;
mobile push notifications
ping your phone when a long task finishes or Claude needs you;
/usage
shows what’s driving your limits; and the CLI moves to native binaries.
Read the Week 16 digest →
​
Week 15
v2.1.92–v2.1.101
April 6–10, 2026
Ultraplan
enters early preview: draft a plan in the cloud from your CLI, review and comment on it in a web editor, then run it remotely or pull it back local. The first run now auto-creates a cloud environment for you.
Also this week: the
Monitor
tool streams background events into the conversation so Claude can tail logs and react live,
/loop
self-paces when you omit the interval,
/team-onboarding
packages your setup into a replayable guide, and
/autofix-pr
turns on PR auto-fix from your terminal.
Read the Week 15 digest →
​
Week 14
v2.1.86–v2.1.91
March 30 – April 3, 2026
Computer use
comes to the CLI in research preview: Claude can open native apps, click through UI, and verify changes from your terminal. Best for closing the loop on things only a GUI can verify.
Also this week:
/powerup
interactive lessons, flicker-free alt-screen rendering, a per-tool MCP result-size override up to 500K, and plugin executables on the Bash tool’s
PATH
.
Read the Week 14 digest →
​
Week 13
v2.1.83–v2.1.85
March 23–27, 2026
Auto mode
lands in research preview: a classifier handles your permission prompts so safe actions run without interruption and risky ones get blocked. The middle ground between approving everything and
--dangerously-skip-permissions
.
Also this week: computer use in the Desktop app, PR auto-fix on Web, transcript search with
/
, a native PowerShell tool for Windows, and conditional
if
hooks.
Read the Week 13 digest →
Was this page helpful?
Yes
No
Week 19 · May 4–8
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/index" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Handle approvals and user input</title>
  <link>https://code.claude.com/docs/en/agent-sdk/user-input</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/user-input</guid>
  <pubDate>Sun, 10 Nov 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Handle approvals and user input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Handle approvals and user input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
While working on a task, Claude sometimes needs to check in with users. It might need permission before deleting files, or need to ask which database to use for a new project. Your application needs to surface these requests to users so Claude can continue with their input.
Claude requests user input in two situations: when it needs
permission to use a tool
(like deleting files or running commands), and when it has
clarifying questions
(via the
AskUserQuestion
tool). Both trigger your
canUseTool
callback, which pauses execution until you return a response. This is different from normal conversation turns where Claude finishes and waits for your next message.
For clarifying questions, Claude generates the questions and options. Your role is to present them to users and return their selections. You can’t add your own questions to this flow; if you need to ask users something yourself, do that separately in your application logic.
The callback can stay pending indefinitely. Execution remains paused until your callback returns, and the SDK only cancels the wait when the query itself is cancelled. If a user might take longer to respond than your process can reasonably stay running, return the
defer
hook decision
, which lets the process exit and resume later from the persisted session.
This guide shows you how to detect each type of request and respond appropriately.
​
Detect when Claude needs input
Pass a
canUseTool
callback in your query options. The callback fires whenever Claude needs user input, receiving the tool name and input as arguments:
Python
TypeScript
async
def
handle_tool_request
(
tool_name
,
input_data
,
context
):
# Prompt user and return allow or deny
...
options
=
ClaudeAgentOptions(
can_use_tool
=
handle_tool_request)
The callback fires in two cases:
Tool needs approval
: Claude wants to use a tool that isn’t auto-approved by
permission rules
or modes. Check
tool_name
for the tool (e.g.,
"Bash"
,
"Write"
).
Claude asks a question
: Claude calls the
AskUserQuestion
tool. Check if
tool_name == "AskUserQuestion"
to handle it differently. If you specify a
tools
array, include
AskUserQuestion
for this to work. See
Handle clarifying questions
for details.
To automatically allow or deny tools without prompting users, use
hooks
instead. Hooks execute before
canUseTool
and can allow, deny, or modify requests based on your own logic. You can also use the
PermissionRequest
hook
to send external notifications (Slack, email, push) when Claude is waiting for approval.
​
Handle tool approval requests
Once you’ve passed a
canUseTool
callback in your query options, it fires when Claude wants to use a tool that isn’t auto-approved. Your callback receives three arguments:
Argument
Description
toolName
The name of the tool Claude wants to use (e.g.,
"Bash"
,
"Write"
,
"Edit"
)
input
The parameters Claude is passing to the tool. Contents vary by tool.
options
(TS) /
context
(Python)
Additional context including optional
suggestions
(proposed
PermissionUpdate
entries to avoid re-prompting) and a cancellation signal. In TypeScript,
signal
is an
AbortSignal
; in Python, the signal field is reserved for future use. See
ToolPermissionContext
for Python.
The
input
object contains tool-specific parameters. Common examples:
Tool
Input fields
Bash
command
,
description
,
timeout
Write
file_path
,
content
Edit
file_path
,
old_string
,
new_string
Read
file_path
,
offset
,
limit
See the SDK reference for complete input schemas:
Python
|
TypeScript
.
You can display this information to the user so they can decide whether to allow or reject the action, then return the appropriate response.
The following example asks Claude to create and delete a test file. When Claude attempts each operation, the callback prints the tool request to the terminal and prompts for y/n approval.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeAgentOptions, ResultMessage, query
from
claude_agent_sdk.types
import
(
HookMatcher,
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
# Display the tool request
print
(
f
"
\n
Tool:
{
tool_name
}
"
)
if
tool_name
==
"Bash"
:
print
(
f
"Command:
{
input_data.get(
'command'
)
}
"
)
if
input_data.get(
"description"
):
print
(
f
"Description:
{
input_data.get(
'description'
)
}
"
)
else
:
print
(
f
"Input:
{
input_data
}
"
)
# Get user approval
response
=
input
(
"Allow this action? (y/n): "
)
# Return allow or deny based on user's response
if
response.lower()
==
"y"
:
# Allow: tool executes with the original (or modified) input
return
PermissionResultAllow(
updated_input
=
input_data)
else
:
# Deny: tool doesn't execute, Claude sees the message
return
PermissionResultDeny(
message
=
"User denied this action"
)
# Required workaround: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Create a test file in /tmp and then delete it"
,
},
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
In Python,
can_use_tool
requires
streaming mode
and a
PreToolUse
hook that returns
{"continue_": True}
to keep the stream open. Without this hook, the stream closes before the permission callback can be invoked.
This example uses a
y/n
flow where any input other than
y
is treated as a denial. In practice, you might build a richer UI that lets users modify the request, provide feedback, or redirect Claude entirely. See
Respond to tool requests
for all the ways you can respond.
​
Respond to tool requests
Your callback returns one of two response types:
Response
Python
TypeScript
Allow
PermissionResultAllow(updated_input=...)
{ behavior: "allow", updatedInput }
Deny
PermissionResultDeny(message=...)
{ behavior: "deny", message }
When allowing, pass the tool input (original or modified). When denying, provide a message explaining why. Claude sees this message and may adjust its approach.
Python
TypeScript
from
claude_agent_sdk.types
import
PermissionResultAllow, PermissionResultDeny
# Allow the tool to execute
return
PermissionResultAllow(
updated_input
=
input_data)
# Block the tool
return
PermissionResultDeny(
message
=
"User rejected this action"
)
Beyond allowing or denying, you can modify the tool’s input or provide context that helps Claude adjust its approach:
Approve
: let the tool execute as Claude requested
Approve with changes
: modify the input before execution (e.g., sanitize paths, add constraints)
Approve and remember
: echo a suggested permission rule back so matching calls skip the prompt next time
Reject
: block the tool and tell Claude why
Suggest alternative
: block but guide Claude toward what the user wants instead
Redirect entirely
: use
streaming input
to send Claude a completely new instruction
Approve
Approve with changes
Approve and remember
Reject
Suggest alternative
Redirect entirely
The user approves the action as-is. Pass through the
input
from your callback unchanged and the tool executes exactly as Claude requested.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
print
(
f
"Claude wants to use
{
tool_name
}
"
)
approved
=
await
ask_user(
"Allow this action?"
)
if
approved:
return
PermissionResultAllow(
updated_input
=
input_data)
return
PermissionResultDeny(
message
=
"User declined"
)
The user approves but wants to modify the request first. You can change the input before the tool executes. Claude sees the result but isn’t told you changed anything. Useful for sanitizing parameters, adding constraints, or scoping access.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
if
tool_name
==
"Bash"
:
# User approved, but scope all commands to sandbox
sandboxed_input
=
{
**
input_data}
sandboxed_input[
"command"
]
=
input_data[
"command"
].replace(
"/tmp"
,
"/tmp/sandbox"
)
return
PermissionResultAllow(
updated_input
=
sandboxed_input)
return
PermissionResultAllow(
updated_input
=
input_data)
The user approves and doesn’t want to be asked again for this kind of call. The third callback argument carries
suggestions
, an array of ready-made
PermissionUpdate
entries. Echo one back in
updatedPermissions
to apply it. A suggestion with the
localSettings
destination writes the rule to
.claude/settings.local.json
so future sessions skip the prompt for matching calls.
The Python example requires
claude-agent-sdk
0.1.80 or later.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
choice
=
await
ask_user(
f
"Allow
{
tool_name
}
?"
, [
"once"
,
"always"
,
"no"
])
if
choice
==
"always"
:
persist
=
[
s
for
s
in
context.suggestions
if
s.destination
==
"localSettings"
]
return
PermissionResultAllow(
updated_input
=
input_data,
updated_permissions
=
persist
)
if
choice
==
"once"
:
return
PermissionResultAllow(
updated_input
=
input_data)
return
PermissionResultDeny(
message
=
"User declined"
)
The user doesn’t want this action to happen. Block the tool and provide a message explaining why. Claude sees this message and may try a different approach.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
approved
=
await
ask_user(
f
"Allow
{
tool_name
}
?"
)
if
not
approved:
return
PermissionResultDeny(
message
=
"User rejected this action"
)
return
PermissionResultAllow(
updated_input
=
input_data)
The user doesn’t want this specific action, but has a different idea. Block the tool and include guidance in your message. Claude will read this and decide how to proceed based on your feedback.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
if
tool_name
==
"Bash"
and
"rm"
in
input_data.get(
"command"
,
""
):
# User doesn't want to delete, suggest archiving instead
return
PermissionResultDeny(
message
=
"User doesn't want to delete files. They asked if you could compress them into an archive instead."
)
return
PermissionResultAllow(
updated_input
=
input_data)
For a complete change of direction (not just a nudge), use
streaming input
to send Claude a new instruction directly. This bypasses the current tool request and gives Claude entirely new instructions to follow.
​
Handle clarifying questions
When Claude needs more direction on a task with multiple valid approaches, it calls the
AskUserQuestion
tool. This triggers your
canUseTool
callback with
toolName
set to
AskUserQuestion
. The input contains Claude’s questions as multiple-choice options, which you display to the user and return their selections.
Clarifying questions are especially common in
plan
mode
, where Claude explores the codebase and asks questions before proposing a plan. This makes plan mode ideal for interactive workflows where you want Claude to gather requirements before making changes.
The following steps show how to handle clarifying questions:
1
Pass a canUseTool callback
Pass a
canUseTool
callback in your query options. By default,
AskUserQuestion
is available. If you specify a
tools
array to restrict Claude’s capabilities (for example, a read-only agent with only
Read
,
Glob
, and
Grep
), include
AskUserQuestion
in that array. Otherwise, Claude won’t be able to ask clarifying questions:
Python
TypeScript
async
for
message
in
query(
prompt
=
"Analyze this codebase"
,
options
=
ClaudeAgentOptions(
# Include AskUserQuestion in your tools list
tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"AskUserQuestion"
],
can_use_tool
=
can_use_tool,
),
):
print
(message)
2
Detect AskUserQuestion
In your callback, check if
toolName
equals
AskUserQuestion
to handle it differently from other tools:
Python
TypeScript
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
):
if
tool_name
==
"AskUserQuestion"
:
# Your implementation to collect answers from the user
return
await
handle_clarifying_questions(input_data)
# Handle other tools normally
return
await
prompt_for_approval(tool_name, input_data)
3
Parse the question input
The input contains Claude’s questions in a
questions
array. Each question has a
question
(the text to display),
options
(the choices), and
multiSelect
(whether multiple selections are allowed):
{
"questions"
: [
{
"question"
:
"How should I format the output?"
,
"header"
:
"Format"
,
"options"
: [
{
"label"
:
"Summary"
,
"description"
:
"Brief overview"
},
{
"label"
:
"Detailed"
,
"description"
:
"Full explanation"
}
],
"multiSelect"
:
false
},
{
"question"
:
"Which sections should I include?"
,
"header"
:
"Sections"
,
"options"
: [
{
"label"
:
"Introduction"
,
"description"
:
"Opening context"
},
{
"label"
:
"Conclusion"
,
"description"
:
"Final summary"
}
],
"multiSelect"
:
true
}
]
}
See
Question format
for full field descriptions.
4
Collect answers from the user
Present the questions to the user and collect their selections. How you do this depends on your application: a terminal prompt, a web form, a mobile dialog, etc.
5
Return answers to Claude
Build the
answers
object as a record where each key is the
question
text and each value is the selected option’s
label
:
From the question object
Use as
question
field (e.g.,
"How should I format the output?"
)
Key
Selected option’s
label
field (e.g.,
"Summary"
)
Value
For multi-select questions, pass an array of labels or join them with
", "
. If you
support free-text input
, use the user’s custom text as the value.
Python
TypeScript
return
PermissionResultAllow(
updated_input
=
{
"questions"
: input_data.get(
"questions"
, []),
"answers"
: {
"How should I format the output?"
:
"Summary"
,
"Which sections should I include?"
: [
"Introduction"
,
"Conclusion"
],
},
}
)
​
Question format
The input contains Claude’s generated questions in a
questions
array. Each question has these fields:
Field
Description
question
The full question text to display
header
Short label for the question (max 12 characters)
options
Array of 2-4 choices, each with
label
and
description
. TypeScript: optionally
preview
(see
below
)
multiSelect
If
true
, users can select multiple options
The structure your callback receives:
{
"questions"
: [
{
"question"
:
"How should I format the output?"
,
"header"
:
"Format"
,
"options"
: [
{
"label"
:
"Summary"
,
"description"
:
"Brief overview of key points"
},
{
"label"
:
"Detailed"
,
"description"
:
"Full explanation with examples"
}
],
"multiSelect"
:
false
}
]
}
​
Option previews (TypeScript)
toolConfig.askUserQuestion.previewFormat
adds a
preview
field to each option so your app can show a visual mockup alongside the label. Without this setting, Claude does not generate previews and the field is absent.
previewFormat
preview
contains
unset (default)
Field is absent. Claude does not generate previews.
"markdown"
ASCII art and fenced code blocks
"html"
A styled
<div>
fragment (the SDK rejects
<script>
,
<style>
, and
<!DOCTYPE>
before your callback runs)
The format applies to all questions in the session. Claude includes
preview
on options where a visual comparison helps (layout choices, color schemes) and omits it where one wouldn’t (yes/no confirmations, text-only choices). Check for
undefined
before rendering.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Help me choose a card layout"
,
options:
{
toolConfig:
{
askUserQuestion:
{
previewFormat:
"html"
}
},
canUseTool
:
async
(
toolName
,
input
)
=>
{
// input.questions[].options[].preview is an HTML string or undefined
return
{
behavior:
"allow"
,
updatedInput:
input
};
}
}
})) {
// ...
}
An option with an HTML preview:
{
"label"
:
"Compact"
,
"description"
:
"Title and metric value only"
,
"preview"
:
"<div style=
\"
padding:12px;border:1px solid #ddd;border-radius:8px
\"
><div style=
\"
font-size:12px;color:#666
\"
>Active users</div><div style=
\"
font-size:28px;font-weight:600
\"
>1,284</div></div>"
}
​
Response format
Return an
answers
object mapping each question’s
question
field to the selected option’s
label
:
Field
Description
questions
Pass through the original questions array (required for tool processing)
answers
Object where keys are question text and values are selected labels
For multi-select questions, pass an array of labels or join them with
", "
. For free-text input, use the user’s custom text directly.
{
"questions"
: [
// ...
],
"answers"
: {
"How should I format the output?"
:
"Summary"
,
"Which sections should I include?"
: [
"Introduction"
,
"Conclusion"
]
}
}
​
Support free-text input
Claude’s predefined options won’t always cover what users want. To let users type their own answer:
Display an additional “Other” choice after Claude’s options that accepts text input
Use the user’s custom text as the answer value (not the word “Other”)
See the
complete example
below for a full implementation.
​
Complete example
Claude asks clarifying questions when it needs user input to proceed. For example, when asked to help decide on a tech stack for a mobile app, Claude might ask about cross-platform vs native, backend preferences, or target platforms. These questions help Claude make decisions that match the user’s preferences rather than guessing.
This example handles those questions in a terminal application. Here’s what happens at each step:
Route the request
: The
canUseTool
callback checks if the tool name is
"AskUserQuestion"
and routes to a dedicated handler
Display questions
: The handler loops through the
questions
array and prints each question with numbered options
Collect input
: The user can enter a number to select an option, or type free text directly (e.g., “jquery”, “i don’t know”)
Map answers
: The code checks if input is numeric (uses the option’s label) or free text (uses the text directly)
Return to Claude
: The response includes both the original
questions
array and the
answers
mapping
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeAgentOptions, ResultMessage, query
from
claude_agent_sdk.types
import
HookMatcher, PermissionResultAllow
def
parse_response
(
response
:
str
,
options
:
list
) ->
str
:
"""Parse user input as option number(s) or free text."""
try
:
indices
=
[
int
(s.strip())
-
1
for
s
in
response.split(
","
)]
labels
=
[options[i][
"label"
]
for
i
in
indices
if
0
<=
i
<
len
(options)]
return
", "
.join(labels)
if
labels
else
response
except
ValueError
:
return
response
async
def
handle_ask_user_question
(
input_data
:
dict
) -> PermissionResultAllow:
"""Display Claude's questions and collect user answers."""
answers
=
{}
for
q
in
input_data.get(
"questions"
, []):
print
(
f
"
\n
{
q[
'header'
]
}
:
{
q[
'question'
]
}
"
)
options
=
q[
"options"
]
for
i, opt
in
enumerate
(options):
print
(
f
"
{
i
+
1
}
.
{
opt[
'label'
]
}
-
{
opt[
'description'
]
}
"
)
if
q.get(
"multiSelect"
):
print
(
"  (Enter numbers separated by commas, or type your own answer)"
)
else
:
print
(
"  (Enter a number, or type your own answer)"
)
response
=
input
(
"Your choice: "
).strip()
answers[q[
"question"
]]
=
parse_response(response, options)
return
PermissionResultAllow(
updated_input
=
{
"questions"
: input_data.get(
"questions"
, []),
"answers"
: answers,
}
)
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
) -> PermissionResultAllow:
# Route AskUserQuestion to our question handler
if
tool_name
==
"AskUserQuestion"
:
return
await
handle_ask_user_question(input_data)
# Auto-approve other tools for this example
return
PermissionResultAllow(
updated_input
=
input_data)
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Help me decide on the tech stack for a new mobile app"
,
},
}
# Required workaround: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
​
Limitations
Subagents
:
AskUserQuestion
is not currently available in subagents spawned via the Agent tool
Question limits
: each
AskUserQuestion
call supports 1-4 questions with 2-4 options each
​
Other ways to get user input
The
canUseTool
callback and
AskUserQuestion
tool cover most approval and clarification scenarios, but the SDK offers other ways to get input from users:
​
Streaming input
Use
streaming input
when you need to:
Interrupt the agent mid-task
: send a cancel signal or change direction while Claude is working
Provide additional context
: add information Claude needs without waiting for it to ask
Build chat interfaces
: let users send follow-up messages during long-running operations
Streaming input is ideal for conversational UIs where users interact with the agent throughout execution, not just at approval checkpoints.
​
Custom tools
Use
custom tools
when you need to:
Collect structured input
: build forms, wizards, or multi-step workflows that go beyond
AskUserQuestion
’s multiple-choice format
Integrate external approval systems
: connect to existing ticketing, workflow, or approval platforms
Implement domain-specific interactions
: create tools tailored to your application’s needs, like code review interfaces or deployment checklists
Custom tools give you full control over the interaction, but require more implementation work than using the built-in
canUseTool
callback.
​
Related resources
Configure permissions
: set up permission modes and rules
Control execution with hooks
: run custom code at key points in the agent lifecycle
TypeScript SDK reference
: full canUseTool API documentation
Was this page helpful?
Yes
No
Streaming Input
Stream responses in real-time
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/user-input" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Handle approvals and user input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Handle approvals and user input
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
While working on a task, Claude sometimes needs to check in with users. It might need permission before deleting files, or need to ask which database to use for a new project. Your application needs to surface these requests to users so Claude can continue with their input.
Claude requests user input in two situations: when it needs
permission to use a tool
(like deleting files or running commands), and when it has
clarifying questions
(via the
AskUserQuestion
tool). Both trigger your
canUseTool
callback, which pauses execution until you return a response. This is different from normal conversation turns where Claude finishes and waits for your next message.
For clarifying questions, Claude generates the questions and options. Your role is to present them to users and return their selections. You can’t add your own questions to this flow; if you need to ask users something yourself, do that separately in your application logic.
The callback can stay pending indefinitely. Execution remains paused until your callback returns, and the SDK only cancels the wait when the query itself is cancelled. If a user might take longer to respond than your process can reasonably stay running, return the
defer
hook decision
, which lets the process exit and resume later from the persisted session.
This guide shows you how to detect each type of request and respond appropriately.
​
Detect when Claude needs input
Pass a
canUseTool
callback in your query options. The callback fires whenever Claude needs user input, receiving the tool name and input as arguments:
Python
TypeScript
async
def
handle_tool_request
(
tool_name
,
input_data
,
context
):
# Prompt user and return allow or deny
...
options
=
ClaudeAgentOptions(
can_use_tool
=
handle_tool_request)
The callback fires in two cases:
Tool needs approval
: Claude wants to use a tool that isn’t auto-approved by
permission rules
or modes. Check
tool_name
for the tool (e.g.,
"Bash"
,
"Write"
).
Claude asks a question
: Claude calls the
AskUserQuestion
tool. Check if
tool_name == "AskUserQuestion"
to handle it differently. If you specify a
tools
array, include
AskUserQuestion
for this to work. See
Handle clarifying questions
for details.
To automatically allow or deny tools without prompting users, use
hooks
instead. Hooks execute before
canUseTool
and can allow, deny, or modify requests based on your own logic. You can also use the
PermissionRequest
hook
to send external notifications (Slack, email, push) when Claude is waiting for approval.
​
Handle tool approval requests
Once you’ve passed a
canUseTool
callback in your query options, it fires when Claude wants to use a tool that isn’t auto-approved. Your callback receives three arguments:
Argument
Description
toolName
The name of the tool Claude wants to use (e.g.,
"Bash"
,
"Write"
,
"Edit"
)
input
The parameters Claude is passing to the tool. Contents vary by tool.
options
(TS) /
context
(Python)
Additional context including optional
suggestions
(proposed
PermissionUpdate
entries to avoid re-prompting) and a cancellation signal. In TypeScript,
signal
is an
AbortSignal
; in Python, the signal field is reserved for future use. See
ToolPermissionContext
for Python.
The
input
object contains tool-specific parameters. Common examples:
Tool
Input fields
Bash
command
,
description
,
timeout
Write
file_path
,
content
Edit
file_path
,
old_string
,
new_string
Read
file_path
,
offset
,
limit
See the SDK reference for complete input schemas:
Python
|
TypeScript
.
You can display this information to the user so they can decide whether to allow or reject the action, then return the appropriate response.
The following example asks Claude to create and delete a test file. When Claude attempts each operation, the callback prints the tool request to the terminal and prompts for y/n approval.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeAgentOptions, ResultMessage, query
from
claude_agent_sdk.types
import
(
HookMatcher,
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
# Display the tool request
print
(
f
"
\n
Tool:
{
tool_name
}
"
)
if
tool_name
==
"Bash"
:
print
(
f
"Command:
{
input_data.get(
'command'
)
}
"
)
if
input_data.get(
"description"
):
print
(
f
"Description:
{
input_data.get(
'description'
)
}
"
)
else
:
print
(
f
"Input:
{
input_data
}
"
)
# Get user approval
response
=
input
(
"Allow this action? (y/n): "
)
# Return allow or deny based on user's response
if
response.lower()
==
"y"
:
# Allow: tool executes with the original (or modified) input
return
PermissionResultAllow(
updated_input
=
input_data)
else
:
# Deny: tool doesn't execute, Claude sees the message
return
PermissionResultDeny(
message
=
"User denied this action"
)
# Required workaround: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Create a test file in /tmp and then delete it"
,
},
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
In Python,
can_use_tool
requires
streaming mode
and a
PreToolUse
hook that returns
{"continue_": True}
to keep the stream open. Without this hook, the stream closes before the permission callback can be invoked.
This example uses a
y/n
flow where any input other than
y
is treated as a denial. In practice, you might build a richer UI that lets users modify the request, provide feedback, or redirect Claude entirely. See
Respond to tool requests
for all the ways you can respond.
​
Respond to tool requests
Your callback returns one of two response types:
Response
Python
TypeScript
Allow
PermissionResultAllow(updated_input=...)
{ behavior: "allow", updatedInput }
Deny
PermissionResultDeny(message=...)
{ behavior: "deny", message }
When allowing, pass the tool input (original or modified). When denying, provide a message explaining why. Claude sees this message and may adjust its approach.
Python
TypeScript
from
claude_agent_sdk.types
import
PermissionResultAllow, PermissionResultDeny
# Allow the tool to execute
return
PermissionResultAllow(
updated_input
=
input_data)
# Block the tool
return
PermissionResultDeny(
message
=
"User rejected this action"
)
Beyond allowing or denying, you can modify the tool’s input or provide context that helps Claude adjust its approach:
Approve
: let the tool execute as Claude requested
Approve with changes
: modify the input before execution (e.g., sanitize paths, add constraints)
Approve and remember
: echo a suggested permission rule back so matching calls skip the prompt next time
Reject
: block the tool and tell Claude why
Suggest alternative
: block but guide Claude toward what the user wants instead
Redirect entirely
: use
streaming input
to send Claude a completely new instruction
Approve
Approve with changes
Approve and remember
Reject
Suggest alternative
Redirect entirely
The user approves the action as-is. Pass through the
input
from your callback unchanged and the tool executes exactly as Claude requested.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
print
(
f
"Claude wants to use
{
tool_name
}
"
)
approved
=
await
ask_user(
"Allow this action?"
)
if
approved:
return
PermissionResultAllow(
updated_input
=
input_data)
return
PermissionResultDeny(
message
=
"User declined"
)
The user approves but wants to modify the request first. You can change the input before the tool executes. Claude sees the result but isn’t told you changed anything. Useful for sanitizing parameters, adding constraints, or scoping access.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
if
tool_name
==
"Bash"
:
# User approved, but scope all commands to sandbox
sandboxed_input
=
{
**
input_data}
sandboxed_input[
"command"
]
=
input_data[
"command"
].replace(
"/tmp"
,
"/tmp/sandbox"
)
return
PermissionResultAllow(
updated_input
=
sandboxed_input)
return
PermissionResultAllow(
updated_input
=
input_data)
The user approves and doesn’t want to be asked again for this kind of call. The third callback argument carries
suggestions
, an array of ready-made
PermissionUpdate
entries. Echo one back in
updatedPermissions
to apply it. A suggestion with the
localSettings
destination writes the rule to
.claude/settings.local.json
so future sessions skip the prompt for matching calls.
The Python example requires
claude-agent-sdk
0.1.80 or later.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
choice
=
await
ask_user(
f
"Allow
{
tool_name
}
?"
, [
"once"
,
"always"
,
"no"
])
if
choice
==
"always"
:
persist
=
[
s
for
s
in
context.suggestions
if
s.destination
==
"localSettings"
]
return
PermissionResultAllow(
updated_input
=
input_data,
updated_permissions
=
persist
)
if
choice
==
"once"
:
return
PermissionResultAllow(
updated_input
=
input_data)
return
PermissionResultDeny(
message
=
"User declined"
)
The user doesn’t want this action to happen. Block the tool and provide a message explaining why. Claude sees this message and may try a different approach.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
approved
=
await
ask_user(
f
"Allow
{
tool_name
}
?"
)
if
not
approved:
return
PermissionResultDeny(
message
=
"User rejected this action"
)
return
PermissionResultAllow(
updated_input
=
input_data)
The user doesn’t want this specific action, but has a different idea. Block the tool and include guidance in your message. Claude will read this and decide how to proceed based on your feedback.
Python
TypeScript
async
def
can_use_tool
(
tool_name
,
input_data
,
context
):
if
tool_name
==
"Bash"
and
"rm"
in
input_data.get(
"command"
,
""
):
# User doesn't want to delete, suggest archiving instead
return
PermissionResultDeny(
message
=
"User doesn't want to delete files. They asked if you could compress them into an archive instead."
)
return
PermissionResultAllow(
updated_input
=
input_data)
For a complete change of direction (not just a nudge), use
streaming input
to send Claude a new instruction directly. This bypasses the current tool request and gives Claude entirely new instructions to follow.
​
Handle clarifying questions
When Claude needs more direction on a task with multiple valid approaches, it calls the
AskUserQuestion
tool. This triggers your
canUseTool
callback with
toolName
set to
AskUserQuestion
. The input contains Claude’s questions as multiple-choice options, which you display to the user and return their selections.
Clarifying questions are especially common in
plan
mode
, where Claude explores the codebase and asks questions before proposing a plan. This makes plan mode ideal for interactive workflows where you want Claude to gather requirements before making changes.
The following steps show how to handle clarifying questions:
1
Pass a canUseTool callback
Pass a
canUseTool
callback in your query options. By default,
AskUserQuestion
is available. If you specify a
tools
array to restrict Claude’s capabilities (for example, a read-only agent with only
Read
,
Glob
, and
Grep
), include
AskUserQuestion
in that array. Otherwise, Claude won’t be able to ask clarifying questions:
Python
TypeScript
async
for
message
in
query(
prompt
=
"Analyze this codebase"
,
options
=
ClaudeAgentOptions(
# Include AskUserQuestion in your tools list
tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"AskUserQuestion"
],
can_use_tool
=
can_use_tool,
),
):
print
(message)
2
Detect AskUserQuestion
In your callback, check if
toolName
equals
AskUserQuestion
to handle it differently from other tools:
Python
TypeScript
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
):
if
tool_name
==
"AskUserQuestion"
:
# Your implementation to collect answers from the user
return
await
handle_clarifying_questions(input_data)
# Handle other tools normally
return
await
prompt_for_approval(tool_name, input_data)
3
Parse the question input
The input contains Claude’s questions in a
questions
array. Each question has a
question
(the text to display),
options
(the choices), and
multiSelect
(whether multiple selections are allowed):
{
"questions"
: [
{
"question"
:
"How should I format the output?"
,
"header"
:
"Format"
,
"options"
: [
{
"label"
:
"Summary"
,
"description"
:
"Brief overview"
},
{
"label"
:
"Detailed"
,
"description"
:
"Full explanation"
}
],
"multiSelect"
:
false
},
{
"question"
:
"Which sections should I include?"
,
"header"
:
"Sections"
,
"options"
: [
{
"label"
:
"Introduction"
,
"description"
:
"Opening context"
},
{
"label"
:
"Conclusion"
,
"description"
:
"Final summary"
}
],
"multiSelect"
:
true
}
]
}
See
Question format
for full field descriptions.
4
Collect answers from the user
Present the questions to the user and collect their selections. How you do this depends on your application: a terminal prompt, a web form, a mobile dialog, etc.
5
Return answers to Claude
Build the
answers
object as a record where each key is the
question
text and each value is the selected option’s
label
:
From the question object
Use as
question
field (e.g.,
"How should I format the output?"
)
Key
Selected option’s
label
field (e.g.,
"Summary"
)
Value
For multi-select questions, pass an array of labels or join them with
", "
. If you
support free-text input
, use the user’s custom text as the value.
Python
TypeScript
return
PermissionResultAllow(
updated_input
=
{
"questions"
: input_data.get(
"questions"
, []),
"answers"
: {
"How should I format the output?"
:
"Summary"
,
"Which sections should I include?"
: [
"Introduction"
,
"Conclusion"
],
},
}
)
​
Question format
The input contains Claude’s generated questions in a
questions
array. Each question has these fields:
Field
Description
question
The full question text to display
header
Short label for the question (max 12 characters)
options
Array of 2-4 choices, each with
label
and
description
. TypeScript: optionally
preview
(see
below
)
multiSelect
If
true
, users can select multiple options
The structure your callback receives:
{
"questions"
: [
{
"question"
:
"How should I format the output?"
,
"header"
:
"Format"
,
"options"
: [
{
"label"
:
"Summary"
,
"description"
:
"Brief overview of key points"
},
{
"label"
:
"Detailed"
,
"description"
:
"Full explanation with examples"
}
],
"multiSelect"
:
false
}
]
}
​
Option previews (TypeScript)
toolConfig.askUserQuestion.previewFormat
adds a
preview
field to each option so your app can show a visual mockup alongside the label. Without this setting, Claude does not generate previews and the field is absent.
previewFormat
preview
contains
unset (default)
Field is absent. Claude does not generate previews.
"markdown"
ASCII art and fenced code blocks
"html"
A styled
<div>
fragment (the SDK rejects
<script>
,
<style>
, and
<!DOCTYPE>
before your callback runs)
The format applies to all questions in the session. Claude includes
preview
on options where a visual comparison helps (layout choices, color schemes) and omits it where one wouldn’t (yes/no confirmations, text-only choices). Check for
undefined
before rendering.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Help me choose a card layout"
,
options:
{
toolConfig:
{
askUserQuestion:
{
previewFormat:
"html"
}
},
canUseTool
:
async
(
toolName
,
input
)
=>
{
// input.questions[].options[].preview is an HTML string or undefined
return
{
behavior:
"allow"
,
updatedInput:
input
};
}
}
})) {
// ...
}
An option with an HTML preview:
{
"label"
:
"Compact"
,
"description"
:
"Title and metric value only"
,
"preview"
:
"<div style=
\"
padding:12px;border:1px solid #ddd;border-radius:8px
\"
><div style=
\"
font-size:12px;color:#666
\"
>Active users</div><div style=
\"
font-size:28px;font-weight:600
\"
>1,284</div></div>"
}
​
Response format
Return an
answers
object mapping each question’s
question
field to the selected option’s
label
:
Field
Description
questions
Pass through the original questions array (required for tool processing)
answers
Object where keys are question text and values are selected labels
For multi-select questions, pass an array of labels or join them with
", "
. For free-text input, use the user’s custom text directly.
{
"questions"
: [
// ...
],
"answers"
: {
"How should I format the output?"
:
"Summary"
,
"Which sections should I include?"
: [
"Introduction"
,
"Conclusion"
]
}
}
​
Support free-text input
Claude’s predefined options won’t always cover what users want. To let users type their own answer:
Display an additional “Other” choice after Claude’s options that accepts text input
Use the user’s custom text as the answer value (not the word “Other”)
See the
complete example
below for a full implementation.
​
Complete example
Claude asks clarifying questions when it needs user input to proceed. For example, when asked to help decide on a tech stack for a mobile app, Claude might ask about cross-platform vs native, backend preferences, or target platforms. These questions help Claude make decisions that match the user’s preferences rather than guessing.
This example handles those questions in a terminal application. Here’s what happens at each step:
Route the request
: The
canUseTool
callback checks if the tool name is
"AskUserQuestion"
and routes to a dedicated handler
Display questions
: The handler loops through the
questions
array and prints each question with numbered options
Collect input
: The user can enter a number to select an option, or type free text directly (e.g., “jquery”, “i don’t know”)
Map answers
: The code checks if input is numeric (uses the option’s label) or free text (uses the text directly)
Return to Claude
: The response includes both the original
questions
array and the
answers
mapping
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeAgentOptions, ResultMessage, query
from
claude_agent_sdk.types
import
HookMatcher, PermissionResultAllow
def
parse_response
(
response
:
str
,
options
:
list
) ->
str
:
"""Parse user input as option number(s) or free text."""
try
:
indices
=
[
int
(s.strip())
-
1
for
s
in
response.split(
","
)]
labels
=
[options[i][
"label"
]
for
i
in
indices
if
0
<=
i
<
len
(options)]
return
", "
.join(labels)
if
labels
else
response
except
ValueError
:
return
response
async
def
handle_ask_user_question
(
input_data
:
dict
) -> PermissionResultAllow:
"""Display Claude's questions and collect user answers."""
answers
=
{}
for
q
in
input_data.get(
"questions"
, []):
print
(
f
"
\n
{
q[
'header'
]
}
:
{
q[
'question'
]
}
"
)
options
=
q[
"options"
]
for
i, opt
in
enumerate
(options):
print
(
f
"
{
i
+
1
}
.
{
opt[
'label'
]
}
-
{
opt[
'description'
]
}
"
)
if
q.get(
"multiSelect"
):
print
(
"  (Enter numbers separated by commas, or type your own answer)"
)
else
:
print
(
"  (Enter a number, or type your own answer)"
)
response
=
input
(
"Your choice: "
).strip()
answers[q[
"question"
]]
=
parse_response(response, options)
return
PermissionResultAllow(
updated_input
=
{
"questions"
: input_data.get(
"questions"
, []),
"answers"
: answers,
}
)
async
def
can_use_tool
(
tool_name
:
str
,
input_data
:
dict
,
context
) -> PermissionResultAllow:
# Route AskUserQuestion to our question handler
if
tool_name
==
"AskUserQuestion"
:
return
await
handle_ask_user_question(input_data)
# Auto-approve other tools for this example
return
PermissionResultAllow(
updated_input
=
input_data)
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Help me decide on the tech stack for a new mobile app"
,
},
}
# Required workaround: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
​
Limitations
Subagents
:
AskUserQuestion
is not currently available in subagents spawned via the Agent tool
Question limits
: each
AskUserQuestion
call supports 1-4 questions with 2-4 options each
​
Other ways to get user input
The
canUseTool
callback and
AskUserQuestion
tool cover most approval and clarification scenarios, but the SDK offers other ways to get input from users:
​
Streaming input
Use
streaming input
when you need to:
Interrupt the agent mid-task
: send a cancel signal or change direction while Claude is working
Provide additional context
: add information Claude needs without waiting for it to ask
Build chat interfaces
: let users send follow-up messages during long-running operations
Streaming input is ideal for conversational UIs where users interact with the agent throughout execution, not just at approval checkpoints.
​
Custom tools
Use
custom tools
when you need to:
Collect structured input
: build forms, wizards, or multi-step workflows that go beyond
AskUserQuestion
’s multiple-choice format
Integrate external approval systems
: connect to existing ticketing, workflow, or approval platforms
Implement domain-specific interactions
: create tools tailored to your application’s needs, like code review interfaces or deployment checklists
Custom tools give you full control over the interaction, but require more implementation work than using the built-in
canUseTool
callback.
​
Related resources
Configure permissions
: set up permission modes and rules
Control execution with hooks
: run custom code at key points in the agent lifecycle
TypeScript SDK reference
: full canUseTool API documentation
Was this page helpful?
Yes
No
Streaming Input
Stream responses in real-time
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/user-input" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Quickstart</title>
  <link>https://code.claude.com/docs/en/agent-sdk/quickstart</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/quickstart</guid>
  <pubDate>Fri, 08 Nov 2024 00:00:00 +0000</pubDate>
  <category>Getting Started</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Quickstart
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Mo...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Quickstart
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Use the Agent SDK to build an AI agent that reads your code, finds bugs, and fixes them, all without manual intervention.
What you’ll do:
Set up a project with the Agent SDK
Create a file with some buggy code
Run an agent that finds and fixes the bugs automatically
​
Prerequisites
Node.js 18+
or
Python 3.10+
An
Anthropic account
(
sign up here
)
​
Setup
1
Create a project folder
Create a new directory for this quickstart:
mkdir
my-agent
&&
cd
my-agent
For your own projects, you can run the SDK from any folder; it will have access to files in that directory and its subdirectories by default.
2
Install the SDK
Install the Agent SDK package for your language:
TypeScript
Python (uv)
Python (pip)
npm
install
@anthropic-ai/claude-agent-sdk
uv Python package manager
is a fast Python package manager that handles virtual environments automatically:
uv
init
&&
uv
add
claude-agent-sdk
Create a virtual environment first, then install:
python3
-m
venv
.venv
&&
source
.venv/bin/activate
pip3
install
claude-agent-sdk
The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
3
Set your API key
Get an API key from the
Claude Console
, then create a
.env
file in your project directory:
ANTHROPIC_API_KEY
=
your-api-key
The SDK also supports authentication via third-party API providers:
Amazon Bedrock
: set
CLAUDE_CODE_USE_BEDROCK=1
environment variable and configure AWS credentials
Claude Platform on AWS
: set
CLAUDE_CODE_USE_ANTHROPIC_AWS=1
and
ANTHROPIC_AWS_WORKSPACE_ID
, then configure AWS credentials
Google Vertex AI
: set
CLAUDE_CODE_USE_VERTEX=1
environment variable and configure Google Cloud credentials
Microsoft Azure
: set
CLAUDE_CODE_USE_FOUNDRY=1
environment variable and configure Azure credentials
See the setup guides for
Bedrock
,
Claude Platform on AWS
,
Vertex AI
, or
Azure AI Foundry
for details.
Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.
​
Create a buggy file
This quickstart walks you through building an agent that can find and fix bugs in code. First, you need a file with some intentional bugs for the agent to fix. Create
utils.py
in the
my-agent
directory and paste the following code:
def
calculate_average
(
numbers
):
total
=
0
for
num
in
numbers:
total
+=
num
return
total
/
len
(numbers)
def
get_user_name
(
user
):
return
user[
"name"
].upper()
This code has two bugs:
calculate_average([])
crashes with division by zero
get_user_name(None)
crashes with a TypeError
​
Build an agent that finds and fixes bugs
Create
agent.py
if you’re using the Python SDK, or
agent.ts
for TypeScript:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async
def
main
():
# Agentic loop: streams messages as Claude works
async
for
message
in
query(
prompt
=
"Review utils.py for bugs that would cause crashes. Fix any issues you find."
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
],
# Tools Claude can use
permission_mode
=
"acceptEdits"
,
# Auto-approve file edits
),
):
# Print human-readable output
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
hasattr
(block,
"text"
):
print
(block.text)
# Claude's reasoning
elif
hasattr
(block,
"name"
):
print
(
f
"Tool:
{
block.name
}
"
)
# Tool being called
elif
isinstance
(message, ResultMessage):
print
(
f
"Done:
{
message.subtype
}
"
)
# Final result
asyncio.run(main())
This code has three main parts:
query
: the main entry point that creates the agentic loop. It returns an async iterator, so you use
async for
to stream messages as Claude works. See the full API in the
Python
or
TypeScript
SDK reference.
prompt
: what you want Claude to do. Claude figures out which tools to use based on the task.
options
: configuration for the agent. This example uses
allowedTools
to pre-approve
Read
,
Edit
, and
Glob
, and
permissionMode: "acceptEdits"
to auto-approve file changes. Other options include
systemPrompt
,
mcpServers
, and more. See all options for
Python
or
TypeScript
.
The
async for
loop keeps running as Claude thinks, calls tools, observes results, and decides what to do next. Each iteration yields a message: Claude’s reasoning, a tool call, a tool result, or the final outcome. The SDK handles the orchestration (tool execution, context management, retries) so you just consume the stream. The loop ends when Claude finishes the task or hits an error.
The message handling inside the loop filters for human-readable output. Without filtering, you’d see raw message objects including system initialization and internal state, which is useful for debugging but noisy otherwise.
This example uses streaming to show progress in real-time. If you don’t need live output (e.g., for background jobs or CI pipelines), you can collect all messages at once. See
Streaming vs. single-turn mode
for details.
​
Run your agent
Your agent is ready. Run it with the following command:
Python
TypeScript
python3
agent.py
npx
tsx
agent.ts
After running, check
utils.py
. You’ll see defensive code handling empty lists and null users. Your agent autonomously:
Read
utils.py
to understand the code
Analyzed
the logic and identified edge cases that would crash
Edited
the file to add proper error handling
This is what makes the Agent SDK different: Claude executes tools directly instead of asking you to implement them.
If you see “API key not found”, make sure you’ve set the
ANTHROPIC_API_KEY
environment variable in your
.env
file or shell environment. See the
full troubleshooting guide
for more help.
​
Try other prompts
Now that your agent is set up, try some different prompts:
"Add docstrings to all functions in utils.py"
"Add type hints to all functions in utils.py"
"Create a README.md documenting the functions in utils.py"
​
Customize your agent
You can modify your agent’s behavior by changing the options. Here are a few examples:
Add web search capability:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"WebSearch"
],
permission_mode
=
"acceptEdits"
)
Give Claude a custom system prompt:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
],
permission_mode
=
"acceptEdits"
,
system_prompt
=
"You are a senior Python developer. Always follow PEP 8 style guidelines."
,
)
Run commands in the terminal:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
With
Bash
enabled, try:
"Write unit tests for utils.py, run them, and fix any failures"
​
Key concepts
Tools
control what your agent can do:
Tools
What the agent can do
Read
,
Glob
,
Grep
Read-only analysis
Read
,
Edit
,
Glob
Analyze and modify code
Read
,
Edit
,
Bash
,
Glob
,
Grep
Full automation
Permission modes
control how much human oversight you want:
Mode
Behavior
Use case
acceptEdits
Auto-approves file edits and common filesystem commands, asks for other actions
Trusted development workflows
dontAsk
Denies anything not in
allowedTools
Locked-down headless agents
auto
(TypeScript only)
A model classifier approves or denies each tool call
Autonomous agents with safety guardrails
bypassPermissions
Runs every tool without prompts
Sandboxed CI, fully trusted environments
default
Requires a
canUseTool
callback to handle approval
Custom approval flows
The example above uses
acceptEdits
mode, which auto-approves file operations so the agent can run without interactive prompts. If you want to prompt users for approval, use
default
mode and provide a
canUseTool
callback
that collects user input. For more control, see
Permissions
.
​
Troubleshooting
​
API error
thinking.type.enabled
is not supported for this model
Claude Opus 4.7 replaces
thinking.type.enabled
with
thinking.type.adaptive
. Older Agent SDK versions fail with the following API error when you select
claude-opus-4-7
:
API Error: 400 {"type":"invalid_request_error","message":"\"thinking.type.enabled\" is not supported for this model. Use \"thinking.type.adaptive\" and \"output_config.effort\" to control thinking behavior."}
Upgrade to Agent SDK v0.2.111 or later to use Opus 4.7.
​
Next steps
Now that you’ve created your first agent, learn how to extend its capabilities and tailor it to your use case:
Permissions
: control what your agent can do and when it needs approval
Hooks
: run custom code before or after tool calls
Sessions
: build multi-turn agents that maintain context
MCP servers
: connect to databases, browsers, APIs, and other external systems
Hosting
: deploy agents to Docker, cloud, and CI/CD
Example agents
: see complete examples: email assistant, research agent, and more
Was this page helpful?
Yes
No
Overview
How the agent loop works
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Quickstart
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Mo...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Quickstart
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Use the Agent SDK to build an AI agent that reads your code, finds bugs, and fixes them, all without manual intervention.
What you’ll do:
Set up a project with the Agent SDK
Create a file with some buggy code
Run an agent that finds and fixes the bugs automatically
​
Prerequisites
Node.js 18+
or
Python 3.10+
An
Anthropic account
(
sign up here
)
​
Setup
1
Create a project folder
Create a new directory for this quickstart:
mkdir
my-agent
&&
cd
my-agent
For your own projects, you can run the SDK from any folder; it will have access to files in that directory and its subdirectories by default.
2
Install the SDK
Install the Agent SDK package for your language:
TypeScript
Python (uv)
Python (pip)
npm
install
@anthropic-ai/claude-agent-sdk
uv Python package manager
is a fast Python package manager that handles virtual environments automatically:
uv
init
&&
uv
add
claude-agent-sdk
Create a virtual environment first, then install:
python3
-m
venv
.venv
&&
source
.venv/bin/activate
pip3
install
claude-agent-sdk
The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
3
Set your API key
Get an API key from the
Claude Console
, then create a
.env
file in your project directory:
ANTHROPIC_API_KEY
=
your-api-key
The SDK also supports authentication via third-party API providers:
Amazon Bedrock
: set
CLAUDE_CODE_USE_BEDROCK=1
environment variable and configure AWS credentials
Claude Platform on AWS
: set
CLAUDE_CODE_USE_ANTHROPIC_AWS=1
and
ANTHROPIC_AWS_WORKSPACE_ID
, then configure AWS credentials
Google Vertex AI
: set
CLAUDE_CODE_USE_VERTEX=1
environment variable and configure Google Cloud credentials
Microsoft Azure
: set
CLAUDE_CODE_USE_FOUNDRY=1
environment variable and configure Azure credentials
See the setup guides for
Bedrock
,
Claude Platform on AWS
,
Vertex AI
, or
Azure AI Foundry
for details.
Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.
​
Create a buggy file
This quickstart walks you through building an agent that can find and fix bugs in code. First, you need a file with some intentional bugs for the agent to fix. Create
utils.py
in the
my-agent
directory and paste the following code:
def
calculate_average
(
numbers
):
total
=
0
for
num
in
numbers:
total
+=
num
return
total
/
len
(numbers)
def
get_user_name
(
user
):
return
user[
"name"
].upper()
This code has two bugs:
calculate_average([])
crashes with division by zero
get_user_name(None)
crashes with a TypeError
​
Build an agent that finds and fixes bugs
Create
agent.py
if you’re using the Python SDK, or
agent.ts
for TypeScript:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async
def
main
():
# Agentic loop: streams messages as Claude works
async
for
message
in
query(
prompt
=
"Review utils.py for bugs that would cause crashes. Fix any issues you find."
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
],
# Tools Claude can use
permission_mode
=
"acceptEdits"
,
# Auto-approve file edits
),
):
# Print human-readable output
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
hasattr
(block,
"text"
):
print
(block.text)
# Claude's reasoning
elif
hasattr
(block,
"name"
):
print
(
f
"Tool:
{
block.name
}
"
)
# Tool being called
elif
isinstance
(message, ResultMessage):
print
(
f
"Done:
{
message.subtype
}
"
)
# Final result
asyncio.run(main())
This code has three main parts:
query
: the main entry point that creates the agentic loop. It returns an async iterator, so you use
async for
to stream messages as Claude works. See the full API in the
Python
or
TypeScript
SDK reference.
prompt
: what you want Claude to do. Claude figures out which tools to use based on the task.
options
: configuration for the agent. This example uses
allowedTools
to pre-approve
Read
,
Edit
, and
Glob
, and
permissionMode: "acceptEdits"
to auto-approve file changes. Other options include
systemPrompt
,
mcpServers
, and more. See all options for
Python
or
TypeScript
.
The
async for
loop keeps running as Claude thinks, calls tools, observes results, and decides what to do next. Each iteration yields a message: Claude’s reasoning, a tool call, a tool result, or the final outcome. The SDK handles the orchestration (tool execution, context management, retries) so you just consume the stream. The loop ends when Claude finishes the task or hits an error.
The message handling inside the loop filters for human-readable output. Without filtering, you’d see raw message objects including system initialization and internal state, which is useful for debugging but noisy otherwise.
This example uses streaming to show progress in real-time. If you don’t need live output (e.g., for background jobs or CI pipelines), you can collect all messages at once. See
Streaming vs. single-turn mode
for details.
​
Run your agent
Your agent is ready. Run it with the following command:
Python
TypeScript
python3
agent.py
npx
tsx
agent.ts
After running, check
utils.py
. You’ll see defensive code handling empty lists and null users. Your agent autonomously:
Read
utils.py
to understand the code
Analyzed
the logic and identified edge cases that would crash
Edited
the file to add proper error handling
This is what makes the Agent SDK different: Claude executes tools directly instead of asking you to implement them.
If you see “API key not found”, make sure you’ve set the
ANTHROPIC_API_KEY
environment variable in your
.env
file or shell environment. See the
full troubleshooting guide
for more help.
​
Try other prompts
Now that your agent is set up, try some different prompts:
"Add docstrings to all functions in utils.py"
"Add type hints to all functions in utils.py"
"Create a README.md documenting the functions in utils.py"
​
Customize your agent
You can modify your agent’s behavior by changing the options. Here are a few examples:
Add web search capability:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"WebSearch"
],
permission_mode
=
"acceptEdits"
)
Give Claude a custom system prompt:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
],
permission_mode
=
"acceptEdits"
,
system_prompt
=
"You are a senior Python developer. Always follow PEP 8 style guidelines."
,
)
Run commands in the terminal:
Python
TypeScript
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
With
Bash
enabled, try:
"Write unit tests for utils.py, run them, and fix any failures"
​
Key concepts
Tools
control what your agent can do:
Tools
What the agent can do
Read
,
Glob
,
Grep
Read-only analysis
Read
,
Edit
,
Glob
Analyze and modify code
Read
,
Edit
,
Bash
,
Glob
,
Grep
Full automation
Permission modes
control how much human oversight you want:
Mode
Behavior
Use case
acceptEdits
Auto-approves file edits and common filesystem commands, asks for other actions
Trusted development workflows
dontAsk
Denies anything not in
allowedTools
Locked-down headless agents
auto
(TypeScript only)
A model classifier approves or denies each tool call
Autonomous agents with safety guardrails
bypassPermissions
Runs every tool without prompts
Sandboxed CI, fully trusted environments
default
Requires a
canUseTool
callback to handle approval
Custom approval flows
The example above uses
acceptEdits
mode, which auto-approves file operations so the agent can run without interactive prompts. If you want to prompt users for approval, use
default
mode and provide a
canUseTool
callback
that collects user input. For more control, see
Permissions
.
​
Troubleshooting
​
API error
thinking.type.enabled
is not supported for this model
Claude Opus 4.7 replaces
thinking.type.enabled
with
thinking.type.adaptive
. Older Agent SDK versions fail with the following API error when you select
claude-opus-4-7
:
API Error: 400 {"type":"invalid_request_error","message":"\"thinking.type.enabled\" is not supported for this model. Use \"thinking.type.adaptive\" and \"output_config.effort\" to control thinking behavior."}
Upgrade to Agent SDK v0.2.111 or later to use Opus 4.7.
​
Next steps
Now that you’ve created your first agent, learn how to extend its capabilities and tailor it to your use case:
Permissions
: control what your agent can do and when it needs approval
Hooks
: run custom code before or after tool calls
Sessions
: build multi-turn agents that maintain context
MCP servers
: connect to databases, browsers, APIs, and other external systems
Hosting
: deploy agents to Docker, cloud, and CI/CD
Example agents
: see complete examples: email assistant, research agent, and more
Was this page helpful?
Yes
No
Overview
How the agent loop works
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Plugins in the SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/plugins</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/plugins</guid>
  <pubDate>Sun, 03 Nov 2024 00:00:00 +0000</pubDate>
  <category>Plugins</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Plugins in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cust...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Plugins in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins allow you to extend Claude Code with custom functionality that can be shared across projects. Through the Agent SDK, you can programmatically load plugins from local directories to add custom slash commands, agents, skills, hooks, and MCP servers to your agent sessions.
​
What are plugins?
Plugins are packages of Claude Code extensions that can include:
Skills
: Model-invoked capabilities that Claude uses autonomously (can also be invoked with
/skill-name
)
Agents
: Specialized subagents for specific tasks
Hooks
: Event handlers that respond to tool use and other events
MCP servers
: External tool integrations via Model Context Protocol
The
commands/
directory is a legacy format. Use
skills/
for new plugins. Claude Code continues to support both formats for backward compatibility.
For complete information on plugin structure and how to create plugins, see
Plugins
.
​
Loading plugins
Load plugins by providing their local file system paths in your options configuration. The
type
field must be
"local"
, the only value the SDK accepts. To use a plugin distributed through a
marketplace
or remote repository, download it first and provide the local directory path. The SDK supports loading multiple plugins from different locations.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Hello"
,
options:
{
plugins:
[
{
type:
"local"
,
path:
"./my-plugin"
},
{
type:
"local"
,
path:
"/absolute/path/to/another-plugin"
}
]
}
})) {
// Plugin commands, agents, and other features are now available
}
​
Path specifications
Plugin paths can be:
Relative paths
: Resolved relative to your current working directory (for example,
"./plugins/my-plugin"
)
Absolute paths
: Full file system paths (for example,
"/home/user/plugins/my-plugin"
)
The path should point to the plugin’s root directory (the directory containing
.claude-plugin/plugin.json
).
​
Verifying plugin installation
When plugins load successfully, they appear in the system initialization message. You can verify that your plugins are available:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Hello"
,
options:
{
plugins:
[{
type:
"local"
,
path:
"./my-plugin"
}]
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
// Check loaded plugins
console
.
log
(
"Plugins:"
,
message
.
plugins
);
// Example: [{ name: "my-plugin", path: "./my-plugin" }]
// Check available commands from plugins
console
.
log
(
"Commands:"
,
message
.
slash_commands
);
// Example: ["/help", "/compact", "my-plugin:custom-command"]
}
}
​
Using plugin skills
Skills from plugins are automatically namespaced with the plugin name to avoid conflicts. When invoked as slash commands, the format is
plugin-name:skill-name
.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Load a plugin with a custom /greet skill
for
await
(
const
message
of
query
({
prompt:
"/my-plugin:greet"
,
// Use plugin skill with namespace
options:
{
plugins:
[{
type:
"local"
,
path:
"./my-plugin"
}]
}
})) {
// Claude executes the custom greeting skill from the plugin
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
If you installed a plugin via the CLI (for example,
/plugin install my-plugin@marketplace
), you can still use it in the SDK by providing its installation path. Check
~/.claude/plugins/
for CLI-installed plugins.
​
Complete example
Here’s a full example demonstrating plugin loading and usage:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
*
as
path
from
"path"
;
async
function
runWithPlugin
() {
const
pluginPath
=
path
.
join
(
__dirname
,
"plugins"
,
"my-plugin"
);
console
.
log
(
"Loading plugin from:"
,
pluginPath
);
for
await
(
const
message
of
query
({
prompt:
"What custom commands do you have available?"
,
options:
{
plugins:
[{
type:
"local"
,
path:
pluginPath
}],
maxTurns:
3
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"Loaded plugins:"
,
message
.
plugins
);
console
.
log
(
"Available commands:"
,
message
.
slash_commands
);
}
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
"Assistant:"
,
message
.
message
.
content
);
}
}
}
runWithPlugin
().
catch
(
console
.
error
);
​
Plugin structure reference
A plugin directory must contain a
.claude-plugin/plugin.json
manifest file. It can optionally include:
my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required: plugin manifest
├── skills/                   # Agent Skills (invoked autonomously or via /skill-name)
│   └── my-skill/
│       └── SKILL.md
├── commands/                 # Legacy: use skills/ instead
│   └── custom-cmd.md
├── agents/                   # Custom agents
│   └── specialist.md
├── hooks/                    # Event handlers
│   └── hooks.json
└── .mcp.json                # MCP server definitions
For detailed information on creating plugins, see:
Plugins
- Complete plugin development guide
Plugins reference
- Technical specifications and schemas
​
Common use cases
​
Development and testing
Load plugins during development without installing them globally:
plugins
: [{
type:
"local"
,
path:
"./dev-plugins/my-plugin"
}];
​
Project-specific extensions
Include plugins in your project repository for team-wide consistency:
plugins
: [{
type:
"local"
,
path:
"./project-plugins/team-workflows"
}];
​
Multiple plugin sources
Combine plugins from different locations:
plugins
: [
{
type:
"local"
,
path:
"./local-plugin"
},
{
type:
"local"
,
path:
"~/.claude/custom-plugins/shared-plugin"
}
];
​
Troubleshooting
​
Plugin not loading
If your plugin doesn’t appear in the init message:
Check the path
: Ensure the path points to the plugin root directory (containing
.claude-plugin/
)
Validate plugin.json
: Ensure your manifest file has valid JSON syntax
Check file permissions
: Ensure the plugin directory is readable
​
Skills not appearing
If plugin skills don’t work:
Use the namespace
: Plugin skills require the
plugin-name:skill-name
format when invoked as slash commands
Check init message
: Verify the skill appears in
slash_commands
with the correct namespace
Validate skill files
: Ensure each skill has a
SKILL.md
file in its own subdirectory under
skills/
(for example,
skills/my-skill/SKILL.md
)
​
Path resolution issues
If relative paths don’t work:
Check working directory
: Relative paths are resolved from your current working directory
Use absolute paths
: For reliability, consider using absolute paths
Normalize paths
: Use path utilities to construct paths correctly
​
See also
Plugins
- Complete plugin development guide
Plugins reference
- Technical specifications
Slash Commands
- Using slash commands in the SDK
Subagents
- Working with specialized agents
Skills
- Using Agent Skills
Was this page helpful?
Yes
No
Agent Skills in the SDK
Configure permissions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Plugins in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cust...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Plugins in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins allow you to extend Claude Code with custom functionality that can be shared across projects. Through the Agent SDK, you can programmatically load plugins from local directories to add custom slash commands, agents, skills, hooks, and MCP servers to your agent sessions.
​
What are plugins?
Plugins are packages of Claude Code extensions that can include:
Skills
: Model-invoked capabilities that Claude uses autonomously (can also be invoked with
/skill-name
)
Agents
: Specialized subagents for specific tasks
Hooks
: Event handlers that respond to tool use and other events
MCP servers
: External tool integrations via Model Context Protocol
The
commands/
directory is a legacy format. Use
skills/
for new plugins. Claude Code continues to support both formats for backward compatibility.
For complete information on plugin structure and how to create plugins, see
Plugins
.
​
Loading plugins
Load plugins by providing their local file system paths in your options configuration. The
type
field must be
"local"
, the only value the SDK accepts. To use a plugin distributed through a
marketplace
or remote repository, download it first and provide the local directory path. The SDK supports loading multiple plugins from different locations.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Hello"
,
options:
{
plugins:
[
{
type:
"local"
,
path:
"./my-plugin"
},
{
type:
"local"
,
path:
"/absolute/path/to/another-plugin"
}
]
}
})) {
// Plugin commands, agents, and other features are now available
}
​
Path specifications
Plugin paths can be:
Relative paths
: Resolved relative to your current working directory (for example,
"./plugins/my-plugin"
)
Absolute paths
: Full file system paths (for example,
"/home/user/plugins/my-plugin"
)
The path should point to the plugin’s root directory (the directory containing
.claude-plugin/plugin.json
).
​
Verifying plugin installation
When plugins load successfully, they appear in the system initialization message. You can verify that your plugins are available:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Hello"
,
options:
{
plugins:
[{
type:
"local"
,
path:
"./my-plugin"
}]
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
// Check loaded plugins
console
.
log
(
"Plugins:"
,
message
.
plugins
);
// Example: [{ name: "my-plugin", path: "./my-plugin" }]
// Check available commands from plugins
console
.
log
(
"Commands:"
,
message
.
slash_commands
);
// Example: ["/help", "/compact", "my-plugin:custom-command"]
}
}
​
Using plugin skills
Skills from plugins are automatically namespaced with the plugin name to avoid conflicts. When invoked as slash commands, the format is
plugin-name:skill-name
.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Load a plugin with a custom /greet skill
for
await
(
const
message
of
query
({
prompt:
"/my-plugin:greet"
,
// Use plugin skill with namespace
options:
{
plugins:
[{
type:
"local"
,
path:
"./my-plugin"
}]
}
})) {
// Claude executes the custom greeting skill from the plugin
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
If you installed a plugin via the CLI (for example,
/plugin install my-plugin@marketplace
), you can still use it in the SDK by providing its installation path. Check
~/.claude/plugins/
for CLI-installed plugins.
​
Complete example
Here’s a full example demonstrating plugin loading and usage:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
*
as
path
from
"path"
;
async
function
runWithPlugin
() {
const
pluginPath
=
path
.
join
(
__dirname
,
"plugins"
,
"my-plugin"
);
console
.
log
(
"Loading plugin from:"
,
pluginPath
);
for
await
(
const
message
of
query
({
prompt:
"What custom commands do you have available?"
,
options:
{
plugins:
[{
type:
"local"
,
path:
pluginPath
}],
maxTurns:
3
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"Loaded plugins:"
,
message
.
plugins
);
console
.
log
(
"Available commands:"
,
message
.
slash_commands
);
}
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
"Assistant:"
,
message
.
message
.
content
);
}
}
}
runWithPlugin
().
catch
(
console
.
error
);
​
Plugin structure reference
A plugin directory must contain a
.claude-plugin/plugin.json
manifest file. It can optionally include:
my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required: plugin manifest
├── skills/                   # Agent Skills (invoked autonomously or via /skill-name)
│   └── my-skill/
│       └── SKILL.md
├── commands/                 # Legacy: use skills/ instead
│   └── custom-cmd.md
├── agents/                   # Custom agents
│   └── specialist.md
├── hooks/                    # Event handlers
│   └── hooks.json
└── .mcp.json                # MCP server definitions
For detailed information on creating plugins, see:
Plugins
- Complete plugin development guide
Plugins reference
- Technical specifications and schemas
​
Common use cases
​
Development and testing
Load plugins during development without installing them globally:
plugins
: [{
type:
"local"
,
path:
"./dev-plugins/my-plugin"
}];
​
Project-specific extensions
Include plugins in your project repository for team-wide consistency:
plugins
: [{
type:
"local"
,
path:
"./project-plugins/team-workflows"
}];
​
Multiple plugin sources
Combine plugins from different locations:
plugins
: [
{
type:
"local"
,
path:
"./local-plugin"
},
{
type:
"local"
,
path:
"~/.claude/custom-plugins/shared-plugin"
}
];
​
Troubleshooting
​
Plugin not loading
If your plugin doesn’t appear in the init message:
Check the path
: Ensure the path points to the plugin root directory (containing
.claude-plugin/
)
Validate plugin.json
: Ensure your manifest file has valid JSON syntax
Check file permissions
: Ensure the plugin directory is readable
​
Skills not appearing
If plugin skills don’t work:
Use the namespace
: Plugin skills require the
plugin-name:skill-name
format when invoked as slash commands
Check init message
: Verify the skill appears in
slash_commands
with the correct namespace
Validate skill files
: Ensure each skill has a
SKILL.md
file in its own subdirectory under
skills/
(for example,
skills/my-skill/SKILL.md
)
​
Path resolution issues
If relative paths don’t work:
Check working directory
: Relative paths are resolved from your current working directory
Use absolute paths
: For reliability, consider using absolute paths
Normalize paths
: Use path utilities to construct paths correctly
​
See also
Plugins
- Complete plugin development guide
Plugins reference
- Technical specifications
Slash Commands
- Using slash commands in the SDK
Subagents
- Working with specialized agents
Skills
- Using Agent Skills
Was this page helpful?
Yes
No
Agent Skills in the SDK
Configure permissions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Environment variables</title>
  <link>https://code.claude.com/docs/en/env-vars</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/env-vars</guid>
  <pubDate>Sun, 03 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Environment variables
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports the following environ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Environment variables
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports the following environment variables to control its behavior. Set them in your shell before launching
claude
, or configure them in
settings.json
under the
env
key to apply them to every session or roll them out across your team.
Variable
Purpose
ANTHROPIC_API_KEY
API key sent as
X-Api-Key
header. When set, this key is used instead of your Claude Pro, Max, Team, or Enterprise subscription even if you are logged in. In non-interactive mode (
-p
), the key is always used when present. In interactive mode, you are prompted to approve the key once before it overrides your subscription. To use your subscription instead, run
unset ANTHROPIC_API_KEY
ANTHROPIC_AUTH_TOKEN
Custom value for the
Authorization
header (the value you set here will be prefixed with
Bearer
)
ANTHROPIC_AWS_API_KEY
Workspace API key for
Claude Platform on AWS
, generated in the AWS Console. Sent as
x-api-key
and takes precedence over AWS SigV4
ANTHROPIC_AWS_BASE_URL
Override the
Claude Platform on AWS
endpoint URL. Use for custom regions or when routing through an
LLM gateway
. Defaults to
https://aws-external-anthropic.{AWS_REGION}.api.aws
ANTHROPIC_AWS_WORKSPACE_ID
Required for
Claude Platform on AWS
. Sent on every request as the
anthropic-workspace-id
header
ANTHROPIC_BASE_URL
Override the API endpoint to route requests through a proxy or gateway. When set to a non-first-party host,
MCP tool search
is disabled by default. Set
ENABLE_TOOL_SEARCH=true
if your proxy forwards
tool_reference
blocks
ANTHROPIC_BEDROCK_BASE_URL
Override the Bedrock endpoint URL. Use for custom Bedrock endpoints or when routing through an
LLM gateway
. See
Amazon Bedrock
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
Override the Bedrock Mantle endpoint URL. See
Mantle endpoint
ANTHROPIC_BEDROCK_SERVICE_TIER
Bedrock
service tier
(
default
,
flex
, or
priority
). Sent as the
X-Amzn-Bedrock-Service-Tier
header. See
Amazon Bedrock
ANTHROPIC_BETAS
Comma-separated list of additional
anthropic-beta
header values to include in API requests. Claude Code already sends the beta headers it needs; use this to opt into an
Anthropic API beta
before Claude Code adds native support. Unlike the
--betas
flag
, which requires API key authentication, this variable works with all auth methods including Claude.ai subscription
ANTHROPIC_CUSTOM_HEADERS
Custom headers to add to requests (
Name: Value
format, newline-separated for multiple headers)
ANTHROPIC_CUSTOM_MODEL_OPTION
Model ID to add as a custom entry in the
/model
picker. Use this to make a non-standard or gateway-specific model selectable without replacing built-in aliases. See
Model configuration
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
Display description for the custom model entry in the
/model
picker. Defaults to
Custom model (<model-id>)
when not set
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
Display name for the custom model entry in the
/model
picker. Defaults to the model ID when not set
ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_FOUNDRY_API_KEY
API key for Microsoft Foundry authentication (see
Microsoft Foundry
)
ANTHROPIC_FOUNDRY_BASE_URL
Full base URL for the Foundry resource (for example,
https://my-resource.services.ai.azure.com/anthropic
). Alternative to
ANTHROPIC_FOUNDRY_RESOURCE
(see
Microsoft Foundry
)
ANTHROPIC_FOUNDRY_RESOURCE
Foundry resource name (for example,
my-resource
). Required if
ANTHROPIC_FOUNDRY_BASE_URL
is not set (see
Microsoft Foundry
)
ANTHROPIC_MODEL
Name of the model setting to use (see
Model Configuration
)
ANTHROPIC_SMALL_FAST_MODEL
[DEPRECATED] Name of
Haiku-class model for background tasks
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
Override AWS region for the Haiku-class model when using Bedrock or Bedrock Mantle. On Bedrock, this only takes effect when
ANTHROPIC_DEFAULT_HAIKU_MODEL
or the deprecated
ANTHROPIC_SMALL_FAST_MODEL
is also set, since Bedrock otherwise uses the primary model for background tasks
ANTHROPIC_VERTEX_BASE_URL
Override the Vertex AI endpoint URL. Use for custom Vertex endpoints or when routing through an
LLM gateway
. See
Google Vertex AI
ANTHROPIC_VERTEX_PROJECT_ID
GCP project ID for Vertex AI requests. Overridden by
GCLOUD_PROJECT
,
GOOGLE_CLOUD_PROJECT
, or the project in your
GOOGLE_APPLICATION_CREDENTIALS
credential file. See
Google Vertex AI
ANTHROPIC_WORKSPACE_ID
Workspace ID for
workload identity federation
. Set this when your federation rule is scoped to more than one workspace so the token exchange knows which workspace to target
API_TIMEOUT_MS
Timeout for API requests in milliseconds (default: 600000, or 10 minutes; maximum: 2147483647). Increase this when requests time out on slow networks or when routing through a proxy. Values above the maximum overflow the underlying timer and cause requests to fail immediately
AWS_BEARER_TOKEN_BEDROCK
Bedrock API key for authentication (see
Bedrock API keys
)
BASH_DEFAULT_TIMEOUT_MS
Default timeout for long-running bash commands (default: 120000, or 2 minutes)
BASH_MAX_OUTPUT_LENGTH
Maximum number of characters in bash outputs before the full output is saved to a file and Claude receives the path plus a short preview. See
Bash tool behavior
BASH_MAX_TIMEOUT_MS
Maximum timeout the model can set for long-running bash commands (default: 600000, or 10 minutes)
CCR_FORCE_BUNDLE
Set to
1
to force
claude --remote
to bundle and upload your local repository even when GitHub access is available
CLAUDECODE
Set to
1
in shell environments Claude Code spawns (Bash tool, tmux sessions). Not set in
hooks
or
status line
commands. Use to detect when a script is running inside a shell spawned by Claude Code
CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS
Set to
1
to disable all built-in
subagent
types such as Explore and Plan. Only applies in non-interactive mode (the
-p
flag). Useful for SDK users who want a blank slate
CLAUDE_AGENT_SDK_MCP_NO_PREFIX
Set to
1
to skip the
mcp__<server>__
prefix on tool names from SDK-created MCP servers. Tools use their original names. SDK usage only
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
Stall timeout in milliseconds for background subagents. Default
600000
(10 minutes). The timer resets on each streaming progress event; if no progress arrives within the window, the subagent is aborted and the task is marked failed, surfacing any partial result to the parent
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
Set the percentage of context capacity (1-100) at which auto-compaction triggers. By default, auto-compaction triggers at approximately 95% capacity. Use lower values like
50
to compact earlier. Values above the default threshold have no effect. Applies to both main conversations and subagents. This percentage aligns with the
context_window.used_percentage
field available in
status line
CLAUDE_AUTO_BACKGROUND_TASKS
Set to
1
to force-enable automatic backgrounding of long-running agent tasks. When enabled, subagents are moved to the background after running for approximately two minutes
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR
Return to the original working directory after each Bash or PowerShell command in the main session
CLAUDE_CODE_ACCESSIBILITY
Set to
1
to keep the native terminal cursor visible and disable the inverted-text cursor indicator. Allows screen magnifiers like macOS Zoom to track cursor position
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
Set to
1
to load memory files from directories specified with
--add-dir
. Loads
CLAUDE.md
,
.claude/CLAUDE.md
,
.claude/rules/*.md
, and
CLAUDE.local.md
. By default, additional directories do not load memory files
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
Interval in milliseconds at which credentials should be refreshed (when using
apiKeyHelper
)
CLAUDE_CODE_ATTRIBUTION_HEADER
Set to
0
to omit the attribution block (client version and prompt fingerprint) from the start of the system prompt. Disabling it improves prompt-cache hit rates when routing through an
LLM gateway
. Anthropic API caching is unaffected
CLAUDE_CODE_AUTO_COMPACT_WINDOW
Set the context capacity in tokens used for auto-compaction calculations. Defaults to the model’s context window: 200K for standard models or 1M for
extended context
models. Use a lower value like
500000
on a 1M model to treat the window as 500K for compaction purposes. The value is capped at the model’s actual context window.
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
is applied as a percentage of this value. Setting this variable decouples the compaction threshold from the status line’s
used_percentage
, which always uses the model’s full context window
CLAUDE_CODE_AUTO_CONNECT_IDE
Override automatic
IDE connection
. By default, Claude Code connects automatically when launched inside a supported IDE’s integrated terminal. Set to
false
to prevent this. Set to
true
to force a connection attempt when auto-detection fails, such as when tmux obscures the parent terminal. Takes precedence over the
autoConnectIde
global config setting
CLAUDE_CODE_CERT_STORE
Comma-separated list of CA certificate sources for TLS connections.
bundled
is the Mozilla CA set shipped with Claude Code.
system
is the operating system trust store. Default is
bundled,system
CLAUDE_CODE_CLIENT_CERT
Path to client certificate file for mTLS authentication
CLAUDE_CODE_CLIENT_KEY
Path to client private key file for mTLS authentication
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
Passphrase for encrypted CLAUDE_CODE_CLIENT_KEY (optional)
CLAUDE_CODE_DEBUG_LOGS_DIR
Override the debug log file path. Despite the name, this is a file path, not a directory. Requires debug mode to be enabled separately via
--debug
,
/debug
, or the
DEBUG
environment variable: setting this variable alone does not enable logging. The
--debug-file
flag does both at once. Defaults to
~/.claude/debug/<session-id>.txt
CLAUDE_CODE_DEBUG_LOG_LEVEL
Minimum log level written to the debug log file. Values:
verbose
,
debug
(default),
info
,
warn
,
error
. Set to
verbose
to include high-volume diagnostics like full status line command output, or raise to
error
to reduce noise
CLAUDE_CODE_DISABLE_1M_CONTEXT
Set to
1
to disable
1M context window
support. When set, 1M model variants are unavailable in the model picker. Useful for enterprise environments with compliance requirements
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
Set to
1
to disable
adaptive reasoning
on Opus 4.6 and Sonnet 4.6 and fall back to the fixed thinking budget controlled by
MAX_THINKING_TOKENS
. Has no effect on Opus 4.7, which always uses adaptive reasoning
CLAUDE_CODE_DISABLE_AGENT_VIEW
Set to
1
to turn off
background agents and agent view
:
claude agents
,
--bg
,
/background
, and the on-demand supervisor. Equivalent to the
disableAgentView
setting
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN
Set to
1
to disable
fullscreen rendering
and use the classic main-screen renderer. The conversation stays in your terminal’s native scrollback so
Cmd+f
and tmux copy mode work as usual. Takes precedence over
CLAUDE_CODE_NO_FLICKER
and the
tui
setting. You can also switch with
/tui default
CLAUDE_CODE_DISABLE_ATTACHMENTS
Set to
1
to disable attachment processing. File mentions with
@
syntax are sent as plain text instead of being expanded into file content
CLAUDE_CODE_DISABLE_AUTO_MEMORY
Set to
1
to disable
auto memory
. Set to
0
to force auto memory on even when
--bare
mode or
autoMemoryEnabled: false
would otherwise disable it. When disabled, Claude does not create or load auto memory files
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
Set to
1
to disable all background task functionality, including the
run_in_background
parameter on Bash and subagent tools, auto-backgrounding, and the Ctrl+B shortcut
CLAUDE_CODE_DISABLE_CLAUDE_MDS
Set to
1
to prevent loading any CLAUDE.md memory files into context, including user, project, and auto-memory files
CLAUDE_CODE_DISABLE_CRON
Set to
1
to disable
scheduled tasks
. The
/loop
skill and cron tools become unavailable and any already-scheduled tasks stop firing, including tasks that are already running mid-session
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS
Set to
1
to strip Anthropic-specific
anthropic-beta
request headers and beta tool-schema fields (such as
defer_loading
and
eager_input_streaming
) from API requests. Use this when a proxy gateway rejects requests with errors like “Unexpected value(s) for the
anthropic-beta
header” or “Extra inputs are not permitted”. Standard fields (
name
,
description
,
input_schema
,
cache_control
) are preserved.
CLAUDE_CODE_DISABLE_FAST_MODE
Set to
1
to disable
fast mode
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
Set to
1
to disable the “How is Claude doing?” session quality surveys. Surveys are also disabled when
DISABLE_TELEMETRY
,
DO_NOT_TRACK
, or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set, unless
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
opts back in. To set a sample rate instead of disabling outright, use the
feedbackSurveyRate
setting. See
Session quality surveys
CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING
Set to
1
to disable file
checkpointing
. The
/rewind
command will not be able to restore code changes
CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS
Set to
1
to remove built-in commit and PR workflow instructions and the git status snapshot from Claude’s system prompt. Useful when using your own git workflow skills. Takes precedence over the
includeGitInstructions
setting when set
CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP
Set to
1
to prevent automatic remapping of Opus 4.0 and 4.1 to the current Opus version on the Anthropic API. Use when you intentionally want to pin an older model. The remap does not run on Bedrock, Vertex, or Foundry
CLAUDE_CODE_DISABLE_MOUSE
Set to
1
to disable mouse tracking in
fullscreen rendering
. Keyboard scrolling with
PgUp
and
PgDn
still works. Use this to keep your terminal’s native copy-on-select behavior
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
Equivalent of setting
DISABLE_AUTOUPDATER
,
DISABLE_FEEDBACK_COMMAND
,
DISABLE_ERROR_REPORTING
, and
DISABLE_TELEMETRY
CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK
Set to
1
to disable the non-streaming fallback when a streaming request fails mid-stream. Streaming errors propagate to the retry layer instead. Useful when a proxy or gateway causes the fallback to produce duplicate tool execution
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL
Set to
1
to skip automatic addition of the official plugin marketplace on first run
CLAUDE_CODE_DISABLE_POLICY_SKILLS
Set to
1
to skip loading skills from the system-wide managed skills directory. Useful for container or CI sessions that should not load operator-provisioned skills
CLAUDE_CODE_DISABLE_TERMINAL_TITLE
Set to
1
to disable automatic terminal title updates based on conversation context
CLAUDE_CODE_DISABLE_THINKING
Set to
1
to force-disable
extended thinking
regardless of model support or other settings. More direct than
MAX_THINKING_TOKENS=0
CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL
Set to
1
to disable virtual scrolling in
fullscreen rendering
and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear
CLAUDE_CODE_EFFORT_LEVEL
Set the effort level for supported models. Values:
low
,
medium
,
high
,
xhigh
,
max
, or
auto
to use the model default. Available levels depend on the model. Takes precedence over
/effort
and the
effortLevel
setting. See
Adjust effort level
CLAUDE_CODE_ENABLE_AWAY_SUMMARY
Override
session recap
availability. Set to
0
to force recaps off regardless of the
/config
toggle. Set to
1
to force recaps on when
awaySummaryEnabled
is
false
. Takes precedence over the setting and
/config
toggle
CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH
Set to
1
to refresh plugin state at turn boundaries in
non-interactive mode
after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates
prompt caching
for that turn
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
Set to
1
to route the “How is Claude doing?” session quality survey to your own
OpenTelemetry collector
when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
,
DISABLE_TELEMETRY
, or
DO_NOT_TRACK
is set, and has no effect otherwise.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
and the organization product feedback policy take precedence
CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING
Controls whether tool call inputs stream from the API as Claude generates them. With this off, a large tool input such as a long file write arrives only after Claude finishes generating it, which can look like it’s hanging. Enabled by default on the Anthropic API. On Bedrock and Vertex, enabled per model where the deployed container supports it. Set to
0
to opt out. Set to
1
to force on when routing through a proxy via
ANTHROPIC_BASE_URL
,
ANTHROPIC_VERTEX_BASE_URL
, or
ANTHROPIC_BEDROCK_BASE_URL
. Off by default on Foundry and
gateway
connections
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY
Set to
1
to populate the
/model
picker from your gateway’s
/v1/models
endpoint when
ANTHROPIC_BASE_URL
points at an Anthropic-compatible gateway such as LiteLLM, Kong, or an internal proxy. Off by default because gateways backed by a shared API key would otherwise show every user every model the key can access. Discovered models are still filtered by the
availableModels
allowlist
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
Set to
1
to run
fast mode
on Claude Opus 4.7 instead of Opus 4.6. With the variable set,
/fast
switches to Opus 4.7; without it,
/fast
continues to use Opus 4.6
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION
Set to
false
to disable prompt suggestions (the “Prompt suggestions” toggle in
/config
). These are the grayed-out predictions that appear in your prompt input after Claude responds. See
Prompt suggestions
CLAUDE_CODE_ENABLE_TASKS
Set to
1
to enable the task tracking system in non-interactive mode (the
-p
flag). Tasks are on by default in interactive mode. See
Task list
CLAUDE_CODE_ENABLE_TELEMETRY
Set to
1
to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. See
Monitoring
CLAUDE_CODE_EXIT_AFTER_STOP_DELAY
Time in milliseconds to wait after the query loop becomes idle before automatically exiting. Useful for automated workflows and scripts using SDK mode
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
Set to
1
to enable
agent teams
. Agent teams are experimental and disabled by default
CLAUDE_CODE_EXTRA_BODY
JSON object to merge into the top level of every API request body. Useful for passing provider-specific parameters that Claude Code does not expose directly
CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS
Override the default token limit for file reads. Useful when you need to read larger files in full
CLAUDE_CODE_FORCE_SYNC_OUTPUT
Set to
1
to force-enable DEC private mode 2026
synchronized output
when your terminal supports it but is not auto-detected. Useful for emulators such as Emacs
eat
that implement BSU/ESU but do not reply to the capability probe. Has no effect under tmux
CLAUDE_CODE_FORK_SUBAGENT
Set to
1
to enable
forked subagents
. A forked subagent inherits the full conversation context from the main session instead of starting fresh. When enabled,
/fork
spawns a forked subagent rather than acting as an alias for
/branch
, and all subagent spawns run in the background. Works in interactive mode and via the SDK or
claude -p
CLAUDE_CODE_GIT_BASH_PATH
Windows only: path to the Git Bash executable (
bash.exe
). Use when Git Bash is installed but not in your PATH. See
Windows setup
CLAUDE_CODE_GLOB_HIDDEN
Set to
false
to exclude dotfiles from results when Claude invokes the
Glob tool
. Included by default. Does not affect
@
file autocomplete,
ls
, Grep, or Read
CLAUDE_CODE_GLOB_NO_IGNORE
Set to
false
to make the
Glob tool
respect
.gitignore
patterns. By default, Glob returns all matching files including gitignored ones. Does not affect
@
file autocomplete, which has its own
respectGitignore
setting
CLAUDE_CODE_GLOB_TIMEOUT_SECONDS
Timeout in seconds for Glob tool file discovery. Defaults to 20 seconds on most platforms and 60 seconds on WSL
CLAUDE_CODE_HIDE_CWD
Set to
1
to hide the working directory in the startup logo. Useful for screenshares or recordings where the path exposes your OS username
CLAUDE_CODE_IDE_HOST_OVERRIDE
Override the host address used to connect to the IDE extension. By default Claude Code auto-detects the correct address, including WSL-to-Windows routing
CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL
Skip auto-installation of IDE extensions. Equivalent to setting
autoInstallIdeExtension
to
false
CLAUDE_CODE_IDE_SKIP_VALID_CHECK
Set to
1
to skip validation of IDE lockfile entries during connection. Use when auto-connect fails to find your IDE despite it running
CLAUDE_CODE_MAX_CONTEXT_TOKENS
Override the context window size Claude Code assumes for the active model. Only takes effect when
DISABLE_COMPACT
is also set. Use this when routing to a model through
ANTHROPIC_BASE_URL
whose context window does not match the built-in size for its name
CLAUDE_CODE_MAX_OUTPUT_TOKENS
Set the maximum number of output tokens for most requests. Defaults and caps vary by model; see
max output tokens
. Increasing this value reduces the effective context window available before
auto-compaction
triggers.
CLAUDE_CODE_MAX_RETRIES
Override the number of times to retry failed API requests (default: 10)
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
Maximum number of read-only tools and subagents that can execute in parallel (default: 10). Higher values increase parallelism but consume more resources
CLAUDE_CODE_MAX_TURNS
Cap the number of agentic turns when no explicit limit is passed. Equivalent to passing
--max-turns
, which takes precedence when both are set. A value that is not a positive integer is rejected at startup with an error rather than treated as no cap
CLAUDE_CODE_MCP_ALLOWLIST_ENV
Set to
1
to spawn stdio MCP servers with only a safe baseline environment plus the server’s configured
env
, instead of inheriting your shell environment
CLAUDE_CODE_NATIVE_CURSOR
Set to
1
to show the terminal’s own cursor at the input caret instead of a drawn block. The cursor respects the terminal’s blink, shape, and focus settings
CLAUDE_CODE_NEW_INIT
Set to
1
to make
/init
run an interactive setup flow. The flow asks which files to generate, including CLAUDE.md, skills, and hooks, before exploring the codebase and writing them. Without this variable,
/init
generates a CLAUDE.md automatically without prompting.
CLAUDE_CODE_NO_FLICKER
Set to
1
to enable
fullscreen rendering
, a research preview that reduces flicker and keeps memory flat in long conversations. Equivalent to the
tui
setting; you can also switch with
/tui fullscreen
CLAUDE_CODE_OAUTH_REFRESH_TOKEN
OAuth refresh token for Claude.ai authentication. When set,
claude auth login
exchanges this token directly instead of opening a browser. Requires
CLAUDE_CODE_OAUTH_SCOPES
. Useful for provisioning authentication in automated environments
CLAUDE_CODE_OAUTH_SCOPES
Space-separated OAuth scopes the refresh token was issued with, such as
"user:profile user:inference user:sessions:claude_code"
. Required when
CLAUDE_CODE_OAUTH_REFRESH_TOKEN
is set
CLAUDE_CODE_OAUTH_TOKEN
OAuth access token for Claude.ai authentication. Alternative to
/login
for SDK and automated environments. Takes precedence over keychain-stored credentials. Generate one with
claude setup-token
CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE
Set to
1
to keep
fast mode
on Claude Opus 4.6. Takes precedence over
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
, so set this if you need to pin Opus 4.6 regardless of how the default changes
CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS
Timeout in milliseconds for flushing pending OpenTelemetry spans (default: 5000). See
Monitoring
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
Interval for refreshing dynamic OpenTelemetry headers in milliseconds (default: 1740000 / 29 minutes). See
Dynamic headers
CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS
Timeout in milliseconds for the OpenTelemetry exporter to finish on shutdown (default: 2000). Increase if metrics are dropped at exit. See
Monitoring
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
Set to
1
to let Claude Code run your package manager’s upgrade command in the background when a new version is available. Applies to Homebrew and WinGet installations. Other package managers continue to show the upgrade command without running it. See
Auto updates
CLAUDE_CODE_PERFORCE_MODE
Set to
1
to enable Perforce-aware write protection. When set, Edit, Write, and NotebookEdit fail with a
p4 edit <file>
hint if the target file lacks the owner-write bit, which Perforce clears on synced files until
p4 edit
opens them. This prevents Claude Code from bypassing Perforce change tracking
CLAUDE_CODE_PLUGIN_CACHE_DIR
Override the plugins root directory. Despite the name, this sets the parent directory, not the cache itself: marketplaces and the plugin cache live in subdirectories under this path. Defaults to
~/.claude/plugins
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
Timeout in milliseconds for git operations when installing or updating plugins (default: 120000). Increase this value for large repositories or slow network connections. See
Git operations time out
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE
Set to
1
to keep the existing marketplace cache when a
git pull
fails instead of wiping and re-cloning. Useful in offline or airgapped environments where re-cloning would fail the same way. See
Marketplace updates fail in offline environments
CLAUDE_CODE_PLUGIN_PREFER_HTTPS
Set to
1
to clone GitHub
owner/repo
plugin sources over HTTPS instead of SSH. Useful in CI runners, containers, or any environment without a configured SSH key for
github.com
CLAUDE_CODE_PLUGIN_SEED_DIR
Path to one or more read-only plugin seed directories, separated by
:
on Unix or
;
on Windows. Use this to bundle a pre-populated plugins directory into a container image. Claude Code registers marketplaces from these directories at startup and uses pre-cached plugins without re-cloning. See
Pre-populate plugins for containers
CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST
Set by host platforms that embed Claude Code and manage model provider routing on its behalf. When set, provider-selection, endpoint, and authentication variables such as
CLAUDE_CODE_USE_BEDROCK
,
ANTHROPIC_BASE_URL
, and
ANTHROPIC_API_KEY
in settings files are ignored so user settings cannot override the host’s routing. The automatic telemetry opt-out for Bedrock, Vertex, and Foundry is also skipped, so telemetry follows the standard
DISABLE_TELEMETRY
opt-out. See
Default behaviors by API provider
CLAUDE_CODE_PROXY_RESOLVES_HOSTS
Set to
1
to allow the proxy to perform DNS resolution instead of the caller. Opt-in for environments where the proxy should handle hostname resolution
CLAUDE_CODE_REMOTE
Set automatically to
true
when Claude Code is running as a
cloud session
. Read this from a hook or setup script to detect whether you are in a cloud environment
CLAUDE_CODE_REMOTE_SESSION_ID
Set automatically in
cloud sessions
to the current session’s ID. Read this to construct a link back to the session transcript. See
Link artifacts back to the session
CLAUDE_CODE_RESUME_INTERRUPTED_TURN
Set to
1
to automatically resume if the previous session ended mid-turn. Used in SDK mode so the model continues without requiring the SDK to re-send the prompt
CLAUDE_CODE_RESUME_PROMPT
Override the continuation message injected when resuming a session that ended mid-turn. Defaults to
Continue from where you left off.
. Spawn scripts for long-running agents can set this to a more directive boot message. An empty string uses the default
CLAUDE_CODE_SCRIPT_CAPS
JSON object limiting how many times specific scripts may be invoked per session when
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
is set. Keys are substrings matched against the command text; values are integer call limits. For example,
{"deploy.sh": 2}
allows
deploy.sh
to be called at most twice. Matching is substring-based so shell-expansion tricks like
./scripts/deploy.sh $(evil)
still count against the cap. Runtime fan-out via
xargs
or
find -exec
is not detected; this is a defense-in-depth control
CLAUDE_CODE_SCROLL_SPEED
Set the mouse wheel scroll multiplier in
fullscreen rendering
. Accepts values from 1 to 20. Set to
3
to match
vim
if your terminal sends one wheel event per notch without amplification. Ignored in the JetBrains IDE terminal, where Claude Code uses its own scroll handling
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
Override the time budget in milliseconds for
SessionEnd
hooks. Applies to session exit,
/clear
, and switching sessions via interactive
/resume
. By default the budget is 1.5 seconds, automatically raised to the highest per-hook
timeout
configured in settings files, up to 60 seconds. Timeouts on plugin-provided hooks do not raise the budget
CLAUDE_CODE_SESSION_ID
Set automatically in Bash and PowerShell tool subprocesses to the current session ID. Matches the
session_id
field passed to
hooks
. Updated on
/clear
. Use to correlate scripts and external tools with the Claude Code session that launched them
CLAUDE_CODE_SHELL
Override automatic shell detection. Useful when your login shell differs from your preferred working shell (for example,
bash
vs
zsh
)
CLAUDE_CODE_SHELL_PREFIX
Command prefix that wraps shell commands Claude Code spawns: Bash tool calls,
hook
commands, and stdio
MCP server
startup commands. Useful for logging or auditing. Example: setting
/path/to/logger.sh
runs each command as
/path/to/logger.sh <command>
CLAUDE_CODE_SIMPLE
Set to
1
to run with a minimal system prompt and only the Bash, file read, and file edit tools. MCP tools from
--mcp-config
are still available. Disables auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. The
--bare
CLI flag sets this
CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT
Set to
1
to use a shorter system prompt and abbreviated tool descriptions on any model. Set to
0
,
false
,
no
, or
off
to opt out even on models where the experiment or server configuration would otherwise enable it. The full tool set, hooks, MCP servers, and CLAUDE.md discovery remain enabled
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
Skip client-side authentication for
Claude Platform on AWS
, for gateways that sign requests themselves
CLAUDE_CODE_SKIP_BEDROCK_AUTH
Skip AWS authentication for Bedrock (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_FOUNDRY_AUTH
Skip Azure authentication for Microsoft Foundry (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_MANTLE_AUTH
Skip AWS authentication for Bedrock Mantle (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_PROMPT_HISTORY
Set to
1
to skip writing prompt history and session transcripts to disk. Sessions started with this variable set do not appear in
--resume
,
--continue
, or up-arrow history. Useful for ephemeral scripted sessions
CLAUDE_CODE_SKIP_VERTEX_AUTH
Skip Google authentication for Vertex (for example, when using an LLM gateway)
CLAUDE_CODE_SUBAGENT_MODEL
See
Model configuration
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
Set to
1
to strip Anthropic and cloud provider credentials from subprocess environments (Bash tool, hooks, MCP stdio servers). The parent Claude process keeps these credentials for API calls, but child processes cannot read them, reducing exposure to prompt injection attacks that attempt to exfiltrate secrets via shell expansion. On Linux, this also runs Bash subprocesses in an isolated PID namespace so they cannot read host process environments via
/proc
; as a side effect,
ps
,
pgrep
, and
kill
cannot see or signal host processes.
claude-code-action
sets this automatically when
allowed_non_write_users
is configured
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
Set to
1
in non-interactive mode (the
-p
flag) to wait for plugin installation to complete before the first query. Without this, plugins install in the background and may not be available on the first turn. Combine with
CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS
to bound the wait
CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS
Timeout in milliseconds for synchronous plugin installation. When exceeded, Claude Code proceeds without plugins and logs an error. No default: without this variable, synchronous installation waits until complete
CLAUDE_CODE_SYNTAX_HIGHLIGHT
Set to
false
to disable syntax highlighting in diff output. Useful when colors interfere with your terminal setup. To also disable highlighting in code blocks and file previews, use the
syntaxHighlightingDisabled
setting
CLAUDE_CODE_TASK_LIST_ID
Share a task list across sessions. Set the same ID in multiple Claude Code instances to coordinate on a shared task list. See
Task list
CLAUDE_CODE_TEAM_NAME
Name of the agent team this teammate belongs to. Set automatically on
agent team
members
CLAUDE_CODE_TMPDIR
Override the temp directory used for internal temp files. Claude Code appends
/claude-{uid}/
(Unix) or
/claude/
(Windows) to this path. Default:
/tmp
on macOS,
os.tmpdir()
on Linux/Windows
CLAUDE_CODE_TMUX_TRUECOLOR
Set to
1
to allow 24-bit truecolor output inside tmux. By default, Claude Code clamps to 256 colors when
$TMUX
is set because tmux does not pass through truecolor escape sequences unless configured to. Set this after adding
set -ga terminal-overrides ',*:Tc'
to your
~/.tmux.conf
. See
Terminal configuration
for other tmux settings
CLAUDE_CODE_USE_ANTHROPIC_AWS
Use
Claude Platform on AWS
CLAUDE_CODE_USE_BEDROCK
Use
Bedrock
CLAUDE_CODE_USE_FOUNDRY
Use
Microsoft Foundry
CLAUDE_CODE_USE_MANTLE
Use the Bedrock
Mantle endpoint
CLAUDE_CODE_USE_NATIVE_FILE_SEARCH
Set to
1
to discover custom commands, subagents, and output styles using Node.js file APIs instead of ripgrep. Set this if the bundled ripgrep binary is unavailable or blocked in your environment. Does not affect the Grep or file search tools
CLAUDE_CODE_USE_POWERSHELL_TOOL
Controls the PowerShell tool. On Windows without Git Bash, the tool is enabled automatically; set to
0
to disable it. On Windows with Git Bash installed, the tool is rolling out progressively: set to
1
to opt in or
0
to opt out. On Linux, macOS, and WSL, set to
1
to enable it, which requires
pwsh
on your
PATH
. When enabled on Windows, Claude can run PowerShell commands natively instead of routing through Git Bash. See
PowerShell tool
CLAUDE_CODE_USE_VERTEX
Use
Vertex
CLAUDE_CONFIG_DIR
Override the configuration directory (default:
~/.claude
). All settings, credentials, session history, and plugins are stored under this path. Useful for running multiple accounts side by side: for example,
alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'
CLAUDE_EFFORT
Set automatically in Bash tool subprocesses and hook commands to the active
effort level
for the turn:
low
,
medium
,
high
,
xhigh
, or
max
. Matches the
effort.level
field passed to
hooks
. Only set when the current model supports the effort parameter
CLAUDE_ENABLE_BYTE_WATCHDOG
Set to
1
to force-enable the byte-level streaming idle watchdog, or set to
0
to force-disable it. When unset, the watchdog is enabled by default for Anthropic API connections. The byte watchdog aborts a connection when no bytes arrive on the wire for the duration set by
CLAUDE_STREAM_IDLE_TIMEOUT_MS
, with a minimum of 5 minutes, independent of the event-level watchdog
CLAUDE_ENABLE_STREAM_WATCHDOG
Set to
1
to enable the event-level streaming idle watchdog. Off by default. For Bedrock, Vertex, and Foundry, this is the only idle watchdog available. Configure the timeout with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
CLAUDE_ENV_FILE
Path to a shell script whose contents Claude Code runs before each Bash command in the same shell process, so exports in the file are visible to the command. Use to persist virtualenv or conda activation across commands. Also populated dynamically by
SessionStart
,
Setup
,
CwdChanged
, and
FileChanged
hooks
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
Prefix for auto-generated
Remote Control
session names when no explicit name is provided. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. The
--remote-control-session-name-prefix
CLI flag sets the same value for a single invocation
CLAUDE_STREAM_IDLE_TIMEOUT_MS
Timeout in milliseconds before the streaming idle watchdog closes a stalled connection. Default and minimum
300000
(5 minutes) for both the byte-level and event-level watchdogs; lower values are silently clamped to absorb extended thinking pauses and proxy buffering. For third-party providers, requires
CLAUDE_ENABLE_STREAM_WATCHDOG=1
DEBUG
Set to
1
to enable debug mode, equivalent to launching with
--debug
. Debug logs are written to
~/.claude/debug/<session-id>.txt
, or to the path set by
CLAUDE_CODE_DEBUG_LOGS_DIR
. Only the truthy values
1
,
true
,
yes
, and
on
enable debug mode, so namespace patterns like
DEBUG=express:*
set for other tools do not trigger it
DISABLE_AUTOUPDATER
Set to
1
to disable automatic background updates. Manual
claude update
still works. Use
DISABLE_UPDATES
to block both
DISABLE_AUTO_COMPACT
Set to
1
to disable automatic compaction when approaching the context limit. The manual
/compact
command remains available. Use when you want explicit control over when compaction occurs
DISABLE_COMPACT
Set to
1
to disable all compaction: both automatic compaction and the manual
/compact
command
DISABLE_COST_WARNINGS
Set to
1
to disable cost warning messages
DISABLE_DOCTOR_COMMAND
Set to
1
to hide the
/doctor
command. Useful for managed deployments where users should not run installation diagnostics
DISABLE_ERROR_REPORTING
Set to
1
to opt out of Sentry error reporting
DISABLE_EXTRA_USAGE_COMMAND
Set to
1
to hide the
/extra-usage
command that lets users purchase additional usage beyond rate limits
DISABLE_FEEDBACK_COMMAND
Set to
1
to disable the
/feedback
command. The older name
DISABLE_BUG_COMMAND
is also accepted
DISABLE_GROWTHBOOK
Set to
1
to disable GrowthBook feature-flag fetching and use code defaults for every flag. Telemetry event logging stays on unless
DISABLE_TELEMETRY
is also set
DISABLE_INSTALLATION_CHECKS
Set to
1
to disable installation warnings. Use only when manually managing the installation location, as this can mask issues with standard installations
DISABLE_INSTALL_GITHUB_APP_COMMAND
Set to
1
to hide the
/install-github-app
command. Already hidden when using third-party providers (Bedrock, Vertex, or Foundry)
DISABLE_INTERLEAVED_THINKING
Set to
1
to prevent sending the interleaved-thinking beta header. Useful when your LLM gateway or provider does not support
interleaved thinking
DISABLE_LOGIN_COMMAND
Set to
1
to hide the
/login
command. Useful when authentication is handled externally via API keys or
apiKeyHelper
DISABLE_LOGOUT_COMMAND
Set to
1
to hide the
/logout
command
DISABLE_PROMPT_CACHING
Set to
1
to disable prompt caching for all models (takes precedence over per-model settings)
DISABLE_PROMPT_CACHING_HAIKU
Set to
1
to disable prompt caching for Haiku models
DISABLE_PROMPT_CACHING_OPUS
Set to
1
to disable prompt caching for Opus models
DISABLE_PROMPT_CACHING_SONNET
Set to
1
to disable prompt caching for Sonnet models
DISABLE_TELEMETRY
Set to
1
to opt out of telemetry. Telemetry events do not include user data like code, file paths, or bash commands. Also disables feature flags, so some features that are still rolling out may not be available
DISABLE_UPDATES
Set to
1
to block all updates including manual
claude update
and
claude install
. Stricter than
DISABLE_AUTOUPDATER
. Use when distributing Claude Code through your own channels and users should not self-update
DISABLE_UPGRADE_COMMAND
Set to
1
to hide the
/upgrade
command
DO_NOT_TRACK
Set to
1
to opt out of telemetry. Equivalent to setting
DISABLE_TELEMETRY
. Honored as the
standard cross-tool convention
ENABLE_CLAUDEAI_MCP_SERVERS
Set to
false
to disable
claude.ai MCP servers
in Claude Code. Enabled by default for logged-in users
ENABLE_PROMPT_CACHING_1H
Set to
1
to request a 1-hour prompt cache TTL instead of the default 5 minutes. Intended for API key,
Bedrock
,
Vertex
,
Foundry
, and
Claude Platform on AWS
users. Subscription users receive 1-hour TTL automatically. 1-hour cache writes are billed at a higher rate
ENABLE_PROMPT_CACHING_1H_BEDROCK
Deprecated. Use
ENABLE_PROMPT_CACHING_1H
instead
ENABLE_TOOL_SEARCH
Controls
MCP tool search
. Unset: all MCP tools deferred by default, but loaded upfront on Vertex AI or when
ANTHROPIC_BASE_URL
points to a non-first-party host. Values:
true
(always defer and send the beta header; supported on Vertex AI with Sonnet 4.5 and later or Opus 4.5 and later; requests fail on earlier Vertex AI models or on proxies that do not support
tool_reference
),
auto
(threshold mode: load upfront if tools fit within 10% of context),
auto:N
(custom threshold, e.g.,
auto:5
for 5%),
false
(load all upfront)
FALLBACK_FOR_ALL_PRIMARY_MODELS
Set to any non-empty value to trigger fallback to
--fallback-model
after repeated overload errors on any primary model. By default, only Opus models trigger the fallback
FORCE_AUTOUPDATE_PLUGINS
Set to
1
to force plugin auto-updates even when the main auto-updater is disabled via
DISABLE_AUTOUPDATER
FORCE_PROMPT_CACHING_5M
Set to
1
to force the 5-minute prompt cache TTL even when 1-hour TTL would otherwise apply. Overrides
ENABLE_PROMPT_CACHING_1H
HTTP_PROXY
Specify HTTP proxy server for network connections
HTTPS_PROXY
Specify HTTPS proxy server for network connections
IS_DEMO
Set to
1
to enable demo mode: hides your email and organization name from the header and
/status
output, and skips onboarding. Useful when streaming or recording a session
MAX_MCP_OUTPUT_TOKENS
Maximum number of tokens allowed in MCP tool responses. Claude Code displays a warning when output exceeds 10,000 tokens. Tools that declare
anthropic/maxResultSizeChars
use that character limit for text content instead, but image content from those tools is still subject to this variable (default: 25000)
MAX_STRUCTURED_OUTPUT_RETRIES
Number of times to retry when the model’s response fails validation against the
--json-schema
in non-interactive mode (the
-p
flag). Defaults to 5
MAX_THINKING_TOKENS
Override the
extended thinking
token budget. The ceiling is the model’s
max output tokens
minus one. Set to
0
to disable thinking entirely. On models with
adaptive reasoning
, the budget is ignored unless adaptive reasoning is disabled via
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
MCP_CLIENT_SECRET
OAuth client secret for MCP servers that require
pre-configured credentials
. Avoids the interactive prompt when adding a server with
--client-secret
MCP_CONNECTION_NONBLOCKING
Set to
true
in non-interactive mode (
-p
) to skip the MCP connection wait entirely. Useful for scripted pipelines where MCP tools are not needed. Without this variable, the first query waits up to 5 seconds for
--mcp-config
server connections. Servers configured with
alwaysLoad: true
always block startup regardless of this variable, since their tools must be present when the first prompt is built
MCP_CONNECT_TIMEOUT_MS
How long the first query waits, in milliseconds, for the MCP connection batch before snapshotting the tool list (default: 5000). Servers still pending at the deadline keep connecting in the background but won’t appear until the next query. Distinct from
MCP_TIMEOUT
, which bounds an individual server’s connect attempt. Most relevant to non-interactive sessions that issue a single query and need slow-connecting servers to be visible
MCP_OAUTH_CALLBACK_PORT
Fixed port for the OAuth redirect callback, as an alternative to
--callback-port
when adding an MCP server with
pre-configured credentials
MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE
Maximum number of remote MCP servers (HTTP/SSE) to connect in parallel during startup (default: 20)
MCP_SERVER_CONNECTION_BATCH_SIZE
Maximum number of local MCP servers (stdio) to connect in parallel during startup (default: 3)
MCP_TIMEOUT
Timeout in milliseconds for MCP server startup (default: 30000, or 30 seconds)
MCP_TOOL_TIMEOUT
Timeout in milliseconds for MCP tool execution (default: 100000000, about 28 hours)
NO_PROXY
List of domains and IPs to which requests will be directly issued, bypassing proxy
OTEL_LOG_RAW_API_BODIES
Emit Anthropic Messages API request and response JSON as
api_request_body
/
api_response_body
log events. Set to
1
for inline bodies truncated at 60 KB, or
file:<dir>
to write untruncated bodies to disk and emit a
body_ref
path instead. Disabled by default; bodies include the entire conversation history. See
Monitoring
OTEL_LOG_TOOL_CONTENT
Set to
1
to include tool input and output content in OpenTelemetry span events. Disabled by default to protect sensitive data. See
Monitoring
OTEL_LOG_TOOL_DETAILS
Set to
1
to include tool input arguments, MCP server names, raw error strings on tool failures, and other tool details in OpenTelemetry traces and logs. Disabled by default to protect PII. See
Monitoring
OTEL_LOG_USER_PROMPTS
Set to
1
to include user prompt text in OpenTelemetry traces and logs. Disabled by default (prompts are redacted). See
Monitoring
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
Set to
false
to exclude account UUID from metrics attributes (default: included). See
Monitoring
OTEL_METRICS_INCLUDE_SESSION_ID
Set to
false
to exclude session ID from metrics attributes (default: included). See
Monitoring
OTEL_METRICS_INCLUDE_VERSION
Set to
true
to include Claude Code version in metrics attributes (default: excluded). See
Monitoring
SLASH_COMMAND_TOOL_CHAR_BUDGET
Override the character budget for skill metadata shown to the
Skill tool
. The budget scales dynamically at 1% of the context window, with a fallback of 8,000 characters. Legacy name kept for backwards compatibility
TASK_MAX_OUTPUT_LENGTH
Maximum number of characters in
subagent
output before truncation (default: 32000, maximum: 160000). When truncated, the full output is saved to disk and the path is included in the truncated response
USE_BUILTIN_RIPGREP
Set to
0
to use system-installed
rg
instead of
rg
included with Claude Code
VERTEX_REGION_CLAUDE_3_5_HAIKU
Override region for Claude 3.5 Haiku when using Vertex AI
VERTEX_REGION_CLAUDE_3_5_SONNET
Override region for Claude 3.5 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_3_7_SONNET
Override region for Claude 3.7 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_4_0_OPUS
Override region for Claude 4.0 Opus when using Vertex AI
VERTEX_REGION_CLAUDE_4_0_SONNET
Override region for Claude 4.0 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_4_1_OPUS
Override region for Claude 4.1 Opus when using Vertex AI
VERTEX_REGION_CLAUDE_4_5_OPUS
Override region for Claude Opus 4.5 when using Vertex AI
VERTEX_REGION_CLAUDE_4_5_SONNET
Override region for Claude Sonnet 4.5 when using Vertex AI
VERTEX_REGION_CLAUDE_4_6_OPUS
Override region for Claude Opus 4.6 when using Vertex AI
VERTEX_REGION_CLAUDE_4_6_SONNET
Override region for Claude Sonnet 4.6 when using Vertex AI
VERTEX_REGION_CLAUDE_4_7_OPUS
Override region for Claude Opus 4.7 when using Vertex AI
VERTEX_REGION_CLAUDE_HAIKU_4_5
Override region for Claude Haiku 4.5 when using Vertex AI
Standard OpenTelemetry exporter variables (
OTEL_METRICS_EXPORTER
,
OTEL_LOGS_EXPORTER
,
OTEL_EXPORTER_OTLP_ENDPOINT
,
OTEL_EXPORTER_OTLP_PROTOCOL
,
OTEL_EXPORTER_OTLP_HEADERS
,
OTEL_METRIC_EXPORT_INTERVAL
,
OTEL_RESOURCE_ATTRIBUTES
, and signal-specific variants) are also supported. See
Monitoring
for configuration details.
​
See also
Settings
: configure environment variables in
settings.json
so they apply to every session
CLI reference
: launch-time flags
Network configuration
: proxy and TLS setup
Monitoring
: OpenTelemetry configuration
Was this page helpful?
Yes
No
Commands
Tools reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/env-vars" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Environment variables
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports the following environ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Environment variables
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports the following environment variables to control its behavior. Set them in your shell before launching
claude
, or configure them in
settings.json
under the
env
key to apply them to every session or roll them out across your team.
Variable
Purpose
ANTHROPIC_API_KEY
API key sent as
X-Api-Key
header. When set, this key is used instead of your Claude Pro, Max, Team, or Enterprise subscription even if you are logged in. In non-interactive mode (
-p
), the key is always used when present. In interactive mode, you are prompted to approve the key once before it overrides your subscription. To use your subscription instead, run
unset ANTHROPIC_API_KEY
ANTHROPIC_AUTH_TOKEN
Custom value for the
Authorization
header (the value you set here will be prefixed with
Bearer
)
ANTHROPIC_AWS_API_KEY
Workspace API key for
Claude Platform on AWS
, generated in the AWS Console. Sent as
x-api-key
and takes precedence over AWS SigV4
ANTHROPIC_AWS_BASE_URL
Override the
Claude Platform on AWS
endpoint URL. Use for custom regions or when routing through an
LLM gateway
. Defaults to
https://aws-external-anthropic.{AWS_REGION}.api.aws
ANTHROPIC_AWS_WORKSPACE_ID
Required for
Claude Platform on AWS
. Sent on every request as the
anthropic-workspace-id
header
ANTHROPIC_BASE_URL
Override the API endpoint to route requests through a proxy or gateway. When set to a non-first-party host,
MCP tool search
is disabled by default. Set
ENABLE_TOOL_SEARCH=true
if your proxy forwards
tool_reference
blocks
ANTHROPIC_BEDROCK_BASE_URL
Override the Bedrock endpoint URL. Use for custom Bedrock endpoints or when routing through an
LLM gateway
. See
Amazon Bedrock
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
Override the Bedrock Mantle endpoint URL. See
Mantle endpoint
ANTHROPIC_BEDROCK_SERVICE_TIER
Bedrock
service tier
(
default
,
flex
, or
priority
). Sent as the
X-Amzn-Bedrock-Service-Tier
header. See
Amazon Bedrock
ANTHROPIC_BETAS
Comma-separated list of additional
anthropic-beta
header values to include in API requests. Claude Code already sends the beta headers it needs; use this to opt into an
Anthropic API beta
before Claude Code adds native support. Unlike the
--betas
flag
, which requires API key authentication, this variable works with all auth methods including Claude.ai subscription
ANTHROPIC_CUSTOM_HEADERS
Custom headers to add to requests (
Name: Value
format, newline-separated for multiple headers)
ANTHROPIC_CUSTOM_MODEL_OPTION
Model ID to add as a custom entry in the
/model
picker. Use this to make a non-standard or gateway-specific model selectable without replacing built-in aliases. See
Model configuration
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
Display description for the custom model entry in the
/model
picker. Defaults to
Custom model (<model-id>)
when not set
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
Display name for the custom model entry in the
/model
picker. Defaults to the model ID when not set
ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME
See
Model configuration
ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES
See
Model configuration
ANTHROPIC_FOUNDRY_API_KEY
API key for Microsoft Foundry authentication (see
Microsoft Foundry
)
ANTHROPIC_FOUNDRY_BASE_URL
Full base URL for the Foundry resource (for example,
https://my-resource.services.ai.azure.com/anthropic
). Alternative to
ANTHROPIC_FOUNDRY_RESOURCE
(see
Microsoft Foundry
)
ANTHROPIC_FOUNDRY_RESOURCE
Foundry resource name (for example,
my-resource
). Required if
ANTHROPIC_FOUNDRY_BASE_URL
is not set (see
Microsoft Foundry
)
ANTHROPIC_MODEL
Name of the model setting to use (see
Model Configuration
)
ANTHROPIC_SMALL_FAST_MODEL
[DEPRECATED] Name of
Haiku-class model for background tasks
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
Override AWS region for the Haiku-class model when using Bedrock or Bedrock Mantle. On Bedrock, this only takes effect when
ANTHROPIC_DEFAULT_HAIKU_MODEL
or the deprecated
ANTHROPIC_SMALL_FAST_MODEL
is also set, since Bedrock otherwise uses the primary model for background tasks
ANTHROPIC_VERTEX_BASE_URL
Override the Vertex AI endpoint URL. Use for custom Vertex endpoints or when routing through an
LLM gateway
. See
Google Vertex AI
ANTHROPIC_VERTEX_PROJECT_ID
GCP project ID for Vertex AI requests. Overridden by
GCLOUD_PROJECT
,
GOOGLE_CLOUD_PROJECT
, or the project in your
GOOGLE_APPLICATION_CREDENTIALS
credential file. See
Google Vertex AI
ANTHROPIC_WORKSPACE_ID
Workspace ID for
workload identity federation
. Set this when your federation rule is scoped to more than one workspace so the token exchange knows which workspace to target
API_TIMEOUT_MS
Timeout for API requests in milliseconds (default: 600000, or 10 minutes; maximum: 2147483647). Increase this when requests time out on slow networks or when routing through a proxy. Values above the maximum overflow the underlying timer and cause requests to fail immediately
AWS_BEARER_TOKEN_BEDROCK
Bedrock API key for authentication (see
Bedrock API keys
)
BASH_DEFAULT_TIMEOUT_MS
Default timeout for long-running bash commands (default: 120000, or 2 minutes)
BASH_MAX_OUTPUT_LENGTH
Maximum number of characters in bash outputs before the full output is saved to a file and Claude receives the path plus a short preview. See
Bash tool behavior
BASH_MAX_TIMEOUT_MS
Maximum timeout the model can set for long-running bash commands (default: 600000, or 10 minutes)
CCR_FORCE_BUNDLE
Set to
1
to force
claude --remote
to bundle and upload your local repository even when GitHub access is available
CLAUDECODE
Set to
1
in shell environments Claude Code spawns (Bash tool, tmux sessions). Not set in
hooks
or
status line
commands. Use to detect when a script is running inside a shell spawned by Claude Code
CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS
Set to
1
to disable all built-in
subagent
types such as Explore and Plan. Only applies in non-interactive mode (the
-p
flag). Useful for SDK users who want a blank slate
CLAUDE_AGENT_SDK_MCP_NO_PREFIX
Set to
1
to skip the
mcp__<server>__
prefix on tool names from SDK-created MCP servers. Tools use their original names. SDK usage only
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
Stall timeout in milliseconds for background subagents. Default
600000
(10 minutes). The timer resets on each streaming progress event; if no progress arrives within the window, the subagent is aborted and the task is marked failed, surfacing any partial result to the parent
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
Set the percentage of context capacity (1-100) at which auto-compaction triggers. By default, auto-compaction triggers at approximately 95% capacity. Use lower values like
50
to compact earlier. Values above the default threshold have no effect. Applies to both main conversations and subagents. This percentage aligns with the
context_window.used_percentage
field available in
status line
CLAUDE_AUTO_BACKGROUND_TASKS
Set to
1
to force-enable automatic backgrounding of long-running agent tasks. When enabled, subagents are moved to the background after running for approximately two minutes
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR
Return to the original working directory after each Bash or PowerShell command in the main session
CLAUDE_CODE_ACCESSIBILITY
Set to
1
to keep the native terminal cursor visible and disable the inverted-text cursor indicator. Allows screen magnifiers like macOS Zoom to track cursor position
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
Set to
1
to load memory files from directories specified with
--add-dir
. Loads
CLAUDE.md
,
.claude/CLAUDE.md
,
.claude/rules/*.md
, and
CLAUDE.local.md
. By default, additional directories do not load memory files
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
Interval in milliseconds at which credentials should be refreshed (when using
apiKeyHelper
)
CLAUDE_CODE_ATTRIBUTION_HEADER
Set to
0
to omit the attribution block (client version and prompt fingerprint) from the start of the system prompt. Disabling it improves prompt-cache hit rates when routing through an
LLM gateway
. Anthropic API caching is unaffected
CLAUDE_CODE_AUTO_COMPACT_WINDOW
Set the context capacity in tokens used for auto-compaction calculations. Defaults to the model’s context window: 200K for standard models or 1M for
extended context
models. Use a lower value like
500000
on a 1M model to treat the window as 500K for compaction purposes. The value is capped at the model’s actual context window.
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
is applied as a percentage of this value. Setting this variable decouples the compaction threshold from the status line’s
used_percentage
, which always uses the model’s full context window
CLAUDE_CODE_AUTO_CONNECT_IDE
Override automatic
IDE connection
. By default, Claude Code connects automatically when launched inside a supported IDE’s integrated terminal. Set to
false
to prevent this. Set to
true
to force a connection attempt when auto-detection fails, such as when tmux obscures the parent terminal. Takes precedence over the
autoConnectIde
global config setting
CLAUDE_CODE_CERT_STORE
Comma-separated list of CA certificate sources for TLS connections.
bundled
is the Mozilla CA set shipped with Claude Code.
system
is the operating system trust store. Default is
bundled,system
CLAUDE_CODE_CLIENT_CERT
Path to client certificate file for mTLS authentication
CLAUDE_CODE_CLIENT_KEY
Path to client private key file for mTLS authentication
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
Passphrase for encrypted CLAUDE_CODE_CLIENT_KEY (optional)
CLAUDE_CODE_DEBUG_LOGS_DIR
Override the debug log file path. Despite the name, this is a file path, not a directory. Requires debug mode to be enabled separately via
--debug
,
/debug
, or the
DEBUG
environment variable: setting this variable alone does not enable logging. The
--debug-file
flag does both at once. Defaults to
~/.claude/debug/<session-id>.txt
CLAUDE_CODE_DEBUG_LOG_LEVEL
Minimum log level written to the debug log file. Values:
verbose
,
debug
(default),
info
,
warn
,
error
. Set to
verbose
to include high-volume diagnostics like full status line command output, or raise to
error
to reduce noise
CLAUDE_CODE_DISABLE_1M_CONTEXT
Set to
1
to disable
1M context window
support. When set, 1M model variants are unavailable in the model picker. Useful for enterprise environments with compliance requirements
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
Set to
1
to disable
adaptive reasoning
on Opus 4.6 and Sonnet 4.6 and fall back to the fixed thinking budget controlled by
MAX_THINKING_TOKENS
. Has no effect on Opus 4.7, which always uses adaptive reasoning
CLAUDE_CODE_DISABLE_AGENT_VIEW
Set to
1
to turn off
background agents and agent view
:
claude agents
,
--bg
,
/background
, and the on-demand supervisor. Equivalent to the
disableAgentView
setting
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN
Set to
1
to disable
fullscreen rendering
and use the classic main-screen renderer. The conversation stays in your terminal’s native scrollback so
Cmd+f
and tmux copy mode work as usual. Takes precedence over
CLAUDE_CODE_NO_FLICKER
and the
tui
setting. You can also switch with
/tui default
CLAUDE_CODE_DISABLE_ATTACHMENTS
Set to
1
to disable attachment processing. File mentions with
@
syntax are sent as plain text instead of being expanded into file content
CLAUDE_CODE_DISABLE_AUTO_MEMORY
Set to
1
to disable
auto memory
. Set to
0
to force auto memory on even when
--bare
mode or
autoMemoryEnabled: false
would otherwise disable it. When disabled, Claude does not create or load auto memory files
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
Set to
1
to disable all background task functionality, including the
run_in_background
parameter on Bash and subagent tools, auto-backgrounding, and the Ctrl+B shortcut
CLAUDE_CODE_DISABLE_CLAUDE_MDS
Set to
1
to prevent loading any CLAUDE.md memory files into context, including user, project, and auto-memory files
CLAUDE_CODE_DISABLE_CRON
Set to
1
to disable
scheduled tasks
. The
/loop
skill and cron tools become unavailable and any already-scheduled tasks stop firing, including tasks that are already running mid-session
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS
Set to
1
to strip Anthropic-specific
anthropic-beta
request headers and beta tool-schema fields (such as
defer_loading
and
eager_input_streaming
) from API requests. Use this when a proxy gateway rejects requests with errors like “Unexpected value(s) for the
anthropic-beta
header” or “Extra inputs are not permitted”. Standard fields (
name
,
description
,
input_schema
,
cache_control
) are preserved.
CLAUDE_CODE_DISABLE_FAST_MODE
Set to
1
to disable
fast mode
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
Set to
1
to disable the “How is Claude doing?” session quality surveys. Surveys are also disabled when
DISABLE_TELEMETRY
,
DO_NOT_TRACK
, or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set, unless
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
opts back in. To set a sample rate instead of disabling outright, use the
feedbackSurveyRate
setting. See
Session quality surveys
CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING
Set to
1
to disable file
checkpointing
. The
/rewind
command will not be able to restore code changes
CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS
Set to
1
to remove built-in commit and PR workflow instructions and the git status snapshot from Claude’s system prompt. Useful when using your own git workflow skills. Takes precedence over the
includeGitInstructions
setting when set
CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP
Set to
1
to prevent automatic remapping of Opus 4.0 and 4.1 to the current Opus version on the Anthropic API. Use when you intentionally want to pin an older model. The remap does not run on Bedrock, Vertex, or Foundry
CLAUDE_CODE_DISABLE_MOUSE
Set to
1
to disable mouse tracking in
fullscreen rendering
. Keyboard scrolling with
PgUp
and
PgDn
still works. Use this to keep your terminal’s native copy-on-select behavior
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
Equivalent of setting
DISABLE_AUTOUPDATER
,
DISABLE_FEEDBACK_COMMAND
,
DISABLE_ERROR_REPORTING
, and
DISABLE_TELEMETRY
CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK
Set to
1
to disable the non-streaming fallback when a streaming request fails mid-stream. Streaming errors propagate to the retry layer instead. Useful when a proxy or gateway causes the fallback to produce duplicate tool execution
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL
Set to
1
to skip automatic addition of the official plugin marketplace on first run
CLAUDE_CODE_DISABLE_POLICY_SKILLS
Set to
1
to skip loading skills from the system-wide managed skills directory. Useful for container or CI sessions that should not load operator-provisioned skills
CLAUDE_CODE_DISABLE_TERMINAL_TITLE
Set to
1
to disable automatic terminal title updates based on conversation context
CLAUDE_CODE_DISABLE_THINKING
Set to
1
to force-disable
extended thinking
regardless of model support or other settings. More direct than
MAX_THINKING_TOKENS=0
CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL
Set to
1
to disable virtual scrolling in
fullscreen rendering
and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear
CLAUDE_CODE_EFFORT_LEVEL
Set the effort level for supported models. Values:
low
,
medium
,
high
,
xhigh
,
max
, or
auto
to use the model default. Available levels depend on the model. Takes precedence over
/effort
and the
effortLevel
setting. See
Adjust effort level
CLAUDE_CODE_ENABLE_AWAY_SUMMARY
Override
session recap
availability. Set to
0
to force recaps off regardless of the
/config
toggle. Set to
1
to force recaps on when
awaySummaryEnabled
is
false
. Takes precedence over the setting and
/config
toggle
CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH
Set to
1
to refresh plugin state at turn boundaries in
non-interactive mode
after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates
prompt caching
for that turn
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
Set to
1
to route the “How is Claude doing?” session quality survey to your own
OpenTelemetry collector
when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
,
DISABLE_TELEMETRY
, or
DO_NOT_TRACK
is set, and has no effect otherwise.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
and the organization product feedback policy take precedence
CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING
Controls whether tool call inputs stream from the API as Claude generates them. With this off, a large tool input such as a long file write arrives only after Claude finishes generating it, which can look like it’s hanging. Enabled by default on the Anthropic API. On Bedrock and Vertex, enabled per model where the deployed container supports it. Set to
0
to opt out. Set to
1
to force on when routing through a proxy via
ANTHROPIC_BASE_URL
,
ANTHROPIC_VERTEX_BASE_URL
, or
ANTHROPIC_BEDROCK_BASE_URL
. Off by default on Foundry and
gateway
connections
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY
Set to
1
to populate the
/model
picker from your gateway’s
/v1/models
endpoint when
ANTHROPIC_BASE_URL
points at an Anthropic-compatible gateway such as LiteLLM, Kong, or an internal proxy. Off by default because gateways backed by a shared API key would otherwise show every user every model the key can access. Discovered models are still filtered by the
availableModels
allowlist
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
Set to
1
to run
fast mode
on Claude Opus 4.7 instead of Opus 4.6. With the variable set,
/fast
switches to Opus 4.7; without it,
/fast
continues to use Opus 4.6
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION
Set to
false
to disable prompt suggestions (the “Prompt suggestions” toggle in
/config
). These are the grayed-out predictions that appear in your prompt input after Claude responds. See
Prompt suggestions
CLAUDE_CODE_ENABLE_TASKS
Set to
1
to enable the task tracking system in non-interactive mode (the
-p
flag). Tasks are on by default in interactive mode. See
Task list
CLAUDE_CODE_ENABLE_TELEMETRY
Set to
1
to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. See
Monitoring
CLAUDE_CODE_EXIT_AFTER_STOP_DELAY
Time in milliseconds to wait after the query loop becomes idle before automatically exiting. Useful for automated workflows and scripts using SDK mode
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
Set to
1
to enable
agent teams
. Agent teams are experimental and disabled by default
CLAUDE_CODE_EXTRA_BODY
JSON object to merge into the top level of every API request body. Useful for passing provider-specific parameters that Claude Code does not expose directly
CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS
Override the default token limit for file reads. Useful when you need to read larger files in full
CLAUDE_CODE_FORCE_SYNC_OUTPUT
Set to
1
to force-enable DEC private mode 2026
synchronized output
when your terminal supports it but is not auto-detected. Useful for emulators such as Emacs
eat
that implement BSU/ESU but do not reply to the capability probe. Has no effect under tmux
CLAUDE_CODE_FORK_SUBAGENT
Set to
1
to enable
forked subagents
. A forked subagent inherits the full conversation context from the main session instead of starting fresh. When enabled,
/fork
spawns a forked subagent rather than acting as an alias for
/branch
, and all subagent spawns run in the background. Works in interactive mode and via the SDK or
claude -p
CLAUDE_CODE_GIT_BASH_PATH
Windows only: path to the Git Bash executable (
bash.exe
). Use when Git Bash is installed but not in your PATH. See
Windows setup
CLAUDE_CODE_GLOB_HIDDEN
Set to
false
to exclude dotfiles from results when Claude invokes the
Glob tool
. Included by default. Does not affect
@
file autocomplete,
ls
, Grep, or Read
CLAUDE_CODE_GLOB_NO_IGNORE
Set to
false
to make the
Glob tool
respect
.gitignore
patterns. By default, Glob returns all matching files including gitignored ones. Does not affect
@
file autocomplete, which has its own
respectGitignore
setting
CLAUDE_CODE_GLOB_TIMEOUT_SECONDS
Timeout in seconds for Glob tool file discovery. Defaults to 20 seconds on most platforms and 60 seconds on WSL
CLAUDE_CODE_HIDE_CWD
Set to
1
to hide the working directory in the startup logo. Useful for screenshares or recordings where the path exposes your OS username
CLAUDE_CODE_IDE_HOST_OVERRIDE
Override the host address used to connect to the IDE extension. By default Claude Code auto-detects the correct address, including WSL-to-Windows routing
CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL
Skip auto-installation of IDE extensions. Equivalent to setting
autoInstallIdeExtension
to
false
CLAUDE_CODE_IDE_SKIP_VALID_CHECK
Set to
1
to skip validation of IDE lockfile entries during connection. Use when auto-connect fails to find your IDE despite it running
CLAUDE_CODE_MAX_CONTEXT_TOKENS
Override the context window size Claude Code assumes for the active model. Only takes effect when
DISABLE_COMPACT
is also set. Use this when routing to a model through
ANTHROPIC_BASE_URL
whose context window does not match the built-in size for its name
CLAUDE_CODE_MAX_OUTPUT_TOKENS
Set the maximum number of output tokens for most requests. Defaults and caps vary by model; see
max output tokens
. Increasing this value reduces the effective context window available before
auto-compaction
triggers.
CLAUDE_CODE_MAX_RETRIES
Override the number of times to retry failed API requests (default: 10)
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
Maximum number of read-only tools and subagents that can execute in parallel (default: 10). Higher values increase parallelism but consume more resources
CLAUDE_CODE_MAX_TURNS
Cap the number of agentic turns when no explicit limit is passed. Equivalent to passing
--max-turns
, which takes precedence when both are set. A value that is not a positive integer is rejected at startup with an error rather than treated as no cap
CLAUDE_CODE_MCP_ALLOWLIST_ENV
Set to
1
to spawn stdio MCP servers with only a safe baseline environment plus the server’s configured
env
, instead of inheriting your shell environment
CLAUDE_CODE_NATIVE_CURSOR
Set to
1
to show the terminal’s own cursor at the input caret instead of a drawn block. The cursor respects the terminal’s blink, shape, and focus settings
CLAUDE_CODE_NEW_INIT
Set to
1
to make
/init
run an interactive setup flow. The flow asks which files to generate, including CLAUDE.md, skills, and hooks, before exploring the codebase and writing them. Without this variable,
/init
generates a CLAUDE.md automatically without prompting.
CLAUDE_CODE_NO_FLICKER
Set to
1
to enable
fullscreen rendering
, a research preview that reduces flicker and keeps memory flat in long conversations. Equivalent to the
tui
setting; you can also switch with
/tui fullscreen
CLAUDE_CODE_OAUTH_REFRESH_TOKEN
OAuth refresh token for Claude.ai authentication. When set,
claude auth login
exchanges this token directly instead of opening a browser. Requires
CLAUDE_CODE_OAUTH_SCOPES
. Useful for provisioning authentication in automated environments
CLAUDE_CODE_OAUTH_SCOPES
Space-separated OAuth scopes the refresh token was issued with, such as
"user:profile user:inference user:sessions:claude_code"
. Required when
CLAUDE_CODE_OAUTH_REFRESH_TOKEN
is set
CLAUDE_CODE_OAUTH_TOKEN
OAuth access token for Claude.ai authentication. Alternative to
/login
for SDK and automated environments. Takes precedence over keychain-stored credentials. Generate one with
claude setup-token
CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE
Set to
1
to keep
fast mode
on Claude Opus 4.6. Takes precedence over
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
, so set this if you need to pin Opus 4.6 regardless of how the default changes
CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS
Timeout in milliseconds for flushing pending OpenTelemetry spans (default: 5000). See
Monitoring
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
Interval for refreshing dynamic OpenTelemetry headers in milliseconds (default: 1740000 / 29 minutes). See
Dynamic headers
CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS
Timeout in milliseconds for the OpenTelemetry exporter to finish on shutdown (default: 2000). Increase if metrics are dropped at exit. See
Monitoring
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
Set to
1
to let Claude Code run your package manager’s upgrade command in the background when a new version is available. Applies to Homebrew and WinGet installations. Other package managers continue to show the upgrade command without running it. See
Auto updates
CLAUDE_CODE_PERFORCE_MODE
Set to
1
to enable Perforce-aware write protection. When set, Edit, Write, and NotebookEdit fail with a
p4 edit <file>
hint if the target file lacks the owner-write bit, which Perforce clears on synced files until
p4 edit
opens them. This prevents Claude Code from bypassing Perforce change tracking
CLAUDE_CODE_PLUGIN_CACHE_DIR
Override the plugins root directory. Despite the name, this sets the parent directory, not the cache itself: marketplaces and the plugin cache live in subdirectories under this path. Defaults to
~/.claude/plugins
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
Timeout in milliseconds for git operations when installing or updating plugins (default: 120000). Increase this value for large repositories or slow network connections. See
Git operations time out
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE
Set to
1
to keep the existing marketplace cache when a
git pull
fails instead of wiping and re-cloning. Useful in offline or airgapped environments where re-cloning would fail the same way. See
Marketplace updates fail in offline environments
CLAUDE_CODE_PLUGIN_PREFER_HTTPS
Set to
1
to clone GitHub
owner/repo
plugin sources over HTTPS instead of SSH. Useful in CI runners, containers, or any environment without a configured SSH key for
github.com
CLAUDE_CODE_PLUGIN_SEED_DIR
Path to one or more read-only plugin seed directories, separated by
:
on Unix or
;
on Windows. Use this to bundle a pre-populated plugins directory into a container image. Claude Code registers marketplaces from these directories at startup and uses pre-cached plugins without re-cloning. See
Pre-populate plugins for containers
CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST
Set by host platforms that embed Claude Code and manage model provider routing on its behalf. When set, provider-selection, endpoint, and authentication variables such as
CLAUDE_CODE_USE_BEDROCK
,
ANTHROPIC_BASE_URL
, and
ANTHROPIC_API_KEY
in settings files are ignored so user settings cannot override the host’s routing. The automatic telemetry opt-out for Bedrock, Vertex, and Foundry is also skipped, so telemetry follows the standard
DISABLE_TELEMETRY
opt-out. See
Default behaviors by API provider
CLAUDE_CODE_PROXY_RESOLVES_HOSTS
Set to
1
to allow the proxy to perform DNS resolution instead of the caller. Opt-in for environments where the proxy should handle hostname resolution
CLAUDE_CODE_REMOTE
Set automatically to
true
when Claude Code is running as a
cloud session
. Read this from a hook or setup script to detect whether you are in a cloud environment
CLAUDE_CODE_REMOTE_SESSION_ID
Set automatically in
cloud sessions
to the current session’s ID. Read this to construct a link back to the session transcript. See
Link artifacts back to the session
CLAUDE_CODE_RESUME_INTERRUPTED_TURN
Set to
1
to automatically resume if the previous session ended mid-turn. Used in SDK mode so the model continues without requiring the SDK to re-send the prompt
CLAUDE_CODE_RESUME_PROMPT
Override the continuation message injected when resuming a session that ended mid-turn. Defaults to
Continue from where you left off.
. Spawn scripts for long-running agents can set this to a more directive boot message. An empty string uses the default
CLAUDE_CODE_SCRIPT_CAPS
JSON object limiting how many times specific scripts may be invoked per session when
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
is set. Keys are substrings matched against the command text; values are integer call limits. For example,
{"deploy.sh": 2}
allows
deploy.sh
to be called at most twice. Matching is substring-based so shell-expansion tricks like
./scripts/deploy.sh $(evil)
still count against the cap. Runtime fan-out via
xargs
or
find -exec
is not detected; this is a defense-in-depth control
CLAUDE_CODE_SCROLL_SPEED
Set the mouse wheel scroll multiplier in
fullscreen rendering
. Accepts values from 1 to 20. Set to
3
to match
vim
if your terminal sends one wheel event per notch without amplification. Ignored in the JetBrains IDE terminal, where Claude Code uses its own scroll handling
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
Override the time budget in milliseconds for
SessionEnd
hooks. Applies to session exit,
/clear
, and switching sessions via interactive
/resume
. By default the budget is 1.5 seconds, automatically raised to the highest per-hook
timeout
configured in settings files, up to 60 seconds. Timeouts on plugin-provided hooks do not raise the budget
CLAUDE_CODE_SESSION_ID
Set automatically in Bash and PowerShell tool subprocesses to the current session ID. Matches the
session_id
field passed to
hooks
. Updated on
/clear
. Use to correlate scripts and external tools with the Claude Code session that launched them
CLAUDE_CODE_SHELL
Override automatic shell detection. Useful when your login shell differs from your preferred working shell (for example,
bash
vs
zsh
)
CLAUDE_CODE_SHELL_PREFIX
Command prefix that wraps shell commands Claude Code spawns: Bash tool calls,
hook
commands, and stdio
MCP server
startup commands. Useful for logging or auditing. Example: setting
/path/to/logger.sh
runs each command as
/path/to/logger.sh <command>
CLAUDE_CODE_SIMPLE
Set to
1
to run with a minimal system prompt and only the Bash, file read, and file edit tools. MCP tools from
--mcp-config
are still available. Disables auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. The
--bare
CLI flag sets this
CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT
Set to
1
to use a shorter system prompt and abbreviated tool descriptions on any model. Set to
0
,
false
,
no
, or
off
to opt out even on models where the experiment or server configuration would otherwise enable it. The full tool set, hooks, MCP servers, and CLAUDE.md discovery remain enabled
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
Skip client-side authentication for
Claude Platform on AWS
, for gateways that sign requests themselves
CLAUDE_CODE_SKIP_BEDROCK_AUTH
Skip AWS authentication for Bedrock (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_FOUNDRY_AUTH
Skip Azure authentication for Microsoft Foundry (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_MANTLE_AUTH
Skip AWS authentication for Bedrock Mantle (for example, when using an LLM gateway)
CLAUDE_CODE_SKIP_PROMPT_HISTORY
Set to
1
to skip writing prompt history and session transcripts to disk. Sessions started with this variable set do not appear in
--resume
,
--continue
, or up-arrow history. Useful for ephemeral scripted sessions
CLAUDE_CODE_SKIP_VERTEX_AUTH
Skip Google authentication for Vertex (for example, when using an LLM gateway)
CLAUDE_CODE_SUBAGENT_MODEL
See
Model configuration
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
Set to
1
to strip Anthropic and cloud provider credentials from subprocess environments (Bash tool, hooks, MCP stdio servers). The parent Claude process keeps these credentials for API calls, but child processes cannot read them, reducing exposure to prompt injection attacks that attempt to exfiltrate secrets via shell expansion. On Linux, this also runs Bash subprocesses in an isolated PID namespace so they cannot read host process environments via
/proc
; as a side effect,
ps
,
pgrep
, and
kill
cannot see or signal host processes.
claude-code-action
sets this automatically when
allowed_non_write_users
is configured
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
Set to
1
in non-interactive mode (the
-p
flag) to wait for plugin installation to complete before the first query. Without this, plugins install in the background and may not be available on the first turn. Combine with
CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS
to bound the wait
CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS
Timeout in milliseconds for synchronous plugin installation. When exceeded, Claude Code proceeds without plugins and logs an error. No default: without this variable, synchronous installation waits until complete
CLAUDE_CODE_SYNTAX_HIGHLIGHT
Set to
false
to disable syntax highlighting in diff output. Useful when colors interfere with your terminal setup. To also disable highlighting in code blocks and file previews, use the
syntaxHighlightingDisabled
setting
CLAUDE_CODE_TASK_LIST_ID
Share a task list across sessions. Set the same ID in multiple Claude Code instances to coordinate on a shared task list. See
Task list
CLAUDE_CODE_TEAM_NAME
Name of the agent team this teammate belongs to. Set automatically on
agent team
members
CLAUDE_CODE_TMPDIR
Override the temp directory used for internal temp files. Claude Code appends
/claude-{uid}/
(Unix) or
/claude/
(Windows) to this path. Default:
/tmp
on macOS,
os.tmpdir()
on Linux/Windows
CLAUDE_CODE_TMUX_TRUECOLOR
Set to
1
to allow 24-bit truecolor output inside tmux. By default, Claude Code clamps to 256 colors when
$TMUX
is set because tmux does not pass through truecolor escape sequences unless configured to. Set this after adding
set -ga terminal-overrides ',*:Tc'
to your
~/.tmux.conf
. See
Terminal configuration
for other tmux settings
CLAUDE_CODE_USE_ANTHROPIC_AWS
Use
Claude Platform on AWS
CLAUDE_CODE_USE_BEDROCK
Use
Bedrock
CLAUDE_CODE_USE_FOUNDRY
Use
Microsoft Foundry
CLAUDE_CODE_USE_MANTLE
Use the Bedrock
Mantle endpoint
CLAUDE_CODE_USE_NATIVE_FILE_SEARCH
Set to
1
to discover custom commands, subagents, and output styles using Node.js file APIs instead of ripgrep. Set this if the bundled ripgrep binary is unavailable or blocked in your environment. Does not affect the Grep or file search tools
CLAUDE_CODE_USE_POWERSHELL_TOOL
Controls the PowerShell tool. On Windows without Git Bash, the tool is enabled automatically; set to
0
to disable it. On Windows with Git Bash installed, the tool is rolling out progressively: set to
1
to opt in or
0
to opt out. On Linux, macOS, and WSL, set to
1
to enable it, which requires
pwsh
on your
PATH
. When enabled on Windows, Claude can run PowerShell commands natively instead of routing through Git Bash. See
PowerShell tool
CLAUDE_CODE_USE_VERTEX
Use
Vertex
CLAUDE_CONFIG_DIR
Override the configuration directory (default:
~/.claude
). All settings, credentials, session history, and plugins are stored under this path. Useful for running multiple accounts side by side: for example,
alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'
CLAUDE_EFFORT
Set automatically in Bash tool subprocesses and hook commands to the active
effort level
for the turn:
low
,
medium
,
high
,
xhigh
, or
max
. Matches the
effort.level
field passed to
hooks
. Only set when the current model supports the effort parameter
CLAUDE_ENABLE_BYTE_WATCHDOG
Set to
1
to force-enable the byte-level streaming idle watchdog, or set to
0
to force-disable it. When unset, the watchdog is enabled by default for Anthropic API connections. The byte watchdog aborts a connection when no bytes arrive on the wire for the duration set by
CLAUDE_STREAM_IDLE_TIMEOUT_MS
, with a minimum of 5 minutes, independent of the event-level watchdog
CLAUDE_ENABLE_STREAM_WATCHDOG
Set to
1
to enable the event-level streaming idle watchdog. Off by default. For Bedrock, Vertex, and Foundry, this is the only idle watchdog available. Configure the timeout with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
CLAUDE_ENV_FILE
Path to a shell script whose contents Claude Code runs before each Bash command in the same shell process, so exports in the file are visible to the command. Use to persist virtualenv or conda activation across commands. Also populated dynamically by
SessionStart
,
Setup
,
CwdChanged
, and
FileChanged
hooks
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
Prefix for auto-generated
Remote Control
session names when no explicit name is provided. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. The
--remote-control-session-name-prefix
CLI flag sets the same value for a single invocation
CLAUDE_STREAM_IDLE_TIMEOUT_MS
Timeout in milliseconds before the streaming idle watchdog closes a stalled connection. Default and minimum
300000
(5 minutes) for both the byte-level and event-level watchdogs; lower values are silently clamped to absorb extended thinking pauses and proxy buffering. For third-party providers, requires
CLAUDE_ENABLE_STREAM_WATCHDOG=1
DEBUG
Set to
1
to enable debug mode, equivalent to launching with
--debug
. Debug logs are written to
~/.claude/debug/<session-id>.txt
, or to the path set by
CLAUDE_CODE_DEBUG_LOGS_DIR
. Only the truthy values
1
,
true
,
yes
, and
on
enable debug mode, so namespace patterns like
DEBUG=express:*
set for other tools do not trigger it
DISABLE_AUTOUPDATER
Set to
1
to disable automatic background updates. Manual
claude update
still works. Use
DISABLE_UPDATES
to block both
DISABLE_AUTO_COMPACT
Set to
1
to disable automatic compaction when approaching the context limit. The manual
/compact
command remains available. Use when you want explicit control over when compaction occurs
DISABLE_COMPACT
Set to
1
to disable all compaction: both automatic compaction and the manual
/compact
command
DISABLE_COST_WARNINGS
Set to
1
to disable cost warning messages
DISABLE_DOCTOR_COMMAND
Set to
1
to hide the
/doctor
command. Useful for managed deployments where users should not run installation diagnostics
DISABLE_ERROR_REPORTING
Set to
1
to opt out of Sentry error reporting
DISABLE_EXTRA_USAGE_COMMAND
Set to
1
to hide the
/extra-usage
command that lets users purchase additional usage beyond rate limits
DISABLE_FEEDBACK_COMMAND
Set to
1
to disable the
/feedback
command. The older name
DISABLE_BUG_COMMAND
is also accepted
DISABLE_GROWTHBOOK
Set to
1
to disable GrowthBook feature-flag fetching and use code defaults for every flag. Telemetry event logging stays on unless
DISABLE_TELEMETRY
is also set
DISABLE_INSTALLATION_CHECKS
Set to
1
to disable installation warnings. Use only when manually managing the installation location, as this can mask issues with standard installations
DISABLE_INSTALL_GITHUB_APP_COMMAND
Set to
1
to hide the
/install-github-app
command. Already hidden when using third-party providers (Bedrock, Vertex, or Foundry)
DISABLE_INTERLEAVED_THINKING
Set to
1
to prevent sending the interleaved-thinking beta header. Useful when your LLM gateway or provider does not support
interleaved thinking
DISABLE_LOGIN_COMMAND
Set to
1
to hide the
/login
command. Useful when authentication is handled externally via API keys or
apiKeyHelper
DISABLE_LOGOUT_COMMAND
Set to
1
to hide the
/logout
command
DISABLE_PROMPT_CACHING
Set to
1
to disable prompt caching for all models (takes precedence over per-model settings)
DISABLE_PROMPT_CACHING_HAIKU
Set to
1
to disable prompt caching for Haiku models
DISABLE_PROMPT_CACHING_OPUS
Set to
1
to disable prompt caching for Opus models
DISABLE_PROMPT_CACHING_SONNET
Set to
1
to disable prompt caching for Sonnet models
DISABLE_TELEMETRY
Set to
1
to opt out of telemetry. Telemetry events do not include user data like code, file paths, or bash commands. Also disables feature flags, so some features that are still rolling out may not be available
DISABLE_UPDATES
Set to
1
to block all updates including manual
claude update
and
claude install
. Stricter than
DISABLE_AUTOUPDATER
. Use when distributing Claude Code through your own channels and users should not self-update
DISABLE_UPGRADE_COMMAND
Set to
1
to hide the
/upgrade
command
DO_NOT_TRACK
Set to
1
to opt out of telemetry. Equivalent to setting
DISABLE_TELEMETRY
. Honored as the
standard cross-tool convention
ENABLE_CLAUDEAI_MCP_SERVERS
Set to
false
to disable
claude.ai MCP servers
in Claude Code. Enabled by default for logged-in users
ENABLE_PROMPT_CACHING_1H
Set to
1
to request a 1-hour prompt cache TTL instead of the default 5 minutes. Intended for API key,
Bedrock
,
Vertex
,
Foundry
, and
Claude Platform on AWS
users. Subscription users receive 1-hour TTL automatically. 1-hour cache writes are billed at a higher rate
ENABLE_PROMPT_CACHING_1H_BEDROCK
Deprecated. Use
ENABLE_PROMPT_CACHING_1H
instead
ENABLE_TOOL_SEARCH
Controls
MCP tool search
. Unset: all MCP tools deferred by default, but loaded upfront on Vertex AI or when
ANTHROPIC_BASE_URL
points to a non-first-party host. Values:
true
(always defer and send the beta header; supported on Vertex AI with Sonnet 4.5 and later or Opus 4.5 and later; requests fail on earlier Vertex AI models or on proxies that do not support
tool_reference
),
auto
(threshold mode: load upfront if tools fit within 10% of context),
auto:N
(custom threshold, e.g.,
auto:5
for 5%),
false
(load all upfront)
FALLBACK_FOR_ALL_PRIMARY_MODELS
Set to any non-empty value to trigger fallback to
--fallback-model
after repeated overload errors on any primary model. By default, only Opus models trigger the fallback
FORCE_AUTOUPDATE_PLUGINS
Set to
1
to force plugin auto-updates even when the main auto-updater is disabled via
DISABLE_AUTOUPDATER
FORCE_PROMPT_CACHING_5M
Set to
1
to force the 5-minute prompt cache TTL even when 1-hour TTL would otherwise apply. Overrides
ENABLE_PROMPT_CACHING_1H
HTTP_PROXY
Specify HTTP proxy server for network connections
HTTPS_PROXY
Specify HTTPS proxy server for network connections
IS_DEMO
Set to
1
to enable demo mode: hides your email and organization name from the header and
/status
output, and skips onboarding. Useful when streaming or recording a session
MAX_MCP_OUTPUT_TOKENS
Maximum number of tokens allowed in MCP tool responses. Claude Code displays a warning when output exceeds 10,000 tokens. Tools that declare
anthropic/maxResultSizeChars
use that character limit for text content instead, but image content from those tools is still subject to this variable (default: 25000)
MAX_STRUCTURED_OUTPUT_RETRIES
Number of times to retry when the model’s response fails validation against the
--json-schema
in non-interactive mode (the
-p
flag). Defaults to 5
MAX_THINKING_TOKENS
Override the
extended thinking
token budget. The ceiling is the model’s
max output tokens
minus one. Set to
0
to disable thinking entirely. On models with
adaptive reasoning
, the budget is ignored unless adaptive reasoning is disabled via
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
MCP_CLIENT_SECRET
OAuth client secret for MCP servers that require
pre-configured credentials
. Avoids the interactive prompt when adding a server with
--client-secret
MCP_CONNECTION_NONBLOCKING
Set to
true
in non-interactive mode (
-p
) to skip the MCP connection wait entirely. Useful for scripted pipelines where MCP tools are not needed. Without this variable, the first query waits up to 5 seconds for
--mcp-config
server connections. Servers configured with
alwaysLoad: true
always block startup regardless of this variable, since their tools must be present when the first prompt is built
MCP_CONNECT_TIMEOUT_MS
How long the first query waits, in milliseconds, for the MCP connection batch before snapshotting the tool list (default: 5000). Servers still pending at the deadline keep connecting in the background but won’t appear until the next query. Distinct from
MCP_TIMEOUT
, which bounds an individual server’s connect attempt. Most relevant to non-interactive sessions that issue a single query and need slow-connecting servers to be visible
MCP_OAUTH_CALLBACK_PORT
Fixed port for the OAuth redirect callback, as an alternative to
--callback-port
when adding an MCP server with
pre-configured credentials
MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE
Maximum number of remote MCP servers (HTTP/SSE) to connect in parallel during startup (default: 20)
MCP_SERVER_CONNECTION_BATCH_SIZE
Maximum number of local MCP servers (stdio) to connect in parallel during startup (default: 3)
MCP_TIMEOUT
Timeout in milliseconds for MCP server startup (default: 30000, or 30 seconds)
MCP_TOOL_TIMEOUT
Timeout in milliseconds for MCP tool execution (default: 100000000, about 28 hours)
NO_PROXY
List of domains and IPs to which requests will be directly issued, bypassing proxy
OTEL_LOG_RAW_API_BODIES
Emit Anthropic Messages API request and response JSON as
api_request_body
/
api_response_body
log events. Set to
1
for inline bodies truncated at 60 KB, or
file:<dir>
to write untruncated bodies to disk and emit a
body_ref
path instead. Disabled by default; bodies include the entire conversation history. See
Monitoring
OTEL_LOG_TOOL_CONTENT
Set to
1
to include tool input and output content in OpenTelemetry span events. Disabled by default to protect sensitive data. See
Monitoring
OTEL_LOG_TOOL_DETAILS
Set to
1
to include tool input arguments, MCP server names, raw error strings on tool failures, and other tool details in OpenTelemetry traces and logs. Disabled by default to protect PII. See
Monitoring
OTEL_LOG_USER_PROMPTS
Set to
1
to include user prompt text in OpenTelemetry traces and logs. Disabled by default (prompts are redacted). See
Monitoring
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
Set to
false
to exclude account UUID from metrics attributes (default: included). See
Monitoring
OTEL_METRICS_INCLUDE_SESSION_ID
Set to
false
to exclude session ID from metrics attributes (default: included). See
Monitoring
OTEL_METRICS_INCLUDE_VERSION
Set to
true
to include Claude Code version in metrics attributes (default: excluded). See
Monitoring
SLASH_COMMAND_TOOL_CHAR_BUDGET
Override the character budget for skill metadata shown to the
Skill tool
. The budget scales dynamically at 1% of the context window, with a fallback of 8,000 characters. Legacy name kept for backwards compatibility
TASK_MAX_OUTPUT_LENGTH
Maximum number of characters in
subagent
output before truncation (default: 32000, maximum: 160000). When truncated, the full output is saved to disk and the path is included in the truncated response
USE_BUILTIN_RIPGREP
Set to
0
to use system-installed
rg
instead of
rg
included with Claude Code
VERTEX_REGION_CLAUDE_3_5_HAIKU
Override region for Claude 3.5 Haiku when using Vertex AI
VERTEX_REGION_CLAUDE_3_5_SONNET
Override region for Claude 3.5 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_3_7_SONNET
Override region for Claude 3.7 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_4_0_OPUS
Override region for Claude 4.0 Opus when using Vertex AI
VERTEX_REGION_CLAUDE_4_0_SONNET
Override region for Claude 4.0 Sonnet when using Vertex AI
VERTEX_REGION_CLAUDE_4_1_OPUS
Override region for Claude 4.1 Opus when using Vertex AI
VERTEX_REGION_CLAUDE_4_5_OPUS
Override region for Claude Opus 4.5 when using Vertex AI
VERTEX_REGION_CLAUDE_4_5_SONNET
Override region for Claude Sonnet 4.5 when using Vertex AI
VERTEX_REGION_CLAUDE_4_6_OPUS
Override region for Claude Opus 4.6 when using Vertex AI
VERTEX_REGION_CLAUDE_4_6_SONNET
Override region for Claude Sonnet 4.6 when using Vertex AI
VERTEX_REGION_CLAUDE_4_7_OPUS
Override region for Claude Opus 4.7 when using Vertex AI
VERTEX_REGION_CLAUDE_HAIKU_4_5
Override region for Claude Haiku 4.5 when using Vertex AI
Standard OpenTelemetry exporter variables (
OTEL_METRICS_EXPORTER
,
OTEL_LOGS_EXPORTER
,
OTEL_EXPORTER_OTLP_ENDPOINT
,
OTEL_EXPORTER_OTLP_PROTOCOL
,
OTEL_EXPORTER_OTLP_HEADERS
,
OTEL_METRIC_EXPORT_INTERVAL
,
OTEL_RESOURCE_ATTRIBUTES
, and signal-specific variants) are also supported. See
Monitoring
for configuration details.
​
See also
Settings
: configure environment variables in
settings.json
so they apply to every session
CLI reference
: launch-time flags
Network configuration
: proxy and TLS setup
Monitoring
: OpenTelemetry configuration
Was this page helpful?
Yes
No
Commands
Tools reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/env-vars" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Find bugs with ultrareview</title>
  <link>https://code.claude.com/docs/en/ultrareview</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/ultrareview</guid>
  <pubDate>Sat, 02 Nov 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Find bugs with ultrareview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Find bugs with ultrareview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Ultrareview is a research preview feature available in Claude Code v2.1.86 and later. The feature, pricing, and availability may change based on feedback.
Ultrareview is a deep code review that runs on Claude Code on the web infrastructure. When you run
/ultrareview
, Claude Code launches a fleet of reviewer agents in a remote sandbox to find bugs in your branch or pull request.
Compared to a local
/review
, ultrareview offers:
Higher signal
: every reported finding is independently reproduced and verified, so the results focus on real bugs rather than style suggestions
Broader coverage
: many reviewer agents explore the change in parallel, which surfaces issues that a single-pass review can miss
No local resource use
: the review runs entirely in a remote sandbox, so your terminal stays free for other work while it runs
Ultrareview requires authentication with a Claude.ai account because it runs on Claude Code on the web infrastructure. If you are signed in with an API key only, run
/login
and authenticate with Claude.ai first. Ultrareview is not available when using Claude Code with Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry, and it is not available to organizations that have enabled Zero Data Retention.
​
Run ultrareview from the CLI
Start a review from any git repository in the Claude Code CLI.
/ultrareview
Without arguments, ultrareview reviews the diff between your current branch and the default branch, including any uncommitted and staged changes in your working tree. Claude Code bundles the repository state and uploads it to a remote sandbox for the review.
To review a GitHub pull request instead, pass the PR number.
/ultrareview 1234
In PR mode, the remote sandbox clones the pull request directly from GitHub rather than bundling your local working tree. PR mode requires a
github.com
remote on the repository.
If your repository is too large to bundle, Claude Code prompts you to use PR mode instead. Push your branch and open a draft PR, then run
/ultrareview <PR-number>
.
Before launching, Claude Code shows a confirmation dialog with the review scope (including the file and line count when reviewing a branch), your remaining free runs, and the estimated cost. After you confirm, the review continues in the background and you can keep using your session. The command runs only when you invoke it with
/ultrareview
; Claude does not start an ultrareview on its own.
​
Pricing and free runs
Ultrareview is a premium feature that bills against extra usage rather than your plan’s included usage.
Plan
Included free runs
After free runs
Pro
3 free runs
billed as
extra usage
Max
3 free runs
billed as
extra usage
Team and Enterprise
none
billed as
extra usage
Pro and Max subscribers receive three free ultrareview runs to try the feature. These three runs are a one-time allotment per account and do not refresh. After you use all three, or after the free run period ends, each review is billed to extra usage and typically costs $5 to $20 depending on the size of the change. A run counts once the remote session starts, so a review that you stop early or that fails to complete still uses a free run. For a paid review, extra usage is billed only for the portion that ran.
Because ultrareview always bills as extra usage outside the free runs, your account or organization must have extra usage enabled before you can launch a paid review. If extra usage is not enabled, Claude Code blocks the launch and links you to the billing settings where you can turn it on. You can also run
/extra-usage
to check or change your current setting.
​
Track a running review
A review typically takes 5 to 10 minutes. The review runs as a background task, so you can keep working in your session, start other commands, or close the terminal entirely.
Use
/tasks
to see running and completed reviews, open the detail view for a review, or stop a review that is in progress. Stopping a review archives the cloud session, and partial findings are not returned. When the review finishes, the verified findings appear as a notification in your session. Each finding includes the file location and an explanation of the issue so you can ask Claude to fix it directly.
​
Run ultrareview non-interactively
Use the
claude ultrareview
subcommand to start an ultrareview from CI or a script without an interactive session. The subcommand launches the same review as
/ultrareview
, blocks until the remote review finishes, prints the findings to stdout, and exits with code 0 on success or 1 on failure.
claude
ultrareview
claude
ultrareview
1234
claude
ultrareview
origin/main
Without arguments, the subcommand reviews the diff between your current branch and the default branch. Pass a PR number to review a pull request, or pass a base branch to review the diff against that branch instead. Invoking the subcommand counts as consent for the billing and terms prompt that the interactive command shows.
Progress messages and the live session URL go to stderr so stdout stays parseable. Use these flags to control the output and timeout:
Flag
Description
--json
Print the raw
bugs.json
payload instead of the formatted findings
--timeout <minutes>
Maximum minutes to wait for the review to finish. Defaults to 30
Running
claude ultrareview
requires the same authentication and extra usage configuration as
/ultrareview
. The subcommand exits with code 0 when the review completes with or without findings, code 1 when the review fails to launch, the remote session errors, or the timeout elapses, and code 130 when interrupted with Ctrl-C. The remote review keeps running if you interrupt the subcommand; follow the session URL printed to stderr to watch it in the browser.
For automatic reviews on GitHub pull requests,
Code Review
integrates with your repository directly and posts findings as inline PR comments without a CLI step.
​
How ultrareview compares to /review
Both commands review code, but they target different stages of your workflow.
/review
/ultrareview
Runs
locally in your session
remotely in a cloud sandbox
Depth
single-pass review
multi-agent fleet with independent verification
Duration
seconds to a few minutes
roughly 5 to 10 minutes
Cost
counts toward normal usage
free runs, then roughly $5 to $20 per review as extra usage
Best for
quick feedback while iterating
pre-merge confidence on substantial changes
Use
/review
for fast feedback as you work. Use
/ultrareview
before merging a substantial change when you want a deeper pass that catches issues a single review might miss.
​
Related resources
Claude Code on the web
: learn how remote sessions and cloud sandboxes work
Plan complex changes with ultraplan
: the planning counterpart to ultrareview for upfront design work
Manage costs effectively
: track usage and set spending limits
Was this page helpful?
Yes
No
Plan in the cloud
Get started
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/ultrareview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Find bugs with ultrareview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Find bugs with ultrareview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Ultrareview is a research preview feature available in Claude Code v2.1.86 and later. The feature, pricing, and availability may change based on feedback.
Ultrareview is a deep code review that runs on Claude Code on the web infrastructure. When you run
/ultrareview
, Claude Code launches a fleet of reviewer agents in a remote sandbox to find bugs in your branch or pull request.
Compared to a local
/review
, ultrareview offers:
Higher signal
: every reported finding is independently reproduced and verified, so the results focus on real bugs rather than style suggestions
Broader coverage
: many reviewer agents explore the change in parallel, which surfaces issues that a single-pass review can miss
No local resource use
: the review runs entirely in a remote sandbox, so your terminal stays free for other work while it runs
Ultrareview requires authentication with a Claude.ai account because it runs on Claude Code on the web infrastructure. If you are signed in with an API key only, run
/login
and authenticate with Claude.ai first. Ultrareview is not available when using Claude Code with Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry, and it is not available to organizations that have enabled Zero Data Retention.
​
Run ultrareview from the CLI
Start a review from any git repository in the Claude Code CLI.
/ultrareview
Without arguments, ultrareview reviews the diff between your current branch and the default branch, including any uncommitted and staged changes in your working tree. Claude Code bundles the repository state and uploads it to a remote sandbox for the review.
To review a GitHub pull request instead, pass the PR number.
/ultrareview 1234
In PR mode, the remote sandbox clones the pull request directly from GitHub rather than bundling your local working tree. PR mode requires a
github.com
remote on the repository.
If your repository is too large to bundle, Claude Code prompts you to use PR mode instead. Push your branch and open a draft PR, then run
/ultrareview <PR-number>
.
Before launching, Claude Code shows a confirmation dialog with the review scope (including the file and line count when reviewing a branch), your remaining free runs, and the estimated cost. After you confirm, the review continues in the background and you can keep using your session. The command runs only when you invoke it with
/ultrareview
; Claude does not start an ultrareview on its own.
​
Pricing and free runs
Ultrareview is a premium feature that bills against extra usage rather than your plan’s included usage.
Plan
Included free runs
After free runs
Pro
3 free runs
billed as
extra usage
Max
3 free runs
billed as
extra usage
Team and Enterprise
none
billed as
extra usage
Pro and Max subscribers receive three free ultrareview runs to try the feature. These three runs are a one-time allotment per account and do not refresh. After you use all three, or after the free run period ends, each review is billed to extra usage and typically costs $5 to $20 depending on the size of the change. A run counts once the remote session starts, so a review that you stop early or that fails to complete still uses a free run. For a paid review, extra usage is billed only for the portion that ran.
Because ultrareview always bills as extra usage outside the free runs, your account or organization must have extra usage enabled before you can launch a paid review. If extra usage is not enabled, Claude Code blocks the launch and links you to the billing settings where you can turn it on. You can also run
/extra-usage
to check or change your current setting.
​
Track a running review
A review typically takes 5 to 10 minutes. The review runs as a background task, so you can keep working in your session, start other commands, or close the terminal entirely.
Use
/tasks
to see running and completed reviews, open the detail view for a review, or stop a review that is in progress. Stopping a review archives the cloud session, and partial findings are not returned. When the review finishes, the verified findings appear as a notification in your session. Each finding includes the file location and an explanation of the issue so you can ask Claude to fix it directly.
​
Run ultrareview non-interactively
Use the
claude ultrareview
subcommand to start an ultrareview from CI or a script without an interactive session. The subcommand launches the same review as
/ultrareview
, blocks until the remote review finishes, prints the findings to stdout, and exits with code 0 on success or 1 on failure.
claude
ultrareview
claude
ultrareview
1234
claude
ultrareview
origin/main
Without arguments, the subcommand reviews the diff between your current branch and the default branch. Pass a PR number to review a pull request, or pass a base branch to review the diff against that branch instead. Invoking the subcommand counts as consent for the billing and terms prompt that the interactive command shows.
Progress messages and the live session URL go to stderr so stdout stays parseable. Use these flags to control the output and timeout:
Flag
Description
--json
Print the raw
bugs.json
payload instead of the formatted findings
--timeout <minutes>
Maximum minutes to wait for the review to finish. Defaults to 30
Running
claude ultrareview
requires the same authentication and extra usage configuration as
/ultrareview
. The subcommand exits with code 0 when the review completes with or without findings, code 1 when the review fails to launch, the remote session errors, or the timeout elapses, and code 130 when interrupted with Ctrl-C. The remote review keeps running if you interrupt the subcommand; follow the session URL printed to stderr to watch it in the browser.
For automatic reviews on GitHub pull requests,
Code Review
integrates with your repository directly and posts findings as inline PR comments without a CLI step.
​
How ultrareview compares to /review
Both commands review code, but they target different stages of your workflow.
/review
/ultrareview
Runs
locally in your session
remotely in a cloud sandbox
Depth
single-pass review
multi-agent fleet with independent verification
Duration
seconds to a few minutes
roughly 5 to 10 minutes
Cost
counts toward normal usage
free runs, then roughly $5 to $20 per review as extra usage
Best for
quick feedback while iterating
pre-merge confidence on substantial changes
Use
/review
for fast feedback as you work. Use
/ultrareview
before merging a substantial change when you want a deeper pass that catches issues a single review might miss.
​
Related resources
Claude Code on the web
: learn how remote sessions and cloud sandboxes work
Plan complex changes with ultraplan
: the planning counterpart to ultrareview for upfront design work
Manage costs effectively
: track usage and set spending limits
Was this page helpful?
Yes
No
Plan in the cloud
Get started
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/ultrareview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Rewind file changes with checkpointing</title>
  <link>https://code.claude.com/docs/en/agent-sdk/file-checkpointing</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/file-checkpointing</guid>
  <pubDate>Thu, 31 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Rewind file changes with checkpointing
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool searc...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Rewind file changes with checkpointing
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
File checkpointing tracks file modifications made through the Write, Edit, and NotebookEdit tools during an agent session, allowing you to rewind files to any previous state. Want to try it out? Jump to the
interactive example
.
With checkpointing, you can:
Undo unwanted changes
by restoring files to a known good state
Explore alternatives
by restoring to a checkpoint and trying a different approach
Recover from errors
when the agent makes incorrect modifications
Only changes made through the Write, Edit, and NotebookEdit tools are tracked. Changes made through Bash commands (like
echo > file.txt
or
sed -i
) are not captured by the checkpoint system.
​
How checkpointing works
When you enable file checkpointing, the SDK creates backups of files before modifying them through the Write, Edit, or NotebookEdit tools. User messages in the response stream include a checkpoint UUID that you can use as a restore point.
Checkpoint works with these built-in tools that the agent uses to modify files:
Tool
Description
Write
Creates a new file or overwrites an existing file with new content
Edit
Makes targeted edits to specific parts of an existing file
NotebookEdit
Modifies cells in Jupyter notebooks (
.ipynb
files)
File rewinding restores files on disk to a previous state. It does not rewind the conversation itself. The conversation history and context remain intact after calling
rewindFiles()
(TypeScript) or
rewind_files()
(Python).
The checkpoint system tracks:
Files created during the session
Files modified during the session
The original content of modified files
When you rewind to a checkpoint, created files are deleted and modified files are restored to their content at that point.
​
Implement checkpointing
To use file checkpointing, enable it in your options, capture checkpoint UUIDs from the response stream, then call
rewindFiles()
(TypeScript) or
rewind_files()
(Python) when you need to restore.
The following example shows the complete flow: enable checkpointing, capture the checkpoint UUID and session ID from the response stream, then resume the session later to rewind files. Each step is explained in detail below.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
async
def
main
():
# Step 1: Enable checkpointing
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
# Auto-accept file edits without prompting
extra_args
=
{
"replay-user-messages"
:
None
},
# Required to receive checkpoint UUIDs in the response stream
)
checkpoint_id
=
None
session_id
=
None
# Run the query and capture checkpoint UUID and session ID
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
# Step 2: Capture checkpoint UUID from the first user message
async
for
message
in
client.receive_response():
if
isinstance
(message, UserMessage)
and
message.uuid
and
not
checkpoint_id:
checkpoint_id
=
message.uuid
if
isinstance
(message, ResultMessage)
and
not
session_id:
session_id
=
message.session_id
# Step 3: Later, rewind by resuming the session with an empty prompt
if
checkpoint_id
and
session_id:
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
print
(
f
"Rewound to checkpoint:
{
checkpoint_id
}
"
)
asyncio.run(main())
1
Enable checkpointing
Configure your SDK options to enable checkpointing and receive checkpoint UUIDs:
Option
Python
TypeScript
Description
Enable checkpointing
enable_file_checkpointing=True
enableFileCheckpointing: true
Tracks file changes for rewinding
Receive checkpoint UUIDs
extra_args={"replay-user-messages": None}
extraArgs: { 'replay-user-messages': null }
Required to get user message UUIDs in the stream
Python
TypeScript
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
2
Capture checkpoint UUID and session ID
With the
replay-user-messages
option set (shown above), each user message in the response stream has a UUID that serves as a checkpoint.
For most use cases, capture the first user message UUID (
message.uuid
); rewinding to it restores all files to their original state. To store multiple checkpoints and rewind to intermediate states, see
Multiple restore points
.
Capturing the session ID (
message.session_id
) is optional; you only need it if you want to rewind later, after the stream completes. If you’re calling
rewindFiles()
immediately while still processing messages (as the example in
Checkpoint before risky operations
does), you can skip capturing the session ID.
Python
TypeScript
checkpoint_id
=
None
session_id
=
None
async
for
message
in
client.receive_response():
# Update checkpoint on each user message (keeps the latest)
if
isinstance
(message, UserMessage)
and
message.uuid:
checkpoint_id
=
message.uuid
# Capture session ID from the result message
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
3
Rewind files
To rewind after the stream completes, resume the session with an empty prompt and call
rewind_files()
(Python) or
rewindFiles()
(TypeScript) with your checkpoint UUID. You can also rewind during the stream; see
Checkpoint before risky operations
for that pattern.
Python
TypeScript
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
If you capture the session ID and checkpoint ID, you can also rewind from the CLI:
claude
-p
--resume
<
session-i
d
>
--rewind-files
<
checkpoint-uui
d
>
​
Common patterns
These patterns show different ways to capture and use checkpoint UUIDs depending on your use case.
​
Checkpoint before risky operations
This pattern keeps only the most recent checkpoint UUID, updating it before each agent turn. If something goes wrong during processing, you can immediately rewind to the last safe state and break out of the loop.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, UserMessage
async
def
main
():
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
safe_checkpoint
=
None
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
async
for
message
in
client.receive_response():
# Update checkpoint before each agent turn starts
# This overwrites the previous checkpoint. Only keep the latest
if
isinstance
(message, UserMessage)
and
message.uuid:
safe_checkpoint
=
message.uuid
# Decide when to revert based on your own logic
# For example: error detection, validation failure, or user input
if
your_revert_condition
and
safe_checkpoint:
await
client.rewind_files(safe_checkpoint)
# Exit the loop after rewinding, files are restored
break
asyncio.run(main())
​
Multiple restore points
If Claude makes changes across multiple turns, you might want to rewind to a specific point rather than all the way back. For example, if Claude refactors a file in turn one and adds tests in turn two, you might want to keep the refactor but undo the tests.
This pattern stores all checkpoint UUIDs in an array with metadata. After the session completes, you can rewind to any previous checkpoint:
Python
TypeScript
import
asyncio
from
dataclasses
import
dataclass
from
datetime
import
datetime
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
# Store checkpoint metadata for better tracking
@dataclass
class
Checkpoint
:
id
:
str
description:
str
timestamp: datetime
async
def
main
():
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
checkpoints
=
[]
session_id
=
None
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, UserMessage)
and
message.uuid:
checkpoints.append(
Checkpoint(
id
=
message.uuid,
description
=
f
"After turn
{
len
(checkpoints)
+
1
}
"
,
timestamp
=
datetime.now(),
)
)
if
isinstance
(message, ResultMessage)
and
not
session_id:
session_id
=
message.session_id
# Later: rewind to any checkpoint by resuming the session
if
checkpoints
and
session_id:
target
=
checkpoints[
0
]
# Pick any checkpoint
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(target.id)
break
print
(
f
"Rewound to:
{
target.description
}
"
)
asyncio.run(main())
​
Try it out
This complete example creates a small utility file, has the agent add documentation comments, shows you the changes, then asks if you want to rewind.
Before you begin, make sure you have the
Claude Agent SDK installed
.
1
Create a test file
Create a new file called
utils.py
(Python) or
utils.ts
(TypeScript) and paste the following code:
utils.py
utils.ts
def
add
(
a
,
b
):
return
a
+
b
def
subtract
(
a
,
b
):
return
a
-
b
def
multiply
(
a
,
b
):
return
a
*
b
def
divide
(
a
,
b
):
if
b
==
0
:
raise
ValueError
(
"Cannot divide by zero"
)
return
a
/
b
2
Run the interactive example
Create a new file called
try_checkpointing.py
(Python) or
try_checkpointing.ts
(TypeScript) in the same directory as your utility file, and paste the following code.
This script asks Claude to add doc comments to your utility file, then gives you the option to rewind and restore the original.
try_checkpointing.py
try_checkpointing.ts
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
async
def
main
():
# Configure the SDK with checkpointing enabled
# - enable_file_checkpointing: Track file changes for rewinding
# - permission_mode: Auto-accept file edits without prompting
# - extra_args: Required to receive user message UUIDs in the stream
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
checkpoint_id
=
None
# Store the user message UUID for rewinding
session_id
=
None
# Store the session ID for resuming
print
(
"Running agent to add doc comments to utils.py...
\n
"
)
# Run the agent and capture checkpoint data from the response stream
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Add doc comments to utils.py"
)
async
for
message
in
client.receive_response():
# Capture the first user message UUID - this is our restore point
if
isinstance
(message, UserMessage)
and
message.uuid
and
not
checkpoint_id:
checkpoint_id
=
message.uuid
# Capture the session ID so we can resume later
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
print
(
"Done! Open utils.py to see the added doc comments.
\n
"
)
# Ask the user if they want to rewind the changes
if
checkpoint_id
and
session_id:
response
=
input
(
"Rewind to remove the doc comments? (y/n): "
)
if
response.lower()
==
"y"
:
# Resume the session with an empty prompt, then rewind
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt opens the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
# Restore files
break
print
(
"
\n
✓ File restored! Open utils.py to verify the doc comments are gone."
)
else
:
print
(
"
\n
Kept the modified file."
)
asyncio.run(main())
This example demonstrates the complete checkpointing workflow:
Enable checkpointing
: configure the SDK with
enable_file_checkpointing=True
and
permission_mode="acceptEdits"
to auto-approve file edits
Capture checkpoint data
: as the agent runs, store the first user message UUID (your restore point) and the session ID
Prompt for rewind
: after the agent finishes, check your utility file to see the doc comments, then decide if you want to undo the changes
Resume and rewind
: if yes, resume the session with an empty prompt and call
rewind_files()
to restore the original file
3
Run the example
Run the script from the same directory as your utility file.
Open your utility file (
utils.py
or
utils.ts
) in your IDE or editor before running the script. You’ll see the file update in real-time as the agent adds doc comments, then revert back to the original when you choose to rewind.
Python
TypeScript
python
try_checkpointing.py
npx
tsx
try_checkpointing.ts
You’ll see the agent add doc comments, then a prompt asking if you want to rewind. If you choose yes, the file is restored to its original state.
​
Limitations
File checkpointing has the following limitations:
Limitation
Description
Write/Edit/NotebookEdit tools only
Changes made through Bash commands are not tracked
Same session
Checkpoints are tied to the session that created them
File content only
Creating, moving, or deleting directories is not undone by rewinding
Local files
Remote or network files are not tracked
​
Troubleshooting
​
Checkpointing options not recognized
If
enableFileCheckpointing
or
rewindFiles()
isn’t available, you may be on an older SDK version.
Solution
: Update to the latest SDK version:
Python
:
pip install --upgrade claude-agent-sdk
TypeScript
:
npm install @anthropic-ai/claude-agent-sdk@latest
​
User messages don’t have UUIDs
If
message.uuid
is
undefined
or missing, you’re not receiving checkpoint UUIDs.
Cause
: The
replay-user-messages
option isn’t set.
Solution
: Add
extra_args={"replay-user-messages": None}
(Python) or
extraArgs: { 'replay-user-messages': null }
(TypeScript) to your options.
​
”No file checkpoint found for message” error
This error occurs when the checkpoint data doesn’t exist for the specified user message UUID.
Common causes
:
File checkpointing was not enabled on the original session (
enable_file_checkpointing
or
enableFileCheckpointing
was not set to
true
)
The session wasn’t properly completed before attempting to resume and rewind
Solution
: Ensure
enable_file_checkpointing=True
(Python) or
enableFileCheckpointing: true
(TypeScript) was set on the original session, then use the pattern shown in the examples: capture the first user message UUID, complete the session fully, then resume with an empty prompt and call
rewindFiles()
once.
​
”ProcessTransport is not ready for writing” error
This error occurs when you call
rewindFiles()
or
rewind_files()
after you’ve finished iterating through the response. The connection to the CLI process closes when the loop completes.
Solution
: Resume the session with an empty prompt, then call rewind on the new query:
Python
TypeScript
# Resume session with empty prompt, then rewind
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
​
Next steps
Sessions
: learn how to resume sessions, which is required for rewinding after the stream completes. Covers session IDs, resuming conversations, and session forking.
Permissions
: configure which tools Claude can use and how file modifications are approved. Useful if you want more control over when edits happen.
TypeScript SDK reference
: complete API reference including all options for
query()
and the
rewindFiles()
method.
Python SDK reference
: complete API reference including all options for
ClaudeAgentOptions
and the
rewind_files()
method.
Was this page helpful?
Yes
No
Intercept and control agent behavior with hooks
Track cost and usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/file-checkpointing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Rewind file changes with checkpointing
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool searc...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Rewind file changes with checkpointing
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
File checkpointing tracks file modifications made through the Write, Edit, and NotebookEdit tools during an agent session, allowing you to rewind files to any previous state. Want to try it out? Jump to the
interactive example
.
With checkpointing, you can:
Undo unwanted changes
by restoring files to a known good state
Explore alternatives
by restoring to a checkpoint and trying a different approach
Recover from errors
when the agent makes incorrect modifications
Only changes made through the Write, Edit, and NotebookEdit tools are tracked. Changes made through Bash commands (like
echo > file.txt
or
sed -i
) are not captured by the checkpoint system.
​
How checkpointing works
When you enable file checkpointing, the SDK creates backups of files before modifying them through the Write, Edit, or NotebookEdit tools. User messages in the response stream include a checkpoint UUID that you can use as a restore point.
Checkpoint works with these built-in tools that the agent uses to modify files:
Tool
Description
Write
Creates a new file or overwrites an existing file with new content
Edit
Makes targeted edits to specific parts of an existing file
NotebookEdit
Modifies cells in Jupyter notebooks (
.ipynb
files)
File rewinding restores files on disk to a previous state. It does not rewind the conversation itself. The conversation history and context remain intact after calling
rewindFiles()
(TypeScript) or
rewind_files()
(Python).
The checkpoint system tracks:
Files created during the session
Files modified during the session
The original content of modified files
When you rewind to a checkpoint, created files are deleted and modified files are restored to their content at that point.
​
Implement checkpointing
To use file checkpointing, enable it in your options, capture checkpoint UUIDs from the response stream, then call
rewindFiles()
(TypeScript) or
rewind_files()
(Python) when you need to restore.
The following example shows the complete flow: enable checkpointing, capture the checkpoint UUID and session ID from the response stream, then resume the session later to rewind files. Each step is explained in detail below.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
async
def
main
():
# Step 1: Enable checkpointing
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
# Auto-accept file edits without prompting
extra_args
=
{
"replay-user-messages"
:
None
},
# Required to receive checkpoint UUIDs in the response stream
)
checkpoint_id
=
None
session_id
=
None
# Run the query and capture checkpoint UUID and session ID
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
# Step 2: Capture checkpoint UUID from the first user message
async
for
message
in
client.receive_response():
if
isinstance
(message, UserMessage)
and
message.uuid
and
not
checkpoint_id:
checkpoint_id
=
message.uuid
if
isinstance
(message, ResultMessage)
and
not
session_id:
session_id
=
message.session_id
# Step 3: Later, rewind by resuming the session with an empty prompt
if
checkpoint_id
and
session_id:
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
print
(
f
"Rewound to checkpoint:
{
checkpoint_id
}
"
)
asyncio.run(main())
1
Enable checkpointing
Configure your SDK options to enable checkpointing and receive checkpoint UUIDs:
Option
Python
TypeScript
Description
Enable checkpointing
enable_file_checkpointing=True
enableFileCheckpointing: true
Tracks file changes for rewinding
Receive checkpoint UUIDs
extra_args={"replay-user-messages": None}
extraArgs: { 'replay-user-messages': null }
Required to get user message UUIDs in the stream
Python
TypeScript
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
2
Capture checkpoint UUID and session ID
With the
replay-user-messages
option set (shown above), each user message in the response stream has a UUID that serves as a checkpoint.
For most use cases, capture the first user message UUID (
message.uuid
); rewinding to it restores all files to their original state. To store multiple checkpoints and rewind to intermediate states, see
Multiple restore points
.
Capturing the session ID (
message.session_id
) is optional; you only need it if you want to rewind later, after the stream completes. If you’re calling
rewindFiles()
immediately while still processing messages (as the example in
Checkpoint before risky operations
does), you can skip capturing the session ID.
Python
TypeScript
checkpoint_id
=
None
session_id
=
None
async
for
message
in
client.receive_response():
# Update checkpoint on each user message (keeps the latest)
if
isinstance
(message, UserMessage)
and
message.uuid:
checkpoint_id
=
message.uuid
# Capture session ID from the result message
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
3
Rewind files
To rewind after the stream completes, resume the session with an empty prompt and call
rewind_files()
(Python) or
rewindFiles()
(TypeScript) with your checkpoint UUID. You can also rewind during the stream; see
Checkpoint before risky operations
for that pattern.
Python
TypeScript
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
If you capture the session ID and checkpoint ID, you can also rewind from the CLI:
claude
-p
--resume
<
session-i
d
>
--rewind-files
<
checkpoint-uui
d
>
​
Common patterns
These patterns show different ways to capture and use checkpoint UUIDs depending on your use case.
​
Checkpoint before risky operations
This pattern keeps only the most recent checkpoint UUID, updating it before each agent turn. If something goes wrong during processing, you can immediately rewind to the last safe state and break out of the loop.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, UserMessage
async
def
main
():
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
safe_checkpoint
=
None
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
async
for
message
in
client.receive_response():
# Update checkpoint before each agent turn starts
# This overwrites the previous checkpoint. Only keep the latest
if
isinstance
(message, UserMessage)
and
message.uuid:
safe_checkpoint
=
message.uuid
# Decide when to revert based on your own logic
# For example: error detection, validation failure, or user input
if
your_revert_condition
and
safe_checkpoint:
await
client.rewind_files(safe_checkpoint)
# Exit the loop after rewinding, files are restored
break
asyncio.run(main())
​
Multiple restore points
If Claude makes changes across multiple turns, you might want to rewind to a specific point rather than all the way back. For example, if Claude refactors a file in turn one and adds tests in turn two, you might want to keep the refactor but undo the tests.
This pattern stores all checkpoint UUIDs in an array with metadata. After the session completes, you can rewind to any previous checkpoint:
Python
TypeScript
import
asyncio
from
dataclasses
import
dataclass
from
datetime
import
datetime
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
# Store checkpoint metadata for better tracking
@dataclass
class
Checkpoint
:
id
:
str
description:
str
timestamp: datetime
async
def
main
():
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
checkpoints
=
[]
session_id
=
None
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Refactor the authentication module"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, UserMessage)
and
message.uuid:
checkpoints.append(
Checkpoint(
id
=
message.uuid,
description
=
f
"After turn
{
len
(checkpoints)
+
1
}
"
,
timestamp
=
datetime.now(),
)
)
if
isinstance
(message, ResultMessage)
and
not
session_id:
session_id
=
message.session_id
# Later: rewind to any checkpoint by resuming the session
if
checkpoints
and
session_id:
target
=
checkpoints[
0
]
# Pick any checkpoint
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt to open the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(target.id)
break
print
(
f
"Rewound to:
{
target.description
}
"
)
asyncio.run(main())
​
Try it out
This complete example creates a small utility file, has the agent add documentation comments, shows you the changes, then asks if you want to rewind.
Before you begin, make sure you have the
Claude Agent SDK installed
.
1
Create a test file
Create a new file called
utils.py
(Python) or
utils.ts
(TypeScript) and paste the following code:
utils.py
utils.ts
def
add
(
a
,
b
):
return
a
+
b
def
subtract
(
a
,
b
):
return
a
-
b
def
multiply
(
a
,
b
):
return
a
*
b
def
divide
(
a
,
b
):
if
b
==
0
:
raise
ValueError
(
"Cannot divide by zero"
)
return
a
/
b
2
Run the interactive example
Create a new file called
try_checkpointing.py
(Python) or
try_checkpointing.ts
(TypeScript) in the same directory as your utility file, and paste the following code.
This script asks Claude to add doc comments to your utility file, then gives you the option to rewind and restore the original.
try_checkpointing.py
try_checkpointing.ts
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
UserMessage,
ResultMessage,
)
async
def
main
():
# Configure the SDK with checkpointing enabled
# - enable_file_checkpointing: Track file changes for rewinding
# - permission_mode: Auto-accept file edits without prompting
# - extra_args: Required to receive user message UUIDs in the stream
options
=
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
permission_mode
=
"acceptEdits"
,
extra_args
=
{
"replay-user-messages"
:
None
},
)
checkpoint_id
=
None
# Store the user message UUID for rewinding
session_id
=
None
# Store the session ID for resuming
print
(
"Running agent to add doc comments to utils.py...
\n
"
)
# Run the agent and capture checkpoint data from the response stream
async
with
ClaudeSDKClient(options)
as
client:
await
client.query(
"Add doc comments to utils.py"
)
async
for
message
in
client.receive_response():
# Capture the first user message UUID - this is our restore point
if
isinstance
(message, UserMessage)
and
message.uuid
and
not
checkpoint_id:
checkpoint_id
=
message.uuid
# Capture the session ID so we can resume later
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
print
(
"Done! Open utils.py to see the added doc comments.
\n
"
)
# Ask the user if they want to rewind the changes
if
checkpoint_id
and
session_id:
response
=
input
(
"Rewind to remove the doc comments? (y/n): "
)
if
response.lower()
==
"y"
:
# Resume the session with an empty prompt, then rewind
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
# Empty prompt opens the connection
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
# Restore files
break
print
(
"
\n
✓ File restored! Open utils.py to verify the doc comments are gone."
)
else
:
print
(
"
\n
Kept the modified file."
)
asyncio.run(main())
This example demonstrates the complete checkpointing workflow:
Enable checkpointing
: configure the SDK with
enable_file_checkpointing=True
and
permission_mode="acceptEdits"
to auto-approve file edits
Capture checkpoint data
: as the agent runs, store the first user message UUID (your restore point) and the session ID
Prompt for rewind
: after the agent finishes, check your utility file to see the doc comments, then decide if you want to undo the changes
Resume and rewind
: if yes, resume the session with an empty prompt and call
rewind_files()
to restore the original file
3
Run the example
Run the script from the same directory as your utility file.
Open your utility file (
utils.py
or
utils.ts
) in your IDE or editor before running the script. You’ll see the file update in real-time as the agent adds doc comments, then revert back to the original when you choose to rewind.
Python
TypeScript
python
try_checkpointing.py
npx
tsx
try_checkpointing.ts
You’ll see the agent add doc comments, then a prompt asking if you want to rewind. If you choose yes, the file is restored to its original state.
​
Limitations
File checkpointing has the following limitations:
Limitation
Description
Write/Edit/NotebookEdit tools only
Changes made through Bash commands are not tracked
Same session
Checkpoints are tied to the session that created them
File content only
Creating, moving, or deleting directories is not undone by rewinding
Local files
Remote or network files are not tracked
​
Troubleshooting
​
Checkpointing options not recognized
If
enableFileCheckpointing
or
rewindFiles()
isn’t available, you may be on an older SDK version.
Solution
: Update to the latest SDK version:
Python
:
pip install --upgrade claude-agent-sdk
TypeScript
:
npm install @anthropic-ai/claude-agent-sdk@latest
​
User messages don’t have UUIDs
If
message.uuid
is
undefined
or missing, you’re not receiving checkpoint UUIDs.
Cause
: The
replay-user-messages
option isn’t set.
Solution
: Add
extra_args={"replay-user-messages": None}
(Python) or
extraArgs: { 'replay-user-messages': null }
(TypeScript) to your options.
​
”No file checkpoint found for message” error
This error occurs when the checkpoint data doesn’t exist for the specified user message UUID.
Common causes
:
File checkpointing was not enabled on the original session (
enable_file_checkpointing
or
enableFileCheckpointing
was not set to
true
)
The session wasn’t properly completed before attempting to resume and rewind
Solution
: Ensure
enable_file_checkpointing=True
(Python) or
enableFileCheckpointing: true
(TypeScript) was set on the original session, then use the pattern shown in the examples: capture the first user message UUID, complete the session fully, then resume with an empty prompt and call
rewindFiles()
once.
​
”ProcessTransport is not ready for writing” error
This error occurs when you call
rewindFiles()
or
rewind_files()
after you’ve finished iterating through the response. The connection to the CLI process closes when the loop completes.
Solution
: Resume the session with an empty prompt, then call rewind on the new query:
Python
TypeScript
# Resume session with empty prompt, then rewind
async
with
ClaudeSDKClient(
ClaudeAgentOptions(
enable_file_checkpointing
=
True
,
resume
=
session_id)
)
as
client:
await
client.query(
""
)
async
for
message
in
client.receive_response():
await
client.rewind_files(checkpoint_id)
break
​
Next steps
Sessions
: learn how to resume sessions, which is required for rewinding after the stream completes. Covers session IDs, resuming conversations, and session forking.
Permissions
: configure which tools Claude can use and how file modifications are approved. Useful if you want more control over when edits happen.
TypeScript SDK reference
: complete API reference including all options for
query()
and the
rewindFiles()
method.
Python SDK reference
: complete API reference including all options for
ClaudeAgentOptions
and the
rewind_files()
method.
Was this page helpful?
Yes
No
Intercept and control agent behavior with hooks
Track cost and usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/file-checkpointing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Observability with OpenTelemetry</title>
  <link>https://code.claude.com/docs/en/agent-sdk/observability</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/observability</guid>
  <pubDate>Mon, 28 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Observability with OpenTelemetry
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Suba...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Observability with OpenTelemetry
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When you run agents in production, you need visibility into what they did:
which tools they called
how long each model request took
how many tokens were spent
where failures occurred
The Agent SDK can export this data as OpenTelemetry traces, metrics, and log events to any backend that accepts the OpenTelemetry Protocol (OTLP), such as Honeycomb, Datadog, Grafana, Langfuse, or a self-hosted collector.
This guide explains how the SDK emits telemetry, how to configure the export, and how to tag and filter the data once it reaches your backend. To read token usage and cost directly from the SDK response stream instead of exporting to a backend, see
Track cost and usage
.
​
How telemetry flows from the SDK
The Agent SDK runs the Claude Code CLI as a child process and communicates with it over a local pipe. The CLI has OpenTelemetry instrumentation built in: it records spans around each model request and tool execution, emits metrics for token and cost counters, and emits structured log events for prompts and tool results. The SDK does not produce telemetry of its own. Instead, it passes configuration through to the CLI process, and the CLI exports directly to your collector.
Configuration is passed as environment variables. By default, the child process inherits your application’s environment, so you can configure telemetry in either of two places:
Process environment:
set the variables in your shell, container, or orchestrator before your application starts. Every
query()
call picks them up automatically with no code change. This is the recommended approach for production deployments.
Per-call options:
set the variables in
ClaudeAgentOptions.env
(Python) or
options.env
(TypeScript). Use this when different agents in the same process need different telemetry settings. In Python,
env
is merged on top of the inherited environment. In TypeScript,
env
replaces the inherited environment entirely, so include
...process.env
in the object you pass.
The CLI exports three independent OpenTelemetry signals. Each has its own enable switch and its own exporter, so you can turn on only the ones you need.
Signal
What it contains
Enable with
Metrics
Counters for tokens, cost, sessions, lines of code, and tool decisions
OTEL_METRICS_EXPORTER
Log events
Structured records for each prompt, API request, API error, and tool result
OTEL_LOGS_EXPORTER
Traces
Spans for each interaction, model request, tool call, and hook (beta)
OTEL_TRACES_EXPORTER
plus
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
For the complete list of metric names, event names, and attributes, see the Claude Code
Monitoring
reference. The Agent SDK emits the same data because it runs the same CLI. Span names are listed in
Read agent traces
below.
​
Enable telemetry export
Telemetry is off until you set
CLAUDE_CODE_ENABLE_TELEMETRY=1
and choose at least one exporter. The most common configuration sends all three signals over OTLP HTTP to a collector.
The following example sets the variables in a dictionary and passes them through
options.env
. The agent runs a single task, and the CLI exports spans, metrics, and events to the collector at
collector.example.com
while the loop consumes the response stream:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
OTEL_ENV
=
{
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
# Required for traces, which are in beta. Metrics and log events do not need this.
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA"
:
"1"
,
# Choose an exporter per signal. Use otlp for the SDK; see the Note below.
"OTEL_TRACES_EXPORTER"
:
"otlp"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
# Standard OTLP transport configuration.
"OTEL_EXPORTER_OTLP_PROTOCOL"
:
"http/protobuf"
,
"OTEL_EXPORTER_OTLP_ENDPOINT"
:
"http://collector.example.com:4318"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer your-token"
,
}
async
def
main
():
options
=
ClaudeAgentOptions(
env
=
OTEL_ENV
)
async
for
message
in
query(
prompt
=
"List the files in this directory"
,
options
=
options
):
print
(message)
asyncio.run(main())
Because the child process inherits your application’s environment by default, you can achieve the same result by exporting these variables in a Dockerfile, Kubernetes manifest, or shell profile and omitting
options.env
entirely.
The
console
exporter writes telemetry to standard output, which the SDK uses
as its message channel. Do not set
console
as an exporter value when running
through the SDK. To inspect telemetry locally, point
OTEL_EXPORTER_OTLP_ENDPOINT
at a local collector or an all-in-one Jaeger
container instead.
​
Flush telemetry from short-lived calls
The CLI batches telemetry and exports on an interval. On a clean process exit it attempts to flush pending data, but the flush is bounded by a short timeout, so spans can still be dropped if the collector is slow to respond. If your process is killed before the CLI shuts down, anything still in the batch buffer is lost. Lowering the export intervals reduces both windows.
By default, metrics export every 60 seconds and traces and logs export every 5 seconds. The following example shortens all three intervals so that data reaches the collector while a short task is still running:
Python
TypeScript
OTEL_ENV
=
{
# ... exporter configuration from the previous example ...
"OTEL_METRIC_EXPORT_INTERVAL"
:
"1000"
,
"OTEL_LOGS_EXPORT_INTERVAL"
:
"1000"
,
"OTEL_TRACES_EXPORT_INTERVAL"
:
"1000"
,
}
​
Read agent traces
Traces give you the most detailed view of an agent run. With
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
set, each step of the agent loop becomes a span you can inspect in your tracing backend:
claude_code.interaction
:
wraps a single turn of the agent loop, from receiving a prompt to producing a response.
claude_code.llm_request
:
wraps each call to the Claude API, with model name, latency, and token counts as attributes.
claude_code.tool
:
wraps each tool invocation, with child spans for the permission wait (
claude_code.tool.blocked_on_user
) and the execution itself (
claude_code.tool.execution
).
claude_code.hook
:
wraps each
hook
execution. Requires detailed beta tracing (
ENABLE_BETA_TRACING_DETAILED=1
and
BETA_TRACING_ENDPOINT
) in addition to the variables above.
The
llm_request
,
tool
, and
hook
spans are children of the enclosing
claude_code.interaction
span. When the agent spawns a subagent through the Task tool, the subagent’s
llm_request
and
tool
spans nest under the parent agent’s
claude_code.tool
span, so the full delegation chain appears as one trace.
Spans carry a
session.id
attribute by default. When you make several
query()
calls against the same
session
, filter on
session.id
in your backend to see them as one timeline. The attribute is omitted if
OTEL_METRICS_INCLUDE_SESSION_ID
is set to a falsy value.
Tracing is in beta. Span names and attributes may change between releases. See
Traces (beta)
in the Monitoring reference
for the trace exporter configuration variables.
​
Link traces to your application
The SDK automatically propagates W3C trace context into the CLI subprocess. When you call
query()
while an OpenTelemetry span is active in your application, the SDK injects
TRACEPARENT
and
TRACESTATE
into the child process environment, and the CLI reads them so its
claude_code.interaction
span becomes a child of your span. The agent run then appears inside your application’s trace instead of as a disconnected root.
The CLI also forwards
TRACEPARENT
to every Bash and PowerShell command it runs. If a command launched through the Bash tool emits its own OpenTelemetry spans, those spans nest under the
claude_code.tool.execution
span that wraps the command.
Auto-injection is skipped when you set
TRACEPARENT
explicitly in
options.env
, so you can pin a specific parent context if needed. Interactive CLI sessions ignore inbound
TRACEPARENT
entirely; only Agent SDK and
claude -p
runs honor it. See
Traces (beta)
in the Monitoring reference for the full span and attribute reference.
​
Tag telemetry from your agent
By default, the CLI reports
service.name
as
claude-code
. If you run several agents, or run the SDK alongside other services that export to the same collector, override the service name and add resource attributes so you can filter by agent in your backend.
The following example renames the service and attaches deployment metadata. These values are applied as OpenTelemetry resource attributes on every span, metric, and event the agent emits:
Python
TypeScript
options
=
ClaudeAgentOptions(
env
=
{
# ... exporter configuration ...
"OTEL_SERVICE_NAME"
:
"support-triage-agent"
,
"OTEL_RESOURCE_ATTRIBUTES"
:
"service.version=1.4.0,deployment.environment=production"
,
},
)
​
Attribute actions to your end users
The CLI attaches
identity attributes
to every event based on the credential it uses to call Anthropic. When you build an application that serves many end users from one deployment, these attributes identify your service’s credential, not the end user on whose behalf the agent acted.
To make tool calls and MCP activity attributable to your application’s end users, inject end-user identity as resource attributes on each
query()
call. Percent-encode values before interpolating them, since
OTEL_RESOURCE_ATTRIBUTES
reserves commas, spaces, and equals signs
. The following example attaches the requesting user and tenant to every span and event from one request:
Python
TypeScript
from
urllib.parse
import
quote
options
=
ClaudeAgentOptions(
env
=
{
# ... exporter configuration ...
"OTEL_RESOURCE_ATTRIBUTES"
:
f
"enduser.id=
{
quote(request.user_id)
}
,tenant.id=
{
quote(request.tenant_id)
}
"
,
},
)
With end-user identity attached, the
tool_decision
,
tool_result
,
mcp_server_connection
, and
permission_mode_changed
events become a per-user audit trail you can forward to a Security Information and Event Management (SIEM) platform. See
Audit security events
in the Monitoring reference for the full list of security-relevant events and the attributes each one carries.
​
Control sensitive data in exports
Telemetry is structural by default. Durations, model names, and tool names are recorded on every span; token counts are recorded when the underlying API request returns usage data, so spans for failed or aborted requests may omit them. The content your agent reads and writes is not recorded by default. These opt-in variables add content to the exported data:
Variable
Adds
OTEL_LOG_USER_PROMPTS=1
Prompt text on
claude_code.user_prompt
events and on the
claude_code.interaction
span
OTEL_LOG_TOOL_DETAILS=1
Tool input arguments (file paths, shell commands, search patterns) on
claude_code.tool_result
events
OTEL_LOG_TOOL_CONTENT=1
Full tool input and output bodies as span events on
claude_code.tool
, truncated at 60 KB. Requires
tracing
to be enabled
OTEL_LOG_RAW_API_BODIES
Full Anthropic Messages API request and response JSON as
claude_code.api_request_body
and
claude_code.api_response_body
log events. Set to
1
for inline bodies truncated at 60 KB, or
file:<dir>
for untruncated bodies on disk with a
body_ref
path in the event. Bodies include the entire conversation history and have extended-thinking content redacted. Enabling this implies consent to everything the three variables above would reveal
Leave these unset unless your observability pipeline is approved to store the data your agent handles. See
Security and privacy
in the Monitoring reference for the full list of attributes and redaction behavior.
​
Related documentation
These guides cover adjacent topics for monitoring and deploying agents:
Track cost and usage
: read token and cost data from the message stream without an external backend.
Hosting the Agent SDK
: deploy agents in containers where you can set OpenTelemetry variables at the environment level.
Monitoring
: the complete reference for every environment variable, metric, and event the CLI emits.
Was this page helpful?
Yes
No
Track cost and usage
Todo Lists
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/observability" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Observability with OpenTelemetry
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Suba...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Observability with OpenTelemetry
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When you run agents in production, you need visibility into what they did:
which tools they called
how long each model request took
how many tokens were spent
where failures occurred
The Agent SDK can export this data as OpenTelemetry traces, metrics, and log events to any backend that accepts the OpenTelemetry Protocol (OTLP), such as Honeycomb, Datadog, Grafana, Langfuse, or a self-hosted collector.
This guide explains how the SDK emits telemetry, how to configure the export, and how to tag and filter the data once it reaches your backend. To read token usage and cost directly from the SDK response stream instead of exporting to a backend, see
Track cost and usage
.
​
How telemetry flows from the SDK
The Agent SDK runs the Claude Code CLI as a child process and communicates with it over a local pipe. The CLI has OpenTelemetry instrumentation built in: it records spans around each model request and tool execution, emits metrics for token and cost counters, and emits structured log events for prompts and tool results. The SDK does not produce telemetry of its own. Instead, it passes configuration through to the CLI process, and the CLI exports directly to your collector.
Configuration is passed as environment variables. By default, the child process inherits your application’s environment, so you can configure telemetry in either of two places:
Process environment:
set the variables in your shell, container, or orchestrator before your application starts. Every
query()
call picks them up automatically with no code change. This is the recommended approach for production deployments.
Per-call options:
set the variables in
ClaudeAgentOptions.env
(Python) or
options.env
(TypeScript). Use this when different agents in the same process need different telemetry settings. In Python,
env
is merged on top of the inherited environment. In TypeScript,
env
replaces the inherited environment entirely, so include
...process.env
in the object you pass.
The CLI exports three independent OpenTelemetry signals. Each has its own enable switch and its own exporter, so you can turn on only the ones you need.
Signal
What it contains
Enable with
Metrics
Counters for tokens, cost, sessions, lines of code, and tool decisions
OTEL_METRICS_EXPORTER
Log events
Structured records for each prompt, API request, API error, and tool result
OTEL_LOGS_EXPORTER
Traces
Spans for each interaction, model request, tool call, and hook (beta)
OTEL_TRACES_EXPORTER
plus
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
For the complete list of metric names, event names, and attributes, see the Claude Code
Monitoring
reference. The Agent SDK emits the same data because it runs the same CLI. Span names are listed in
Read agent traces
below.
​
Enable telemetry export
Telemetry is off until you set
CLAUDE_CODE_ENABLE_TELEMETRY=1
and choose at least one exporter. The most common configuration sends all three signals over OTLP HTTP to a collector.
The following example sets the variables in a dictionary and passes them through
options.env
. The agent runs a single task, and the CLI exports spans, metrics, and events to the collector at
collector.example.com
while the loop consumes the response stream:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
OTEL_ENV
=
{
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
# Required for traces, which are in beta. Metrics and log events do not need this.
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA"
:
"1"
,
# Choose an exporter per signal. Use otlp for the SDK; see the Note below.
"OTEL_TRACES_EXPORTER"
:
"otlp"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
# Standard OTLP transport configuration.
"OTEL_EXPORTER_OTLP_PROTOCOL"
:
"http/protobuf"
,
"OTEL_EXPORTER_OTLP_ENDPOINT"
:
"http://collector.example.com:4318"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer your-token"
,
}
async
def
main
():
options
=
ClaudeAgentOptions(
env
=
OTEL_ENV
)
async
for
message
in
query(
prompt
=
"List the files in this directory"
,
options
=
options
):
print
(message)
asyncio.run(main())
Because the child process inherits your application’s environment by default, you can achieve the same result by exporting these variables in a Dockerfile, Kubernetes manifest, or shell profile and omitting
options.env
entirely.
The
console
exporter writes telemetry to standard output, which the SDK uses
as its message channel. Do not set
console
as an exporter value when running
through the SDK. To inspect telemetry locally, point
OTEL_EXPORTER_OTLP_ENDPOINT
at a local collector or an all-in-one Jaeger
container instead.
​
Flush telemetry from short-lived calls
The CLI batches telemetry and exports on an interval. On a clean process exit it attempts to flush pending data, but the flush is bounded by a short timeout, so spans can still be dropped if the collector is slow to respond. If your process is killed before the CLI shuts down, anything still in the batch buffer is lost. Lowering the export intervals reduces both windows.
By default, metrics export every 60 seconds and traces and logs export every 5 seconds. The following example shortens all three intervals so that data reaches the collector while a short task is still running:
Python
TypeScript
OTEL_ENV
=
{
# ... exporter configuration from the previous example ...
"OTEL_METRIC_EXPORT_INTERVAL"
:
"1000"
,
"OTEL_LOGS_EXPORT_INTERVAL"
:
"1000"
,
"OTEL_TRACES_EXPORT_INTERVAL"
:
"1000"
,
}
​
Read agent traces
Traces give you the most detailed view of an agent run. With
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
set, each step of the agent loop becomes a span you can inspect in your tracing backend:
claude_code.interaction
:
wraps a single turn of the agent loop, from receiving a prompt to producing a response.
claude_code.llm_request
:
wraps each call to the Claude API, with model name, latency, and token counts as attributes.
claude_code.tool
:
wraps each tool invocation, with child spans for the permission wait (
claude_code.tool.blocked_on_user
) and the execution itself (
claude_code.tool.execution
).
claude_code.hook
:
wraps each
hook
execution. Requires detailed beta tracing (
ENABLE_BETA_TRACING_DETAILED=1
and
BETA_TRACING_ENDPOINT
) in addition to the variables above.
The
llm_request
,
tool
, and
hook
spans are children of the enclosing
claude_code.interaction
span. When the agent spawns a subagent through the Task tool, the subagent’s
llm_request
and
tool
spans nest under the parent agent’s
claude_code.tool
span, so the full delegation chain appears as one trace.
Spans carry a
session.id
attribute by default. When you make several
query()
calls against the same
session
, filter on
session.id
in your backend to see them as one timeline. The attribute is omitted if
OTEL_METRICS_INCLUDE_SESSION_ID
is set to a falsy value.
Tracing is in beta. Span names and attributes may change between releases. See
Traces (beta)
in the Monitoring reference
for the trace exporter configuration variables.
​
Link traces to your application
The SDK automatically propagates W3C trace context into the CLI subprocess. When you call
query()
while an OpenTelemetry span is active in your application, the SDK injects
TRACEPARENT
and
TRACESTATE
into the child process environment, and the CLI reads them so its
claude_code.interaction
span becomes a child of your span. The agent run then appears inside your application’s trace instead of as a disconnected root.
The CLI also forwards
TRACEPARENT
to every Bash and PowerShell command it runs. If a command launched through the Bash tool emits its own OpenTelemetry spans, those spans nest under the
claude_code.tool.execution
span that wraps the command.
Auto-injection is skipped when you set
TRACEPARENT
explicitly in
options.env
, so you can pin a specific parent context if needed. Interactive CLI sessions ignore inbound
TRACEPARENT
entirely; only Agent SDK and
claude -p
runs honor it. See
Traces (beta)
in the Monitoring reference for the full span and attribute reference.
​
Tag telemetry from your agent
By default, the CLI reports
service.name
as
claude-code
. If you run several agents, or run the SDK alongside other services that export to the same collector, override the service name and add resource attributes so you can filter by agent in your backend.
The following example renames the service and attaches deployment metadata. These values are applied as OpenTelemetry resource attributes on every span, metric, and event the agent emits:
Python
TypeScript
options
=
ClaudeAgentOptions(
env
=
{
# ... exporter configuration ...
"OTEL_SERVICE_NAME"
:
"support-triage-agent"
,
"OTEL_RESOURCE_ATTRIBUTES"
:
"service.version=1.4.0,deployment.environment=production"
,
},
)
​
Attribute actions to your end users
The CLI attaches
identity attributes
to every event based on the credential it uses to call Anthropic. When you build an application that serves many end users from one deployment, these attributes identify your service’s credential, not the end user on whose behalf the agent acted.
To make tool calls and MCP activity attributable to your application’s end users, inject end-user identity as resource attributes on each
query()
call. Percent-encode values before interpolating them, since
OTEL_RESOURCE_ATTRIBUTES
reserves commas, spaces, and equals signs
. The following example attaches the requesting user and tenant to every span and event from one request:
Python
TypeScript
from
urllib.parse
import
quote
options
=
ClaudeAgentOptions(
env
=
{
# ... exporter configuration ...
"OTEL_RESOURCE_ATTRIBUTES"
:
f
"enduser.id=
{
quote(request.user_id)
}
,tenant.id=
{
quote(request.tenant_id)
}
"
,
},
)
With end-user identity attached, the
tool_decision
,
tool_result
,
mcp_server_connection
, and
permission_mode_changed
events become a per-user audit trail you can forward to a Security Information and Event Management (SIEM) platform. See
Audit security events
in the Monitoring reference for the full list of security-relevant events and the attributes each one carries.
​
Control sensitive data in exports
Telemetry is structural by default. Durations, model names, and tool names are recorded on every span; token counts are recorded when the underlying API request returns usage data, so spans for failed or aborted requests may omit them. The content your agent reads and writes is not recorded by default. These opt-in variables add content to the exported data:
Variable
Adds
OTEL_LOG_USER_PROMPTS=1
Prompt text on
claude_code.user_prompt
events and on the
claude_code.interaction
span
OTEL_LOG_TOOL_DETAILS=1
Tool input arguments (file paths, shell commands, search patterns) on
claude_code.tool_result
events
OTEL_LOG_TOOL_CONTENT=1
Full tool input and output bodies as span events on
claude_code.tool
, truncated at 60 KB. Requires
tracing
to be enabled
OTEL_LOG_RAW_API_BODIES
Full Anthropic Messages API request and response JSON as
claude_code.api_request_body
and
claude_code.api_response_body
log events. Set to
1
for inline bodies truncated at 60 KB, or
file:<dir>
for untruncated bodies on disk with a
body_ref
path in the event. Bodies include the entire conversation history and have extended-thinking content redacted. Enabling this implies consent to everything the three variables above would reveal
Leave these unset unless your observability pipeline is approved to store the data your agent handles. See
Security and privacy
in the Monitoring reference for the full list of attributes and redaction behavior.
​
Related documentation
These guides cover adjacent topics for monitoring and deploying agents:
Track cost and usage
: read token and cost data from the message stream without an external backend.
Hosting the Agent SDK
: deploy agents in containers where you can set OpenTelemetry variables at the environment level.
Monitoring
: the complete reference for every environment variable, metric, and event the CLI emits.
Was this page helpful?
Yes
No
Track cost and usage
Todo Lists
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/observability" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Give Claude custom tools</title>
  <link>https://code.claude.com/docs/en/agent-sdk/custom-tools</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/custom-tools</guid>
  <pubDate>Sun, 27 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Give Claude custom tools
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Give Claude custom tools
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Custom tools extend the Agent SDK by letting you define your own functions that Claude can call during a conversation. Using the SDK’s in-process MCP server, you can give Claude access to databases, external APIs, domain-specific logic, or any other capability your application needs.
This guide covers how to define tools with input schemas and handlers, bundle them into an MCP server, pass them to
query
, and control which tools Claude can access. It also covers error handling, tool annotations, and returning non-text content like images.
​
Quick reference
If you want to…
Do this
Define a tool
Use
@tool
(Python) or
tool()
(TypeScript) with a name, description, schema, and handler. See
Create a custom tool
.
Register a tool with Claude
Wrap in
create_sdk_mcp_server
/
createSdkMcpServer
and pass to
mcpServers
in
query()
. See
Call a custom tool
.
Pre-approve a tool
Add to your allowed tools. See
Configure allowed tools
.
Remove a built-in tool from Claude’s context
Pass a
tools
array listing only the built-ins you want. See
Configure allowed tools
.
Let Claude call tools in parallel
Set
readOnlyHint: true
on tools with no side effects. See
Add tool annotations
.
Handle errors without stopping the loop
Return
isError: true
instead of throwing. See
Handle errors
.
Return images or files
Use
image
or
resource
blocks in the content array. See
Return images and resources
.
Return a machine-readable JSON result
Set
structuredContent
on the result. See
Return structured data
.
Scale to many tools
Use
tool search
to load tools on demand.
​
Create a custom tool
A tool is defined by four parts, passed as arguments to the
tool()
helper in TypeScript or the
@tool
decorator in Python:
Name:
a unique identifier Claude uses to call the tool.
Description:
what the tool does. Claude reads this to decide when to call it.
Input schema:
the arguments Claude must provide. In TypeScript this is always a
Zod schema
, and the handler’s
args
are typed from it automatically. In Python this is a dict mapping names to types, like
{"latitude": float}
, which the SDK converts to JSON Schema for you. The Python decorator also accepts a full
JSON Schema
dict directly when you need enums, ranges, optional fields, or nested objects.
Handler:
the async function that runs when Claude calls the tool. It receives the validated arguments and must return an object with:
content
(required): an array of result blocks, each with a
type
of
"text"
,
"image"
, or
"resource"
. See
Return images and resources
for non-text blocks.
structuredContent
(optional): a JSON object holding the result as machine-readable data, returned alongside
content
. See
Return structured data
.
isError
(optional): set to
true
to signal a tool failure so Claude can react to it. See
Handle errors
.
After defining a tool, wrap it in a server with
createSdkMcpServer
(TypeScript) or
create_sdk_mcp_server
(Python). The server runs in-process inside your application, not as a separate process.
​
Weather tool example
This example defines a
get_temperature
tool and wraps it in an MCP server. It only sets up the tool; to pass it to
query
and run it, see
Call a custom tool
below.
Python
TypeScript
from
typing
import
Any
import
httpx
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
# Define a tool: name, description, input schema, handler
@tool
(
"get_temperature"
,
"Get the current temperature at a location"
,
{
"latitude"
:
float
,
"longitude"
:
float
},
)
async
def
get_temperature
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(
"https://api.open-meteo.com/v1/forecast"
,
params
=
{
"latitude"
: args[
"latitude"
],
"longitude"
: args[
"longitude"
],
"current"
:
"temperature_2m"
,
"temperature_unit"
:
"fahrenheit"
,
},
)
data
=
response.json()
# Return a content array - Claude sees this as the tool result
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Temperature:
{
data[
'current'
][
'temperature_2m'
]
}
°F"
,
}
]
}
# Wrap the tool in an in-process MCP server
weather_server
=
create_sdk_mcp_server(
name
=
"weather"
,
version
=
"1.0.0"
,
tools
=
[get_temperature],
)
See the
tool()
TypeScript reference or the
@tool
Python reference for full parameter details, including JSON Schema input formats and return value structure.
To make a parameter optional: in TypeScript, add
.default()
to the Zod field. In Python, the dict schema treats every key as required, so leave the parameter out of the schema, mention it in the description string, and read it with
args.get()
in the handler. The
get_precipitation_chance
tool below
shows both patterns.
​
Call a custom tool
Pass the MCP server you created to
query
via the
mcpServers
option. The key in
mcpServers
becomes the
{server_name}
segment in each tool’s fully qualified name:
mcp__{server_name}__{tool_name}
. List that name in
allowedTools
so the tool runs without a permission prompt.
These snippets reuse the
weatherServer
from the
example above
to ask Claude what the weather is in a specific location.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
main
():
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"weather"
: weather_server},
allowed_tools
=
[
"mcp__weather__get_temperature"
],
)
async
for
message
in
query(
prompt
=
"What's the temperature in San Francisco?"
,
options
=
options,
):
# ResultMessage is the final message after all tool calls complete
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
​
Add more tools
A server holds as many tools as you list in its
tools
array. With more than one tool on a server, you can list each one in
allowedTools
individually or use the wildcard
mcp__weather__*
to cover every tool the server exposes.
The example below adds a second tool,
get_precipitation_chance
, to the
weatherServer
from the
weather tool example
and rebuilds it with both tools in the array.
Python
TypeScript
# Define a second tool for the same server
@tool
(
"get_precipitation_chance"
,
"Get the hourly precipitation probability for a location. "
"Optionally pass 'hours' (1-24) to control how many hours to return."
,
{
"latitude"
:
float
,
"longitude"
:
float
},
)
async
def
get_precipitation_chance
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
# 'hours' isn't in the schema - read it with .get() to make it optional
hours
=
args.get(
"hours"
,
12
)
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(
"https://api.open-meteo.com/v1/forecast"
,
params
=
{
"latitude"
: args[
"latitude"
],
"longitude"
: args[
"longitude"
],
"hourly"
:
"precipitation_probability"
,
"forecast_days"
:
1
,
},
)
data
=
response.json()
chances
=
data[
"hourly"
][
"precipitation_probability"
][:hours]
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Next
{
hours
}
hours:
{
'%, '
.join(
map
(
str
, chances))
}
%"
,
}
]
}
# Rebuild the server with both tools in the array
weather_server
=
create_sdk_mcp_server(
name
=
"weather"
,
version
=
"1.0.0"
,
tools
=
[get_temperature, get_precipitation_chance],
)
Every tool in this array consumes context window space on every turn. If you’re defining dozens of tools, see
tool search
to load them on demand instead.
​
Add tool annotations
Tool annotations
are optional metadata describing how a tool behaves. Pass them as the fifth argument to
tool()
helper in TypeScript or via the
annotations
keyword argument for the
@tool
decorator in Python. All hint fields are Booleans.
Field
Default
Meaning
readOnlyHint
false
Tool does not modify its environment. Controls whether the tool can be called in parallel with other read-only tools.
destructiveHint
true
Tool may perform destructive updates. Informational only.
idempotentHint
false
Repeated calls with the same arguments have no additional effect. Informational only.
openWorldHint
true
Tool reaches systems outside your process. Informational only.
Annotations are metadata, not enforcement. A tool marked
readOnlyHint: true
can still write to disk if that’s what the handler does. Keep the annotation accurate to the handler.
This example adds
readOnlyHint
to the
get_temperature
tool from the
weather tool example
.
Python
TypeScript
from
claude_agent_sdk
import
tool, ToolAnnotations
@tool
(
"get_temperature"
,
"Get the current temperature at a location"
,
{
"latitude"
:
float
,
"longitude"
:
float
},
annotations
=
ToolAnnotations(
readOnlyHint
=
True
),
# Lets Claude batch this with other read-only calls
)
async
def
get_temperature
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
"..."
}]}
See
ToolAnnotations
in the
TypeScript
or
Python
reference.
​
Control tool access
The
weather tool example
registered a server and listed tools in
allowedTools
. This section covers how tool names are constructed and how to scope access when you have multiple tools or want to restrict built-ins.
​
Tool name format
When MCP tools are exposed to Claude, their names follow a specific format:
Pattern:
mcp__{server_name}__{tool_name}
Example: A tool named
get_temperature
in server
weather
becomes
mcp__weather__get_temperature
​
Configure allowed tools
The
tools
option and the allowed/disallowed lists operate on separate layers.
tools
controls which built-in tools appear in Claude’s context. Allowed and disallowed tool lists control whether calls are approved or denied once Claude attempts them.
Option
Layer
Effect
tools: ["Read", "Grep"]
Availability
Only the listed built-ins are in Claude’s context. Unlisted built-ins are removed. MCP tools are unaffected.
tools: []
Availability
All built-ins are removed. Claude can only use your MCP tools.
allowed tools
Permission
Listed tools run without a permission prompt. Unlisted tools remain available; calls go through the
permission flow
.
disallowed tools
Permission
Every call to a listed tool is denied. The tool stays in Claude’s context, so Claude may still attempt it before the call is rejected.
To limit which built-ins Claude can use, prefer
tools
over disallowed tools. Omitting a tool from
tools
removes it from context so Claude never attempts it; listing it in
disallowedTools
(Python:
disallowed_tools
) blocks the call but leaves the tool visible, so Claude may waste a turn trying it. See
Configure permissions
for the full evaluation order.
​
Handle errors
How your handler reports errors determines whether the agent loop continues or stops:
What happens
Result
Handler throws an uncaught exception
Agent loop stops. Claude never sees the error, and the
query
call fails.
Handler catches the error and returns
isError: true
(TS) /
"is_error": True
(Python)
Agent loop continues. Claude sees the error as data and can retry, try a different tool, or explain the failure.
The example below catches two kinds of failures inside the handler instead of letting them throw. A non-200 HTTP status is caught from the response and returned as an error result. A network error or invalid JSON is caught by the surrounding
try/except
(Python) or
try/catch
(TypeScript) and also returned as an error result. In both cases the handler returns normally and the agent loop continues.
Python
TypeScript
import
json
import
httpx
from
typing
import
Any
@tool
(
"fetch_data"
,
"Fetch data from an API"
,
{
"endpoint"
:
str
},
# Simple schema
)
async
def
fetch_data
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
try
:
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(args[
"endpoint"
])
if
response.status_code
!=
200
:
# Return the failure as a tool result so Claude can react to it.
# is_error marks this as a failed call rather than odd-looking data.
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"API error:
{
response.status_code
}
{
response.reason_phrase
}
"
,
}
],
"is_error"
:
True
,
}
data
=
response.json()
return
{
"content"
: [{
"type"
:
"text"
,
"text"
: json.dumps(data,
indent
=
2
)}]}
except
Exception
as
e:
# Catching here keeps the agent loop alive. An uncaught exception
# would end the whole query() call.
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Failed to fetch data:
{
str
(e)
}
"
}],
"is_error"
:
True
,
}
​
Return images and resources
The
content
array in a tool result accepts
text
,
image
, and
resource
blocks. You can mix them in the same response.
​
Images
An image block carries the image bytes inline, encoded as base64. There is no URL field. To return an image that lives at a URL, fetch it in the handler, read the response bytes, and base64-encode them before returning. The result is processed as visual input.
Field
Type
Notes
type
"image"
data
string
Base64-encoded bytes. Raw base64 only, no
data:image/...;base64,
prefix
mimeType
string
Required. For example
image/png
,
image/jpeg
,
image/webp
,
image/gif
Python
TypeScript
import
base64
import
httpx
# Define a tool that fetches an image from a URL and returns it to Claude
@tool
(
"fetch_image"
,
"Fetch an image from a URL and return it to Claude"
, {
"url"
:
str
})
async
def
fetch_image
(
args
):
async
with
httpx.AsyncClient()
as
client:
# Fetch the image bytes
response
=
await
client.get(args[
"url"
])
return
{
"content"
: [
{
"type"
:
"image"
,
"data"
: base64.b64encode(response.content).decode(
"ascii"
),
# Base64-encode the raw bytes
"mimeType"
: response.headers.get(
"content-type"
,
"image/png"
),
# Read MIME type from the response
}
]
}
​
Resources
A resource block embeds a piece of content identified by a URI. The URI is a label for Claude to reference; the actual content rides in the block’s
text
or
blob
field. Use this when your tool produces something that makes sense to address by name later, such as a generated file or a record from an external system.
Field
Type
Notes
type
"resource"
resource.uri
string
Identifier for the content. Any URI scheme
resource.text
string
The content, if it’s text. Provide this or
blob
, not both
resource.blob
string
The content base64-encoded, if it’s binary
resource.mimeType
string
Optional
This example shows a resource block returned from inside a tool handler. The URI
file:///tmp/report.md
is a label that Claude can reference later; the SDK does not read from that path.
TypeScript
Python
return
{
content:
[
{
type:
"resource"
,
resource:
{
uri:
"file:///tmp/report.md"
,
// Label for Claude to reference, not a path the SDK reads
mimeType:
"text/markdown"
,
text:
"# Report
\n
..."
// The actual content, inline
}
}
]
};
These block shapes come from the MCP
CallToolResult
type. See the
MCP specification
for the full definition.
​
Return structured data
structuredContent
is an optional JSON object on the result, separate from the
content
array. Use it to return raw values that Claude can read as exact fields instead of parsing them out of a text string or image.
When
structuredContent
is set, Claude receives the JSON plus any image or resource blocks from
content
. Text blocks in
content
are not forwarded, since they are assumed to duplicate the structured data. The example below renders a chart as an image block and returns the data points behind it in
structuredContent
from the same handler.
TypeScript
return
{
content:
[
{
type:
"image"
,
data:
chartPngBuffer
.
toString
(
"base64"
),
mimeType:
"image/png"
}
],
structuredContent:
{
series:
"temperature_2m"
,
unit:
"fahrenheit"
,
points:
[
62.1
,
63.4
,
65.0
,
64.2
]
}
};
The Python
@tool
decorator forwards only
content
and
is_error
from the handler’s return dict. To return
structuredContent
from Python, run a
standalone MCP server
instead of an in-process SDK server.
​
Example: unit converter
This tool converts values between units of length, temperature, and weight. A user can ask “convert 100 kilometers to miles” or “what is 72°F in Celsius,” and Claude picks the right unit type and units from the request.
It demonstrates two patterns:
Enum schemas:
unit_type
is constrained to a fixed set of values. In TypeScript, use
z.enum()
. In Python, the dict schema doesn’t support enums, so the full JSON Schema dict is required.
Unsupported input handling:
when a conversion pair isn’t found, the handler returns
isError: true
so Claude can tell the user what went wrong rather than treating a failure as a normal result.
Python
TypeScript
from
typing
import
Any
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
# z.enum() in TypeScript becomes an "enum" constraint in JSON Schema.
# The dict schema has no equivalent, so full JSON Schema is required.
@tool
(
"convert_units"
,
"Convert a value from one unit to another"
,
{
"type"
:
"object"
,
"properties"
: {
"unit_type"
: {
"type"
:
"string"
,
"enum"
: [
"length"
,
"temperature"
,
"weight"
],
"description"
:
"Category of unit"
,
},
"from_unit"
: {
"type"
:
"string"
,
"description"
:
"Unit to convert from, e.g. kilometers, fahrenheit, pounds"
,
},
"to_unit"
: {
"type"
:
"string"
,
"description"
:
"Unit to convert to"
},
"value"
: {
"type"
:
"number"
,
"description"
:
"Value to convert"
},
},
"required"
: [
"unit_type"
,
"from_unit"
,
"to_unit"
,
"value"
],
},
)
async
def
convert_units
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
conversions
=
{
"length"
: {
"kilometers_to_miles"
:
lambda
v
: v
*
0.621371
,
"miles_to_kilometers"
:
lambda
v
: v
*
1.60934
,
"meters_to_feet"
:
lambda
v
: v
*
3.28084
,
"feet_to_meters"
:
lambda
v
: v
*
0.3048
,
},
"temperature"
: {
"celsius_to_fahrenheit"
:
lambda
v
: (v
*
9
)
/
5
+
32
,
"fahrenheit_to_celsius"
:
lambda
v
: (v
-
32
)
*
5
/
9
,
"celsius_to_kelvin"
:
lambda
v
: v
+
273.15
,
"kelvin_to_celsius"
:
lambda
v
: v
-
273.15
,
},
"weight"
: {
"kilograms_to_pounds"
:
lambda
v
: v
*
2.20462
,
"pounds_to_kilograms"
:
lambda
v
: v
*
0.453592
,
"grams_to_ounces"
:
lambda
v
: v
*
0.035274
,
"ounces_to_grams"
:
lambda
v
: v
*
28.3495
,
},
}
key
=
f
"
{
args[
'from_unit'
]
}
_to_
{
args[
'to_unit'
]
}
"
fn
=
conversions.get(args[
"unit_type"
], {}).get(key)
if
not
fn:
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Unsupported conversion:
{
args[
'from_unit'
]
}
to
{
args[
'to_unit'
]
}
"
,
}
],
"is_error"
:
True
,
}
result
=
fn(args[
"value"
])
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"
{
args[
'value'
]
}
{
args[
'from_unit'
]
}
=
{
result
:.4f}
{
args[
'to_unit'
]
}
"
,
}
]
}
converter_server
=
create_sdk_mcp_server(
name
=
"converter"
,
version
=
"1.0.0"
,
tools
=
[convert_units],
)
Once the server is defined, pass it to
query
the same way as the weather example. This example sends three different prompts in a loop to show the same tool handling different unit types. For each response, it inspects
AssistantMessage
objects (which contain the tool calls Claude made during that turn) and prints each
ToolUseBlock
before printing the final
ResultMessage
text. This lets you see when Claude is using the tool versus answering from its own knowledge.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
query,
ClaudeAgentOptions,
ResultMessage,
AssistantMessage,
ToolUseBlock,
)
async
def
main
():
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"converter"
: converter_server},
allowed_tools
=
[
"mcp__converter__convert_units"
],
)
prompts
=
[
"Convert 100 kilometers to miles."
,
"What is 72°F in Celsius?"
,
"How many pounds is 5 kilograms?"
,
]
for
prompt
in
prompts:
async
for
message
in
query(
prompt
=
prompt,
options
=
options):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
print
(
f
"[tool call]
{
block.name
}
(
{
block.input
}
)"
)
elif
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"Q:
{
prompt
}
\n
A:
{
message.result
}
\n
"
)
asyncio.run(main())
​
Next steps
Custom tools wrap async functions in a standard interface. You can mix the patterns on this page in the same server: a single server can hold a database tool, an API gateway tool, and an image renderer alongside each other.
From here:
If your server grows to dozens of tools, see
tool search
to defer loading them until Claude needs them.
To connect to external MCP servers (filesystem, GitHub, Slack) instead of building your own, see
Connect MCP servers
.
To control which tools run automatically versus requiring approval, see
Configure permissions
.
​
Related documentation
TypeScript SDK Reference
Python SDK Reference
MCP Documentation
SDK Overview
Was this page helpful?
Yes
No
Get structured output from agents
Connect to external tools with MCP
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/custom-tools" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Give Claude custom tools
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Give Claude custom tools
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Custom tools extend the Agent SDK by letting you define your own functions that Claude can call during a conversation. Using the SDK’s in-process MCP server, you can give Claude access to databases, external APIs, domain-specific logic, or any other capability your application needs.
This guide covers how to define tools with input schemas and handlers, bundle them into an MCP server, pass them to
query
, and control which tools Claude can access. It also covers error handling, tool annotations, and returning non-text content like images.
​
Quick reference
If you want to…
Do this
Define a tool
Use
@tool
(Python) or
tool()
(TypeScript) with a name, description, schema, and handler. See
Create a custom tool
.
Register a tool with Claude
Wrap in
create_sdk_mcp_server
/
createSdkMcpServer
and pass to
mcpServers
in
query()
. See
Call a custom tool
.
Pre-approve a tool
Add to your allowed tools. See
Configure allowed tools
.
Remove a built-in tool from Claude’s context
Pass a
tools
array listing only the built-ins you want. See
Configure allowed tools
.
Let Claude call tools in parallel
Set
readOnlyHint: true
on tools with no side effects. See
Add tool annotations
.
Handle errors without stopping the loop
Return
isError: true
instead of throwing. See
Handle errors
.
Return images or files
Use
image
or
resource
blocks in the content array. See
Return images and resources
.
Return a machine-readable JSON result
Set
structuredContent
on the result. See
Return structured data
.
Scale to many tools
Use
tool search
to load tools on demand.
​
Create a custom tool
A tool is defined by four parts, passed as arguments to the
tool()
helper in TypeScript or the
@tool
decorator in Python:
Name:
a unique identifier Claude uses to call the tool.
Description:
what the tool does. Claude reads this to decide when to call it.
Input schema:
the arguments Claude must provide. In TypeScript this is always a
Zod schema
, and the handler’s
args
are typed from it automatically. In Python this is a dict mapping names to types, like
{"latitude": float}
, which the SDK converts to JSON Schema for you. The Python decorator also accepts a full
JSON Schema
dict directly when you need enums, ranges, optional fields, or nested objects.
Handler:
the async function that runs when Claude calls the tool. It receives the validated arguments and must return an object with:
content
(required): an array of result blocks, each with a
type
of
"text"
,
"image"
, or
"resource"
. See
Return images and resources
for non-text blocks.
structuredContent
(optional): a JSON object holding the result as machine-readable data, returned alongside
content
. See
Return structured data
.
isError
(optional): set to
true
to signal a tool failure so Claude can react to it. See
Handle errors
.
After defining a tool, wrap it in a server with
createSdkMcpServer
(TypeScript) or
create_sdk_mcp_server
(Python). The server runs in-process inside your application, not as a separate process.
​
Weather tool example
This example defines a
get_temperature
tool and wraps it in an MCP server. It only sets up the tool; to pass it to
query
and run it, see
Call a custom tool
below.
Python
TypeScript
from
typing
import
Any
import
httpx
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
# Define a tool: name, description, input schema, handler
@tool
(
"get_temperature"
,
"Get the current temperature at a location"
,
{
"latitude"
:
float
,
"longitude"
:
float
},
)
async
def
get_temperature
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(
"https://api.open-meteo.com/v1/forecast"
,
params
=
{
"latitude"
: args[
"latitude"
],
"longitude"
: args[
"longitude"
],
"current"
:
"temperature_2m"
,
"temperature_unit"
:
"fahrenheit"
,
},
)
data
=
response.json()
# Return a content array - Claude sees this as the tool result
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Temperature:
{
data[
'current'
][
'temperature_2m'
]
}
°F"
,
}
]
}
# Wrap the tool in an in-process MCP server
weather_server
=
create_sdk_mcp_server(
name
=
"weather"
,
version
=
"1.0.0"
,
tools
=
[get_temperature],
)
See the
tool()
TypeScript reference or the
@tool
Python reference for full parameter details, including JSON Schema input formats and return value structure.
To make a parameter optional: in TypeScript, add
.default()
to the Zod field. In Python, the dict schema treats every key as required, so leave the parameter out of the schema, mention it in the description string, and read it with
args.get()
in the handler. The
get_precipitation_chance
tool below
shows both patterns.
​
Call a custom tool
Pass the MCP server you created to
query
via the
mcpServers
option. The key in
mcpServers
becomes the
{server_name}
segment in each tool’s fully qualified name:
mcp__{server_name}__{tool_name}
. List that name in
allowedTools
so the tool runs without a permission prompt.
These snippets reuse the
weatherServer
from the
example above
to ask Claude what the weather is in a specific location.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
main
():
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"weather"
: weather_server},
allowed_tools
=
[
"mcp__weather__get_temperature"
],
)
async
for
message
in
query(
prompt
=
"What's the temperature in San Francisco?"
,
options
=
options,
):
# ResultMessage is the final message after all tool calls complete
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
asyncio.run(main())
​
Add more tools
A server holds as many tools as you list in its
tools
array. With more than one tool on a server, you can list each one in
allowedTools
individually or use the wildcard
mcp__weather__*
to cover every tool the server exposes.
The example below adds a second tool,
get_precipitation_chance
, to the
weatherServer
from the
weather tool example
and rebuilds it with both tools in the array.
Python
TypeScript
# Define a second tool for the same server
@tool
(
"get_precipitation_chance"
,
"Get the hourly precipitation probability for a location. "
"Optionally pass 'hours' (1-24) to control how many hours to return."
,
{
"latitude"
:
float
,
"longitude"
:
float
},
)
async
def
get_precipitation_chance
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
# 'hours' isn't in the schema - read it with .get() to make it optional
hours
=
args.get(
"hours"
,
12
)
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(
"https://api.open-meteo.com/v1/forecast"
,
params
=
{
"latitude"
: args[
"latitude"
],
"longitude"
: args[
"longitude"
],
"hourly"
:
"precipitation_probability"
,
"forecast_days"
:
1
,
},
)
data
=
response.json()
chances
=
data[
"hourly"
][
"precipitation_probability"
][:hours]
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Next
{
hours
}
hours:
{
'%, '
.join(
map
(
str
, chances))
}
%"
,
}
]
}
# Rebuild the server with both tools in the array
weather_server
=
create_sdk_mcp_server(
name
=
"weather"
,
version
=
"1.0.0"
,
tools
=
[get_temperature, get_precipitation_chance],
)
Every tool in this array consumes context window space on every turn. If you’re defining dozens of tools, see
tool search
to load them on demand instead.
​
Add tool annotations
Tool annotations
are optional metadata describing how a tool behaves. Pass them as the fifth argument to
tool()
helper in TypeScript or via the
annotations
keyword argument for the
@tool
decorator in Python. All hint fields are Booleans.
Field
Default
Meaning
readOnlyHint
false
Tool does not modify its environment. Controls whether the tool can be called in parallel with other read-only tools.
destructiveHint
true
Tool may perform destructive updates. Informational only.
idempotentHint
false
Repeated calls with the same arguments have no additional effect. Informational only.
openWorldHint
true
Tool reaches systems outside your process. Informational only.
Annotations are metadata, not enforcement. A tool marked
readOnlyHint: true
can still write to disk if that’s what the handler does. Keep the annotation accurate to the handler.
This example adds
readOnlyHint
to the
get_temperature
tool from the
weather tool example
.
Python
TypeScript
from
claude_agent_sdk
import
tool, ToolAnnotations
@tool
(
"get_temperature"
,
"Get the current temperature at a location"
,
{
"latitude"
:
float
,
"longitude"
:
float
},
annotations
=
ToolAnnotations(
readOnlyHint
=
True
),
# Lets Claude batch this with other read-only calls
)
async
def
get_temperature
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
"..."
}]}
See
ToolAnnotations
in the
TypeScript
or
Python
reference.
​
Control tool access
The
weather tool example
registered a server and listed tools in
allowedTools
. This section covers how tool names are constructed and how to scope access when you have multiple tools or want to restrict built-ins.
​
Tool name format
When MCP tools are exposed to Claude, their names follow a specific format:
Pattern:
mcp__{server_name}__{tool_name}
Example: A tool named
get_temperature
in server
weather
becomes
mcp__weather__get_temperature
​
Configure allowed tools
The
tools
option and the allowed/disallowed lists operate on separate layers.
tools
controls which built-in tools appear in Claude’s context. Allowed and disallowed tool lists control whether calls are approved or denied once Claude attempts them.
Option
Layer
Effect
tools: ["Read", "Grep"]
Availability
Only the listed built-ins are in Claude’s context. Unlisted built-ins are removed. MCP tools are unaffected.
tools: []
Availability
All built-ins are removed. Claude can only use your MCP tools.
allowed tools
Permission
Listed tools run without a permission prompt. Unlisted tools remain available; calls go through the
permission flow
.
disallowed tools
Permission
Every call to a listed tool is denied. The tool stays in Claude’s context, so Claude may still attempt it before the call is rejected.
To limit which built-ins Claude can use, prefer
tools
over disallowed tools. Omitting a tool from
tools
removes it from context so Claude never attempts it; listing it in
disallowedTools
(Python:
disallowed_tools
) blocks the call but leaves the tool visible, so Claude may waste a turn trying it. See
Configure permissions
for the full evaluation order.
​
Handle errors
How your handler reports errors determines whether the agent loop continues or stops:
What happens
Result
Handler throws an uncaught exception
Agent loop stops. Claude never sees the error, and the
query
call fails.
Handler catches the error and returns
isError: true
(TS) /
"is_error": True
(Python)
Agent loop continues. Claude sees the error as data and can retry, try a different tool, or explain the failure.
The example below catches two kinds of failures inside the handler instead of letting them throw. A non-200 HTTP status is caught from the response and returned as an error result. A network error or invalid JSON is caught by the surrounding
try/except
(Python) or
try/catch
(TypeScript) and also returned as an error result. In both cases the handler returns normally and the agent loop continues.
Python
TypeScript
import
json
import
httpx
from
typing
import
Any
@tool
(
"fetch_data"
,
"Fetch data from an API"
,
{
"endpoint"
:
str
},
# Simple schema
)
async
def
fetch_data
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
try
:
async
with
httpx.AsyncClient()
as
client:
response
=
await
client.get(args[
"endpoint"
])
if
response.status_code
!=
200
:
# Return the failure as a tool result so Claude can react to it.
# is_error marks this as a failed call rather than odd-looking data.
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"API error:
{
response.status_code
}
{
response.reason_phrase
}
"
,
}
],
"is_error"
:
True
,
}
data
=
response.json()
return
{
"content"
: [{
"type"
:
"text"
,
"text"
: json.dumps(data,
indent
=
2
)}]}
except
Exception
as
e:
# Catching here keeps the agent loop alive. An uncaught exception
# would end the whole query() call.
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Failed to fetch data:
{
str
(e)
}
"
}],
"is_error"
:
True
,
}
​
Return images and resources
The
content
array in a tool result accepts
text
,
image
, and
resource
blocks. You can mix them in the same response.
​
Images
An image block carries the image bytes inline, encoded as base64. There is no URL field. To return an image that lives at a URL, fetch it in the handler, read the response bytes, and base64-encode them before returning. The result is processed as visual input.
Field
Type
Notes
type
"image"
data
string
Base64-encoded bytes. Raw base64 only, no
data:image/...;base64,
prefix
mimeType
string
Required. For example
image/png
,
image/jpeg
,
image/webp
,
image/gif
Python
TypeScript
import
base64
import
httpx
# Define a tool that fetches an image from a URL and returns it to Claude
@tool
(
"fetch_image"
,
"Fetch an image from a URL and return it to Claude"
, {
"url"
:
str
})
async
def
fetch_image
(
args
):
async
with
httpx.AsyncClient()
as
client:
# Fetch the image bytes
response
=
await
client.get(args[
"url"
])
return
{
"content"
: [
{
"type"
:
"image"
,
"data"
: base64.b64encode(response.content).decode(
"ascii"
),
# Base64-encode the raw bytes
"mimeType"
: response.headers.get(
"content-type"
,
"image/png"
),
# Read MIME type from the response
}
]
}
​
Resources
A resource block embeds a piece of content identified by a URI. The URI is a label for Claude to reference; the actual content rides in the block’s
text
or
blob
field. Use this when your tool produces something that makes sense to address by name later, such as a generated file or a record from an external system.
Field
Type
Notes
type
"resource"
resource.uri
string
Identifier for the content. Any URI scheme
resource.text
string
The content, if it’s text. Provide this or
blob
, not both
resource.blob
string
The content base64-encoded, if it’s binary
resource.mimeType
string
Optional
This example shows a resource block returned from inside a tool handler. The URI
file:///tmp/report.md
is a label that Claude can reference later; the SDK does not read from that path.
TypeScript
Python
return
{
content:
[
{
type:
"resource"
,
resource:
{
uri:
"file:///tmp/report.md"
,
// Label for Claude to reference, not a path the SDK reads
mimeType:
"text/markdown"
,
text:
"# Report
\n
..."
// The actual content, inline
}
}
]
};
These block shapes come from the MCP
CallToolResult
type. See the
MCP specification
for the full definition.
​
Return structured data
structuredContent
is an optional JSON object on the result, separate from the
content
array. Use it to return raw values that Claude can read as exact fields instead of parsing them out of a text string or image.
When
structuredContent
is set, Claude receives the JSON plus any image or resource blocks from
content
. Text blocks in
content
are not forwarded, since they are assumed to duplicate the structured data. The example below renders a chart as an image block and returns the data points behind it in
structuredContent
from the same handler.
TypeScript
return
{
content:
[
{
type:
"image"
,
data:
chartPngBuffer
.
toString
(
"base64"
),
mimeType:
"image/png"
}
],
structuredContent:
{
series:
"temperature_2m"
,
unit:
"fahrenheit"
,
points:
[
62.1
,
63.4
,
65.0
,
64.2
]
}
};
The Python
@tool
decorator forwards only
content
and
is_error
from the handler’s return dict. To return
structuredContent
from Python, run a
standalone MCP server
instead of an in-process SDK server.
​
Example: unit converter
This tool converts values between units of length, temperature, and weight. A user can ask “convert 100 kilometers to miles” or “what is 72°F in Celsius,” and Claude picks the right unit type and units from the request.
It demonstrates two patterns:
Enum schemas:
unit_type
is constrained to a fixed set of values. In TypeScript, use
z.enum()
. In Python, the dict schema doesn’t support enums, so the full JSON Schema dict is required.
Unsupported input handling:
when a conversion pair isn’t found, the handler returns
isError: true
so Claude can tell the user what went wrong rather than treating a failure as a normal result.
Python
TypeScript
from
typing
import
Any
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
# z.enum() in TypeScript becomes an "enum" constraint in JSON Schema.
# The dict schema has no equivalent, so full JSON Schema is required.
@tool
(
"convert_units"
,
"Convert a value from one unit to another"
,
{
"type"
:
"object"
,
"properties"
: {
"unit_type"
: {
"type"
:
"string"
,
"enum"
: [
"length"
,
"temperature"
,
"weight"
],
"description"
:
"Category of unit"
,
},
"from_unit"
: {
"type"
:
"string"
,
"description"
:
"Unit to convert from, e.g. kilometers, fahrenheit, pounds"
,
},
"to_unit"
: {
"type"
:
"string"
,
"description"
:
"Unit to convert to"
},
"value"
: {
"type"
:
"number"
,
"description"
:
"Value to convert"
},
},
"required"
: [
"unit_type"
,
"from_unit"
,
"to_unit"
,
"value"
],
},
)
async
def
convert_units
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
conversions
=
{
"length"
: {
"kilometers_to_miles"
:
lambda
v
: v
*
0.621371
,
"miles_to_kilometers"
:
lambda
v
: v
*
1.60934
,
"meters_to_feet"
:
lambda
v
: v
*
3.28084
,
"feet_to_meters"
:
lambda
v
: v
*
0.3048
,
},
"temperature"
: {
"celsius_to_fahrenheit"
:
lambda
v
: (v
*
9
)
/
5
+
32
,
"fahrenheit_to_celsius"
:
lambda
v
: (v
-
32
)
*
5
/
9
,
"celsius_to_kelvin"
:
lambda
v
: v
+
273.15
,
"kelvin_to_celsius"
:
lambda
v
: v
-
273.15
,
},
"weight"
: {
"kilograms_to_pounds"
:
lambda
v
: v
*
2.20462
,
"pounds_to_kilograms"
:
lambda
v
: v
*
0.453592
,
"grams_to_ounces"
:
lambda
v
: v
*
0.035274
,
"ounces_to_grams"
:
lambda
v
: v
*
28.3495
,
},
}
key
=
f
"
{
args[
'from_unit'
]
}
_to_
{
args[
'to_unit'
]
}
"
fn
=
conversions.get(args[
"unit_type"
], {}).get(key)
if
not
fn:
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"Unsupported conversion:
{
args[
'from_unit'
]
}
to
{
args[
'to_unit'
]
}
"
,
}
],
"is_error"
:
True
,
}
result
=
fn(args[
"value"
])
return
{
"content"
: [
{
"type"
:
"text"
,
"text"
:
f
"
{
args[
'value'
]
}
{
args[
'from_unit'
]
}
=
{
result
:.4f}
{
args[
'to_unit'
]
}
"
,
}
]
}
converter_server
=
create_sdk_mcp_server(
name
=
"converter"
,
version
=
"1.0.0"
,
tools
=
[convert_units],
)
Once the server is defined, pass it to
query
the same way as the weather example. This example sends three different prompts in a loop to show the same tool handling different unit types. For each response, it inspects
AssistantMessage
objects (which contain the tool calls Claude made during that turn) and prints each
ToolUseBlock
before printing the final
ResultMessage
text. This lets you see when Claude is using the tool versus answering from its own knowledge.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
query,
ClaudeAgentOptions,
ResultMessage,
AssistantMessage,
ToolUseBlock,
)
async
def
main
():
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"converter"
: converter_server},
allowed_tools
=
[
"mcp__converter__convert_units"
],
)
prompts
=
[
"Convert 100 kilometers to miles."
,
"What is 72°F in Celsius?"
,
"How many pounds is 5 kilograms?"
,
]
for
prompt
in
prompts:
async
for
message
in
query(
prompt
=
prompt,
options
=
options):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
print
(
f
"[tool call]
{
block.name
}
(
{
block.input
}
)"
)
elif
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"Q:
{
prompt
}
\n
A:
{
message.result
}
\n
"
)
asyncio.run(main())
​
Next steps
Custom tools wrap async functions in a standard interface. You can mix the patterns on this page in the same server: a single server can hold a database tool, an API gateway tool, and an image renderer alongside each other.
From here:
If your server grows to dozens of tools, see
tool search
to defer loading them until Claude needs them.
To connect to external MCP servers (filesystem, GitHub, Slack) instead of building your own, see
Connect MCP servers
.
To control which tools run automatically versus requiring approval, see
Configure permissions
.
​
Related documentation
TypeScript SDK Reference
Python SDK Reference
MCP Documentation
SDK Overview
Was this page helpful?
Yes
No
Get structured output from agents
Connect to external tools with MCP
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/custom-tools" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Hosting the Agent SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/hosting</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/hosting</guid>
  <pubDate>Sat, 19 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Hosting the Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Hosting the Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK differs from traditional stateless LLM APIs in that it maintains conversational state and executes commands in a persistent environment. This guide covers the architecture, hosting considerations, and best practices for deploying SDK-based agents in production.
For security hardening beyond basic sandboxing (including network controls, credential management, and isolation options), see
Secure Deployment
.
​
Hosting Requirements
​
Container-Based Sandboxing
For security and isolation, the SDK should run inside a sandboxed container environment. This provides process isolation, resource limits, network control, and ephemeral filesystems.
The SDK also supports
programmatic sandbox configuration
for command execution.
​
System Requirements
Each SDK instance requires:
Runtime dependencies
Python 3.10+ for the Python SDK, or Node.js 18+ for the TypeScript SDK
Both SDK packages bundle a native Claude Code binary for the host platform, so no separate Claude Code or Node.js install is needed for the spawned CLI
Resource allocation
Recommended: 1GiB RAM, 5GiB of disk, and 1 CPU (vary this based on your task as needed)
Network access
Outbound HTTPS to
api.anthropic.com
Optional: Access to MCP servers or external tools
​
Understanding the SDK Architecture
Unlike stateless API calls, the Claude Agent SDK operates as a
long-running process
that:
Executes commands
in a persistent shell environment
Manages file operations
within a working directory
Handles tool execution
with context from previous interactions
​
Sandbox Provider Options
Several providers specialize in secure container environments for AI code execution:
Modal Sandbox
-
demo implementation
Cloudflare Sandboxes
Daytona
E2B
Fly Machines
Vercel Sandbox
For self-hosted options (Docker, gVisor, Firecracker) and detailed isolation configuration, see
Isolation Technologies
.
​
Production Deployment Patterns
​
Pattern 1: Ephemeral Sessions
Create a new container for each user task, then destroy it when complete.
Best for one-off tasks, the user may still interact with the AI while the task is completing, but once completed the container is destroyed.
Examples:
Bug Investigation & Fix: Debug and resolve a specific issue with relevant context
Invoice Processing: Extract and structure data from receipts/invoices for accounting systems
Translation Tasks: Translate documents or content batches between languages
Image/Video Processing: Apply transformations, optimizations, or extract metadata from media files
​
Pattern 2: Long-Running Sessions
Maintain persistent container instances for long running tasks. Often times running
multiple
Claude Agent processes inside of the container based on demand.
Best for proactive agents that take action without the users input, agents that serve content or agents that process high amounts of messages.
Examples:
Email Agent: Monitors incoming emails and autonomously triages, responds, or takes actions based on content
Site Builder: Hosts custom websites per user with live editing capabilities served through container ports
High-Frequency Chat Bots: Handles continuous message streams from platforms like Slack where rapid response times are critical
​
Pattern 3: Hybrid Sessions
Ephemeral containers that are hydrated with history and state, possibly from a database or from the SDK’s session resumption features.
Best for containers with intermittent interaction from the user that kicks off work and spins down when the work is completed but can be continued.
Examples:
Personal Project Manager: Helps manage ongoing projects with intermittent check-ins, maintains context of tasks, decisions, and progress
Deep Research: Conducts multi-hour research tasks, saves findings and resumes investigation when user returns
Customer Support Agent: Handles support tickets that span multiple interactions, loads ticket history and customer context
​
Pattern 4: Single Containers
Run multiple Claude Agent SDK processes in one global container.
Best for agents that must collaborate closely together. This is likely the least popular pattern because you will have to prevent agents from overwriting each other.
Examples:
Simulations
: Agents that interact with each other in simulations such as video games.
​
FAQ
​
How do I communicate with my sandboxes?
When hosting in containers, expose ports to communicate with your SDK instances. Your application can expose HTTP/WebSocket endpoints for external clients while the SDK runs internally within the container.
​
What is the cost of hosting a container?
The dominant cost of serving agents is the tokens; containers vary based on what you provision, but a minimum cost is roughly 5 cents per hour running.
​
When should I shut down idle containers vs. keeping them warm?
This is likely provider dependent, different sandbox providers will let you set different criteria for idle timeouts after which a sandbox might spin down.
You will want to tune this timeout based on how frequent you think user response might be.
​
How often should I update the Claude Code CLI?
The Claude Code CLI is versioned with semver, so any breaking changes will be versioned.
​
How do I monitor container health and agent performance?
Since containers are just servers the same logging infrastructure you use for the backend will work for containers.
​
How long can an agent session run before timing out?
An agent session will not timeout, but consider setting a ‘maxTurns’ property to prevent Claude from getting stuck in a loop.
​
Next Steps
Secure Deployment
- Network controls, credential management, and isolation hardening
TypeScript SDK - Sandbox Settings
- Configure sandbox programmatically
Sessions Guide
- Learn about session management
Permissions
- Configure tool permissions
Cost Tracking
- Monitor API usage
MCP Integration
- Extend with custom tools
Was this page helpful?
Yes
No
Todo Lists
Securely deploying AI agents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/hosting" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Hosting the Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Hosting the Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK differs from traditional stateless LLM APIs in that it maintains conversational state and executes commands in a persistent environment. This guide covers the architecture, hosting considerations, and best practices for deploying SDK-based agents in production.
For security hardening beyond basic sandboxing (including network controls, credential management, and isolation options), see
Secure Deployment
.
​
Hosting Requirements
​
Container-Based Sandboxing
For security and isolation, the SDK should run inside a sandboxed container environment. This provides process isolation, resource limits, network control, and ephemeral filesystems.
The SDK also supports
programmatic sandbox configuration
for command execution.
​
System Requirements
Each SDK instance requires:
Runtime dependencies
Python 3.10+ for the Python SDK, or Node.js 18+ for the TypeScript SDK
Both SDK packages bundle a native Claude Code binary for the host platform, so no separate Claude Code or Node.js install is needed for the spawned CLI
Resource allocation
Recommended: 1GiB RAM, 5GiB of disk, and 1 CPU (vary this based on your task as needed)
Network access
Outbound HTTPS to
api.anthropic.com
Optional: Access to MCP servers or external tools
​
Understanding the SDK Architecture
Unlike stateless API calls, the Claude Agent SDK operates as a
long-running process
that:
Executes commands
in a persistent shell environment
Manages file operations
within a working directory
Handles tool execution
with context from previous interactions
​
Sandbox Provider Options
Several providers specialize in secure container environments for AI code execution:
Modal Sandbox
-
demo implementation
Cloudflare Sandboxes
Daytona
E2B
Fly Machines
Vercel Sandbox
For self-hosted options (Docker, gVisor, Firecracker) and detailed isolation configuration, see
Isolation Technologies
.
​
Production Deployment Patterns
​
Pattern 1: Ephemeral Sessions
Create a new container for each user task, then destroy it when complete.
Best for one-off tasks, the user may still interact with the AI while the task is completing, but once completed the container is destroyed.
Examples:
Bug Investigation & Fix: Debug and resolve a specific issue with relevant context
Invoice Processing: Extract and structure data from receipts/invoices for accounting systems
Translation Tasks: Translate documents or content batches between languages
Image/Video Processing: Apply transformations, optimizations, or extract metadata from media files
​
Pattern 2: Long-Running Sessions
Maintain persistent container instances for long running tasks. Often times running
multiple
Claude Agent processes inside of the container based on demand.
Best for proactive agents that take action without the users input, agents that serve content or agents that process high amounts of messages.
Examples:
Email Agent: Monitors incoming emails and autonomously triages, responds, or takes actions based on content
Site Builder: Hosts custom websites per user with live editing capabilities served through container ports
High-Frequency Chat Bots: Handles continuous message streams from platforms like Slack where rapid response times are critical
​
Pattern 3: Hybrid Sessions
Ephemeral containers that are hydrated with history and state, possibly from a database or from the SDK’s session resumption features.
Best for containers with intermittent interaction from the user that kicks off work and spins down when the work is completed but can be continued.
Examples:
Personal Project Manager: Helps manage ongoing projects with intermittent check-ins, maintains context of tasks, decisions, and progress
Deep Research: Conducts multi-hour research tasks, saves findings and resumes investigation when user returns
Customer Support Agent: Handles support tickets that span multiple interactions, loads ticket history and customer context
​
Pattern 4: Single Containers
Run multiple Claude Agent SDK processes in one global container.
Best for agents that must collaborate closely together. This is likely the least popular pattern because you will have to prevent agents from overwriting each other.
Examples:
Simulations
: Agents that interact with each other in simulations such as video games.
​
FAQ
​
How do I communicate with my sandboxes?
When hosting in containers, expose ports to communicate with your SDK instances. Your application can expose HTTP/WebSocket endpoints for external clients while the SDK runs internally within the container.
​
What is the cost of hosting a container?
The dominant cost of serving agents is the tokens; containers vary based on what you provision, but a minimum cost is roughly 5 cents per hour running.
​
When should I shut down idle containers vs. keeping them warm?
This is likely provider dependent, different sandbox providers will let you set different criteria for idle timeouts after which a sandbox might spin down.
You will want to tune this timeout based on how frequent you think user response might be.
​
How often should I update the Claude Code CLI?
The Claude Code CLI is versioned with semver, so any breaking changes will be versioned.
​
How do I monitor container health and agent performance?
Since containers are just servers the same logging infrastructure you use for the backend will work for containers.
​
How long can an agent session run before timing out?
An agent session will not timeout, but consider setting a ‘maxTurns’ property to prevent Claude from getting stuck in a loop.
​
Next Steps
Secure Deployment
- Network controls, credential management, and isolation hardening
TypeScript SDK - Sandbox Settings
- Configure sandbox programmatically
Sessions Guide
- Learn about session management
Permissions
- Configure tool permissions
Cost Tracking
- Monitor API usage
MCP Integration
- Extend with custom tools
Was this page helpful?
Yes
No
Todo Lists
Securely deploying AI agents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/hosting" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Communications kit</title>
  <link>https://code.claude.com/docs/en/communications-kit</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/communications-kit</guid>
  <pubDate>Sun, 13 Oct 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Communications kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin de...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Communications kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page is for administrators and engineering leads rolling Claude Code out to a team. It provides copy-ready launch announcements, a tips-and-tricks drip campaign, and one-line FAQ responses for the questions you will be asked most.
Treat everything here as draft copy, not finished copy. Rewrite each message in your organization’s voice, swap the example tasks for real bugs and modules from your own codebase, and replace the
[bracketed placeholders]
before sending. The announcements that drive adoption are the ones that read like someone at your company wrote them.
​
Launch communications
One announcement in two formats, plus two optional variants. Pick whichever fits your rollout and rewrite it from there.
​
Before you send
Work through this checklist before the announcement goes out. Each item closes a gap that otherwise turns into a launch-day support thread.
Item
Why it matters
#claude-code
channel created and linked in the message
Gives questions one place to land
Install command tested on at least one machine in your environment
Catches proxy or firewall issues before everyone hits them at once
Security and data-handling link ready (
Data usage
or your internal equivalent)
“Where does my code go?” will be the first reply
One concrete first task chosen, a real bug or file in your codebase
Generic examples don’t convert; “fix the flaky test in
auth_test.go
” does
A named owner for the channel for the first 48 hours
Unanswered launch-day questions kill momentum
A C-suite sponsor lined up to send or co-sign the announcement
Exec-sent launches consistently see higher first-week adoption than admin-sent ones
​
The announcement
Use this as your standard org-wide rollout message. It covers what Claude Code is, gives a two-minute install path, hands readers one concrete task to try, and answers “where does my code go?” before anyone has to ask.
Email
Slack or Teams
Subject: Claude Code is live for [Engineering / your team]
Team,
As of today you have access to Claude Code, an AI coding agent that runs in
your terminal, reads your actual codebase, and works through real tasks end
to end: debugging, refactors, tests, PRs. It is not autocomplete and it is
not a chat window. It edits files, runs your commands, and asks permission
before anything risky.
Get running in two minutes:
curl -fsSL https://claude.ai/install.sh | bash
cd <your-repo>
claude
Then run /init once. Claude reads your project and writes a CLAUDE.md with
your build commands and conventions, so you stop re-explaining the basics.
Then try one of these on the repo you are already in:
- "The test in [file] is flaky. Figure out why and fix it"
- "Walk me through how [module] handles [X]"
- "Look at my working diff and tell me what's risky before I push"
Where your code goes: Claude Code runs in your terminal and talks directly
to Anthropic's API, with no third-party servers in the loop. It asks before
editing files or running commands. Under our Enterprise agreement, Anthropic
does not use your code or prompts to train its models.
Details: https://code.claude.com/docs/en/data-usage
https://code.claude.com/docs/en/security
Where to go with questions: #claude-code. [Owner name] is watching it
this week.
- [Name]
P.S. Prefer your editor? There is a VS Code extension and a JetBrains
plugin. Same agent, no terminal required.
🚀
*Claude Code is live for [
team
]*
AI coding agent, runs in your terminal, reads your repo, does real work:
bugs, refactors, tests, PRs. Asks before it touches anything.
`curl -fsSL https://claude.ai/install.sh | bash`
→
`cd your-repo`
→
`claude`
*First thing to try*
→ run
`/init`
, then: "the test in [
file
] is flaky,
figure out why and fix it."
🔒 Runs in your terminal, talks only to Anthropic's API. Under our
Enterprise plan your code and prompts are not used to train models.
Data usage → https://code.claude.com/docs/en/data-usage
📚 Quickstart · VS Code · Free 1-hr course
https://code.claude.com/docs/en/quickstart
https://code.claude.com/docs/en/vs-code
https://anthropic.skilljar.com/claude-code-in-action
Questions → this thread. [
Owner
] is on point.
​
Executive sponsor variant
Send this from your sponsoring executive, such as the CTO, CIO, or SVP Engineering, under their name and from their account. Launches that go out under an exec’s name consistently see higher open rates and faster first-week activation than the same message from an admin or tooling team. It signals a company priority rather than an optional experiment.
This version is deliberately stripped to one ask: install it and run it on one real task. The exec’s job is to make the ask land; the standard announcement and
#claude-code
handle the how.
Email
Slack or Teams
Subject: One thing I'd like every engineer to try this week
Team,
We have turned on Claude Code for all of engineering. It is an AI agent
that works directly in your terminal, on your actual codebase, and the
early results from teams already using it are strong enough that I want
everyone on it this week.
I am asking for ten minutes:
curl -fsSL https://claude.ai/install.sh | bash
cd <your-repo>
claude
Then hand it one real task: the bug you have been putting off, or "walk me
through how [module] works."
That is the whole ask. [Owner name] and team are in #claude-code for
anything you hit along the way.
- [Exec Name]
[Title]
📣
*From [Exec Name]: one thing to try this week*
We have turned on
*Claude Code*
for all of engineering. Early results are
strong enough that I am asking everyone to give it ten minutes on real
work this week.
`curl -fsSL https://claude.ai/install.sh | bash`
→
`cd your-repo`
→
`claude`
→ hand it one real task.
That's it. Questions → #claude-code.
​
Pilot group variant
Use for a phased rollout. Send to the pilot cohort only.
Subject: You're in the Claude Code pilot
[Name / team],
You are in the first wave of Claude Code at [company]. We picked this group
because you will put it on real problems and tell us the truth about it.
The ask: use it on at least one real task this week, then drop a note in
#claude-code-pilot covering what worked, what was annoying, and what
surprised you. That feedback decides how we roll it out to everyone else.
[Continue with "Get running in two minutes" from the standard announcement]
One extra thing for pilots: on your first multi-file change, press Shift+Tab
until you see "plan". Claude will lay out exactly what it intends to do
before it touches a file. It is the fastest way to calibrate how much to
trust it.
​
Champion recruitment DM
After launch, DM the two or three people who are most active in
#claude-code
.
Hey [name], your #claude-code posts are doing more for adoption than my
announcement did. A couple of people told me your [thread / screenshot]
was why they actually tried it.
Want to make that semi-official? Low lift: mostly keep posting what you
are posting, plus first crack at new features and a direct line to the
Anthropic team. I can share a short playbook if you're in.
​
Tips and tricks campaign
Ready-to-paste Slack or Teams messages designed to drive feature activation after launch. Each follows the same pattern: a hook, the payoff, a “try it now” prompt, and a docs link. Drip them one or two a week in
#claude-code
, or pick the handful that match your team’s gaps. They stand alone with no required order.
Copy the message body from each block directly into Slack or Teams. Replace
[bracketed placeholders]
before sending.
​
Get started
Choosing the right model
🎯
*Tip: Match the model to the moment*
Using Opus to fix a typo burns compute. Using Haiku for a 12-file refactor
is asking for a re-do.
Claude Code runs on the same models as the Claude app, and you can switch
mid-session.
*Sonnet*
is the workhorse default for everyday feature work,
bugs, tests, and reviews. Reach for
*Opus*
on large refactors, gnarly
debugging, or anything high-stakes. Drop to
*Haiku*
for quick questions,
formatting, and mechanical edits where speed wins.
*Try it now:*
type
`/model`
and pick Sonnet if you haven't already. It is
the right default for most tasks.
📖 Model configuration → https://code.claude.com/docs/en/model-config
Model
Best for
Opus
Large-scale refactors, complex debugging, architecture decisions, high-stakes changes
Sonnet
Everyday feature work, bug fixes, tests, documentation, code review. Recommended default.
Haiku
Quick questions, formatting, mechanical edits, rapid iteration
Quick wins to try first
🚀
*Tip: Three things to try in your first 10 minutes*
Installed Claude Code but not sure what to actually ask it? Start with the
stuff that has been bugging you all week.
-
Fix something annoying: "the test in [
file
] is flaky, figure out why"
-
Get oriented in code you didn't write: "walk me through how [
module
] works"
-
Sanity-check before you push: "look at my working diff and tell me what
looks risky"
None of these need setup. Just
`cd`
into your repo and run
`claude`
.
*Try it now:*
pick the bug you have been avoiding and paste the error
message in.
📖 Quickstart → https://code.claude.com/docs/en/quickstart
​
Project memory
/init
and CLAUDE.md
📁
*Tip: Stop re-explaining your repo every session*
Telling Claude "we use pnpm, not npm" for the fifth time? There is a
one-time fix.
Run
`/init`
once per repo. Claude reads your project structure and writes a
CLAUDE.md file with your build commands, architecture, and conventions.
Every future session in that repo starts from this file automatically. Keep
it under two screens. It is a cheat sheet, not documentation.
*Try it now:*
open your main repo, run
`claude`
, type
`/init`
. Thirty
seconds, pays off every session after.
📖 CLAUDE.md and project memory → https://code.claude.com/docs/en/memory
@-references
📎
*Tip: Stop pasting file contents into the chat*
Copying 200 lines of a component into your prompt so Claude can "see" it?
You don't have to.
Type
`@`
then a file path. Claude pulls the file directly into context.
Works for whole directories too.
>
the styles in @src/components/Button.tsx look off, check against
>
@docs/design-system.md
*Try it now:*
type
`@`
then Tab. Autocomplete shows you every file in reach.
📖 Referencing files → https://code.claude.com/docs/en/common-workflows
​
Control and safety
Permission modes
🛡️
*Tip: One keystroke between "look but don't touch" and "just do it"*
Sometimes you want Claude to ask before every edit. Sometimes you just want
it to ship. You shouldn't have to pick one forever.
*Shift+Tab*
cycles through how much leash Claude gets:
*default*
asks before
risky stuff,
*acceptEdits*
lets file edits and common filesystem commands
flow through while still checking before other shell commands, and
*plan*
proposes changes for your approval before anything is touched. Plan mode is
the trust-builder, so start there for anything touching multiple files.
*Try it now:*
on your next refactor, hit Shift+Tab until you see "plan",
then describe the change. You'll get a full proposal before a single file
moves.
📖 Permission modes → https://code.claude.com/docs/en/permissions
Checkpointing and
/rewind
⏪
*Tip: There is an undo button for the whole conversation*
Claude went down the wrong path three turns ago and now you're untangling
it? You don't have to fix forward.
`/rewind`
rolls back to an earlier point in the conversation, including the
file changes Claude made along the way. Checkpointing is automatic; you
don't set anything up.
*Try it now:*
press
*Esc*
twice to open the rewind menu, or type
`/rewind`
.
Pick the point before things went sideways.
📖 Checkpointing → https://code.claude.com/docs/en/checkpointing
​
Connect your tools
MCP connectors
🔌
*Tip: Let Claude read your issue tracker so you don't have to paste tickets*
Copy-pasting Jira tickets into the terminal feels like a step backward.
It is.
One config file (
`.mcp.json`
at your project root) wires Claude into GitHub,
Jira, Linear, or whatever tracker you use. Then "what's the top-priority
issue assigned to me?" and "go ahead and fix it" happen in the same
conversation.
*Try it now:*
ask Claude "set up an MCP connector for [
GitHub/Jira/Linear
]
in this repo". It will write the config for you.
📖 MCP connectors → https://code.claude.com/docs/en/mcp
​
Automate your workflows
Skills
⚡
*Tip: Turn that prompt you keep retyping into a command*
Typed "summarize what I worked on today from git log, format it for standup"
three times this week? That's a slash command waiting to happen.
A SKILL.md file in
`.claude/skills/<name>/`
becomes a reusable prompt; type
`/name`
to run it. Make one the second time you type a multi-step prompt
you've typed before. Easiest path: ask Claude to make it for you.
*Try it now:*
type "make me a /standup skill that summarizes what I worked
on today from git log", then run
`/standup`
tomorrow morning.
📖 Skills → https://code.claude.com/docs/en/skills
Hooks
🔔
*Tip: Get pinged when your refactor finishes*
Sitting at your desk watching Claude work through a long task? You've got
better things to do for those eight minutes.
Hooks are shell commands that fire on Claude Code events. A Stop hook that
sends a desktop notification means you can kick off a long refactor, walk
away, and get pinged the moment it's done.
*Try it now:*
ask Claude "add a Stop hook that sends a desktop notification
when you finish". It will write the script and wire it up.
📖 Hooks guide → https://code.claude.com/docs/en/hooks-guide
​
Day-to-day development
Screenshots and images
📸
*Tip: Stop describing the error dialog. Just show it.*
Typing out "there's a red box that says something about a null reference
and it's pointing at line 47-ish"? Screenshot it.
Drag a screenshot straight into the terminal and Claude sees it: error
dialogs, UI mockups, whiteboard photos, Figma exports.
*Ctrl+V*
pastes from
clipboard (use Ctrl+V on macOS too, not Cmd+V).
*Try it now:*
next time something visual breaks, screenshot it and paste it
right into the prompt. Then just type "what's wrong here?"
📖 Working with images → https://code.claude.com/docs/en/common-workflows
Git workflows
🌿
*Tip: Hand off the whole git ceremony*
The fix took 5 minutes. The commit message, branch, and PR description
took 15. That ratio is wrong.
Claude handles the full git flow: commits with conventional messages,
branches, PRs with proper summaries. One ask: "fix the off-by-one, commit
with a conventional commit message, and open a PR." Reviewing someone
else's work? Paste the PR URL and ask Claude to walk you through the diff.
*Try it now:*
after your next fix, instead of switching to your git client,
just type "commit this with a good message and open a PR".
📖 Creating pull requests → https://code.claude.com/docs/en/common-workflows
​
Share and scale
Plugins
📦
*Tip: Someone probably already built that skill*
About to spend an hour building a
`/deploy`
command? Check if it
already exists.
Skills get bundled and shared as plugins.
`/plugin`
browses what's
available and installs in one step. Five minutes of browsing can save an
hour of building.
*Try it now:*
type
`/plugin`
and scroll through. You'll find at least one
thing you didn't know you wanted.
📖 Plugins → https://code.claude.com/docs/en/plugins
​
Security and admin
Security architecture
🔐
*Tip: The answer to "is this safe?" for the next time you're asked*
Someone on your team is going to ask "wait, where does my code go?"
Here's the short version you can paste.
Permission-first by design. Every file edit, shell command, and external
call is gated by your approval. The CLI runs in your terminal and talks
directly to Anthropic's API, with no third-party servers, and supports
optional OS-level sandboxing for shell commands. Under our Enterprise plan,
Anthropic does not use your code or prompts to train its models.
*Try it now:*
save these two links for the next time the question comes up.
They answer most security-review questions.
📖 https://code.claude.com/docs/en/security
📖 https://code.claude.com/docs/en/data-usage
Best practices
✅
*Tip: The 4 habits that separate "tried it once" from "use it daily"*
Most people who bounce off Claude Code skipped one of these. Most people
who stick did all four in week one.
-
Start in plan mode for anything touching multiple files
-
Run /init early; context compounds
-
Review diffs before committing; Claude can be confidently wrong
-
Verify changes that touch critical paths; treat it like a sharp
junior, not an oracle
*Try it now:*
if you've only done one or two of these, pick the one you're
missing and do it on your next task. Post what changed in #claude-code.
📖 Best practices → https://code.claude.com/docs/en/best-practices
​
Quick reference
​
FAQ responses
One-line replies for the questions you will be asked most.
Question
Response
”Does it work in VS Code?”
Yes. There is a VS Code extension and a JetBrains plugin with the same features, embedded in your editor.
VS Code →
“Do I have to configure anything first?”
No. Install, then run
claude
in any repo. Run
/init
once and you’re set.
Quickstart →
“Where does my code go?”
The CLI runs in your terminal and sends context to Anthropic’s API for inference, with no third-party servers. Under your Enterprise plan, your code and prompts are not used to train models.
Data usage →
“Can it see my whole repo?”
It reads what you give it access to. File reads inside your working directory don’t prompt; permission prompts gate edits, shell commands, and anything outside that directory.
Permissions →
“How is this different from Copilot?”
Copilot autocompletes lines. Claude Code is an agent that reads files, runs commands, and makes multi-file edits.
Overview →
“What should I try first?”
A bug you’ve been putting off because it’s tedious. “The test in [file] is flaky, figure out why.”
Quickstart →
​
Prompt templates
Share these starter prompts with engineers who have installed but aren’t sure what to ask. Each one is phrased the way it would be typed into a real session; replace the bracketed pieces with files from your own repo.
Task
Prompt
Fix a bug
”the tests in [file] are failing, figure out why and fix it”
Understand code
”walk me through how [module] works, then tell me where the entry point is”
Safe refactor
”refactor [module] to [goal], use plan mode so I can review first”
Write tests
”write tests for [file] that cover the edge cases around [scenario]“
Review before commit
”look at my working diff and tell me what looks risky”
Open a PR
”fix [issue], write a conventional commit, and open a PR with a summary”
Make a skill
”make me a /ship skill that runs tests and lint before commit”
Debug a stack trace
”here’s the stack trace, find the root cause, don’t just paper over it”
Claude Code ships frequently. Verify version-specific details against the
documentation home page
before distributing internally.
Was this page helpful?
Yes
No
Zero data retention
Champion kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/communications-kit" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Communications kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin de...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Communications kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page is for administrators and engineering leads rolling Claude Code out to a team. It provides copy-ready launch announcements, a tips-and-tricks drip campaign, and one-line FAQ responses for the questions you will be asked most.
Treat everything here as draft copy, not finished copy. Rewrite each message in your organization’s voice, swap the example tasks for real bugs and modules from your own codebase, and replace the
[bracketed placeholders]
before sending. The announcements that drive adoption are the ones that read like someone at your company wrote them.
​
Launch communications
One announcement in two formats, plus two optional variants. Pick whichever fits your rollout and rewrite it from there.
​
Before you send
Work through this checklist before the announcement goes out. Each item closes a gap that otherwise turns into a launch-day support thread.
Item
Why it matters
#claude-code
channel created and linked in the message
Gives questions one place to land
Install command tested on at least one machine in your environment
Catches proxy or firewall issues before everyone hits them at once
Security and data-handling link ready (
Data usage
or your internal equivalent)
“Where does my code go?” will be the first reply
One concrete first task chosen, a real bug or file in your codebase
Generic examples don’t convert; “fix the flaky test in
auth_test.go
” does
A named owner for the channel for the first 48 hours
Unanswered launch-day questions kill momentum
A C-suite sponsor lined up to send or co-sign the announcement
Exec-sent launches consistently see higher first-week adoption than admin-sent ones
​
The announcement
Use this as your standard org-wide rollout message. It covers what Claude Code is, gives a two-minute install path, hands readers one concrete task to try, and answers “where does my code go?” before anyone has to ask.
Email
Slack or Teams
Subject: Claude Code is live for [Engineering / your team]
Team,
As of today you have access to Claude Code, an AI coding agent that runs in
your terminal, reads your actual codebase, and works through real tasks end
to end: debugging, refactors, tests, PRs. It is not autocomplete and it is
not a chat window. It edits files, runs your commands, and asks permission
before anything risky.
Get running in two minutes:
curl -fsSL https://claude.ai/install.sh | bash
cd <your-repo>
claude
Then run /init once. Claude reads your project and writes a CLAUDE.md with
your build commands and conventions, so you stop re-explaining the basics.
Then try one of these on the repo you are already in:
- "The test in [file] is flaky. Figure out why and fix it"
- "Walk me through how [module] handles [X]"
- "Look at my working diff and tell me what's risky before I push"
Where your code goes: Claude Code runs in your terminal and talks directly
to Anthropic's API, with no third-party servers in the loop. It asks before
editing files or running commands. Under our Enterprise agreement, Anthropic
does not use your code or prompts to train its models.
Details: https://code.claude.com/docs/en/data-usage
https://code.claude.com/docs/en/security
Where to go with questions: #claude-code. [Owner name] is watching it
this week.
- [Name]
P.S. Prefer your editor? There is a VS Code extension and a JetBrains
plugin. Same agent, no terminal required.
🚀
*Claude Code is live for [
team
]*
AI coding agent, runs in your terminal, reads your repo, does real work:
bugs, refactors, tests, PRs. Asks before it touches anything.
`curl -fsSL https://claude.ai/install.sh | bash`
→
`cd your-repo`
→
`claude`
*First thing to try*
→ run
`/init`
, then: "the test in [
file
] is flaky,
figure out why and fix it."
🔒 Runs in your terminal, talks only to Anthropic's API. Under our
Enterprise plan your code and prompts are not used to train models.
Data usage → https://code.claude.com/docs/en/data-usage
📚 Quickstart · VS Code · Free 1-hr course
https://code.claude.com/docs/en/quickstart
https://code.claude.com/docs/en/vs-code
https://anthropic.skilljar.com/claude-code-in-action
Questions → this thread. [
Owner
] is on point.
​
Executive sponsor variant
Send this from your sponsoring executive, such as the CTO, CIO, or SVP Engineering, under their name and from their account. Launches that go out under an exec’s name consistently see higher open rates and faster first-week activation than the same message from an admin or tooling team. It signals a company priority rather than an optional experiment.
This version is deliberately stripped to one ask: install it and run it on one real task. The exec’s job is to make the ask land; the standard announcement and
#claude-code
handle the how.
Email
Slack or Teams
Subject: One thing I'd like every engineer to try this week
Team,
We have turned on Claude Code for all of engineering. It is an AI agent
that works directly in your terminal, on your actual codebase, and the
early results from teams already using it are strong enough that I want
everyone on it this week.
I am asking for ten minutes:
curl -fsSL https://claude.ai/install.sh | bash
cd <your-repo>
claude
Then hand it one real task: the bug you have been putting off, or "walk me
through how [module] works."
That is the whole ask. [Owner name] and team are in #claude-code for
anything you hit along the way.
- [Exec Name]
[Title]
📣
*From [Exec Name]: one thing to try this week*
We have turned on
*Claude Code*
for all of engineering. Early results are
strong enough that I am asking everyone to give it ten minutes on real
work this week.
`curl -fsSL https://claude.ai/install.sh | bash`
→
`cd your-repo`
→
`claude`
→ hand it one real task.
That's it. Questions → #claude-code.
​
Pilot group variant
Use for a phased rollout. Send to the pilot cohort only.
Subject: You're in the Claude Code pilot
[Name / team],
You are in the first wave of Claude Code at [company]. We picked this group
because you will put it on real problems and tell us the truth about it.
The ask: use it on at least one real task this week, then drop a note in
#claude-code-pilot covering what worked, what was annoying, and what
surprised you. That feedback decides how we roll it out to everyone else.
[Continue with "Get running in two minutes" from the standard announcement]
One extra thing for pilots: on your first multi-file change, press Shift+Tab
until you see "plan". Claude will lay out exactly what it intends to do
before it touches a file. It is the fastest way to calibrate how much to
trust it.
​
Champion recruitment DM
After launch, DM the two or three people who are most active in
#claude-code
.
Hey [name], your #claude-code posts are doing more for adoption than my
announcement did. A couple of people told me your [thread / screenshot]
was why they actually tried it.
Want to make that semi-official? Low lift: mostly keep posting what you
are posting, plus first crack at new features and a direct line to the
Anthropic team. I can share a short playbook if you're in.
​
Tips and tricks campaign
Ready-to-paste Slack or Teams messages designed to drive feature activation after launch. Each follows the same pattern: a hook, the payoff, a “try it now” prompt, and a docs link. Drip them one or two a week in
#claude-code
, or pick the handful that match your team’s gaps. They stand alone with no required order.
Copy the message body from each block directly into Slack or Teams. Replace
[bracketed placeholders]
before sending.
​
Get started
Choosing the right model
🎯
*Tip: Match the model to the moment*
Using Opus to fix a typo burns compute. Using Haiku for a 12-file refactor
is asking for a re-do.
Claude Code runs on the same models as the Claude app, and you can switch
mid-session.
*Sonnet*
is the workhorse default for everyday feature work,
bugs, tests, and reviews. Reach for
*Opus*
on large refactors, gnarly
debugging, or anything high-stakes. Drop to
*Haiku*
for quick questions,
formatting, and mechanical edits where speed wins.
*Try it now:*
type
`/model`
and pick Sonnet if you haven't already. It is
the right default for most tasks.
📖 Model configuration → https://code.claude.com/docs/en/model-config
Model
Best for
Opus
Large-scale refactors, complex debugging, architecture decisions, high-stakes changes
Sonnet
Everyday feature work, bug fixes, tests, documentation, code review. Recommended default.
Haiku
Quick questions, formatting, mechanical edits, rapid iteration
Quick wins to try first
🚀
*Tip: Three things to try in your first 10 minutes*
Installed Claude Code but not sure what to actually ask it? Start with the
stuff that has been bugging you all week.
-
Fix something annoying: "the test in [
file
] is flaky, figure out why"
-
Get oriented in code you didn't write: "walk me through how [
module
] works"
-
Sanity-check before you push: "look at my working diff and tell me what
looks risky"
None of these need setup. Just
`cd`
into your repo and run
`claude`
.
*Try it now:*
pick the bug you have been avoiding and paste the error
message in.
📖 Quickstart → https://code.claude.com/docs/en/quickstart
​
Project memory
/init
and CLAUDE.md
📁
*Tip: Stop re-explaining your repo every session*
Telling Claude "we use pnpm, not npm" for the fifth time? There is a
one-time fix.
Run
`/init`
once per repo. Claude reads your project structure and writes a
CLAUDE.md file with your build commands, architecture, and conventions.
Every future session in that repo starts from this file automatically. Keep
it under two screens. It is a cheat sheet, not documentation.
*Try it now:*
open your main repo, run
`claude`
, type
`/init`
. Thirty
seconds, pays off every session after.
📖 CLAUDE.md and project memory → https://code.claude.com/docs/en/memory
@-references
📎
*Tip: Stop pasting file contents into the chat*
Copying 200 lines of a component into your prompt so Claude can "see" it?
You don't have to.
Type
`@`
then a file path. Claude pulls the file directly into context.
Works for whole directories too.
>
the styles in @src/components/Button.tsx look off, check against
>
@docs/design-system.md
*Try it now:*
type
`@`
then Tab. Autocomplete shows you every file in reach.
📖 Referencing files → https://code.claude.com/docs/en/common-workflows
​
Control and safety
Permission modes
🛡️
*Tip: One keystroke between "look but don't touch" and "just do it"*
Sometimes you want Claude to ask before every edit. Sometimes you just want
it to ship. You shouldn't have to pick one forever.
*Shift+Tab*
cycles through how much leash Claude gets:
*default*
asks before
risky stuff,
*acceptEdits*
lets file edits and common filesystem commands
flow through while still checking before other shell commands, and
*plan*
proposes changes for your approval before anything is touched. Plan mode is
the trust-builder, so start there for anything touching multiple files.
*Try it now:*
on your next refactor, hit Shift+Tab until you see "plan",
then describe the change. You'll get a full proposal before a single file
moves.
📖 Permission modes → https://code.claude.com/docs/en/permissions
Checkpointing and
/rewind
⏪
*Tip: There is an undo button for the whole conversation*
Claude went down the wrong path three turns ago and now you're untangling
it? You don't have to fix forward.
`/rewind`
rolls back to an earlier point in the conversation, including the
file changes Claude made along the way. Checkpointing is automatic; you
don't set anything up.
*Try it now:*
press
*Esc*
twice to open the rewind menu, or type
`/rewind`
.
Pick the point before things went sideways.
📖 Checkpointing → https://code.claude.com/docs/en/checkpointing
​
Connect your tools
MCP connectors
🔌
*Tip: Let Claude read your issue tracker so you don't have to paste tickets*
Copy-pasting Jira tickets into the terminal feels like a step backward.
It is.
One config file (
`.mcp.json`
at your project root) wires Claude into GitHub,
Jira, Linear, or whatever tracker you use. Then "what's the top-priority
issue assigned to me?" and "go ahead and fix it" happen in the same
conversation.
*Try it now:*
ask Claude "set up an MCP connector for [
GitHub/Jira/Linear
]
in this repo". It will write the config for you.
📖 MCP connectors → https://code.claude.com/docs/en/mcp
​
Automate your workflows
Skills
⚡
*Tip: Turn that prompt you keep retyping into a command*
Typed "summarize what I worked on today from git log, format it for standup"
three times this week? That's a slash command waiting to happen.
A SKILL.md file in
`.claude/skills/<name>/`
becomes a reusable prompt; type
`/name`
to run it. Make one the second time you type a multi-step prompt
you've typed before. Easiest path: ask Claude to make it for you.
*Try it now:*
type "make me a /standup skill that summarizes what I worked
on today from git log", then run
`/standup`
tomorrow morning.
📖 Skills → https://code.claude.com/docs/en/skills
Hooks
🔔
*Tip: Get pinged when your refactor finishes*
Sitting at your desk watching Claude work through a long task? You've got
better things to do for those eight minutes.
Hooks are shell commands that fire on Claude Code events. A Stop hook that
sends a desktop notification means you can kick off a long refactor, walk
away, and get pinged the moment it's done.
*Try it now:*
ask Claude "add a Stop hook that sends a desktop notification
when you finish". It will write the script and wire it up.
📖 Hooks guide → https://code.claude.com/docs/en/hooks-guide
​
Day-to-day development
Screenshots and images
📸
*Tip: Stop describing the error dialog. Just show it.*
Typing out "there's a red box that says something about a null reference
and it's pointing at line 47-ish"? Screenshot it.
Drag a screenshot straight into the terminal and Claude sees it: error
dialogs, UI mockups, whiteboard photos, Figma exports.
*Ctrl+V*
pastes from
clipboard (use Ctrl+V on macOS too, not Cmd+V).
*Try it now:*
next time something visual breaks, screenshot it and paste it
right into the prompt. Then just type "what's wrong here?"
📖 Working with images → https://code.claude.com/docs/en/common-workflows
Git workflows
🌿
*Tip: Hand off the whole git ceremony*
The fix took 5 minutes. The commit message, branch, and PR description
took 15. That ratio is wrong.
Claude handles the full git flow: commits with conventional messages,
branches, PRs with proper summaries. One ask: "fix the off-by-one, commit
with a conventional commit message, and open a PR." Reviewing someone
else's work? Paste the PR URL and ask Claude to walk you through the diff.
*Try it now:*
after your next fix, instead of switching to your git client,
just type "commit this with a good message and open a PR".
📖 Creating pull requests → https://code.claude.com/docs/en/common-workflows
​
Share and scale
Plugins
📦
*Tip: Someone probably already built that skill*
About to spend an hour building a
`/deploy`
command? Check if it
already exists.
Skills get bundled and shared as plugins.
`/plugin`
browses what's
available and installs in one step. Five minutes of browsing can save an
hour of building.
*Try it now:*
type
`/plugin`
and scroll through. You'll find at least one
thing you didn't know you wanted.
📖 Plugins → https://code.claude.com/docs/en/plugins
​
Security and admin
Security architecture
🔐
*Tip: The answer to "is this safe?" for the next time you're asked*
Someone on your team is going to ask "wait, where does my code go?"
Here's the short version you can paste.
Permission-first by design. Every file edit, shell command, and external
call is gated by your approval. The CLI runs in your terminal and talks
directly to Anthropic's API, with no third-party servers, and supports
optional OS-level sandboxing for shell commands. Under our Enterprise plan,
Anthropic does not use your code or prompts to train its models.
*Try it now:*
save these two links for the next time the question comes up.
They answer most security-review questions.
📖 https://code.claude.com/docs/en/security
📖 https://code.claude.com/docs/en/data-usage
Best practices
✅
*Tip: The 4 habits that separate "tried it once" from "use it daily"*
Most people who bounce off Claude Code skipped one of these. Most people
who stick did all four in week one.
-
Start in plan mode for anything touching multiple files
-
Run /init early; context compounds
-
Review diffs before committing; Claude can be confidently wrong
-
Verify changes that touch critical paths; treat it like a sharp
junior, not an oracle
*Try it now:*
if you've only done one or two of these, pick the one you're
missing and do it on your next task. Post what changed in #claude-code.
📖 Best practices → https://code.claude.com/docs/en/best-practices
​
Quick reference
​
FAQ responses
One-line replies for the questions you will be asked most.
Question
Response
”Does it work in VS Code?”
Yes. There is a VS Code extension and a JetBrains plugin with the same features, embedded in your editor.
VS Code →
“Do I have to configure anything first?”
No. Install, then run
claude
in any repo. Run
/init
once and you’re set.
Quickstart →
“Where does my code go?”
The CLI runs in your terminal and sends context to Anthropic’s API for inference, with no third-party servers. Under your Enterprise plan, your code and prompts are not used to train models.
Data usage →
“Can it see my whole repo?”
It reads what you give it access to. File reads inside your working directory don’t prompt; permission prompts gate edits, shell commands, and anything outside that directory.
Permissions →
“How is this different from Copilot?”
Copilot autocompletes lines. Claude Code is an agent that reads files, runs commands, and makes multi-file edits.
Overview →
“What should I try first?”
A bug you’ve been putting off because it’s tedious. “The test in [file] is flaky, figure out why.”
Quickstart →
​
Prompt templates
Share these starter prompts with engineers who have installed but aren’t sure what to ask. Each one is phrased the way it would be typed into a real session; replace the bracketed pieces with files from your own repo.
Task
Prompt
Fix a bug
”the tests in [file] are failing, figure out why and fix it”
Understand code
”walk me through how [module] works, then tell me where the entry point is”
Safe refactor
”refactor [module] to [goal], use plan mode so I can review first”
Write tests
”write tests for [file] that cover the edge cases around [scenario]“
Review before commit
”look at my working diff and tell me what looks risky”
Open a PR
”fix [issue], write a conventional commit, and open a PR with a summary”
Make a skill
”make me a /ship skill that runs tests and lint before commit”
Debug a stack trace
”here’s the stack trace, find the root cause, don’t just paper over it”
Claude Code ships frequently. Verify version-specific details against the
documentation home page
before distributing internally.
Was this page helpful?
Yes
No
Zero data retention
Champion kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/communications-kit" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code overview</title>
  <link>https://code.claude.com/docs/en/overview</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/overview</guid>
  <pubDate>Fri, 11 Oct 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Claude Code overview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Compute...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Claude Code overview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an AI-powered coding assistant that helps you build features, fix bugs, and automate development tasks. It understands your entire codebase and can work across multiple files and tools to get things done.
​
Get started
Choose your environment to get started. Most surfaces require a
Claude subscription
or
Anthropic Console
account. The Terminal CLI and VS Code also support
third-party providers
.
Terminal
VS Code
Desktop app
Web
JetBrains
The full-featured CLI for working with Claude Code directly in your terminal. Edit files, run commands, and manage your entire project from the command line.
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
Then start Claude Code in any project:
cd
your-project
claude
You’ll be prompted to log in on first use. That’s it!
Continue with the Quickstart →
See
advanced setup
for installation options, manual updates, or uninstallation instructions. Visit
installation troubleshooting
if you hit issues.
The VS Code extension provides inline diffs, @-mentions, plan review, and conversation history directly in your editor.
Install for VS Code
Install for Cursor
Or search for “Claude Code” in the Extensions view (
Cmd+Shift+X
on Mac,
Ctrl+Shift+X
on Windows/Linux). After installing, open the Command Palette (
Cmd+Shift+P
/
Ctrl+Shift+P
), type “Claude Code”, and select
Open in New Tab
.
Get started with VS Code →
A standalone app for running Claude Code outside your IDE or terminal. Review diffs visually, run multiple sessions side by side, schedule recurring tasks, and kick off cloud sessions.
Download and install:
macOS
(Intel and Apple Silicon)
Windows
(x64)
Windows ARM64
After installing, launch Claude, sign in, and click the
Code
tab to start coding. A
paid subscription
is required.
Learn more about the desktop app →
Run Claude Code in your browser with no local setup. Kick off long-running tasks and check back when they’re done, work on repos you don’t have locally, or run multiple tasks in parallel. Available on desktop browsers and the Claude iOS app.
Start coding at
claude.ai/code
.
Get started on the web →
A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.
Install the
Claude Code plugin
from the JetBrains Marketplace and restart your IDE.
Get started with JetBrains →
​
What you can do
Here are some of the ways you can use Claude Code:
Automate the work you keep putting off
Claude Code handles the tedious tasks that eat up your day: writing tests for untested code, fixing lint errors across a project, resolving merge conflicts, updating dependencies, and writing release notes.
claude
"write tests for the auth module, run them, and fix any failures"
Build features and fix bugs
Describe what you want in plain language. Claude Code plans the approach, writes the code across multiple files, and verifies it works.
For bugs, paste an error message or describe the symptom. Claude Code traces the issue through your codebase, identifies the root cause, and implements a fix. See
common workflows
for more examples.
Create commits and pull requests
Claude Code works directly with git. It stages changes, writes commit messages, creates branches, and opens pull requests.
claude
"commit my changes with a descriptive message"
In CI, you can automate code review and issue triage with
GitHub Actions
or
GitLab CI/CD
.
Connect your tools with MCP
The
Model Context Protocol (MCP)
is an open standard for connecting AI tools to external data sources. With MCP, Claude Code can read your design docs in Google Drive, update tickets in Jira, pull data from Slack, or use your own custom tooling.
Customize with instructions, skills, and hooks
CLAUDE.md
is a markdown file you add to your project root that Claude Code reads at the start of every session. Use it to set coding standards, architecture decisions, preferred libraries, and review checklists. Claude also builds
auto memory
as it works, saving learnings like build commands and debugging insights across sessions without you writing anything.
Create
skills
to package repeatable workflows your team can share, like
/review-pr
or
/deploy-staging
.
Hooks
let you run shell commands before or after Claude Code actions, like auto-formatting after every file edit or running lint before a commit.
Run agent teams and build custom agents
Spawn
multiple Claude Code agents
that work on different parts of a task simultaneously. A lead agent coordinates the work, assigns subtasks, and merges results.
To run several full sessions in parallel and watch them from one screen, use
background agents
. For fully custom workflows, the
Agent SDK
lets you build your own agents powered by Claude Code’s tools and capabilities, with full control over orchestration, tool access, and permissions.
Pipe, script, and automate with the CLI
Claude Code is composable and follows the Unix philosophy. Pipe logs into it, run it in CI, or chain it with other tools:
# Analyze recent log output
tail
-200
app.log
|
claude
-p
"Slack me if you see any anomalies"
# Automate translations in CI
claude
-p
"translate new strings into French and raise a PR for review"
# Bulk operations across files
git
diff
main
--name-only
|
claude
-p
"review these changed files for security issues"
See the
CLI reference
for the full set of commands and flags.
Schedule recurring tasks
Run Claude on a schedule to automate work that repeats: morning PR reviews, overnight CI failure analysis, weekly dependency audits, or syncing docs after PRs merge.
Routines
run on Anthropic-managed infrastructure, so they keep running even when your computer is off. They can also trigger on API calls or GitHub events. Create them from the web, the Desktop app, or by running
/schedule
in the CLI.
Desktop scheduled tasks
run on your machine, with direct access to your local files and tools
/loop
repeats a prompt within a CLI session for quick polling
Work from anywhere
Sessions aren’t tied to a single surface. Move work between environments as your context changes:
Step away from your desk and keep working from your phone or any browser with
Remote Control
Message
Dispatch
a task from your phone and open the Desktop session it creates
Kick off a long-running task on the
web
or
iOS app
, then pull it into your terminal with
claude --teleport
Hand off a terminal session to the
Desktop app
with
/desktop
for visual diff review
Route tasks from team chat: mention
@Claude
in
Slack
with a bug report and get a pull request back
​
Use Claude Code everywhere
Each surface connects to the same underlying Claude Code engine, so your CLAUDE.md files, settings, and MCP servers work across all of them.
Beyond the
Terminal
,
VS Code
,
JetBrains
,
Desktop
, and
Web
environments above, Claude Code integrates with CI/CD, chat, and browser workflows:
I want to…
Best option
Continue a local session from my phone or another device
Remote Control
Push events from Telegram, Discord, iMessage, or my own webhooks into a session
Channels
Start a task locally, continue on mobile
Web
or
Claude iOS app
Run Claude on a recurring schedule
Routines
or
Desktop scheduled tasks
Automate PR reviews and issue triage
GitHub Actions
or
GitLab CI/CD
Get automatic code review on every PR
GitHub Code Review
Route bug reports from Slack to pull requests
Slack
Debug live web applications
Chrome
Build custom agents for your own workflows
Agent SDK
​
Next steps
Once you’ve installed Claude Code, these guides help you go deeper.
Quickstart
: walk through your first real task, from exploring a codebase to committing a fix
Store instructions and memories
: give Claude persistent instructions with CLAUDE.md files and auto memory
Common workflows
and
best practices
: patterns for getting the most out of Claude Code
Settings
: customize Claude Code for your workflow
Troubleshooting
: solutions for common issues
code.claude.com
: demos, pricing, and product details
Was this page helpful?
Yes
No
Quickstart
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Claude Code overview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Compute...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Claude Code overview
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an AI-powered coding assistant that helps you build features, fix bugs, and automate development tasks. It understands your entire codebase and can work across multiple files and tools to get things done.
​
Get started
Choose your environment to get started. Most surfaces require a
Claude subscription
or
Anthropic Console
account. The Terminal CLI and VS Code also support
third-party providers
.
Terminal
VS Code
Desktop app
Web
JetBrains
The full-featured CLI for working with Claude Code directly in your terminal. Edit files, run commands, and manage your entire project from the command line.
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
Then start Claude Code in any project:
cd
your-project
claude
You’ll be prompted to log in on first use. That’s it!
Continue with the Quickstart →
See
advanced setup
for installation options, manual updates, or uninstallation instructions. Visit
installation troubleshooting
if you hit issues.
The VS Code extension provides inline diffs, @-mentions, plan review, and conversation history directly in your editor.
Install for VS Code
Install for Cursor
Or search for “Claude Code” in the Extensions view (
Cmd+Shift+X
on Mac,
Ctrl+Shift+X
on Windows/Linux). After installing, open the Command Palette (
Cmd+Shift+P
/
Ctrl+Shift+P
), type “Claude Code”, and select
Open in New Tab
.
Get started with VS Code →
A standalone app for running Claude Code outside your IDE or terminal. Review diffs visually, run multiple sessions side by side, schedule recurring tasks, and kick off cloud sessions.
Download and install:
macOS
(Intel and Apple Silicon)
Windows
(x64)
Windows ARM64
After installing, launch Claude, sign in, and click the
Code
tab to start coding. A
paid subscription
is required.
Learn more about the desktop app →
Run Claude Code in your browser with no local setup. Kick off long-running tasks and check back when they’re done, work on repos you don’t have locally, or run multiple tasks in parallel. Available on desktop browsers and the Claude iOS app.
Start coding at
claude.ai/code
.
Get started on the web →
A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.
Install the
Claude Code plugin
from the JetBrains Marketplace and restart your IDE.
Get started with JetBrains →
​
What you can do
Here are some of the ways you can use Claude Code:
Automate the work you keep putting off
Claude Code handles the tedious tasks that eat up your day: writing tests for untested code, fixing lint errors across a project, resolving merge conflicts, updating dependencies, and writing release notes.
claude
"write tests for the auth module, run them, and fix any failures"
Build features and fix bugs
Describe what you want in plain language. Claude Code plans the approach, writes the code across multiple files, and verifies it works.
For bugs, paste an error message or describe the symptom. Claude Code traces the issue through your codebase, identifies the root cause, and implements a fix. See
common workflows
for more examples.
Create commits and pull requests
Claude Code works directly with git. It stages changes, writes commit messages, creates branches, and opens pull requests.
claude
"commit my changes with a descriptive message"
In CI, you can automate code review and issue triage with
GitHub Actions
or
GitLab CI/CD
.
Connect your tools with MCP
The
Model Context Protocol (MCP)
is an open standard for connecting AI tools to external data sources. With MCP, Claude Code can read your design docs in Google Drive, update tickets in Jira, pull data from Slack, or use your own custom tooling.
Customize with instructions, skills, and hooks
CLAUDE.md
is a markdown file you add to your project root that Claude Code reads at the start of every session. Use it to set coding standards, architecture decisions, preferred libraries, and review checklists. Claude also builds
auto memory
as it works, saving learnings like build commands and debugging insights across sessions without you writing anything.
Create
skills
to package repeatable workflows your team can share, like
/review-pr
or
/deploy-staging
.
Hooks
let you run shell commands before or after Claude Code actions, like auto-formatting after every file edit or running lint before a commit.
Run agent teams and build custom agents
Spawn
multiple Claude Code agents
that work on different parts of a task simultaneously. A lead agent coordinates the work, assigns subtasks, and merges results.
To run several full sessions in parallel and watch them from one screen, use
background agents
. For fully custom workflows, the
Agent SDK
lets you build your own agents powered by Claude Code’s tools and capabilities, with full control over orchestration, tool access, and permissions.
Pipe, script, and automate with the CLI
Claude Code is composable and follows the Unix philosophy. Pipe logs into it, run it in CI, or chain it with other tools:
# Analyze recent log output
tail
-200
app.log
|
claude
-p
"Slack me if you see any anomalies"
# Automate translations in CI
claude
-p
"translate new strings into French and raise a PR for review"
# Bulk operations across files
git
diff
main
--name-only
|
claude
-p
"review these changed files for security issues"
See the
CLI reference
for the full set of commands and flags.
Schedule recurring tasks
Run Claude on a schedule to automate work that repeats: morning PR reviews, overnight CI failure analysis, weekly dependency audits, or syncing docs after PRs merge.
Routines
run on Anthropic-managed infrastructure, so they keep running even when your computer is off. They can also trigger on API calls or GitHub events. Create them from the web, the Desktop app, or by running
/schedule
in the CLI.
Desktop scheduled tasks
run on your machine, with direct access to your local files and tools
/loop
repeats a prompt within a CLI session for quick polling
Work from anywhere
Sessions aren’t tied to a single surface. Move work between environments as your context changes:
Step away from your desk and keep working from your phone or any browser with
Remote Control
Message
Dispatch
a task from your phone and open the Desktop session it creates
Kick off a long-running task on the
web
or
iOS app
, then pull it into your terminal with
claude --teleport
Hand off a terminal session to the
Desktop app
with
/desktop
for visual diff review
Route tasks from team chat: mention
@Claude
in
Slack
with a bug report and get a pull request back
​
Use Claude Code everywhere
Each surface connects to the same underlying Claude Code engine, so your CLAUDE.md files, settings, and MCP servers work across all of them.
Beyond the
Terminal
,
VS Code
,
JetBrains
,
Desktop
, and
Web
environments above, Claude Code integrates with CI/CD, chat, and browser workflows:
I want to…
Best option
Continue a local session from my phone or another device
Remote Control
Push events from Telegram, Discord, iMessage, or my own webhooks into a session
Channels
Start a task locally, continue on mobile
Web
or
Claude iOS app
Run Claude on a recurring schedule
Routines
or
Desktop scheduled tasks
Automate PR reviews and issue triage
GitHub Actions
or
GitLab CI/CD
Get automatic code review on every PR
GitHub Code Review
Route bug reports from Slack to pull requests
Slack
Debug live web applications
Chrome
Build custom agents for your own workflows
Agent SDK
​
Next steps
Once you’ve installed Claude Code, these guides help you go deeper.
Quickstart
: walk through your first real task, from exploring a codebase to committing a fix
Store instructions and memories
: give Claude persistent instructions with CLAUDE.md files and auto memory
Common workflows
and
best practices
: patterns for getting the most out of Claude Code
Settings
: customize Claude Code for your workflow
Troubleshooting
: solutions for common issues
code.claude.com
: demos, pricing, and product details
Was this page helpful?
Yes
No
Quickstart
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Get structured output from agents</title>
  <link>https://code.claude.com/docs/en/agent-sdk/structured-outputs</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/structured-outputs</guid>
  <pubDate>Wed, 09 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Get structured output from agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Get structured output from agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Structured outputs let you define the exact shape of data you want back from an agent. The agent can use any tools it needs to complete the task, and you still get validated JSON matching your schema at the end. Define a
JSON Schema
for the structure you need, and the SDK validates the output against it, re-prompting on mismatch. If validation does not succeed within the retry limit, the result is an error instead of structured data; see
Error handling
.
For full type safety, use
Zod
(TypeScript) or
Pydantic
(Python) to define your schema and get strongly-typed objects back.
​
Why structured outputs?
Agents return free-form text by default, which works for chat but not when you need to use the output programmatically. Structured outputs give you typed data you can pass directly to your application logic, database, or UI components.
Consider a recipe app where an agent searches the web and brings back recipes. Without structured outputs, you get free-form text that you’d need to parse yourself. With structured outputs, you define the shape you want and get typed data you can use directly in your app.
Without structured outputs
Here's a classic chocolate chip cookie recipe!
**Chocolate Chip Cookies**
Prep time: 15 minutes | Cook time: 10 minutes
Ingredients:
- 2 1/4 cups all-purpose flour
- 1 cup butter, softened
...
To use this in your app, you’d need to parse out the title, convert “15 minutes” to a number, separate ingredients from instructions, and handle inconsistent formatting across responses.
With structured outputs
{
"name"
:
"Chocolate Chip Cookies"
,
"prep_time_minutes"
:
15
,
"cook_time_minutes"
:
10
,
"ingredients"
: [
{
"item"
:
"all-purpose flour"
,
"amount"
:
2.25
,
"unit"
:
"cups"
},
{
"item"
:
"butter, softened"
,
"amount"
:
1
,
"unit"
:
"cup"
}
// ...
],
"steps"
: [
"Preheat oven to 375°F"
,
"Cream butter and sugar"
/* ... */
]
}
Typed data you can use directly in your UI.
​
Quick start
To use structured outputs, define a
JSON Schema
describing the shape of data you want, then pass it to
query()
via the
outputFormat
option (TypeScript) or
output_format
option (Python). When the agent finishes, the result message includes a
structured_output
field with validated data matching your schema.
The example below asks the agent to research Anthropic and return the company name, year founded, and headquarters as structured output.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define the shape of data you want back
const
schema
=
{
type:
"object"
,
properties:
{
company_name:
{
type:
"string"
},
founded_year:
{
type:
"number"
},
headquarters:
{
type:
"string"
}
},
required:
[
"company_name"
]
};
for
await
(
const
message
of
query
({
prompt:
"Research Anthropic and provide key company information"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
schema
}
}
})) {
// The result message contains structured_output with validated data
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
console
.
log
(
message
.
structured_output
);
// { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }
}
}
​
Type-safe schemas with Zod and Pydantic
Instead of writing JSON Schema by hand, you can use
Zod
(TypeScript) or
Pydantic
(Python) to define your schema. These libraries generate the JSON Schema for you and let you parse the response into a fully-typed object you can use throughout your codebase with autocomplete and type checking.
The example below defines a schema for a feature implementation plan with a summary, list of steps (each with complexity level), and potential risks. The agent plans the feature and returns a typed
FeaturePlan
object. You can then access properties like
plan.summary
and iterate over
plan.steps
with full type safety.
TypeScript
Python
import
{
z
}
from
"zod"
;
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define schema with Zod
const
FeaturePlan
=
z
.
object
({
feature_name:
z
.
string
(),
summary:
z
.
string
(),
steps:
z
.
array
(
z
.
object
({
step_number:
z
.
number
(),
description:
z
.
string
(),
estimated_complexity:
z
.
enum
([
"low"
,
"medium"
,
"high"
])
})
),
risks:
z
.
array
(
z
.
string
())
});
type
FeaturePlan
=
z
.
infer
<
typeof
FeaturePlan
>;
// Convert to JSON Schema
const
schema
=
z
.
toJSONSchema
(
FeaturePlan
);
// Use in query
for
await
(
const
message
of
query
({
prompt:
"Plan how to add dark mode support to a React app. Break it into implementation steps."
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
schema
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
// Validate and get fully typed result
const
parsed
=
FeaturePlan
.
safeParse
(
message
.
structured_output
);
if
(
parsed
.
success
) {
const
plan
:
FeaturePlan
=
parsed
.
data
;
console
.
log
(
`Feature:
${
plan
.
feature_name
}
`
);
console
.
log
(
`Summary:
${
plan
.
summary
}
`
);
plan
.
steps
.
forEach
((
step
)
=>
{
console
.
log
(
`
${
step
.
step_number
}
. [
${
step
.
estimated_complexity
}
]
${
step
.
description
}
`
);
});
}
}
}
Benefits:
Full type inference (TypeScript) and type hints (Python)
Runtime validation with
safeParse()
or
model_validate()
Better error messages
Composable, reusable schemas
​
Output format configuration
The
outputFormat
(TypeScript) or
output_format
(Python) option accepts an object with:
type
: Set to
"json_schema"
for structured outputs
schema
: A
JSON Schema
object defining your output structure. You can generate this from a Zod schema with
z.toJSONSchema()
or a Pydantic model with
.model_json_schema()
The SDK supports standard JSON Schema features including all basic types (object, array, string, number, boolean, null),
enum
,
const
,
required
, nested objects, and
$ref
definitions. For the full list of supported features and limitations, see
JSON Schema limitations
.
​
Example: TODO tracking agent
This example demonstrates how structured outputs work with multi-step tool use. The agent needs to find TODO comments in the codebase, then look up git blame information for each one. It autonomously decides which tools to use (Grep to search, Bash to run git commands) and combines the results into a single structured response.
The schema includes optional fields (
author
and
date
) since git blame information might not be available for all files. The agent fills in what it can find and omits the rest.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define structure for TODO extraction
const
todoSchema
=
{
type:
"object"
,
properties:
{
todos:
{
type:
"array"
,
items:
{
type:
"object"
,
properties:
{
text:
{
type:
"string"
},
file:
{
type:
"string"
},
line:
{
type:
"number"
},
author:
{
type:
"string"
},
date:
{
type:
"string"
}
},
required:
[
"text"
,
"file"
,
"line"
]
}
},
total_count:
{
type:
"number"
}
},
required:
[
"todos"
,
"total_count"
]
};
// Agent uses Grep to find TODOs, Bash to get git blame info
for
await
(
const
message
of
query
({
prompt:
"Find all TODO comments in this codebase and identify who added them"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
todoSchema
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
const
data
=
message
.
structured_output
as
{
total_count
:
number
;
todos
:
Array
<{
file
:
string
;
line
:
number
;
text
:
string
;
author
?:
string
;
date
?:
string
}> };
console
.
log
(
`Found
${
data
.
total_count
}
TODOs`
);
data
.
todos
.
forEach
((
todo
)
=>
{
console
.
log
(
`
${
todo
.
file
}
:
${
todo
.
line
}
-
${
todo
.
text
}
`
);
if
(
todo
.
author
) {
console
.
log
(
`  Added by
${
todo
.
author
}
on
${
todo
.
date
}
`
);
}
});
}
}
​
Error handling
Structured output generation can fail when the agent cannot produce valid JSON matching your schema. This typically happens when the schema is too complex for the task, the task itself is ambiguous, or the agent hits its retry limit trying to fix validation errors.
When an error occurs, the result message has a
subtype
indicating what went wrong:
Subtype
Meaning
success
Output was generated and validated successfully
error_max_structured_output_retries
Agent couldn’t produce valid output after multiple attempts
The example below checks the
subtype
field to determine whether the output was generated successfully or if you need to handle a failure:
TypeScript
Python
for
await
(
const
msg
of
query
({
prompt:
"Extract contact info from the document"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
contactSchema
}
}
})) {
if
(
msg
.
type
===
"result"
) {
if
(
msg
.
subtype
===
"success"
&&
msg
.
structured_output
) {
// Use the validated output
console
.
log
(
msg
.
structured_output
);
}
else
if
(
msg
.
subtype
===
"error_max_structured_output_retries"
) {
// Handle the failure - retry with simpler prompt, fall back to unstructured, etc.
console
.
error
(
"Could not produce valid output"
);
}
}
}
Tips for avoiding errors:
Keep schemas focused.
Deeply nested schemas with many required fields are harder to satisfy. Start simple and add complexity as needed.
Match schema to task.
If the task might not have all the information your schema requires, make those fields optional.
Use clear prompts.
Ambiguous prompts make it harder for the agent to know what output to produce.
​
Related resources
JSON Schema documentation
: learn JSON Schema syntax for defining complex schemas with nested objects, arrays, enums, and validation constraints
API Structured Outputs
: use structured outputs with the Claude API directly for single-turn requests without tool use
Custom tools
: give your agent custom tools to call during execution before returning structured output
Was this page helpful?
Yes
No
Stream responses in real-time
Give Claude custom tools
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/structured-outputs" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Get structured output from agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Get structured output from agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Structured outputs let you define the exact shape of data you want back from an agent. The agent can use any tools it needs to complete the task, and you still get validated JSON matching your schema at the end. Define a
JSON Schema
for the structure you need, and the SDK validates the output against it, re-prompting on mismatch. If validation does not succeed within the retry limit, the result is an error instead of structured data; see
Error handling
.
For full type safety, use
Zod
(TypeScript) or
Pydantic
(Python) to define your schema and get strongly-typed objects back.
​
Why structured outputs?
Agents return free-form text by default, which works for chat but not when you need to use the output programmatically. Structured outputs give you typed data you can pass directly to your application logic, database, or UI components.
Consider a recipe app where an agent searches the web and brings back recipes. Without structured outputs, you get free-form text that you’d need to parse yourself. With structured outputs, you define the shape you want and get typed data you can use directly in your app.
Without structured outputs
Here's a classic chocolate chip cookie recipe!
**Chocolate Chip Cookies**
Prep time: 15 minutes | Cook time: 10 minutes
Ingredients:
- 2 1/4 cups all-purpose flour
- 1 cup butter, softened
...
To use this in your app, you’d need to parse out the title, convert “15 minutes” to a number, separate ingredients from instructions, and handle inconsistent formatting across responses.
With structured outputs
{
"name"
:
"Chocolate Chip Cookies"
,
"prep_time_minutes"
:
15
,
"cook_time_minutes"
:
10
,
"ingredients"
: [
{
"item"
:
"all-purpose flour"
,
"amount"
:
2.25
,
"unit"
:
"cups"
},
{
"item"
:
"butter, softened"
,
"amount"
:
1
,
"unit"
:
"cup"
}
// ...
],
"steps"
: [
"Preheat oven to 375°F"
,
"Cream butter and sugar"
/* ... */
]
}
Typed data you can use directly in your UI.
​
Quick start
To use structured outputs, define a
JSON Schema
describing the shape of data you want, then pass it to
query()
via the
outputFormat
option (TypeScript) or
output_format
option (Python). When the agent finishes, the result message includes a
structured_output
field with validated data matching your schema.
The example below asks the agent to research Anthropic and return the company name, year founded, and headquarters as structured output.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define the shape of data you want back
const
schema
=
{
type:
"object"
,
properties:
{
company_name:
{
type:
"string"
},
founded_year:
{
type:
"number"
},
headquarters:
{
type:
"string"
}
},
required:
[
"company_name"
]
};
for
await
(
const
message
of
query
({
prompt:
"Research Anthropic and provide key company information"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
schema
}
}
})) {
// The result message contains structured_output with validated data
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
console
.
log
(
message
.
structured_output
);
// { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }
}
}
​
Type-safe schemas with Zod and Pydantic
Instead of writing JSON Schema by hand, you can use
Zod
(TypeScript) or
Pydantic
(Python) to define your schema. These libraries generate the JSON Schema for you and let you parse the response into a fully-typed object you can use throughout your codebase with autocomplete and type checking.
The example below defines a schema for a feature implementation plan with a summary, list of steps (each with complexity level), and potential risks. The agent plans the feature and returns a typed
FeaturePlan
object. You can then access properties like
plan.summary
and iterate over
plan.steps
with full type safety.
TypeScript
Python
import
{
z
}
from
"zod"
;
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define schema with Zod
const
FeaturePlan
=
z
.
object
({
feature_name:
z
.
string
(),
summary:
z
.
string
(),
steps:
z
.
array
(
z
.
object
({
step_number:
z
.
number
(),
description:
z
.
string
(),
estimated_complexity:
z
.
enum
([
"low"
,
"medium"
,
"high"
])
})
),
risks:
z
.
array
(
z
.
string
())
});
type
FeaturePlan
=
z
.
infer
<
typeof
FeaturePlan
>;
// Convert to JSON Schema
const
schema
=
z
.
toJSONSchema
(
FeaturePlan
);
// Use in query
for
await
(
const
message
of
query
({
prompt:
"Plan how to add dark mode support to a React app. Break it into implementation steps."
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
schema
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
// Validate and get fully typed result
const
parsed
=
FeaturePlan
.
safeParse
(
message
.
structured_output
);
if
(
parsed
.
success
) {
const
plan
:
FeaturePlan
=
parsed
.
data
;
console
.
log
(
`Feature:
${
plan
.
feature_name
}
`
);
console
.
log
(
`Summary:
${
plan
.
summary
}
`
);
plan
.
steps
.
forEach
((
step
)
=>
{
console
.
log
(
`
${
step
.
step_number
}
. [
${
step
.
estimated_complexity
}
]
${
step
.
description
}
`
);
});
}
}
}
Benefits:
Full type inference (TypeScript) and type hints (Python)
Runtime validation with
safeParse()
or
model_validate()
Better error messages
Composable, reusable schemas
​
Output format configuration
The
outputFormat
(TypeScript) or
output_format
(Python) option accepts an object with:
type
: Set to
"json_schema"
for structured outputs
schema
: A
JSON Schema
object defining your output structure. You can generate this from a Zod schema with
z.toJSONSchema()
or a Pydantic model with
.model_json_schema()
The SDK supports standard JSON Schema features including all basic types (object, array, string, number, boolean, null),
enum
,
const
,
required
, nested objects, and
$ref
definitions. For the full list of supported features and limitations, see
JSON Schema limitations
.
​
Example: TODO tracking agent
This example demonstrates how structured outputs work with multi-step tool use. The agent needs to find TODO comments in the codebase, then look up git blame information for each one. It autonomously decides which tools to use (Grep to search, Bash to run git commands) and combines the results into a single structured response.
The schema includes optional fields (
author
and
date
) since git blame information might not be available for all files. The agent fills in what it can find and omits the rest.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Define structure for TODO extraction
const
todoSchema
=
{
type:
"object"
,
properties:
{
todos:
{
type:
"array"
,
items:
{
type:
"object"
,
properties:
{
text:
{
type:
"string"
},
file:
{
type:
"string"
},
line:
{
type:
"number"
},
author:
{
type:
"string"
},
date:
{
type:
"string"
}
},
required:
[
"text"
,
"file"
,
"line"
]
}
},
total_count:
{
type:
"number"
}
},
required:
[
"todos"
,
"total_count"
]
};
// Agent uses Grep to find TODOs, Bash to get git blame info
for
await
(
const
message
of
query
({
prompt:
"Find all TODO comments in this codebase and identify who added them"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
todoSchema
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
&&
message
.
structured_output
) {
const
data
=
message
.
structured_output
as
{
total_count
:
number
;
todos
:
Array
<{
file
:
string
;
line
:
number
;
text
:
string
;
author
?:
string
;
date
?:
string
}> };
console
.
log
(
`Found
${
data
.
total_count
}
TODOs`
);
data
.
todos
.
forEach
((
todo
)
=>
{
console
.
log
(
`
${
todo
.
file
}
:
${
todo
.
line
}
-
${
todo
.
text
}
`
);
if
(
todo
.
author
) {
console
.
log
(
`  Added by
${
todo
.
author
}
on
${
todo
.
date
}
`
);
}
});
}
}
​
Error handling
Structured output generation can fail when the agent cannot produce valid JSON matching your schema. This typically happens when the schema is too complex for the task, the task itself is ambiguous, or the agent hits its retry limit trying to fix validation errors.
When an error occurs, the result message has a
subtype
indicating what went wrong:
Subtype
Meaning
success
Output was generated and validated successfully
error_max_structured_output_retries
Agent couldn’t produce valid output after multiple attempts
The example below checks the
subtype
field to determine whether the output was generated successfully or if you need to handle a failure:
TypeScript
Python
for
await
(
const
msg
of
query
({
prompt:
"Extract contact info from the document"
,
options:
{
outputFormat:
{
type:
"json_schema"
,
schema:
contactSchema
}
}
})) {
if
(
msg
.
type
===
"result"
) {
if
(
msg
.
subtype
===
"success"
&&
msg
.
structured_output
) {
// Use the validated output
console
.
log
(
msg
.
structured_output
);
}
else
if
(
msg
.
subtype
===
"error_max_structured_output_retries"
) {
// Handle the failure - retry with simpler prompt, fall back to unstructured, etc.
console
.
error
(
"Could not produce valid output"
);
}
}
}
Tips for avoiding errors:
Keep schemas focused.
Deeply nested schemas with many required fields are harder to satisfy. Start simple and add complexity as needed.
Match schema to task.
If the task might not have all the information your schema requires, make those fields optional.
Use clear prompts.
Ambiguous prompts make it harder for the agent to know what output to produce.
​
Related resources
JSON Schema documentation
: learn JSON Schema syntax for defining complex schemas with nested objects, arrays, enums, and validation constraints
API Structured Outputs
: use structured outputs with the Claude API directly for single-turn requests without tool use
Custom tools
: give your agent custom tools to call during execution before returning structured output
Was this page helpful?
Yes
No
Stream responses in real-time
Give Claude custom tools
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/structured-outputs" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>How Claude remembers your project</title>
  <link>https://code.claude.com/docs/en/memory</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/memory</guid>
  <pubDate>Tue, 08 Oct 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
How Claude remembers your project
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
How Claude remembers your project
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Each Claude Code session begins with a fresh context window. Two mechanisms carry knowledge across sessions:
CLAUDE.md files
: instructions you write to give Claude persistent context
Auto memory
: notes Claude writes itself based on your corrections and preferences
This page covers how to:
Write and organize CLAUDE.md files
Scope rules to specific file types
with
.claude/rules/
Configure auto memory
so Claude takes notes automatically
Troubleshoot
when instructions aren’t being followed
​
CLAUDE.md vs auto memory
Claude Code has two complementary memory systems. Both are loaded at the start of every conversation. Claude treats them as context, not enforced configuration. The more specific and concise your instructions, the more consistently Claude follows them.
CLAUDE.md files
Auto memory
Who writes it
You
Claude
What it contains
Instructions and rules
Learnings and patterns
Scope
Project, user, or org
Per repository, shared across worktrees
Loaded into
Every session
Every session (first 200 lines or 25KB)
Use for
Coding standards, workflows, project architecture
Build commands, debugging insights, preferences Claude discovers
Use CLAUDE.md files when you want to guide Claude’s behavior. Auto memory lets Claude learn from your corrections without manual effort.
Subagents can also maintain their own auto memory. See
subagent configuration
for details.
​
CLAUDE.md files
CLAUDE.md files are markdown files that give Claude persistent instructions for a project, your personal workflow, or your entire organization. You write these files in plain text; Claude reads them at the start of every session.
​
When to add to CLAUDE.md
Treat CLAUDE.md as the place you write down what you’d otherwise re-explain. Add to it when:
Claude makes the same mistake a second time
A code review catches something Claude should have known about this codebase
You type the same correction or clarification into chat that you typed last session
A new teammate would need the same context to be productive
Keep it to facts Claude should hold in every session: build commands, conventions, project layout, “always do X” rules. If an entry is a multi-step procedure or only matters for one part of the codebase, move it to a
skill
or a
path-scoped rule
instead. The
extension overview
covers when to use each mechanism.
​
Choose where to put CLAUDE.md files
CLAUDE.md files can live in several locations, each with a different scope. The table below lists them in load order, from broadest scope to most specific, so a project instruction appears in context after a user instruction.
Scope
Location
Purpose
Use case examples
Shared with
Managed policy
• macOS:
/Library/Application Support/ClaudeCode/CLAUDE.md
• Linux and WSL:
/etc/claude-code/CLAUDE.md
• Windows:
C:\Program Files\ClaudeCode\CLAUDE.md
Organization-wide instructions managed by IT/DevOps
Company coding standards, security policies, compliance requirements
All users in organization
User instructions
~/.claude/CLAUDE.md
Personal preferences for all projects
Code styling preferences, personal tooling shortcuts
Just you (all projects)
Project instructions
./CLAUDE.md
or
./.claude/CLAUDE.md
Team-shared instructions for the project
Project architecture, coding standards, common workflows
Team members via source control
Local instructions
./CLAUDE.local.md
Personal project-specific preferences; add to
.gitignore
Your sandbox URLs, preferred test data
Just you (current project)
CLAUDE.md and CLAUDE.local.md files in the directory hierarchy above the working directory are loaded in full at launch. Files in subdirectories load on demand when Claude reads files in those directories. See
How CLAUDE.md files load
for the full resolution order.
For large projects, you can break instructions into topic-specific files using
project rules
. Rules let you scope instructions to specific file types or subdirectories.
​
Set up a project CLAUDE.md
A project CLAUDE.md can be stored in either
./CLAUDE.md
or
./.claude/CLAUDE.md
. Create this file and add instructions that apply to anyone working on the project: build and test commands, coding standards, architectural decisions, naming conventions, and common workflows. These instructions are shared with your team through version control, so focus on project-level standards rather than personal preferences.
Run
/init
to generate a starting CLAUDE.md automatically. Claude analyzes your codebase and creates a file with build commands, test instructions, and project conventions it discovers. If a CLAUDE.md already exists,
/init
suggests improvements rather than overwriting it. Refine from there with instructions Claude wouldn’t discover on its own.
Set
CLAUDE_CODE_NEW_INIT=1
to enable an interactive multi-phase flow.
/init
asks which artifacts to set up: CLAUDE.md files, skills, and hooks. It then explores your codebase with a subagent, fills in gaps via follow-up questions, and presents a reviewable proposal before writing any files.
​
Write effective instructions
CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation. The
context window visualization
shows where CLAUDE.md loads relative to the rest of the startup context. Because they’re context rather than enforced configuration, how you write instructions affects how reliably Claude follows them. Specific, concise, well-structured instructions work best.
Size
: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence. If your instructions are growing large, use
path-scoped rules
so instructions load only when Claude works with matching files. You can also split content into
imports
for organization, though imported files still load and enter the context window at launch.
Structure
: use markdown headers and bullets to group related instructions. Claude scans structure the same way readers do: organized sections are easier to follow than dense paragraphs.
Specificity
: write instructions that are concrete enough to verify. For example:
“Use 2-space indentation” instead of “Format code properly”
“Run
npm test
before committing” instead of “Test your changes”
“API handlers live in
src/api/handlers/
” instead of “Keep files organized”
Consistency
: if two rules contradict each other, Claude may pick one arbitrarily. Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and
.claude/rules/
periodically to remove outdated or conflicting instructions. In monorepos, use
claudeMdExcludes
to skip CLAUDE.md files from other teams that aren’t relevant to your work.
​
Import additional files
CLAUDE.md files can import additional files using
@path/to/import
syntax. Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them.
Both relative and absolute paths are allowed. Relative paths resolve relative to the file containing the import, not the working directory. Imported files can recursively import other files, with a maximum depth of five hops.
To pull in a README, package.json, and a workflow guide, reference them with
@
syntax anywhere in your CLAUDE.md:
See @README for project overview and @package.json for available npm commands for this project.
# Additional Instructions
- git workflow @docs/git-instructions.md
For private per-project preferences that shouldn’t be checked into version control, create a
CLAUDE.local.md
at the project root. It loads alongside
CLAUDE.md
and is treated the same way. Add
CLAUDE.local.md
to your
.gitignore
so it isn’t committed; running
/init
and choosing the personal option does this for you.
If you work across multiple git worktrees of the same repository, a gitignored
CLAUDE.local.md
only exists in the worktree where you created it. To share personal instructions across worktrees, import a file from your home directory instead:
# Individual Preferences
- @~/.claude/my-project-instructions.md
The first time Claude Code encounters external imports in a project, it shows an approval dialog listing the files. If you decline, the imports stay disabled and the dialog does not appear again.
For a more structured approach to organizing instructions, see
.claude/rules/
.
​
AGENTS.md
Claude Code reads
CLAUDE.md
, not
AGENTS.md
. If your repository already uses
AGENTS.md
for other coding agents, create a
CLAUDE.md
that imports it so both tools read the same instructions without duplicating them. You can also add Claude-specific instructions below the import. Claude loads the imported file at session start, then appends the rest:
CLAUDE.md
@AGENTS.md
## Claude Code
Use plan mode for changes under
`src/billing/`
.
A symlink also works if you don’t need to add Claude-specific content:
ln
-s
AGENTS.md
CLAUDE.md
On Windows, creating a symlink requires Administrator privileges or Developer Mode, so use the
@AGENTS.md
import instead.
Running
/init
in a repo that already has an
AGENTS.md
reads it and incorporates the relevant parts into the generated
CLAUDE.md
. It also reads other tool configs like
.cursorrules
and
.windsurfrules
.
​
How CLAUDE.md files load
Claude Code reads CLAUDE.md files by walking up the directory tree from your current working directory, checking each directory along the way for
CLAUDE.md
and
CLAUDE.local.md
files. This means if you run Claude Code in
foo/bar/
, it loads instructions from
foo/bar/CLAUDE.md
,
foo/CLAUDE.md
, and any
CLAUDE.local.md
files alongside them.
All discovered files are concatenated into context rather than overriding each other. Across the directory tree, content is ordered from the filesystem root down to your working directory. For the
foo/bar/
example,
foo/CLAUDE.md
appears in context before
foo/bar/CLAUDE.md
, so instructions closer to where you launched Claude are read last. Within each directory,
CLAUDE.local.md
is appended after
CLAUDE.md
, so your personal notes are the last thing Claude reads at that level.
Claude also discovers
CLAUDE.md
and
CLAUDE.local.md
files in subdirectories under your current working directory. Instead of loading them at launch, they are included when Claude reads files in those subdirectories.
If you work in a large monorepo where other teams’ CLAUDE.md files get picked up, use
claudeMdExcludes
to skip them.
Block-level HTML comments (
<!-- maintainer notes -->
) in CLAUDE.md files are stripped before the content is injected into Claude’s context. Use them to leave notes for human maintainers without spending context tokens on them. Comments inside code blocks are preserved. When you open a CLAUDE.md file directly with the Read tool, comments remain visible.
​
Load from additional directories
The
--add-dir
flag gives Claude access to additional directories outside your main working directory. By default, CLAUDE.md files from these directories are not loaded.
To also load memory files from additional directories, set the
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
environment variable:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
=
1
claude
--add-dir
../shared-config
This loads
CLAUDE.md
,
.claude/CLAUDE.md
,
.claude/rules/*.md
, and
CLAUDE.local.md
from the additional directory.
CLAUDE.local.md
is skipped if you exclude
local
from
--setting-sources
.
​
Organize rules with
.claude/rules/
For larger projects, you can organize instructions into multiple files using the
.claude/rules/
directory. This keeps instructions modular and easier for teams to maintain. Rules can also be
scoped to specific file paths
, so they only load into context when Claude works with matching files, reducing noise and saving context space.
Rules load into context every session or when matching files are opened. For task-specific instructions that don’t need to be in context all the time, use
skills
instead, which only load when you invoke them or when Claude determines they’re relevant to your prompt.
​
Set up rules
Place markdown files in your project’s
.claude/rules/
directory. Each file should cover one topic, with a descriptive filename like
testing.md
or
api-design.md
. All
.md
files are discovered recursively, so you can organize rules into subdirectories like
frontend/
or
backend/
:
your-project/
├── .claude/
│   ├── CLAUDE.md           # Main project instructions
│   └── rules/
│       ├── code-style.md   # Code style guidelines
│       ├── testing.md      # Testing conventions
│       └── security.md     # Security requirements
Rules without
paths
frontmatter
are loaded at launch with the same priority as
.claude/CLAUDE.md
.
​
Path-specific rules
Rules can be scoped to specific files using YAML frontmatter with the
paths
field. These conditional rules only apply when Claude is working with files matching the specified patterns.
---
paths
:
-
"src/api/**/*.ts"
---
# API Development Rules
-
All API endpoints must include input validation
-
Use the standard error response format
-
Include OpenAPI documentation comments
Rules without a
paths
field are loaded unconditionally and apply to all files. Path-scoped rules trigger when Claude reads files matching the pattern, not on every tool use.
Use glob patterns in the
paths
field to match files by extension, directory, or any combination:
Pattern
Matches
**/*.ts
All TypeScript files in any directory
src/**/*
All files under
src/
directory
*.md
Markdown files in the project root
src/components/*.tsx
React components in a specific directory
You can specify multiple patterns and use brace expansion to match multiple extensions in one pattern:
---
paths
:
-
"src/**/*.{ts,tsx}"
-
"lib/**/*.ts"
-
"tests/**/*.test.ts"
---
​
Share rules across projects with symlinks
The
.claude/rules/
directory supports symlinks, so you can maintain a shared set of rules and link them into multiple projects. Symlinks are resolved and loaded normally, and circular symlinks are detected and handled gracefully.
This example links both a shared directory and an individual file:
ln
-s
~/shared-claude-rules
.claude/rules/shared
ln
-s
~/company-standards/security.md
.claude/rules/security.md
​
User-level rules
Personal rules in
~/.claude/rules/
apply to every project on your machine. Use them for preferences that aren’t project-specific:
~/.claude/rules/
├── preferences.md    # Your personal coding preferences
└── workflows.md      # Your preferred workflows
User-level rules are loaded before project rules, giving project rules higher priority.
​
Manage CLAUDE.md for large teams
For organizations deploying Claude Code across teams, you can centralize instructions and control which CLAUDE.md files are loaded.
​
Deploy organization-wide CLAUDE.md
Organizations can deploy a centrally managed CLAUDE.md that applies to all users on a machine. This file cannot be excluded by individual settings.
1
Create the file at the managed policy location
macOS:
/Library/Application Support/ClaudeCode/CLAUDE.md
Linux and WSL:
/etc/claude-code/CLAUDE.md
Windows:
C:\Program Files\ClaudeCode\CLAUDE.md
2
Deploy with your configuration management system
Use MDM, Group Policy, Ansible, or similar tools to distribute the file across developer machines. See
managed settings
for other organization-wide configuration options.
The
claudeMd
key lets you put managed CLAUDE.md content directly inside
managed-settings.json
instead of deploying a separate file.
Scope
: every Claude Code session on the machine, in every repository. For repository-specific guidance, commit a project CLAUDE.md instead.
Precedence
: same as a managed CLAUDE.md file. Loads before user and project CLAUDE.md.
Where it’s honored
: managed and policy settings only. Setting
claudeMd
in user, project, or local settings has no effect.
The example below adds behavioral instructions directly in a managed settings file:
{
"claudeMd"
:
"Always run `make lint` before committing.
\n
Never push directly to main."
}
A managed CLAUDE.md and
managed settings
serve different purposes. Use settings for technical enforcement and CLAUDE.md for behavioral guidance:
Concern
Configure in
Block specific tools, commands, or file paths
Managed settings:
permissions.deny
Enforce sandbox isolation
Managed settings:
sandbox.enabled
Environment variables and API provider routing
Managed settings:
env
Authentication method and organization lock
Managed settings:
forceLoginMethod
,
forceLoginOrgUUID
Code style and quality guidelines
Managed CLAUDE.md
Data handling and compliance reminders
Managed CLAUDE.md
Behavioral instructions for Claude
Managed CLAUDE.md
Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude’s behavior but are not a hard enforcement layer.
​
Exclude specific CLAUDE.md files
In large monorepos, ancestor CLAUDE.md files may contain instructions that aren’t relevant to your work. The
claudeMdExcludes
setting lets you skip specific files by path or glob pattern.
This example excludes a top-level CLAUDE.md and a rules directory from a parent folder. Add it to
.claude/settings.local.json
so the exclusion stays local to your machine:
{
"claudeMdExcludes"
: [
"**/monorepo/CLAUDE.md"
,
"/home/user/monorepo/other-team/.claude/rules/**"
]
}
Patterns are matched against absolute file paths using glob syntax. You can configure
claudeMdExcludes
at any
settings layer
: user, project, local, or managed policy. Arrays merge across layers.
Managed policy CLAUDE.md files cannot be excluded. This ensures organization-wide instructions always apply regardless of individual settings.
​
Auto memory
Auto memory lets Claude accumulate knowledge across sessions without you writing anything. Claude saves notes for itself as it works: build commands, debugging insights, architecture notes, code style preferences, and workflow habits. Claude doesn’t save something every session. It decides what’s worth remembering based on whether the information would be useful in a future conversation.
Auto memory requires Claude Code v2.1.59 or later. Check your version with
claude --version
.
​
Enable or disable auto memory
Auto memory is on by default. To toggle it, open
/memory
in a session and use the auto memory toggle, or set
autoMemoryEnabled
in your project settings:
{
"autoMemoryEnabled"
:
false
}
To disable auto memory via environment variable, set
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
.
​
Storage location
Each project gets its own memory directory at
~/.claude/projects/<project>/memory/
. The
<project>
path is derived from the git repository, so all worktrees and subdirectories within the same repo share one auto memory directory. Outside a git repo, the project root is used instead.
To store auto memory in a different location, set
autoMemoryDirectory
in your user settings at
~/.claude/settings.json
:
{
"autoMemoryDirectory"
:
"~/my-custom-memory-dir"
}
The value must be an absolute path or start with
~/
. This setting is accepted from policy and user settings, and from the
--settings
flag. It is not accepted from project or local settings, since both files live inside the project directory and a cloned repository could supply either to redirect auto memory writes to sensitive locations.
The directory contains a
MEMORY.md
entrypoint and optional topic files:
~/.claude/projects/<project>/memory/
├── MEMORY.md          # Concise index, loaded into every session
├── debugging.md       # Detailed notes on debugging patterns
├── api-conventions.md # API design decisions
└── ...                # Any other topic files Claude creates
MEMORY.md
acts as an index of the memory directory. Claude reads and writes files in this directory throughout your session, using
MEMORY.md
to keep track of what’s stored where.
Auto memory is machine-local. All worktrees and subdirectories within the same git repository share one auto memory directory. Files are not shared across machines or cloud environments.
​
How it works
The first 200 lines of
MEMORY.md
, or the first 25KB, whichever comes first, are loaded at the start of every conversation. Content beyond that threshold is not loaded at session start. Claude keeps
MEMORY.md
concise by moving detailed notes into separate topic files.
This limit applies only to
MEMORY.md
. CLAUDE.md files are loaded in full regardless of length, though shorter files produce better adherence.
Topic files like
debugging.md
or
patterns.md
are not loaded at startup. Claude reads them on demand using its standard file tools when it needs the information.
Claude reads and writes memory files during your session. When you see “Writing memory” or “Recalled memory” in the Claude Code interface, Claude is actively updating or reading from
~/.claude/projects/<project>/memory/
.
​
Audit and edit your memory
Auto memory files are plain markdown you can edit or delete at any time. Run
/memory
to browse and open memory files from within a session.
​
View and edit with
/memory
The
/memory
command lists all CLAUDE.md, CLAUDE.local.md, and rules files loaded in your current session, lets you toggle auto memory on or off, and provides a link to open the auto memory folder. Select any file to open it in your editor.
When you ask Claude to remember something, like “always use pnpm, not npm” or “remember that the API tests require a local Redis instance,” Claude saves it to auto memory. To add instructions to CLAUDE.md instead, ask Claude directly, like “add this to CLAUDE.md,” or edit the file yourself via
/memory
.
​
Troubleshoot memory issues
These are the most common issues with CLAUDE.md and auto memory, along with steps to debug them.
​
Claude isn’t following my CLAUDE.md
CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there’s no guarantee of strict compliance, especially for vague or conflicting instructions.
To debug:
Run
/memory
to verify your CLAUDE.md and CLAUDE.local.md files are being loaded. If a file isn’t listed, Claude can’t see it.
Check that the relevant CLAUDE.md is in a location that gets loaded for your session (see
Choose where to put CLAUDE.md files
).
Make instructions more specific. “Use 2-space indentation” works better than “format code nicely.”
Look for conflicting instructions across CLAUDE.md files. If two files give different guidance for the same behavior, Claude may pick one arbitrarily.
If the instruction is something that must run at a specific point, such as before every commit or after each file edit, write it as a
hook
instead. Hooks execute as shell commands at fixed lifecycle events and apply regardless of what Claude decides to do.
For instructions you want at the system prompt level, use
--append-system-prompt
. This must be passed every invocation, so it’s better suited to scripts and automation than interactive use.
Use the
InstructionsLoaded
hook
to log exactly which instruction files are loaded, when they load, and why. This is useful for debugging path-specific rules or lazy-loaded files in subdirectories.
​
I don’t know what auto memory saved
Run
/memory
and select the auto memory folder to browse what Claude has saved. Everything is plain markdown you can read, edit, or delete.
​
My CLAUDE.md is too large
Files over 200 lines consume more context and may reduce adherence. Use
path-scoped rules
to load instructions only when Claude works with matching files, or trim content that isn’t needed in every session. Splitting into
@path
imports
helps organization but does not reduce context, since imported files load at launch.
​
Instructions seem lost after
/compact
Project-root CLAUDE.md survives compaction: after
/compact
, Claude re-reads it from disk and re-injects it into the session. Nested CLAUDE.md files in subdirectories are not re-injected automatically; they reload the next time Claude reads a file in that subdirectory.
If an instruction disappeared after compaction, it was either given only in conversation or lives in a nested CLAUDE.md that hasn’t reloaded yet. Add conversation-only instructions to CLAUDE.md to make them persist. See
What survives compaction
for the full breakdown.
See
Write effective instructions
for guidance on size, structure, and specificity.
​
Related resources
Debug your configuration
: diagnose why CLAUDE.md or settings aren’t taking effect
Skills
: package repeatable workflows that load on demand
Settings
: configure Claude Code behavior with settings files
Subagent memory
: let subagents maintain their own auto memory
Was this page helpful?
Yes
No
Explore the context window
Permission modes
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/memory" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
How Claude remembers your project
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
How Claude remembers your project
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Each Claude Code session begins with a fresh context window. Two mechanisms carry knowledge across sessions:
CLAUDE.md files
: instructions you write to give Claude persistent context
Auto memory
: notes Claude writes itself based on your corrections and preferences
This page covers how to:
Write and organize CLAUDE.md files
Scope rules to specific file types
with
.claude/rules/
Configure auto memory
so Claude takes notes automatically
Troubleshoot
when instructions aren’t being followed
​
CLAUDE.md vs auto memory
Claude Code has two complementary memory systems. Both are loaded at the start of every conversation. Claude treats them as context, not enforced configuration. The more specific and concise your instructions, the more consistently Claude follows them.
CLAUDE.md files
Auto memory
Who writes it
You
Claude
What it contains
Instructions and rules
Learnings and patterns
Scope
Project, user, or org
Per repository, shared across worktrees
Loaded into
Every session
Every session (first 200 lines or 25KB)
Use for
Coding standards, workflows, project architecture
Build commands, debugging insights, preferences Claude discovers
Use CLAUDE.md files when you want to guide Claude’s behavior. Auto memory lets Claude learn from your corrections without manual effort.
Subagents can also maintain their own auto memory. See
subagent configuration
for details.
​
CLAUDE.md files
CLAUDE.md files are markdown files that give Claude persistent instructions for a project, your personal workflow, or your entire organization. You write these files in plain text; Claude reads them at the start of every session.
​
When to add to CLAUDE.md
Treat CLAUDE.md as the place you write down what you’d otherwise re-explain. Add to it when:
Claude makes the same mistake a second time
A code review catches something Claude should have known about this codebase
You type the same correction or clarification into chat that you typed last session
A new teammate would need the same context to be productive
Keep it to facts Claude should hold in every session: build commands, conventions, project layout, “always do X” rules. If an entry is a multi-step procedure or only matters for one part of the codebase, move it to a
skill
or a
path-scoped rule
instead. The
extension overview
covers when to use each mechanism.
​
Choose where to put CLAUDE.md files
CLAUDE.md files can live in several locations, each with a different scope. The table below lists them in load order, from broadest scope to most specific, so a project instruction appears in context after a user instruction.
Scope
Location
Purpose
Use case examples
Shared with
Managed policy
• macOS:
/Library/Application Support/ClaudeCode/CLAUDE.md
• Linux and WSL:
/etc/claude-code/CLAUDE.md
• Windows:
C:\Program Files\ClaudeCode\CLAUDE.md
Organization-wide instructions managed by IT/DevOps
Company coding standards, security policies, compliance requirements
All users in organization
User instructions
~/.claude/CLAUDE.md
Personal preferences for all projects
Code styling preferences, personal tooling shortcuts
Just you (all projects)
Project instructions
./CLAUDE.md
or
./.claude/CLAUDE.md
Team-shared instructions for the project
Project architecture, coding standards, common workflows
Team members via source control
Local instructions
./CLAUDE.local.md
Personal project-specific preferences; add to
.gitignore
Your sandbox URLs, preferred test data
Just you (current project)
CLAUDE.md and CLAUDE.local.md files in the directory hierarchy above the working directory are loaded in full at launch. Files in subdirectories load on demand when Claude reads files in those directories. See
How CLAUDE.md files load
for the full resolution order.
For large projects, you can break instructions into topic-specific files using
project rules
. Rules let you scope instructions to specific file types or subdirectories.
​
Set up a project CLAUDE.md
A project CLAUDE.md can be stored in either
./CLAUDE.md
or
./.claude/CLAUDE.md
. Create this file and add instructions that apply to anyone working on the project: build and test commands, coding standards, architectural decisions, naming conventions, and common workflows. These instructions are shared with your team through version control, so focus on project-level standards rather than personal preferences.
Run
/init
to generate a starting CLAUDE.md automatically. Claude analyzes your codebase and creates a file with build commands, test instructions, and project conventions it discovers. If a CLAUDE.md already exists,
/init
suggests improvements rather than overwriting it. Refine from there with instructions Claude wouldn’t discover on its own.
Set
CLAUDE_CODE_NEW_INIT=1
to enable an interactive multi-phase flow.
/init
asks which artifacts to set up: CLAUDE.md files, skills, and hooks. It then explores your codebase with a subagent, fills in gaps via follow-up questions, and presents a reviewable proposal before writing any files.
​
Write effective instructions
CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation. The
context window visualization
shows where CLAUDE.md loads relative to the rest of the startup context. Because they’re context rather than enforced configuration, how you write instructions affects how reliably Claude follows them. Specific, concise, well-structured instructions work best.
Size
: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence. If your instructions are growing large, use
path-scoped rules
so instructions load only when Claude works with matching files. You can also split content into
imports
for organization, though imported files still load and enter the context window at launch.
Structure
: use markdown headers and bullets to group related instructions. Claude scans structure the same way readers do: organized sections are easier to follow than dense paragraphs.
Specificity
: write instructions that are concrete enough to verify. For example:
“Use 2-space indentation” instead of “Format code properly”
“Run
npm test
before committing” instead of “Test your changes”
“API handlers live in
src/api/handlers/
” instead of “Keep files organized”
Consistency
: if two rules contradict each other, Claude may pick one arbitrarily. Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and
.claude/rules/
periodically to remove outdated or conflicting instructions. In monorepos, use
claudeMdExcludes
to skip CLAUDE.md files from other teams that aren’t relevant to your work.
​
Import additional files
CLAUDE.md files can import additional files using
@path/to/import
syntax. Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them.
Both relative and absolute paths are allowed. Relative paths resolve relative to the file containing the import, not the working directory. Imported files can recursively import other files, with a maximum depth of five hops.
To pull in a README, package.json, and a workflow guide, reference them with
@
syntax anywhere in your CLAUDE.md:
See @README for project overview and @package.json for available npm commands for this project.
# Additional Instructions
- git workflow @docs/git-instructions.md
For private per-project preferences that shouldn’t be checked into version control, create a
CLAUDE.local.md
at the project root. It loads alongside
CLAUDE.md
and is treated the same way. Add
CLAUDE.local.md
to your
.gitignore
so it isn’t committed; running
/init
and choosing the personal option does this for you.
If you work across multiple git worktrees of the same repository, a gitignored
CLAUDE.local.md
only exists in the worktree where you created it. To share personal instructions across worktrees, import a file from your home directory instead:
# Individual Preferences
- @~/.claude/my-project-instructions.md
The first time Claude Code encounters external imports in a project, it shows an approval dialog listing the files. If you decline, the imports stay disabled and the dialog does not appear again.
For a more structured approach to organizing instructions, see
.claude/rules/
.
​
AGENTS.md
Claude Code reads
CLAUDE.md
, not
AGENTS.md
. If your repository already uses
AGENTS.md
for other coding agents, create a
CLAUDE.md
that imports it so both tools read the same instructions without duplicating them. You can also add Claude-specific instructions below the import. Claude loads the imported file at session start, then appends the rest:
CLAUDE.md
@AGENTS.md
## Claude Code
Use plan mode for changes under
`src/billing/`
.
A symlink also works if you don’t need to add Claude-specific content:
ln
-s
AGENTS.md
CLAUDE.md
On Windows, creating a symlink requires Administrator privileges or Developer Mode, so use the
@AGENTS.md
import instead.
Running
/init
in a repo that already has an
AGENTS.md
reads it and incorporates the relevant parts into the generated
CLAUDE.md
. It also reads other tool configs like
.cursorrules
and
.windsurfrules
.
​
How CLAUDE.md files load
Claude Code reads CLAUDE.md files by walking up the directory tree from your current working directory, checking each directory along the way for
CLAUDE.md
and
CLAUDE.local.md
files. This means if you run Claude Code in
foo/bar/
, it loads instructions from
foo/bar/CLAUDE.md
,
foo/CLAUDE.md
, and any
CLAUDE.local.md
files alongside them.
All discovered files are concatenated into context rather than overriding each other. Across the directory tree, content is ordered from the filesystem root down to your working directory. For the
foo/bar/
example,
foo/CLAUDE.md
appears in context before
foo/bar/CLAUDE.md
, so instructions closer to where you launched Claude are read last. Within each directory,
CLAUDE.local.md
is appended after
CLAUDE.md
, so your personal notes are the last thing Claude reads at that level.
Claude also discovers
CLAUDE.md
and
CLAUDE.local.md
files in subdirectories under your current working directory. Instead of loading them at launch, they are included when Claude reads files in those subdirectories.
If you work in a large monorepo where other teams’ CLAUDE.md files get picked up, use
claudeMdExcludes
to skip them.
Block-level HTML comments (
<!-- maintainer notes -->
) in CLAUDE.md files are stripped before the content is injected into Claude’s context. Use them to leave notes for human maintainers without spending context tokens on them. Comments inside code blocks are preserved. When you open a CLAUDE.md file directly with the Read tool, comments remain visible.
​
Load from additional directories
The
--add-dir
flag gives Claude access to additional directories outside your main working directory. By default, CLAUDE.md files from these directories are not loaded.
To also load memory files from additional directories, set the
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
environment variable:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
=
1
claude
--add-dir
../shared-config
This loads
CLAUDE.md
,
.claude/CLAUDE.md
,
.claude/rules/*.md
, and
CLAUDE.local.md
from the additional directory.
CLAUDE.local.md
is skipped if you exclude
local
from
--setting-sources
.
​
Organize rules with
.claude/rules/
For larger projects, you can organize instructions into multiple files using the
.claude/rules/
directory. This keeps instructions modular and easier for teams to maintain. Rules can also be
scoped to specific file paths
, so they only load into context when Claude works with matching files, reducing noise and saving context space.
Rules load into context every session or when matching files are opened. For task-specific instructions that don’t need to be in context all the time, use
skills
instead, which only load when you invoke them or when Claude determines they’re relevant to your prompt.
​
Set up rules
Place markdown files in your project’s
.claude/rules/
directory. Each file should cover one topic, with a descriptive filename like
testing.md
or
api-design.md
. All
.md
files are discovered recursively, so you can organize rules into subdirectories like
frontend/
or
backend/
:
your-project/
├── .claude/
│   ├── CLAUDE.md           # Main project instructions
│   └── rules/
│       ├── code-style.md   # Code style guidelines
│       ├── testing.md      # Testing conventions
│       └── security.md     # Security requirements
Rules without
paths
frontmatter
are loaded at launch with the same priority as
.claude/CLAUDE.md
.
​
Path-specific rules
Rules can be scoped to specific files using YAML frontmatter with the
paths
field. These conditional rules only apply when Claude is working with files matching the specified patterns.
---
paths
:
-
"src/api/**/*.ts"
---
# API Development Rules
-
All API endpoints must include input validation
-
Use the standard error response format
-
Include OpenAPI documentation comments
Rules without a
paths
field are loaded unconditionally and apply to all files. Path-scoped rules trigger when Claude reads files matching the pattern, not on every tool use.
Use glob patterns in the
paths
field to match files by extension, directory, or any combination:
Pattern
Matches
**/*.ts
All TypeScript files in any directory
src/**/*
All files under
src/
directory
*.md
Markdown files in the project root
src/components/*.tsx
React components in a specific directory
You can specify multiple patterns and use brace expansion to match multiple extensions in one pattern:
---
paths
:
-
"src/**/*.{ts,tsx}"
-
"lib/**/*.ts"
-
"tests/**/*.test.ts"
---
​
Share rules across projects with symlinks
The
.claude/rules/
directory supports symlinks, so you can maintain a shared set of rules and link them into multiple projects. Symlinks are resolved and loaded normally, and circular symlinks are detected and handled gracefully.
This example links both a shared directory and an individual file:
ln
-s
~/shared-claude-rules
.claude/rules/shared
ln
-s
~/company-standards/security.md
.claude/rules/security.md
​
User-level rules
Personal rules in
~/.claude/rules/
apply to every project on your machine. Use them for preferences that aren’t project-specific:
~/.claude/rules/
├── preferences.md    # Your personal coding preferences
└── workflows.md      # Your preferred workflows
User-level rules are loaded before project rules, giving project rules higher priority.
​
Manage CLAUDE.md for large teams
For organizations deploying Claude Code across teams, you can centralize instructions and control which CLAUDE.md files are loaded.
​
Deploy organization-wide CLAUDE.md
Organizations can deploy a centrally managed CLAUDE.md that applies to all users on a machine. This file cannot be excluded by individual settings.
1
Create the file at the managed policy location
macOS:
/Library/Application Support/ClaudeCode/CLAUDE.md
Linux and WSL:
/etc/claude-code/CLAUDE.md
Windows:
C:\Program Files\ClaudeCode\CLAUDE.md
2
Deploy with your configuration management system
Use MDM, Group Policy, Ansible, or similar tools to distribute the file across developer machines. See
managed settings
for other organization-wide configuration options.
The
claudeMd
key lets you put managed CLAUDE.md content directly inside
managed-settings.json
instead of deploying a separate file.
Scope
: every Claude Code session on the machine, in every repository. For repository-specific guidance, commit a project CLAUDE.md instead.
Precedence
: same as a managed CLAUDE.md file. Loads before user and project CLAUDE.md.
Where it’s honored
: managed and policy settings only. Setting
claudeMd
in user, project, or local settings has no effect.
The example below adds behavioral instructions directly in a managed settings file:
{
"claudeMd"
:
"Always run `make lint` before committing.
\n
Never push directly to main."
}
A managed CLAUDE.md and
managed settings
serve different purposes. Use settings for technical enforcement and CLAUDE.md for behavioral guidance:
Concern
Configure in
Block specific tools, commands, or file paths
Managed settings:
permissions.deny
Enforce sandbox isolation
Managed settings:
sandbox.enabled
Environment variables and API provider routing
Managed settings:
env
Authentication method and organization lock
Managed settings:
forceLoginMethod
,
forceLoginOrgUUID
Code style and quality guidelines
Managed CLAUDE.md
Data handling and compliance reminders
Managed CLAUDE.md
Behavioral instructions for Claude
Managed CLAUDE.md
Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude’s behavior but are not a hard enforcement layer.
​
Exclude specific CLAUDE.md files
In large monorepos, ancestor CLAUDE.md files may contain instructions that aren’t relevant to your work. The
claudeMdExcludes
setting lets you skip specific files by path or glob pattern.
This example excludes a top-level CLAUDE.md and a rules directory from a parent folder. Add it to
.claude/settings.local.json
so the exclusion stays local to your machine:
{
"claudeMdExcludes"
: [
"**/monorepo/CLAUDE.md"
,
"/home/user/monorepo/other-team/.claude/rules/**"
]
}
Patterns are matched against absolute file paths using glob syntax. You can configure
claudeMdExcludes
at any
settings layer
: user, project, local, or managed policy. Arrays merge across layers.
Managed policy CLAUDE.md files cannot be excluded. This ensures organization-wide instructions always apply regardless of individual settings.
​
Auto memory
Auto memory lets Claude accumulate knowledge across sessions without you writing anything. Claude saves notes for itself as it works: build commands, debugging insights, architecture notes, code style preferences, and workflow habits. Claude doesn’t save something every session. It decides what’s worth remembering based on whether the information would be useful in a future conversation.
Auto memory requires Claude Code v2.1.59 or later. Check your version with
claude --version
.
​
Enable or disable auto memory
Auto memory is on by default. To toggle it, open
/memory
in a session and use the auto memory toggle, or set
autoMemoryEnabled
in your project settings:
{
"autoMemoryEnabled"
:
false
}
To disable auto memory via environment variable, set
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
.
​
Storage location
Each project gets its own memory directory at
~/.claude/projects/<project>/memory/
. The
<project>
path is derived from the git repository, so all worktrees and subdirectories within the same repo share one auto memory directory. Outside a git repo, the project root is used instead.
To store auto memory in a different location, set
autoMemoryDirectory
in your user settings at
~/.claude/settings.json
:
{
"autoMemoryDirectory"
:
"~/my-custom-memory-dir"
}
The value must be an absolute path or start with
~/
. This setting is accepted from policy and user settings, and from the
--settings
flag. It is not accepted from project or local settings, since both files live inside the project directory and a cloned repository could supply either to redirect auto memory writes to sensitive locations.
The directory contains a
MEMORY.md
entrypoint and optional topic files:
~/.claude/projects/<project>/memory/
├── MEMORY.md          # Concise index, loaded into every session
├── debugging.md       # Detailed notes on debugging patterns
├── api-conventions.md # API design decisions
└── ...                # Any other topic files Claude creates
MEMORY.md
acts as an index of the memory directory. Claude reads and writes files in this directory throughout your session, using
MEMORY.md
to keep track of what’s stored where.
Auto memory is machine-local. All worktrees and subdirectories within the same git repository share one auto memory directory. Files are not shared across machines or cloud environments.
​
How it works
The first 200 lines of
MEMORY.md
, or the first 25KB, whichever comes first, are loaded at the start of every conversation. Content beyond that threshold is not loaded at session start. Claude keeps
MEMORY.md
concise by moving detailed notes into separate topic files.
This limit applies only to
MEMORY.md
. CLAUDE.md files are loaded in full regardless of length, though shorter files produce better adherence.
Topic files like
debugging.md
or
patterns.md
are not loaded at startup. Claude reads them on demand using its standard file tools when it needs the information.
Claude reads and writes memory files during your session. When you see “Writing memory” or “Recalled memory” in the Claude Code interface, Claude is actively updating or reading from
~/.claude/projects/<project>/memory/
.
​
Audit and edit your memory
Auto memory files are plain markdown you can edit or delete at any time. Run
/memory
to browse and open memory files from within a session.
​
View and edit with
/memory
The
/memory
command lists all CLAUDE.md, CLAUDE.local.md, and rules files loaded in your current session, lets you toggle auto memory on or off, and provides a link to open the auto memory folder. Select any file to open it in your editor.
When you ask Claude to remember something, like “always use pnpm, not npm” or “remember that the API tests require a local Redis instance,” Claude saves it to auto memory. To add instructions to CLAUDE.md instead, ask Claude directly, like “add this to CLAUDE.md,” or edit the file yourself via
/memory
.
​
Troubleshoot memory issues
These are the most common issues with CLAUDE.md and auto memory, along with steps to debug them.
​
Claude isn’t following my CLAUDE.md
CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there’s no guarantee of strict compliance, especially for vague or conflicting instructions.
To debug:
Run
/memory
to verify your CLAUDE.md and CLAUDE.local.md files are being loaded. If a file isn’t listed, Claude can’t see it.
Check that the relevant CLAUDE.md is in a location that gets loaded for your session (see
Choose where to put CLAUDE.md files
).
Make instructions more specific. “Use 2-space indentation” works better than “format code nicely.”
Look for conflicting instructions across CLAUDE.md files. If two files give different guidance for the same behavior, Claude may pick one arbitrarily.
If the instruction is something that must run at a specific point, such as before every commit or after each file edit, write it as a
hook
instead. Hooks execute as shell commands at fixed lifecycle events and apply regardless of what Claude decides to do.
For instructions you want at the system prompt level, use
--append-system-prompt
. This must be passed every invocation, so it’s better suited to scripts and automation than interactive use.
Use the
InstructionsLoaded
hook
to log exactly which instruction files are loaded, when they load, and why. This is useful for debugging path-specific rules or lazy-loaded files in subdirectories.
​
I don’t know what auto memory saved
Run
/memory
and select the auto memory folder to browse what Claude has saved. Everything is plain markdown you can read, edit, or delete.
​
My CLAUDE.md is too large
Files over 200 lines consume more context and may reduce adherence. Use
path-scoped rules
to load instructions only when Claude works with matching files, or trim content that isn’t needed in every session. Splitting into
@path
imports
helps organization but does not reduce context, since imported files load at launch.
​
Instructions seem lost after
/compact
Project-root CLAUDE.md survives compaction: after
/compact
, Claude re-reads it from disk and re-injects it into the session. Nested CLAUDE.md files in subdirectories are not re-injected automatically; they reload the next time Claude reads a file in that subdirectory.
If an instruction disappeared after compaction, it was either given only in conversation or lives in a nested CLAUDE.md that hasn’t reloaded yet. Add conversation-only instructions to CLAUDE.md to make them persist. See
What survives compaction
for the full breakdown.
See
Write effective instructions
for guidance on size, structure, and specificity.
​
Related resources
Debug your configuration
: diagnose why CLAUDE.md or settings aren’t taking effect
Skills
: package repeatable workflows that load on demand
Settings
: configure Claude Code behavior with settings files
Subagent memory
: let subagents maintain their own auto memory
Was this page helpful?
Yes
No
Explore the context window
Permission modes
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/memory" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Legal and compliance</title>
  <link>https://code.claude.com/docs/en/legal-and-compliance</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/legal-and-compliance</guid>
  <pubDate>Mon, 07 Oct 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Resources
Legal and compliance
Resources
Legal and compliance
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claud...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Resources
Legal and compliance
Resources
Legal and compliance
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
​
Legal agreements
​
License
Your use of Claude Code is subject to:
Commercial Terms
- for Team, Enterprise, and Claude API users
Consumer Terms of Service
- for Free, Pro, and Max users
​
Commercial agreements
Whether you’re using the Claude API directly (1P) or accessing it through Amazon Bedrock or Google Vertex (3P), your existing commercial agreement will apply to Claude Code usage, unless we’ve mutually agreed otherwise.
​
Compliance
​
Healthcare compliance (BAA)
If a customer has a Business Associate Agreement (BAA) with us, and wants to use Claude Code, the BAA will automatically extend to cover Claude Code if the customer has executed a BAA and has
Zero Data Retention (ZDR)
activated. The BAA will be applicable to that customer’s API traffic flowing through Claude Code. ZDR is enabled on a per-organization basis, so each organization must have ZDR enabled separately to be covered under the BAA.
​
Usage policy
​
Acceptable use
Claude Code usage is subject to the
Anthropic Usage Policy
. Advertised usage limits for Pro and Max plans assume ordinary, individual usage of Claude Code and the Agent SDK.
​
Authentication and credential use
Claude Code authenticates with Anthropic’s servers using OAuth tokens or API keys. These authentication methods serve different purposes:
OAuth authentication
is intended exclusively for purchasers of Claude Free, Pro, Max, Team, and Enterprise subscription plans and is designed to support ordinary use of Claude Code and other native Anthropic applications. More information about how users can authenticate with OAuth tokens can be found in
Logging in to your Claude account
.
Developers
building products or services that interact with Claude’s capabilities, including those using the
Agent SDK
, should use API key authentication through
Claude Console
or a supported cloud provider. Anthropic does not permit third-party developers to offer Claude.ai login or to route requests through Free, Pro, or Max plan credentials on behalf of their users.
Anthropic reserves the right to take measures to enforce these restrictions and may do so without prior notice.
For questions about permitted authentication methods for your use case, please
contact sales
.
​
Security and trust
​
Trust and safety
You can find more information in the
Anthropic Trust Center
and
Transparency Hub
.
​
Security vulnerability reporting
Anthropic manages our security program through HackerOne.
Use this form to report vulnerabilities
.
© Anthropic PBC. All rights reserved. Use is subject to applicable Anthropic Terms of Service.
Was this page helpful?
Yes
No
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/legal-and-compliance" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Resources
Legal and compliance
Resources
Legal and compliance
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claud...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Resources
Legal and compliance
Resources
Legal and compliance
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
​
Legal agreements
​
License
Your use of Claude Code is subject to:
Commercial Terms
- for Team, Enterprise, and Claude API users
Consumer Terms of Service
- for Free, Pro, and Max users
​
Commercial agreements
Whether you’re using the Claude API directly (1P) or accessing it through Amazon Bedrock or Google Vertex (3P), your existing commercial agreement will apply to Claude Code usage, unless we’ve mutually agreed otherwise.
​
Compliance
​
Healthcare compliance (BAA)
If a customer has a Business Associate Agreement (BAA) with us, and wants to use Claude Code, the BAA will automatically extend to cover Claude Code if the customer has executed a BAA and has
Zero Data Retention (ZDR)
activated. The BAA will be applicable to that customer’s API traffic flowing through Claude Code. ZDR is enabled on a per-organization basis, so each organization must have ZDR enabled separately to be covered under the BAA.
​
Usage policy
​
Acceptable use
Claude Code usage is subject to the
Anthropic Usage Policy
. Advertised usage limits for Pro and Max plans assume ordinary, individual usage of Claude Code and the Agent SDK.
​
Authentication and credential use
Claude Code authenticates with Anthropic’s servers using OAuth tokens or API keys. These authentication methods serve different purposes:
OAuth authentication
is intended exclusively for purchasers of Claude Free, Pro, Max, Team, and Enterprise subscription plans and is designed to support ordinary use of Claude Code and other native Anthropic applications. More information about how users can authenticate with OAuth tokens can be found in
Logging in to your Claude account
.
Developers
building products or services that interact with Claude’s capabilities, including those using the
Agent SDK
, should use API key authentication through
Claude Console
or a supported cloud provider. Anthropic does not permit third-party developers to offer Claude.ai login or to route requests through Free, Pro, or Max plan credentials on behalf of their users.
Anthropic reserves the right to take measures to enforce these restrictions and may do so without prior notice.
For questions about permitted authentication methods for your use case, please
contact sales
.
​
Security and trust
​
Trust and safety
You can find more information in the
Anthropic Trust Center
and
Transparency Hub
.
​
Security vulnerability reporting
Anthropic manages our security program through HackerOne.
Use this form to report vulnerabilities
.
© Anthropic PBC. All rights reserved. Use is subject to applicable Anthropic Terms of Service.
Was this page helpful?
Yes
No
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/legal-and-compliance" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>TypeScript SDK V2 session API (deprecated)</title>
  <link>https://code.claude.com/docs/en/agent-sdk/typescript-v2-preview</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/typescript-v2-preview</guid>
  <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
TypeScript SDK V2 session API (deprecated)
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subag...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
TypeScript SDK V2 session API (deprecated)
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The V2 session API functions
unstable_v2_createSession
,
unstable_v2_resumeSession
, and
unstable_v2_prompt
are deprecated and will be removed in a future release. Use the
V1
query()
API
instead.
V2 was an experimental session API that removed the need for async generators and yield coordination. Instead of managing generator state across turns, each turn was a separate
send()
/
stream()
cycle. The API surface reduced to three concepts:
createSession()
/
resumeSession()
: Start or continue a conversation
session.send()
: Send a message
session.stream()
: Get the response
​
Installation
The V2 interface is included in the existing SDK package:
npm
install
@anthropic-ai/claude-agent-sdk
The SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
​
Quick start
​
One-shot prompt
For simple single-turn queries where you don’t need to maintain a session, use
unstable_v2_prompt()
. This example sends a math question and logs the answer:
import
{
unstable_v2_prompt
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
result
=
await
unstable_v2_prompt
(
"What is 2 + 2?"
, {
model:
"claude-opus-4-7"
});
if
(
result
.
subtype
===
"success"
) {
console
.
log
(
result
.
result
);
}
​
Basic session
For interactions beyond a single prompt, create a session. V2 separates sending and streaming into distinct steps:
send()
dispatches your message
stream()
streams back the response
This explicit separation makes it easier to add logic between turns (like processing responses before sending follow-ups).
The example below creates a session, sends “Hello!” to Claude, and prints the text response. It uses
await using
(TypeScript 5.2+) to automatically close the session when the block exits. You can also call
session.close()
manually.
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
await
session
.
send
(
"Hello!"
);
for
await
(
const
msg
of
session
.
stream
()) {
// Filter for assistant messages to get human-readable output
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
​
Multi-turn conversation
Sessions persist context across multiple exchanges. To continue a conversation, call
send()
again on the same session. Claude remembers the previous turns.
This example asks a math question, then asks a follow-up that references the previous answer:
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// Turn 1
await
session
.
send
(
"What is 5 + 3?"
);
for
await
(
const
msg
of
session
.
stream
()) {
// Filter for assistant messages to get human-readable output
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
// Turn 2
await
session
.
send
(
"Multiply that by 2"
);
for
await
(
const
msg
of
session
.
stream
()) {
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
​
Session resume
If you have a session ID from a previous interaction, you can resume it later. This is useful for long-running workflows or when you need to persist conversations across application restarts.
This example creates a session, stores its ID, closes it, then resumes the conversation:
import
{
unstable_v2_createSession
,
unstable_v2_resumeSession
,
type
SDKMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Helper to extract text from assistant messages
function
getAssistantText
(
msg
:
SDKMessage
)
:
string
|
null
{
if
(
msg
.
type
!==
"assistant"
)
return
null
;
return
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
}
// Create initial session and have a conversation
const
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
await
session
.
send
(
"Remember this number: 42"
);
// Get the session ID from any received message
let
sessionId
:
string
|
undefined
;
for
await
(
const
msg
of
session
.
stream
()) {
sessionId
=
msg
.
session_id
;
const
text
=
getAssistantText
(
msg
);
if
(
text
)
console
.
log
(
"Initial response:"
,
text
);
}
console
.
log
(
"Session ID:"
,
sessionId
);
session
.
close
();
// Later: resume the session using the stored ID
await using
resumedSession
=
unstable_v2_resumeSession
(
sessionId
!
, {
model:
"claude-opus-4-7"
});
await
resumedSession
.
send
(
"What number did I ask you to remember?"
);
for
await
(
const
msg
of
resumedSession
.
stream
()) {
const
text
=
getAssistantText
(
msg
);
if
(
text
)
console
.
log
(
"Resumed response:"
,
text
);
}
​
Cleanup
Sessions can be closed manually or automatically using
await using
, a TypeScript 5.2+ feature for automatic resource cleanup. If you’re using an older TypeScript version or encounter compatibility issues, use manual cleanup instead.
Automatic cleanup (TypeScript 5.2+):
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// Session closes automatically when the block exits
Manual cleanup:
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// ... use the session ...
session
.
close
();
​
API reference
​
unstable_v2_createSession()
Creates a new session for multi-turn conversations.
function
unstable_v2_createSession
(
options
:
{
model
:
string
;
// Additional options supported
})
:
SDKSession
;
​
unstable_v2_resumeSession()
Resumes an existing session by ID.
function
unstable_v2_resumeSession
(
sessionId
:
string
,
options
:
{
model
:
string
;
// Additional options supported
}
)
:
SDKSession
;
​
unstable_v2_prompt()
One-shot convenience function for single-turn queries.
function
unstable_v2_prompt
(
prompt
:
string
,
options
:
{
model
:
string
;
// Additional options supported
}
)
:
Promise
<
SDKResultMessage
>;
​
SDKSession interface
interface
SDKSession
{
readonly
sessionId
:
string
;
send
(
message
:
string
|
SDKUserMessage
)
:
Promise
<
void
>;
stream
()
:
AsyncGenerator
<
SDKMessage
,
void
>;
close
()
:
void
;
}
​
Feature availability
The V2 session API does not support every V1 feature. The following require the
V1 SDK
:
Session forking (
forkSession
option)
Some advanced streaming input patterns
​
See also
TypeScript SDK reference (V1)
- Full V1 SDK documentation
SDK overview
- General SDK concepts
V2 examples on GitHub
- Working code examples
Was this page helpful?
Yes
No
TypeScript SDK
Python SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/typescript-v2-preview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
TypeScript SDK V2 session API (deprecated)
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subag...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
TypeScript SDK V2 session API (deprecated)
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The V2 session API functions
unstable_v2_createSession
,
unstable_v2_resumeSession
, and
unstable_v2_prompt
are deprecated and will be removed in a future release. Use the
V1
query()
API
instead.
V2 was an experimental session API that removed the need for async generators and yield coordination. Instead of managing generator state across turns, each turn was a separate
send()
/
stream()
cycle. The API surface reduced to three concepts:
createSession()
/
resumeSession()
: Start or continue a conversation
session.send()
: Send a message
session.stream()
: Get the response
​
Installation
The V2 interface is included in the existing SDK package:
npm
install
@anthropic-ai/claude-agent-sdk
The SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
​
Quick start
​
One-shot prompt
For simple single-turn queries where you don’t need to maintain a session, use
unstable_v2_prompt()
. This example sends a math question and logs the answer:
import
{
unstable_v2_prompt
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
result
=
await
unstable_v2_prompt
(
"What is 2 + 2?"
, {
model:
"claude-opus-4-7"
});
if
(
result
.
subtype
===
"success"
) {
console
.
log
(
result
.
result
);
}
​
Basic session
For interactions beyond a single prompt, create a session. V2 separates sending and streaming into distinct steps:
send()
dispatches your message
stream()
streams back the response
This explicit separation makes it easier to add logic between turns (like processing responses before sending follow-ups).
The example below creates a session, sends “Hello!” to Claude, and prints the text response. It uses
await using
(TypeScript 5.2+) to automatically close the session when the block exits. You can also call
session.close()
manually.
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
await
session
.
send
(
"Hello!"
);
for
await
(
const
msg
of
session
.
stream
()) {
// Filter for assistant messages to get human-readable output
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
​
Multi-turn conversation
Sessions persist context across multiple exchanges. To continue a conversation, call
send()
again on the same session. Claude remembers the previous turns.
This example asks a math question, then asks a follow-up that references the previous answer:
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// Turn 1
await
session
.
send
(
"What is 5 + 3?"
);
for
await
(
const
msg
of
session
.
stream
()) {
// Filter for assistant messages to get human-readable output
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
// Turn 2
await
session
.
send
(
"Multiply that by 2"
);
for
await
(
const
msg
of
session
.
stream
()) {
if
(
msg
.
type
===
"assistant"
) {
const
text
=
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
console
.
log
(
text
);
}
}
​
Session resume
If you have a session ID from a previous interaction, you can resume it later. This is useful for long-running workflows or when you need to persist conversations across application restarts.
This example creates a session, stores its ID, closes it, then resumes the conversation:
import
{
unstable_v2_createSession
,
unstable_v2_resumeSession
,
type
SDKMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Helper to extract text from assistant messages
function
getAssistantText
(
msg
:
SDKMessage
)
:
string
|
null
{
if
(
msg
.
type
!==
"assistant"
)
return
null
;
return
msg
.
message
.
content
.
filter
((
block
)
=>
block
.
type
===
"text"
)
.
map
((
block
)
=>
block
.
text
)
.
join
(
""
);
}
// Create initial session and have a conversation
const
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
await
session
.
send
(
"Remember this number: 42"
);
// Get the session ID from any received message
let
sessionId
:
string
|
undefined
;
for
await
(
const
msg
of
session
.
stream
()) {
sessionId
=
msg
.
session_id
;
const
text
=
getAssistantText
(
msg
);
if
(
text
)
console
.
log
(
"Initial response:"
,
text
);
}
console
.
log
(
"Session ID:"
,
sessionId
);
session
.
close
();
// Later: resume the session using the stored ID
await using
resumedSession
=
unstable_v2_resumeSession
(
sessionId
!
, {
model:
"claude-opus-4-7"
});
await
resumedSession
.
send
(
"What number did I ask you to remember?"
);
for
await
(
const
msg
of
resumedSession
.
stream
()) {
const
text
=
getAssistantText
(
msg
);
if
(
text
)
console
.
log
(
"Resumed response:"
,
text
);
}
​
Cleanup
Sessions can be closed manually or automatically using
await using
, a TypeScript 5.2+ feature for automatic resource cleanup. If you’re using an older TypeScript version or encounter compatibility issues, use manual cleanup instead.
Automatic cleanup (TypeScript 5.2+):
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
await using
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// Session closes automatically when the block exits
Manual cleanup:
import
{
unstable_v2_createSession
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
session
=
unstable_v2_createSession
({
model:
"claude-opus-4-7"
});
// ... use the session ...
session
.
close
();
​
API reference
​
unstable_v2_createSession()
Creates a new session for multi-turn conversations.
function
unstable_v2_createSession
(
options
:
{
model
:
string
;
// Additional options supported
})
:
SDKSession
;
​
unstable_v2_resumeSession()
Resumes an existing session by ID.
function
unstable_v2_resumeSession
(
sessionId
:
string
,
options
:
{
model
:
string
;
// Additional options supported
}
)
:
SDKSession
;
​
unstable_v2_prompt()
One-shot convenience function for single-turn queries.
function
unstable_v2_prompt
(
prompt
:
string
,
options
:
{
model
:
string
;
// Additional options supported
}
)
:
Promise
<
SDKResultMessage
>;
​
SDKSession interface
interface
SDKSession
{
readonly
sessionId
:
string
;
send
(
message
:
string
|
SDKUserMessage
)
:
Promise
<
void
>;
stream
()
:
AsyncGenerator
<
SDKMessage
,
void
>;
close
()
:
void
;
}
​
Feature availability
The V2 session API does not support every V1 feature. The following require the
V1 SDK
:
Session forking (
forkSession
option)
Some advanced streaming input patterns
​
See also
TypeScript SDK reference (V1)
- Full V1 SDK documentation
SDK overview
- General SDK concepts
V2 examples on GitHub
- Working code examples
Was this page helpful?
Yes
No
TypeScript SDK
Python SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/typescript-v2-preview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Choose a permission mode</title>
  <link>https://code.claude.com/docs/en/permission-modes</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/permission-modes</guid>
  <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Choose a permission mode
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Com...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Choose a permission mode
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When Claude wants to edit a file, run a shell command, or make a network request, it pauses and asks you to approve the action. Permission modes control how often that pause happens. The mode you pick shapes the flow of a session: default mode has you review each action as it comes, while looser modes let Claude work in longer uninterrupted stretches and report back when done. Pick more oversight for sensitive work, or fewer interruptions when you trust the direction.
​
Available modes
Each mode makes a different tradeoff between convenience and oversight. The table below shows what Claude can do without a permission prompt in each mode.
Mode
What runs without asking
Best for
default
Reads only
Getting started, sensitive work
acceptEdits
Reads, file edits, and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.)
Iterating on code you’re reviewing
plan
Reads only
Exploring a codebase before changing it
auto
Everything, with background safety checks
Long tasks, reducing prompt fatigue
dontAsk
Only pre-approved tools
Locked-down CI and scripts
bypassPermissions
Everything
Isolated containers and VMs only
In every mode except
bypassPermissions
, writes to
protected paths
are never auto-approved, guarding repository state and Claude’s own configuration against accidental corruption.
Modes set the baseline. Layer
permission rules
on top to pre-approve or block specific tools in any mode except
bypassPermissions
, which skips the permission layer entirely.
​
Switch permission modes
You can switch modes mid-session, at startup, or as a persistent default. The mode is set through these controls, not by asking Claude in chat. Select your interface below to see how to change it.
CLI
VS Code
JetBrains
Desktop
Web and mobile
During a session
: press
Shift+Tab
to cycle
default
→
acceptEdits
→
plan
. The current mode appears in the status bar. Not every mode is in the default cycle:
auto
: appears when your account meets the
auto mode requirements
; cycling to auto shows an opt-in prompt until you accept it, or select
No, don’t ask again
to remove auto from the cycle
bypassPermissions
: appears after you start with
--permission-mode bypassPermissions
,
--dangerously-skip-permissions
, or
--allow-dangerously-skip-permissions
; the
--allow-
variant adds the mode to the cycle without activating it
dontAsk
: never appears in the cycle; set it with
--permission-mode dontAsk
Enabled optional modes slot in after
plan
, with
bypassPermissions
first and
auto
last. If you have both enabled, you will cycle through
bypassPermissions
on the way to
auto
.
At startup
: pass the mode as a flag.
claude
--permission-mode
plan
As a default
: set
defaultMode
in
settings
.
{
"permissions"
: {
"defaultMode"
:
"acceptEdits"
}
}
The same
--permission-mode
flag works with
-p
for
non-interactive runs
.
During a session
: click the mode indicator at the bottom of the prompt box.
As a default
: set
claudeCode.initialPermissionMode
in VS Code settings, or use the Claude Code extension settings panel.
The mode indicator shows these labels, mapped to the mode each one applies:
UI label
Mode
Ask before edits
default
Edit automatically
acceptEdits
Plan mode
plan
Auto mode
auto
Bypass permissions
bypassPermissions
Auto mode appears in the mode indicator after you enable
Allow dangerously skip permissions
in the extension settings, but it stays unavailable until your account meets every requirement listed in the
auto mode section
. The
claudeCode.initialPermissionMode
setting does not accept
auto
; to start in auto mode by default, set
defaultMode
in your Claude Code
settings.json
instead.
Bypass permissions also requires the
Allow dangerously skip permissions
toggle before it appears in the mode indicator.
See the
VS Code guide
for extension-specific details.
The JetBrains plugin runs Claude Code in the IDE terminal, so switching modes works the same as in the CLI: press
Shift+Tab
to cycle, or pass
--permission-mode
when launching.
Use the mode selector next to the send button. Auto and Bypass permissions appear only after you enable them in Desktop settings. See the
Desktop guide
.
Use the mode dropdown next to the prompt box on
claude.ai/code
or in the mobile app. Permission prompts appear in claude.ai for approval. Which modes appear depends on where the session runs:
Cloud sessions
on
Claude Code on the web
: Auto accept edits and Plan mode. Ask permissions, Auto, and Bypass permissions are not available.
Remote Control
sessions
on your local machine: Ask permissions, Auto accept edits, and Plan mode. Auto and Bypass permissions are not available.
For Remote Control, you can also set the starting mode when launching the host:
claude
remote-control
--permission-mode
acceptEdits
​
Auto-approve file edits with acceptEdits mode
acceptEdits
mode lets Claude create and edit files in your working directory without prompting. The status bar shows
⏵⏵ accept edits on
while this mode is active.
In addition to file edits,
acceptEdits
mode auto-approves common filesystem Bash commands:
mkdir
,
touch
,
rm
,
rmdir
,
mv
,
cp
, and
sed
. These commands are also auto-approved when prefixed with safe environment variables such as
LANG=C
or
NO_COLOR=1
, or process wrappers such as
timeout
,
nice
, or
nohup
. Like file edits, auto-approval applies only to paths inside your working directory or
additionalDirectories
. Paths outside that scope, writes to
protected paths
, and all other Bash commands still prompt.
When the
PowerShell tool
is enabled,
acceptEdits
mode also auto-approves
Set-Content
,
Add-Content
,
Clear-Content
, and
Remove-Item
on in-scope paths, along with their common aliases. The same scope and protected-path rules apply.
Use
acceptEdits
when you want to review changes in your editor or via
git diff
after the fact rather than approving each edit inline. Press
Shift+Tab
once from default mode to enter it, or start with it directly:
claude
--permission-mode
acceptEdits
​
Analyze before you edit with plan mode
Plan mode tells Claude to research and propose changes without making them. Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source. Permission prompts still apply the same as default mode.
Enter plan mode by pressing
Shift+Tab
or prefixing a single prompt with
/plan
. You can also start in plan mode from the CLI:
claude
--permission-mode
plan
Press
Shift+Tab
again to leave plan mode without approving a plan.
​
Review and approve a plan
When the plan is ready, Claude presents it and asks how to proceed. From that prompt you can:
Approve and start in auto mode
Approve and accept edits
Approve and review each edit manually
Keep planning with feedback
Refine with
Ultraplan
for browser-based review
Approving a plan exits plan mode and switches the session to the permission mode each approve option describes, so Claude starts editing. To plan again, cycle back to plan mode with
Shift+Tab
, or prefix your next prompt with
/plan
.
Press
Ctrl+G
to open the proposed plan in your default text editor and edit it directly before Claude proceeds. When
showClearContextOnPlanAccept
is enabled, each approve option also offers to clear the planning context first.
Accepting a plan also names the session from the plan content automatically, unless you’ve already set a name with
--name
or
/rename
.
​
Set plan mode as the default
To make plan mode the default for a project, set
defaultMode
in
.claude/settings.json
:
{
"permissions"
: {
"defaultMode"
:
"plan"
}
}
​
Eliminate prompts with auto mode
Auto mode requires Claude Code v2.1.83 or later.
Auto mode lets Claude execute without permission prompts. A separate classifier model reviews actions before they run, blocking anything that escalates beyond your request, targets unrecognized infrastructure, or appears driven by hostile content Claude read.
Auto mode also instructs Claude to execute immediately and minimize clarifying questions. To get that behavior while keeping permission prompts, set the
Proactive output style
instead.
Auto mode is a research preview. It reduces prompts but does not guarantee safety. Use it for tasks where you trust the general direction, not as a replacement for review on sensitive operations.
Auto mode is available only when your account meets all of these requirements:
Plan
: Max, Team, Enterprise, or API. Not available on Pro.
Admin
: on Team and Enterprise, an admin must enable it in
Claude Code admin settings
before users can turn it on. Admins can also lock it off by setting
permissions.disableAutoMode
to
"disable"
in
managed settings
.
Model
: Claude Sonnet 4.6, Opus 4.6, or Opus 4.7 on Team, Enterprise, and API plans; Claude Opus 4.7 only on Max plans. Other models, including Haiku and claude-3 models, are not supported.
Provider
: Anthropic API only. Not available on Bedrock, Vertex, or Foundry.
If Claude Code reports auto mode as unavailable, one of these requirements is unmet; this is not a transient outage. A separate message that names a model and says auto mode “cannot determine the safety” of an action is a transient classifier outage; see the
error reference
.
​
What the classifier blocks by default
The classifier trusts your working directory and your repo’s configured remotes. Everything else is treated as external until you
configure trusted infrastructure
.
Blocked by default
:
Downloading and executing code, like
curl | bash
Sending sensitive data to external endpoints
Production deploys and migrations
Mass deletion on cloud storage
Granting IAM or repo permissions
Modifying shared infrastructure
Irreversibly destroying files that existed before the session
Force push, or pushing directly to
main
Allowed by default
:
Local file operations in your working directory
Installing dependencies declared in your lock files or manifests
Reading
.env
and sending credentials to their matching API
Read-only HTTP requests
Pushing to the branch you started on or one Claude created
Sandbox network access requests are routed through the classifier rather than allowed by default. Run
claude auto-mode defaults
to see the full rule lists. If routine actions get blocked, an administrator can add trusted repos, buckets, and services via the
autoMode.environment
setting: see
Configure auto mode
.
​
Boundaries you state in conversation
The classifier treats boundaries you state in the conversation as a block signal. If you tell Claude “don’t push” or “wait until I review before deploying”, the classifier blocks matching actions even when the default rules would allow them. A boundary stays in force until you lift it in a later message. Claude’s own judgment that a condition was met does not lift it.
Boundaries are not stored as rules. The classifier re-reads them from the transcript on each check, so a boundary can be lost if
context compaction
removes the message that stated it. For a hard guarantee, add a
deny rule
instead.
​
When auto mode falls back
Each denied action shows a notification and appears in
/permissions
under the Recently denied tab, where you can press
r
to retry it with a manual approval.
If the classifier blocks an action 3 times in a row or 20 times total, auto mode pauses and Claude Code resumes prompting. Approving the prompted action resumes auto mode. These thresholds are not configurable. Any allowed action resets the consecutive counter, while the total counter persists for the session and resets only when its own limit triggers a fallback.
In
non-interactive mode
with the
-p
flag, repeated blocks abort the session since there is no user to prompt.
Repeated blocks usually mean the classifier is missing context about your infrastructure. Use
/feedback
to report false positives, or have an administrator
configure trusted infrastructure
.
How the classifier evaluates actions
Each action goes through a fixed decision order. The first matching step wins:
Actions matching your
allow or deny rules
resolve immediately
Read-only actions and file edits in your working directory are auto-approved, except writes to
protected paths
Everything else goes to the classifier
If the classifier blocks, Claude receives the reason and tries an alternative
On entering auto mode, broad allow rules that grant arbitrary code execution are dropped:
Blanket
Bash(*)
or
PowerShell(*)
Wildcarded interpreters like
Bash(python*)
Package-manager run commands
Agent
allow rules
Narrow rules like
Bash(npm test)
carry over. Dropped rules are restored when you leave auto mode.
The classifier sees user messages, tool calls, and your CLAUDE.md content. Tool results are stripped, so hostile content in a file or web page cannot manipulate it directly. A separate server-side probe scans incoming tool results and flags suspicious content before Claude reads it. For more on how these layers work together, see the
auto mode announcement
and the
engineering deep dive
.
How auto mode handles subagents
The classifier checks
subagent
work at three points:
Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.
While the subagent runs, each of its actions goes through the classifier with the same rules as the parent session, and any
permissionMode
in the subagent’s frontmatter is ignored.
When the subagent finishes, the classifier reviews its full action history; if that return check flags a concern, a security warning is prepended to the subagent’s results.
Cost and latency
The classifier runs on a server-configured model that is independent of your
/model
selection, so switching models does not change classifier availability. Classifier calls count toward your token usage. Each check sends a portion of the transcript plus the pending action, adding a round-trip before execution. Reads and working-directory edits outside protected paths skip the classifier, so the overhead comes mainly from shell commands and network operations.
​
Allow only pre-approved tools with dontAsk mode
dontAsk
mode auto-denies every tool call that would otherwise prompt. Only actions matching your
permissions.allow
rules and
read-only Bash commands
can execute; explicit
ask
rules are denied rather than prompting. This makes the mode fully non-interactive for CI pipelines or restricted environments where you pre-define exactly what Claude may do.
Set it at startup with the flag:
claude
--permission-mode
dontAsk
​
Skip all checks with bypassPermissions mode
bypassPermissions
mode disables permission prompts and safety checks so tool calls execute immediately. As of v2.1.126 this includes writes to
protected paths
, which earlier versions still prompted for. Removals targeting the filesystem root or home directory, such as
rm -rf /
and
rm -rf ~
, still prompt as a circuit breaker against model error. Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system.
You cannot enter
bypassPermissions
from a session that was started without one of the enabling flags; restart with one to enable it:
claude
--permission-mode
bypassPermissions
The
--dangerously-skip-permissions
flag is equivalent.
On Linux and macOS, Claude Code refuses to start in this mode when running as root or under
sudo
:
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons
The check is skipped automatically inside a recognized sandbox. To run autonomously in a container, use the
dev container
configuration, which runs Claude Code as a non-root user.
bypassPermissions
offers no protection against prompt injection or unintended actions. For background safety checks without prompts, use
auto mode
instead. Administrators can block this mode by setting
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
​
Protected paths
Writes to a small set of paths are never auto-approved, in every mode except
bypassPermissions
. This prevents accidental corruption of repository state and Claude’s own configuration. In
default
,
acceptEdits
, and
plan
these writes prompt; in
auto
they route to the classifier; in
dontAsk
they are denied; in
bypassPermissions
they are allowed.
Protected directories:
.git
.vscode
.idea
.husky
.claude
, except for
.claude/commands
,
.claude/agents
,
.claude/skills
, and
.claude/worktrees
where Claude routinely creates content
Protected files:
.gitconfig
,
.gitmodules
.bashrc
,
.bash_profile
,
.zshrc
,
.zprofile
,
.profile
.ripgreprc
.mcp.json
,
.claude.json
​
See also
Permissions
: allow, ask, and deny rules; managed policies
Configure auto mode
: tell the classifier which infrastructure your organization trusts
Hooks
: custom permission logic via
PreToolUse
and
PermissionRequest
hooks
Ultraplan
: run plan mode in a Claude Code on the web session with browser-based review
Security
: safeguards and best practices
Sandboxing
: filesystem and network isolation for Bash commands
Non-interactive mode
: run Claude Code with the
-p
flag
Was this page helpful?
Yes
No
Store instructions and memories
Common workflows
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/permission-modes" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Choose a permission mode
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Com...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Choose a permission mode
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When Claude wants to edit a file, run a shell command, or make a network request, it pauses and asks you to approve the action. Permission modes control how often that pause happens. The mode you pick shapes the flow of a session: default mode has you review each action as it comes, while looser modes let Claude work in longer uninterrupted stretches and report back when done. Pick more oversight for sensitive work, or fewer interruptions when you trust the direction.
​
Available modes
Each mode makes a different tradeoff between convenience and oversight. The table below shows what Claude can do without a permission prompt in each mode.
Mode
What runs without asking
Best for
default
Reads only
Getting started, sensitive work
acceptEdits
Reads, file edits, and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.)
Iterating on code you’re reviewing
plan
Reads only
Exploring a codebase before changing it
auto
Everything, with background safety checks
Long tasks, reducing prompt fatigue
dontAsk
Only pre-approved tools
Locked-down CI and scripts
bypassPermissions
Everything
Isolated containers and VMs only
In every mode except
bypassPermissions
, writes to
protected paths
are never auto-approved, guarding repository state and Claude’s own configuration against accidental corruption.
Modes set the baseline. Layer
permission rules
on top to pre-approve or block specific tools in any mode except
bypassPermissions
, which skips the permission layer entirely.
​
Switch permission modes
You can switch modes mid-session, at startup, or as a persistent default. The mode is set through these controls, not by asking Claude in chat. Select your interface below to see how to change it.
CLI
VS Code
JetBrains
Desktop
Web and mobile
During a session
: press
Shift+Tab
to cycle
default
→
acceptEdits
→
plan
. The current mode appears in the status bar. Not every mode is in the default cycle:
auto
: appears when your account meets the
auto mode requirements
; cycling to auto shows an opt-in prompt until you accept it, or select
No, don’t ask again
to remove auto from the cycle
bypassPermissions
: appears after you start with
--permission-mode bypassPermissions
,
--dangerously-skip-permissions
, or
--allow-dangerously-skip-permissions
; the
--allow-
variant adds the mode to the cycle without activating it
dontAsk
: never appears in the cycle; set it with
--permission-mode dontAsk
Enabled optional modes slot in after
plan
, with
bypassPermissions
first and
auto
last. If you have both enabled, you will cycle through
bypassPermissions
on the way to
auto
.
At startup
: pass the mode as a flag.
claude
--permission-mode
plan
As a default
: set
defaultMode
in
settings
.
{
"permissions"
: {
"defaultMode"
:
"acceptEdits"
}
}
The same
--permission-mode
flag works with
-p
for
non-interactive runs
.
During a session
: click the mode indicator at the bottom of the prompt box.
As a default
: set
claudeCode.initialPermissionMode
in VS Code settings, or use the Claude Code extension settings panel.
The mode indicator shows these labels, mapped to the mode each one applies:
UI label
Mode
Ask before edits
default
Edit automatically
acceptEdits
Plan mode
plan
Auto mode
auto
Bypass permissions
bypassPermissions
Auto mode appears in the mode indicator after you enable
Allow dangerously skip permissions
in the extension settings, but it stays unavailable until your account meets every requirement listed in the
auto mode section
. The
claudeCode.initialPermissionMode
setting does not accept
auto
; to start in auto mode by default, set
defaultMode
in your Claude Code
settings.json
instead.
Bypass permissions also requires the
Allow dangerously skip permissions
toggle before it appears in the mode indicator.
See the
VS Code guide
for extension-specific details.
The JetBrains plugin runs Claude Code in the IDE terminal, so switching modes works the same as in the CLI: press
Shift+Tab
to cycle, or pass
--permission-mode
when launching.
Use the mode selector next to the send button. Auto and Bypass permissions appear only after you enable them in Desktop settings. See the
Desktop guide
.
Use the mode dropdown next to the prompt box on
claude.ai/code
or in the mobile app. Permission prompts appear in claude.ai for approval. Which modes appear depends on where the session runs:
Cloud sessions
on
Claude Code on the web
: Auto accept edits and Plan mode. Ask permissions, Auto, and Bypass permissions are not available.
Remote Control
sessions
on your local machine: Ask permissions, Auto accept edits, and Plan mode. Auto and Bypass permissions are not available.
For Remote Control, you can also set the starting mode when launching the host:
claude
remote-control
--permission-mode
acceptEdits
​
Auto-approve file edits with acceptEdits mode
acceptEdits
mode lets Claude create and edit files in your working directory without prompting. The status bar shows
⏵⏵ accept edits on
while this mode is active.
In addition to file edits,
acceptEdits
mode auto-approves common filesystem Bash commands:
mkdir
,
touch
,
rm
,
rmdir
,
mv
,
cp
, and
sed
. These commands are also auto-approved when prefixed with safe environment variables such as
LANG=C
or
NO_COLOR=1
, or process wrappers such as
timeout
,
nice
, or
nohup
. Like file edits, auto-approval applies only to paths inside your working directory or
additionalDirectories
. Paths outside that scope, writes to
protected paths
, and all other Bash commands still prompt.
When the
PowerShell tool
is enabled,
acceptEdits
mode also auto-approves
Set-Content
,
Add-Content
,
Clear-Content
, and
Remove-Item
on in-scope paths, along with their common aliases. The same scope and protected-path rules apply.
Use
acceptEdits
when you want to review changes in your editor or via
git diff
after the fact rather than approving each edit inline. Press
Shift+Tab
once from default mode to enter it, or start with it directly:
claude
--permission-mode
acceptEdits
​
Analyze before you edit with plan mode
Plan mode tells Claude to research and propose changes without making them. Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source. Permission prompts still apply the same as default mode.
Enter plan mode by pressing
Shift+Tab
or prefixing a single prompt with
/plan
. You can also start in plan mode from the CLI:
claude
--permission-mode
plan
Press
Shift+Tab
again to leave plan mode without approving a plan.
​
Review and approve a plan
When the plan is ready, Claude presents it and asks how to proceed. From that prompt you can:
Approve and start in auto mode
Approve and accept edits
Approve and review each edit manually
Keep planning with feedback
Refine with
Ultraplan
for browser-based review
Approving a plan exits plan mode and switches the session to the permission mode each approve option describes, so Claude starts editing. To plan again, cycle back to plan mode with
Shift+Tab
, or prefix your next prompt with
/plan
.
Press
Ctrl+G
to open the proposed plan in your default text editor and edit it directly before Claude proceeds. When
showClearContextOnPlanAccept
is enabled, each approve option also offers to clear the planning context first.
Accepting a plan also names the session from the plan content automatically, unless you’ve already set a name with
--name
or
/rename
.
​
Set plan mode as the default
To make plan mode the default for a project, set
defaultMode
in
.claude/settings.json
:
{
"permissions"
: {
"defaultMode"
:
"plan"
}
}
​
Eliminate prompts with auto mode
Auto mode requires Claude Code v2.1.83 or later.
Auto mode lets Claude execute without permission prompts. A separate classifier model reviews actions before they run, blocking anything that escalates beyond your request, targets unrecognized infrastructure, or appears driven by hostile content Claude read.
Auto mode also instructs Claude to execute immediately and minimize clarifying questions. To get that behavior while keeping permission prompts, set the
Proactive output style
instead.
Auto mode is a research preview. It reduces prompts but does not guarantee safety. Use it for tasks where you trust the general direction, not as a replacement for review on sensitive operations.
Auto mode is available only when your account meets all of these requirements:
Plan
: Max, Team, Enterprise, or API. Not available on Pro.
Admin
: on Team and Enterprise, an admin must enable it in
Claude Code admin settings
before users can turn it on. Admins can also lock it off by setting
permissions.disableAutoMode
to
"disable"
in
managed settings
.
Model
: Claude Sonnet 4.6, Opus 4.6, or Opus 4.7 on Team, Enterprise, and API plans; Claude Opus 4.7 only on Max plans. Other models, including Haiku and claude-3 models, are not supported.
Provider
: Anthropic API only. Not available on Bedrock, Vertex, or Foundry.
If Claude Code reports auto mode as unavailable, one of these requirements is unmet; this is not a transient outage. A separate message that names a model and says auto mode “cannot determine the safety” of an action is a transient classifier outage; see the
error reference
.
​
What the classifier blocks by default
The classifier trusts your working directory and your repo’s configured remotes. Everything else is treated as external until you
configure trusted infrastructure
.
Blocked by default
:
Downloading and executing code, like
curl | bash
Sending sensitive data to external endpoints
Production deploys and migrations
Mass deletion on cloud storage
Granting IAM or repo permissions
Modifying shared infrastructure
Irreversibly destroying files that existed before the session
Force push, or pushing directly to
main
Allowed by default
:
Local file operations in your working directory
Installing dependencies declared in your lock files or manifests
Reading
.env
and sending credentials to their matching API
Read-only HTTP requests
Pushing to the branch you started on or one Claude created
Sandbox network access requests are routed through the classifier rather than allowed by default. Run
claude auto-mode defaults
to see the full rule lists. If routine actions get blocked, an administrator can add trusted repos, buckets, and services via the
autoMode.environment
setting: see
Configure auto mode
.
​
Boundaries you state in conversation
The classifier treats boundaries you state in the conversation as a block signal. If you tell Claude “don’t push” or “wait until I review before deploying”, the classifier blocks matching actions even when the default rules would allow them. A boundary stays in force until you lift it in a later message. Claude’s own judgment that a condition was met does not lift it.
Boundaries are not stored as rules. The classifier re-reads them from the transcript on each check, so a boundary can be lost if
context compaction
removes the message that stated it. For a hard guarantee, add a
deny rule
instead.
​
When auto mode falls back
Each denied action shows a notification and appears in
/permissions
under the Recently denied tab, where you can press
r
to retry it with a manual approval.
If the classifier blocks an action 3 times in a row or 20 times total, auto mode pauses and Claude Code resumes prompting. Approving the prompted action resumes auto mode. These thresholds are not configurable. Any allowed action resets the consecutive counter, while the total counter persists for the session and resets only when its own limit triggers a fallback.
In
non-interactive mode
with the
-p
flag, repeated blocks abort the session since there is no user to prompt.
Repeated blocks usually mean the classifier is missing context about your infrastructure. Use
/feedback
to report false positives, or have an administrator
configure trusted infrastructure
.
How the classifier evaluates actions
Each action goes through a fixed decision order. The first matching step wins:
Actions matching your
allow or deny rules
resolve immediately
Read-only actions and file edits in your working directory are auto-approved, except writes to
protected paths
Everything else goes to the classifier
If the classifier blocks, Claude receives the reason and tries an alternative
On entering auto mode, broad allow rules that grant arbitrary code execution are dropped:
Blanket
Bash(*)
or
PowerShell(*)
Wildcarded interpreters like
Bash(python*)
Package-manager run commands
Agent
allow rules
Narrow rules like
Bash(npm test)
carry over. Dropped rules are restored when you leave auto mode.
The classifier sees user messages, tool calls, and your CLAUDE.md content. Tool results are stripped, so hostile content in a file or web page cannot manipulate it directly. A separate server-side probe scans incoming tool results and flags suspicious content before Claude reads it. For more on how these layers work together, see the
auto mode announcement
and the
engineering deep dive
.
How auto mode handles subagents
The classifier checks
subagent
work at three points:
Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.
While the subagent runs, each of its actions goes through the classifier with the same rules as the parent session, and any
permissionMode
in the subagent’s frontmatter is ignored.
When the subagent finishes, the classifier reviews its full action history; if that return check flags a concern, a security warning is prepended to the subagent’s results.
Cost and latency
The classifier runs on a server-configured model that is independent of your
/model
selection, so switching models does not change classifier availability. Classifier calls count toward your token usage. Each check sends a portion of the transcript plus the pending action, adding a round-trip before execution. Reads and working-directory edits outside protected paths skip the classifier, so the overhead comes mainly from shell commands and network operations.
​
Allow only pre-approved tools with dontAsk mode
dontAsk
mode auto-denies every tool call that would otherwise prompt. Only actions matching your
permissions.allow
rules and
read-only Bash commands
can execute; explicit
ask
rules are denied rather than prompting. This makes the mode fully non-interactive for CI pipelines or restricted environments where you pre-define exactly what Claude may do.
Set it at startup with the flag:
claude
--permission-mode
dontAsk
​
Skip all checks with bypassPermissions mode
bypassPermissions
mode disables permission prompts and safety checks so tool calls execute immediately. As of v2.1.126 this includes writes to
protected paths
, which earlier versions still prompted for. Removals targeting the filesystem root or home directory, such as
rm -rf /
and
rm -rf ~
, still prompt as a circuit breaker against model error. Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system.
You cannot enter
bypassPermissions
from a session that was started without one of the enabling flags; restart with one to enable it:
claude
--permission-mode
bypassPermissions
The
--dangerously-skip-permissions
flag is equivalent.
On Linux and macOS, Claude Code refuses to start in this mode when running as root or under
sudo
:
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons
The check is skipped automatically inside a recognized sandbox. To run autonomously in a container, use the
dev container
configuration, which runs Claude Code as a non-root user.
bypassPermissions
offers no protection against prompt injection or unintended actions. For background safety checks without prompts, use
auto mode
instead. Administrators can block this mode by setting
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
​
Protected paths
Writes to a small set of paths are never auto-approved, in every mode except
bypassPermissions
. This prevents accidental corruption of repository state and Claude’s own configuration. In
default
,
acceptEdits
, and
plan
these writes prompt; in
auto
they route to the classifier; in
dontAsk
they are denied; in
bypassPermissions
they are allowed.
Protected directories:
.git
.vscode
.idea
.husky
.claude
, except for
.claude/commands
,
.claude/agents
,
.claude/skills
, and
.claude/worktrees
where Claude routinely creates content
Protected files:
.gitconfig
,
.gitmodules
.bashrc
,
.bash_profile
,
.zshrc
,
.zprofile
,
.profile
.ripgreprc
.mcp.json
,
.claude.json
​
See also
Permissions
: allow, ask, and deny rules; managed policies
Configure auto mode
: tell the classifier which infrastructure your organization trusts
Hooks
: custom permission logic via
PreToolUse
and
PermissionRequest
hooks
Ultraplan
: run plan mode in a Claude Code on the web session with browser-based review
Security
: safeguards and best practices
Sandboxing
: filesystem and network isolation for Bash commands
Non-interactive mode
: run Claude Code with the
-p
flag
Was this page helpful?
Yes
No
Store instructions and memories
Common workflows
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/permission-modes" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>JetBrains IDEs</title>
  <link>https://code.claude.com/docs/en/jetbrains</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/jetbrains</guid>
  <pubDate>Fri, 27 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
JetBrains IDEs
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Co...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
JetBrains IDEs
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code integrates with JetBrains IDEs through a dedicated plugin, providing features like interactive diff viewing, selection context sharing, and more.
​
Supported IDEs
The Claude Code plugin works with most JetBrains IDEs, including:
IntelliJ IDEA
PyCharm
Android Studio
WebStorm
PhpStorm
GoLand
​
Features
Quick launch
: use
Cmd+Esc
(Mac) or
Ctrl+Esc
(Windows/Linux) to open Claude Code directly from your editor, or click the Claude Code button in the UI
Diff viewing
: code changes can be displayed directly in the IDE diff viewer instead of the terminal
Selection context
: the current selection or tab in the IDE is automatically shared with Claude Code
File reference shortcuts
: use
Cmd+Option+K
(Mac) or
Alt+Ctrl+K
(Linux/Windows) to insert file references such as
@src/auth.ts#L1-99
Diagnostic sharing
: diagnostic errors from the IDE, such as lint and syntax errors, are automatically shared with Claude as you work
​
Installation
​
Marketplace installation
Find and install the
Claude Code plugin
from the JetBrains marketplace and restart your IDE.
If you haven’t installed Claude Code yet, see the
quickstart guide
for installation instructions.
After installing the plugin, you may need to restart your IDE completely for it to take effect.
​
Usage
​
From your IDE
Run
claude
from your IDE’s integrated terminal, and all integration features will be active.
​
From external terminals
Use the
/ide
command in any external terminal to connect Claude Code to your JetBrains IDE and activate all features:
claude
/ide
If you want Claude to have access to the same files as your IDE, start Claude Code from the same directory as your IDE project root.
​
Configuration
​
Claude Code settings
Configure IDE integration through Claude Code’s settings:
Run
claude
Enter the
/config
command
Set the diff tool to
auto
to show diffs in the IDE, or
terminal
to keep them in the terminal
​
Plugin settings
Configure the Claude Code plugin by going to
Settings → Tools → Claude Code [Beta]
:
​
General settings
Claude command
: specify a custom command to run Claude, for example
claude
,
/usr/local/bin/claude
, or
npx @anthropic-ai/claude-code
Suppress notification for Claude command not found
: skip notifications about not finding the Claude command
Enable using Option+Enter for multi-line prompts
: on macOS only. When enabled, Option+Enter inserts new lines in Claude Code prompts. Disable if the Option key is being captured unexpectedly. Requires a terminal restart.
Enable automatic updates
: automatically check for and install plugin updates, applied on restart
For WSL users: Set
wsl -d Ubuntu -- bash -lic "claude"
as your Claude command (replace
Ubuntu
with your WSL distribution name)
​
ESC key configuration
If the ESC key doesn’t interrupt Claude Code operations in JetBrains terminals:
Go to
Settings → Tools → Terminal
Either:
Uncheck “Move focus to the editor with Escape”, or
Click “Configure terminal keybindings” and delete the “Switch focus to Editor” shortcut
Apply the changes
This allows the ESC key to properly interrupt Claude Code operations.
​
Special configurations
​
Remote development
When using JetBrains Remote Development, you must install the plugin in the remote host via
Settings → Plugin (Host)
.
The plugin must be installed on the remote host, not on your local client machine.
​
WSL configuration
If you’re using Claude Code on WSL2 with a JetBrains IDE and see “No available IDEs detected”, the cause is usually WSL2’s NAT networking or Windows Firewall blocking the connection between WSL2 and the IDE running on the Windows host. WSL1 uses the host’s network directly and isn’t affected.
​
Allow WSL2 traffic through Windows Firewall
This is the recommended fix because it keeps your existing WSL2 networking mode.
1
Find your WSL2 IP address
From inside your WSL shell, run:
hostname
-I
Note the subnet, for example
172.21.123.45
is in
172.21.0.0/16
.
2
Create a firewall rule
Open PowerShell as Administrator and run the following, adjusting the IP range to match your subnet:
New-NetFirewallRule
-
DisplayName
"Allow WSL2 Internal Traffic"
-
Direction Inbound
-
Protocol TCP
-
Action Allow
-
RemoteAddress
172.21
.
0.0
/
16
-
LocalAddress
172.21
.
0.0
/
16
3
Restart your IDE and Claude Code
Close and reopen both so the new rule takes effect.
​
Switch WSL2 to mirrored networking
Mirrored networking requires Windows 11 22H2 or later. If you’re on Windows 10, use the firewall rule above instead.
Add this to
.wslconfig
in your Windows user directory:
[wsl2]
networkingMode
=mirrored
Then restart WSL with
wsl --shutdown
from PowerShell.
​
Troubleshooting
​
Plugin not working
If the plugin is installed but Claude Code features don’t appear in your IDE:
Ensure you’re running Claude Code from the project root directory
Check that the JetBrains plugin is enabled in the IDE settings
Completely restart the IDE (you may need to do this multiple times)
For Remote Development, ensure the plugin is installed in the remote host
​
IDE not detected
If running
claude
shows “No available IDEs detected”:
Verify the plugin is installed and enabled
Restart the IDE completely
Check that you’re running Claude Code from the integrated terminal
For WSL users, see
WSL configuration
above
​
Command not found
If clicking the Claude icon shows “command not found”:
Verify Claude Code is installed by running
claude --version
in a terminal
Configure the Claude command path in plugin settings
For WSL users, use the WSL command format mentioned in the configuration section
​
Security considerations
When Claude Code runs in a JetBrains IDE with auto-edit permissions enabled, it may be able to modify IDE configuration files that can be automatically executed by your IDE. This may increase the risk of running Claude Code in auto-edit mode and allow bypassing Claude Code’s permission prompts for bash execution.
When running in JetBrains IDEs, consider:
Using manual approval mode for edits
Taking extra care to ensure Claude is only used with trusted prompts
Being aware of which files Claude Code has access to modify
For Claude Code installation or login problems outside the IDE, see
Troubleshoot installation and login
.
Was this page helpful?
Yes
No
Visual Studio Code
Code Review
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/jetbrains" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
JetBrains IDEs
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Co...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
JetBrains IDEs
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code integrates with JetBrains IDEs through a dedicated plugin, providing features like interactive diff viewing, selection context sharing, and more.
​
Supported IDEs
The Claude Code plugin works with most JetBrains IDEs, including:
IntelliJ IDEA
PyCharm
Android Studio
WebStorm
PhpStorm
GoLand
​
Features
Quick launch
: use
Cmd+Esc
(Mac) or
Ctrl+Esc
(Windows/Linux) to open Claude Code directly from your editor, or click the Claude Code button in the UI
Diff viewing
: code changes can be displayed directly in the IDE diff viewer instead of the terminal
Selection context
: the current selection or tab in the IDE is automatically shared with Claude Code
File reference shortcuts
: use
Cmd+Option+K
(Mac) or
Alt+Ctrl+K
(Linux/Windows) to insert file references such as
@src/auth.ts#L1-99
Diagnostic sharing
: diagnostic errors from the IDE, such as lint and syntax errors, are automatically shared with Claude as you work
​
Installation
​
Marketplace installation
Find and install the
Claude Code plugin
from the JetBrains marketplace and restart your IDE.
If you haven’t installed Claude Code yet, see the
quickstart guide
for installation instructions.
After installing the plugin, you may need to restart your IDE completely for it to take effect.
​
Usage
​
From your IDE
Run
claude
from your IDE’s integrated terminal, and all integration features will be active.
​
From external terminals
Use the
/ide
command in any external terminal to connect Claude Code to your JetBrains IDE and activate all features:
claude
/ide
If you want Claude to have access to the same files as your IDE, start Claude Code from the same directory as your IDE project root.
​
Configuration
​
Claude Code settings
Configure IDE integration through Claude Code’s settings:
Run
claude
Enter the
/config
command
Set the diff tool to
auto
to show diffs in the IDE, or
terminal
to keep them in the terminal
​
Plugin settings
Configure the Claude Code plugin by going to
Settings → Tools → Claude Code [Beta]
:
​
General settings
Claude command
: specify a custom command to run Claude, for example
claude
,
/usr/local/bin/claude
, or
npx @anthropic-ai/claude-code
Suppress notification for Claude command not found
: skip notifications about not finding the Claude command
Enable using Option+Enter for multi-line prompts
: on macOS only. When enabled, Option+Enter inserts new lines in Claude Code prompts. Disable if the Option key is being captured unexpectedly. Requires a terminal restart.
Enable automatic updates
: automatically check for and install plugin updates, applied on restart
For WSL users: Set
wsl -d Ubuntu -- bash -lic "claude"
as your Claude command (replace
Ubuntu
with your WSL distribution name)
​
ESC key configuration
If the ESC key doesn’t interrupt Claude Code operations in JetBrains terminals:
Go to
Settings → Tools → Terminal
Either:
Uncheck “Move focus to the editor with Escape”, or
Click “Configure terminal keybindings” and delete the “Switch focus to Editor” shortcut
Apply the changes
This allows the ESC key to properly interrupt Claude Code operations.
​
Special configurations
​
Remote development
When using JetBrains Remote Development, you must install the plugin in the remote host via
Settings → Plugin (Host)
.
The plugin must be installed on the remote host, not on your local client machine.
​
WSL configuration
If you’re using Claude Code on WSL2 with a JetBrains IDE and see “No available IDEs detected”, the cause is usually WSL2’s NAT networking or Windows Firewall blocking the connection between WSL2 and the IDE running on the Windows host. WSL1 uses the host’s network directly and isn’t affected.
​
Allow WSL2 traffic through Windows Firewall
This is the recommended fix because it keeps your existing WSL2 networking mode.
1
Find your WSL2 IP address
From inside your WSL shell, run:
hostname
-I
Note the subnet, for example
172.21.123.45
is in
172.21.0.0/16
.
2
Create a firewall rule
Open PowerShell as Administrator and run the following, adjusting the IP range to match your subnet:
New-NetFirewallRule
-
DisplayName
"Allow WSL2 Internal Traffic"
-
Direction Inbound
-
Protocol TCP
-
Action Allow
-
RemoteAddress
172.21
.
0.0
/
16
-
LocalAddress
172.21
.
0.0
/
16
3
Restart your IDE and Claude Code
Close and reopen both so the new rule takes effect.
​
Switch WSL2 to mirrored networking
Mirrored networking requires Windows 11 22H2 or later. If you’re on Windows 10, use the firewall rule above instead.
Add this to
.wslconfig
in your Windows user directory:
[wsl2]
networkingMode
=mirrored
Then restart WSL with
wsl --shutdown
from PowerShell.
​
Troubleshooting
​
Plugin not working
If the plugin is installed but Claude Code features don’t appear in your IDE:
Ensure you’re running Claude Code from the project root directory
Check that the JetBrains plugin is enabled in the IDE settings
Completely restart the IDE (you may need to do this multiple times)
For Remote Development, ensure the plugin is installed in the remote host
​
IDE not detected
If running
claude
shows “No available IDEs detected”:
Verify the plugin is installed and enabled
Restart the IDE completely
Check that you’re running Claude Code from the integrated terminal
For WSL users, see
WSL configuration
above
​
Command not found
If clicking the Claude icon shows “command not found”:
Verify Claude Code is installed by running
claude --version
in a terminal
Configure the Claude command path in plugin settings
For WSL users, use the WSL command format mentioned in the configuration section
​
Security considerations
When Claude Code runs in a JetBrains IDE with auto-edit permissions enabled, it may be able to modify IDE configuration files that can be automatically executed by your IDE. This may increase the risk of running Claude Code in auto-edit mode and allow bypassing Claude Code’s permission prompts for bash execution.
When running in JetBrains IDEs, consider:
Using manual approval mode for edits
Taking extra care to ensure Claude is only used with trusted prompts
Being aware of which files Claude Code has access to modify
For Claude Code installation or login problems outside the IDE, see
Troubleshoot installation and login
.
Was this page helpful?
Yes
No
Visual Studio Code
Code Review
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/jetbrains" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Output styles</title>
  <link>https://code.claude.com/docs/en/output-styles</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/output-styles</guid>
  <pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Output styles
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to di...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Output styles
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Output styles change how Claude responds, not what Claude knows. They modify the system prompt to set role, tone, and output format. Use one when you keep re-prompting for the same voice or format every turn, or when you want Claude to act as something other than a software engineer.
A custom output style adds your instructions to the system prompt and lets you choose whether to keep Claude Code’s built-in software engineering instructions. Keep them when you’re changing how Claude communicates but still coding, like always answering with a diagram. Leave them out when Claude isn’t doing software engineering at all, like a writing assistant or data analyst.
For instructions about your project, conventions, or codebase, use
CLAUDE.md
instead.
​
Built-in output styles
Claude Code’s
Default
output style is the existing system prompt, designed to help you complete software engineering tasks efficiently.
There are three additional built-in output styles:
Proactive
: Claude executes immediately, makes reasonable assumptions instead of pausing for routine decisions, and prefers action over planning. This applies the same guidance as
auto mode
without changing your permission mode, so you still see permission prompts before tools run.
Explanatory
: Provides educational “Insights” in between helping you complete software engineering tasks. Helps you understand implementation choices and codebase patterns.
Learning
: Collaborative, learn-by-doing mode where Claude will not only share “Insights” while coding, but also ask you to contribute small, strategic pieces of code yourself. Claude Code will add
TODO(human)
markers in your code for you to implement.
​
Change your output style
Run
/config
and select
Output style
to pick a style from a menu. Your selection is saved to
.claude/settings.local.json
at the
local project level
.
To set a style without the menu, edit the
outputStyle
field directly in a settings file:
{
"outputStyle"
:
"Explanatory"
}
Because the output style is set in the system prompt at session start, changes take effect the next time you start a new session. This keeps the system prompt stable throughout a conversation so prompt caching can reduce latency and cost.
​
Create a custom output style
A custom output style is a Markdown file: frontmatter for metadata, then the instructions to add to the system prompt.
1
Create a Markdown file
Save it at one of three levels. The file name becomes the style name unless you set
name
in the frontmatter.
User:
~/.claude/output-styles
Project:
.claude/output-styles
Managed policy:
.claude/output-styles
inside the
managed settings directory
2
Add frontmatter and instructions
Decide whether to keep Claude Code’s software engineering instructions. Set
keep-coding-instructions: true
if you’re changing how Claude communicates but still want it coding the same way. Leave it out if Claude won’t be doing software engineering.
This example leads every explanation with a diagram while keeping Claude’s coding behavior:
---
name
:
Diagrams first
description
:
Lead every explanation with a diagram
keep-coding-instructions
:
true
---
When explaining code, architecture, or data flow, start with a Mermaid diagram showing the structure, then explain in prose.
## Diagram conventions
Use
`flowchart TD`
for control flow and
`sequenceDiagram`
for request paths. Keep diagrams under 15 nodes.
3
Switch to your style
Run
/config
and select your style under
Output style
. It takes effect the next time you start a session.
Plugins
can also ship output styles in an
output-styles/
directory.
​
Frontmatter
Output style files support these frontmatter fields:
Frontmatter
Purpose
Default
name
Name of the output style, if not the file name
Inherits from file name
description
Description of the output style, shown in the
/config
picker
None
keep-coding-instructions
Keep Claude Code’s built-in software engineering instructions
false
force-for-plugin
Plugin output styles only: apply this style automatically whenever the plugin is enabled, without requiring users to select it. Overrides the user’s
outputStyle
setting. If multiple enabled plugins set this, Claude Code uses the first one loaded.
false
​
How output styles work
Output styles directly modify Claude Code’s system prompt.
All output styles have their own custom instructions added to the end of the system prompt.
All output styles trigger reminders for Claude to adhere to the output style instructions during the conversation.
Custom output styles leave out Claude Code’s built-in software engineering instructions, such as how to scope changes, write comments, and verify work, unless
keep-coding-instructions
is set to
true
.
Token usage depends on the style. Adding instructions to the system prompt increases input tokens, though prompt caching reduces this cost after the first request in a session. The built-in Explanatory and Learning styles produce longer responses than Default by design, which increases output tokens. For custom styles, output token usage depends on what your instructions tell Claude to produce.
​
Comparisons to related features
Several features customize how Claude Code behaves. Output styles modify the system prompt directly and apply to every response. The others add instructions without changing the default system prompt, or scope them to a specific task.
Feature
How it works
Use it when
Output styles
Modifies the system prompt
You want a different role, tone, or default response format every turn
CLAUDE.md
Adds a user message after the system prompt
Claude should always know your project conventions and codebase context
--append-system-prompt
Appends to the system prompt without removing anything
You want a one-off addition for a single invocation
Agents
Runs a subagent with its own system prompt, model, and tools
You want a separately scoped helper for a focused task
Skills
Loads task-specific instructions when invoked or relevant
You have a reusable workflow
​
Related resources
Settings
: where the
outputStyle
field lives and how settings precedence works
Permission modes
: the Proactive style mirrors auto mode without changing your permission mode
Plugins
: package and distribute output styles alongside skills, hooks, and agents
Debug your configuration
: diagnose why an output style isn’t taking effect
Was this page helpful?
Yes
No
Speed up responses with fast mode
Terminal configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/output-styles" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Output styles
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to di...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Output styles
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Output styles change how Claude responds, not what Claude knows. They modify the system prompt to set role, tone, and output format. Use one when you keep re-prompting for the same voice or format every turn, or when you want Claude to act as something other than a software engineer.
A custom output style adds your instructions to the system prompt and lets you choose whether to keep Claude Code’s built-in software engineering instructions. Keep them when you’re changing how Claude communicates but still coding, like always answering with a diagram. Leave them out when Claude isn’t doing software engineering at all, like a writing assistant or data analyst.
For instructions about your project, conventions, or codebase, use
CLAUDE.md
instead.
​
Built-in output styles
Claude Code’s
Default
output style is the existing system prompt, designed to help you complete software engineering tasks efficiently.
There are three additional built-in output styles:
Proactive
: Claude executes immediately, makes reasonable assumptions instead of pausing for routine decisions, and prefers action over planning. This applies the same guidance as
auto mode
without changing your permission mode, so you still see permission prompts before tools run.
Explanatory
: Provides educational “Insights” in between helping you complete software engineering tasks. Helps you understand implementation choices and codebase patterns.
Learning
: Collaborative, learn-by-doing mode where Claude will not only share “Insights” while coding, but also ask you to contribute small, strategic pieces of code yourself. Claude Code will add
TODO(human)
markers in your code for you to implement.
​
Change your output style
Run
/config
and select
Output style
to pick a style from a menu. Your selection is saved to
.claude/settings.local.json
at the
local project level
.
To set a style without the menu, edit the
outputStyle
field directly in a settings file:
{
"outputStyle"
:
"Explanatory"
}
Because the output style is set in the system prompt at session start, changes take effect the next time you start a new session. This keeps the system prompt stable throughout a conversation so prompt caching can reduce latency and cost.
​
Create a custom output style
A custom output style is a Markdown file: frontmatter for metadata, then the instructions to add to the system prompt.
1
Create a Markdown file
Save it at one of three levels. The file name becomes the style name unless you set
name
in the frontmatter.
User:
~/.claude/output-styles
Project:
.claude/output-styles
Managed policy:
.claude/output-styles
inside the
managed settings directory
2
Add frontmatter and instructions
Decide whether to keep Claude Code’s software engineering instructions. Set
keep-coding-instructions: true
if you’re changing how Claude communicates but still want it coding the same way. Leave it out if Claude won’t be doing software engineering.
This example leads every explanation with a diagram while keeping Claude’s coding behavior:
---
name
:
Diagrams first
description
:
Lead every explanation with a diagram
keep-coding-instructions
:
true
---
When explaining code, architecture, or data flow, start with a Mermaid diagram showing the structure, then explain in prose.
## Diagram conventions
Use
`flowchart TD`
for control flow and
`sequenceDiagram`
for request paths. Keep diagrams under 15 nodes.
3
Switch to your style
Run
/config
and select your style under
Output style
. It takes effect the next time you start a session.
Plugins
can also ship output styles in an
output-styles/
directory.
​
Frontmatter
Output style files support these frontmatter fields:
Frontmatter
Purpose
Default
name
Name of the output style, if not the file name
Inherits from file name
description
Description of the output style, shown in the
/config
picker
None
keep-coding-instructions
Keep Claude Code’s built-in software engineering instructions
false
force-for-plugin
Plugin output styles only: apply this style automatically whenever the plugin is enabled, without requiring users to select it. Overrides the user’s
outputStyle
setting. If multiple enabled plugins set this, Claude Code uses the first one loaded.
false
​
How output styles work
Output styles directly modify Claude Code’s system prompt.
All output styles have their own custom instructions added to the end of the system prompt.
All output styles trigger reminders for Claude to adhere to the output style instructions during the conversation.
Custom output styles leave out Claude Code’s built-in software engineering instructions, such as how to scope changes, write comments, and verify work, unless
keep-coding-instructions
is set to
true
.
Token usage depends on the style. Adding instructions to the system prompt increases input tokens, though prompt caching reduces this cost after the first request in a session. The built-in Explanatory and Learning styles produce longer responses than Default by design, which increases output tokens. For custom styles, output token usage depends on what your instructions tell Claude to produce.
​
Comparisons to related features
Several features customize how Claude Code behaves. Output styles modify the system prompt directly and apply to every response. The others add instructions without changing the default system prompt, or scope them to a specific task.
Feature
How it works
Use it when
Output styles
Modifies the system prompt
You want a different role, tone, or default response format every turn
CLAUDE.md
Adds a user message after the system prompt
Claude should always know your project conventions and codebase context
--append-system-prompt
Appends to the system prompt without removing anything
You want a one-off addition for a single invocation
Agents
Runs a subagent with its own system prompt, model, and tools
You want a separately scoped helper for a focused task
Skills
Loads task-specific instructions when invoked or relevant
You have a reusable workflow
​
Related resources
Settings
: where the
outputStyle
field lives and how settings precedence works
Permission modes
: the Proactive style mirrors auto mode without changing your permission mode
Plugins
: package and distribute output styles alongside skills, hooks, and agents
Debug your configuration
: diagnose why an output style isn’t taking effect
Was this page helpful?
Yes
No
Speed up responses with fast mode
Terminal configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/output-styles" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 15 · April 6–10, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w15</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w15</guid>
  <pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 15 · April 6–10, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.92 → v2.1.101
4 features ·...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 15 · April 6–10, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.92 → v2.1.101
4 features · April 6–10
Ultraplan
research preview
Kick off plan mode in the cloud from your terminal, then review the result in your browser. Claude drafts the plan in a Claude Code on the web session while your terminal stays free; when it’s ready you comment on individual sections, ask for revisions, and choose to execute remotely or send it back to your CLI. As of v2.1.101 the first run auto-creates a default cloud environment, so there’s no web setup step before you can try it.
Run the command, or just include the keyword in any prompt:
Claude Code
> /ultraplan migrate the auth service from sessions to JWTs
Ultraplan guide
Monitor tool
v2.1.98
A new built-in tool that spawns a background watcher and streams its events into the conversation: each event lands as a new transcript message that Claude reacts to immediately. Tail a training run, babysit a PR’s CI, or auto-fix a dev server crash the moment it happens, all without a Bash sleep loop holding the turn open.
Ask Claude to watch something while you keep working:
Claude Code
> Tail server.log in the background and tell me the moment a 5xx shows up
This pairs with
/loop
, which now self-paces: omit the interval and Claude schedules the next tick based on the task, or reaches for the Monitor tool to skip polling altogether.
Claude Code
> /loop check CI on my PR
Monitor tool reference
/autofix-pr
CLI
PR auto-fix landed on the web in Week 13. Now you can turn it on without leaving your terminal:
/autofix-pr
infers the open PR for your current branch and enables auto-fix for it on Claude Code on the web in one step. Push your branch, run the command, walk away; Claude watches CI and review comments and pushes fixes until it’s green.
Run it from the PR’s branch:
Claude Code
> /autofix-pr
Auto-fix pull requests
/team-onboarding
v2.1.101
Generates a teammate ramp-up guide from your local Claude Code usage. Run it in a project you know well and hand the output to a new teammate so they can replay your setup instead of starting from defaults.
Run it from a project you’ve spent real time in:
Claude Code
> /team-onboarding
Commands reference
Other wins
Focus view: press
Ctrl+O
in flicker-free mode to collapse the view to your last prompt, a one-line tool summary with diffstats, and Claude’s final response
Guided
Bedrock
and
Vertex AI
setup wizards on the login screen: pick “3rd-party platform” for step-by-step auth, region, credential check, and model pinning
/agents
gets a tabbed layout: a Running tab shows live subagents with a
● N running
count, plus Run agent and View running instance actions in the Library tab
Default effort level is now
high
for API-key, Bedrock, Vertex, Foundry, Team, and Enterprise users (control with
/effort
)
/cost
shows a per-model and cache-hit breakdown for subscription users
/release-notes
is now an interactive version picker
Status line: new
refreshInterval
setting re-runs the command every N seconds, and
workspace.git_worktree
in the JSON input
CLAUDE_CODE_PERFORCE_MODE
: Edit/Write fail on read-only files with a
p4 edit
hint instead of silently overwriting
OS CA certificate store is now trusted by default, so enterprise TLS proxies work without extra setup (
CLAUDE_CODE_CERT_STORE=bundled
to opt out)
Amazon Bedrock powered by Mantle: set
CLAUDE_CODE_USE_MANTLE=1
Hardened Bash tool permissions: backslash-escaped flags, env-var prefixes,
/dev/tcp
redirects, and compound commands now prompt correctly
UserPromptSubmit
hooks can set the session title via
hookSpecificOutput.sessionTitle
Full changelog for v2.1.92–v2.1.101 →
Was this page helpful?
Yes
No
Week 16 · Apr 13–17
Week 14 · Mar 30 – Apr 3
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w15" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 15 · April 6–10, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.92 → v2.1.101
4 features ·...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 15 · April 6–10, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.92 → v2.1.101
4 features · April 6–10
Ultraplan
research preview
Kick off plan mode in the cloud from your terminal, then review the result in your browser. Claude drafts the plan in a Claude Code on the web session while your terminal stays free; when it’s ready you comment on individual sections, ask for revisions, and choose to execute remotely or send it back to your CLI. As of v2.1.101 the first run auto-creates a default cloud environment, so there’s no web setup step before you can try it.
Run the command, or just include the keyword in any prompt:
Claude Code
> /ultraplan migrate the auth service from sessions to JWTs
Ultraplan guide
Monitor tool
v2.1.98
A new built-in tool that spawns a background watcher and streams its events into the conversation: each event lands as a new transcript message that Claude reacts to immediately. Tail a training run, babysit a PR’s CI, or auto-fix a dev server crash the moment it happens, all without a Bash sleep loop holding the turn open.
Ask Claude to watch something while you keep working:
Claude Code
> Tail server.log in the background and tell me the moment a 5xx shows up
This pairs with
/loop
, which now self-paces: omit the interval and Claude schedules the next tick based on the task, or reaches for the Monitor tool to skip polling altogether.
Claude Code
> /loop check CI on my PR
Monitor tool reference
/autofix-pr
CLI
PR auto-fix landed on the web in Week 13. Now you can turn it on without leaving your terminal:
/autofix-pr
infers the open PR for your current branch and enables auto-fix for it on Claude Code on the web in one step. Push your branch, run the command, walk away; Claude watches CI and review comments and pushes fixes until it’s green.
Run it from the PR’s branch:
Claude Code
> /autofix-pr
Auto-fix pull requests
/team-onboarding
v2.1.101
Generates a teammate ramp-up guide from your local Claude Code usage. Run it in a project you know well and hand the output to a new teammate so they can replay your setup instead of starting from defaults.
Run it from a project you’ve spent real time in:
Claude Code
> /team-onboarding
Commands reference
Other wins
Focus view: press
Ctrl+O
in flicker-free mode to collapse the view to your last prompt, a one-line tool summary with diffstats, and Claude’s final response
Guided
Bedrock
and
Vertex AI
setup wizards on the login screen: pick “3rd-party platform” for step-by-step auth, region, credential check, and model pinning
/agents
gets a tabbed layout: a Running tab shows live subagents with a
● N running
count, plus Run agent and View running instance actions in the Library tab
Default effort level is now
high
for API-key, Bedrock, Vertex, Foundry, Team, and Enterprise users (control with
/effort
)
/cost
shows a per-model and cache-hit breakdown for subscription users
/release-notes
is now an interactive version picker
Status line: new
refreshInterval
setting re-runs the command every N seconds, and
workspace.git_worktree
in the JSON input
CLAUDE_CODE_PERFORCE_MODE
: Edit/Write fail on read-only files with a
p4 edit
hint instead of silently overwriting
OS CA certificate store is now trusted by default, so enterprise TLS proxies work without extra setup (
CLAUDE_CODE_CERT_STORE=bundled
to opt out)
Amazon Bedrock powered by Mantle: set
CLAUDE_CODE_USE_MANTLE=1
Hardened Bash tool permissions: backslash-escaped flags, env-var prefixes,
/dev/tcp
redirects, and compound commands now prompt correctly
UserPromptSubmit
hooks can set the session title via
hookSpecificOutput.sessionTitle
Full changelog for v2.1.92–v2.1.101 →
Was this page helpful?
Yes
No
Week 16 · Apr 13–17
Week 14 · Mar 30 – Apr 3
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w15" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Security</title>
  <link>https://code.claude.com/docs/en/security</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/security</guid>
  <pubDate>Sun, 22 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Security
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dep...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Security
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
How we approach security
​
Security foundation
Your code’s security is paramount. Claude Code is built with security at its core, developed according to Anthropic’s comprehensive security program. Learn more and access resources (SOC 2 Type 2 report, ISO 27001 certificate, etc.) at
Anthropic Trust Center
.
​
Permission-based architecture
Claude Code uses strict read-only permissions by default. When additional actions are needed (editing files, running tests, executing commands), Claude Code requests explicit permission. Users control whether to approve actions once or allow them automatically.
We designed Claude Code to be transparent and secure. For example, we require approval for bash commands before executing them, giving you direct control. This approach enables users and organizations to configure permissions directly.
For detailed permission configuration, see
Permissions
.
​
Built-in protections
To mitigate risks in agentic systems:
Sandboxed bash tool
:
Sandbox
bash commands with filesystem and network isolation, reducing permission prompts while maintaining security. Enable with
/sandbox
to define boundaries where Claude Code can work autonomously
Write access restriction
: Claude Code can only write to the folder where it was started and its subfolders—it cannot modify files in parent directories without explicit permission. While Claude Code can read files outside the working directory (useful for accessing system libraries and dependencies), write operations are strictly confined to the project scope, creating a clear security boundary
Prompt fatigue mitigation
: Support for allowlisting frequently used safe commands per-user, per-codebase, or per-organization
Accept Edits mode
: Auto-approves file edits and a fixed set of filesystem Bash commands like
mkdir
,
touch
,
rm
,
mv
,
cp
, and
sed
for paths in the working directory. Other Bash commands and out-of-scope paths still prompt
​
User responsibility
Claude Code only has the permissions you grant it. You’re responsible for reviewing proposed code and commands for safety before approval.
​
Protect against prompt injection
Prompt injection is a technique where an attacker attempts to override or manipulate an AI assistant’s instructions by inserting malicious text. Claude Code includes several safeguards against these attacks:
​
Core protections
Permission system
: Sensitive operations require explicit approval
Context-aware analysis
: Detects potentially harmful instructions by analyzing the full request
Input sanitization
: Prevents command injection by processing user inputs
Command blocklist
: Blocks risky commands that fetch arbitrary content from the web like
curl
and
wget
by default. When explicitly allowed, be aware of
permission pattern limitations
​
Privacy safeguards
We have implemented several safeguards to protect your data, including:
Limited retention periods for sensitive information (see the
Privacy Center
to learn more)
Restricted access to user session data
User control over data training preferences. Consumer users can change their
privacy settings
at any time.
For full details, please review our
Commercial Terms of Service
(for Team, Enterprise, and API users) or
Consumer Terms
(for Free, Pro, and Max users) and
Privacy Policy
.
​
Additional safeguards
Network request approval
: Tools that make network requests require user approval by default
Isolated context windows
: Web fetch uses a separate context window to avoid injecting potentially malicious prompts
Trust verification
: First-time codebase runs and new MCP servers require trust verification
Note: Trust verification is disabled when running non-interactively with the
-p
flag. The exception is
--worktree
, which still requires that trust has been accepted for the directory
Command injection detection
: Suspicious bash commands require manual approval even if previously allowlisted
Fail-closed matching
: Unmatched commands default to requiring manual approval
Natural language descriptions
: Complex bash commands include explanations for user understanding
Secure credential storage
: API keys and tokens are encrypted. See
Credential Management
Windows WebDAV security risk
: When running Claude Code on Windows, we recommend against enabling WebDAV or allowing Claude Code to access paths such as
\\*
that may contain WebDAV subdirectories.
WebDAV has been deprecated by Microsoft
due to security risks. Enabling WebDAV may allow Claude Code to trigger network requests to remote hosts, bypassing the permission system.
Best practices for working with untrusted content
:
Review suggested commands before approval
Avoid piping untrusted content directly to Claude
Verify proposed changes to critical files
Use virtual machines (VMs) to run scripts and make tool calls, especially when interacting with external web services
Report suspicious behavior with
/feedback
While these protections significantly reduce risk, no system is completely
immune to all attacks. Always maintain good security practices when working
with any AI tool.
​
MCP security
Claude Code allows users to configure Model Context Protocol (MCP) servers. The list of allowed MCP servers is configured in your source code, as part of Claude Code settings engineers check into source control.
We encourage either writing your own MCP servers or using MCP servers from providers that you trust. You are able to configure Claude Code permissions for MCP servers. Anthropic reviews connectors against its
listing criteria
before adding them to the
Anthropic Directory
, but does not security-audit or manage any MCP server.
​
IDE security
See
VS Code security and privacy
for more information on running Claude Code in an IDE.
​
Cloud execution security
When using
Claude Code on the web
, additional security controls are in place:
Isolated virtual machines
: Each cloud session runs in an isolated, Anthropic-managed VM
Network access controls
: Network access is limited by default and can be configured to be disabled or allow only specific domains
Credential protection
: Authentication is handled through a secure proxy that uses a scoped credential inside the sandbox, which is then translated to your actual GitHub authentication token
Branch restrictions
: Git push operations are restricted to the current working branch
Audit logging
: All operations in cloud environments are logged for compliance and audit purposes
Automatic cleanup
: Cloud environments are automatically terminated after session completion
For more details on cloud execution, see
Claude Code on the web
.
Remote Control
sessions work differently: the web interface connects to a Claude Code process running on your local machine. All code execution and file access stays local, and the same data that flows during any local Claude Code session travels through the Anthropic API over TLS. No cloud VMs or sandboxing are involved. The connection uses multiple short-lived, narrowly scoped credentials, each limited to a specific purpose and expiring independently, to limit the blast radius of any single compromised credential.
​
Security best practices
​
Working with sensitive code
Review all suggested changes before approval
Use project-specific permission settings for sensitive repositories
Consider using
dev containers
for additional isolation
Regularly audit your permission settings with
/permissions
​
Team security
Use
managed settings
to enforce organizational standards
Share approved permission configurations through version control
Train team members on security best practices
Monitor Claude Code usage through
OpenTelemetry metrics
Audit or block settings changes during sessions with
ConfigChange
hooks
​
Reporting security issues
If you discover a security vulnerability in Claude Code:
Do not disclose it publicly
Report it through our
HackerOne program
Include detailed reproduction steps
Allow time for us to address the issue before public disclosure
​
Related resources
Sandboxing
- Filesystem and network isolation for bash commands
Permissions
- Configure permissions and access controls
Monitoring usage
- Track and audit Claude Code activity
Development containers
- Secure, isolated environments
Anthropic Trust Center
- Security certifications and compliance
Was this page helpful?
Yes
No
Plugin dependency versions
Data usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/security" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Security
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dep...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Security
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
How we approach security
​
Security foundation
Your code’s security is paramount. Claude Code is built with security at its core, developed according to Anthropic’s comprehensive security program. Learn more and access resources (SOC 2 Type 2 report, ISO 27001 certificate, etc.) at
Anthropic Trust Center
.
​
Permission-based architecture
Claude Code uses strict read-only permissions by default. When additional actions are needed (editing files, running tests, executing commands), Claude Code requests explicit permission. Users control whether to approve actions once or allow them automatically.
We designed Claude Code to be transparent and secure. For example, we require approval for bash commands before executing them, giving you direct control. This approach enables users and organizations to configure permissions directly.
For detailed permission configuration, see
Permissions
.
​
Built-in protections
To mitigate risks in agentic systems:
Sandboxed bash tool
:
Sandbox
bash commands with filesystem and network isolation, reducing permission prompts while maintaining security. Enable with
/sandbox
to define boundaries where Claude Code can work autonomously
Write access restriction
: Claude Code can only write to the folder where it was started and its subfolders—it cannot modify files in parent directories without explicit permission. While Claude Code can read files outside the working directory (useful for accessing system libraries and dependencies), write operations are strictly confined to the project scope, creating a clear security boundary
Prompt fatigue mitigation
: Support for allowlisting frequently used safe commands per-user, per-codebase, or per-organization
Accept Edits mode
: Auto-approves file edits and a fixed set of filesystem Bash commands like
mkdir
,
touch
,
rm
,
mv
,
cp
, and
sed
for paths in the working directory. Other Bash commands and out-of-scope paths still prompt
​
User responsibility
Claude Code only has the permissions you grant it. You’re responsible for reviewing proposed code and commands for safety before approval.
​
Protect against prompt injection
Prompt injection is a technique where an attacker attempts to override or manipulate an AI assistant’s instructions by inserting malicious text. Claude Code includes several safeguards against these attacks:
​
Core protections
Permission system
: Sensitive operations require explicit approval
Context-aware analysis
: Detects potentially harmful instructions by analyzing the full request
Input sanitization
: Prevents command injection by processing user inputs
Command blocklist
: Blocks risky commands that fetch arbitrary content from the web like
curl
and
wget
by default. When explicitly allowed, be aware of
permission pattern limitations
​
Privacy safeguards
We have implemented several safeguards to protect your data, including:
Limited retention periods for sensitive information (see the
Privacy Center
to learn more)
Restricted access to user session data
User control over data training preferences. Consumer users can change their
privacy settings
at any time.
For full details, please review our
Commercial Terms of Service
(for Team, Enterprise, and API users) or
Consumer Terms
(for Free, Pro, and Max users) and
Privacy Policy
.
​
Additional safeguards
Network request approval
: Tools that make network requests require user approval by default
Isolated context windows
: Web fetch uses a separate context window to avoid injecting potentially malicious prompts
Trust verification
: First-time codebase runs and new MCP servers require trust verification
Note: Trust verification is disabled when running non-interactively with the
-p
flag. The exception is
--worktree
, which still requires that trust has been accepted for the directory
Command injection detection
: Suspicious bash commands require manual approval even if previously allowlisted
Fail-closed matching
: Unmatched commands default to requiring manual approval
Natural language descriptions
: Complex bash commands include explanations for user understanding
Secure credential storage
: API keys and tokens are encrypted. See
Credential Management
Windows WebDAV security risk
: When running Claude Code on Windows, we recommend against enabling WebDAV or allowing Claude Code to access paths such as
\\*
that may contain WebDAV subdirectories.
WebDAV has been deprecated by Microsoft
due to security risks. Enabling WebDAV may allow Claude Code to trigger network requests to remote hosts, bypassing the permission system.
Best practices for working with untrusted content
:
Review suggested commands before approval
Avoid piping untrusted content directly to Claude
Verify proposed changes to critical files
Use virtual machines (VMs) to run scripts and make tool calls, especially when interacting with external web services
Report suspicious behavior with
/feedback
While these protections significantly reduce risk, no system is completely
immune to all attacks. Always maintain good security practices when working
with any AI tool.
​
MCP security
Claude Code allows users to configure Model Context Protocol (MCP) servers. The list of allowed MCP servers is configured in your source code, as part of Claude Code settings engineers check into source control.
We encourage either writing your own MCP servers or using MCP servers from providers that you trust. You are able to configure Claude Code permissions for MCP servers. Anthropic reviews connectors against its
listing criteria
before adding them to the
Anthropic Directory
, but does not security-audit or manage any MCP server.
​
IDE security
See
VS Code security and privacy
for more information on running Claude Code in an IDE.
​
Cloud execution security
When using
Claude Code on the web
, additional security controls are in place:
Isolated virtual machines
: Each cloud session runs in an isolated, Anthropic-managed VM
Network access controls
: Network access is limited by default and can be configured to be disabled or allow only specific domains
Credential protection
: Authentication is handled through a secure proxy that uses a scoped credential inside the sandbox, which is then translated to your actual GitHub authentication token
Branch restrictions
: Git push operations are restricted to the current working branch
Audit logging
: All operations in cloud environments are logged for compliance and audit purposes
Automatic cleanup
: Cloud environments are automatically terminated after session completion
For more details on cloud execution, see
Claude Code on the web
.
Remote Control
sessions work differently: the web interface connects to a Claude Code process running on your local machine. All code execution and file access stays local, and the same data that flows during any local Claude Code session travels through the Anthropic API over TLS. No cloud VMs or sandboxing are involved. The connection uses multiple short-lived, narrowly scoped credentials, each limited to a specific purpose and expiring independently, to limit the blast radius of any single compromised credential.
​
Security best practices
​
Working with sensitive code
Review all suggested changes before approval
Use project-specific permission settings for sensitive repositories
Consider using
dev containers
for additional isolation
Regularly audit your permission settings with
/permissions
​
Team security
Use
managed settings
to enforce organizational standards
Share approved permission configurations through version control
Train team members on security best practices
Monitor Claude Code usage through
OpenTelemetry metrics
Audit or block settings changes during sessions with
ConfigChange
hooks
​
Reporting security issues
If you discover a security vulnerability in Claude Code:
Do not disclose it publicly
Report it through our
HackerOne program
Include detailed reproduction steps
Allow time for us to address the issue before public disclosure
​
Related resources
Sandboxing
- Filesystem and network isolation for bash commands
Permissions
- Configure permissions and access controls
Monitoring usage
- Track and audit Claude Code activity
Development containers
- Secure, isolated environments
Anthropic Trust Center
- Security certifications and compliance
Was this page helpful?
Yes
No
Plugin dependency versions
Data usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/security" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Error reference</title>
  <link>https://code.claude.com/docs/en/errors</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/errors</guid>
  <pubDate>Wed, 18 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Error reference
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troub...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Error reference
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page lists runtime errors Claude Code displays and how to recover from each one, plus what to check when responses seem off without an error. For installation errors such as
command not found
or TLS failures during setup, see
Troubleshoot installation and login
.
These errors and recovery commands apply across the CLI, the
Desktop app
, and
Claude Code on the web
, since all three wrap the same Claude Code CLI. For surface-specific issues, see the troubleshooting section on that surface’s page.
Claude Code calls the Claude API for model responses, so most runtime errors map to an underlying API error code. This page covers what each error means inside Claude Code and how to recover. For the raw HTTP status code definitions, see the
Claude Platform error reference
.
​
Find your error
Match the message you see in your terminal to a section below.
Message
Section
API Error: 500 ... Internal server error
Server errors
API Error: Repeated 529 Overloaded errors
Server errors
Request timed out
Server errors
, or
Network
if the message mentions your internet connection
<model> is temporarily unavailable, so auto mode cannot determine the safety of...
Server errors
Auto mode could not evaluate this action and is blocking it for safety
Server errors
Auto mode classifier transcript exceeded context window
Server errors
You've hit your session limit
/
You've hit your weekly limit
Usage limits
Server is temporarily limiting requests
Usage limits
Request rejected (429)
Usage limits
Credit balance is too low
Usage limits
Not logged in · Please run /login
Authentication
Invalid API key
Authentication
This organization has been disabled
Authentication
Routines are disabled by your organization's policy
Authentication
OAuth token revoked
/
OAuth token has expired
Authentication
does not meet scope requirement user:profile
Authentication
Unable to connect to API
Network
SSL certificate verification failed
Network
403
with
x-deny-reason: host_not_allowed
in a cloud or routine session
Network
Prompt is too long
Request errors
Error during compaction: Conversation too long
Request errors
Request too large
Request errors
Image was too large
Request errors
PDF too large
/
PDF is password protected
Request errors
Extra inputs are not permitted
Request errors
There's an issue with the selected model
Request errors
Claude Opus is not available with the Claude Pro plan
Request errors
thinking.type.enabled is not supported for this model
Request errors
max_tokens must be greater than thinking.budget_tokens
Request errors
API Error: 400 due to tool use concurrency issues
Request errors
Responses seem lower quality than usual
Response quality
​
Automatic retries
Claude Code retries transient failures before showing you an error. Server errors, overloaded responses, request timeouts, temporary 429 throttles, and dropped connections are all retried up to 10 times with exponential backoff. While retrying, the spinner shows a
Retrying in Ns · attempt x/y
countdown.
When you see one of the errors on this page, those retries have already been exhausted. You can tune the behavior with two environment variables:
Variable
Default
Effect
CLAUDE_CODE_MAX_RETRIES
10
Number of retry attempts. Lower it to surface failures faster in scripts; raise it to wait through longer incidents.
API_TIMEOUT_MS
600000
Per-request timeout in milliseconds. Raise it for slow networks or proxies.
​
Server errors
These errors come from Anthropic infrastructure rather than your account or request.
​
API Error: 500 Internal server error
Claude Code shows the raw API response body for any 5xx status. The example below shows a 500 response:
API Error: 500 {"type":"error","error":{"type":"api_error","message":"Internal server error"}} · check status.claude.com
This indicates an unexpected failure inside the API. It is not caused by your prompt, settings, or account.
What to do:
Check
status.claude.com
for active incidents
Wait a minute, then send your message again. Your original message is still in the conversation, so for a long prompt you can type
try again
instead of pasting the whole thing.
If the error persists with no posted incident, run
/feedback
so Anthropic can investigate with your request details. See
Report an error
if
/feedback
is unavailable in your environment.
​
API Error: Repeated 529 Overloaded errors
The API is temporarily at capacity across all users. Claude Code has already retried several times before showing this message:
API Error: Repeated 529 Overloaded errors · check status.claude.com
A 529 is not your usage limit and does not count against your quota.
What to do:
Check
status.claude.com
for capacity notices
Try again in a few minutes
Run
/model
and switch to a different model to keep working, since capacity is tracked per model. Claude Code prompts you to do this when one model is under particularly high load, for example
Opus is experiencing high load, please use /model to switch to Sonnet
.
​
Request timed out
The API did not respond before the connection deadline.
Request timed out
This can happen during periods of high load or when a very large response is being generated. The default request timeout is 10 minutes.
What to do:
Retry the request
For long-running tasks, break the work into smaller prompts
If a slow network or proxy is the cause, raise
API_TIMEOUT_MS
as described in
Automatic retries
If timeouts are frequent and your network is otherwise healthy, see
Network and connection errors
below
​
Auto mode cannot determine the safety of an action
The model that
auto mode
uses to classify actions could not produce a decision, so auto mode did not approve the action automatically. The message you see depends on why the classifier failed.
Reads, searches, and edits inside your working directory skip the classifier, so they keep working in all of these cases.
When the classifier model is overloaded:
<model> is temporarily unavailable, so auto mode cannot determine the safety of <tool> right now. Wait briefly and then try this action again.
What to do:
Retry after a few seconds; Claude sees the same message and usually retries on its own
If retries keep failing, continue with read-only tasks and come back to the blocked action later
This is transient and unrelated to
auto mode eligibility
; you do not need to change settings
When the classifier returned an unparseable response:
Auto mode could not evaluate this action and is blocking it for safety — run with --debug for details
What to do:
Retry the action; this usually succeeds on the next attempt
Run
claude --debug
and repeat the action to see the underlying classifier response in the debug log
When the conversation has grown larger than the classifier’s context window:
Auto mode classifier transcript exceeded context window — falling back to manual approval (try /compact to reduce conversation size)
In an interactive session, auto mode falls back to a normal permission prompt for that action so you can approve or deny it manually. In
non-interactive mode
the run aborts because the transcript only grows and retrying cannot succeed.
What to do:
Approve or deny the action in the prompt that appears
Run
/compact
to reduce the conversation size so subsequent actions fit within the classifier window again
​
Usage limits
These errors mean a quota tied to your account or plan has been reached. They are distinct from
server errors
, which affect everyone.
​
You’ve hit your session limit
Subscription plans include a rolling usage allowance. When it runs out you see one of these messages:
You've hit your session limit · resets 3:45pm
You've hit your weekly limit · resets Mon 12:00am
You've hit your Opus limit · resets 3:45pm
Claude Code blocks further requests until the reset time shown in the message.
What to do:
Wait for the reset time shown in the error
Run
/usage
to see your plan limits and when they reset
Run
/extra-usage
to buy additional usage on Pro and Max, or to request it from your admin on Team and Enterprise. See
Extra usage for paid plans
for how this is billed.
To upgrade your plan for higher base limits, see
claude.com/pricing
To watch your remaining allowance before you hit the limit, add the
rate_limits
fields to a
custom status line
, or in the Desktop app click the
usage ring
next to the model picker.
​
Server is temporarily limiting requests
The API applied a short-lived throttle that is unrelated to your plan quota.
API Error: Server is temporarily limiting requests (not your usage limit)
This is
retried automatically
before being shown.
What to do:
Wait briefly and try again
Check
status.claude.com
if it persists
​
Request rejected (429)
You have hit the rate limit configured for your API key, Amazon Bedrock project, or Google Vertex AI project.
API Error: Request rejected (429) · this may be a temporary capacity issue
What to do:
Run
/status
and confirm the active credential is the one you expect. A stray
ANTHROPIC_API_KEY
in your environment can route requests through a low-tier key instead of your subscription.
Check your provider console for the active limits and request a higher tier if needed
For Anthropic API keys, see the
rate limits reference
for how tiers work and how to set per-workspace caps
Reduce concurrency: lower
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
, avoid running many parallel subagents, or switch to a smaller model with
/model
for high-volume scripted runs
​
Credit balance is too low
Your Console organization has run out of prepaid credits.
Credit balance is too low
What to do:
Add credits at
platform.claude.com/settings/billing
, and consider enabling auto-reload there so the balance refills before it hits zero
Switch to subscription authentication with
/login
if you have a Pro, Max, Team, or Enterprise plan
Set per-workspace spend caps in the Console to prevent a single project from draining the org balance. See
Manage costs effectively
.
​
Authentication errors
These errors mean Claude Code cannot prove who you are to the API. Run
/status
at any time to see which credential is currently active.
​
Not logged in
No valid credential is available for this session.
Not logged in · Please run /login
What to do:
Run
/login
to authenticate with your Claude subscription or Console account
If you expected an environment variable to authenticate you, confirm
ANTHROPIC_API_KEY
is set and exported in the shell where you launched
claude
For CI or automation where interactive login is not possible, configure an
apiKeyHelper
script that fetches a key at startup
See
Authentication precedence
to understand which credential wins when several are present
If you are prompted to log in repeatedly, see
Not logged in or token expired
for system clock and macOS Keychain fixes.
​
Invalid API key
The
ANTHROPIC_API_KEY
environment variable or
apiKeyHelper
script returned a key the API rejected.
Invalid API key · Fix external API key
What to do:
Check for typos and confirm the key has not been revoked in the
Console
Run
env | grep ANTHROPIC
in the same shell. Tools like direnv, dotenv shell plugins, and IDE terminals can load a stale key from a
.env
file in your project without you setting it explicitly.
Unset
ANTHROPIC_API_KEY
and run
/login
to use subscription auth instead
If the key comes from an
apiKeyHelper
script, run the script directly to confirm it prints a valid key on stdout
Run
/status
to confirm which credential source Claude Code is actually using
​
This organization has been disabled
A stale
ANTHROPIC_API_KEY
from a disabled Console organization is overriding your subscription login.
Your ANTHROPIC_API_KEY belongs to a disabled organization · Unset the environment variable to use your other credentials
API Error: 400 ... This organization has been disabled.
Environment variables take precedence over
/login
, so a key exported in your shell profile or loaded from a
.env
file is used even when you have a working Pro or Max subscription. In non-interactive mode (
-p
), the key is always used when present.
What to do:
Unset
ANTHROPIC_API_KEY
in the current shell and remove it from your shell profile, then relaunch
claude
Run
/status
afterward to confirm the active credential is your subscription
If no environment variable is set and the error persists, the disabled organization is the one tied to your
/login
. Contact support or sign in with a different account.
​
Routines are disabled by your organization’s policy
Your Team or Enterprise admin has turned off routines at the organization level. The error appears when you try to create or run a routine, including from
/schedule
and the
Routines
UI on claude.ai/code.
Routines are disabled by your organization's policy.
This is a server-side setting, so it cannot be overridden from local settings, environment variables, or CLI flags.
What to do:
Ask your admin to enable the
Routines
toggle at
claude.ai/admin-settings/claude-code
For one-off scheduled work that does not require organization-level routines, see
scheduled tasks
​
OAuth token revoked or expired
Your saved login is no longer valid. A revoked token means you signed out everywhere or an admin removed access; an expired token means the automatic refresh failed mid-session.
OAuth token revoked · Please run /login
OAuth token has expired · Please run /login
API Error: 401 ... authentication_error
What to do:
Run
/login
to sign in again
If the error returns within the same session after re-authenticating, run
/logout
first to fully clear the stored token, then
/login
For repeated prompts to log in across launches, see the system clock and macOS Keychain checks in
Troubleshooting
For other failures including
403 Forbidden
and OAuth browser issues, see
Login and authentication
​
OAuth scope requirement
The stored token predates a permission scope that a newer feature needs. You see this most often from
/usage
and the status line usage indicator:
OAuth token does not meet scope requirement: user:profile
What to do:
Run
/login
to mint a new token with the current scopes. You do not need to log out first.
​
Network and connection errors
These errors mean a network request from Claude Code failed to reach its destination. They usually originate in your local network, proxy, or firewall, or in the cloud environment’s network policy.
​
Unable to connect to API
The TCP connection to the API failed or never completed.
Unable to connect to API. Check your internet connection
Unable to connect to API (ECONNREFUSED)
Unable to connect to API (ECONNRESET)
Unable to connect to API (ETIMEDOUT)
fetch failed
Request timed out. Check your internet connection and proxy settings
Common causes include no internet access, a VPN that blocks
api.anthropic.com
, or a required corporate proxy that is not configured.
What to do:
Confirm you can reach the API host from the same shell by running
curl -I https://api.anthropic.com
. On Windows PowerShell use
curl.exe -I https://api.anthropic.com
so the built-in
Invoke-WebRequest
alias is not used.
If you are behind a corporate proxy, set
HTTPS_PROXY
before launching Claude Code and see
Network configuration
If you route through an LLM gateway or relay, set
ANTHROPIC_BASE_URL
to its address. See
LLM gateway configuration
for setup.
Ensure your firewall allows the hosts listed in
Network access requirements
Intermittent failures are
retried automatically
; persistent failures point to a local network issue
If
curl
succeeds but Claude Code still fails, the cause is usually something between the runtime and the network rather than the network itself:
On Linux and WSL, check
/etc/resolv.conf
for an unreachable nameserver. WSL in particular can inherit a broken resolver from the host.
On macOS, a VPN client that was disconnected or uninstalled can leave a tunnel interface or routing rule behind. Check
ifconfig
for stale
utun
interfaces and remove the VPN’s network extension in System Settings.
Docker Desktop and similar container runtimes can intercept outbound traffic. Quit them and retry to rule this out.
​
SSL certificate errors
A proxy or security appliance on your network is intercepting TLS traffic with its own certificate, and Claude Code does not trust it.
Unable to connect to API: SSL certificate verification failed. Check your proxy or corporate SSL certificates
Unable to connect to API: Self-signed certificate detected
What to do:
Export your organization’s CA bundle and point Claude Code at it with
NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem
See
Network configuration
for full setup instructions
Do not set
NODE_TLS_REJECT_UNAUTHORIZED=0
, which disables certificate validation entirely
​
Host not allowed in a cloud session
An outbound HTTP request from a cloud session or routine was blocked by the environment’s network policy.
HTTP 403
x-deny-reason: host_not_allowed
You may also see a TLS certificate that doesn’t match the destination’s real certificate. The cloud environment routes outbound traffic through a proxy that enforces the network policy, so a mismatched certificate means the proxy terminated the connection, not the destination.
This is not a client-side network problem. Cloud sessions and
routines
run inside a sandboxed environment whose outbound traffic is filtered to the environment’s allowlist. The
Default
environment uses
Trusted
access, which permits the
default allowlist
of package registries, cloud provider APIs, container registries, and common development domains but blocks everything else.
What to do:
Open the routine for editing, or start a cloud session. Select the cloud icon showing your environment’s name, such as
Default
, to open the selector. Hover over your environment and click the settings icon.
In the
Update cloud environment
dialog, change
Network access
from
Trusted
to
Custom
, then add the blocked domain to
Allowed domains
. Enter one domain per line. Check
Also include default list of common package managers
to keep the
default allowlist
alongside your custom domains. Select
Full
instead if you want unrestricted access.
Click
Save changes
. The next run uses the updated allowlist.
See
Network access
for access levels and the default allowlist. Local CLI sessions are not affected by this policy.
​
Request errors
These errors mean the API received your request but rejected its content.
​
Prompt is too long
The conversation plus attached files exceeds the model’s context window.
Prompt is too long
What to do:
Run
/compact
to summarize earlier turns and free space, or
/clear
to start fresh
Run
/context
to see a breakdown of what is consuming the window: system prompt, tools, memory files, and messages
Disable MCP servers you are not using with
/mcp disable <name>
to remove their tool definitions from context
Trim large
CLAUDE.md
memory files, or move instructions into
path-scoped rules
that load only when relevant
Subagents inherit every MCP tool definition from the parent session, which can fill their context window before the first turn. Disable MCP servers you are not using before spawning subagents.
Auto-compact is on by default and normally prevents this error. If you have set
DISABLE_AUTO_COMPACT
, re-enable it or run
/compact
manually before the window fills.
See
Explore the context window
for an interactive view of how context fills up.
​
Error during compaction: Conversation too long
/compact
itself failed because there is not enough free context to hold the summary it produces.
Error during compaction: Conversation too long. Press esc twice to go up a few messages and try again.
This can happen when the window is already full at the moment auto-compact triggers, or when you run
/compact
after seeing
Prompt is too long
.
What to do:
Press Esc twice to open the message list and step back several turns. This drops the most recent messages from context. Then run
/compact
again.
If stepping back does not free enough space, run
/clear
to start a fresh session. Your previous conversation is preserved and can be reopened with
/resume
.
​
Request too large
The raw request body exceeded the API’s byte limit before tokenization, usually because of a large pasted file or attachment.
Request too large (max 30 MB). Double press esc to go back and remove or shrink the attached content.
This is a size limit on the HTTP request, separate from the
context window limit
.
What to do:
Press Esc twice and step back past the turn that added the oversized content
Reference large files by path instead of pasting their contents, so Claude can read them in chunks
For images, see
Image was too large
below
​
Image was too large
A pasted or attached image exceeds the API’s size or dimension limits.
Image was too large. Double press esc to go back and try again with a smaller image.
API Error: 400 ... image dimensions exceed max allowed size
The image stays in conversation history after the error, so every subsequent message fails with the same error until you remove it.
What to do:
Press Esc twice and step back past the turn where the image was added
Resize the image before pasting. The API accepts images up to 8000 pixels on the longest edge for a single image, or 2000 pixels when many images are in context.
Take a tighter screenshot of the relevant region instead of the full screen
​
PDF errors
The PDF you attached could not be processed.
PDF too large (max 100 pages, 32 MB). Try splitting it or extracting text first.
PDF is password protected. Try removing protection or extracting text first.
The PDF file was not valid. Try converting to a different format first.
What to do:
For oversized PDFs, ask Claude to read a page range with the Read tool instead of attaching the whole file, or extract text with a tool like
pdftotext
and reference the output file by path
For protected or invalid PDFs, remove the password or re-export the file from its source application, then try again
​
Extra inputs are not permitted
A proxy or LLM gateway between Claude Code and the API stripped the
anthropic-beta
request header, so the API rejected fields that depend on it.
API Error: 400 ... Extra inputs are not permitted ... context_management
API Error: 400 ... Extra inputs are not permitted ... tools.0.custom.input_examples
API Error: 400 ... Unexpected value(s) for the `anthropic-beta` header
Claude Code sends beta-only fields such as
context_management
,
effort
, and tool
input_examples
alongside an
anthropic-beta
header that enables them. When a gateway forwards the body but drops the header, the API sees fields it does not recognize.
What to do:
Configure your gateway to forward the
anthropic-beta
header. See
LLM gateway configuration
.
As a fallback, set
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
before launching. This disables features that require the beta header so requests succeed through a gateway that cannot forward it.
​
There’s an issue with the selected model
The configured model name was not recognized or your account lacks access to it.
There's an issue with the selected model (claude-...). It may not exist or you may not have access to it. Run /model to select a different one.
What to do:
Run
/model
to pick from models available to your account
Use an alias such as
sonnet
or
opus
instead of a full versioned ID. Aliases track the latest release so they do not go stale. See
Model configuration
.
If the wrong model keeps coming back, a stale ID is set somewhere. Check in
priority order
: the
--model
flag, the
ANTHROPIC_MODEL
environment variable, then the
model
field in
.claude/settings.local.json
, your project’s
.claude/settings.json
, and
~/.claude/settings.json
. Remove the stale value and Claude Code falls back to your account default.
For Vertex AI deployments, see
Vertex AI troubleshooting
.
​
Claude Opus is not available with the Claude Pro plan
Your active subscription plan does not include the model you selected.
Claude Opus is not available with the Claude Pro plan · Select a different model in /model
What to do:
Run
/model
and select a model your plan includes
If you upgraded your plan recently and still see this, run
/logout
then
/login
. The stored token reflects your plan at the time you signed in, so upgrading on the web does not take effect in an existing session until you re-authenticate.
See
claude.com/pricing
for which models each plan includes
​
thinking.type.enabled is not supported for this model
Your Claude Code version is older than the minimum for Opus 4.7. The CLI sent a thinking configuration the model no longer accepts.
API Error: 400 ... "thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
What to do:
Run
claude update
to upgrade to v2.1.111 or later, then restart Claude Code
If you cannot upgrade, run
/model
and select Opus 4.6 or Sonnet instead
If you hit this in the Agent SDK, see
SDK troubleshooting
​
Thinking budget exceeds output limit
The configured extended thinking budget exceeds the maximum response length, so there is no room left for the actual answer.
API Error: 400 ... max_tokens must be greater than thinking.budget_tokens
Claude Code adjusts these values automatically on the Anthropic API. You typically see this error on Amazon Bedrock or Google Vertex AI when
MAX_THINKING_TOKENS
is set higher than the provider’s output limit, or when plan mode raises the thinking budget.
What to do:
Lower
MAX_THINKING_TOKENS
, or raise
CLAUDE_CODE_MAX_OUTPUT_TOKENS
above the thinking budget
See
Extended thinking
for how the budget interacts with output length
​
Tool use or thinking block mismatch
The conversation history reached the API in an inconsistent state, usually after a tool call was interrupted or a turn was edited mid-stream.
API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.
API Error: 400 ... unexpected `tool_use_id` found in `tool_result` blocks
API Error: 400 ... thinking blocks ... cannot be modified
All three variants mean the same thing: the sequence of
tool_use
,
tool_result
, and
thinking
blocks in history no longer matches what the API expects.
What to do:
Run
/rewind
, or press Esc twice, to step back to a checkpoint before the corrupted turn and continue from there. See
Checkpointing
for how checkpoints are created and restored.
​
Responses seem lower quality than usual
If Claude’s answers seem less capable than you expect but no error is shown, the cause is usually conversation state rather than the model itself. Claude Code does not silently change model versions. It can switch to a fallback model in specific cases such as an Opus quota being reached or a Bedrock or Vertex AI region lacking your model; the Model selection check below catches both, and
Model configuration
explains when fallback applies.
Check these first:
Model selection
: run
/model
to confirm you are on the model you expect. A previous
/model
choice or an
ANTHROPIC_MODEL
environment variable may have you on a smaller model than you intended.
Effort level
: run
/effort
to check the current reasoning level and raise it for hard debugging or design work. Defaults vary by model, so check before assuming you are below the maximum. See
Adjust effort level
for per-model defaults and the
ultrathink
shortcut.
Context pressure
: run
/context
to see how full the window is. If it is near capacity, run
/compact
at a natural breakpoint or
/clear
to start fresh. See
Explore the context window
for how auto-compact affects earlier turns.
Stale instructions
: large or outdated
CLAUDE.md
files and MCP tool definitions consume context and can steer responses.
/doctor
flags oversized memory files and subagent definitions;
/context
shows MCP tool token usage.
When a response goes wrong, rewinding usually works better than replying with corrections. Press Esc twice or run
/rewind
to step back to before the bad turn, then rephrase the prompt with more specifics. Correcting in-thread keeps the wrong attempt in context, which can anchor later answers to it. See
Checkpointing
.
If quality still seems off after checking the above, run
/feedback
and describe what you expected versus what you got. Feedback submitted this way includes the conversation transcript, which is the fastest way for Anthropic to diagnose a real regression. See
Report an error
if
/feedback
is unavailable in your environment.
​
Report an error
This page covers errors from the Claude API. For errors from other Claude Code components, see the relevant guide:
MCP server failed to connect or authenticate:
MCP
Hook script failed or blocked a tool:
Debug hooks
Permission denied or filesystem errors during install:
Troubleshoot installation and login
If an error is not listed here or the suggested fix does not help:
Run
/feedback
inside Claude Code to send the transcript and a description to Anthropic. The command also offers to open a prefilled GitHub issue. On Bedrock, Vertex AI, Foundry, and other third-party providers,
/feedback
saves a local archive you can send to your Anthropic account representative instead.
Run
/doctor
to check for local configuration problems
Check
status.claude.com
for active incidents
Search
existing issues
on GitHub
Was this page helpful?
Yes
No
Debug configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/errors" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Error reference
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troub...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Error reference
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page lists runtime errors Claude Code displays and how to recover from each one, plus what to check when responses seem off without an error. For installation errors such as
command not found
or TLS failures during setup, see
Troubleshoot installation and login
.
These errors and recovery commands apply across the CLI, the
Desktop app
, and
Claude Code on the web
, since all three wrap the same Claude Code CLI. For surface-specific issues, see the troubleshooting section on that surface’s page.
Claude Code calls the Claude API for model responses, so most runtime errors map to an underlying API error code. This page covers what each error means inside Claude Code and how to recover. For the raw HTTP status code definitions, see the
Claude Platform error reference
.
​
Find your error
Match the message you see in your terminal to a section below.
Message
Section
API Error: 500 ... Internal server error
Server errors
API Error: Repeated 529 Overloaded errors
Server errors
Request timed out
Server errors
, or
Network
if the message mentions your internet connection
<model> is temporarily unavailable, so auto mode cannot determine the safety of...
Server errors
Auto mode could not evaluate this action and is blocking it for safety
Server errors
Auto mode classifier transcript exceeded context window
Server errors
You've hit your session limit
/
You've hit your weekly limit
Usage limits
Server is temporarily limiting requests
Usage limits
Request rejected (429)
Usage limits
Credit balance is too low
Usage limits
Not logged in · Please run /login
Authentication
Invalid API key
Authentication
This organization has been disabled
Authentication
Routines are disabled by your organization's policy
Authentication
OAuth token revoked
/
OAuth token has expired
Authentication
does not meet scope requirement user:profile
Authentication
Unable to connect to API
Network
SSL certificate verification failed
Network
403
with
x-deny-reason: host_not_allowed
in a cloud or routine session
Network
Prompt is too long
Request errors
Error during compaction: Conversation too long
Request errors
Request too large
Request errors
Image was too large
Request errors
PDF too large
/
PDF is password protected
Request errors
Extra inputs are not permitted
Request errors
There's an issue with the selected model
Request errors
Claude Opus is not available with the Claude Pro plan
Request errors
thinking.type.enabled is not supported for this model
Request errors
max_tokens must be greater than thinking.budget_tokens
Request errors
API Error: 400 due to tool use concurrency issues
Request errors
Responses seem lower quality than usual
Response quality
​
Automatic retries
Claude Code retries transient failures before showing you an error. Server errors, overloaded responses, request timeouts, temporary 429 throttles, and dropped connections are all retried up to 10 times with exponential backoff. While retrying, the spinner shows a
Retrying in Ns · attempt x/y
countdown.
When you see one of the errors on this page, those retries have already been exhausted. You can tune the behavior with two environment variables:
Variable
Default
Effect
CLAUDE_CODE_MAX_RETRIES
10
Number of retry attempts. Lower it to surface failures faster in scripts; raise it to wait through longer incidents.
API_TIMEOUT_MS
600000
Per-request timeout in milliseconds. Raise it for slow networks or proxies.
​
Server errors
These errors come from Anthropic infrastructure rather than your account or request.
​
API Error: 500 Internal server error
Claude Code shows the raw API response body for any 5xx status. The example below shows a 500 response:
API Error: 500 {"type":"error","error":{"type":"api_error","message":"Internal server error"}} · check status.claude.com
This indicates an unexpected failure inside the API. It is not caused by your prompt, settings, or account.
What to do:
Check
status.claude.com
for active incidents
Wait a minute, then send your message again. Your original message is still in the conversation, so for a long prompt you can type
try again
instead of pasting the whole thing.
If the error persists with no posted incident, run
/feedback
so Anthropic can investigate with your request details. See
Report an error
if
/feedback
is unavailable in your environment.
​
API Error: Repeated 529 Overloaded errors
The API is temporarily at capacity across all users. Claude Code has already retried several times before showing this message:
API Error: Repeated 529 Overloaded errors · check status.claude.com
A 529 is not your usage limit and does not count against your quota.
What to do:
Check
status.claude.com
for capacity notices
Try again in a few minutes
Run
/model
and switch to a different model to keep working, since capacity is tracked per model. Claude Code prompts you to do this when one model is under particularly high load, for example
Opus is experiencing high load, please use /model to switch to Sonnet
.
​
Request timed out
The API did not respond before the connection deadline.
Request timed out
This can happen during periods of high load or when a very large response is being generated. The default request timeout is 10 minutes.
What to do:
Retry the request
For long-running tasks, break the work into smaller prompts
If a slow network or proxy is the cause, raise
API_TIMEOUT_MS
as described in
Automatic retries
If timeouts are frequent and your network is otherwise healthy, see
Network and connection errors
below
​
Auto mode cannot determine the safety of an action
The model that
auto mode
uses to classify actions could not produce a decision, so auto mode did not approve the action automatically. The message you see depends on why the classifier failed.
Reads, searches, and edits inside your working directory skip the classifier, so they keep working in all of these cases.
When the classifier model is overloaded:
<model> is temporarily unavailable, so auto mode cannot determine the safety of <tool> right now. Wait briefly and then try this action again.
What to do:
Retry after a few seconds; Claude sees the same message and usually retries on its own
If retries keep failing, continue with read-only tasks and come back to the blocked action later
This is transient and unrelated to
auto mode eligibility
; you do not need to change settings
When the classifier returned an unparseable response:
Auto mode could not evaluate this action and is blocking it for safety — run with --debug for details
What to do:
Retry the action; this usually succeeds on the next attempt
Run
claude --debug
and repeat the action to see the underlying classifier response in the debug log
When the conversation has grown larger than the classifier’s context window:
Auto mode classifier transcript exceeded context window — falling back to manual approval (try /compact to reduce conversation size)
In an interactive session, auto mode falls back to a normal permission prompt for that action so you can approve or deny it manually. In
non-interactive mode
the run aborts because the transcript only grows and retrying cannot succeed.
What to do:
Approve or deny the action in the prompt that appears
Run
/compact
to reduce the conversation size so subsequent actions fit within the classifier window again
​
Usage limits
These errors mean a quota tied to your account or plan has been reached. They are distinct from
server errors
, which affect everyone.
​
You’ve hit your session limit
Subscription plans include a rolling usage allowance. When it runs out you see one of these messages:
You've hit your session limit · resets 3:45pm
You've hit your weekly limit · resets Mon 12:00am
You've hit your Opus limit · resets 3:45pm
Claude Code blocks further requests until the reset time shown in the message.
What to do:
Wait for the reset time shown in the error
Run
/usage
to see your plan limits and when they reset
Run
/extra-usage
to buy additional usage on Pro and Max, or to request it from your admin on Team and Enterprise. See
Extra usage for paid plans
for how this is billed.
To upgrade your plan for higher base limits, see
claude.com/pricing
To watch your remaining allowance before you hit the limit, add the
rate_limits
fields to a
custom status line
, or in the Desktop app click the
usage ring
next to the model picker.
​
Server is temporarily limiting requests
The API applied a short-lived throttle that is unrelated to your plan quota.
API Error: Server is temporarily limiting requests (not your usage limit)
This is
retried automatically
before being shown.
What to do:
Wait briefly and try again
Check
status.claude.com
if it persists
​
Request rejected (429)
You have hit the rate limit configured for your API key, Amazon Bedrock project, or Google Vertex AI project.
API Error: Request rejected (429) · this may be a temporary capacity issue
What to do:
Run
/status
and confirm the active credential is the one you expect. A stray
ANTHROPIC_API_KEY
in your environment can route requests through a low-tier key instead of your subscription.
Check your provider console for the active limits and request a higher tier if needed
For Anthropic API keys, see the
rate limits reference
for how tiers work and how to set per-workspace caps
Reduce concurrency: lower
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
, avoid running many parallel subagents, or switch to a smaller model with
/model
for high-volume scripted runs
​
Credit balance is too low
Your Console organization has run out of prepaid credits.
Credit balance is too low
What to do:
Add credits at
platform.claude.com/settings/billing
, and consider enabling auto-reload there so the balance refills before it hits zero
Switch to subscription authentication with
/login
if you have a Pro, Max, Team, or Enterprise plan
Set per-workspace spend caps in the Console to prevent a single project from draining the org balance. See
Manage costs effectively
.
​
Authentication errors
These errors mean Claude Code cannot prove who you are to the API. Run
/status
at any time to see which credential is currently active.
​
Not logged in
No valid credential is available for this session.
Not logged in · Please run /login
What to do:
Run
/login
to authenticate with your Claude subscription or Console account
If you expected an environment variable to authenticate you, confirm
ANTHROPIC_API_KEY
is set and exported in the shell where you launched
claude
For CI or automation where interactive login is not possible, configure an
apiKeyHelper
script that fetches a key at startup
See
Authentication precedence
to understand which credential wins when several are present
If you are prompted to log in repeatedly, see
Not logged in or token expired
for system clock and macOS Keychain fixes.
​
Invalid API key
The
ANTHROPIC_API_KEY
environment variable or
apiKeyHelper
script returned a key the API rejected.
Invalid API key · Fix external API key
What to do:
Check for typos and confirm the key has not been revoked in the
Console
Run
env | grep ANTHROPIC
in the same shell. Tools like direnv, dotenv shell plugins, and IDE terminals can load a stale key from a
.env
file in your project without you setting it explicitly.
Unset
ANTHROPIC_API_KEY
and run
/login
to use subscription auth instead
If the key comes from an
apiKeyHelper
script, run the script directly to confirm it prints a valid key on stdout
Run
/status
to confirm which credential source Claude Code is actually using
​
This organization has been disabled
A stale
ANTHROPIC_API_KEY
from a disabled Console organization is overriding your subscription login.
Your ANTHROPIC_API_KEY belongs to a disabled organization · Unset the environment variable to use your other credentials
API Error: 400 ... This organization has been disabled.
Environment variables take precedence over
/login
, so a key exported in your shell profile or loaded from a
.env
file is used even when you have a working Pro or Max subscription. In non-interactive mode (
-p
), the key is always used when present.
What to do:
Unset
ANTHROPIC_API_KEY
in the current shell and remove it from your shell profile, then relaunch
claude
Run
/status
afterward to confirm the active credential is your subscription
If no environment variable is set and the error persists, the disabled organization is the one tied to your
/login
. Contact support or sign in with a different account.
​
Routines are disabled by your organization’s policy
Your Team or Enterprise admin has turned off routines at the organization level. The error appears when you try to create or run a routine, including from
/schedule
and the
Routines
UI on claude.ai/code.
Routines are disabled by your organization's policy.
This is a server-side setting, so it cannot be overridden from local settings, environment variables, or CLI flags.
What to do:
Ask your admin to enable the
Routines
toggle at
claude.ai/admin-settings/claude-code
For one-off scheduled work that does not require organization-level routines, see
scheduled tasks
​
OAuth token revoked or expired
Your saved login is no longer valid. A revoked token means you signed out everywhere or an admin removed access; an expired token means the automatic refresh failed mid-session.
OAuth token revoked · Please run /login
OAuth token has expired · Please run /login
API Error: 401 ... authentication_error
What to do:
Run
/login
to sign in again
If the error returns within the same session after re-authenticating, run
/logout
first to fully clear the stored token, then
/login
For repeated prompts to log in across launches, see the system clock and macOS Keychain checks in
Troubleshooting
For other failures including
403 Forbidden
and OAuth browser issues, see
Login and authentication
​
OAuth scope requirement
The stored token predates a permission scope that a newer feature needs. You see this most often from
/usage
and the status line usage indicator:
OAuth token does not meet scope requirement: user:profile
What to do:
Run
/login
to mint a new token with the current scopes. You do not need to log out first.
​
Network and connection errors
These errors mean a network request from Claude Code failed to reach its destination. They usually originate in your local network, proxy, or firewall, or in the cloud environment’s network policy.
​
Unable to connect to API
The TCP connection to the API failed or never completed.
Unable to connect to API. Check your internet connection
Unable to connect to API (ECONNREFUSED)
Unable to connect to API (ECONNRESET)
Unable to connect to API (ETIMEDOUT)
fetch failed
Request timed out. Check your internet connection and proxy settings
Common causes include no internet access, a VPN that blocks
api.anthropic.com
, or a required corporate proxy that is not configured.
What to do:
Confirm you can reach the API host from the same shell by running
curl -I https://api.anthropic.com
. On Windows PowerShell use
curl.exe -I https://api.anthropic.com
so the built-in
Invoke-WebRequest
alias is not used.
If you are behind a corporate proxy, set
HTTPS_PROXY
before launching Claude Code and see
Network configuration
If you route through an LLM gateway or relay, set
ANTHROPIC_BASE_URL
to its address. See
LLM gateway configuration
for setup.
Ensure your firewall allows the hosts listed in
Network access requirements
Intermittent failures are
retried automatically
; persistent failures point to a local network issue
If
curl
succeeds but Claude Code still fails, the cause is usually something between the runtime and the network rather than the network itself:
On Linux and WSL, check
/etc/resolv.conf
for an unreachable nameserver. WSL in particular can inherit a broken resolver from the host.
On macOS, a VPN client that was disconnected or uninstalled can leave a tunnel interface or routing rule behind. Check
ifconfig
for stale
utun
interfaces and remove the VPN’s network extension in System Settings.
Docker Desktop and similar container runtimes can intercept outbound traffic. Quit them and retry to rule this out.
​
SSL certificate errors
A proxy or security appliance on your network is intercepting TLS traffic with its own certificate, and Claude Code does not trust it.
Unable to connect to API: SSL certificate verification failed. Check your proxy or corporate SSL certificates
Unable to connect to API: Self-signed certificate detected
What to do:
Export your organization’s CA bundle and point Claude Code at it with
NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem
See
Network configuration
for full setup instructions
Do not set
NODE_TLS_REJECT_UNAUTHORIZED=0
, which disables certificate validation entirely
​
Host not allowed in a cloud session
An outbound HTTP request from a cloud session or routine was blocked by the environment’s network policy.
HTTP 403
x-deny-reason: host_not_allowed
You may also see a TLS certificate that doesn’t match the destination’s real certificate. The cloud environment routes outbound traffic through a proxy that enforces the network policy, so a mismatched certificate means the proxy terminated the connection, not the destination.
This is not a client-side network problem. Cloud sessions and
routines
run inside a sandboxed environment whose outbound traffic is filtered to the environment’s allowlist. The
Default
environment uses
Trusted
access, which permits the
default allowlist
of package registries, cloud provider APIs, container registries, and common development domains but blocks everything else.
What to do:
Open the routine for editing, or start a cloud session. Select the cloud icon showing your environment’s name, such as
Default
, to open the selector. Hover over your environment and click the settings icon.
In the
Update cloud environment
dialog, change
Network access
from
Trusted
to
Custom
, then add the blocked domain to
Allowed domains
. Enter one domain per line. Check
Also include default list of common package managers
to keep the
default allowlist
alongside your custom domains. Select
Full
instead if you want unrestricted access.
Click
Save changes
. The next run uses the updated allowlist.
See
Network access
for access levels and the default allowlist. Local CLI sessions are not affected by this policy.
​
Request errors
These errors mean the API received your request but rejected its content.
​
Prompt is too long
The conversation plus attached files exceeds the model’s context window.
Prompt is too long
What to do:
Run
/compact
to summarize earlier turns and free space, or
/clear
to start fresh
Run
/context
to see a breakdown of what is consuming the window: system prompt, tools, memory files, and messages
Disable MCP servers you are not using with
/mcp disable <name>
to remove their tool definitions from context
Trim large
CLAUDE.md
memory files, or move instructions into
path-scoped rules
that load only when relevant
Subagents inherit every MCP tool definition from the parent session, which can fill their context window before the first turn. Disable MCP servers you are not using before spawning subagents.
Auto-compact is on by default and normally prevents this error. If you have set
DISABLE_AUTO_COMPACT
, re-enable it or run
/compact
manually before the window fills.
See
Explore the context window
for an interactive view of how context fills up.
​
Error during compaction: Conversation too long
/compact
itself failed because there is not enough free context to hold the summary it produces.
Error during compaction: Conversation too long. Press esc twice to go up a few messages and try again.
This can happen when the window is already full at the moment auto-compact triggers, or when you run
/compact
after seeing
Prompt is too long
.
What to do:
Press Esc twice to open the message list and step back several turns. This drops the most recent messages from context. Then run
/compact
again.
If stepping back does not free enough space, run
/clear
to start a fresh session. Your previous conversation is preserved and can be reopened with
/resume
.
​
Request too large
The raw request body exceeded the API’s byte limit before tokenization, usually because of a large pasted file or attachment.
Request too large (max 30 MB). Double press esc to go back and remove or shrink the attached content.
This is a size limit on the HTTP request, separate from the
context window limit
.
What to do:
Press Esc twice and step back past the turn that added the oversized content
Reference large files by path instead of pasting their contents, so Claude can read them in chunks
For images, see
Image was too large
below
​
Image was too large
A pasted or attached image exceeds the API’s size or dimension limits.
Image was too large. Double press esc to go back and try again with a smaller image.
API Error: 400 ... image dimensions exceed max allowed size
The image stays in conversation history after the error, so every subsequent message fails with the same error until you remove it.
What to do:
Press Esc twice and step back past the turn where the image was added
Resize the image before pasting. The API accepts images up to 8000 pixels on the longest edge for a single image, or 2000 pixels when many images are in context.
Take a tighter screenshot of the relevant region instead of the full screen
​
PDF errors
The PDF you attached could not be processed.
PDF too large (max 100 pages, 32 MB). Try splitting it or extracting text first.
PDF is password protected. Try removing protection or extracting text first.
The PDF file was not valid. Try converting to a different format first.
What to do:
For oversized PDFs, ask Claude to read a page range with the Read tool instead of attaching the whole file, or extract text with a tool like
pdftotext
and reference the output file by path
For protected or invalid PDFs, remove the password or re-export the file from its source application, then try again
​
Extra inputs are not permitted
A proxy or LLM gateway between Claude Code and the API stripped the
anthropic-beta
request header, so the API rejected fields that depend on it.
API Error: 400 ... Extra inputs are not permitted ... context_management
API Error: 400 ... Extra inputs are not permitted ... tools.0.custom.input_examples
API Error: 400 ... Unexpected value(s) for the `anthropic-beta` header
Claude Code sends beta-only fields such as
context_management
,
effort
, and tool
input_examples
alongside an
anthropic-beta
header that enables them. When a gateway forwards the body but drops the header, the API sees fields it does not recognize.
What to do:
Configure your gateway to forward the
anthropic-beta
header. See
LLM gateway configuration
.
As a fallback, set
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
before launching. This disables features that require the beta header so requests succeed through a gateway that cannot forward it.
​
There’s an issue with the selected model
The configured model name was not recognized or your account lacks access to it.
There's an issue with the selected model (claude-...). It may not exist or you may not have access to it. Run /model to select a different one.
What to do:
Run
/model
to pick from models available to your account
Use an alias such as
sonnet
or
opus
instead of a full versioned ID. Aliases track the latest release so they do not go stale. See
Model configuration
.
If the wrong model keeps coming back, a stale ID is set somewhere. Check in
priority order
: the
--model
flag, the
ANTHROPIC_MODEL
environment variable, then the
model
field in
.claude/settings.local.json
, your project’s
.claude/settings.json
, and
~/.claude/settings.json
. Remove the stale value and Claude Code falls back to your account default.
For Vertex AI deployments, see
Vertex AI troubleshooting
.
​
Claude Opus is not available with the Claude Pro plan
Your active subscription plan does not include the model you selected.
Claude Opus is not available with the Claude Pro plan · Select a different model in /model
What to do:
Run
/model
and select a model your plan includes
If you upgraded your plan recently and still see this, run
/logout
then
/login
. The stored token reflects your plan at the time you signed in, so upgrading on the web does not take effect in an existing session until you re-authenticate.
See
claude.com/pricing
for which models each plan includes
​
thinking.type.enabled is not supported for this model
Your Claude Code version is older than the minimum for Opus 4.7. The CLI sent a thinking configuration the model no longer accepts.
API Error: 400 ... "thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
What to do:
Run
claude update
to upgrade to v2.1.111 or later, then restart Claude Code
If you cannot upgrade, run
/model
and select Opus 4.6 or Sonnet instead
If you hit this in the Agent SDK, see
SDK troubleshooting
​
Thinking budget exceeds output limit
The configured extended thinking budget exceeds the maximum response length, so there is no room left for the actual answer.
API Error: 400 ... max_tokens must be greater than thinking.budget_tokens
Claude Code adjusts these values automatically on the Anthropic API. You typically see this error on Amazon Bedrock or Google Vertex AI when
MAX_THINKING_TOKENS
is set higher than the provider’s output limit, or when plan mode raises the thinking budget.
What to do:
Lower
MAX_THINKING_TOKENS
, or raise
CLAUDE_CODE_MAX_OUTPUT_TOKENS
above the thinking budget
See
Extended thinking
for how the budget interacts with output length
​
Tool use or thinking block mismatch
The conversation history reached the API in an inconsistent state, usually after a tool call was interrupted or a turn was edited mid-stream.
API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.
API Error: 400 ... unexpected `tool_use_id` found in `tool_result` blocks
API Error: 400 ... thinking blocks ... cannot be modified
All three variants mean the same thing: the sequence of
tool_use
,
tool_result
, and
thinking
blocks in history no longer matches what the API expects.
What to do:
Run
/rewind
, or press Esc twice, to step back to a checkpoint before the corrupted turn and continue from there. See
Checkpointing
for how checkpoints are created and restored.
​
Responses seem lower quality than usual
If Claude’s answers seem less capable than you expect but no error is shown, the cause is usually conversation state rather than the model itself. Claude Code does not silently change model versions. It can switch to a fallback model in specific cases such as an Opus quota being reached or a Bedrock or Vertex AI region lacking your model; the Model selection check below catches both, and
Model configuration
explains when fallback applies.
Check these first:
Model selection
: run
/model
to confirm you are on the model you expect. A previous
/model
choice or an
ANTHROPIC_MODEL
environment variable may have you on a smaller model than you intended.
Effort level
: run
/effort
to check the current reasoning level and raise it for hard debugging or design work. Defaults vary by model, so check before assuming you are below the maximum. See
Adjust effort level
for per-model defaults and the
ultrathink
shortcut.
Context pressure
: run
/context
to see how full the window is. If it is near capacity, run
/compact
at a natural breakpoint or
/clear
to start fresh. See
Explore the context window
for how auto-compact affects earlier turns.
Stale instructions
: large or outdated
CLAUDE.md
files and MCP tool definitions consume context and can steer responses.
/doctor
flags oversized memory files and subagent definitions;
/context
shows MCP tool token usage.
When a response goes wrong, rewinding usually works better than replying with corrections. Press Esc twice or run
/rewind
to step back to before the bad turn, then rephrase the prompt with more specifics. Correcting in-thread keeps the wrong attempt in context, which can anchor later answers to it. See
Checkpointing
.
If quality still seems off after checking the above, run
/feedback
and describe what you expected versus what you got. Feedback submitted this way includes the conversation transcript, which is the fastest way for Anthropic to diagnose a real regression. See
Report an error
if
/feedback
is unavailable in your environment.
​
Report an error
This page covers errors from the Claude API. For errors from other Claude Code components, see the relevant guide:
MCP server failed to connect or authenticate:
MCP
Hook script failed or blocked a tool:
Debug hooks
Permission denied or filesystem errors during install:
Troubleshoot installation and login
If an error is not listed here or the suggested fix does not help:
Run
/feedback
inside Claude Code to send the transcript and a description to Anthropic. The command also offers to open a prefilled GitHub issue. On Bedrock, Vertex AI, Foundry, and other third-party providers,
/feedback
saves a local archive you can send to your Anthropic account representative instead.
Run
/doctor
to check for local configuration problems
Check
status.claude.com
for active incidents
Search
existing issues
on GitHub
Was this page helpful?
Yes
No
Debug configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/errors" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Quickstart</title>
  <link>https://code.claude.com/docs/en/quickstart</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/quickstart</guid>
  <pubDate>Sun, 15 Sep 2024 00:00:00 +0000</pubDate>
  <category>Getting Started</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Quickstart
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (pre...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Quickstart
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This quickstart guide will have you using AI-powered coding assistance in a few minutes. By the end, you’ll understand how to use Claude Code for common development tasks.
​
Before you begin
Make sure you have:
A terminal or command prompt open
If you’ve never used the terminal before, check out the
terminal guide
A code project to work with
A
Claude subscription
(Pro, Max, Team, or Enterprise),
Claude Console
account, or access through a
supported cloud provider
This guide covers the terminal CLI. Claude Code is also available on the
web
, as a
desktop app
, in
VS Code
and
JetBrains IDEs
, in
Slack
, and in CI/CD with
GitHub Actions
and
GitLab
. See
all interfaces
.
​
Step 1: Install Claude Code
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
​
Step 2: Log in to your account
Claude Code requires an account to use. When you start an interactive session with the
claude
command, you’ll need to log in:
claude
# You'll be prompted to log in on first use
/login
# Follow the prompts to log in with your account
You can log in using any of these account types:
Claude Pro, Max, Team, or Enterprise
(recommended)
Claude Console
(API access with pre-paid credits). On first login, a “Claude Code” workspace is automatically created in the Console for centralized cost tracking.
Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
(enterprise cloud providers)
Once logged in, your credentials are stored and you won’t need to log in again. To switch accounts later, use the
/login
command.
​
Step 3: Start your first session
Open your terminal in any project directory and start Claude Code:
cd
/path/to/your/project
claude
You’ll see the Claude Code welcome screen with your session information, recent conversations, and latest updates. Type
/help
for available commands or
/resume
to continue a previous conversation.
After logging in (Step 2), your credentials are stored on your system. Learn more in
Credential Management
.
​
Step 4: Ask your first question
Let’s start with understanding your codebase. Try one of these commands:
what does this project do?
Claude will analyze your files and provide a summary. You can also ask more specific questions:
what technologies does this project use?
where is the main entry point?
explain the folder structure
You can also ask Claude about its own capabilities:
what can Claude Code do?
how do I create custom skills in Claude Code?
can Claude Code work with Docker?
Claude Code reads your project files as needed. You don’t have to manually add context.
​
Step 5: Make your first code change
Now let’s make Claude Code do some actual coding. Try a simple task:
add a hello world function to the main file
Claude Code will:
Find the appropriate file
Show you the proposed changes
Ask for your approval
Make the edit
Claude Code always asks for permission before modifying files. You can approve individual changes or enable “Accept all” mode for a session.
​
Step 6: Use Git with Claude Code
Claude Code makes Git operations conversational:
what files have I changed?
commit my changes with a descriptive message
You can also prompt for more complex Git operations:
create a new branch called feature/quickstart
show me the last 5 commits
help me resolve merge conflicts
​
Step 7: Fix a bug or add a feature
Claude is proficient at debugging and feature implementation.
Describe what you want in natural language:
add input validation to the user registration form
Or fix existing issues:
there's a bug where users can submit empty forms - fix it
Claude Code will:
Locate the relevant code
Understand the context
Implement a solution
Run tests if available
​
Step 8: Test out other common workflows
There are a number of ways to work with Claude:
Refactor code
refactor the authentication module to use async/await instead of callbacks
Write tests
write unit tests for the calculator functions
Update documentation
update the README with installation instructions
Code review
review my changes and suggest improvements
Talk to Claude like you would a helpful colleague. Describe what you want to achieve, and it will help you get there.
​
Essential commands
Here are the most important commands for daily use:
Command
What it does
Example
claude
Start interactive mode
claude
claude "task"
Run a one-time task
claude "fix the build error"
claude -p "query"
Run one-off query, then exit
claude -p "explain this function"
claude -c
Continue most recent conversation in current directory
claude -c
claude -r
Resume a previous conversation
claude -r
/clear
Clear conversation history
/clear
/help
Show available commands
/help
exit
or Ctrl+D
Exit Claude Code
exit
See the
CLI reference
for a complete list of commands.
​
Pro tips for beginners
For more, see
best practices
and
common workflows
.
Be specific with your requests
Instead of: “fix the bug”
Try: “fix the login bug where users see a blank screen after entering wrong credentials”
Use step-by-step instructions
Break complex tasks into steps:
1. create a new database table for user profiles
2. create an API endpoint to get and update user profiles
3. build a webpage that allows users to see and edit their information
Let Claude explore first
Before making changes, let Claude understand your code:
analyze the database schema
build a dashboard showing products that are most frequently returned by our UK customers
Save time with shortcuts
Type
/
to see all commands and skills
Use Tab for command completion
Press ↑ for command history
Press
Shift+Tab
to cycle permission modes
​
What’s next?
Now that you’ve learned the basics, explore more advanced features:
How Claude Code works
Understand the agentic loop, built-in tools, and how Claude Code interacts with your project
Best practices
Get better results with effective prompting and project setup
Common workflows
Step-by-step guides for common tasks
Extend Claude Code
Customize with CLAUDE.md, skills, hooks, MCP, and more
​
Getting help
In Claude Code
: Type
/help
or ask “how do I…”
Documentation
: You’re here! Browse other guides
Community
: Join our
Discord
for tips and support
Was this page helpful?
Yes
No
Overview
Changelog
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Quickstart
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (pre...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Getting started
Quickstart
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This quickstart guide will have you using AI-powered coding assistance in a few minutes. By the end, you’ll understand how to use Claude Code for common development tasks.
​
Before you begin
Make sure you have:
A terminal or command prompt open
If you’ve never used the terminal before, check out the
terminal guide
A code project to work with
A
Claude subscription
(Pro, Max, Team, or Enterprise),
Claude Console
account, or access through a
supported cloud provider
This guide covers the terminal CLI. Claude Code is also available on the
web
, as a
desktop app
, in
VS Code
and
JetBrains IDEs
, in
Slack
, and in CI/CD with
GitHub Actions
and
GitLab
. See
all interfaces
.
​
Step 1: Install Claude Code
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
​
Step 2: Log in to your account
Claude Code requires an account to use. When you start an interactive session with the
claude
command, you’ll need to log in:
claude
# You'll be prompted to log in on first use
/login
# Follow the prompts to log in with your account
You can log in using any of these account types:
Claude Pro, Max, Team, or Enterprise
(recommended)
Claude Console
(API access with pre-paid credits). On first login, a “Claude Code” workspace is automatically created in the Console for centralized cost tracking.
Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
(enterprise cloud providers)
Once logged in, your credentials are stored and you won’t need to log in again. To switch accounts later, use the
/login
command.
​
Step 3: Start your first session
Open your terminal in any project directory and start Claude Code:
cd
/path/to/your/project
claude
You’ll see the Claude Code welcome screen with your session information, recent conversations, and latest updates. Type
/help
for available commands or
/resume
to continue a previous conversation.
After logging in (Step 2), your credentials are stored on your system. Learn more in
Credential Management
.
​
Step 4: Ask your first question
Let’s start with understanding your codebase. Try one of these commands:
what does this project do?
Claude will analyze your files and provide a summary. You can also ask more specific questions:
what technologies does this project use?
where is the main entry point?
explain the folder structure
You can also ask Claude about its own capabilities:
what can Claude Code do?
how do I create custom skills in Claude Code?
can Claude Code work with Docker?
Claude Code reads your project files as needed. You don’t have to manually add context.
​
Step 5: Make your first code change
Now let’s make Claude Code do some actual coding. Try a simple task:
add a hello world function to the main file
Claude Code will:
Find the appropriate file
Show you the proposed changes
Ask for your approval
Make the edit
Claude Code always asks for permission before modifying files. You can approve individual changes or enable “Accept all” mode for a session.
​
Step 6: Use Git with Claude Code
Claude Code makes Git operations conversational:
what files have I changed?
commit my changes with a descriptive message
You can also prompt for more complex Git operations:
create a new branch called feature/quickstart
show me the last 5 commits
help me resolve merge conflicts
​
Step 7: Fix a bug or add a feature
Claude is proficient at debugging and feature implementation.
Describe what you want in natural language:
add input validation to the user registration form
Or fix existing issues:
there's a bug where users can submit empty forms - fix it
Claude Code will:
Locate the relevant code
Understand the context
Implement a solution
Run tests if available
​
Step 8: Test out other common workflows
There are a number of ways to work with Claude:
Refactor code
refactor the authentication module to use async/await instead of callbacks
Write tests
write unit tests for the calculator functions
Update documentation
update the README with installation instructions
Code review
review my changes and suggest improvements
Talk to Claude like you would a helpful colleague. Describe what you want to achieve, and it will help you get there.
​
Essential commands
Here are the most important commands for daily use:
Command
What it does
Example
claude
Start interactive mode
claude
claude "task"
Run a one-time task
claude "fix the build error"
claude -p "query"
Run one-off query, then exit
claude -p "explain this function"
claude -c
Continue most recent conversation in current directory
claude -c
claude -r
Resume a previous conversation
claude -r
/clear
Clear conversation history
/clear
/help
Show available commands
/help
exit
or Ctrl+D
Exit Claude Code
exit
See the
CLI reference
for a complete list of commands.
​
Pro tips for beginners
For more, see
best practices
and
common workflows
.
Be specific with your requests
Instead of: “fix the bug”
Try: “fix the login bug where users see a blank screen after entering wrong credentials”
Use step-by-step instructions
Break complex tasks into steps:
1. create a new database table for user profiles
2. create an API endpoint to get and update user profiles
3. build a webpage that allows users to see and edit their information
Let Claude explore first
Before making changes, let Claude understand your code:
analyze the database schema
build a dashboard showing products that are most frequently returned by our UK customers
Save time with shortcuts
Type
/
to see all commands and skills
Use Tab for command completion
Press ↑ for command history
Press
Shift+Tab
to cycle permission modes
​
What’s next?
Now that you’ve learned the basics, explore more advanced features:
How Claude Code works
Understand the agentic loop, built-in tools, and how Claude Code interacts with your project
Best practices
Get better results with effective prompting and project setup
Common workflows
Step-by-step guides for common tasks
Extend Claude Code
Customize with CLAUDE.md, skills, hooks, MCP, and more
​
Getting help
In Claude Code
: Type
/help
or ask “how do I…”
Documentation
: You’re here! Browse other guides
Community
: Join our
Discord
for tips and support
Was this page helpful?
Yes
No
Overview
Changelog
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Keep Claude working toward a goal</title>
  <link>https://code.claude.com/docs/en/goal</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/goal</guid>
  <pubDate>Sun, 15 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Keep Claude working toward a goal
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions fro...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Keep Claude working toward a goal
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
/goal
requires Claude Code v2.1.139 or later.
The
/goal
command sets a completion condition and Claude keeps working toward it without you prompting each step. After each turn, a small fast model checks whether the condition holds. If not, Claude starts another turn instead of returning control to you. The goal clears automatically once the condition is met.
Use a goal for substantial work with a verifiable end state:
Migrating a module to a new API until every call site compiles and tests pass
Implementing a design doc until all acceptance criteria hold
Splitting a large file into focused modules until each is under a size budget
Working through a labeled issue backlog until the queue is empty
This page covers how to:
Compare autonomous workflow approaches
:
/loop
, Stop hooks, and auto mode
Set a goal
and
write an effective condition
Check status
,
clear early
, and
run non-interactively
See
how evaluation works
and
requirements
​
Compare to other autonomous workflows
Three approaches keep the current session running between prompts. Pick based on what should start the next turn:
Approach
Next turn starts when
Stops when
/goal
The previous turn finishes
A model confirms the condition is met
/loop
A time interval elapses
You stop it, or Claude decides the work is done
Stop hook
The previous turn finishes
Your own script or prompt decides
/goal
and a Stop hook both fire after every turn.
/goal
is a session-scoped shortcut: you type a condition and it’s active for the current session only. A Stop hook lives in your settings file, applies to every session in its scope, and can run a script for deterministic checks or a prompt for model-evaluated ones.
Auto mode
on its own approves tool calls within a single turn but doesn’t start a new one. Claude stops when it judges the work done.
/goal
adds a separate evaluator that checks your condition after every turn, so completion is decided by a fresh model rather than the one doing the work. The two are complementary: auto mode removes per-tool prompts, and
/goal
removes per-turn prompts.
The approaches above keep the current session running. You can also schedule work that runs independent of any open session, such as nightly tests or morning triage. See
scheduling options
for cloud routines and desktop scheduled tasks.
​
Use
/goal
One goal can be active per session. The same command sets, checks, and clears it depending on the argument.
​
Set a goal
Run
/goal
followed by the condition you want satisfied. If a goal is already active, the new one replaces it.
/goal all tests in test/auth pass and the lint step is clean
Setting a goal starts a turn immediately, with the condition itself as the directive. You don’t need to send a separate prompt. While the goal is active, a
◎ /goal active
indicator shows how long the goal has been running.
After each turn, the evaluator returns a short reason explaining why the condition is or isn’t met. The most recent reason appears in the status view and in the transcript so you can see what Claude is working toward next.
A goal keeps running until the condition is met or you run
/goal clear
. Run
/goal
with no argument to see turns and tokens spent so far.
​
Write an effective condition
The
evaluator
judges your condition against what Claude has surfaced in the conversation. It doesn’t run commands or read files independently, so write the condition as something Claude’s own output can demonstrate. “All tests in
test/auth
pass” works because Claude runs the tests and the result lands in the transcript for the evaluator to read.
A condition that holds up across many turns usually has:
One measurable end state
: a test result, a build exit code, a file count, an empty queue
A stated check
: how Claude should prove it, such as “
npm test
exits 0” or “
git status
is clean”
Constraints that matter
: anything that must not change on the way there, such as “no other test file is modified”
The condition can be up to 4,000 characters.
To bound how long a goal runs, include a turn or time clause in the condition, such as
or stop after 20 turns
. Claude reports progress against that clause each turn and the evaluator judges it from the conversation.
​
Check status
Run
/goal
with no arguments to see the current state.
/goal
If a goal is active, the status shows:
The condition
How long it has been running
How many turns have been evaluated
The current token spend
The evaluator’s most recent reason
If no goal is active but one was achieved earlier in the session, the status shows the achieved condition along with its duration, turn count, and token spend.
​
Clear a goal
Run
/goal clear
to remove an active goal before its condition is met.
/goal clear
stop
,
off
,
reset
,
none
, and
cancel
are accepted as aliases for
clear
. Running
/clear
to start a new conversation also removes any active goal.
​
Resume with an active goal
A goal that was still active when a session ended is restored when you resume that session with
--resume
or
--continue
. The condition carries over, but the turn count, timer, and token-spend baseline all reset on resume. A goal that was already achieved or cleared is not restored.
​
Run non-interactively
/goal
works in
non-interactive mode
, in the
desktop app
, and through
Remote Control
. Setting a goal with
-p
runs the loop to completion in a single invocation:
claude
-p
"/goal CHANGELOG.md has an entry for every PR merged this week"
Interrupt the process with Ctrl+C to stop a non-interactive goal before the condition is met.
​
How evaluation works
/goal
is a wrapper around a session-scoped
prompt-based Stop hook
. Each time Claude finishes a turn, the condition and the conversation so far are sent to your configured
small fast model
, which defaults to Haiku. The model returns a yes-or-no decision and a short reason. A “no” tells Claude to keep working and includes the reason as guidance for the next turn. A “yes” clears the goal and records an achieved entry in the transcript.
The evaluator runs on whichever provider your session is configured for. It does not call tools, so it can only judge what Claude has already surfaced in the conversation.
Evaluation tokens are billed on the small fast model configured for your provider and are typically negligible compared to main-turn spend.
​
Requirements
/goal
runs only in workspaces where you have accepted the trust dialog, because the evaluator is part of the hooks system.
/goal
is also unavailable when
disableAllHooks
is set at any settings level or when
allowManagedHooksOnly
is set in managed settings. In each case, the command tells you why instead of silently doing nothing.
​
See also
Run a prompt repeatedly with
/loop
: re-run on a time interval instead of until a condition holds
Prompt-based hooks
: write your own Stop hook when you need custom evaluation logic
Auto mode
: approve tool calls automatically so each goal turn runs unattended
Scheduling comparison
: run work on a schedule independent of any open session
Was this page helpful?
Yes
No
Run prompts on a schedule
Programmatic usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/goal" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Keep Claude working toward a goal
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions fro...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Keep Claude working toward a goal
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
/goal
requires Claude Code v2.1.139 or later.
The
/goal
command sets a completion condition and Claude keeps working toward it without you prompting each step. After each turn, a small fast model checks whether the condition holds. If not, Claude starts another turn instead of returning control to you. The goal clears automatically once the condition is met.
Use a goal for substantial work with a verifiable end state:
Migrating a module to a new API until every call site compiles and tests pass
Implementing a design doc until all acceptance criteria hold
Splitting a large file into focused modules until each is under a size budget
Working through a labeled issue backlog until the queue is empty
This page covers how to:
Compare autonomous workflow approaches
:
/loop
, Stop hooks, and auto mode
Set a goal
and
write an effective condition
Check status
,
clear early
, and
run non-interactively
See
how evaluation works
and
requirements
​
Compare to other autonomous workflows
Three approaches keep the current session running between prompts. Pick based on what should start the next turn:
Approach
Next turn starts when
Stops when
/goal
The previous turn finishes
A model confirms the condition is met
/loop
A time interval elapses
You stop it, or Claude decides the work is done
Stop hook
The previous turn finishes
Your own script or prompt decides
/goal
and a Stop hook both fire after every turn.
/goal
is a session-scoped shortcut: you type a condition and it’s active for the current session only. A Stop hook lives in your settings file, applies to every session in its scope, and can run a script for deterministic checks or a prompt for model-evaluated ones.
Auto mode
on its own approves tool calls within a single turn but doesn’t start a new one. Claude stops when it judges the work done.
/goal
adds a separate evaluator that checks your condition after every turn, so completion is decided by a fresh model rather than the one doing the work. The two are complementary: auto mode removes per-tool prompts, and
/goal
removes per-turn prompts.
The approaches above keep the current session running. You can also schedule work that runs independent of any open session, such as nightly tests or morning triage. See
scheduling options
for cloud routines and desktop scheduled tasks.
​
Use
/goal
One goal can be active per session. The same command sets, checks, and clears it depending on the argument.
​
Set a goal
Run
/goal
followed by the condition you want satisfied. If a goal is already active, the new one replaces it.
/goal all tests in test/auth pass and the lint step is clean
Setting a goal starts a turn immediately, with the condition itself as the directive. You don’t need to send a separate prompt. While the goal is active, a
◎ /goal active
indicator shows how long the goal has been running.
After each turn, the evaluator returns a short reason explaining why the condition is or isn’t met. The most recent reason appears in the status view and in the transcript so you can see what Claude is working toward next.
A goal keeps running until the condition is met or you run
/goal clear
. Run
/goal
with no argument to see turns and tokens spent so far.
​
Write an effective condition
The
evaluator
judges your condition against what Claude has surfaced in the conversation. It doesn’t run commands or read files independently, so write the condition as something Claude’s own output can demonstrate. “All tests in
test/auth
pass” works because Claude runs the tests and the result lands in the transcript for the evaluator to read.
A condition that holds up across many turns usually has:
One measurable end state
: a test result, a build exit code, a file count, an empty queue
A stated check
: how Claude should prove it, such as “
npm test
exits 0” or “
git status
is clean”
Constraints that matter
: anything that must not change on the way there, such as “no other test file is modified”
The condition can be up to 4,000 characters.
To bound how long a goal runs, include a turn or time clause in the condition, such as
or stop after 20 turns
. Claude reports progress against that clause each turn and the evaluator judges it from the conversation.
​
Check status
Run
/goal
with no arguments to see the current state.
/goal
If a goal is active, the status shows:
The condition
How long it has been running
How many turns have been evaluated
The current token spend
The evaluator’s most recent reason
If no goal is active but one was achieved earlier in the session, the status shows the achieved condition along with its duration, turn count, and token spend.
​
Clear a goal
Run
/goal clear
to remove an active goal before its condition is met.
/goal clear
stop
,
off
,
reset
,
none
, and
cancel
are accepted as aliases for
clear
. Running
/clear
to start a new conversation also removes any active goal.
​
Resume with an active goal
A goal that was still active when a session ended is restored when you resume that session with
--resume
or
--continue
. The condition carries over, but the turn count, timer, and token-spend baseline all reset on resume. A goal that was already achieved or cleared is not restored.
​
Run non-interactively
/goal
works in
non-interactive mode
, in the
desktop app
, and through
Remote Control
. Setting a goal with
-p
runs the loop to completion in a single invocation:
claude
-p
"/goal CHANGELOG.md has an entry for every PR merged this week"
Interrupt the process with Ctrl+C to stop a non-interactive goal before the condition is met.
​
How evaluation works
/goal
is a wrapper around a session-scoped
prompt-based Stop hook
. Each time Claude finishes a turn, the condition and the conversation so far are sent to your configured
small fast model
, which defaults to Haiku. The model returns a yes-or-no decision and a short reason. A “no” tells Claude to keep working and includes the reason as guidance for the next turn. A “yes” clears the goal and records an achieved entry in the transcript.
The evaluator runs on whichever provider your session is configured for. It does not call tools, so it can only judge what Claude has already surfaced in the conversation.
Evaluation tokens are billed on the small fast model configured for your provider and are typically negligible compared to main-turn spend.
​
Requirements
/goal
runs only in workspaces where you have accepted the trust dialog, because the evaluator is part of the hooks system.
/goal
is also unavailable when
disableAllHooks
is set at any settings level or when
allowManagedHooksOnly
is set in managed settings. In each case, the command tells you why instead of silently doing nothing.
​
See also
Run a prompt repeatedly with
/loop
: re-run on a time interval instead of until a condition holds
Prompt-based hooks
: write your own Stop hook when you need custom evaluation logic
Auto mode
: approve tool calls automatically so each goal turn runs unattended
Scheduling comparison
: run work on a schedule independent of any open session
Was this page helpful?
Yes
No
Run prompts on a schedule
Programmatic usage
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/goal" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Enterprise network configuration</title>
  <link>https://code.claude.com/docs/en/network-config</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/network-config</guid>
  <pubDate>Tue, 10 Sep 2024 00:00:00 +0000</pubDate>
  <category>Configuration</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise network configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marke...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise network configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports various enterprise network and security configurations through environment variables. This includes routing traffic through corporate proxy servers, trusting custom Certificate Authorities (CA), and authenticating with mutual Transport Layer Security (mTLS) certificates for enhanced security.
All environment variables shown on this page can also be configured in
settings.json
.
​
Proxy configuration
​
Environment variables
Claude Code respects standard proxy environment variables:
# HTTPS proxy (recommended)
export
HTTPS_PROXY
=
https
://
proxy
.
example
.
com
:
8080
# HTTP proxy (if HTTPS not available)
export
HTTP_PROXY
=
http
://
proxy
.
example
.
com
:
8080
# Bypass proxy for specific requests - space-separated format
export
NO_PROXY
=
"localhost 192.168.1.1 example.com .example.com"
# Bypass proxy for specific requests - comma-separated format
export
NO_PROXY
=
"localhost,192.168.1.1,example.com,.example.com"
# Bypass proxy for all requests
export
NO_PROXY
=
"*"
Claude Code does not support SOCKS proxies.
​
Basic authentication
If your proxy requires basic authentication, include credentials in the proxy URL:
export
HTTPS_PROXY
=
http
://
username
:
password
@
proxy
.
example
.
com
:
8080
Avoid hardcoding passwords in scripts. Use environment variables or secure credential storage instead.
For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.
​
CA certificate store
By default, Claude Code trusts both its bundled Mozilla CA certificates and your operating system’s certificate store. Enterprise TLS-inspection proxies such as CrowdStrike Falcon and Zscaler work without additional configuration when their root certificate is installed in the OS trust store.
CLAUDE_CODE_CERT_STORE
accepts a comma-separated list of sources. Recognized values are
bundled
for the Mozilla CA set shipped with Claude Code and
system
for the operating system trust store. The default is
bundled,system
.
To trust only the bundled Mozilla CA set:
export
CLAUDE_CODE_CERT_STORE
=
bundled
To trust only the OS certificate store:
export
CLAUDE_CODE_CERT_STORE
=
system
CLAUDE_CODE_CERT_STORE
has no dedicated
settings.json
schema key. Set it via the
env
block in
~/.claude/settings.json
or directly in the process environment.
​
Custom CA certificates
If your enterprise environment uses a custom CA, configure Claude Code to trust it directly:
export
NODE_EXTRA_CA_CERTS
=
/
path
/
to
/
ca-cert
.
pem
​
mTLS authentication
For enterprise environments requiring client certificate authentication:
# Client certificate for authentication
export
CLAUDE_CODE_CLIENT_CERT
=
/
path
/
to
/
client-cert
.
pem
# Client private key
export
CLAUDE_CODE_CLIENT_KEY
=
/
path
/
to
/
client-key
.
pem
# Optional: Passphrase for encrypted private key
export
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
=
"your-passphrase"
​
Network access requirements
Claude Code requires access to the following URLs. Allowlist these in your proxy configuration and firewall rules, especially in containerized or restricted network environments.
URL
Required for
api.anthropic.com
Claude API requests
claude.ai
claude.ai account authentication
platform.claude.com
Anthropic Console account authentication
downloads.claude.ai
Plugin executable downloads; native installer and native auto-updater
storage.googleapis.com
Native installer and native auto-updater on versions prior to 2.1.116
bridge.claudeusercontent.com
Claude in Chrome
extension WebSocket bridge
raw.githubusercontent.com
Changelog feed for
/release-notes
and the release notes shown after updating; plugin marketplace install counts
If you install Claude Code through npm or manage your own binary distribution, end users may not need access to
downloads.claude.ai
or
storage.googleapis.com
.
Claude Code also sends optional operational telemetry by default, which you can disable with environment variables. See
Telemetry services
for how to disable it before finalizing your allowlist.
When using
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
, model traffic and authentication go to your provider instead of
api.anthropic.com
,
claude.ai
, or
platform.claude.com
. The WebFetch tool still calls
api.anthropic.com
for its
domain safety check
unless you set
skipWebFetchPreflight: true
in
settings
.
Claude Code on the web
and
Code Review
connect to your repositories from Anthropic-managed infrastructure. If your GitHub Enterprise Cloud organization restricts access by IP address, enable
IP allow list inheritance for installed GitHub Apps
. The Claude GitHub App registers its IP ranges, so enabling this setting allows access without manual configuration. To
add the ranges to your allow list manually
instead, or to configure other firewalls, see the
Anthropic API IP addresses
.
For self-hosted
GitHub Enterprise Server
instances behind a firewall, allowlist the same
Anthropic API IP addresses
so Anthropic infrastructure can reach your GHES host to clone repositories and post review comments.
​
Additional resources
Claude Code settings
Environment variables reference
Troubleshooting guide
Was this page helpful?
Yes
No
Microsoft Foundry
LLM gateway
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/network-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise network configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marke...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise network configuration
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports various enterprise network and security configurations through environment variables. This includes routing traffic through corporate proxy servers, trusting custom Certificate Authorities (CA), and authenticating with mutual Transport Layer Security (mTLS) certificates for enhanced security.
All environment variables shown on this page can also be configured in
settings.json
.
​
Proxy configuration
​
Environment variables
Claude Code respects standard proxy environment variables:
# HTTPS proxy (recommended)
export
HTTPS_PROXY
=
https
://
proxy
.
example
.
com
:
8080
# HTTP proxy (if HTTPS not available)
export
HTTP_PROXY
=
http
://
proxy
.
example
.
com
:
8080
# Bypass proxy for specific requests - space-separated format
export
NO_PROXY
=
"localhost 192.168.1.1 example.com .example.com"
# Bypass proxy for specific requests - comma-separated format
export
NO_PROXY
=
"localhost,192.168.1.1,example.com,.example.com"
# Bypass proxy for all requests
export
NO_PROXY
=
"*"
Claude Code does not support SOCKS proxies.
​
Basic authentication
If your proxy requires basic authentication, include credentials in the proxy URL:
export
HTTPS_PROXY
=
http
://
username
:
password
@
proxy
.
example
.
com
:
8080
Avoid hardcoding passwords in scripts. Use environment variables or secure credential storage instead.
For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.
​
CA certificate store
By default, Claude Code trusts both its bundled Mozilla CA certificates and your operating system’s certificate store. Enterprise TLS-inspection proxies such as CrowdStrike Falcon and Zscaler work without additional configuration when their root certificate is installed in the OS trust store.
CLAUDE_CODE_CERT_STORE
accepts a comma-separated list of sources. Recognized values are
bundled
for the Mozilla CA set shipped with Claude Code and
system
for the operating system trust store. The default is
bundled,system
.
To trust only the bundled Mozilla CA set:
export
CLAUDE_CODE_CERT_STORE
=
bundled
To trust only the OS certificate store:
export
CLAUDE_CODE_CERT_STORE
=
system
CLAUDE_CODE_CERT_STORE
has no dedicated
settings.json
schema key. Set it via the
env
block in
~/.claude/settings.json
or directly in the process environment.
​
Custom CA certificates
If your enterprise environment uses a custom CA, configure Claude Code to trust it directly:
export
NODE_EXTRA_CA_CERTS
=
/
path
/
to
/
ca-cert
.
pem
​
mTLS authentication
For enterprise environments requiring client certificate authentication:
# Client certificate for authentication
export
CLAUDE_CODE_CLIENT_CERT
=
/
path
/
to
/
client-cert
.
pem
# Client private key
export
CLAUDE_CODE_CLIENT_KEY
=
/
path
/
to
/
client-key
.
pem
# Optional: Passphrase for encrypted private key
export
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
=
"your-passphrase"
​
Network access requirements
Claude Code requires access to the following URLs. Allowlist these in your proxy configuration and firewall rules, especially in containerized or restricted network environments.
URL
Required for
api.anthropic.com
Claude API requests
claude.ai
claude.ai account authentication
platform.claude.com
Anthropic Console account authentication
downloads.claude.ai
Plugin executable downloads; native installer and native auto-updater
storage.googleapis.com
Native installer and native auto-updater on versions prior to 2.1.116
bridge.claudeusercontent.com
Claude in Chrome
extension WebSocket bridge
raw.githubusercontent.com
Changelog feed for
/release-notes
and the release notes shown after updating; plugin marketplace install counts
If you install Claude Code through npm or manage your own binary distribution, end users may not need access to
downloads.claude.ai
or
storage.googleapis.com
.
Claude Code also sends optional operational telemetry by default, which you can disable with environment variables. See
Telemetry services
for how to disable it before finalizing your allowlist.
When using
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
, model traffic and authentication go to your provider instead of
api.anthropic.com
,
claude.ai
, or
platform.claude.com
. The WebFetch tool still calls
api.anthropic.com
for its
domain safety check
unless you set
skipWebFetchPreflight: true
in
settings
.
Claude Code on the web
and
Code Review
connect to your repositories from Anthropic-managed infrastructure. If your GitHub Enterprise Cloud organization restricts access by IP address, enable
IP allow list inheritance for installed GitHub Apps
. The Claude GitHub App registers its IP ranges, so enabling this setting allows access without manual configuration. To
add the ranges to your allow list manually
instead, or to configure other firewalls, see the
Anthropic API IP addresses
.
For self-hosted
GitHub Enterprise Server
instances behind a firewall, allowlist the same
Anthropic API IP addresses
so Anthropic infrastructure can reach your GHES host to clone repositories and post review comments.
​
Additional resources
Claude Code settings
Environment variables reference
Troubleshooting guide
Was this page helpful?
Yes
No
Microsoft Foundry
LLM gateway
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/network-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code on Claude Platform on AWS</title>
  <link>https://code.claude.com/docs/en/claude-platform-on-aws</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/claude-platform-on-aws</guid>
  <pubDate>Mon, 09 Sep 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Claude Platform on AWS
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Claude Platform on AWS
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Platform on AWS is the Anthropic-operated Claude API with AWS authentication, IAM access control, and AWS Marketplace billing. Requests reach Anthropic’s API directly, so you get the same models and features as the
Claude API
on the same release schedule. You authenticate with AWS credentials or a workspace API key, and you pay through AWS Marketplace.
Use this guide to point Claude Code at a workspace you’ve already provisioned through Claude Platform on AWS. For the AWS subscription and workspace setup that comes before this, see the
Claude Platform on AWS documentation
.
Subscribing through AWS Marketplace provisions a new Anthropic organization tied to your AWS account. This organization is separate from any organization you already have with Anthropic, and credentials don’t transfer between them. Use the workspace ID and API keys from the AWS-linked organization, not from a pre-existing Claude Console account.
​
Prerequisites
Before configuring Claude Code, you need:
An active Claude Platform on AWS subscription through AWS Marketplace
A workspace in your AWS-linked Anthropic organization, with its workspace ID
An IAM principal with permission to invoke the Anthropic service, or an API key scoped to the workspace
AWS credentials in your environment, in
~/.aws/credentials
, or from an attached IAM role if you want SigV4 authentication. The AWS CLI is required only for the SSO login flow.
​
Setup
​
1. Configure AWS credentials
Claude Code supports two authentication methods for Claude Platform on AWS. Choose the method that fits how your team manages access.
Option A: AWS credentials with SigV4
Claude Code signs requests with SigV4 using the standard AWS credential chain: environment variables, shared credentials in
~/.aws/credentials
, IAM roles, AWS SSO sessions, and any other sources the AWS SDK supports.
For local use, log in with the AWS CLI before starting Claude Code. The example below uses an SSO profile, but any method that produces credentials in the standard locations works.
aws
sso
login
--profile
my-profile
export
AWS_PROFILE
=
my-profile
For CI and automation, give the runner an IAM role with permission to invoke the Anthropic service and set
AWS_REGION
. The credential chain picks the role up automatically.
If your SSO credentials expire mid-session, configure
awsAuthRefresh
so Claude Code re-runs your login command and retries instead of failing. Add the command to your
settings.json
:
{
"awsAuthRefresh"
:
"aws sso login --profile my-profile"
}
Option B: Workspace API key
A workspace API key is a long-lived secret, useful when you don’t want to manage federated AWS credentials. Generate one in the AWS Console under
Claude Platform on AWS → API keys
and set it as
ANTHROPIC_AWS_API_KEY
:
export
ANTHROPIC_AWS_API_KEY
=
sk-ant-xxxxx
The key is sent as
x-api-key
and takes precedence over SigV4, so any AWS credentials in your environment are ignored. API keys from a separate Claude Console organization won’t work here.
Treat workspace API keys like any other production credential. The
user settings file
env
block is a convenient way to scope the key to your machine without exporting it globally.
The
/login
and
/logout
commands don’t change Claude Platform on AWS authentication. Authentication runs through your AWS credentials or workspace API key, not through a Claude.ai subscription.
​
2. Configure Claude Code
Set the environment variables that route Claude Code through Claude Platform on AWS instead of the default Anthropic API.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
AWS_REGION
=
us-east-1
ANTHROPIC_AWS_WORKSPACE_ID
is required and is sent on every request as the
anthropic-workspace-id
header. The base URL is computed from
AWS_REGION
as
https://aws-external-anthropic.{region}.api.aws
. To override the URL directly, set
ANTHROPIC_AWS_BASE_URL
.
Claude Platform on AWS is opt-in even when AWS credentials are present in your environment. Bedrock and Foundry take precedence in provider routing, so unset
CLAUDE_CODE_USE_BEDROCK
and
CLAUDE_CODE_USE_FOUNDRY
if they’re set.
​
3. Pin model versions
Claude Platform on AWS uses the same model IDs as the direct Claude API. The default aliases
opus
,
sonnet
, and
haiku
resolve to the latest versions available in your workspace.
If you deploy Claude Code to a team, pin the model IDs explicitly so a new release doesn’t move everyone at once:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
claude-opus-4-7
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
claude-sonnet-4-6
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
claude-haiku-4-5
For the full list of model IDs and aliases, see
Models overview
. For other model-related variables, see
Model configuration
.
Prompt caching
is enabled automatically. 1-hour cache writes are billed at a higher rate than 5-minute writes. To request a 1-hour cache TTL instead of the 5-minute default, set
ENABLE_PROMPT_CACHING_1H=1
.
​
Use the Agent SDK
The
Agent SDK
reads the same environment variables as the CLI, so any program that spawns the Claude Code subprocess can target Claude Platform on AWS by exporting
CLAUDE_CODE_USE_ANTHROPIC_AWS
,
ANTHROPIC_AWS_WORKSPACE_ID
, and either
ANTHROPIC_AWS_API_KEY
or AWS credentials before the call.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
process
.
env
.
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
"1"
;
process
.
env
.
ANTHROPIC_AWS_WORKSPACE_ID
=
"wrkspc_01ABCDEFGHIJKLMN"
;
process
.
env
.
AWS_REGION
=
"us-east-1"
;
for
await
(
const
msg
of
query
({
prompt:
"What's in this repo?"
})) {
console
.
log
(
msg
);
}
This example relies on the ambient AWS credential chain for SigV4. To authenticate with a workspace API key instead, set
ANTHROPIC_AWS_API_KEY
the same way. For the broader Agent SDK surface, see
Agent SDK overview
.
​
Route through a corporate proxy
To route traffic through a proxy or
LLM gateway
, set
ANTHROPIC_AWS_BASE_URL
to the proxy’s address. Claude Code sends requests to that URL with the same workspace and authentication headers, so any gateway that forwards them unchanged works.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
ANTHROPIC_AWS_BASE_URL
=
https
://
anthropic-proxy
.
example
.
com
If your gateway signs requests itself, set
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH=1
so Claude Code sends unsigned requests and lets the gateway add SigV4 headers before forwarding to AWS. If the gateway requires its own token, set it in
ANTHROPIC_AUTH_TOKEN
.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
ANTHROPIC_AWS_BASE_URL
=
https
://
anthropic-proxy
.
example
.
com
​
Troubleshooting
Run
/status
to see the resolved provider and any explicitly configured workspace ID, region, base URL override, and auth-skip setting. This is the fastest way to confirm Claude Code is targeting Claude Platform on AWS at all.
​
403 Forbidden
or
AccessDenied
on every request
The IAM principal Claude Code resolved likely lacks permission to invoke the Anthropic service in your workspace. Check the role attached to your AWS profile or the runner that started Claude Code, and verify it has the
aws-external-anthropic
actions documented in the
IAM action reference
.
If you set
ANTHROPIC_AWS_API_KEY
, the key takes precedence over SigV4 and a stale key produces the same error. Regenerate the key in the AWS Console under
Claude Platform on AWS → API keys
or unset the variable to fall back to your AWS credentials.
​
Requests fail with a missing-workspace error
ANTHROPIC_AWS_WORKSPACE_ID
is likely unset or empty. Every Claude Platform on AWS request must include the workspace ID. It is not implied by your AWS credentials. Find the ID under
Workspaces
on the AWS Console service page and export it before starting Claude Code.
​
Requests still go to
api.anthropic.com
CLAUDE_CODE_USE_ANTHROPIC_AWS
is likely unset or set to a value that doesn’t parse as truthy. Set it to
1
and run
/status
to confirm the resolved provider. If
CLAUDE_CODE_USE_BEDROCK
or
CLAUDE_CODE_USE_FOUNDRY
is also set, those take precedence over Claude Platform on AWS.
​
Additional resources
The Claude Platform on AWS subscription, workspace, and IAM setup that comes before configuring Claude Code is covered in the platform documentation:
Claude Platform on AWS overview
: subscription, workspace setup, and product reference
IAM action reference
: permissions and managed policies
Was this page helpful?
Yes
No
Amazon Bedrock
Google Vertex AI
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-platform-on-aws" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Claude Platform on AWS
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Claude Platform on AWS
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Platform on AWS is the Anthropic-operated Claude API with AWS authentication, IAM access control, and AWS Marketplace billing. Requests reach Anthropic’s API directly, so you get the same models and features as the
Claude API
on the same release schedule. You authenticate with AWS credentials or a workspace API key, and you pay through AWS Marketplace.
Use this guide to point Claude Code at a workspace you’ve already provisioned through Claude Platform on AWS. For the AWS subscription and workspace setup that comes before this, see the
Claude Platform on AWS documentation
.
Subscribing through AWS Marketplace provisions a new Anthropic organization tied to your AWS account. This organization is separate from any organization you already have with Anthropic, and credentials don’t transfer between them. Use the workspace ID and API keys from the AWS-linked organization, not from a pre-existing Claude Console account.
​
Prerequisites
Before configuring Claude Code, you need:
An active Claude Platform on AWS subscription through AWS Marketplace
A workspace in your AWS-linked Anthropic organization, with its workspace ID
An IAM principal with permission to invoke the Anthropic service, or an API key scoped to the workspace
AWS credentials in your environment, in
~/.aws/credentials
, or from an attached IAM role if you want SigV4 authentication. The AWS CLI is required only for the SSO login flow.
​
Setup
​
1. Configure AWS credentials
Claude Code supports two authentication methods for Claude Platform on AWS. Choose the method that fits how your team manages access.
Option A: AWS credentials with SigV4
Claude Code signs requests with SigV4 using the standard AWS credential chain: environment variables, shared credentials in
~/.aws/credentials
, IAM roles, AWS SSO sessions, and any other sources the AWS SDK supports.
For local use, log in with the AWS CLI before starting Claude Code. The example below uses an SSO profile, but any method that produces credentials in the standard locations works.
aws
sso
login
--profile
my-profile
export
AWS_PROFILE
=
my-profile
For CI and automation, give the runner an IAM role with permission to invoke the Anthropic service and set
AWS_REGION
. The credential chain picks the role up automatically.
If your SSO credentials expire mid-session, configure
awsAuthRefresh
so Claude Code re-runs your login command and retries instead of failing. Add the command to your
settings.json
:
{
"awsAuthRefresh"
:
"aws sso login --profile my-profile"
}
Option B: Workspace API key
A workspace API key is a long-lived secret, useful when you don’t want to manage federated AWS credentials. Generate one in the AWS Console under
Claude Platform on AWS → API keys
and set it as
ANTHROPIC_AWS_API_KEY
:
export
ANTHROPIC_AWS_API_KEY
=
sk-ant-xxxxx
The key is sent as
x-api-key
and takes precedence over SigV4, so any AWS credentials in your environment are ignored. API keys from a separate Claude Console organization won’t work here.
Treat workspace API keys like any other production credential. The
user settings file
env
block is a convenient way to scope the key to your machine without exporting it globally.
The
/login
and
/logout
commands don’t change Claude Platform on AWS authentication. Authentication runs through your AWS credentials or workspace API key, not through a Claude.ai subscription.
​
2. Configure Claude Code
Set the environment variables that route Claude Code through Claude Platform on AWS instead of the default Anthropic API.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
AWS_REGION
=
us-east-1
ANTHROPIC_AWS_WORKSPACE_ID
is required and is sent on every request as the
anthropic-workspace-id
header. The base URL is computed from
AWS_REGION
as
https://aws-external-anthropic.{region}.api.aws
. To override the URL directly, set
ANTHROPIC_AWS_BASE_URL
.
Claude Platform on AWS is opt-in even when AWS credentials are present in your environment. Bedrock and Foundry take precedence in provider routing, so unset
CLAUDE_CODE_USE_BEDROCK
and
CLAUDE_CODE_USE_FOUNDRY
if they’re set.
​
3. Pin model versions
Claude Platform on AWS uses the same model IDs as the direct Claude API. The default aliases
opus
,
sonnet
, and
haiku
resolve to the latest versions available in your workspace.
If you deploy Claude Code to a team, pin the model IDs explicitly so a new release doesn’t move everyone at once:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
claude-opus-4-7
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
claude-sonnet-4-6
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
claude-haiku-4-5
For the full list of model IDs and aliases, see
Models overview
. For other model-related variables, see
Model configuration
.
Prompt caching
is enabled automatically. 1-hour cache writes are billed at a higher rate than 5-minute writes. To request a 1-hour cache TTL instead of the 5-minute default, set
ENABLE_PROMPT_CACHING_1H=1
.
​
Use the Agent SDK
The
Agent SDK
reads the same environment variables as the CLI, so any program that spawns the Claude Code subprocess can target Claude Platform on AWS by exporting
CLAUDE_CODE_USE_ANTHROPIC_AWS
,
ANTHROPIC_AWS_WORKSPACE_ID
, and either
ANTHROPIC_AWS_API_KEY
or AWS credentials before the call.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
process
.
env
.
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
"1"
;
process
.
env
.
ANTHROPIC_AWS_WORKSPACE_ID
=
"wrkspc_01ABCDEFGHIJKLMN"
;
process
.
env
.
AWS_REGION
=
"us-east-1"
;
for
await
(
const
msg
of
query
({
prompt:
"What's in this repo?"
})) {
console
.
log
(
msg
);
}
This example relies on the ambient AWS credential chain for SigV4. To authenticate with a workspace API key instead, set
ANTHROPIC_AWS_API_KEY
the same way. For the broader Agent SDK surface, see
Agent SDK overview
.
​
Route through a corporate proxy
To route traffic through a proxy or
LLM gateway
, set
ANTHROPIC_AWS_BASE_URL
to the proxy’s address. Claude Code sends requests to that URL with the same workspace and authentication headers, so any gateway that forwards them unchanged works.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
ANTHROPIC_AWS_BASE_URL
=
https
://
anthropic-proxy
.
example
.
com
If your gateway signs requests itself, set
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH=1
so Claude Code sends unsigned requests and lets the gateway add SigV4 headers before forwarding to AWS. If the gateway requires its own token, set it in
ANTHROPIC_AUTH_TOKEN
.
export
CLAUDE_CODE_USE_ANTHROPIC_AWS
=
1
export
CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH
=
1
export
ANTHROPIC_AWS_WORKSPACE_ID
=
wrkspc_01ABCDEFGHIJKLMN
export
ANTHROPIC_AWS_BASE_URL
=
https
://
anthropic-proxy
.
example
.
com
​
Troubleshooting
Run
/status
to see the resolved provider and any explicitly configured workspace ID, region, base URL override, and auth-skip setting. This is the fastest way to confirm Claude Code is targeting Claude Platform on AWS at all.
​
403 Forbidden
or
AccessDenied
on every request
The IAM principal Claude Code resolved likely lacks permission to invoke the Anthropic service in your workspace. Check the role attached to your AWS profile or the runner that started Claude Code, and verify it has the
aws-external-anthropic
actions documented in the
IAM action reference
.
If you set
ANTHROPIC_AWS_API_KEY
, the key takes precedence over SigV4 and a stale key produces the same error. Regenerate the key in the AWS Console under
Claude Platform on AWS → API keys
or unset the variable to fall back to your AWS credentials.
​
Requests fail with a missing-workspace error
ANTHROPIC_AWS_WORKSPACE_ID
is likely unset or empty. Every Claude Platform on AWS request must include the workspace ID. It is not implied by your AWS credentials. Find the ID under
Workspaces
on the AWS Console service page and export it before starting Claude Code.
​
Requests still go to
api.anthropic.com
CLAUDE_CODE_USE_ANTHROPIC_AWS
is likely unset or set to a value that doesn’t parse as truthy. Set it to
1
and run
/status
to confirm the resolved provider. If
CLAUDE_CODE_USE_BEDROCK
or
CLAUDE_CODE_USE_FOUNDRY
is also set, those take precedence over Claude Platform on AWS.
​
Additional resources
The Claude Platform on AWS subscription, workspace, and IAM setup that comes before configuring Claude Code is covered in the platform documentation:
Claude Platform on AWS overview
: subscription, workspace setup, and product reference
IAM action reference
: permissions and managed policies
Was this page helpful?
Yes
No
Amazon Bedrock
Google Vertex AI
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-platform-on-aws" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Get started with the desktop app</title>
  <link>https://code.claude.com/docs/en/desktop-quickstart</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/desktop-quickstart</guid>
  <pubDate>Thu, 05 Sep 2024 00:00:00 +0000</pubDate>
  <category>Getting Started</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Get started with the desktop app
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Get started with the desktop app
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The desktop app gives you Claude Code with a graphical interface built for running multiple sessions side by side: a sidebar for managing parallel work, a drag-and-drop layout with an integrated terminal and file editor, visual diff review, live app preview, GitHub PR monitoring with auto-merge, and scheduled tasks. No terminal required.
Download for macOS
Universal build for Intel and Apple Silicon
Download for Windows
For x64 processors
For Windows ARM64, download the
ARM64 installer
. The desktop app is not available on Linux; use the
CLI
instead.
Claude Code requires a
Pro, Max, Team, or Enterprise subscription
.
This page walks through installing the app and starting your first session. If you’re already set up, see
Use Claude Code Desktop
for the full reference.
The desktop app has three tabs:
Chat
: General conversation with no file access, similar to claude.ai.
Cowork
: An autonomous background agent that works on tasks in a cloud VM with its own environment. It can run independently while you do other work.
Code
: An interactive coding assistant with direct access to your local files. You review and approve each change in real time.
Chat and Cowork are covered in the
Claude Desktop support articles
. This page focuses on the
Code
tab.
​
Install
1
Install and sign in
Download the installer for your platform from the links above and run it. Launch Claude from your Applications folder on macOS or the Start menu on Windows, then sign in with your Anthropic account.
2
Open the Code tab
Click the
Code
tab at the top center. If clicking Code prompts you to upgrade, you need to
subscribe to a paid plan
first. If it prompts you to sign in online, complete the sign-in and restart the app. If you see a 403 error, see
authentication troubleshooting
.
The desktop app includes Claude Code. You don’t need to install Node.js or the CLI separately. To use
claude
from the terminal, install the CLI separately. See
Get started with the CLI
.
​
Start your first session
With the Code tab open, choose a project and give Claude something to do.
1
Choose an environment and folder
Select
Local
to run Claude on your machine using your files directly. Click
Select folder
and choose your project directory.
Start with a small project you know well. It’s the fastest way to see what Claude Code can do. On Windows,
Git
must be installed for local sessions to work. Most Macs include Git by default.
You can also select:
Remote
: Run sessions on Anthropic’s cloud infrastructure that continue even if you close the app. Remote sessions use the same infrastructure as
Claude Code on the web
.
SSH
: Connect to a remote machine over SSH, such as your own servers, cloud VMs, or dev containers. Desktop installs Claude Code on the remote machine automatically the first time you connect.
2
Choose a model
Select a model from the dropdown next to the send button. See
models
for a comparison of Opus, Sonnet, and Haiku. You can change the model later from the same dropdown.
3
Tell Claude what to do
Type what you want Claude to do:
Find a TODO comment and fix it
Add tests for the main function
Create a CLAUDE.md with instructions for this codebase
A
session
is a conversation with Claude about your code. Each session tracks its own context and changes, so you can work on multiple tasks without them interfering with each other.
4
Review and accept changes
By default, the Code tab starts in
Ask permissions mode
, where Claude proposes changes and waits for your approval before applying them. You’ll see:
A
diff view
showing exactly what will change in each file
Accept/Reject buttons to approve or decline each change
Real-time updates as Claude works through your request
If you reject a change, Claude will ask how you’d like to proceed differently. Your files aren’t modified until you accept.
​
Now what?
You’ve made your first edit. For the full reference on everything Desktop can do, see
Use Claude Code Desktop
. Here are some things to try next.
Interrupt and steer.
You can interrupt Claude at any point. If it’s going down the wrong path, click the stop button or type your correction and press
Enter
. Claude stops what it’s doing and adjusts based on your input. You don’t have to wait for it to finish or start over.
Give Claude more context.
Type
@filename
in the prompt box to pull a specific file into the conversation, attach images and PDFs using the attachment button, or drag and drop files directly into the prompt. The more context Claude has, the better the results. See
Add files and context
.
Use skills for repeatable tasks.
Type
/
or click
+
→
Slash commands
to browse
built-in commands
,
custom skills
, and plugin skills. Skills are reusable prompts you can invoke whenever you need them, like code review checklists or deployment steps.
Review changes before committing.
After Claude edits files, a
+12 -1
indicator appears. Click it to open the
diff view
, review modifications file by file, and comment on specific lines. Claude reads your comments and revises. Click
Review code
to have Claude evaluate the diffs itself and leave inline suggestions.
Adjust how much control you have.
Your
permission mode
controls the balance. Ask permissions (default) requires approval before every edit. Auto accept edits auto-accepts file edits for faster iteration. Plan mode lets Claude map out an approach without touching any files, which is useful before a large refactor.
Add plugins for more capabilities.
Click the
+
button next to the prompt box and select
Plugins
to browse and install
plugins
that add skills, agents, MCP servers, and more.
Arrange your workspace.
Drag the chat, diff, terminal, file, and preview panes into whatever layout you want. Open the terminal with
Ctrl+`
to run commands alongside your session, or click a file path to open it in the file pane. See
Arrange your workspace
.
Preview your app.
Click the
Preview
dropdown to run your dev server directly in the desktop. Claude can view the running app, test endpoints, inspect logs, and iterate on what it sees. See
Preview your app
.
Track your pull request.
After opening a PR, Claude Code monitors CI check results and can automatically fix failures or merge the PR once all checks pass. See
Monitor pull request status
.
Put Claude on a schedule.
Set up
scheduled tasks
to run Claude automatically on a recurring basis: a daily code review every morning, a weekly dependency audit, or a briefing that pulls from your connected tools.
Scale up when you’re ready.
Open
parallel sessions
from the sidebar to work on multiple tasks at once, each in its own Git worktree, and open the
tasks pane
to watch the subagents and background commands a session has running. Open a
side chat
to ask a question without derailing the main thread. Send
long-running work to the cloud
so it continues even if you close the app, or
continue a session on the web or in your IDE
if a task takes longer than expected.
Connect external tools
like GitHub, Slack, and Linear to bring your workflow together.
​
Coming from the CLI?
Desktop runs the same engine as the CLI with a graphical interface. You can run both simultaneously on the same project, and they share configuration (CLAUDE.md files, MCP servers, hooks, skills, and settings). For a full comparison of features, flag equivalents, and what’s not available in Desktop, see
CLI comparison
.
​
What’s next
Use Claude Code Desktop
: permission modes, parallel sessions, diff view, connectors, and enterprise configuration
Troubleshooting
: solutions to common errors and setup issues
Best practices
: tips for writing effective prompts and getting the most out of Claude Code
Common workflows
: tutorials for debugging, refactoring, testing, and more
Was this page helpful?
Yes
No
Ultrareview
Reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Get started with the desktop app
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Get started with the desktop app
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The desktop app gives you Claude Code with a graphical interface built for running multiple sessions side by side: a sidebar for managing parallel work, a drag-and-drop layout with an integrated terminal and file editor, visual diff review, live app preview, GitHub PR monitoring with auto-merge, and scheduled tasks. No terminal required.
Download for macOS
Universal build for Intel and Apple Silicon
Download for Windows
For x64 processors
For Windows ARM64, download the
ARM64 installer
. The desktop app is not available on Linux; use the
CLI
instead.
Claude Code requires a
Pro, Max, Team, or Enterprise subscription
.
This page walks through installing the app and starting your first session. If you’re already set up, see
Use Claude Code Desktop
for the full reference.
The desktop app has three tabs:
Chat
: General conversation with no file access, similar to claude.ai.
Cowork
: An autonomous background agent that works on tasks in a cloud VM with its own environment. It can run independently while you do other work.
Code
: An interactive coding assistant with direct access to your local files. You review and approve each change in real time.
Chat and Cowork are covered in the
Claude Desktop support articles
. This page focuses on the
Code
tab.
​
Install
1
Install and sign in
Download the installer for your platform from the links above and run it. Launch Claude from your Applications folder on macOS or the Start menu on Windows, then sign in with your Anthropic account.
2
Open the Code tab
Click the
Code
tab at the top center. If clicking Code prompts you to upgrade, you need to
subscribe to a paid plan
first. If it prompts you to sign in online, complete the sign-in and restart the app. If you see a 403 error, see
authentication troubleshooting
.
The desktop app includes Claude Code. You don’t need to install Node.js or the CLI separately. To use
claude
from the terminal, install the CLI separately. See
Get started with the CLI
.
​
Start your first session
With the Code tab open, choose a project and give Claude something to do.
1
Choose an environment and folder
Select
Local
to run Claude on your machine using your files directly. Click
Select folder
and choose your project directory.
Start with a small project you know well. It’s the fastest way to see what Claude Code can do. On Windows,
Git
must be installed for local sessions to work. Most Macs include Git by default.
You can also select:
Remote
: Run sessions on Anthropic’s cloud infrastructure that continue even if you close the app. Remote sessions use the same infrastructure as
Claude Code on the web
.
SSH
: Connect to a remote machine over SSH, such as your own servers, cloud VMs, or dev containers. Desktop installs Claude Code on the remote machine automatically the first time you connect.
2
Choose a model
Select a model from the dropdown next to the send button. See
models
for a comparison of Opus, Sonnet, and Haiku. You can change the model later from the same dropdown.
3
Tell Claude what to do
Type what you want Claude to do:
Find a TODO comment and fix it
Add tests for the main function
Create a CLAUDE.md with instructions for this codebase
A
session
is a conversation with Claude about your code. Each session tracks its own context and changes, so you can work on multiple tasks without them interfering with each other.
4
Review and accept changes
By default, the Code tab starts in
Ask permissions mode
, where Claude proposes changes and waits for your approval before applying them. You’ll see:
A
diff view
showing exactly what will change in each file
Accept/Reject buttons to approve or decline each change
Real-time updates as Claude works through your request
If you reject a change, Claude will ask how you’d like to proceed differently. Your files aren’t modified until you accept.
​
Now what?
You’ve made your first edit. For the full reference on everything Desktop can do, see
Use Claude Code Desktop
. Here are some things to try next.
Interrupt and steer.
You can interrupt Claude at any point. If it’s going down the wrong path, click the stop button or type your correction and press
Enter
. Claude stops what it’s doing and adjusts based on your input. You don’t have to wait for it to finish or start over.
Give Claude more context.
Type
@filename
in the prompt box to pull a specific file into the conversation, attach images and PDFs using the attachment button, or drag and drop files directly into the prompt. The more context Claude has, the better the results. See
Add files and context
.
Use skills for repeatable tasks.
Type
/
or click
+
→
Slash commands
to browse
built-in commands
,
custom skills
, and plugin skills. Skills are reusable prompts you can invoke whenever you need them, like code review checklists or deployment steps.
Review changes before committing.
After Claude edits files, a
+12 -1
indicator appears. Click it to open the
diff view
, review modifications file by file, and comment on specific lines. Claude reads your comments and revises. Click
Review code
to have Claude evaluate the diffs itself and leave inline suggestions.
Adjust how much control you have.
Your
permission mode
controls the balance. Ask permissions (default) requires approval before every edit. Auto accept edits auto-accepts file edits for faster iteration. Plan mode lets Claude map out an approach without touching any files, which is useful before a large refactor.
Add plugins for more capabilities.
Click the
+
button next to the prompt box and select
Plugins
to browse and install
plugins
that add skills, agents, MCP servers, and more.
Arrange your workspace.
Drag the chat, diff, terminal, file, and preview panes into whatever layout you want. Open the terminal with
Ctrl+`
to run commands alongside your session, or click a file path to open it in the file pane. See
Arrange your workspace
.
Preview your app.
Click the
Preview
dropdown to run your dev server directly in the desktop. Claude can view the running app, test endpoints, inspect logs, and iterate on what it sees. See
Preview your app
.
Track your pull request.
After opening a PR, Claude Code monitors CI check results and can automatically fix failures or merge the PR once all checks pass. See
Monitor pull request status
.
Put Claude on a schedule.
Set up
scheduled tasks
to run Claude automatically on a recurring basis: a daily code review every morning, a weekly dependency audit, or a briefing that pulls from your connected tools.
Scale up when you’re ready.
Open
parallel sessions
from the sidebar to work on multiple tasks at once, each in its own Git worktree, and open the
tasks pane
to watch the subagents and background commands a session has running. Open a
side chat
to ask a question without derailing the main thread. Send
long-running work to the cloud
so it continues even if you close the app, or
continue a session on the web or in your IDE
if a task takes longer than expected.
Connect external tools
like GitHub, Slack, and Linear to bring your workflow together.
​
Coming from the CLI?
Desktop runs the same engine as the CLI with a graphical interface. You can run both simultaneously on the same project, and they share configuration (CLAUDE.md files, MCP servers, hooks, skills, and settings). For a full comparison of features, flag equivalents, and what’s not available in Desktop, see
CLI comparison
.
​
What’s next
Use Claude Code Desktop
: permission modes, parallel sessions, diff view, connectors, and enterprise configuration
Troubleshooting
: solutions to common errors and setup issues
Best practices
: tips for writing effective prompts and getting the most out of Claude Code
Common workflows
: tutorials for debugging, refactoring, testing, and more
Was this page helpful?
Yes
No
Ultrareview
Reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Track cost and usage</title>
  <link>https://code.claude.com/docs/en/agent-sdk/cost-tracking</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/cost-tracking</guid>
  <pubDate>Tue, 03 Sep 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Track cost and usage
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Track cost and usage
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK provides detailed token usage information for each interaction with Claude. This guide explains how to properly track usage and understand cost reporting, especially when dealing with parallel tool uses and multi-step conversations.
For complete API documentation, see the
TypeScript SDK reference
and
Python SDK reference
.
The
total_cost_usd
and
costUSD
fields are client-side estimates, not authoritative billing data. The SDK computes them locally from a price table bundled at build time, so they can drift from what you are actually billed when:
pricing changes
the installed SDK version does not recognize a model
billing rules apply that the client cannot model
Use these fields for development insight and approximate budgeting. For authoritative billing, use the
Usage and Cost API
or the Usage page in the
Claude Console
. Do not bill end users or trigger financial decisions from these fields.
​
Understand token usage
The TypeScript and Python SDKs expose the same usage data with different field names:
TypeScript
provides per-step token breakdowns on each assistant message (
message.message.id
,
message.message.usage
), per-model cost via
modelUsage
on the result message, and a cumulative total on the result message.
Python
provides per-step token breakdowns on each assistant message (
message.usage
,
message.message_id
), per-model cost via
model_usage
on the result message, and the accumulated total on the result message (
total_cost_usd
and
usage
dict).
Both SDKs use the same underlying cost model and expose the same granularity. The difference is in field naming and where per-step usage is nested.
Cost tracking depends on understanding how the SDK scopes usage data:
query()
call:
one invocation of the SDK’s
query()
function. A single call can involve multiple steps (Claude responds, uses tools, gets results, responds again). Each call produces one
result
message at the end.
Step:
a single request/response cycle within a
query()
call. Each step produces assistant messages with token usage.
Session:
a series of
query()
calls linked by a session ID (using the
resume
option). Each
query()
call within a session reports its own cost independently.
The following diagram shows the message stream from a single
query()
call, with token usage reported at each step and the cumulative estimate at the end:
1
Each step produces assistant messages
When Claude responds, it sends one or more assistant messages. In TypeScript, each assistant message contains a nested
BetaMessage
(accessed via
message.message
) with an
id
and a
usage
object with token counts (
input_tokens
,
output_tokens
). In Python, the
AssistantMessage
dataclass exposes the same data directly via
message.usage
and
message.message_id
. When Claude uses multiple tools in one turn, all messages in that turn share the same ID, so deduplicate by ID to avoid double-counting.
2
The result message provides the cumulative estimate
When the
query()
call completes, the SDK emits a result message with
total_cost_usd
and cumulative
usage
. This is available in both TypeScript (
SDKResultMessage
) and Python (
ResultMessage
). If you make multiple
query()
calls (for example, in a multi-turn session), each result only reflects the cost of that individual call. If you only need the estimated total, you can ignore the per-step usage and read this single value.
​
Get the total cost of a query
The result message (
TypeScript
,
Python
) marks the end of the agent loop for a
query()
call. It includes
total_cost_usd
, the cumulative estimated cost across all steps in that call. This works for both success and error results. If you use sessions to make multiple
query()
calls, each result only reflects the cost of that individual call.
The following examples iterate over the message stream from a
query()
call and print the total cost when the
result
message arrives:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
===
"result"
) {
console
.
log
(
`Total cost: $
${
message
.
total_cost_usd
}
`
);
}
}
​
Track per-step and per-model usage
The examples in this section use TypeScript field names. In Python, the equivalent fields are
AssistantMessage.usage
and
AssistantMessage.message_id
for per-step usage, and
ResultMessage.model_usage
for per-model breakdowns.
​
Track per-step usage
Each assistant message contains a nested
BetaMessage
(accessed via
message.message
) with an
id
and
usage
object with token counts. When Claude uses tools in parallel, multiple messages share the same
id
with identical usage data. Track which IDs you’ve already counted and skip duplicates to avoid inflated totals.
Parallel tool calls produce multiple assistant messages whose nested
BetaMessage
shares the same
id
and identical usage. Always deduplicate by ID to get accurate per-step token counts.
The following example accumulates input and output tokens across all steps, counting each unique message ID only once:
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
seenIds
=
new
Set
<
string
>();
let
totalInputTokens
=
0
;
let
totalOutputTokens
=
0
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
===
"assistant"
) {
const
msgId
=
message
.
message
.
id
;
// Parallel tool calls share the same ID, only count once
if
(
!
seenIds
.
has
(
msgId
)) {
seenIds
.
add
(
msgId
);
totalInputTokens
+=
message
.
message
.
usage
.
input_tokens
;
totalOutputTokens
+=
message
.
message
.
usage
.
output_tokens
;
}
}
}
console
.
log
(
`Steps:
${
seenIds
.
size
}
`
);
console
.
log
(
`Input tokens:
${
totalInputTokens
}
`
);
console
.
log
(
`Output tokens:
${
totalOutputTokens
}
`
);
​
Break down usage per model
The result message includes
modelUsage
, a map of model name to per-model token counts and cost. This is useful when you run multiple models (for example, Haiku for subagents and Opus for the main agent) and want to see where tokens are going.
The following example runs a query and prints the cost and token breakdown for each model used:
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
!==
"result"
)
continue
;
for
(
const
[
modelName
,
usage
]
of
Object
.
entries
(
message
.
modelUsage
)) {
console
.
log
(
`
${
modelName
}
: $
${
usage
.
costUSD
.
toFixed
(
4
)
}
`
);
console
.
log
(
`  Input tokens:
${
usage
.
inputTokens
}
`
);
console
.
log
(
`  Output tokens:
${
usage
.
outputTokens
}
`
);
console
.
log
(
`  Cache read:
${
usage
.
cacheReadInputTokens
}
`
);
console
.
log
(
`  Cache creation:
${
usage
.
cacheCreationInputTokens
}
`
);
}
}
​
Accumulate costs across multiple calls
Each
query()
call returns its own
total_cost_usd
. The SDK does not provide a session-level total, so if your application makes multiple
query()
calls (for example, in a multi-turn session or across different users), accumulate the totals yourself.
The following examples run two
query()
calls sequentially, add each call’s
total_cost_usd
to a running total, and print both the per-call and combined cost:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Track cumulative cost across multiple query() calls
let
totalSpend
=
0
;
const
prompts
=
[
"Read the files in src/ and summarize the architecture"
,
"List all exported functions in src/auth.ts"
];
for
(
const
prompt
of
prompts
) {
for
await
(
const
message
of
query
({
prompt
})) {
if
(
message
.
type
===
"result"
) {
totalSpend
+=
message
.
total_cost_usd
;
console
.
log
(
`This call: $
${
message
.
total_cost_usd
}
`
);
}
}
}
console
.
log
(
`Total spend: $
${
totalSpend
.
toFixed
(
4
)
}
`
);
​
Handle errors, caching, and token discrepancies
For accurate cost tracking, account for failed conversations, cache token pricing, and occasional reporting inconsistencies.
​
Resolve output token discrepancies
In rare cases, you might observe different
output_tokens
values for messages with the same ID. When this occurs:
Use the highest value:
the final message in a group typically contains the accurate total.
Prefer the result message:
the
total_cost_usd
in the result message reflects the SDK’s accumulated estimate across all steps, so it is more reliable than summing per-step values yourself. It is still an estimate and may differ from your actual bill.
Report inconsistencies:
file issues at the
Claude Code GitHub repository
.
​
Track costs on failed conversations
Both success and error result messages include
usage
and
total_cost_usd
. If a conversation fails mid-way, you still consumed tokens up to the point of failure. Always read cost data from the result message regardless of its
subtype
.
​
Track cache tokens
The Agent SDK automatically uses
prompt caching
to reduce costs on repeated content. You do not need to configure caching yourself. The usage object includes two additional fields for cache tracking:
cache_creation_input_tokens
: tokens used to create new cache entries (charged at a higher rate than standard input tokens).
cache_read_input_tokens
: tokens read from existing cache entries (charged at a reduced rate).
Track these separately from
input_tokens
to understand caching savings. In TypeScript, these fields are typed on the
Usage
object. In Python, they appear as keys in the
ResultMessage.usage
dict (for example,
message.usage.get("cache_read_input_tokens", 0)
).
​
Extend the prompt cache TTL to one hour
Cache entries written by the SDK use a 5-minute TTL by default when you authenticate with an API key or run on Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If your workload runs many short sessions against the same system prompt and context with gaps longer than 5 minutes between them, the cache expires between sessions and each new session pays full input price.
To request a 1-hour TTL on cache writes, set the
ENABLE_PROMPT_CACHING_1H
environment variable. You can export it in your shell or container environment, or pass it through
options.env
.
The following example enables 1-hour TTL for an agent running on Bedrock:
Python
TypeScript
options
=
ClaudeAgentOptions(
env
=
{
"CLAUDE_CODE_USE_BEDROCK"
:
"1"
,
"ENABLE_PROMPT_CACHING_1H"
:
"1"
,
},
)
Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes, so enabling this trades higher write cost for more cache reads. See
prompt caching pricing
for details. Claude subscription users already receive 1-hour TTL automatically and do not need to set this variable.
​
Related documentation
TypeScript SDK Reference
- Complete API documentation
SDK Overview
- Getting started with the SDK
SDK Permissions
- Managing tool permissions
Was this page helpful?
Yes
No
Rewind file changes with checkpointing
Observability with OpenTelemetry
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/cost-tracking" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Track cost and usage
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Track cost and usage
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK provides detailed token usage information for each interaction with Claude. This guide explains how to properly track usage and understand cost reporting, especially when dealing with parallel tool uses and multi-step conversations.
For complete API documentation, see the
TypeScript SDK reference
and
Python SDK reference
.
The
total_cost_usd
and
costUSD
fields are client-side estimates, not authoritative billing data. The SDK computes them locally from a price table bundled at build time, so they can drift from what you are actually billed when:
pricing changes
the installed SDK version does not recognize a model
billing rules apply that the client cannot model
Use these fields for development insight and approximate budgeting. For authoritative billing, use the
Usage and Cost API
or the Usage page in the
Claude Console
. Do not bill end users or trigger financial decisions from these fields.
​
Understand token usage
The TypeScript and Python SDKs expose the same usage data with different field names:
TypeScript
provides per-step token breakdowns on each assistant message (
message.message.id
,
message.message.usage
), per-model cost via
modelUsage
on the result message, and a cumulative total on the result message.
Python
provides per-step token breakdowns on each assistant message (
message.usage
,
message.message_id
), per-model cost via
model_usage
on the result message, and the accumulated total on the result message (
total_cost_usd
and
usage
dict).
Both SDKs use the same underlying cost model and expose the same granularity. The difference is in field naming and where per-step usage is nested.
Cost tracking depends on understanding how the SDK scopes usage data:
query()
call:
one invocation of the SDK’s
query()
function. A single call can involve multiple steps (Claude responds, uses tools, gets results, responds again). Each call produces one
result
message at the end.
Step:
a single request/response cycle within a
query()
call. Each step produces assistant messages with token usage.
Session:
a series of
query()
calls linked by a session ID (using the
resume
option). Each
query()
call within a session reports its own cost independently.
The following diagram shows the message stream from a single
query()
call, with token usage reported at each step and the cumulative estimate at the end:
1
Each step produces assistant messages
When Claude responds, it sends one or more assistant messages. In TypeScript, each assistant message contains a nested
BetaMessage
(accessed via
message.message
) with an
id
and a
usage
object with token counts (
input_tokens
,
output_tokens
). In Python, the
AssistantMessage
dataclass exposes the same data directly via
message.usage
and
message.message_id
. When Claude uses multiple tools in one turn, all messages in that turn share the same ID, so deduplicate by ID to avoid double-counting.
2
The result message provides the cumulative estimate
When the
query()
call completes, the SDK emits a result message with
total_cost_usd
and cumulative
usage
. This is available in both TypeScript (
SDKResultMessage
) and Python (
ResultMessage
). If you make multiple
query()
calls (for example, in a multi-turn session), each result only reflects the cost of that individual call. If you only need the estimated total, you can ignore the per-step usage and read this single value.
​
Get the total cost of a query
The result message (
TypeScript
,
Python
) marks the end of the agent loop for a
query()
call. It includes
total_cost_usd
, the cumulative estimated cost across all steps in that call. This works for both success and error results. If you use sessions to make multiple
query()
calls, each result only reflects the cost of that individual call.
The following examples iterate over the message stream from a
query()
call and print the total cost when the
result
message arrives:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
===
"result"
) {
console
.
log
(
`Total cost: $
${
message
.
total_cost_usd
}
`
);
}
}
​
Track per-step and per-model usage
The examples in this section use TypeScript field names. In Python, the equivalent fields are
AssistantMessage.usage
and
AssistantMessage.message_id
for per-step usage, and
ResultMessage.model_usage
for per-model breakdowns.
​
Track per-step usage
Each assistant message contains a nested
BetaMessage
(accessed via
message.message
) with an
id
and
usage
object with token counts. When Claude uses tools in parallel, multiple messages share the same
id
with identical usage data. Track which IDs you’ve already counted and skip duplicates to avoid inflated totals.
Parallel tool calls produce multiple assistant messages whose nested
BetaMessage
shares the same
id
and identical usage. Always deduplicate by ID to get accurate per-step token counts.
The following example accumulates input and output tokens across all steps, counting each unique message ID only once:
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
seenIds
=
new
Set
<
string
>();
let
totalInputTokens
=
0
;
let
totalOutputTokens
=
0
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
===
"assistant"
) {
const
msgId
=
message
.
message
.
id
;
// Parallel tool calls share the same ID, only count once
if
(
!
seenIds
.
has
(
msgId
)) {
seenIds
.
add
(
msgId
);
totalInputTokens
+=
message
.
message
.
usage
.
input_tokens
;
totalOutputTokens
+=
message
.
message
.
usage
.
output_tokens
;
}
}
}
console
.
log
(
`Steps:
${
seenIds
.
size
}
`
);
console
.
log
(
`Input tokens:
${
totalInputTokens
}
`
);
console
.
log
(
`Output tokens:
${
totalOutputTokens
}
`
);
​
Break down usage per model
The result message includes
modelUsage
, a map of model name to per-model token counts and cost. This is useful when you run multiple models (for example, Haiku for subagents and Opus for the main agent) and want to see where tokens are going.
The following example runs a query and prints the cost and token breakdown for each model used:
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Summarize this project"
})) {
if
(
message
.
type
!==
"result"
)
continue
;
for
(
const
[
modelName
,
usage
]
of
Object
.
entries
(
message
.
modelUsage
)) {
console
.
log
(
`
${
modelName
}
: $
${
usage
.
costUSD
.
toFixed
(
4
)
}
`
);
console
.
log
(
`  Input tokens:
${
usage
.
inputTokens
}
`
);
console
.
log
(
`  Output tokens:
${
usage
.
outputTokens
}
`
);
console
.
log
(
`  Cache read:
${
usage
.
cacheReadInputTokens
}
`
);
console
.
log
(
`  Cache creation:
${
usage
.
cacheCreationInputTokens
}
`
);
}
}
​
Accumulate costs across multiple calls
Each
query()
call returns its own
total_cost_usd
. The SDK does not provide a session-level total, so if your application makes multiple
query()
calls (for example, in a multi-turn session or across different users), accumulate the totals yourself.
The following examples run two
query()
calls sequentially, add each call’s
total_cost_usd
to a running total, and print both the per-call and combined cost:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Track cumulative cost across multiple query() calls
let
totalSpend
=
0
;
const
prompts
=
[
"Read the files in src/ and summarize the architecture"
,
"List all exported functions in src/auth.ts"
];
for
(
const
prompt
of
prompts
) {
for
await
(
const
message
of
query
({
prompt
})) {
if
(
message
.
type
===
"result"
) {
totalSpend
+=
message
.
total_cost_usd
;
console
.
log
(
`This call: $
${
message
.
total_cost_usd
}
`
);
}
}
}
console
.
log
(
`Total spend: $
${
totalSpend
.
toFixed
(
4
)
}
`
);
​
Handle errors, caching, and token discrepancies
For accurate cost tracking, account for failed conversations, cache token pricing, and occasional reporting inconsistencies.
​
Resolve output token discrepancies
In rare cases, you might observe different
output_tokens
values for messages with the same ID. When this occurs:
Use the highest value:
the final message in a group typically contains the accurate total.
Prefer the result message:
the
total_cost_usd
in the result message reflects the SDK’s accumulated estimate across all steps, so it is more reliable than summing per-step values yourself. It is still an estimate and may differ from your actual bill.
Report inconsistencies:
file issues at the
Claude Code GitHub repository
.
​
Track costs on failed conversations
Both success and error result messages include
usage
and
total_cost_usd
. If a conversation fails mid-way, you still consumed tokens up to the point of failure. Always read cost data from the result message regardless of its
subtype
.
​
Track cache tokens
The Agent SDK automatically uses
prompt caching
to reduce costs on repeated content. You do not need to configure caching yourself. The usage object includes two additional fields for cache tracking:
cache_creation_input_tokens
: tokens used to create new cache entries (charged at a higher rate than standard input tokens).
cache_read_input_tokens
: tokens read from existing cache entries (charged at a reduced rate).
Track these separately from
input_tokens
to understand caching savings. In TypeScript, these fields are typed on the
Usage
object. In Python, they appear as keys in the
ResultMessage.usage
dict (for example,
message.usage.get("cache_read_input_tokens", 0)
).
​
Extend the prompt cache TTL to one hour
Cache entries written by the SDK use a 5-minute TTL by default when you authenticate with an API key or run on Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If your workload runs many short sessions against the same system prompt and context with gaps longer than 5 minutes between them, the cache expires between sessions and each new session pays full input price.
To request a 1-hour TTL on cache writes, set the
ENABLE_PROMPT_CACHING_1H
environment variable. You can export it in your shell or container environment, or pass it through
options.env
.
The following example enables 1-hour TTL for an agent running on Bedrock:
Python
TypeScript
options
=
ClaudeAgentOptions(
env
=
{
"CLAUDE_CODE_USE_BEDROCK"
:
"1"
,
"ENABLE_PROMPT_CACHING_1H"
:
"1"
,
},
)
Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes, so enabling this trades higher write cost for more cache reads. See
prompt caching pricing
for details. Claude subscription users already receive 1-hour TTL automatically and do not need to set this variable.
​
Related documentation
TypeScript SDK Reference
- Complete API documentation
SDK Overview
- Getting started with the SDK
SDK Permissions
- Managing tool permissions
Was this page helpful?
Yes
No
Rewind file changes with checkpointing
Observability with OpenTelemetry
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/cost-tracking" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Plugins reference</title>
  <link>https://code.claude.com/docs/en/plugins-reference</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/plugins-reference</guid>
  <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
  <category>Reference</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Plugins reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Looking to install plugins? See
Discover and i...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Plugins reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Looking to install plugins? See
Discover and install plugins
. For creating plugins, see
Plugins
. For distributing plugins, see
Plugin marketplaces
.
This reference provides complete technical specifications for the Claude Code plugin system, including component schemas, CLI commands, and development tools.
A
plugin
is a self-contained directory of components that extends Claude Code with custom functionality. Plugin components include skills, agents, hooks, MCP servers, LSP servers, and monitors.
​
Plugin components reference
​
Skills
Plugins add skills to Claude Code, creating
/name
shortcuts that you or Claude can invoke.
Location
:
skills/
or
commands/
directory in plugin root
File format
: Skills are directories with
SKILL.md
; commands are simple markdown files
Skill structure
:
skills/
├── pdf-processor/
│   ├── SKILL.md
│   ├── reference.md (optional)
│   └── scripts/ (optional)
└── code-reviewer/
└── SKILL.md
Integration behavior
:
Skills and commands are automatically discovered when the plugin is installed
Claude can invoke them automatically based on task context
Skills can include supporting files alongside SKILL.md
For complete details, see
Skills
.
​
Agents
Plugins can provide specialized subagents for specific tasks that Claude can invoke automatically when appropriate.
Location
:
agents/
directory in plugin root
File format
: Markdown files describing agent capabilities
Agent structure
:
---
name
:
agent-name
description
:
What this agent specializes in and when Claude should invoke it
model
:
sonnet
effort
:
medium
maxTurns
:
20
disallowedTools
:
Write, Edit
---
Detailed system prompt for the agent describing its role, expertise, and behavior.
Plugin agents support
name
,
description
,
model
,
effort
,
maxTurns
,
tools
,
disallowedTools
,
skills
,
memory
,
background
, and
isolation
frontmatter fields. The only valid
isolation
value is
"worktree"
. For security reasons,
hooks
,
mcpServers
, and
permissionMode
are not supported for plugin-shipped agents.
Integration points
:
Agents appear in the
/agents
interface
Claude can invoke agents automatically based on task context
Agents can be invoked manually by users
Plugin agents work alongside built-in Claude agents
For complete details, see
Subagents
.
​
Hooks
Plugins can provide event handlers that respond to Claude Code events automatically.
Location
:
hooks/hooks.json
in plugin root, or inline in plugin.json
Format
: JSON configuration with event matchers and actions
Hook configuration
:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/format-code.sh"
}
]
}
]
}
}
Plugin hooks respond to the same lifecycle events as
user-defined hooks
:
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
Hook types
:
command
: execute shell commands or scripts
http
: send the event JSON as a POST request to a URL
mcp_tool
: call a tool on a configured
MCP server
prompt
: evaluate a prompt with an LLM (uses
$ARGUMENTS
placeholder for context)
agent
: run an agentic verifier with tools for complex verification tasks
​
MCP servers
Plugins can bundle Model Context Protocol (MCP) servers to connect Claude Code with external tools and services.
Location
:
.mcp.json
in plugin root, or inline in plugin.json
Format
: Standard MCP server configuration
MCP server configuration
:
{
"mcpServers"
: {
"plugin-database"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
],
"env"
: {
"DB_PATH"
:
"${CLAUDE_PLUGIN_ROOT}/data"
}
},
"plugin-api-client"
: {
"command"
:
"npx"
,
"args"
: [
"@company/mcp-server"
,
"--plugin-mode"
],
"cwd"
:
"${CLAUDE_PLUGIN_ROOT}"
}
}
}
Integration behavior
:
Plugin MCP servers start automatically when the plugin is enabled
Servers appear as standard MCP tools in Claude’s toolkit
Server capabilities integrate seamlessly with Claude’s existing tools
Plugin servers can be configured independently of user MCP servers
​
LSP servers
Looking to use LSP plugins? Install them from the official marketplace: search for “lsp” in the
/plugin
Discover tab. This section documents how to create LSP plugins for languages not covered by the official marketplace.
Plugins can provide
Language Server Protocol
(LSP) servers to give Claude real-time code intelligence while working on your codebase.
LSP integration provides:
Instant diagnostics
: Claude sees errors and warnings immediately after each edit
Code navigation
: go to definition, find references, and hover information
Language awareness
: type information and documentation for code symbols
Location
:
.lsp.json
in plugin root, or inline in
plugin.json
Format
: JSON configuration mapping language server names to their configurations
.lsp.json
file format
:
{
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
Inline in
plugin.json
:
{
"name"
:
"my-plugin"
,
"lspServers"
: {
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
}
Required fields:
Field
Description
command
The LSP binary to execute (must be in PATH)
extensionToLanguage
Maps file extensions to language identifiers
Optional fields:
Field
Description
args
Command-line arguments for the LSP server
transport
Communication transport:
stdio
(default) or
socket
env
Environment variables to set when starting the server
initializationOptions
Options passed to the server during initialization
settings
Settings passed via
workspace/didChangeConfiguration
workspaceFolder
Workspace folder path for the server
startupTimeout
Max time to wait for server startup (milliseconds)
shutdownTimeout
Max time to wait for graceful shutdown (milliseconds)
restartOnCrash
Whether to automatically restart the server if it crashes
maxRestarts
Maximum number of restart attempts before giving up
You must install the language server binary separately.
LSP plugins configure how Claude Code connects to a language server, but they don’t include the server itself. If you see
Executable not found in $PATH
in the
/plugin
Errors tab, install the required binary for your language.
Available LSP plugins:
Plugin
Language server
Install command
pyright-lsp
Pyright (Python)
pip install pyright
or
npm install -g pyright
typescript-lsp
TypeScript Language Server
npm install -g typescript-language-server typescript
rust-analyzer-lsp
rust-analyzer
See rust-analyzer installation
Install the language server first, then install the plugin from the marketplace.
​
Monitors
Plugins can declare background monitors that Claude Code starts automatically when the plugin is active. Each monitor runs a shell command for the lifetime of the session and delivers every stdout line to Claude as a notification, so Claude can react to log entries, status changes, or polled events without being asked to start the watch itself.
Plugin monitors use the same mechanism as the
Monitor tool
and share its availability constraints. They run only in interactive CLI sessions, run unsandboxed at the same trust level as
hooks
, and are skipped on hosts where the Monitor tool is unavailable.
Plugin monitors require Claude Code v2.1.105 or later.
Location
:
monitors/monitors.json
in the plugin root, or inline in
plugin.json
Format
: JSON array of monitor entries
The following
monitors/monitors.json
watches a deployment status endpoint and a local error log:
[
{
"name"
:
"deploy-status"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/poll-deploy.sh ${user_config.api_endpoint}"
,
"description"
:
"Deployment status changes"
},
{
"name"
:
"error-log"
,
"command"
:
"tail -F ./logs/error.log"
,
"description"
:
"Application error log"
,
"when"
:
"on-skill-invoke:debug"
}
]
To declare monitors inline, set
experimental.monitors
in
plugin.json
to the same array. To load from a non-default path, set
experimental.monitors
to a relative path string such as
"./config/monitors.json"
. Monitors are an
experimental component
.
Required fields:
Field
Description
name
Identifier unique within the plugin. Prevents duplicate processes when the plugin reloads or a skill is invoked again
command
Shell command run as a persistent background process in the session working directory
description
Short summary of what is being watched. Shown in the task panel and in notification summaries
Optional fields:
Field
Description
when
Controls when the monitor starts.
"always"
starts it at session start and on plugin reload, and is the default.
"on-skill-invoke:<skill-name>"
starts it the first time the named skill in this plugin is dispatched
The
command
value supports the same
variable substitutions
as MCP and LSP server configs:
${CLAUDE_PLUGIN_ROOT}
,
${CLAUDE_PLUGIN_DATA}
,
${CLAUDE_PROJECT_DIR}
,
${user_config.*}
, and any
${ENV_VAR}
from the environment. Prefix the command with
cd "${CLAUDE_PLUGIN_ROOT}" &&
if the script needs to run from the plugin’s own directory.
Disabling a plugin mid-session does not stop monitors that are already running. They stop when the session ends.
​
Themes
Plugins can ship color themes that appear in
/theme
alongside the built-in presets and the user’s local themes. A theme is a JSON file in
themes/
with a
base
preset and a sparse
overrides
map of color tokens. Themes are an
experimental component
.
{
"name"
:
"Dracula"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#bd93f9"
,
"error"
:
"#ff5555"
,
"success"
:
"#50fa7b"
}
}
Selecting a plugin theme persists
custom:<plugin-name>:<slug>
in the user’s config. Plugin themes are read-only; pressing
Ctrl+E
on one in
/theme
copies it into
~/.claude/themes/
so the user can edit the copy.
​
Plugin installation scopes
When you install a plugin, you choose a
scope
that determines where the plugin is available and who else can use it:
Scope
Settings file
Use case
user
~/.claude/settings.json
Personal plugins available across all projects (default)
project
.claude/settings.json
Team plugins shared via version control
local
.claude/settings.local.json
Project-specific plugins, gitignored
managed
Managed settings
Managed plugins (read-only, update only)
Plugins use the same scope system as other Claude Code configurations. For installation instructions and scope flags, see
Install plugins
. For a complete explanation of scopes, see
Configuration scopes
.
​
Plugin manifest schema
The
.claude-plugin/plugin.json
file defines your plugin’s metadata and configuration. This section documents all supported fields and options.
The manifest is optional. If omitted, Claude Code auto-discovers components in
default locations
and derives the plugin name from the directory name. Use a manifest when you need to provide metadata or custom component paths.
​
Complete schema
{
"name"
:
"plugin-name"
,
"version"
:
"1.2.0"
,
"description"
:
"Brief plugin description"
,
"author"
: {
"name"
:
"Author Name"
,
"email"
:
"author@example.com"
,
"url"
:
"https://github.com/author"
},
"homepage"
:
"https://docs.example.com/plugin"
,
"repository"
:
"https://github.com/author/plugin"
,
"license"
:
"MIT"
,
"keywords"
: [
"keyword1"
,
"keyword2"
],
"skills"
:
"./custom/skills/"
,
"commands"
: [
"./custom/commands/special.md"
],
"agents"
: [
"./custom/agents/reviewer.md"
],
"hooks"
:
"./config/hooks.json"
,
"mcpServers"
:
"./mcp-config.json"
,
"outputStyles"
:
"./styles/"
,
"lspServers"
:
"./.lsp.json"
,
"experimental"
: {
"themes"
:
"./themes/"
,
"monitors"
:
"./monitors.json"
},
"dependencies"
: [
"helper-lib"
,
{
"name"
:
"secrets-vault"
,
"version"
:
"~2.1.0"
}
]
}
​
Required fields
If you include a manifest,
name
is the only required field.
Field
Type
Description
Example
name
string
Unique identifier (kebab-case, no spaces)
"deployment-tools"
This name is used for namespacing components. For example, in the UI, the
agent
agent-creator
for the plugin with name
plugin-dev
will appear as
plugin-dev:agent-creator
.
​
Metadata fields
Field
Type
Description
Example
$schema
string
JSON Schema URL for editor autocomplete and validation. Claude Code ignores this field at load time.
"https://json.schemastore.org/claude-code-plugin-manifest.json"
version
string
Optional. Semantic version. Setting this pins the plugin to that version string, so users only receive updates when you bump it. If omitted, Claude Code falls back to the git commit SHA, so every commit is treated as a new version. If also set in the marketplace entry,
plugin.json
wins. See
Version management
.
"2.1.0"
description
string
Brief explanation of plugin purpose
"Deployment automation tools"
author
object
Author information
{"name": "Dev Team", "email": "dev@company.com"}
homepage
string
Documentation URL
"https://docs.example.com"
repository
string
Source code URL
"https://github.com/user/plugin"
license
string
License identifier
"MIT"
,
"Apache-2.0"
keywords
array
Discovery tags
["deployment", "ci-cd"]
​
Component path fields
Field
Type
Description
Example
skills
string|array
Custom skill directories containing
<name>/SKILL.md
(in addition to default
skills/
)
"./custom/skills/"
commands
string|array
Custom flat
.md
skill files or directories (replaces default
commands/
)
"./custom/cmd.md"
or
["./cmd1.md"]
agents
string|array
Custom agent files (replaces default
agents/
)
"./custom/agents/reviewer.md"
hooks
string|array|object
Hook config paths or inline config
"./my-extra-hooks.json"
mcpServers
string|array|object
MCP config paths or inline config
"./my-extra-mcp-config.json"
outputStyles
string|array
Custom output style files/directories (replaces default
output-styles/
)
"./styles/"
lspServers
string|array|object
Language Server Protocol
configs for code intelligence (go to definition, find references, etc.)
"./.lsp.json"
experimental.themes
string|array
Color theme files/directories (replaces default
themes/
). See
Themes
"./themes/"
experimental.monitors
string|array
Background
Monitor
configurations that start automatically when the plugin is active. See
Monitors
"./monitors.json"
userConfig
object
User-configurable values prompted at enable time. See
User configuration
See below
channels
array
Channel declarations for message injection (Telegram, Slack, Discord style). See
Channels
See below
dependencies
array
Other plugins this plugin requires, optionally with semver version constraints. See
Constrain plugin dependency versions
[{ "name": "secrets-vault", "version": "~2.1.0" }]
​
Experimental components
Components under the
experimental
key,
themes
and
monitors
, have a manifest schema that may change between releases while they stabilize. Where you declare them is a separate migration: the top level still works,
claude plugin validate
warns, and a future release will require
experimental.*
.
​
User configuration
The
userConfig
field declares values that Claude Code prompts the user for when the plugin is enabled. Use this instead of requiring users to hand-edit
settings.json
.
{
"userConfig"
: {
"api_endpoint"
: {
"type"
:
"string"
,
"title"
:
"API endpoint"
,
"description"
:
"Your team's API endpoint"
},
"api_token"
: {
"type"
:
"string"
,
"title"
:
"API token"
,
"description"
:
"API authentication token"
,
"sensitive"
:
true
}
}
}
Keys must be valid identifiers. Each option supports these fields:
Field
Required
Description
type
Yes
One of
string
,
number
,
boolean
,
directory
, or
file
title
Yes
Label shown in the configuration dialog
description
Yes
Help text shown beneath the field
sensitive
No
If
true
, masks input and stores the value in secure storage instead of
settings.json
required
No
If
true
, validation fails when the field is empty
default
No
Value used when the user provides nothing
multiple
No
For
string
type, allow an array of strings
min
/
max
No
Bounds for
number
type
Each value is available for substitution as
${user_config.KEY}
in MCP and LSP server configs, hook commands, and monitor commands. Non-sensitive values can also be substituted in skill and agent content. All values are exported to plugin subprocesses as
CLAUDE_PLUGIN_OPTION_<KEY>
environment variables.
Non-sensitive values are stored in
settings.json
under
pluginConfigs[<plugin-id>].options
. Sensitive values go to the system keychain (or
~/.claude/.credentials.json
where the keychain is unavailable). Keychain storage is shared with OAuth tokens and has an approximately 2 KB total limit, so keep sensitive values small.
​
Channels
The
channels
field lets a plugin declare one or more message channels that inject content into the conversation. Each channel binds to an MCP server that the plugin provides.
{
"channels"
: [
{
"server"
:
"telegram"
,
"userConfig"
: {
"bot_token"
: {
"type"
:
"string"
,
"title"
:
"Bot token"
,
"description"
:
"Telegram bot token"
,
"sensitive"
:
true
},
"owner_id"
: {
"type"
:
"string"
,
"title"
:
"Owner ID"
,
"description"
:
"Your Telegram user ID"
}
}
}
]
}
The
server
field is required and must match a key in the plugin’s
mcpServers
. The optional per-channel
userConfig
uses the same schema as the top-level field, letting the plugin prompt for bot tokens or owner IDs when the plugin is enabled.
​
Path behavior rules
Whether a custom path replaces or extends the plugin’s default directory depends on the field:
Replaces the default
:
commands
,
agents
,
outputStyles
,
experimental.themes
,
experimental.monitors
. For example, when the manifest specifies
commands
, the default
commands/
directory is not scanned. To keep the default and add more, list it explicitly:
"commands": ["./commands/", "./extras/"]
Adds to the default
:
skills
. The default
skills/
directory is always scanned, and directories listed in
skills
are loaded alongside it
Own merge rules
:
hooks
,
MCP servers
, and
LSP servers
. See each section for how multiple sources combine
When a plugin has both a default folder and the matching manifest key, Claude Code v2.1.140 and later flags the ignored folder in
/doctor
,
claude plugin list
, and the
/plugin
detail view. The plugin still loads using the manifest paths. No warning is shown when the manifest key points into the default folder, for example
"commands": ["./commands/deploy.md"]
, because the folder is addressed explicitly in that case.
For all path fields:
All paths must be relative to the plugin root and start with
./
Components from custom paths use the same naming and namespacing rules
Multiple paths can be specified as arrays
When a skill path points to a directory that contains a
SKILL.md
directly, for example
"skills": ["./"]
pointing to the plugin root, the frontmatter
name
field in
SKILL.md
determines the skill’s invocation name. This gives a stable name regardless of the install directory. If
name
is not set in the frontmatter, the directory basename is used as a fallback.
Path examples
:
{
"commands"
: [
"./specialized/deploy.md"
,
"./utilities/batch-process.md"
],
"agents"
: [
"./custom-agents/reviewer.md"
,
"./custom-agents/tester.md"
]
}
​
Environment variables
Claude Code provides three variables for referencing paths. All are substituted inline anywhere they appear in skill content, agent content, hook commands, monitor commands, and MCP or LSP server configs. All are also exported as environment variables to hook processes and MCP or LSP server subprocesses.
${CLAUDE_PLUGIN_ROOT}
: the absolute path to your plugin’s installation directory. Use this to reference scripts, binaries, and config files bundled with the plugin. In hook commands, use
exec form
with
args
so the path is passed as one argument with no quoting. In shell-form hooks and monitor commands, wrap it in double quotes, as in
"${CLAUDE_PLUGIN_ROOT}"
. This path changes when the plugin updates. The previous version’s directory remains on disk for about seven days after an update before cleanup, but treat it as ephemeral and do not write state here.
When a plugin updates mid-session, hook commands, monitors, MCP servers, and LSP servers keep using the previous version’s path. Run
/reload-plugins
to switch hooks, MCP servers, and LSP servers to the new path; monitors require a session restart.
${CLAUDE_PLUGIN_DATA}
: a persistent directory for plugin state that survives updates. Use this for installed dependencies such as
node_modules
or Python virtual environments, generated code, caches, and any other files that should persist across plugin versions. The directory is created automatically the first time this variable is referenced.
${CLAUDE_PROJECT_DIR}
: the project root. This is the same directory hooks receive in their
CLAUDE_PROJECT_DIR
variable. Use this to reference project-local scripts or config files. Wrap in quotes to handle paths with spaces, for example
"${CLAUDE_PROJECT_DIR}/scripts/server.sh"
. MCP servers can also call the MCP
roots/list
request, which returns the directory Claude Code was launched from.
{
"hooks"
: {
"PostToolUse"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/process.sh"
}
]
}
]
}
}
​
Persistent data directory
The
${CLAUDE_PLUGIN_DATA}
directory resolves to
~/.claude/plugins/data/{id}/
, where
{id}
is the plugin identifier with characters outside
a-z
,
A-Z
,
0-9
,
_
, and
-
replaced by
-
. For a plugin installed as
formatter@my-marketplace
, the directory is
~/.claude/plugins/data/formatter-my-marketplace/
.
A common use is installing language dependencies once and reusing them across sessions and plugin updates. Because the data directory outlives any single plugin version, a check for directory existence alone cannot detect when an update changes the plugin’s dependency manifest. The recommended pattern compares the bundled manifest against a copy in the data directory and reinstalls when they differ.
This
SessionStart
hook installs
node_modules
on the first run and again whenever a plugin update includes a changed
package.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"diff -q
\"
${CLAUDE_PLUGIN_ROOT}/package.json
\"
\"
${CLAUDE_PLUGIN_DATA}/package.json
\"
>/dev/null 2>&1 || (cd
\"
${CLAUDE_PLUGIN_DATA}
\"
&& cp
\"
${CLAUDE_PLUGIN_ROOT}/package.json
\"
. && npm install) || rm -f
\"
${CLAUDE_PLUGIN_DATA}/package.json
\"
"
}
]
}
]
}
}
The
diff
exits nonzero when the stored copy is missing or differs from the bundled one, covering both first run and dependency-changing updates. If
npm install
fails, the trailing
rm
removes the copied manifest so the next session retries.
Scripts bundled in
${CLAUDE_PLUGIN_ROOT}
can then run against the persisted
node_modules
:
{
"mcpServers"
: {
"routines"
: {
"command"
:
"node"
,
"args"
: [
"${CLAUDE_PLUGIN_ROOT}/server.js"
],
"env"
: {
"NODE_PATH"
:
"${CLAUDE_PLUGIN_DATA}/node_modules"
}
}
}
}
The data directory is deleted automatically when you uninstall the plugin from the last scope where it is installed. The
/plugin
interface shows the directory size and prompts before deleting. The CLI deletes by default; pass
--keep-data
to preserve it.
​
Plugin caching and file resolution
Plugins are specified in one of two ways:
Through
claude --plugin-dir
or
claude --plugin-url
, for the duration of a session.
Through a marketplace, installed for future sessions.
For security and verification purposes, Claude Code copies
marketplace
plugins to the user’s local
plugin cache
(
~/.claude/plugins/cache
) rather than using them in-place. Understanding this behavior is important when developing plugins that reference external files.
Each installed version is a separate directory in the cache. When you update or uninstall a plugin, the previous version directory is marked as orphaned and removed automatically 7 days later. The grace period lets concurrent Claude Code sessions that already loaded the old version keep running without errors.
Claude’s Glob and Grep tools skip orphaned version directories during searches, so file results don’t include outdated plugin code.
​
Path traversal limitations
Installed plugins cannot reference files outside their directory. Paths that traverse outside the plugin root (such as
../shared-utils
) will not work after installation because those external files are not copied to the cache.
​
Share files within a marketplace with symlinks
If your plugin needs to share files with other parts of the same marketplace, you can create symbolic links inside your plugin directory. How a symlink is handled when the plugin is copied into the cache depends on where its target resolves:
Within the plugin’s own directory:
the symlink is preserved as a relative symlink in the cache, so it keeps resolving to the copied target at runtime.
Elsewhere within the same marketplace:
the symlink is dereferenced. The target’s content is copied into the cache in its place. This lets a meta-plugin’s
skills/
directory link to skills defined by other plugins in the marketplace.
Outside the marketplace:
the symlink is skipped for security. This prevents plugins from pulling arbitrary host files such as system paths into the cache.
For plugins installed with
--plugin-dir
or from a local path, only symlinks that resolve within the plugin’s own directory are preserved. All others are skipped.
The following command creates a link from inside a marketplace plugin to a shared skill defined by a sibling plugin. On Windows, use
mklink /D
from an elevated Command Prompt or enable Developer Mode:
ln
-s
../../shared-plugin/skills/foo
./skills/foo
This provides flexibility while maintaining the security benefits of the caching system.
​
Plugin directory structure
​
Standard plugin layout
A complete plugin follows this structure:
enterprise-plugin/
├── .claude-plugin/           # Metadata directory (optional)
│   └── plugin.json             # plugin manifest
├── skills/                   # Skills
│   ├── code-reviewer/
│   │   └── SKILL.md
│   └── pdf-processor/
│       ├── SKILL.md
│       └── scripts/
├── commands/                 # Skills as flat .md files
│   ├── status.md
│   └── logs.md
├── agents/                   # Subagent definitions
│   ├── security-reviewer.md
│   ├── performance-tester.md
│   └── compliance-checker.md
├── output-styles/            # Output style definitions
│   └── terse.md
├── themes/                   # Color theme definitions
│   └── dracula.json
├── monitors/                 # Background monitor configurations
│   └── monitors.json
├── hooks/                    # Hook configurations
│   ├── hooks.json           # Main hook config
│   └── security-hooks.json  # Additional hooks
├── bin/                      # Plugin executables added to PATH
│   └── my-tool               # Invokable as bare command in Bash tool
├── settings.json            # Default settings for the plugin
├── .mcp.json                # MCP server definitions
├── .lsp.json                # LSP server configurations
├── scripts/                 # Hook and utility scripts
│   ├── security-scan.sh
│   ├── format-code.py
│   └── deploy.js
├── LICENSE                  # License file
└── CHANGELOG.md             # Version history
The
.claude-plugin/
directory contains the
plugin.json
file. All other directories (commands/, agents/, skills/, output-styles/, themes/, monitors/, hooks/) must be at the plugin root, not inside
.claude-plugin/
.
A
CLAUDE.md
file at the plugin root is not loaded as project context. Plugins contribute context through skills, agents, and hooks rather than CLAUDE.md. To ship instructions that load into Claude’s context, put them in a
skill
.
​
File locations reference
Component
Default Location
Purpose
Manifest
.claude-plugin/plugin.json
Plugin metadata and configuration (optional)
Skills
skills/
Skills with
<name>/SKILL.md
structure
Commands
commands/
Skills as flat Markdown files. Use
skills/
for new plugins
Agents
agents/
Subagent Markdown files
Output styles
output-styles/
Output style definitions
Themes
themes/
Color theme definitions
Hooks
hooks/hooks.json
Hook configuration
MCP servers
.mcp.json
MCP server definitions
LSP servers
.lsp.json
Language server configurations
Monitors
monitors/monitors.json
Background monitor configurations
Executables
bin/
Executables added to the Bash tool’s
PATH
. Files here are invokable as bare commands in any Bash tool call while the plugin is enabled
Settings
settings.json
Default configuration applied when the plugin is enabled. Only the
agent
and
subagentStatusLine
keys are currently supported
​
CLI commands reference
Claude Code provides CLI commands for non-interactive plugin management, useful for scripting and automation.
​
plugin install
Install a plugin from available marketplaces.
claude
plugin
install
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
for a specific marketplace
Options:
Option
Description
Default
-s, --scope <scope>
Installation scope:
user
,
project
, or
local
user
-h, --help
Display help for command
Scope determines which settings file the installed plugin is added to. For example,
--scope project
writes to
enabledPlugins
in .claude/settings.json, making the plugin available to everyone who clones the project repository.
Examples:
# Install to user scope (default)
claude
plugin
install
formatter@my-marketplace
# Install to project scope (shared with team)
claude
plugin
install
formatter@my-marketplace
--scope
project
# Install to local scope (gitignored)
claude
plugin
install
formatter@my-marketplace
--scope
local
​
plugin uninstall
Remove an installed plugin.
claude
plugin
uninstall
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Uninstall from scope:
user
,
project
, or
local
user
--keep-data
Preserve the plugin’s
persistent data directory
--prune
Also remove auto-installed dependencies that no other plugin requires. See
plugin prune
-y, --yes
Skip the
--prune
confirmation prompt. Required when stdin or stdout is not a TTY
-h, --help
Display help for command
Aliases:
remove
,
rm
By default, uninstalling from the last remaining scope also deletes the plugin’s
${CLAUDE_PLUGIN_DATA}
directory. Use
--keep-data
to preserve it, for example when reinstalling after testing a new version.
​
plugin prune
Remove auto-installed plugin dependencies that are no longer required by any installed plugin. Dependencies that Claude Code pulled in to satisfy another plugin’s
dependencies
field are removed; plugins you installed directly are never touched.
claude
plugin
prune
[options]
Options:
Option
Description
Default
-s, --scope <scope>
Prune at scope:
user
,
project
, or
local
user
--dry-run
List what would be removed without removing anything
-y, --yes
Skip the confirmation prompt. Required when stdin or stdout is not a TTY
-h, --help
Display help for command
Aliases:
autoremove
The command lists orphaned dependencies and asks for confirmation before removing them. To remove a plugin and clean up its dependencies in one step, run
claude plugin uninstall <plugin> --prune
.
claude plugin prune
requires Claude Code v2.1.121 or later.
​
plugin enable
Enable a disabled plugin.
claude
plugin
enable
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to enable:
user
,
project
, or
local
user
-h, --help
Display help for command
​
plugin disable
Disable a plugin without uninstalling it.
claude
plugin
disable
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to disable:
user
,
project
, or
local
user
-h, --help
Display help for command
​
plugin update
Update a plugin to the latest version.
claude
plugin
update
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to update:
user
,
project
,
local
, or
managed
user
-h, --help
Display help for command
​
plugin list
List installed plugins with their version, source marketplace, and enable status.
claude
plugin
list
[options]
Options:
Option
Description
Default
--json
Output as JSON
--available
Include available plugins from marketplaces. Requires
--json
-h, --help
Display help for command
​
plugin details
Show a plugin’s component inventory and projected token cost. The output lists all components the plugin contributes, grouped as Skills (skills and commands), Agents, Hooks, and MCP servers, along with an estimate of how many tokens it adds to each session.
claude
plugin
details
<
nam
e
>
Arguments:
<name>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-h, --help
Display help for command
The output shows two cost figures for each component:
Always-on:
tokens added to every session by the plugin’s listing text, such as skill descriptions, agent descriptions, and command names, regardless of whether any component fires.
On-invoke:
tokens a component costs when it fires. Shown per component, not as a plugin total, because a typical session invokes only a subset of components.
This example shows what the output looks like for a plugin with two skills:
security-guidance 1.2.0
Real-time security analysis for Claude Code sessions
Source: security-guidance@claude-code-marketplace
Component inventory
Skills (2)  scan-dependencies, review-changes
Agents (0)
Hooks (1)  (harness-only — no model context cost)
MCP servers (0)
Projected token cost
Always-on:   ~180 tok   added to every session
Per-component (rounded)
component            always-on  on-invoke
scan-dependencies        ~100      ~2400
review-changes            ~80      ~1800
On-invoke cost is paid each time a skill or agent fires.
Token counts are estimates and may differ from actual usage.
The always-on total is computed via the
count_tokens
API for your active model. Per-component numbers are proportionally scaled from that total. If the API is unreachable, the command falls back to a character-based estimate.
​
plugin tag
Create a release git tag for the plugin in the current directory. Run from inside the plugin’s folder. See
Tag plugin releases
.
claude
plugin
tag
[options]
Options:
Option
Description
Default
--push
Push the tag to the remote after creating it
--dry-run
Print what would be tagged without creating the tag
-f, --force
Create the tag even if the working tree is dirty or the tag already exists
-h, --help
Display help for command
​
Debugging and development tools
​
Debugging commands
Use
claude --debug
to see plugin loading details:
This shows:
Which plugins are being loaded
Any errors in plugin manifests
Skill, agent, and hook registration
MCP server initialization
​
Common issues
Issue
Cause
Solution
Plugin not loading
Invalid
plugin.json
Run
claude plugin validate
or
/plugin validate
to check
plugin.json
, skill/agent/command frontmatter, and
hooks/hooks.json
for syntax and schema errors
Skills not appearing
Wrong directory structure
Ensure
skills/
or
commands/
is at the plugin root, not inside
.claude-plugin/
Hooks not firing
Script not executable
Run
chmod +x script.sh
MCP server fails
Missing
${CLAUDE_PLUGIN_ROOT}
Use variable for all plugin paths
Path errors
Absolute paths used
All paths must be relative and start with
./
LSP
Executable not found in $PATH
Language server not installed
Install the binary (e.g.,
npm install -g typescript-language-server typescript
)
​
Example error messages
Manifest validation errors
:
Invalid JSON syntax: Unexpected token } in JSON at position 142
: check for missing commas, extra commas, or unquoted strings
Plugin has an invalid manifest file at .claude-plugin/plugin.json. Validation errors: name: Required
: a required field is missing
Plugin has a corrupt manifest file at .claude-plugin/plugin.json. JSON parse error: ...
: JSON syntax error
Plugin loading errors
:
Warning: No commands found in plugin my-plugin custom directory: ./cmds. Expected .md files or SKILL.md in subdirectories.
: command path exists but contains no valid command files
Plugin directory not found at path: ./plugins/my-plugin. Check that the marketplace entry has the correct path.
: the
source
path in marketplace.json points to a non-existent directory
Plugin my-plugin has conflicting manifests: both plugin.json and marketplace entry specify components.
: remove duplicate component definitions or remove
strict: false
in marketplace entry
​
Hook troubleshooting
Hook script not executing
:
Check the script is executable:
chmod +x ./scripts/your-script.sh
Verify the shebang line: First line should be
#!/bin/bash
or
#!/usr/bin/env bash
Check the path uses
${CLAUDE_PLUGIN_ROOT}
:
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/your-script.sh"
Test the script manually:
./scripts/your-script.sh
Hook not triggering on expected events
:
Verify the event name is correct (case-sensitive):
PostToolUse
, not
postToolUse
Check the matcher pattern matches your tools:
"matcher": "Write|Edit"
for file operations
Confirm the hook type is valid:
command
,
http
,
mcp_tool
,
prompt
, or
agent
​
MCP server troubleshooting
Server not starting
:
Check the command exists and is executable
Verify all paths use
${CLAUDE_PLUGIN_ROOT}
variable
Check the MCP server logs:
claude --debug
shows initialization errors
Test the server manually outside of Claude Code
Server tools not appearing
:
Ensure the server is properly configured in
.mcp.json
or
plugin.json
Verify the server implements the MCP protocol correctly
Check for connection timeouts in debug output
​
Directory structure mistakes
Symptoms
: Plugin loads but components (skills, agents, hooks) are missing.
Correct structure
: Components must be at the plugin root, not inside
.claude-plugin/
. Only
plugin.json
belongs in
.claude-plugin/
.
my-plugin/
├── .claude-plugin/
│   └── plugin.json      ← Only manifest here
├── commands/            ← At root level
├── agents/              ← At root level
└── hooks/               ← At root level
If your components are inside
.claude-plugin/
, move them to the plugin root.
Debug checklist
:
Run
claude --debug
and look for “loading plugin” messages
Check that each component directory is listed in the debug output
Verify file permissions allow reading the plugin files
​
Distribution and versioning reference
​
Version management
Claude Code uses the plugin’s version as the cache key that determines whether an update is available. When you run
/plugin update
or auto-update fires, Claude Code computes the current version and skips the update if it matches what’s already installed.
The version is resolved from the first of these that is set:
The
version
field in the plugin’s
plugin.json
The
version
field in the plugin’s marketplace entry in
marketplace.json
The git commit SHA of the plugin’s source, for
github
,
url
,
git-subdir
, and relative-path sources in a git-hosted marketplace
unknown
, for
npm
sources or local directories not inside a git repository
This gives you two ways to version a plugin:
Approach
How
Update behavior
Best for
Explicit version
Set
"version": "2.1.0"
in
plugin.json
Users get updates only when you bump this field. Pushing new commits without bumping it has no effect, and
/plugin update
reports “already at the latest version”.
Published plugins with stable release cycles
Commit-SHA version
Omit
version
from both
plugin.json
and the marketplace entry
Users get updates on every new commit to the plugin’s git source
Internal or team plugins under active development
If you set
version
in
plugin.json
, you must bump it every time you want users to receive changes. Pushing new commits alone is not enough, because Claude Code sees the same version string and keeps the cached copy. If you’re iterating quickly, leave
version
unset so the git commit SHA is used instead.
If you use explicit versions, follow
semantic versioning
(
MAJOR.MINOR.PATCH
): bump MAJOR for breaking changes, MINOR for new features, PATCH for bug fixes. Document changes in a
CHANGELOG.md
.
​
See also
Plugins
- Tutorials and practical usage
Plugin marketplaces
- Creating and managing marketplaces
Skills
- Skill development details
Subagents
- Agent configuration and capabilities
Hooks
- Event handling and automation
MCP
- External tool integration
Settings
- Configuration options for plugins
Was this page helpful?
Yes
No
Hooks reference
Channels reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugins-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Plugins reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Looking to install plugins? See
Discover and i...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Plugins reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Looking to install plugins? See
Discover and install plugins
. For creating plugins, see
Plugins
. For distributing plugins, see
Plugin marketplaces
.
This reference provides complete technical specifications for the Claude Code plugin system, including component schemas, CLI commands, and development tools.
A
plugin
is a self-contained directory of components that extends Claude Code with custom functionality. Plugin components include skills, agents, hooks, MCP servers, LSP servers, and monitors.
​
Plugin components reference
​
Skills
Plugins add skills to Claude Code, creating
/name
shortcuts that you or Claude can invoke.
Location
:
skills/
or
commands/
directory in plugin root
File format
: Skills are directories with
SKILL.md
; commands are simple markdown files
Skill structure
:
skills/
├── pdf-processor/
│   ├── SKILL.md
│   ├── reference.md (optional)
│   └── scripts/ (optional)
└── code-reviewer/
└── SKILL.md
Integration behavior
:
Skills and commands are automatically discovered when the plugin is installed
Claude can invoke them automatically based on task context
Skills can include supporting files alongside SKILL.md
For complete details, see
Skills
.
​
Agents
Plugins can provide specialized subagents for specific tasks that Claude can invoke automatically when appropriate.
Location
:
agents/
directory in plugin root
File format
: Markdown files describing agent capabilities
Agent structure
:
---
name
:
agent-name
description
:
What this agent specializes in and when Claude should invoke it
model
:
sonnet
effort
:
medium
maxTurns
:
20
disallowedTools
:
Write, Edit
---
Detailed system prompt for the agent describing its role, expertise, and behavior.
Plugin agents support
name
,
description
,
model
,
effort
,
maxTurns
,
tools
,
disallowedTools
,
skills
,
memory
,
background
, and
isolation
frontmatter fields. The only valid
isolation
value is
"worktree"
. For security reasons,
hooks
,
mcpServers
, and
permissionMode
are not supported for plugin-shipped agents.
Integration points
:
Agents appear in the
/agents
interface
Claude can invoke agents automatically based on task context
Agents can be invoked manually by users
Plugin agents work alongside built-in Claude agents
For complete details, see
Subagents
.
​
Hooks
Plugins can provide event handlers that respond to Claude Code events automatically.
Location
:
hooks/hooks.json
in plugin root, or inline in plugin.json
Format
: JSON configuration with event matchers and actions
Hook configuration
:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/format-code.sh"
}
]
}
]
}
}
Plugin hooks respond to the same lifecycle events as
user-defined hooks
:
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
Hook types
:
command
: execute shell commands or scripts
http
: send the event JSON as a POST request to a URL
mcp_tool
: call a tool on a configured
MCP server
prompt
: evaluate a prompt with an LLM (uses
$ARGUMENTS
placeholder for context)
agent
: run an agentic verifier with tools for complex verification tasks
​
MCP servers
Plugins can bundle Model Context Protocol (MCP) servers to connect Claude Code with external tools and services.
Location
:
.mcp.json
in plugin root, or inline in plugin.json
Format
: Standard MCP server configuration
MCP server configuration
:
{
"mcpServers"
: {
"plugin-database"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
],
"env"
: {
"DB_PATH"
:
"${CLAUDE_PLUGIN_ROOT}/data"
}
},
"plugin-api-client"
: {
"command"
:
"npx"
,
"args"
: [
"@company/mcp-server"
,
"--plugin-mode"
],
"cwd"
:
"${CLAUDE_PLUGIN_ROOT}"
}
}
}
Integration behavior
:
Plugin MCP servers start automatically when the plugin is enabled
Servers appear as standard MCP tools in Claude’s toolkit
Server capabilities integrate seamlessly with Claude’s existing tools
Plugin servers can be configured independently of user MCP servers
​
LSP servers
Looking to use LSP plugins? Install them from the official marketplace: search for “lsp” in the
/plugin
Discover tab. This section documents how to create LSP plugins for languages not covered by the official marketplace.
Plugins can provide
Language Server Protocol
(LSP) servers to give Claude real-time code intelligence while working on your codebase.
LSP integration provides:
Instant diagnostics
: Claude sees errors and warnings immediately after each edit
Code navigation
: go to definition, find references, and hover information
Language awareness
: type information and documentation for code symbols
Location
:
.lsp.json
in plugin root, or inline in
plugin.json
Format
: JSON configuration mapping language server names to their configurations
.lsp.json
file format
:
{
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
Inline in
plugin.json
:
{
"name"
:
"my-plugin"
,
"lspServers"
: {
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
}
Required fields:
Field
Description
command
The LSP binary to execute (must be in PATH)
extensionToLanguage
Maps file extensions to language identifiers
Optional fields:
Field
Description
args
Command-line arguments for the LSP server
transport
Communication transport:
stdio
(default) or
socket
env
Environment variables to set when starting the server
initializationOptions
Options passed to the server during initialization
settings
Settings passed via
workspace/didChangeConfiguration
workspaceFolder
Workspace folder path for the server
startupTimeout
Max time to wait for server startup (milliseconds)
shutdownTimeout
Max time to wait for graceful shutdown (milliseconds)
restartOnCrash
Whether to automatically restart the server if it crashes
maxRestarts
Maximum number of restart attempts before giving up
You must install the language server binary separately.
LSP plugins configure how Claude Code connects to a language server, but they don’t include the server itself. If you see
Executable not found in $PATH
in the
/plugin
Errors tab, install the required binary for your language.
Available LSP plugins:
Plugin
Language server
Install command
pyright-lsp
Pyright (Python)
pip install pyright
or
npm install -g pyright
typescript-lsp
TypeScript Language Server
npm install -g typescript-language-server typescript
rust-analyzer-lsp
rust-analyzer
See rust-analyzer installation
Install the language server first, then install the plugin from the marketplace.
​
Monitors
Plugins can declare background monitors that Claude Code starts automatically when the plugin is active. Each monitor runs a shell command for the lifetime of the session and delivers every stdout line to Claude as a notification, so Claude can react to log entries, status changes, or polled events without being asked to start the watch itself.
Plugin monitors use the same mechanism as the
Monitor tool
and share its availability constraints. They run only in interactive CLI sessions, run unsandboxed at the same trust level as
hooks
, and are skipped on hosts where the Monitor tool is unavailable.
Plugin monitors require Claude Code v2.1.105 or later.
Location
:
monitors/monitors.json
in the plugin root, or inline in
plugin.json
Format
: JSON array of monitor entries
The following
monitors/monitors.json
watches a deployment status endpoint and a local error log:
[
{
"name"
:
"deploy-status"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/poll-deploy.sh ${user_config.api_endpoint}"
,
"description"
:
"Deployment status changes"
},
{
"name"
:
"error-log"
,
"command"
:
"tail -F ./logs/error.log"
,
"description"
:
"Application error log"
,
"when"
:
"on-skill-invoke:debug"
}
]
To declare monitors inline, set
experimental.monitors
in
plugin.json
to the same array. To load from a non-default path, set
experimental.monitors
to a relative path string such as
"./config/monitors.json"
. Monitors are an
experimental component
.
Required fields:
Field
Description
name
Identifier unique within the plugin. Prevents duplicate processes when the plugin reloads or a skill is invoked again
command
Shell command run as a persistent background process in the session working directory
description
Short summary of what is being watched. Shown in the task panel and in notification summaries
Optional fields:
Field
Description
when
Controls when the monitor starts.
"always"
starts it at session start and on plugin reload, and is the default.
"on-skill-invoke:<skill-name>"
starts it the first time the named skill in this plugin is dispatched
The
command
value supports the same
variable substitutions
as MCP and LSP server configs:
${CLAUDE_PLUGIN_ROOT}
,
${CLAUDE_PLUGIN_DATA}
,
${CLAUDE_PROJECT_DIR}
,
${user_config.*}
, and any
${ENV_VAR}
from the environment. Prefix the command with
cd "${CLAUDE_PLUGIN_ROOT}" &&
if the script needs to run from the plugin’s own directory.
Disabling a plugin mid-session does not stop monitors that are already running. They stop when the session ends.
​
Themes
Plugins can ship color themes that appear in
/theme
alongside the built-in presets and the user’s local themes. A theme is a JSON file in
themes/
with a
base
preset and a sparse
overrides
map of color tokens. Themes are an
experimental component
.
{
"name"
:
"Dracula"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#bd93f9"
,
"error"
:
"#ff5555"
,
"success"
:
"#50fa7b"
}
}
Selecting a plugin theme persists
custom:<plugin-name>:<slug>
in the user’s config. Plugin themes are read-only; pressing
Ctrl+E
on one in
/theme
copies it into
~/.claude/themes/
so the user can edit the copy.
​
Plugin installation scopes
When you install a plugin, you choose a
scope
that determines where the plugin is available and who else can use it:
Scope
Settings file
Use case
user
~/.claude/settings.json
Personal plugins available across all projects (default)
project
.claude/settings.json
Team plugins shared via version control
local
.claude/settings.local.json
Project-specific plugins, gitignored
managed
Managed settings
Managed plugins (read-only, update only)
Plugins use the same scope system as other Claude Code configurations. For installation instructions and scope flags, see
Install plugins
. For a complete explanation of scopes, see
Configuration scopes
.
​
Plugin manifest schema
The
.claude-plugin/plugin.json
file defines your plugin’s metadata and configuration. This section documents all supported fields and options.
The manifest is optional. If omitted, Claude Code auto-discovers components in
default locations
and derives the plugin name from the directory name. Use a manifest when you need to provide metadata or custom component paths.
​
Complete schema
{
"name"
:
"plugin-name"
,
"version"
:
"1.2.0"
,
"description"
:
"Brief plugin description"
,
"author"
: {
"name"
:
"Author Name"
,
"email"
:
"author@example.com"
,
"url"
:
"https://github.com/author"
},
"homepage"
:
"https://docs.example.com/plugin"
,
"repository"
:
"https://github.com/author/plugin"
,
"license"
:
"MIT"
,
"keywords"
: [
"keyword1"
,
"keyword2"
],
"skills"
:
"./custom/skills/"
,
"commands"
: [
"./custom/commands/special.md"
],
"agents"
: [
"./custom/agents/reviewer.md"
],
"hooks"
:
"./config/hooks.json"
,
"mcpServers"
:
"./mcp-config.json"
,
"outputStyles"
:
"./styles/"
,
"lspServers"
:
"./.lsp.json"
,
"experimental"
: {
"themes"
:
"./themes/"
,
"monitors"
:
"./monitors.json"
},
"dependencies"
: [
"helper-lib"
,
{
"name"
:
"secrets-vault"
,
"version"
:
"~2.1.0"
}
]
}
​
Required fields
If you include a manifest,
name
is the only required field.
Field
Type
Description
Example
name
string
Unique identifier (kebab-case, no spaces)
"deployment-tools"
This name is used for namespacing components. For example, in the UI, the
agent
agent-creator
for the plugin with name
plugin-dev
will appear as
plugin-dev:agent-creator
.
​
Metadata fields
Field
Type
Description
Example
$schema
string
JSON Schema URL for editor autocomplete and validation. Claude Code ignores this field at load time.
"https://json.schemastore.org/claude-code-plugin-manifest.json"
version
string
Optional. Semantic version. Setting this pins the plugin to that version string, so users only receive updates when you bump it. If omitted, Claude Code falls back to the git commit SHA, so every commit is treated as a new version. If also set in the marketplace entry,
plugin.json
wins. See
Version management
.
"2.1.0"
description
string
Brief explanation of plugin purpose
"Deployment automation tools"
author
object
Author information
{"name": "Dev Team", "email": "dev@company.com"}
homepage
string
Documentation URL
"https://docs.example.com"
repository
string
Source code URL
"https://github.com/user/plugin"
license
string
License identifier
"MIT"
,
"Apache-2.0"
keywords
array
Discovery tags
["deployment", "ci-cd"]
​
Component path fields
Field
Type
Description
Example
skills
string|array
Custom skill directories containing
<name>/SKILL.md
(in addition to default
skills/
)
"./custom/skills/"
commands
string|array
Custom flat
.md
skill files or directories (replaces default
commands/
)
"./custom/cmd.md"
or
["./cmd1.md"]
agents
string|array
Custom agent files (replaces default
agents/
)
"./custom/agents/reviewer.md"
hooks
string|array|object
Hook config paths or inline config
"./my-extra-hooks.json"
mcpServers
string|array|object
MCP config paths or inline config
"./my-extra-mcp-config.json"
outputStyles
string|array
Custom output style files/directories (replaces default
output-styles/
)
"./styles/"
lspServers
string|array|object
Language Server Protocol
configs for code intelligence (go to definition, find references, etc.)
"./.lsp.json"
experimental.themes
string|array
Color theme files/directories (replaces default
themes/
). See
Themes
"./themes/"
experimental.monitors
string|array
Background
Monitor
configurations that start automatically when the plugin is active. See
Monitors
"./monitors.json"
userConfig
object
User-configurable values prompted at enable time. See
User configuration
See below
channels
array
Channel declarations for message injection (Telegram, Slack, Discord style). See
Channels
See below
dependencies
array
Other plugins this plugin requires, optionally with semver version constraints. See
Constrain plugin dependency versions
[{ "name": "secrets-vault", "version": "~2.1.0" }]
​
Experimental components
Components under the
experimental
key,
themes
and
monitors
, have a manifest schema that may change between releases while they stabilize. Where you declare them is a separate migration: the top level still works,
claude plugin validate
warns, and a future release will require
experimental.*
.
​
User configuration
The
userConfig
field declares values that Claude Code prompts the user for when the plugin is enabled. Use this instead of requiring users to hand-edit
settings.json
.
{
"userConfig"
: {
"api_endpoint"
: {
"type"
:
"string"
,
"title"
:
"API endpoint"
,
"description"
:
"Your team's API endpoint"
},
"api_token"
: {
"type"
:
"string"
,
"title"
:
"API token"
,
"description"
:
"API authentication token"
,
"sensitive"
:
true
}
}
}
Keys must be valid identifiers. Each option supports these fields:
Field
Required
Description
type
Yes
One of
string
,
number
,
boolean
,
directory
, or
file
title
Yes
Label shown in the configuration dialog
description
Yes
Help text shown beneath the field
sensitive
No
If
true
, masks input and stores the value in secure storage instead of
settings.json
required
No
If
true
, validation fails when the field is empty
default
No
Value used when the user provides nothing
multiple
No
For
string
type, allow an array of strings
min
/
max
No
Bounds for
number
type
Each value is available for substitution as
${user_config.KEY}
in MCP and LSP server configs, hook commands, and monitor commands. Non-sensitive values can also be substituted in skill and agent content. All values are exported to plugin subprocesses as
CLAUDE_PLUGIN_OPTION_<KEY>
environment variables.
Non-sensitive values are stored in
settings.json
under
pluginConfigs[<plugin-id>].options
. Sensitive values go to the system keychain (or
~/.claude/.credentials.json
where the keychain is unavailable). Keychain storage is shared with OAuth tokens and has an approximately 2 KB total limit, so keep sensitive values small.
​
Channels
The
channels
field lets a plugin declare one or more message channels that inject content into the conversation. Each channel binds to an MCP server that the plugin provides.
{
"channels"
: [
{
"server"
:
"telegram"
,
"userConfig"
: {
"bot_token"
: {
"type"
:
"string"
,
"title"
:
"Bot token"
,
"description"
:
"Telegram bot token"
,
"sensitive"
:
true
},
"owner_id"
: {
"type"
:
"string"
,
"title"
:
"Owner ID"
,
"description"
:
"Your Telegram user ID"
}
}
}
]
}
The
server
field is required and must match a key in the plugin’s
mcpServers
. The optional per-channel
userConfig
uses the same schema as the top-level field, letting the plugin prompt for bot tokens or owner IDs when the plugin is enabled.
​
Path behavior rules
Whether a custom path replaces or extends the plugin’s default directory depends on the field:
Replaces the default
:
commands
,
agents
,
outputStyles
,
experimental.themes
,
experimental.monitors
. For example, when the manifest specifies
commands
, the default
commands/
directory is not scanned. To keep the default and add more, list it explicitly:
"commands": ["./commands/", "./extras/"]
Adds to the default
:
skills
. The default
skills/
directory is always scanned, and directories listed in
skills
are loaded alongside it
Own merge rules
:
hooks
,
MCP servers
, and
LSP servers
. See each section for how multiple sources combine
When a plugin has both a default folder and the matching manifest key, Claude Code v2.1.140 and later flags the ignored folder in
/doctor
,
claude plugin list
, and the
/plugin
detail view. The plugin still loads using the manifest paths. No warning is shown when the manifest key points into the default folder, for example
"commands": ["./commands/deploy.md"]
, because the folder is addressed explicitly in that case.
For all path fields:
All paths must be relative to the plugin root and start with
./
Components from custom paths use the same naming and namespacing rules
Multiple paths can be specified as arrays
When a skill path points to a directory that contains a
SKILL.md
directly, for example
"skills": ["./"]
pointing to the plugin root, the frontmatter
name
field in
SKILL.md
determines the skill’s invocation name. This gives a stable name regardless of the install directory. If
name
is not set in the frontmatter, the directory basename is used as a fallback.
Path examples
:
{
"commands"
: [
"./specialized/deploy.md"
,
"./utilities/batch-process.md"
],
"agents"
: [
"./custom-agents/reviewer.md"
,
"./custom-agents/tester.md"
]
}
​
Environment variables
Claude Code provides three variables for referencing paths. All are substituted inline anywhere they appear in skill content, agent content, hook commands, monitor commands, and MCP or LSP server configs. All are also exported as environment variables to hook processes and MCP or LSP server subprocesses.
${CLAUDE_PLUGIN_ROOT}
: the absolute path to your plugin’s installation directory. Use this to reference scripts, binaries, and config files bundled with the plugin. In hook commands, use
exec form
with
args
so the path is passed as one argument with no quoting. In shell-form hooks and monitor commands, wrap it in double quotes, as in
"${CLAUDE_PLUGIN_ROOT}"
. This path changes when the plugin updates. The previous version’s directory remains on disk for about seven days after an update before cleanup, but treat it as ephemeral and do not write state here.
When a plugin updates mid-session, hook commands, monitors, MCP servers, and LSP servers keep using the previous version’s path. Run
/reload-plugins
to switch hooks, MCP servers, and LSP servers to the new path; monitors require a session restart.
${CLAUDE_PLUGIN_DATA}
: a persistent directory for plugin state that survives updates. Use this for installed dependencies such as
node_modules
or Python virtual environments, generated code, caches, and any other files that should persist across plugin versions. The directory is created automatically the first time this variable is referenced.
${CLAUDE_PROJECT_DIR}
: the project root. This is the same directory hooks receive in their
CLAUDE_PROJECT_DIR
variable. Use this to reference project-local scripts or config files. Wrap in quotes to handle paths with spaces, for example
"${CLAUDE_PROJECT_DIR}/scripts/server.sh"
. MCP servers can also call the MCP
roots/list
request, which returns the directory Claude Code was launched from.
{
"hooks"
: {
"PostToolUse"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/process.sh"
}
]
}
]
}
}
​
Persistent data directory
The
${CLAUDE_PLUGIN_DATA}
directory resolves to
~/.claude/plugins/data/{id}/
, where
{id}
is the plugin identifier with characters outside
a-z
,
A-Z
,
0-9
,
_
, and
-
replaced by
-
. For a plugin installed as
formatter@my-marketplace
, the directory is
~/.claude/plugins/data/formatter-my-marketplace/
.
A common use is installing language dependencies once and reusing them across sessions and plugin updates. Because the data directory outlives any single plugin version, a check for directory existence alone cannot detect when an update changes the plugin’s dependency manifest. The recommended pattern compares the bundled manifest against a copy in the data directory and reinstalls when they differ.
This
SessionStart
hook installs
node_modules
on the first run and again whenever a plugin update includes a changed
package.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"diff -q
\"
${CLAUDE_PLUGIN_ROOT}/package.json
\"
\"
${CLAUDE_PLUGIN_DATA}/package.json
\"
>/dev/null 2>&1 || (cd
\"
${CLAUDE_PLUGIN_DATA}
\"
&& cp
\"
${CLAUDE_PLUGIN_ROOT}/package.json
\"
. && npm install) || rm -f
\"
${CLAUDE_PLUGIN_DATA}/package.json
\"
"
}
]
}
]
}
}
The
diff
exits nonzero when the stored copy is missing or differs from the bundled one, covering both first run and dependency-changing updates. If
npm install
fails, the trailing
rm
removes the copied manifest so the next session retries.
Scripts bundled in
${CLAUDE_PLUGIN_ROOT}
can then run against the persisted
node_modules
:
{
"mcpServers"
: {
"routines"
: {
"command"
:
"node"
,
"args"
: [
"${CLAUDE_PLUGIN_ROOT}/server.js"
],
"env"
: {
"NODE_PATH"
:
"${CLAUDE_PLUGIN_DATA}/node_modules"
}
}
}
}
The data directory is deleted automatically when you uninstall the plugin from the last scope where it is installed. The
/plugin
interface shows the directory size and prompts before deleting. The CLI deletes by default; pass
--keep-data
to preserve it.
​
Plugin caching and file resolution
Plugins are specified in one of two ways:
Through
claude --plugin-dir
or
claude --plugin-url
, for the duration of a session.
Through a marketplace, installed for future sessions.
For security and verification purposes, Claude Code copies
marketplace
plugins to the user’s local
plugin cache
(
~/.claude/plugins/cache
) rather than using them in-place. Understanding this behavior is important when developing plugins that reference external files.
Each installed version is a separate directory in the cache. When you update or uninstall a plugin, the previous version directory is marked as orphaned and removed automatically 7 days later. The grace period lets concurrent Claude Code sessions that already loaded the old version keep running without errors.
Claude’s Glob and Grep tools skip orphaned version directories during searches, so file results don’t include outdated plugin code.
​
Path traversal limitations
Installed plugins cannot reference files outside their directory. Paths that traverse outside the plugin root (such as
../shared-utils
) will not work after installation because those external files are not copied to the cache.
​
Share files within a marketplace with symlinks
If your plugin needs to share files with other parts of the same marketplace, you can create symbolic links inside your plugin directory. How a symlink is handled when the plugin is copied into the cache depends on where its target resolves:
Within the plugin’s own directory:
the symlink is preserved as a relative symlink in the cache, so it keeps resolving to the copied target at runtime.
Elsewhere within the same marketplace:
the symlink is dereferenced. The target’s content is copied into the cache in its place. This lets a meta-plugin’s
skills/
directory link to skills defined by other plugins in the marketplace.
Outside the marketplace:
the symlink is skipped for security. This prevents plugins from pulling arbitrary host files such as system paths into the cache.
For plugins installed with
--plugin-dir
or from a local path, only symlinks that resolve within the plugin’s own directory are preserved. All others are skipped.
The following command creates a link from inside a marketplace plugin to a shared skill defined by a sibling plugin. On Windows, use
mklink /D
from an elevated Command Prompt or enable Developer Mode:
ln
-s
../../shared-plugin/skills/foo
./skills/foo
This provides flexibility while maintaining the security benefits of the caching system.
​
Plugin directory structure
​
Standard plugin layout
A complete plugin follows this structure:
enterprise-plugin/
├── .claude-plugin/           # Metadata directory (optional)
│   └── plugin.json             # plugin manifest
├── skills/                   # Skills
│   ├── code-reviewer/
│   │   └── SKILL.md
│   └── pdf-processor/
│       ├── SKILL.md
│       └── scripts/
├── commands/                 # Skills as flat .md files
│   ├── status.md
│   └── logs.md
├── agents/                   # Subagent definitions
│   ├── security-reviewer.md
│   ├── performance-tester.md
│   └── compliance-checker.md
├── output-styles/            # Output style definitions
│   └── terse.md
├── themes/                   # Color theme definitions
│   └── dracula.json
├── monitors/                 # Background monitor configurations
│   └── monitors.json
├── hooks/                    # Hook configurations
│   ├── hooks.json           # Main hook config
│   └── security-hooks.json  # Additional hooks
├── bin/                      # Plugin executables added to PATH
│   └── my-tool               # Invokable as bare command in Bash tool
├── settings.json            # Default settings for the plugin
├── .mcp.json                # MCP server definitions
├── .lsp.json                # LSP server configurations
├── scripts/                 # Hook and utility scripts
│   ├── security-scan.sh
│   ├── format-code.py
│   └── deploy.js
├── LICENSE                  # License file
└── CHANGELOG.md             # Version history
The
.claude-plugin/
directory contains the
plugin.json
file. All other directories (commands/, agents/, skills/, output-styles/, themes/, monitors/, hooks/) must be at the plugin root, not inside
.claude-plugin/
.
A
CLAUDE.md
file at the plugin root is not loaded as project context. Plugins contribute context through skills, agents, and hooks rather than CLAUDE.md. To ship instructions that load into Claude’s context, put them in a
skill
.
​
File locations reference
Component
Default Location
Purpose
Manifest
.claude-plugin/plugin.json
Plugin metadata and configuration (optional)
Skills
skills/
Skills with
<name>/SKILL.md
structure
Commands
commands/
Skills as flat Markdown files. Use
skills/
for new plugins
Agents
agents/
Subagent Markdown files
Output styles
output-styles/
Output style definitions
Themes
themes/
Color theme definitions
Hooks
hooks/hooks.json
Hook configuration
MCP servers
.mcp.json
MCP server definitions
LSP servers
.lsp.json
Language server configurations
Monitors
monitors/monitors.json
Background monitor configurations
Executables
bin/
Executables added to the Bash tool’s
PATH
. Files here are invokable as bare commands in any Bash tool call while the plugin is enabled
Settings
settings.json
Default configuration applied when the plugin is enabled. Only the
agent
and
subagentStatusLine
keys are currently supported
​
CLI commands reference
Claude Code provides CLI commands for non-interactive plugin management, useful for scripting and automation.
​
plugin install
Install a plugin from available marketplaces.
claude
plugin
install
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
for a specific marketplace
Options:
Option
Description
Default
-s, --scope <scope>
Installation scope:
user
,
project
, or
local
user
-h, --help
Display help for command
Scope determines which settings file the installed plugin is added to. For example,
--scope project
writes to
enabledPlugins
in .claude/settings.json, making the plugin available to everyone who clones the project repository.
Examples:
# Install to user scope (default)
claude
plugin
install
formatter@my-marketplace
# Install to project scope (shared with team)
claude
plugin
install
formatter@my-marketplace
--scope
project
# Install to local scope (gitignored)
claude
plugin
install
formatter@my-marketplace
--scope
local
​
plugin uninstall
Remove an installed plugin.
claude
plugin
uninstall
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Uninstall from scope:
user
,
project
, or
local
user
--keep-data
Preserve the plugin’s
persistent data directory
--prune
Also remove auto-installed dependencies that no other plugin requires. See
plugin prune
-y, --yes
Skip the
--prune
confirmation prompt. Required when stdin or stdout is not a TTY
-h, --help
Display help for command
Aliases:
remove
,
rm
By default, uninstalling from the last remaining scope also deletes the plugin’s
${CLAUDE_PLUGIN_DATA}
directory. Use
--keep-data
to preserve it, for example when reinstalling after testing a new version.
​
plugin prune
Remove auto-installed plugin dependencies that are no longer required by any installed plugin. Dependencies that Claude Code pulled in to satisfy another plugin’s
dependencies
field are removed; plugins you installed directly are never touched.
claude
plugin
prune
[options]
Options:
Option
Description
Default
-s, --scope <scope>
Prune at scope:
user
,
project
, or
local
user
--dry-run
List what would be removed without removing anything
-y, --yes
Skip the confirmation prompt. Required when stdin or stdout is not a TTY
-h, --help
Display help for command
Aliases:
autoremove
The command lists orphaned dependencies and asks for confirmation before removing them. To remove a plugin and clean up its dependencies in one step, run
claude plugin uninstall <plugin> --prune
.
claude plugin prune
requires Claude Code v2.1.121 or later.
​
plugin enable
Enable a disabled plugin.
claude
plugin
enable
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to enable:
user
,
project
, or
local
user
-h, --help
Display help for command
​
plugin disable
Disable a plugin without uninstalling it.
claude
plugin
disable
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to disable:
user
,
project
, or
local
user
-h, --help
Display help for command
​
plugin update
Update a plugin to the latest version.
claude
plugin
update
<
plugi
n
>
[options]
Arguments:
<plugin>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-s, --scope <scope>
Scope to update:
user
,
project
,
local
, or
managed
user
-h, --help
Display help for command
​
plugin list
List installed plugins with their version, source marketplace, and enable status.
claude
plugin
list
[options]
Options:
Option
Description
Default
--json
Output as JSON
--available
Include available plugins from marketplaces. Requires
--json
-h, --help
Display help for command
​
plugin details
Show a plugin’s component inventory and projected token cost. The output lists all components the plugin contributes, grouped as Skills (skills and commands), Agents, Hooks, and MCP servers, along with an estimate of how many tokens it adds to each session.
claude
plugin
details
<
nam
e
>
Arguments:
<name>
: Plugin name or
plugin-name@marketplace-name
Options:
Option
Description
Default
-h, --help
Display help for command
The output shows two cost figures for each component:
Always-on:
tokens added to every session by the plugin’s listing text, such as skill descriptions, agent descriptions, and command names, regardless of whether any component fires.
On-invoke:
tokens a component costs when it fires. Shown per component, not as a plugin total, because a typical session invokes only a subset of components.
This example shows what the output looks like for a plugin with two skills:
security-guidance 1.2.0
Real-time security analysis for Claude Code sessions
Source: security-guidance@claude-code-marketplace
Component inventory
Skills (2)  scan-dependencies, review-changes
Agents (0)
Hooks (1)  (harness-only — no model context cost)
MCP servers (0)
Projected token cost
Always-on:   ~180 tok   added to every session
Per-component (rounded)
component            always-on  on-invoke
scan-dependencies        ~100      ~2400
review-changes            ~80      ~1800
On-invoke cost is paid each time a skill or agent fires.
Token counts are estimates and may differ from actual usage.
The always-on total is computed via the
count_tokens
API for your active model. Per-component numbers are proportionally scaled from that total. If the API is unreachable, the command falls back to a character-based estimate.
​
plugin tag
Create a release git tag for the plugin in the current directory. Run from inside the plugin’s folder. See
Tag plugin releases
.
claude
plugin
tag
[options]
Options:
Option
Description
Default
--push
Push the tag to the remote after creating it
--dry-run
Print what would be tagged without creating the tag
-f, --force
Create the tag even if the working tree is dirty or the tag already exists
-h, --help
Display help for command
​
Debugging and development tools
​
Debugging commands
Use
claude --debug
to see plugin loading details:
This shows:
Which plugins are being loaded
Any errors in plugin manifests
Skill, agent, and hook registration
MCP server initialization
​
Common issues
Issue
Cause
Solution
Plugin not loading
Invalid
plugin.json
Run
claude plugin validate
or
/plugin validate
to check
plugin.json
, skill/agent/command frontmatter, and
hooks/hooks.json
for syntax and schema errors
Skills not appearing
Wrong directory structure
Ensure
skills/
or
commands/
is at the plugin root, not inside
.claude-plugin/
Hooks not firing
Script not executable
Run
chmod +x script.sh
MCP server fails
Missing
${CLAUDE_PLUGIN_ROOT}
Use variable for all plugin paths
Path errors
Absolute paths used
All paths must be relative and start with
./
LSP
Executable not found in $PATH
Language server not installed
Install the binary (e.g.,
npm install -g typescript-language-server typescript
)
​
Example error messages
Manifest validation errors
:
Invalid JSON syntax: Unexpected token } in JSON at position 142
: check for missing commas, extra commas, or unquoted strings
Plugin has an invalid manifest file at .claude-plugin/plugin.json. Validation errors: name: Required
: a required field is missing
Plugin has a corrupt manifest file at .claude-plugin/plugin.json. JSON parse error: ...
: JSON syntax error
Plugin loading errors
:
Warning: No commands found in plugin my-plugin custom directory: ./cmds. Expected .md files or SKILL.md in subdirectories.
: command path exists but contains no valid command files
Plugin directory not found at path: ./plugins/my-plugin. Check that the marketplace entry has the correct path.
: the
source
path in marketplace.json points to a non-existent directory
Plugin my-plugin has conflicting manifests: both plugin.json and marketplace entry specify components.
: remove duplicate component definitions or remove
strict: false
in marketplace entry
​
Hook troubleshooting
Hook script not executing
:
Check the script is executable:
chmod +x ./scripts/your-script.sh
Verify the shebang line: First line should be
#!/bin/bash
or
#!/usr/bin/env bash
Check the path uses
${CLAUDE_PLUGIN_ROOT}
:
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/your-script.sh"
Test the script manually:
./scripts/your-script.sh
Hook not triggering on expected events
:
Verify the event name is correct (case-sensitive):
PostToolUse
, not
postToolUse
Check the matcher pattern matches your tools:
"matcher": "Write|Edit"
for file operations
Confirm the hook type is valid:
command
,
http
,
mcp_tool
,
prompt
, or
agent
​
MCP server troubleshooting
Server not starting
:
Check the command exists and is executable
Verify all paths use
${CLAUDE_PLUGIN_ROOT}
variable
Check the MCP server logs:
claude --debug
shows initialization errors
Test the server manually outside of Claude Code
Server tools not appearing
:
Ensure the server is properly configured in
.mcp.json
or
plugin.json
Verify the server implements the MCP protocol correctly
Check for connection timeouts in debug output
​
Directory structure mistakes
Symptoms
: Plugin loads but components (skills, agents, hooks) are missing.
Correct structure
: Components must be at the plugin root, not inside
.claude-plugin/
. Only
plugin.json
belongs in
.claude-plugin/
.
my-plugin/
├── .claude-plugin/
│   └── plugin.json      ← Only manifest here
├── commands/            ← At root level
├── agents/              ← At root level
└── hooks/               ← At root level
If your components are inside
.claude-plugin/
, move them to the plugin root.
Debug checklist
:
Run
claude --debug
and look for “loading plugin” messages
Check that each component directory is listed in the debug output
Verify file permissions allow reading the plugin files
​
Distribution and versioning reference
​
Version management
Claude Code uses the plugin’s version as the cache key that determines whether an update is available. When you run
/plugin update
or auto-update fires, Claude Code computes the current version and skips the update if it matches what’s already installed.
The version is resolved from the first of these that is set:
The
version
field in the plugin’s
plugin.json
The
version
field in the plugin’s marketplace entry in
marketplace.json
The git commit SHA of the plugin’s source, for
github
,
url
,
git-subdir
, and relative-path sources in a git-hosted marketplace
unknown
, for
npm
sources or local directories not inside a git repository
This gives you two ways to version a plugin:
Approach
How
Update behavior
Best for
Explicit version
Set
"version": "2.1.0"
in
plugin.json
Users get updates only when you bump this field. Pushing new commits without bumping it has no effect, and
/plugin update
reports “already at the latest version”.
Published plugins with stable release cycles
Commit-SHA version
Omit
version
from both
plugin.json
and the marketplace entry
Users get updates on every new commit to the plugin’s git source
Internal or team plugins under active development
If you set
version
in
plugin.json
, you must bump it every time you want users to receive changes. Pushing new commits alone is not enough, because Claude Code sees the same version string and keeps the cached copy. If you’re iterating quickly, leave
version
unset so the git commit SHA is used instead.
If you use explicit versions, follow
semantic versioning
(
MAJOR.MINOR.PATCH
): bump MAJOR for breaking changes, MINOR for new features, PATCH for bug fixes. Document changes in a
CHANGELOG.md
.
​
See also
Plugins
- Tutorials and practical usage
Plugin marketplaces
- Creating and managing marketplaces
Skills
- Skill development details
Subagents
- Agent configuration and capabilities
Hooks
- Event handling and automation
MCP
- External tool integration
Settings
- Configuration options for plugins
Was this page helpful?
Yes
No
Hooks reference
Channels reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugins-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Data usage</title>
  <link>https://code.claude.com/docs/en/data-usage</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/data-usage</guid>
  <pubDate>Thu, 29 Aug 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Data usage
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin d...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Data usage
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Data policies
​
Data training policy
Consumer users (Free, Pro, and Max plans)
:
We give you the choice to allow your data to be used to improve future Claude models. We will train new models using data from Free, Pro, and Max accounts when this setting is on (including when you use Claude Code from these accounts).
Commercial users
: (Team and Enterprise plans, API, 3rd-party platforms, and Claude Gov) maintain existing policies: Anthropic does not train generative models using code or prompts sent to Claude Code under commercial terms, unless the customer has chosen to provide their data to us for model improvement (for example, the
Developer Partner Program
).
​
Development Partner Program
If you explicitly opt in to methods to provide us with materials to train on, such as via the
Development Partner Program
, we may use those materials provided to train our models. An organization admin can expressly opt-in to the Development Partner Program for their organization. Note that this program is available only for Anthropic first-party API, and not for Bedrock or Vertex users.
​
Feedback using the
/feedback
command
If you choose to send us feedback about Claude Code using the
/feedback
command, we may use your feedback to improve our products and services. Transcripts shared via
/feedback
are retained for 5 years.
​
Session quality surveys
When you see the “How is Claude doing this session?” prompt in Claude Code, responding to this survey, including selecting “Dismiss”, records only your rating. We do not collect or store any conversation transcripts, inputs, outputs, or other session data as part of the rating prompt itself. Unlike thumbs up/down feedback or
/feedback
reports, this session quality survey is a simple product satisfaction metric.
After the rating prompt, you may see a separate follow-up asking “Can Anthropic look at your session transcript to help us improve Claude Code?”. This is an optional second step distinct from the rating:
Yes
: uploads your conversation transcript, any subagent transcripts, and the raw session log file from disk to Anthropic. Known API key and token patterns are redacted before upload. Source code, file contents, and other conversation content are uploaded as-is. Shared transcripts are retained for up to 6 months.
No
: declines without sending anything
Don’t ask again
: declines and stops this follow-up from appearing in future sessions
Nothing is uploaded unless you explicitly select
Yes
. Organizations with
zero data retention
, or where product feedback is disabled by organization policy, or where
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set, never see this follow-up. Your responses to this survey, including session transcripts submitted after the rating prompt, do not impact your data training preferences and cannot be used to train our AI models.
To disable these surveys, set
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
. The survey is also disabled when
DISABLE_TELEMETRY
,
DO_NOT_TRACK
, or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set. Organizations that block nonessential traffic but capture survey responses through their own
OpenTelemetry collector
can opt the survey back in by setting
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL=1
. The survey then logs ratings to the configured collector only. The transcript-share follow-up and all other Anthropic-bound feedback traffic stay disabled. To control frequency instead of disabling, set
feedbackSurveyRate
in your settings file to a probability between
0
and
1
.
​
Data retention
Anthropic retains Claude Code data based on your account type and preferences.
Consumer users (Free, Pro, and Max plans)
:
Users who allow data use for model improvement: 5-year retention period to support model development and safety improvements
Users who don’t allow data use for model improvement: 30-day retention period
Privacy settings can be changed at any time at
claude.ai/settings/data-privacy-controls
.
Commercial users (Team, Enterprise, and API)
:
Standard: 30-day retention period
Zero data retention
: available for Claude Code on Claude for Enterprise. ZDR is enabled on a per-organization basis; each new organization must have ZDR enabled separately by your account team
Local caching: Claude Code clients store session transcripts locally in plaintext under
~/.claude/projects/
for 30 days by default to enable session resumption. Adjust the period with
cleanupPeriodDays
. See
application data
for what’s stored and how to clear it.
You can delete individual Claude Code on the web sessions at any time. Deleting a session permanently removes the session’s event data. For instructions on how to delete sessions, see
Delete sessions
.
Learn more about data retention practices in our
Privacy Center
.
For full details, please review our
Commercial Terms of Service
(for Team, Enterprise, and API users) or
Consumer Terms
(for Free, Pro, and Max users) and
Privacy Policy
.
​
Data access
For all first party users, you can learn more about what data is logged for
local Claude Code
and
remote Claude Code
.
Remote Control
sessions follow the local data flow since all execution happens on your machine. Note for remote Claude Code, Claude accesses the repository where you initiate your Claude Code session. Claude does not access repositories that you have connected but have not started a session in.
​
Local Claude Code: Data flow and dependencies
The diagram below shows how Claude Code connects to external services during installation and normal operation. Solid lines indicate required connections, while dashed lines represent optional or user-initiated data flows.
Claude Code runs locally. To interact with the LLM, Claude Code sends data over the network. This data includes all user prompts and model outputs, encrypted in transit via TLS 1.2+. Claude Code is compatible with most popular VPNs and LLM proxies.
Encryption at rest depends on your model provider:
Provider
Encryption at rest
Anthropic API
Infrastructure-level disk encryption (AES-256). Enable
Zero Data Retention
for no server-side persistence.
Amazon Bedrock
AES-256 with AWS-managed keys. Customer-managed keys available via AWS KMS.
Google Cloud Vertex AI
Google-managed encryption keys. CMEK available.
Microsoft Foundry
Requests route to Anthropic infrastructure with AES-256 disk encryption.
Claude Code is built on Anthropic’s APIs. For details on API security controls, including API logging procedures, see the compliance artifacts in the
Anthropic Trust Center
.
​
Cloud execution: Data flow and dependencies
When using
Claude Code on the web
, sessions run in Anthropic-managed virtual machines instead of locally. In cloud environments:
Code and data storage:
Your repository is cloned to an isolated VM. Code and session data are subject to the retention and usage policies for your account type (see Data retention section above)
Credentials:
GitHub authentication is handled through a secure proxy; your GitHub credentials never enter the sandbox
Network traffic:
All outbound traffic goes through a security proxy for audit logging and abuse prevention
Session data:
Prompts, code changes, and outputs follow the same data policies as local Claude Code usage
For security details about cloud execution, see
Security
.
​
Telemetry services
Claude Code connects from users’ machines to Anthropic to log operational metrics such as latency, reliability, and usage patterns. This logging does not include any code or file paths. Data is encrypted in transit and at rest. To opt out of telemetry, set the
DISABLE_TELEMETRY
environment variable.
Claude Code connects from users’ machines to Sentry for operational error logging. The data is encrypted in transit using TLS and at rest using 256-bit AES encryption. Read more in the
Sentry security documentation
. To opt out of error logging, set the
DISABLE_ERROR_REPORTING
environment variable.
When you run the
/feedback
command, a copy of your conversation history including code is sent to Anthropic. Before submitting, you choose how much history to include: the current session only, which is the default, or also other sessions from the same project over the last 24 hours or 7 days. The data is encrypted in transit via TLS. Optionally, a GitHub issue is created in the public repository. To opt out, set the
DISABLE_FEEDBACK_COMMAND
environment variable to
1
.
When you use a third-party provider such as Bedrock or Vertex, or have no Anthropic credentials configured,
/feedback
writes the report to a local archive under
~/.claude/feedback-bundles/
instead of sending it to Anthropic. Known API key and token patterns are redacted before the archive is written. Nothing leaves your machine until you send that file to your Anthropic account representative or attach it to a support request.
​
Default behaviors by API provider
By default, error reporting, telemetry, and bug reporting are disabled when using Bedrock, Vertex, Foundry, or Claude Platform on AWS. Session quality surveys and the WebFetch domain safety check are exceptions and run regardless of provider. You can opt out of all non-essential traffic, including surveys, at once by setting
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
. This variable does not affect the WebFetch check, which has its own opt-out. Here are the full default behaviors:
Service
Claude API
Vertex API
Bedrock API
Foundry API
Claude Platform on AWS
Anthropic (Metrics)
Default on.
DISABLE_TELEMETRY=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Sentry (Errors)
Default on.
DISABLE_ERROR_REPORTING=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Claude API (
/feedback
reports)
Default on.
DISABLE_FEEDBACK_COMMAND=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Session quality surveys
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
WebFetch domain safety check
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
All environment variables can be checked into
settings.json
(see
settings reference
).
As of v2.1.126, when a host platform sets
CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST
, metrics default to on for Vertex, Bedrock, and Foundry, and follow the standard
DISABLE_TELEMETRY
opt-out. Sentry error reporting and
/feedback
reports remain off by default on those providers.
​
WebFetch domain safety check
Before fetching a URL, the WebFetch tool sends the requested hostname to
api.anthropic.com
to check it against a safety blocklist maintained by Anthropic. Only the hostname is sent, not the full URL, path, or page contents. Results are cached per hostname for five minutes.
This check runs regardless of which model provider you use and is not affected by
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
. If your network blocks
api.anthropic.com
, WebFetch requests fail until you either allowlist the domain or set
skipWebFetchPreflight: true
in
settings
. Disabling the check means WebFetch attempts to retrieve any URL without consulting the blocklist, so combine it with
WebFetch
permission rules
if you need to restrict which domains Claude can reach.
Was this page helpful?
Yes
No
Security
Zero data retention
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/data-usage" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Data usage
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin d...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Data usage
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Data policies
​
Data training policy
Consumer users (Free, Pro, and Max plans)
:
We give you the choice to allow your data to be used to improve future Claude models. We will train new models using data from Free, Pro, and Max accounts when this setting is on (including when you use Claude Code from these accounts).
Commercial users
: (Team and Enterprise plans, API, 3rd-party platforms, and Claude Gov) maintain existing policies: Anthropic does not train generative models using code or prompts sent to Claude Code under commercial terms, unless the customer has chosen to provide their data to us for model improvement (for example, the
Developer Partner Program
).
​
Development Partner Program
If you explicitly opt in to methods to provide us with materials to train on, such as via the
Development Partner Program
, we may use those materials provided to train our models. An organization admin can expressly opt-in to the Development Partner Program for their organization. Note that this program is available only for Anthropic first-party API, and not for Bedrock or Vertex users.
​
Feedback using the
/feedback
command
If you choose to send us feedback about Claude Code using the
/feedback
command, we may use your feedback to improve our products and services. Transcripts shared via
/feedback
are retained for 5 years.
​
Session quality surveys
When you see the “How is Claude doing this session?” prompt in Claude Code, responding to this survey, including selecting “Dismiss”, records only your rating. We do not collect or store any conversation transcripts, inputs, outputs, or other session data as part of the rating prompt itself. Unlike thumbs up/down feedback or
/feedback
reports, this session quality survey is a simple product satisfaction metric.
After the rating prompt, you may see a separate follow-up asking “Can Anthropic look at your session transcript to help us improve Claude Code?”. This is an optional second step distinct from the rating:
Yes
: uploads your conversation transcript, any subagent transcripts, and the raw session log file from disk to Anthropic. Known API key and token patterns are redacted before upload. Source code, file contents, and other conversation content are uploaded as-is. Shared transcripts are retained for up to 6 months.
No
: declines without sending anything
Don’t ask again
: declines and stops this follow-up from appearing in future sessions
Nothing is uploaded unless you explicitly select
Yes
. Organizations with
zero data retention
, or where product feedback is disabled by organization policy, or where
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set, never see this follow-up. Your responses to this survey, including session transcripts submitted after the rating prompt, do not impact your data training preferences and cannot be used to train our AI models.
To disable these surveys, set
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
. The survey is also disabled when
DISABLE_TELEMETRY
,
DO_NOT_TRACK
, or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set. Organizations that block nonessential traffic but capture survey responses through their own
OpenTelemetry collector
can opt the survey back in by setting
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL=1
. The survey then logs ratings to the configured collector only. The transcript-share follow-up and all other Anthropic-bound feedback traffic stay disabled. To control frequency instead of disabling, set
feedbackSurveyRate
in your settings file to a probability between
0
and
1
.
​
Data retention
Anthropic retains Claude Code data based on your account type and preferences.
Consumer users (Free, Pro, and Max plans)
:
Users who allow data use for model improvement: 5-year retention period to support model development and safety improvements
Users who don’t allow data use for model improvement: 30-day retention period
Privacy settings can be changed at any time at
claude.ai/settings/data-privacy-controls
.
Commercial users (Team, Enterprise, and API)
:
Standard: 30-day retention period
Zero data retention
: available for Claude Code on Claude for Enterprise. ZDR is enabled on a per-organization basis; each new organization must have ZDR enabled separately by your account team
Local caching: Claude Code clients store session transcripts locally in plaintext under
~/.claude/projects/
for 30 days by default to enable session resumption. Adjust the period with
cleanupPeriodDays
. See
application data
for what’s stored and how to clear it.
You can delete individual Claude Code on the web sessions at any time. Deleting a session permanently removes the session’s event data. For instructions on how to delete sessions, see
Delete sessions
.
Learn more about data retention practices in our
Privacy Center
.
For full details, please review our
Commercial Terms of Service
(for Team, Enterprise, and API users) or
Consumer Terms
(for Free, Pro, and Max users) and
Privacy Policy
.
​
Data access
For all first party users, you can learn more about what data is logged for
local Claude Code
and
remote Claude Code
.
Remote Control
sessions follow the local data flow since all execution happens on your machine. Note for remote Claude Code, Claude accesses the repository where you initiate your Claude Code session. Claude does not access repositories that you have connected but have not started a session in.
​
Local Claude Code: Data flow and dependencies
The diagram below shows how Claude Code connects to external services during installation and normal operation. Solid lines indicate required connections, while dashed lines represent optional or user-initiated data flows.
Claude Code runs locally. To interact with the LLM, Claude Code sends data over the network. This data includes all user prompts and model outputs, encrypted in transit via TLS 1.2+. Claude Code is compatible with most popular VPNs and LLM proxies.
Encryption at rest depends on your model provider:
Provider
Encryption at rest
Anthropic API
Infrastructure-level disk encryption (AES-256). Enable
Zero Data Retention
for no server-side persistence.
Amazon Bedrock
AES-256 with AWS-managed keys. Customer-managed keys available via AWS KMS.
Google Cloud Vertex AI
Google-managed encryption keys. CMEK available.
Microsoft Foundry
Requests route to Anthropic infrastructure with AES-256 disk encryption.
Claude Code is built on Anthropic’s APIs. For details on API security controls, including API logging procedures, see the compliance artifacts in the
Anthropic Trust Center
.
​
Cloud execution: Data flow and dependencies
When using
Claude Code on the web
, sessions run in Anthropic-managed virtual machines instead of locally. In cloud environments:
Code and data storage:
Your repository is cloned to an isolated VM. Code and session data are subject to the retention and usage policies for your account type (see Data retention section above)
Credentials:
GitHub authentication is handled through a secure proxy; your GitHub credentials never enter the sandbox
Network traffic:
All outbound traffic goes through a security proxy for audit logging and abuse prevention
Session data:
Prompts, code changes, and outputs follow the same data policies as local Claude Code usage
For security details about cloud execution, see
Security
.
​
Telemetry services
Claude Code connects from users’ machines to Anthropic to log operational metrics such as latency, reliability, and usage patterns. This logging does not include any code or file paths. Data is encrypted in transit and at rest. To opt out of telemetry, set the
DISABLE_TELEMETRY
environment variable.
Claude Code connects from users’ machines to Sentry for operational error logging. The data is encrypted in transit using TLS and at rest using 256-bit AES encryption. Read more in the
Sentry security documentation
. To opt out of error logging, set the
DISABLE_ERROR_REPORTING
environment variable.
When you run the
/feedback
command, a copy of your conversation history including code is sent to Anthropic. Before submitting, you choose how much history to include: the current session only, which is the default, or also other sessions from the same project over the last 24 hours or 7 days. The data is encrypted in transit via TLS. Optionally, a GitHub issue is created in the public repository. To opt out, set the
DISABLE_FEEDBACK_COMMAND
environment variable to
1
.
When you use a third-party provider such as Bedrock or Vertex, or have no Anthropic credentials configured,
/feedback
writes the report to a local archive under
~/.claude/feedback-bundles/
instead of sending it to Anthropic. Known API key and token patterns are redacted before the archive is written. Nothing leaves your machine until you send that file to your Anthropic account representative or attach it to a support request.
​
Default behaviors by API provider
By default, error reporting, telemetry, and bug reporting are disabled when using Bedrock, Vertex, Foundry, or Claude Platform on AWS. Session quality surveys and the WebFetch domain safety check are exceptions and run regardless of provider. You can opt out of all non-essential traffic, including surveys, at once by setting
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
. This variable does not affect the WebFetch check, which has its own opt-out. Here are the full default behaviors:
Service
Claude API
Vertex API
Bedrock API
Foundry API
Claude Platform on AWS
Anthropic (Metrics)
Default on.
DISABLE_TELEMETRY=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Sentry (Errors)
Default on.
DISABLE_ERROR_REPORTING=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Claude API (
/feedback
reports)
Default on.
DISABLE_FEEDBACK_COMMAND=1
to disable.
Default off.
CLAUDE_CODE_USE_VERTEX
must be 1.
Default off.
CLAUDE_CODE_USE_BEDROCK
must be 1.
Default off.
CLAUDE_CODE_USE_FOUNDRY
must be 1.
Default off.
CLAUDE_CODE_USE_ANTHROPIC_AWS
must be 1.
Session quality surveys
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
Default on.
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1
to disable.
WebFetch domain safety check
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
Default on.
skipWebFetchPreflight: true
in
settings
to disable.
All environment variables can be checked into
settings.json
(see
settings reference
).
As of v2.1.126, when a host platform sets
CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST
, metrics default to on for Vertex, Bedrock, and Foundry, and follow the standard
DISABLE_TELEMETRY
opt-out. Sentry error reporting and
/feedback
reports remain off by default on those providers.
​
WebFetch domain safety check
Before fetching a URL, the WebFetch tool sends the requested hostname to
api.anthropic.com
to check it against a safety blocklist maintained by Anthropic. Only the hostname is sent, not the full URL, path, or page contents. Results are cached per hostname for five minutes.
This check runs regardless of which model provider you use and is not affected by
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
. If your network blocks
api.anthropic.com
, WebFetch requests fail until you either allowlist the domain or set
skipWebFetchPreflight: true
in
settings
. Disabling the check means WebFetch attempts to retrieve any URL without consulting the blocklist, so combine it with
WebFetch
permission rules
if you need to restrict which domains Claude can reach.
Was this page helpful?
Yes
No
Security
Zero data retention
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/data-usage" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Launch sessions from links</title>
  <link>https://code.claude.com/docs/en/deep-links</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/deep-links</guid>
  <pubDate>Thu, 29 Aug 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Launch sessions from links
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Launch sessions from links
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A deep link is a
claude-cli://
URL that opens Claude Code in a new terminal window. The URL can carry a working directory and a prompt to pre-fill.
This lets you share a one-click starting point for a task: anyone with Claude Code installed who clicks the link sees a session open with the prompt already typed. The prompt is populated but not sent until you press Enter.
Because a deep link is a URL, you can put one anywhere a link can go:
An incident runbook step that opens the affected service’s repo with a diagnostic prompt
A monitoring alert or dashboard that links to an investigation prompt for a specific metric
A README or wiki page that opens the project with an onboarding prompt
A CI failure notification that pre-fills the failing job’s name
This page covers how to
build a link
,
embed one in a runbook or trigger it from the shell
, and
manage or disable handler registration
on each platform.
Deep links require Claude Code v2.1.91 or later.
​
How it works
The
claude-cli://
prefix is a custom URL scheme that Claude Code registers with your operating system, similar to how
mailto:
links open your email client. The link can live on a web page, in a wiki, in a Slack message, or in any app that renders links. When you click one:
The browser or app hands the URL to your operating system.
The operating system recognizes the
claude-cli://
prefix and starts Claude Code on your machine.
A new terminal window opens with Claude Code running in the directory the link specified, and the link’s prompt text already in the input box.
You read the prompt, edit it if you want, and press Enter to send it.
The link itself can be hosted anywhere, but the session always opens locally on the computer where you clicked. See
Registration and supported platforms
for which terminal emulator opens on each operating system.
The platform that displays the link must allow custom URL schemes. GitHub-rendered Markdown allows
http
and
https
but strips schemes like
claude-cli://
in READMEs, issues, pull requests, and wikis. Only the link text shows, with no link behind it and the URL hidden. See
Troubleshooting
for a workaround.
​
What a launched session shows
A deep link never executes anything on its own. The link only chooses a directory and fills the prompt box. If you click a link from a page you do not trust, the prompt is still inert: nothing reaches the model until you read what was filled in and press Enter.
When the session opens, a banner above the input shows that an external link launched it and which directory it selected. For prompts over 1,000 characters, the banner tells you to scroll and review the full text before pressing Enter, since long prompts can push instructions off screen. Permission rules,
CLAUDE.md
, and trust prompts for the selected directory apply the same way as for any other session.
​
Build a link
Every deep link starts with
claude-cli://open
, which is the only path the handler accepts, followed by optional query parameters. The minimal form opens Claude Code in your home directory with an empty prompt:
claude-cli://open
Add parameters to control where the session starts and what the prompt box contains:
Parameter
Description
q
Text to pre-fill in the prompt box.
URL-encode
the value. Use
%0A
for line breaks in multi-line prompts. Maximum 5,000 characters.
cwd
Absolute path to use as the working directory. Network and UNC paths are rejected.
repo
A GitHub
owner/name
slug. Claude Code resolves it to a local clone it has seen before and starts there. If you have no matching clone, the session opens in your home directory instead.
cwd
and
repo
are
two ways to set the working directory
. If you pass both,
cwd
takes precedence and
repo
is ignored, even if the
cwd
path does not exist.
The following link points at a repository called
acme/payments
with a two-line diagnostic prompt. Replace
acme/payments
with your repository’s
owner/name
slug when you build your own:
claude-cli://open?repo=acme/payments&q=Investigate%20the%20failed%20deploy%20of%20payments-api.%0ACheck%20recent%20commits%20to%20main%20and%20the%20last%20successful%20build.
Clicking it opens a new terminal window, starts Claude Code in your local clone of
acme/payments
, and fills the prompt box with the decoded text:
Investigate the failed deploy of payments-api.
Check recent commits to main and the last successful build.
You can edit the prompt before pressing Enter to send it. If you have no local clone of the repository, the session opens in your home directory instead. See
Choose between
cwd
and
repo
for how the local path is selected when you have multiple clones or worktrees.
​
Choose between
cwd
and
repo
Use
cwd
when everyone who clicks the link has the project at the same absolute path, such as a standardized devcontainer or VM image.
Use
repo
when the link is shared and each person clones to a different location. Claude Code resolves the slug to a local path as follows:
Each time you run
claude
in a Git repository, that directory’s filesystem path is recorded against the repository’s GitHub
owner/name
slug.
When a deep link arrives,
repo
opens whichever matching path you used most recently. Multiple clones and worktrees are tracked separately, so it picks the one you worked in last.
The lookup only finds paths where you have already run Claude Code at least once.
The link does not change which branch is checked out. The session opens in whatever state that directory is currently in.
The launched session shows which path it picked and when that clone last fetched from the remote, so you can tell if you are looking at stale code.
​
Examples
The sections below show two common ways to use a deep link: as a Markdown link in a document and as a command in a script or shell alias.
​
Embed a link in a runbook
A deep link in a runbook gives whoever is triaging a one-click way to start investigating in the right repository with a prepared prompt. The platform that renders the runbook must allow custom URL schemes. GitHub-rendered Markdown does not allow
claude-cli://
, so a deep link in a GitHub README, issue, or wiki shows only its label with no clickable link. See
the troubleshooting note
for a workaround.
The prompt is part of the URL and must be URL-encoded. To produce the encoded value, pass your prompt text through
encodeURIComponent
in a browser console or any URL encoder.
The example below adds an investigation entry point to an incident runbook for a service called
web-gateway
:
## High 5xx rate on web-gateway
1.
Acknowledge the page in PagerDuty.
2.
[
Open Claude Code in the gateway repo
](
claude-cli://open?repo=acme/web-gateway&q=5xx%20rate%20is%20elevated%20on%20web-gateway.%20Check%20recent%20deploys%2C%20error%20logs%20from%20the%20last%2030%20minutes%2C%20and%20open%20incidents%20in%20Linear.
)
3.
Post initial findings in #incident.
To use this in your own runbook, replace
acme/web-gateway
with your service’s repository slug. This allows engineers with Claude Code installed and a local clone of that repository to click step 2 and start investigating with the prompt ready to send.
​
Open a link from the shell
You can also open a deep link from a shell script, alias, or automation rather than by clicking it. Call your operating system’s URL-opening command with the link as the argument.
macOS
Linux
Windows
The built-in
open
command passes the URL to the registered
claude-cli://
handler:
open
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
Most desktop environments provide
xdg-open
, which passes the URL to the registered handler:
xdg-open
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
In PowerShell,
Start-Process
passes the URL to the registered handler:
Start-Process
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
In
cmd.exe
,
start
treats its first quoted argument as a window title, so pass an empty title before the URL:
start
""
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
​
Registration and supported platforms
Claude Code registers the
claude-cli://
handler with your operating system the first time you start an interactive session on macOS, Linux, and Windows. You do not run a separate install command. Registration writes to user-level locations only:
Platform
Handler location
macOS
~/Applications/Claude Code URL Handler.app
Linux
claude-code-url-handler.desktop
under
$XDG_DATA_HOME/applications
, defaulting to
~/.local/share/applications
Windows
HKEY_CURRENT_USER\Software\Classes\claude-cli
The handler launches Claude Code in a detected terminal emulator. On macOS, Claude Code remembers the terminal from your most recent interactive session and reuses it, supporting iTerm2, Ghostty, kitty, Alacritty, WezTerm, and Terminal.app. On Linux it honors the
$TERMINAL
environment variable, then
x-terminal-emulator
, then a list of common emulators. On Windows it prefers Windows Terminal, then PowerShell, then
cmd.exe
.
To prevent registration entirely, set
disableDeepLinkRegistration
to
"disable"
in
settings.json
. To enforce this across an organization so users cannot re-enable it, set it in
managed settings
instead.
​
Open a VS Code tab instead of a terminal
The VS Code extension registers its own handler at
vscode://anthropic.claude-code/open
, which opens a Claude Code editor tab rather than a terminal window. See
Launch a VS Code tab from other tools
for that URL’s parameters.
​
Troubleshooting
​
Clicking the link does nothing
The handler likely is not registered yet. Start an interactive
claude
session once on that machine, exit, and try the link again. If you are on Linux without a desktop environment,
xdg-open
may have nothing to dispatch to.
​
The link renders as plain text instead of being clickable
Some Markdown renderers only allow
http
and
https
links and strip other URL schemes. GitHub does this in READMEs, issues, pull requests, and wikis:
[label](claude-cli://...)
renders as just
label
, with no link and the URL removed. On these platforms, put the deep link in a code block so readers can see the URL and paste it into their browser’s address bar.
​
The session opens in my home directory instead of the repo
The
repo
parameter only resolves to clones Claude Code has already seen. Run
claude
inside the clone once so its path is recorded, or switch the link to use
cwd
with an absolute path.
​
The link opens the wrong terminal
On macOS, start
claude
in your preferred terminal once and the next deep link will use it. On Linux, set the
$TERMINAL
environment variable to your preferred emulator’s command name. On Windows, the order is fixed: install Windows Terminal if you want links to open there instead of a PowerShell or
cmd.exe
window.
​
Learn more
These pages cover related ways to launch or extend Claude Code sessions:
Skills
: store a long runbook prompt as a
/skill
in the repo so the deep link’s
q
parameter only has to name it
Non-interactive mode
: run Claude from a script and capture the output without opening a terminal
Was this page helpful?
Yes
No
Programmatic usage
Troubleshoot installation and login
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/deep-links" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Launch sessions from links
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Launch sessions from links
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A deep link is a
claude-cli://
URL that opens Claude Code in a new terminal window. The URL can carry a working directory and a prompt to pre-fill.
This lets you share a one-click starting point for a task: anyone with Claude Code installed who clicks the link sees a session open with the prompt already typed. The prompt is populated but not sent until you press Enter.
Because a deep link is a URL, you can put one anywhere a link can go:
An incident runbook step that opens the affected service’s repo with a diagnostic prompt
A monitoring alert or dashboard that links to an investigation prompt for a specific metric
A README or wiki page that opens the project with an onboarding prompt
A CI failure notification that pre-fills the failing job’s name
This page covers how to
build a link
,
embed one in a runbook or trigger it from the shell
, and
manage or disable handler registration
on each platform.
Deep links require Claude Code v2.1.91 or later.
​
How it works
The
claude-cli://
prefix is a custom URL scheme that Claude Code registers with your operating system, similar to how
mailto:
links open your email client. The link can live on a web page, in a wiki, in a Slack message, or in any app that renders links. When you click one:
The browser or app hands the URL to your operating system.
The operating system recognizes the
claude-cli://
prefix and starts Claude Code on your machine.
A new terminal window opens with Claude Code running in the directory the link specified, and the link’s prompt text already in the input box.
You read the prompt, edit it if you want, and press Enter to send it.
The link itself can be hosted anywhere, but the session always opens locally on the computer where you clicked. See
Registration and supported platforms
for which terminal emulator opens on each operating system.
The platform that displays the link must allow custom URL schemes. GitHub-rendered Markdown allows
http
and
https
but strips schemes like
claude-cli://
in READMEs, issues, pull requests, and wikis. Only the link text shows, with no link behind it and the URL hidden. See
Troubleshooting
for a workaround.
​
What a launched session shows
A deep link never executes anything on its own. The link only chooses a directory and fills the prompt box. If you click a link from a page you do not trust, the prompt is still inert: nothing reaches the model until you read what was filled in and press Enter.
When the session opens, a banner above the input shows that an external link launched it and which directory it selected. For prompts over 1,000 characters, the banner tells you to scroll and review the full text before pressing Enter, since long prompts can push instructions off screen. Permission rules,
CLAUDE.md
, and trust prompts for the selected directory apply the same way as for any other session.
​
Build a link
Every deep link starts with
claude-cli://open
, which is the only path the handler accepts, followed by optional query parameters. The minimal form opens Claude Code in your home directory with an empty prompt:
claude-cli://open
Add parameters to control where the session starts and what the prompt box contains:
Parameter
Description
q
Text to pre-fill in the prompt box.
URL-encode
the value. Use
%0A
for line breaks in multi-line prompts. Maximum 5,000 characters.
cwd
Absolute path to use as the working directory. Network and UNC paths are rejected.
repo
A GitHub
owner/name
slug. Claude Code resolves it to a local clone it has seen before and starts there. If you have no matching clone, the session opens in your home directory instead.
cwd
and
repo
are
two ways to set the working directory
. If you pass both,
cwd
takes precedence and
repo
is ignored, even if the
cwd
path does not exist.
The following link points at a repository called
acme/payments
with a two-line diagnostic prompt. Replace
acme/payments
with your repository’s
owner/name
slug when you build your own:
claude-cli://open?repo=acme/payments&q=Investigate%20the%20failed%20deploy%20of%20payments-api.%0ACheck%20recent%20commits%20to%20main%20and%20the%20last%20successful%20build.
Clicking it opens a new terminal window, starts Claude Code in your local clone of
acme/payments
, and fills the prompt box with the decoded text:
Investigate the failed deploy of payments-api.
Check recent commits to main and the last successful build.
You can edit the prompt before pressing Enter to send it. If you have no local clone of the repository, the session opens in your home directory instead. See
Choose between
cwd
and
repo
for how the local path is selected when you have multiple clones or worktrees.
​
Choose between
cwd
and
repo
Use
cwd
when everyone who clicks the link has the project at the same absolute path, such as a standardized devcontainer or VM image.
Use
repo
when the link is shared and each person clones to a different location. Claude Code resolves the slug to a local path as follows:
Each time you run
claude
in a Git repository, that directory’s filesystem path is recorded against the repository’s GitHub
owner/name
slug.
When a deep link arrives,
repo
opens whichever matching path you used most recently. Multiple clones and worktrees are tracked separately, so it picks the one you worked in last.
The lookup only finds paths where you have already run Claude Code at least once.
The link does not change which branch is checked out. The session opens in whatever state that directory is currently in.
The launched session shows which path it picked and when that clone last fetched from the remote, so you can tell if you are looking at stale code.
​
Examples
The sections below show two common ways to use a deep link: as a Markdown link in a document and as a command in a script or shell alias.
​
Embed a link in a runbook
A deep link in a runbook gives whoever is triaging a one-click way to start investigating in the right repository with a prepared prompt. The platform that renders the runbook must allow custom URL schemes. GitHub-rendered Markdown does not allow
claude-cli://
, so a deep link in a GitHub README, issue, or wiki shows only its label with no clickable link. See
the troubleshooting note
for a workaround.
The prompt is part of the URL and must be URL-encoded. To produce the encoded value, pass your prompt text through
encodeURIComponent
in a browser console or any URL encoder.
The example below adds an investigation entry point to an incident runbook for a service called
web-gateway
:
## High 5xx rate on web-gateway
1.
Acknowledge the page in PagerDuty.
2.
[
Open Claude Code in the gateway repo
](
claude-cli://open?repo=acme/web-gateway&q=5xx%20rate%20is%20elevated%20on%20web-gateway.%20Check%20recent%20deploys%2C%20error%20logs%20from%20the%20last%2030%20minutes%2C%20and%20open%20incidents%20in%20Linear.
)
3.
Post initial findings in #incident.
To use this in your own runbook, replace
acme/web-gateway
with your service’s repository slug. This allows engineers with Claude Code installed and a local clone of that repository to click step 2 and start investigating with the prompt ready to send.
​
Open a link from the shell
You can also open a deep link from a shell script, alias, or automation rather than by clicking it. Call your operating system’s URL-opening command with the link as the argument.
macOS
Linux
Windows
The built-in
open
command passes the URL to the registered
claude-cli://
handler:
open
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
Most desktop environments provide
xdg-open
, which passes the URL to the registered handler:
xdg-open
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
In PowerShell,
Start-Process
passes the URL to the registered handler:
Start-Process
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
In
cmd.exe
,
start
treats its first quoted argument as a window title, so pass an empty title before the URL:
start
""
"claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
​
Registration and supported platforms
Claude Code registers the
claude-cli://
handler with your operating system the first time you start an interactive session on macOS, Linux, and Windows. You do not run a separate install command. Registration writes to user-level locations only:
Platform
Handler location
macOS
~/Applications/Claude Code URL Handler.app
Linux
claude-code-url-handler.desktop
under
$XDG_DATA_HOME/applications
, defaulting to
~/.local/share/applications
Windows
HKEY_CURRENT_USER\Software\Classes\claude-cli
The handler launches Claude Code in a detected terminal emulator. On macOS, Claude Code remembers the terminal from your most recent interactive session and reuses it, supporting iTerm2, Ghostty, kitty, Alacritty, WezTerm, and Terminal.app. On Linux it honors the
$TERMINAL
environment variable, then
x-terminal-emulator
, then a list of common emulators. On Windows it prefers Windows Terminal, then PowerShell, then
cmd.exe
.
To prevent registration entirely, set
disableDeepLinkRegistration
to
"disable"
in
settings.json
. To enforce this across an organization so users cannot re-enable it, set it in
managed settings
instead.
​
Open a VS Code tab instead of a terminal
The VS Code extension registers its own handler at
vscode://anthropic.claude-code/open
, which opens a Claude Code editor tab rather than a terminal window. See
Launch a VS Code tab from other tools
for that URL’s parameters.
​
Troubleshooting
​
Clicking the link does nothing
The handler likely is not registered yet. Start an interactive
claude
session once on that machine, exit, and try the link again. If you are on Linux without a desktop environment,
xdg-open
may have nothing to dispatch to.
​
The link renders as plain text instead of being clickable
Some Markdown renderers only allow
http
and
https
links and strip other URL schemes. GitHub does this in READMEs, issues, pull requests, and wikis:
[label](claude-cli://...)
renders as just
label
, with no link and the URL removed. On these platforms, put the deep link in a code block so readers can see the URL and paste it into their browser’s address bar.
​
The session opens in my home directory instead of the repo
The
repo
parameter only resolves to clones Claude Code has already seen. Run
claude
inside the clone once so its path is recorded, or switch the link to use
cwd
with an absolute path.
​
The link opens the wrong terminal
On macOS, start
claude
in your preferred terminal once and the next deep link will use it. On Linux, set the
$TERMINAL
environment variable to your preferred emulator’s command name. On Windows, the order is fixed: install Windows Terminal if you want links to open there instead of a PowerShell or
cmd.exe
window.
​
Learn more
These pages cover related ways to launch or extend Claude Code sessions:
Skills
: store a long runbook prompt as a
/skill
in the repo so the deep link’s
q
parameter only has to name it
Non-interactive mode
: run Claude from a script and capture the output without opening a terminal
Was this page helpful?
Yes
No
Programmatic usage
Troubleshoot installation and login
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/deep-links" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Manage costs effectively</title>
  <link>https://code.claude.com/docs/en/costs</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/costs</guid>
  <pubDate>Thu, 29 Aug 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Manage costs effectively
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketpl...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Manage costs effectively
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code charges by API token consumption. For subscription plan pricing (Pro, Max, Team, Enterprise), see
claude.com/pricing
. Per-developer costs vary widely based on model selection, codebase size, and usage patterns such as running multiple instances or automation.
Across enterprise deployments, the average cost is around $13 per developer per active day and $150-250 per developer per month, with costs remaining below $30 per active day for 90% of users. To estimate spend for your own team, start with a small pilot group and use the tracking tools below to establish a baseline before wider rollout.
This page covers how to
track your costs
,
manage costs for teams
, and
reduce token usage
.
​
Track your costs
​
Using the
/usage
command
The Session block in
/usage
shows API token usage and is intended for API users. Claude Max and Pro subscribers have usage included in their subscription, so the session cost figure isn’t relevant for billing purposes. Subscribers see plan usage bars and activity stats on the same screen.
The
/usage
command provides detailed token usage statistics for your current session. The dollar figure is an estimate computed locally from token counts and may differ from your actual bill. For authoritative billing, see the Usage page in the
Claude Console
.
Total cost:            $0.55
Total duration (API):  6m 19.7s
Total duration (wall): 6h 33m 10.2s
Total code changes:    0 lines added, 0 lines removed
​
Managing costs for teams
When using Claude API, you can
set workspace spend limits
on the total Claude Code workspace spend. Admins can
view cost and usage reporting
in the Console.
When you first authenticate Claude Code with your Claude Console account, a workspace called “Claude Code” is automatically created for you. This workspace provides centralized cost tracking and management for all Claude Code usage in your organization. You cannot create API keys for this workspace; it is exclusively for Claude Code authentication and usage.
For organizations with custom rate limits, Claude Code traffic in this workspace counts toward your organization’s overall API rate limits. You can set a
workspace rate limit
on this workspace’s Limits page in the Claude Console to cap Claude Code’s share and protect other production workloads.
On Bedrock, Vertex, and Foundry, Claude Code does not send metrics from your cloud. To get cost metrics, several large enterprises reported using
LiteLLM
, which is an open-source tool that helps companies
track spend by key
. This project is unaffiliated with Anthropic and has not been audited for security.
​
Rate limit recommendations
When setting up Claude Code for teams, consider these Token Per Minute (TPM) and Request Per Minute (RPM) per-user recommendations based on your organization size:
Team size
TPM per user
RPM per user
1-5 users
200k-300k
5-7
5-20 users
100k-150k
2.5-3.5
20-50 users
50k-75k
1.25-1.75
50-100 users
25k-35k
0.62-0.87
100-500 users
15k-20k
0.37-0.47
500+ users
10k-15k
0.25-0.35
For example, if you have 200 users, you might request 20k TPM for each user, or 4 million total TPM (200*20,000 = 4 million).
The TPM per user decreases as team size grows because fewer users tend to use Claude Code concurrently in larger organizations. These rate limits apply at the organization level, not per individual user, which means individual users can temporarily consume more than their calculated share when others aren’t actively using the service.
If you anticipate scenarios with unusually high concurrent usage (such as live training sessions with large groups), you may need higher TPM allocations per user.
​
Agent team token costs
Agent teams
spawn multiple Claude Code instances, each with its own context window. Token usage scales with the number of active teammates and how long each one runs.
To keep agent team costs manageable:
Use Sonnet for teammates. It balances capability and cost for coordination tasks.
Keep teams small. Each teammate runs its own context window, so token usage is roughly proportional to team size.
Keep spawn prompts focused. Teammates load CLAUDE.md, MCP servers, and skills automatically, but everything in the spawn prompt adds to their context from the start.
Clean up teams when work is done. Active teammates continue consuming tokens even if idle.
Agent teams are disabled by default. Set
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
in your
settings.json
or environment to enable them. See
enable agent teams
.
​
Reduce token usage
Token costs scale with context size: the more context Claude processes, the more tokens you use. Claude Code automatically optimizes costs through prompt caching (which reduces costs for repeated content like system prompts) and auto-compaction (which summarizes conversation history when approaching context limits).
The following strategies help you keep context small and reduce per-message costs.
​
Manage context proactively
Use
/usage
to check your current token usage, or
configure your status line
to display it continuously.
Clear between tasks
: Use
/clear
to start fresh when switching to unrelated work. Stale context wastes tokens on every subsequent message. Use
/rename
before clearing so you can easily find the session later, then
/resume
to return to it.
Add custom compaction instructions
:
/compact Focus on code samples and API usage
tells Claude what to preserve during summarization.
You can also customize compaction behavior in your CLAUDE.md:
# Compact instructions
When you are using compact, please focus on test output and code changes
​
Choose the right model
Sonnet handles most coding tasks well and costs less than Opus. Reserve Opus for complex architectural decisions or multi-step reasoning. Use
/model
to switch models mid-session, or set a default in
/config
. For simple subagent tasks, specify
model: haiku
in your
subagent configuration
.
​
Reduce MCP server overhead
MCP tool definitions are
deferred by default
, so only tool names enter context until Claude uses a specific tool. Run
/context
to see what’s consuming space.
Prefer CLI tools when available
: Tools like
gh
,
aws
,
gcloud
, and
sentry-cli
are still more context-efficient than MCP servers because they don’t add any per-tool listing. Claude can run CLI commands directly.
Disable unused servers
: Run
/mcp
to see configured servers and disable any you’re not actively using.
​
Install code intelligence plugins for typed languages
Code intelligence plugins
give Claude precise symbol navigation instead of text-based search, reducing unnecessary file reads when exploring unfamiliar code. A single “go to definition” call replaces what might otherwise be a grep followed by reading multiple candidate files. Installed language servers also report type errors automatically after edits, so Claude catches mistakes without running a compiler.
​
Offload processing to hooks and skills
Custom
hooks
can preprocess data before Claude sees it. Instead of Claude reading a 10,000-line log file to find errors, a hook can grep for
ERROR
and return only matching lines, reducing context from tens of thousands of tokens to hundreds.
A
skill
can give Claude domain knowledge so it doesn’t have to explore. For example, a “codebase-overview” skill could describe your project’s architecture, key directories, and naming conventions. When Claude invokes the skill, it gets this context immediately instead of spending tokens reading multiple files to understand the structure.
For example, this PreToolUse hook filters test output to show only failures:
settings.json
filter-test-output.sh
Add this to your
settings.json
to run the hook before every Bash command:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"~/.claude/hooks/filter-test-output.sh"
}
]
}
]
}
}
The hook calls this script, which checks if the command is a test runner and modifies it to show only failures:
#!/bin/bash
input
=
$(
cat
)
cmd
=
$(
echo
"
$input
"
|
jq
-r
'.tool_input.command'
)
# If running tests, filter to show only failures
if
[[
"
$cmd
"
=~
^(
npm
test
|
pytest
|
go
test
) ]];
then
filtered_cmd
=
"
$cmd
2>&1 | grep -A 5 -E '(FAIL|ERROR|error:)' | head -100"
echo
"{
\"
hookSpecificOutput
\"
:{
\"
hookEventName
\"
:
\"
PreToolUse
\"
,
\"
permissionDecision
\"
:
\"
allow
\"
,
\"
updatedInput
\"
:{
\"
command
\"
:
\"
$filtered_cmd
\"
}}}"
else
echo
"{}"
fi
​
Move instructions from CLAUDE.md to skills
Your
CLAUDE.md
file is loaded into context at session start. If it contains detailed instructions for specific workflows (like PR reviews or database migrations), those tokens are present even when you’re doing unrelated work.
Skills
load on-demand only when invoked, so moving specialized instructions into skills keeps your base context smaller. Aim to keep CLAUDE.md under 200 lines by including only essentials.
​
Adjust extended thinking
Extended thinking is enabled by default because it significantly improves performance on complex planning and reasoning tasks. Thinking tokens are billed as output tokens, and the default budget can be tens of thousands of tokens per request depending on the model. For simpler tasks where deep reasoning isn’t needed, you can reduce costs by lowering the
effort level
with
/effort
or in
/model
, disabling thinking in
/config
, or lowering the budget with
MAX_THINKING_TOKENS=8000
.
​
Delegate verbose operations to subagents
Running tests, fetching documentation, or processing log files can consume significant context. Delegate these to
subagents
so the verbose output stays in the subagent’s context while only a summary returns to your main conversation.
​
Manage agent team costs
Agent teams use approximately 7x more tokens than standard sessions when teammates run in plan mode, because each teammate maintains its own context window and runs as a separate Claude instance. Keep team tasks small and self-contained to limit per-teammate token usage. See
agent teams
for details.
​
Write specific prompts
Vague requests like “improve this codebase” trigger broad scanning. Specific requests like “add input validation to the login function in auth.ts” let Claude work efficiently with minimal file reads.
​
Work efficiently on complex tasks
For longer or more complex work, these habits help avoid wasted tokens from going down the wrong path:
Use plan mode for complex tasks
: Press Shift+Tab to enter
plan mode
before implementation. Claude explores the codebase and proposes an approach for your approval, preventing expensive re-work when the initial direction is wrong.
Course-correct early
: If Claude starts heading the wrong direction, press Escape to stop immediately. Use
/rewind
or double-tap Escape to restore conversation and code to a previous checkpoint.
Give verification targets
: Include test cases, paste screenshots, or define expected output in your prompt. When Claude can verify its own work, it catches issues before you need to request fixes.
Test incrementally
: Write one file, test it, then continue. This catches issues early when they’re cheap to fix.
​
Background token usage
Claude Code uses tokens for some background functionality even when idle:
Conversation summarization
: Background jobs that summarize previous conversations for the
claude --resume
feature
Command processing
: Some commands like
/usage
may generate requests to check status
These background processes consume a small amount of tokens (typically under $0.04 per session) even without active interaction.
​
Understanding changes in Claude Code behavior
Claude Code regularly receives updates that may change how features work, including cost reporting. Run
claude --version
to check your current version. For specific billing questions, contact Anthropic support through your
Console account
.
Was this page helpful?
Yes
No
Monitoring
Track team usage with analytics
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/costs" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Manage costs effectively
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketpl...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Manage costs effectively
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code charges by API token consumption. For subscription plan pricing (Pro, Max, Team, Enterprise), see
claude.com/pricing
. Per-developer costs vary widely based on model selection, codebase size, and usage patterns such as running multiple instances or automation.
Across enterprise deployments, the average cost is around $13 per developer per active day and $150-250 per developer per month, with costs remaining below $30 per active day for 90% of users. To estimate spend for your own team, start with a small pilot group and use the tracking tools below to establish a baseline before wider rollout.
This page covers how to
track your costs
,
manage costs for teams
, and
reduce token usage
.
​
Track your costs
​
Using the
/usage
command
The Session block in
/usage
shows API token usage and is intended for API users. Claude Max and Pro subscribers have usage included in their subscription, so the session cost figure isn’t relevant for billing purposes. Subscribers see plan usage bars and activity stats on the same screen.
The
/usage
command provides detailed token usage statistics for your current session. The dollar figure is an estimate computed locally from token counts and may differ from your actual bill. For authoritative billing, see the Usage page in the
Claude Console
.
Total cost:            $0.55
Total duration (API):  6m 19.7s
Total duration (wall): 6h 33m 10.2s
Total code changes:    0 lines added, 0 lines removed
​
Managing costs for teams
When using Claude API, you can
set workspace spend limits
on the total Claude Code workspace spend. Admins can
view cost and usage reporting
in the Console.
When you first authenticate Claude Code with your Claude Console account, a workspace called “Claude Code” is automatically created for you. This workspace provides centralized cost tracking and management for all Claude Code usage in your organization. You cannot create API keys for this workspace; it is exclusively for Claude Code authentication and usage.
For organizations with custom rate limits, Claude Code traffic in this workspace counts toward your organization’s overall API rate limits. You can set a
workspace rate limit
on this workspace’s Limits page in the Claude Console to cap Claude Code’s share and protect other production workloads.
On Bedrock, Vertex, and Foundry, Claude Code does not send metrics from your cloud. To get cost metrics, several large enterprises reported using
LiteLLM
, which is an open-source tool that helps companies
track spend by key
. This project is unaffiliated with Anthropic and has not been audited for security.
​
Rate limit recommendations
When setting up Claude Code for teams, consider these Token Per Minute (TPM) and Request Per Minute (RPM) per-user recommendations based on your organization size:
Team size
TPM per user
RPM per user
1-5 users
200k-300k
5-7
5-20 users
100k-150k
2.5-3.5
20-50 users
50k-75k
1.25-1.75
50-100 users
25k-35k
0.62-0.87
100-500 users
15k-20k
0.37-0.47
500+ users
10k-15k
0.25-0.35
For example, if you have 200 users, you might request 20k TPM for each user, or 4 million total TPM (200*20,000 = 4 million).
The TPM per user decreases as team size grows because fewer users tend to use Claude Code concurrently in larger organizations. These rate limits apply at the organization level, not per individual user, which means individual users can temporarily consume more than their calculated share when others aren’t actively using the service.
If you anticipate scenarios with unusually high concurrent usage (such as live training sessions with large groups), you may need higher TPM allocations per user.
​
Agent team token costs
Agent teams
spawn multiple Claude Code instances, each with its own context window. Token usage scales with the number of active teammates and how long each one runs.
To keep agent team costs manageable:
Use Sonnet for teammates. It balances capability and cost for coordination tasks.
Keep teams small. Each teammate runs its own context window, so token usage is roughly proportional to team size.
Keep spawn prompts focused. Teammates load CLAUDE.md, MCP servers, and skills automatically, but everything in the spawn prompt adds to their context from the start.
Clean up teams when work is done. Active teammates continue consuming tokens even if idle.
Agent teams are disabled by default. Set
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
in your
settings.json
or environment to enable them. See
enable agent teams
.
​
Reduce token usage
Token costs scale with context size: the more context Claude processes, the more tokens you use. Claude Code automatically optimizes costs through prompt caching (which reduces costs for repeated content like system prompts) and auto-compaction (which summarizes conversation history when approaching context limits).
The following strategies help you keep context small and reduce per-message costs.
​
Manage context proactively
Use
/usage
to check your current token usage, or
configure your status line
to display it continuously.
Clear between tasks
: Use
/clear
to start fresh when switching to unrelated work. Stale context wastes tokens on every subsequent message. Use
/rename
before clearing so you can easily find the session later, then
/resume
to return to it.
Add custom compaction instructions
:
/compact Focus on code samples and API usage
tells Claude what to preserve during summarization.
You can also customize compaction behavior in your CLAUDE.md:
# Compact instructions
When you are using compact, please focus on test output and code changes
​
Choose the right model
Sonnet handles most coding tasks well and costs less than Opus. Reserve Opus for complex architectural decisions or multi-step reasoning. Use
/model
to switch models mid-session, or set a default in
/config
. For simple subagent tasks, specify
model: haiku
in your
subagent configuration
.
​
Reduce MCP server overhead
MCP tool definitions are
deferred by default
, so only tool names enter context until Claude uses a specific tool. Run
/context
to see what’s consuming space.
Prefer CLI tools when available
: Tools like
gh
,
aws
,
gcloud
, and
sentry-cli
are still more context-efficient than MCP servers because they don’t add any per-tool listing. Claude can run CLI commands directly.
Disable unused servers
: Run
/mcp
to see configured servers and disable any you’re not actively using.
​
Install code intelligence plugins for typed languages
Code intelligence plugins
give Claude precise symbol navigation instead of text-based search, reducing unnecessary file reads when exploring unfamiliar code. A single “go to definition” call replaces what might otherwise be a grep followed by reading multiple candidate files. Installed language servers also report type errors automatically after edits, so Claude catches mistakes without running a compiler.
​
Offload processing to hooks and skills
Custom
hooks
can preprocess data before Claude sees it. Instead of Claude reading a 10,000-line log file to find errors, a hook can grep for
ERROR
and return only matching lines, reducing context from tens of thousands of tokens to hundreds.
A
skill
can give Claude domain knowledge so it doesn’t have to explore. For example, a “codebase-overview” skill could describe your project’s architecture, key directories, and naming conventions. When Claude invokes the skill, it gets this context immediately instead of spending tokens reading multiple files to understand the structure.
For example, this PreToolUse hook filters test output to show only failures:
settings.json
filter-test-output.sh
Add this to your
settings.json
to run the hook before every Bash command:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"~/.claude/hooks/filter-test-output.sh"
}
]
}
]
}
}
The hook calls this script, which checks if the command is a test runner and modifies it to show only failures:
#!/bin/bash
input
=
$(
cat
)
cmd
=
$(
echo
"
$input
"
|
jq
-r
'.tool_input.command'
)
# If running tests, filter to show only failures
if
[[
"
$cmd
"
=~
^(
npm
test
|
pytest
|
go
test
) ]];
then
filtered_cmd
=
"
$cmd
2>&1 | grep -A 5 -E '(FAIL|ERROR|error:)' | head -100"
echo
"{
\"
hookSpecificOutput
\"
:{
\"
hookEventName
\"
:
\"
PreToolUse
\"
,
\"
permissionDecision
\"
:
\"
allow
\"
,
\"
updatedInput
\"
:{
\"
command
\"
:
\"
$filtered_cmd
\"
}}}"
else
echo
"{}"
fi
​
Move instructions from CLAUDE.md to skills
Your
CLAUDE.md
file is loaded into context at session start. If it contains detailed instructions for specific workflows (like PR reviews or database migrations), those tokens are present even when you’re doing unrelated work.
Skills
load on-demand only when invoked, so moving specialized instructions into skills keeps your base context smaller. Aim to keep CLAUDE.md under 200 lines by including only essentials.
​
Adjust extended thinking
Extended thinking is enabled by default because it significantly improves performance on complex planning and reasoning tasks. Thinking tokens are billed as output tokens, and the default budget can be tens of thousands of tokens per request depending on the model. For simpler tasks where deep reasoning isn’t needed, you can reduce costs by lowering the
effort level
with
/effort
or in
/model
, disabling thinking in
/config
, or lowering the budget with
MAX_THINKING_TOKENS=8000
.
​
Delegate verbose operations to subagents
Running tests, fetching documentation, or processing log files can consume significant context. Delegate these to
subagents
so the verbose output stays in the subagent’s context while only a summary returns to your main conversation.
​
Manage agent team costs
Agent teams use approximately 7x more tokens than standard sessions when teammates run in plan mode, because each teammate maintains its own context window and runs as a separate Claude instance. Keep team tasks small and self-contained to limit per-teammate token usage. See
agent teams
for details.
​
Write specific prompts
Vague requests like “improve this codebase” trigger broad scanning. Specific requests like “add input validation to the login function in auth.ts” let Claude work efficiently with minimal file reads.
​
Work efficiently on complex tasks
For longer or more complex work, these habits help avoid wasted tokens from going down the wrong path:
Use plan mode for complex tasks
: Press Shift+Tab to enter
plan mode
before implementation. Claude explores the codebase and proposes an approach for your approval, preventing expensive re-work when the initial direction is wrong.
Course-correct early
: If Claude starts heading the wrong direction, press Escape to stop immediately. Use
/rewind
or double-tap Escape to restore conversation and code to a previous checkpoint.
Give verification targets
: Include test cases, paste screenshots, or define expected output in your prompt. When Claude can verify its own work, it catches issues before you need to request fixes.
Test incrementally
: Write one file, test it, then continue. This catches issues early when they’re cheap to fix.
​
Background token usage
Claude Code uses tokens for some background functionality even when idle:
Conversation summarization
: Background jobs that summarize previous conversations for the
claude --resume
feature
Command processing
: Some commands like
/usage
may generate requests to check status
These background processes consume a small amount of tokens (typically under $0.04 per session) even without active interaction.
​
Understanding changes in Claude Code behavior
Claude Code regularly receives updates that may change how features work, including cost reporting. Run
claude --version
to check your current version. For specific billing questions, contact Anthropic support through your
Console account
.
Was this page helpful?
Yes
No
Monitoring
Track team usage with analytics
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/costs" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Sandboxing</title>
  <link>https://code.claude.com/docs/en/sandboxing</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/sandboxing</guid>
  <pubDate>Tue, 27 Aug 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Sandboxing
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Sandboxing
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
Claude Code features native sandboxing to provide a more secure environment for agent execution while reducing the need for constant permission prompts. Instead of asking permission for each bash command, sandboxing creates defined boundaries upfront where Claude Code can work more freely with reduced risk.
The sandboxed bash tool uses OS-level primitives to enforce both filesystem and network isolation.
​
Why sandboxing matters
Traditional permission-based security requires constant user approval for bash commands. While this provides control, it can lead to:
Approval fatigue
: Repeatedly clicking “approve” can cause users to pay less attention to what they’re approving
Reduced productivity
: Constant interruptions slow down development workflows
Limited autonomy
: Claude Code cannot work as efficiently when waiting for approvals
Sandboxing addresses these challenges by:
Defining clear boundaries
: Specify exactly which directories and network hosts Claude Code can access
Reducing permission prompts
: Safe commands within the sandbox don’t require approval
Maintaining security
: Attempts to access resources outside the sandbox trigger immediate notifications
Enabling autonomy
: Claude Code can run more independently within defined limits
Effective sandboxing requires
both
filesystem and network isolation. Without network isolation, a compromised agent could exfiltrate sensitive files like SSH keys. Without filesystem isolation, a compromised agent could backdoor system resources to gain network access. When configuring sandboxing it is important to ensure that your configured settings do not create bypasses in these systems.
​
How it works
​
Filesystem isolation
The sandboxed bash tool restricts file system access to specific directories:
Default writes behavior
: Read and write access to the current working directory and its subdirectories
Default read behavior
: Read access to the entire computer, except certain denied directories
Blocked access
: Cannot modify files outside the current working directory without explicit permission
Configurable
: Define custom allowed and denied paths through settings
You can grant write access to additional paths using
sandbox.filesystem.allowWrite
in your settings. These restrictions are enforced at the OS level (Seatbelt on macOS, bubblewrap on Linux), so they apply to all subprocess commands, including tools like
kubectl
,
terraform
, and
npm
, not just Claude’s file tools.
​
Network isolation
Network access is controlled through a proxy server running outside the sandbox:
Domain restrictions
: Only approved domains can be accessed
User confirmation
: New domain requests trigger permission prompts (unless
allowManagedDomainsOnly
is enabled, which blocks non-allowed domains automatically)
Custom proxy support
: Advanced users can implement custom rules on outgoing traffic
Comprehensive coverage
: Restrictions apply to all scripts, programs, and subprocesses spawned by commands
The built-in proxy enforces the allowlist based on the requested hostname and does not terminate or inspect TLS traffic. See
Security limitations
for the implications of this design, and
Custom proxy configuration
if your threat model requires TLS inspection.
​
OS-level enforcement
The sandboxed bash tool leverages operating system security primitives:
macOS
: Uses Seatbelt for sandbox enforcement
Linux
: Uses
bubblewrap
for isolation
WSL2
: Uses bubblewrap, same as Linux
WSL1 is not supported because bubblewrap requires kernel features only available in WSL2.
These OS-level restrictions ensure that all child processes spawned by Claude Code’s commands inherit the same security boundaries.
​
Getting started
​
Prerequisites
On
macOS
, sandboxing works out of the box using the built-in Seatbelt framework.
On
Linux and WSL2
, install the required packages first:
Ubuntu/Debian
Fedora
sudo
apt-get
install
bubblewrap
socat
sudo
dnf
install
bubblewrap
socat
On Ubuntu 24.04 and later, the default AppArmor policy prevents bubblewrap from creating the user namespaces it needs for isolation. Add an AppArmor profile that grants
bwrap
this capability:
sudo
tee
/etc/apparmor.d/bwrap
>
/dev/null
<<
'EOF'
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}
EOF
The profile applies only to
bwrap
itself, not to the commands it runs inside the sandbox. Reload AppArmor to apply it:
sudo
systemctl
reload
apparmor
WSL1 does not support sandboxing because it lacks the required Linux namespace primitives. If you see
Sandboxing requires WSL2
, upgrade your distribution to WSL2 or run Claude Code without sandboxing.
On WSL2, sandboxed commands cannot launch Windows binaries such as
cmd.exe
,
powershell.exe
, or anything under
/mnt/c/
. WSL hands these off to the Windows host over a Unix socket, which the sandbox blocks. If a command needs to invoke a Windows binary, add it to
excludedCommands
so it runs outside the sandbox.
​
Enable sandboxing
You can enable sandboxing by running the
/sandbox
command:
/sandbox
This opens a menu where you can choose between sandbox modes. If required dependencies are missing (such as
bubblewrap
or
socat
on Linux), the menu displays installation instructions for your platform.
By default, if the sandbox cannot start (missing dependencies or unsupported platform), Claude Code shows a warning and runs commands without sandboxing. To make this a hard failure instead, set
sandbox.failIfUnavailable
to
true
. This is intended for managed deployments that require sandboxing as a security gate.
​
Sandbox modes
Claude Code offers two sandbox modes:
Auto-allow mode
: Bash commands will attempt to run inside the sandbox and are automatically allowed without requiring permission. Commands that cannot be sandboxed (such as those needing network access to non-allowed hosts) fall back to the regular permission flow. Explicit deny rules are always respected, and
rm
or
rmdir
commands that target
/
, your home directory, or other critical system paths still trigger a permission prompt. Ask rules apply only to commands that fall back to the regular permission flow.
Regular permissions mode
: All bash commands go through the standard permission flow, even when sandboxed. This provides more control but requires more approvals.
In both modes, the sandbox enforces the same filesystem and network restrictions. The difference is only in whether sandboxed commands are auto-approved or require explicit permission.
Auto-allow mode works independently of your permission mode setting. Even if you’re not in “accept edits” mode, sandboxed bash commands will run automatically when auto-allow is enabled. This means bash commands that modify files within the sandbox boundaries will execute without prompting, even when file edit tools would normally require approval.
​
Configure sandboxing
Customize sandbox behavior through your
settings.json
file. See
Settings
for complete configuration reference.
​
Granting subprocess write access to specific paths
By default, sandboxed commands can only write to the current working directory. If subprocess commands like
kubectl
,
terraform
, or
npm
need to write outside the project directory, use
sandbox.filesystem.allowWrite
to grant access to specific paths:
{
"sandbox"
: {
"enabled"
:
true
,
"filesystem"
: {
"allowWrite"
: [
"~/.kube"
,
"/tmp/build"
]
}
}
}
These paths are enforced at the OS level, so all commands running inside the sandbox, including their child processes, respect them. This is the recommended approach when a tool needs write access to a specific location, rather than excluding the tool from the sandbox entirely with
excludedCommands
.
When
allowWrite
(or
denyWrite
/
denyRead
/
allowRead
) is defined in multiple
settings scopes
, the arrays are
merged
, meaning paths from every scope are combined, not replaced. For example, if managed settings allow writes to
/opt/company-tools
and a user adds
~/.kube
in their personal settings, both paths are included in the final sandbox configuration. This means users and projects can extend the list without duplicating or overriding paths set by higher-priority scopes.
Path prefixes control how paths are resolved:
Prefix
Meaning
Example
/
Absolute path from filesystem root
/tmp/build
stays
/tmp/build
~/
Relative to home directory
~/.kube
becomes
$HOME/.kube
./
or no prefix
Relative to the project root for project settings, or to
~/.claude
for user settings
./output
in
.claude/settings.json
resolves to
<project-root>/output
The older
//path
prefix for absolute paths still works. If you previously used single-slash
/path
expecting project-relative resolution, switch to
./path
. This syntax differs from
Read and Edit permission rules
, which use
//path
for absolute and
/path
for project-relative. Sandbox filesystem paths use standard conventions:
/tmp/build
is an absolute path.
You can also deny write or read access using
sandbox.filesystem.denyWrite
and
sandbox.filesystem.denyRead
. These are merged with any paths from
Edit(...)
and
Read(...)
permission rules. To re-allow reading specific paths within a denied region, use
sandbox.filesystem.allowRead
, which takes precedence over
denyRead
. When
allowManagedReadPathsOnly
is enabled in managed settings, only managed
allowRead
entries are respected; user, project, and local
allowRead
entries are ignored.
denyRead
still merges from all sources.
For example, to block reading from the entire home directory while still allowing reads from the current project, add this to your project’s
.claude/settings.json
:
{
"sandbox"
: {
"enabled"
:
true
,
"filesystem"
: {
"denyRead"
: [
"~/"
],
"allowRead"
: [
"."
]
}
}
}
The
.
in
allowRead
resolves to the project root because this configuration lives in project settings. If you placed the same configuration in
~/.claude/settings.json
,
.
would resolve to
~/.claude
instead, and project files would remain blocked by the
denyRead
rule.
Not all commands are compatible with sandboxing out of the box. Some notes that may help you make the most out of the sandbox:
Many CLI tools require accessing certain hosts. As you use these tools, they will request permission to access certain hosts. Granting permission will allow them to access these hosts now and in the future, enabling them to safely execute inside the sandbox.
watchman
is incompatible with running in the sandbox. If you’re running
jest
, consider using
jest --no-watchman
docker
is incompatible with running in the sandbox. Consider specifying
docker *
in
excludedCommands
to force it to run outside of the sandbox.
Claude Code includes an intentional escape hatch mechanism that allows commands to run outside the sandbox when necessary. When a command fails due to sandbox restrictions (such as network connectivity issues or incompatible tools), Claude is prompted to analyze the failure and may retry the command with the
dangerouslyDisableSandbox
parameter. Commands that use this parameter go through the normal Claude Code permissions flow requiring user permission to execute. This allows Claude Code to handle edge cases where certain tools or network operations cannot function within sandbox constraints.
You can disable this escape hatch by setting
"allowUnsandboxedCommands": false
in your
sandbox settings
. When disabled, the
dangerouslyDisableSandbox
parameter is completely ignored and all commands must run sandboxed or be explicitly listed in
excludedCommands
.
​
Security benefits
​
Protection against prompt injection
Even if an attacker successfully manipulates Claude Code’s behavior through prompt injection, the sandbox ensures your system remains secure:
Filesystem protection:
Cannot modify critical config files such as
~/.bashrc
Cannot modify system-level files in
/bin/
Cannot read files that are denied in your
Claude permission settings
Network protection:
Cannot exfiltrate data to attacker-controlled servers
Cannot download malicious scripts from unauthorized domains
Cannot make unexpected API calls to unapproved services
Cannot contact any domains not explicitly allowed
Monitoring and control:
All access attempts outside the sandbox are blocked at the OS level
You receive immediate notifications when boundaries are tested
You can choose to deny, allow once, or permanently update your configuration
​
Reduced attack surface
Sandboxing limits the potential damage from:
Malicious dependencies
: NPM packages or other dependencies with harmful code
Compromised scripts
: Build scripts or tools with security vulnerabilities
Social engineering
: Attacks that trick users into running dangerous commands
Prompt injection
: Attacks that trick Claude into running dangerous commands
​
Transparent operation
When Claude Code attempts to access network resources outside the sandbox:
The operation is blocked at the OS level
You receive an immediate notification
You can choose to:
Deny the request
Allow it once
Update your sandbox configuration to permanently allow it
​
Security Limitations
Network Sandboxing Limitations: The network filtering system operates by restricting the domains that processes are allowed to connect to. The built-in proxy does not terminate or perform TLS inspection on outbound traffic, so the contents of encrypted connections are not examined. You are responsible for ensuring that only trusted domains are allowed in your policy.
Allowing broad domains such as
github.com
can create paths for data exfiltration. Because the proxy makes its allow decision from the client-supplied hostname without inspecting TLS, code running inside the sandbox can potentially use
domain fronting
or similar techniques to reach hosts outside the allowlist. If your threat model requires stronger guarantees, configure a
custom proxy
that terminates TLS and inspects traffic, and install its CA certificate inside the sandbox. Stronger TLS-aware network isolation is an active area of development.
Privilege Escalation via Unix Sockets: The
allowUnixSockets
configuration can inadvertently grant access to powerful system services that could lead to sandbox bypasses. For example, if it is used to allow access to
/var/run/docker.sock
this would effectively grant access to the host system through exploiting the docker socket. Users are encouraged to carefully consider any unix sockets that they allow through the sandbox.
Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in
$PATH
, system configuration directories, or user shell configuration files (
.bashrc
,
.zshrc
) can lead to code execution in different security contexts when other users or system processes access these files.
Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an
enableWeakerNestedSandbox
mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used in cases where additional isolation is otherwise enforced.
​
How sandboxing relates to permissions
Sandboxing and
permissions
are complementary security layers that work together:
Permissions
control which tools Claude Code can use and are evaluated before any tool runs. They apply to all tools: Bash, Read, Edit, WebFetch, MCP, and others.
Sandboxing
provides OS-level enforcement that restricts what Bash commands can access at the filesystem and network level. It applies only to Bash commands and their child processes.
Filesystem and network restrictions are configured through both sandbox settings and permission rules:
Use
sandbox.filesystem.allowWrite
to grant subprocess write access to paths outside the working directory
Use
sandbox.filesystem.denyWrite
and
sandbox.filesystem.denyRead
to block subprocess access to specific paths
Use
sandbox.filesystem.allowRead
to re-allow reading specific paths within a
denyRead
region
Use
Read
and
Edit
deny rules to block access to specific files or directories
Use
WebFetch
allow/deny rules to control domain access
Use sandbox
allowedDomains
to control which domains Bash commands can reach
Use sandbox
deniedDomains
to block specific domains even when a broader
allowedDomains
wildcard would otherwise permit them
Paths from both
sandbox.filesystem
settings and permission rules are merged together into the final sandbox configuration.
This
repository
includes starter settings configurations for common deployment scenarios, including sandbox-specific examples. Use these as starting points and adjust them to fit your needs.
​
Advanced usage
​
Custom proxy configuration
For organizations requiring advanced network security, you can implement a custom proxy to:
Decrypt and inspect HTTPS traffic
Apply custom filtering rules
Log all network requests
Integrate with existing security infrastructure
{
"sandbox"
: {
"network"
: {
"httpProxyPort"
:
8080
,
"socksProxyPort"
:
8081
}
}
}
​
Integration with existing security tools
The sandboxed bash tool works alongside:
Permission rules
: Combine with
permission settings
for defense-in-depth
Development containers
: Use with
dev containers
for additional isolation
Enterprise policies
: Enforce sandbox configurations through
managed settings
​
Best practices
Start restrictive
: Begin with minimal permissions and expand as needed
Monitor logs
: Review sandbox violation attempts to understand Claude Code’s needs
Use environment-specific configs
: Different sandbox rules for development vs. production contexts
Combine with permissions
: Use sandboxing alongside IAM policies for comprehensive security
Test configurations
: Verify your sandbox settings don’t block legitimate workflows
​
Open source
The sandbox runtime is available as an open source npm package for use in your own agent projects. This enables the broader AI agent community to build safer, more secure autonomous systems. This can also be used to sandbox other programs you may wish to run. For example, to sandbox an MCP server you could run:
npx
@anthropic-ai/sandbox-runtime
<
command-to-sandbo
x
>
For implementation details and source code, visit the
GitHub repository
.
​
Limitations
Performance overhead
: Minimal, but some filesystem operations may be slightly slower
Compatibility
: Some tools that require specific system access patterns may need configuration adjustments, or may even need to be run outside of the sandbox
Platform support
: Supports macOS, Linux, and WSL2. WSL1 is not supported. Native Windows support is planned.
​
What sandboxing does not cover
The sandbox isolates Bash subprocesses. Other tools operate under different boundaries:
Built-in file tools
: Read, Edit, and Write use the permission system directly rather than running through the sandbox. See
permissions
.
Computer use
: when Claude opens apps and controls your screen, it runs on your actual desktop rather than in an isolated environment. Per-app permission prompts gate each application. See
computer use in the CLI
or
computer use in Desktop
.
​
See also
Security
- Comprehensive security features and best practices
Permissions
- Permission configuration and access control
Settings
- Complete configuration reference
CLI reference
- Command-line options
Was this page helpful?
Yes
No
Permissions
Model configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/sandboxing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Sandboxing
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Sandboxing
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
Claude Code features native sandboxing to provide a more secure environment for agent execution while reducing the need for constant permission prompts. Instead of asking permission for each bash command, sandboxing creates defined boundaries upfront where Claude Code can work more freely with reduced risk.
The sandboxed bash tool uses OS-level primitives to enforce both filesystem and network isolation.
​
Why sandboxing matters
Traditional permission-based security requires constant user approval for bash commands. While this provides control, it can lead to:
Approval fatigue
: Repeatedly clicking “approve” can cause users to pay less attention to what they’re approving
Reduced productivity
: Constant interruptions slow down development workflows
Limited autonomy
: Claude Code cannot work as efficiently when waiting for approvals
Sandboxing addresses these challenges by:
Defining clear boundaries
: Specify exactly which directories and network hosts Claude Code can access
Reducing permission prompts
: Safe commands within the sandbox don’t require approval
Maintaining security
: Attempts to access resources outside the sandbox trigger immediate notifications
Enabling autonomy
: Claude Code can run more independently within defined limits
Effective sandboxing requires
both
filesystem and network isolation. Without network isolation, a compromised agent could exfiltrate sensitive files like SSH keys. Without filesystem isolation, a compromised agent could backdoor system resources to gain network access. When configuring sandboxing it is important to ensure that your configured settings do not create bypasses in these systems.
​
How it works
​
Filesystem isolation
The sandboxed bash tool restricts file system access to specific directories:
Default writes behavior
: Read and write access to the current working directory and its subdirectories
Default read behavior
: Read access to the entire computer, except certain denied directories
Blocked access
: Cannot modify files outside the current working directory without explicit permission
Configurable
: Define custom allowed and denied paths through settings
You can grant write access to additional paths using
sandbox.filesystem.allowWrite
in your settings. These restrictions are enforced at the OS level (Seatbelt on macOS, bubblewrap on Linux), so they apply to all subprocess commands, including tools like
kubectl
,
terraform
, and
npm
, not just Claude’s file tools.
​
Network isolation
Network access is controlled through a proxy server running outside the sandbox:
Domain restrictions
: Only approved domains can be accessed
User confirmation
: New domain requests trigger permission prompts (unless
allowManagedDomainsOnly
is enabled, which blocks non-allowed domains automatically)
Custom proxy support
: Advanced users can implement custom rules on outgoing traffic
Comprehensive coverage
: Restrictions apply to all scripts, programs, and subprocesses spawned by commands
The built-in proxy enforces the allowlist based on the requested hostname and does not terminate or inspect TLS traffic. See
Security limitations
for the implications of this design, and
Custom proxy configuration
if your threat model requires TLS inspection.
​
OS-level enforcement
The sandboxed bash tool leverages operating system security primitives:
macOS
: Uses Seatbelt for sandbox enforcement
Linux
: Uses
bubblewrap
for isolation
WSL2
: Uses bubblewrap, same as Linux
WSL1 is not supported because bubblewrap requires kernel features only available in WSL2.
These OS-level restrictions ensure that all child processes spawned by Claude Code’s commands inherit the same security boundaries.
​
Getting started
​
Prerequisites
On
macOS
, sandboxing works out of the box using the built-in Seatbelt framework.
On
Linux and WSL2
, install the required packages first:
Ubuntu/Debian
Fedora
sudo
apt-get
install
bubblewrap
socat
sudo
dnf
install
bubblewrap
socat
On Ubuntu 24.04 and later, the default AppArmor policy prevents bubblewrap from creating the user namespaces it needs for isolation. Add an AppArmor profile that grants
bwrap
this capability:
sudo
tee
/etc/apparmor.d/bwrap
>
/dev/null
<<
'EOF'
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}
EOF
The profile applies only to
bwrap
itself, not to the commands it runs inside the sandbox. Reload AppArmor to apply it:
sudo
systemctl
reload
apparmor
WSL1 does not support sandboxing because it lacks the required Linux namespace primitives. If you see
Sandboxing requires WSL2
, upgrade your distribution to WSL2 or run Claude Code without sandboxing.
On WSL2, sandboxed commands cannot launch Windows binaries such as
cmd.exe
,
powershell.exe
, or anything under
/mnt/c/
. WSL hands these off to the Windows host over a Unix socket, which the sandbox blocks. If a command needs to invoke a Windows binary, add it to
excludedCommands
so it runs outside the sandbox.
​
Enable sandboxing
You can enable sandboxing by running the
/sandbox
command:
/sandbox
This opens a menu where you can choose between sandbox modes. If required dependencies are missing (such as
bubblewrap
or
socat
on Linux), the menu displays installation instructions for your platform.
By default, if the sandbox cannot start (missing dependencies or unsupported platform), Claude Code shows a warning and runs commands without sandboxing. To make this a hard failure instead, set
sandbox.failIfUnavailable
to
true
. This is intended for managed deployments that require sandboxing as a security gate.
​
Sandbox modes
Claude Code offers two sandbox modes:
Auto-allow mode
: Bash commands will attempt to run inside the sandbox and are automatically allowed without requiring permission. Commands that cannot be sandboxed (such as those needing network access to non-allowed hosts) fall back to the regular permission flow. Explicit deny rules are always respected, and
rm
or
rmdir
commands that target
/
, your home directory, or other critical system paths still trigger a permission prompt. Ask rules apply only to commands that fall back to the regular permission flow.
Regular permissions mode
: All bash commands go through the standard permission flow, even when sandboxed. This provides more control but requires more approvals.
In both modes, the sandbox enforces the same filesystem and network restrictions. The difference is only in whether sandboxed commands are auto-approved or require explicit permission.
Auto-allow mode works independently of your permission mode setting. Even if you’re not in “accept edits” mode, sandboxed bash commands will run automatically when auto-allow is enabled. This means bash commands that modify files within the sandbox boundaries will execute without prompting, even when file edit tools would normally require approval.
​
Configure sandboxing
Customize sandbox behavior through your
settings.json
file. See
Settings
for complete configuration reference.
​
Granting subprocess write access to specific paths
By default, sandboxed commands can only write to the current working directory. If subprocess commands like
kubectl
,
terraform
, or
npm
need to write outside the project directory, use
sandbox.filesystem.allowWrite
to grant access to specific paths:
{
"sandbox"
: {
"enabled"
:
true
,
"filesystem"
: {
"allowWrite"
: [
"~/.kube"
,
"/tmp/build"
]
}
}
}
These paths are enforced at the OS level, so all commands running inside the sandbox, including their child processes, respect them. This is the recommended approach when a tool needs write access to a specific location, rather than excluding the tool from the sandbox entirely with
excludedCommands
.
When
allowWrite
(or
denyWrite
/
denyRead
/
allowRead
) is defined in multiple
settings scopes
, the arrays are
merged
, meaning paths from every scope are combined, not replaced. For example, if managed settings allow writes to
/opt/company-tools
and a user adds
~/.kube
in their personal settings, both paths are included in the final sandbox configuration. This means users and projects can extend the list without duplicating or overriding paths set by higher-priority scopes.
Path prefixes control how paths are resolved:
Prefix
Meaning
Example
/
Absolute path from filesystem root
/tmp/build
stays
/tmp/build
~/
Relative to home directory
~/.kube
becomes
$HOME/.kube
./
or no prefix
Relative to the project root for project settings, or to
~/.claude
for user settings
./output
in
.claude/settings.json
resolves to
<project-root>/output
The older
//path
prefix for absolute paths still works. If you previously used single-slash
/path
expecting project-relative resolution, switch to
./path
. This syntax differs from
Read and Edit permission rules
, which use
//path
for absolute and
/path
for project-relative. Sandbox filesystem paths use standard conventions:
/tmp/build
is an absolute path.
You can also deny write or read access using
sandbox.filesystem.denyWrite
and
sandbox.filesystem.denyRead
. These are merged with any paths from
Edit(...)
and
Read(...)
permission rules. To re-allow reading specific paths within a denied region, use
sandbox.filesystem.allowRead
, which takes precedence over
denyRead
. When
allowManagedReadPathsOnly
is enabled in managed settings, only managed
allowRead
entries are respected; user, project, and local
allowRead
entries are ignored.
denyRead
still merges from all sources.
For example, to block reading from the entire home directory while still allowing reads from the current project, add this to your project’s
.claude/settings.json
:
{
"sandbox"
: {
"enabled"
:
true
,
"filesystem"
: {
"denyRead"
: [
"~/"
],
"allowRead"
: [
"."
]
}
}
}
The
.
in
allowRead
resolves to the project root because this configuration lives in project settings. If you placed the same configuration in
~/.claude/settings.json
,
.
would resolve to
~/.claude
instead, and project files would remain blocked by the
denyRead
rule.
Not all commands are compatible with sandboxing out of the box. Some notes that may help you make the most out of the sandbox:
Many CLI tools require accessing certain hosts. As you use these tools, they will request permission to access certain hosts. Granting permission will allow them to access these hosts now and in the future, enabling them to safely execute inside the sandbox.
watchman
is incompatible with running in the sandbox. If you’re running
jest
, consider using
jest --no-watchman
docker
is incompatible with running in the sandbox. Consider specifying
docker *
in
excludedCommands
to force it to run outside of the sandbox.
Claude Code includes an intentional escape hatch mechanism that allows commands to run outside the sandbox when necessary. When a command fails due to sandbox restrictions (such as network connectivity issues or incompatible tools), Claude is prompted to analyze the failure and may retry the command with the
dangerouslyDisableSandbox
parameter. Commands that use this parameter go through the normal Claude Code permissions flow requiring user permission to execute. This allows Claude Code to handle edge cases where certain tools or network operations cannot function within sandbox constraints.
You can disable this escape hatch by setting
"allowUnsandboxedCommands": false
in your
sandbox settings
. When disabled, the
dangerouslyDisableSandbox
parameter is completely ignored and all commands must run sandboxed or be explicitly listed in
excludedCommands
.
​
Security benefits
​
Protection against prompt injection
Even if an attacker successfully manipulates Claude Code’s behavior through prompt injection, the sandbox ensures your system remains secure:
Filesystem protection:
Cannot modify critical config files such as
~/.bashrc
Cannot modify system-level files in
/bin/
Cannot read files that are denied in your
Claude permission settings
Network protection:
Cannot exfiltrate data to attacker-controlled servers
Cannot download malicious scripts from unauthorized domains
Cannot make unexpected API calls to unapproved services
Cannot contact any domains not explicitly allowed
Monitoring and control:
All access attempts outside the sandbox are blocked at the OS level
You receive immediate notifications when boundaries are tested
You can choose to deny, allow once, or permanently update your configuration
​
Reduced attack surface
Sandboxing limits the potential damage from:
Malicious dependencies
: NPM packages or other dependencies with harmful code
Compromised scripts
: Build scripts or tools with security vulnerabilities
Social engineering
: Attacks that trick users into running dangerous commands
Prompt injection
: Attacks that trick Claude into running dangerous commands
​
Transparent operation
When Claude Code attempts to access network resources outside the sandbox:
The operation is blocked at the OS level
You receive an immediate notification
You can choose to:
Deny the request
Allow it once
Update your sandbox configuration to permanently allow it
​
Security Limitations
Network Sandboxing Limitations: The network filtering system operates by restricting the domains that processes are allowed to connect to. The built-in proxy does not terminate or perform TLS inspection on outbound traffic, so the contents of encrypted connections are not examined. You are responsible for ensuring that only trusted domains are allowed in your policy.
Allowing broad domains such as
github.com
can create paths for data exfiltration. Because the proxy makes its allow decision from the client-supplied hostname without inspecting TLS, code running inside the sandbox can potentially use
domain fronting
or similar techniques to reach hosts outside the allowlist. If your threat model requires stronger guarantees, configure a
custom proxy
that terminates TLS and inspects traffic, and install its CA certificate inside the sandbox. Stronger TLS-aware network isolation is an active area of development.
Privilege Escalation via Unix Sockets: The
allowUnixSockets
configuration can inadvertently grant access to powerful system services that could lead to sandbox bypasses. For example, if it is used to allow access to
/var/run/docker.sock
this would effectively grant access to the host system through exploiting the docker socket. Users are encouraged to carefully consider any unix sockets that they allow through the sandbox.
Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in
$PATH
, system configuration directories, or user shell configuration files (
.bashrc
,
.zshrc
) can lead to code execution in different security contexts when other users or system processes access these files.
Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an
enableWeakerNestedSandbox
mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used in cases where additional isolation is otherwise enforced.
​
How sandboxing relates to permissions
Sandboxing and
permissions
are complementary security layers that work together:
Permissions
control which tools Claude Code can use and are evaluated before any tool runs. They apply to all tools: Bash, Read, Edit, WebFetch, MCP, and others.
Sandboxing
provides OS-level enforcement that restricts what Bash commands can access at the filesystem and network level. It applies only to Bash commands and their child processes.
Filesystem and network restrictions are configured through both sandbox settings and permission rules:
Use
sandbox.filesystem.allowWrite
to grant subprocess write access to paths outside the working directory
Use
sandbox.filesystem.denyWrite
and
sandbox.filesystem.denyRead
to block subprocess access to specific paths
Use
sandbox.filesystem.allowRead
to re-allow reading specific paths within a
denyRead
region
Use
Read
and
Edit
deny rules to block access to specific files or directories
Use
WebFetch
allow/deny rules to control domain access
Use sandbox
allowedDomains
to control which domains Bash commands can reach
Use sandbox
deniedDomains
to block specific domains even when a broader
allowedDomains
wildcard would otherwise permit them
Paths from both
sandbox.filesystem
settings and permission rules are merged together into the final sandbox configuration.
This
repository
includes starter settings configurations for common deployment scenarios, including sandbox-specific examples. Use these as starting points and adjust them to fit your needs.
​
Advanced usage
​
Custom proxy configuration
For organizations requiring advanced network security, you can implement a custom proxy to:
Decrypt and inspect HTTPS traffic
Apply custom filtering rules
Log all network requests
Integrate with existing security infrastructure
{
"sandbox"
: {
"network"
: {
"httpProxyPort"
:
8080
,
"socksProxyPort"
:
8081
}
}
}
​
Integration with existing security tools
The sandboxed bash tool works alongside:
Permission rules
: Combine with
permission settings
for defense-in-depth
Development containers
: Use with
dev containers
for additional isolation
Enterprise policies
: Enforce sandbox configurations through
managed settings
​
Best practices
Start restrictive
: Begin with minimal permissions and expand as needed
Monitor logs
: Review sandbox violation attempts to understand Claude Code’s needs
Use environment-specific configs
: Different sandbox rules for development vs. production contexts
Combine with permissions
: Use sandboxing alongside IAM policies for comprehensive security
Test configurations
: Verify your sandbox settings don’t block legitimate workflows
​
Open source
The sandbox runtime is available as an open source npm package for use in your own agent projects. This enables the broader AI agent community to build safer, more secure autonomous systems. This can also be used to sandbox other programs you may wish to run. For example, to sandbox an MCP server you could run:
npx
@anthropic-ai/sandbox-runtime
<
command-to-sandbo
x
>
For implementation details and source code, visit the
GitHub repository
.
​
Limitations
Performance overhead
: Minimal, but some filesystem operations may be slightly slower
Compatibility
: Some tools that require specific system access patterns may need configuration adjustments, or may even need to be run outside of the sandbox
Platform support
: Supports macOS, Linux, and WSL2. WSL1 is not supported. Native Windows support is planned.
​
What sandboxing does not cover
The sandbox isolates Bash subprocesses. Other tools operate under different boundaries:
Built-in file tools
: Read, Edit, and Write use the permission system directly rather than running through the sandbox. See
permissions
.
Computer use
: when Claude opens apps and controls your screen, it runs on your actual desktop rather than in an isolated environment. Per-app permission prompts gate each application. See
computer use in the CLI
or
computer use in Desktop
.
​
See also
Security
- Comprehensive security features and best practices
Permissions
- Permission configuration and access control
Settings
- Complete configuration reference
CLI reference
- Command-line options
Was this page helpful?
Yes
No
Permissions
Model configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/sandboxing" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>How Claude Code works</title>
  <link>https://code.claude.com/docs/en/how-claude-code-works</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/how-claude-code-works</guid>
  <pubDate>Wed, 14 Aug 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How Claude Code works
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How Claude Code works
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an agentic assistant that runs in your terminal. While it excels at coding, it can help with anything you can do from the command line: writing docs, running builds, searching files, researching topics, and more.
This guide covers the core architecture, built-in capabilities, and
tips for working effectively
. For step-by-step walkthroughs, see
Common workflows
. For extensibility features like skills, MCP, and hooks, see
Extend Claude Code
.
​
The agentic loop
When you give Claude a task, it works through three phases:
gather context
,
take action
, and
verify results
. These phases blend together. Claude uses tools throughout, whether searching files to understand your code, editing to make changes, or running tests to check its work.
The loop adapts to what you ask. A question about your codebase might only need context gathering. A bug fix cycles through all three phases repeatedly. A refactor might involve extensive verification. Claude decides what each step requires based on what it learned from the previous step, chaining dozens of actions together and course-correcting along the way.
You’re part of this loop too. You can interrupt at any point to steer Claude in a different direction, provide additional context, or ask it to try a different approach. Claude works autonomously but stays responsive to your input.
The agentic loop is powered by two components:
models
that reason and
tools
that act. Claude Code serves as the
agentic harness
around Claude: it provides the tools, context management, and execution environment that turn a language model into a capable coding agent.
​
Models
Claude Code uses Claude models to understand your code and reason about tasks. Claude can read code in any language, understand how components connect, and figure out what needs to change to accomplish your goal. For complex tasks, it breaks work into steps, executes them, and adjusts based on what it learns.
Multiple models
are available with different tradeoffs. Sonnet handles most coding tasks well. Opus provides stronger reasoning for complex architectural decisions. Switch with
/model
during a session or start with
claude --model <name>
.
When this guide says “Claude chooses” or “Claude decides,” it’s the model doing the reasoning.
​
Tools
Tools are what make Claude Code agentic. Without tools, Claude can only respond with text. With tools, Claude can act: read your code, edit files, run commands, search the web, and interact with external services. Each tool use returns information that feeds back into the loop, informing Claude’s next decision.
The built-in tools generally fall into five categories, each representing a different kind of agency.
Category
What Claude can do
File operations
Read files, edit code, create new files, rename and reorganize
Search
Find files by pattern, search content with regex, explore codebases
Execution
Run shell commands, start servers, run tests, use git
Web
Search the web, fetch documentation, look up error messages
Code intelligence
See type errors and warnings after edits, jump to definitions, find references (requires
code intelligence plugins
)
These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See
Tools available to Claude
for the complete list.
Claude chooses which tools to use based on your prompt and what it learns along the way. When you say “fix the failing tests,” Claude might:
Run the test suite to see what’s failing
Read the error output
Search for the relevant source files
Read those files to understand the code
Edit the files to fix the issue
Run the tests again to verify
Each tool use gives Claude new information that informs the next step. This is the agentic loop in action.
Extending the base capabilities:
The built-in tools are the foundation. You can extend what Claude knows with
skills
, connect to external services with
MCP
, automate workflows with
hooks
, and offload tasks to
subagents
. These extensions form a layer on top of the core agentic loop. See
Extend Claude Code
for guidance on choosing the right extension for your needs.
​
What Claude can access
This guide focuses on the terminal. Claude Code also runs in
VS Code
,
JetBrains IDEs
, and other environments.
When you run
claude
in a directory, Claude Code gains access to:
Your project.
Files in your directory and subdirectories, plus files elsewhere with your permission.
Your terminal.
Any command you could run: build tools, git, package managers, system utilities, scripts. If you can do it from the command line, Claude can too.
Your git state.
Current branch, uncommitted changes, and recent commit history.
Your
CLAUDE.md
.
A markdown file where you store project-specific instructions, conventions, and context that Claude should know every session.
Auto memory
.
Learnings Claude saves automatically as you work, like project patterns and your preferences. The first 200 lines or 25KB of MEMORY.md, whichever comes first, load at the start of each session.
Extensions you configure.
MCP servers
for external services,
skills
for workflows,
subagents
for delegated work, and
Claude in Chrome
for browser interaction.
Because Claude sees your whole project, it can work across it. When you ask Claude to “fix the authentication bug,” it searches for relevant files, reads multiple files to understand context, makes coordinated edits across them, runs tests to verify the fix, and commits the changes if you ask. This is different from inline code assistants that only see the current file.
​
Environments and interfaces
The agentic loop, tools, and capabilities described above are the same everywhere you use Claude Code. What changes is where the code executes and how you interact with it.
​
Execution environments
Claude Code runs in three environments, each with different tradeoffs for where your code executes.
Environment
Where code runs
Use case
Local
Your machine
Default. Full access to your files, tools, and environment
Cloud
Anthropic-managed VMs
Offload tasks, work on repos you don’t have locally
Remote Control
Your machine, controlled from a browser
Use the web UI while keeping everything local
​
Interfaces
You can access Claude Code through the terminal, the
desktop app
,
IDE extensions
,
claude.ai/code
,
Remote Control
,
Slack
, and
CI/CD pipelines
. The interface determines how you see and interact with Claude, but the underlying agentic loop is identical. See
Use Claude Code everywhere
for the full list.
​
Work with sessions
Claude Code saves your conversation locally as you work. Each message, tool use, and result is written to a plaintext JSONL file under
~/.claude/projects/
, which enables
rewinding
,
resuming, and forking
sessions. Before Claude makes code changes, it also snapshots the affected files so you can revert if needed. For paths, retention, and how to clear this data, see
application data in
~/.claude
.
Sessions are independent.
Each new session starts with a fresh context window, without the conversation history from previous sessions. Claude can persist learnings across sessions using
auto memory
, and you can add your own persistent instructions in
CLAUDE.md
.
​
Work across branches
Each Claude Code conversation is a session tied to your current directory. The
/resume
picker shows sessions from the current worktree by default, with keyboard shortcuts to widen the list to other worktrees or projects. See
Manage sessions
for the full list of picker shortcuts and how name resolution works.
Claude sees your current branch’s files. When you switch branches, Claude sees the new branch’s files, but your conversation history stays the same. Claude remembers what you discussed even after switching.
Since sessions are tied to directories, you can run parallel Claude sessions by using
git worktrees
, which create separate directories for individual branches.
​
Resume or fork sessions
Resuming a session with
claude --continue
or
claude --resume
reopens it under the same session ID and appends new messages to the existing conversation. Forking with
--fork-session
or
/branch
copies the history into a new session ID, leaving the original unchanged.
For the resume flags, the
/resume
picker, naming, and what happens when the same session is open in two terminals, see
Manage sessions
.
​
The context window
Claude’s context window holds your conversation history, file contents, command outputs,
CLAUDE.md
,
auto memory
, loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run
/context
to see what’s using space.
For an interactive walkthrough of what loads and when, see
Explore the context window
.
​
When context fills up
Claude Code manages context automatically as you approach the limit. It clears older tool outputs first, then summarizes the conversation if needed. Your requests and key code snippets are preserved; detailed instructions from early in the conversation may be lost. Put persistent rules in CLAUDE.md rather than relying on conversation history.
To control what’s preserved during compaction, add a “Compact Instructions” section to CLAUDE.md or run
/compact
with a focus (like
/compact focus on the API changes
).
If a single file or tool output is so large that context refills immediately after each summary, Claude Code stops auto-compacting after a few attempts and shows an error instead of looping. See
Auto-compaction stops with a thrashing error
for recovery steps.
Run
/context
to see what’s using space. MCP tool definitions are deferred by default and loaded on demand via
tool search
, so only tool names consume context until Claude uses a specific tool. Run
/mcp
to check per-server costs.
​
Manage context with skills and subagents
Beyond compaction, you can use other features to control what loads into context.
Skills
load on demand. Claude sees skill descriptions at session start, but the full content only loads when a skill is used. For skills you invoke manually, set
disable-model-invocation: true
to keep descriptions out of context until you need them. For skills you didn’t write, use
skillOverrides
to do the same from settings.
Subagents
get their own fresh context, completely separate from your main conversation. Their work doesn’t bloat your context. When done, they return a summary. This isolation is why subagents help with long sessions.
See
context costs
for what each feature costs, and
reduce token usage
for tips on managing context.
​
Stay safe with checkpoints and permissions
Claude has two safety mechanisms: checkpoints let you undo file changes, and permissions control what Claude can do without asking.
​
Undo changes with checkpoints
Every file edit is reversible.
Before Claude edits any file, it snapshots the current contents. If something goes wrong, press
Esc
twice to rewind to a previous state, or ask Claude to undo.
Checkpoints are local to your session, separate from git. They only cover file changes. Actions that affect remote systems (databases, APIs, deployments) can’t be checkpointed, which is why Claude asks before running commands with external side effects.
​
Control what Claude can do
Press
Shift+Tab
to cycle through permission modes:
Default
: Claude asks before file edits and shell commands
Auto-accept edits
: Claude edits files and runs common filesystem commands like
mkdir
and
mv
without asking, still asks for other commands
Plan mode
: Claude uses read-only tools only, creating a plan you can approve before execution
Auto mode
: Claude evaluates all actions with background safety checks. Currently a research preview
You can also allow specific commands in
.claude/settings.json
so Claude doesn’t ask each time. This is useful for trusted commands like
npm test
or
git status
. Settings can be scoped from organization-wide policies down to personal preferences. See
Permissions
for details.
​
Work effectively with Claude Code
These tips help you get better results from Claude Code.
​
Ask Claude Code for help
Claude Code can teach you how to use it. Ask questions like “how do I set up hooks?” or “what’s the best way to structure my CLAUDE.md?” and Claude will explain.
Built-in commands also guide you through setup:
/init
walks you through creating a CLAUDE.md for your project
/agents
helps you configure custom subagents
/doctor
diagnoses common issues with your installation
​
It’s a conversation
Claude Code is conversational. You don’t need perfect prompts. Start with what you want, then refine:
Fix the login bug
[Claude investigates, tries something]
That's not quite right. The issue is in the session handling.
[Claude adjusts approach]
When the first attempt isn’t right, you don’t start over. You iterate.
​
Interrupt and steer
You can interrupt Claude at any point. If it’s going down the wrong path, just type your correction and press Enter. Claude will stop what it’s doing and adjust its approach based on your input. You don’t have to wait for it to finish or start over.
​
Be specific upfront
The more precise your initial prompt, the fewer corrections you’ll need. Reference specific files, mention constraints, and point to example patterns.
The checkout flow is broken for users with expired cards.
Check src/payments/ for the issue, especially token refresh.
Write a failing test first, then fix it.
Vague prompts work, but you’ll spend more time steering. Specific prompts like the one above often succeed on the first attempt.
​
Give Claude something to verify against
Claude performs better when it can check its own work. Include test cases, paste screenshots of expected UI, or define the output you want.
Implement validateEmail. Test cases: 'user@example.com' → true,
'invalid' → false, 'user@.com' → false. Run the tests after.
For visual work, paste a screenshot of the design and ask Claude to compare its implementation against it.
​
Explore before implementing
For complex problems, separate research from coding. Use plan mode (
Shift+Tab
twice) to analyze the codebase first:
Read src/auth/ and understand how we handle sessions.
Then create a plan for adding OAuth support.
Review the plan, refine it through conversation, then let Claude implement. This two-phase approach produces better results than jumping straight to code.
​
Delegate, don’t dictate
Think of delegating to a capable colleague. Give context and direction, then trust Claude to figure out the details:
The checkout flow is broken for users with expired cards.
The relevant code is in src/payments/. Can you investigate and fix it?
You don’t need to specify which files to read or what commands to run. Claude figures that out.
​
What’s next
Extend with features
Add Skills, MCP connections, and custom commands
Common workflows
Step-by-step guides for typical tasks
Was this page helpful?
Yes
No
Changelog
Extend Claude Code
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/how-claude-code-works" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How Claude Code works
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How Claude Code works
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an agentic assistant that runs in your terminal. While it excels at coding, it can help with anything you can do from the command line: writing docs, running builds, searching files, researching topics, and more.
This guide covers the core architecture, built-in capabilities, and
tips for working effectively
. For step-by-step walkthroughs, see
Common workflows
. For extensibility features like skills, MCP, and hooks, see
Extend Claude Code
.
​
The agentic loop
When you give Claude a task, it works through three phases:
gather context
,
take action
, and
verify results
. These phases blend together. Claude uses tools throughout, whether searching files to understand your code, editing to make changes, or running tests to check its work.
The loop adapts to what you ask. A question about your codebase might only need context gathering. A bug fix cycles through all three phases repeatedly. A refactor might involve extensive verification. Claude decides what each step requires based on what it learned from the previous step, chaining dozens of actions together and course-correcting along the way.
You’re part of this loop too. You can interrupt at any point to steer Claude in a different direction, provide additional context, or ask it to try a different approach. Claude works autonomously but stays responsive to your input.
The agentic loop is powered by two components:
models
that reason and
tools
that act. Claude Code serves as the
agentic harness
around Claude: it provides the tools, context management, and execution environment that turn a language model into a capable coding agent.
​
Models
Claude Code uses Claude models to understand your code and reason about tasks. Claude can read code in any language, understand how components connect, and figure out what needs to change to accomplish your goal. For complex tasks, it breaks work into steps, executes them, and adjusts based on what it learns.
Multiple models
are available with different tradeoffs. Sonnet handles most coding tasks well. Opus provides stronger reasoning for complex architectural decisions. Switch with
/model
during a session or start with
claude --model <name>
.
When this guide says “Claude chooses” or “Claude decides,” it’s the model doing the reasoning.
​
Tools
Tools are what make Claude Code agentic. Without tools, Claude can only respond with text. With tools, Claude can act: read your code, edit files, run commands, search the web, and interact with external services. Each tool use returns information that feeds back into the loop, informing Claude’s next decision.
The built-in tools generally fall into five categories, each representing a different kind of agency.
Category
What Claude can do
File operations
Read files, edit code, create new files, rename and reorganize
Search
Find files by pattern, search content with regex, explore codebases
Execution
Run shell commands, start servers, run tests, use git
Web
Search the web, fetch documentation, look up error messages
Code intelligence
See type errors and warnings after edits, jump to definitions, find references (requires
code intelligence plugins
)
These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See
Tools available to Claude
for the complete list.
Claude chooses which tools to use based on your prompt and what it learns along the way. When you say “fix the failing tests,” Claude might:
Run the test suite to see what’s failing
Read the error output
Search for the relevant source files
Read those files to understand the code
Edit the files to fix the issue
Run the tests again to verify
Each tool use gives Claude new information that informs the next step. This is the agentic loop in action.
Extending the base capabilities:
The built-in tools are the foundation. You can extend what Claude knows with
skills
, connect to external services with
MCP
, automate workflows with
hooks
, and offload tasks to
subagents
. These extensions form a layer on top of the core agentic loop. See
Extend Claude Code
for guidance on choosing the right extension for your needs.
​
What Claude can access
This guide focuses on the terminal. Claude Code also runs in
VS Code
,
JetBrains IDEs
, and other environments.
When you run
claude
in a directory, Claude Code gains access to:
Your project.
Files in your directory and subdirectories, plus files elsewhere with your permission.
Your terminal.
Any command you could run: build tools, git, package managers, system utilities, scripts. If you can do it from the command line, Claude can too.
Your git state.
Current branch, uncommitted changes, and recent commit history.
Your
CLAUDE.md
.
A markdown file where you store project-specific instructions, conventions, and context that Claude should know every session.
Auto memory
.
Learnings Claude saves automatically as you work, like project patterns and your preferences. The first 200 lines or 25KB of MEMORY.md, whichever comes first, load at the start of each session.
Extensions you configure.
MCP servers
for external services,
skills
for workflows,
subagents
for delegated work, and
Claude in Chrome
for browser interaction.
Because Claude sees your whole project, it can work across it. When you ask Claude to “fix the authentication bug,” it searches for relevant files, reads multiple files to understand context, makes coordinated edits across them, runs tests to verify the fix, and commits the changes if you ask. This is different from inline code assistants that only see the current file.
​
Environments and interfaces
The agentic loop, tools, and capabilities described above are the same everywhere you use Claude Code. What changes is where the code executes and how you interact with it.
​
Execution environments
Claude Code runs in three environments, each with different tradeoffs for where your code executes.
Environment
Where code runs
Use case
Local
Your machine
Default. Full access to your files, tools, and environment
Cloud
Anthropic-managed VMs
Offload tasks, work on repos you don’t have locally
Remote Control
Your machine, controlled from a browser
Use the web UI while keeping everything local
​
Interfaces
You can access Claude Code through the terminal, the
desktop app
,
IDE extensions
,
claude.ai/code
,
Remote Control
,
Slack
, and
CI/CD pipelines
. The interface determines how you see and interact with Claude, but the underlying agentic loop is identical. See
Use Claude Code everywhere
for the full list.
​
Work with sessions
Claude Code saves your conversation locally as you work. Each message, tool use, and result is written to a plaintext JSONL file under
~/.claude/projects/
, which enables
rewinding
,
resuming, and forking
sessions. Before Claude makes code changes, it also snapshots the affected files so you can revert if needed. For paths, retention, and how to clear this data, see
application data in
~/.claude
.
Sessions are independent.
Each new session starts with a fresh context window, without the conversation history from previous sessions. Claude can persist learnings across sessions using
auto memory
, and you can add your own persistent instructions in
CLAUDE.md
.
​
Work across branches
Each Claude Code conversation is a session tied to your current directory. The
/resume
picker shows sessions from the current worktree by default, with keyboard shortcuts to widen the list to other worktrees or projects. See
Manage sessions
for the full list of picker shortcuts and how name resolution works.
Claude sees your current branch’s files. When you switch branches, Claude sees the new branch’s files, but your conversation history stays the same. Claude remembers what you discussed even after switching.
Since sessions are tied to directories, you can run parallel Claude sessions by using
git worktrees
, which create separate directories for individual branches.
​
Resume or fork sessions
Resuming a session with
claude --continue
or
claude --resume
reopens it under the same session ID and appends new messages to the existing conversation. Forking with
--fork-session
or
/branch
copies the history into a new session ID, leaving the original unchanged.
For the resume flags, the
/resume
picker, naming, and what happens when the same session is open in two terminals, see
Manage sessions
.
​
The context window
Claude’s context window holds your conversation history, file contents, command outputs,
CLAUDE.md
,
auto memory
, loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run
/context
to see what’s using space.
For an interactive walkthrough of what loads and when, see
Explore the context window
.
​
When context fills up
Claude Code manages context automatically as you approach the limit. It clears older tool outputs first, then summarizes the conversation if needed. Your requests and key code snippets are preserved; detailed instructions from early in the conversation may be lost. Put persistent rules in CLAUDE.md rather than relying on conversation history.
To control what’s preserved during compaction, add a “Compact Instructions” section to CLAUDE.md or run
/compact
with a focus (like
/compact focus on the API changes
).
If a single file or tool output is so large that context refills immediately after each summary, Claude Code stops auto-compacting after a few attempts and shows an error instead of looping. See
Auto-compaction stops with a thrashing error
for recovery steps.
Run
/context
to see what’s using space. MCP tool definitions are deferred by default and loaded on demand via
tool search
, so only tool names consume context until Claude uses a specific tool. Run
/mcp
to check per-server costs.
​
Manage context with skills and subagents
Beyond compaction, you can use other features to control what loads into context.
Skills
load on demand. Claude sees skill descriptions at session start, but the full content only loads when a skill is used. For skills you invoke manually, set
disable-model-invocation: true
to keep descriptions out of context until you need them. For skills you didn’t write, use
skillOverrides
to do the same from settings.
Subagents
get their own fresh context, completely separate from your main conversation. Their work doesn’t bloat your context. When done, they return a summary. This isolation is why subagents help with long sessions.
See
context costs
for what each feature costs, and
reduce token usage
for tips on managing context.
​
Stay safe with checkpoints and permissions
Claude has two safety mechanisms: checkpoints let you undo file changes, and permissions control what Claude can do without asking.
​
Undo changes with checkpoints
Every file edit is reversible.
Before Claude edits any file, it snapshots the current contents. If something goes wrong, press
Esc
twice to rewind to a previous state, or ask Claude to undo.
Checkpoints are local to your session, separate from git. They only cover file changes. Actions that affect remote systems (databases, APIs, deployments) can’t be checkpointed, which is why Claude asks before running commands with external side effects.
​
Control what Claude can do
Press
Shift+Tab
to cycle through permission modes:
Default
: Claude asks before file edits and shell commands
Auto-accept edits
: Claude edits files and runs common filesystem commands like
mkdir
and
mv
without asking, still asks for other commands
Plan mode
: Claude uses read-only tools only, creating a plan you can approve before execution
Auto mode
: Claude evaluates all actions with background safety checks. Currently a research preview
You can also allow specific commands in
.claude/settings.json
so Claude doesn’t ask each time. This is useful for trusted commands like
npm test
or
git status
. Settings can be scoped from organization-wide policies down to personal preferences. See
Permissions
for details.
​
Work effectively with Claude Code
These tips help you get better results from Claude Code.
​
Ask Claude Code for help
Claude Code can teach you how to use it. Ask questions like “how do I set up hooks?” or “what’s the best way to structure my CLAUDE.md?” and Claude will explain.
Built-in commands also guide you through setup:
/init
walks you through creating a CLAUDE.md for your project
/agents
helps you configure custom subagents
/doctor
diagnoses common issues with your installation
​
It’s a conversation
Claude Code is conversational. You don’t need perfect prompts. Start with what you want, then refine:
Fix the login bug
[Claude investigates, tries something]
That's not quite right. The issue is in the session handling.
[Claude adjusts approach]
When the first attempt isn’t right, you don’t start over. You iterate.
​
Interrupt and steer
You can interrupt Claude at any point. If it’s going down the wrong path, just type your correction and press Enter. Claude will stop what it’s doing and adjust its approach based on your input. You don’t have to wait for it to finish or start over.
​
Be specific upfront
The more precise your initial prompt, the fewer corrections you’ll need. Reference specific files, mention constraints, and point to example patterns.
The checkout flow is broken for users with expired cards.
Check src/payments/ for the issue, especially token refresh.
Write a failing test first, then fix it.
Vague prompts work, but you’ll spend more time steering. Specific prompts like the one above often succeed on the first attempt.
​
Give Claude something to verify against
Claude performs better when it can check its own work. Include test cases, paste screenshots of expected UI, or define the output you want.
Implement validateEmail. Test cases: 'user@example.com' → true,
'invalid' → false, 'user@.com' → false. Run the tests after.
For visual work, paste a screenshot of the design and ask Claude to compare its implementation against it.
​
Explore before implementing
For complex problems, separate research from coding. Use plan mode (
Shift+Tab
twice) to analyze the codebase first:
Read src/auth/ and understand how we handle sessions.
Then create a plan for adding OAuth support.
Review the plan, refine it through conversation, then let Claude implement. This two-phase approach produces better results than jumping straight to code.
​
Delegate, don’t dictate
Think of delegating to a capable colleague. Give context and direction, then trust Claude to figure out the details:
The checkout flow is broken for users with expired cards.
The relevant code is in src/payments/. Can you investigate and fix it?
You don’t need to specify which files to read or what commands to run. Claude figures that out.
​
What’s next
Extend with features
Add Skills, MCP connections, and custom commands
Common workflows
Step-by-step guides for typical tasks
Was this page helpful?
Yes
No
Changelog
Extend Claude Code
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/how-claude-code-works" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Create custom subagents</title>
  <link>https://code.claude.com/docs/en/sub-agents</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/sub-agents</guid>
  <pubDate>Sun, 11 Aug 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Create custom subagents
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Create custom subagents
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents are specialized AI assistants that handle specific types of tasks. Use one when a side task would flood your main conversation with search results, logs, or file contents you won’t reference again: the subagent does that work in its own context and returns only the summary. Define a custom subagent when you keep spawning the same kind of worker with the same instructions.
Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent’s description, it delegates to that subagent, which works independently and returns results. To see the context savings in practice, the
context window visualization
walks through a session where a subagent handles research in its own separate window.
Subagents work within a single session. To run many independent sessions in parallel and monitor them from one place, see
background agents
. For sessions that communicate with each other, see
agent teams
.
Subagents help you:
Preserve context
by keeping exploration and implementation out of your main conversation
Enforce constraints
by limiting which tools a subagent can use
Reuse configurations
across projects with user-level subagents
Specialize behavior
with focused system prompts for specific domains
Control costs
by routing tasks to faster, cheaper models like Haiku
Claude uses each subagent’s description to decide when to delegate tasks. When you create a subagent, write a clear description so Claude knows when to use it.
Claude Code includes several built-in subagents like
Explore
,
Plan
, and
general-purpose
. You can also create custom subagents to handle specific tasks. This page covers:
Built-in subagents
How to create your own
Full configuration options
Patterns for working with subagents
Forked subagents
Example subagents
​
Built-in subagents
Claude Code includes built-in subagents that Claude automatically uses when appropriate. Each inherits the parent conversation’s permissions with additional tool restrictions.
Explore
Plan
General-purpose
Other
A fast, read-only agent optimized for searching and analyzing codebases.
Model
: Haiku (fast, low-latency)
Tools
: Read-only tools (denied access to Write and Edit tools)
Purpose
: File discovery, code search, codebase exploration
Claude delegates to Explore when it needs to search or understand a codebase without making changes. This keeps exploration results out of your main conversation context.
When invoking Explore, Claude specifies a thoroughness level:
quick
for targeted lookups,
medium
for balanced exploration, or
very thorough
for comprehensive analysis.
A research agent used during
plan mode
to gather context before presenting a plan.
Model
: Inherits from main conversation
Tools
: Read-only tools (denied access to Write and Edit tools)
Purpose
: Codebase research for planning
When you’re in plan mode and Claude needs to understand your codebase, it delegates research to the Plan subagent. This prevents infinite nesting (subagents cannot spawn other subagents) while still gathering necessary context.
A capable agent for complex, multi-step tasks that require both exploration and action.
Model
: Inherits from main conversation
Tools
: All tools
Purpose
: Complex research, multi-step operations, code modifications
Claude delegates to general-purpose when the task requires both exploration and modification, complex reasoning to interpret results, or multiple dependent steps.
Claude Code includes additional helper agents for specific tasks. These are typically invoked automatically, so you don’t need to use them directly.
Agent
Model
When Claude uses it
statusline-setup
Sonnet
When you run
/statusline
to configure your status line
claude-code-guide
Haiku
When you ask questions about Claude Code features
Beyond these built-in subagents, you can create your own with custom prompts, tool restrictions, permission modes, hooks, and skills. The following sections show how to get started and customize subagents.
​
Quickstart: create your first subagent
Subagents are defined in Markdown files with YAML frontmatter. You can
create them manually
or use the
/agents
command.
This walkthrough guides you through creating a user-level subagent with the
/agents
command. The subagent reviews code and suggests improvements for the codebase.
1
Open the subagents interface
In Claude Code, run:
/agents
2
Choose a location
Switch to the
Library
tab, select
Create new agent
, then choose
Personal
. This saves the subagent to
~/.claude/agents/
so it’s available in all your projects.
3
Generate with Claude
Select
Generate with Claude
. When prompted, describe the subagent:
A code improvement agent that scans files and suggests improvements
for readability, performance, and best practices. It should explain
each issue, show the current code, and provide an improved version.
Claude generates the identifier, description, and system prompt for you.
4
Select tools
For a read-only reviewer, deselect everything except
Read-only tools
. If you keep all tools selected, the subagent inherits all tools available to the main conversation.
5
Select model
Choose which model the subagent uses. For this example agent, select
Sonnet
, which balances capability and speed for analyzing code patterns.
6
Choose a color
Pick a background color for the subagent. This helps you identify which subagent is running in the UI.
7
Configure memory
Select
User scope
to give the subagent a
persistent memory directory
at
~/.claude/agent-memory/
. The subagent uses this to accumulate insights across conversations, such as codebase patterns and recurring issues. Select
None
if you don’t want the subagent to persist learnings.
8
Save and try it out
Review the configuration summary. Press
s
or
Enter
to save, or press
e
to save and edit the file in your editor. The subagent is available immediately. Try it:
Use the code-improver agent to suggest improvements in this project
Claude delegates to your new subagent, which scans the codebase and returns improvement suggestions.
You now have a subagent you can use in any project on your machine to analyze codebases and suggest improvements.
You can also create subagents manually as Markdown files, define them via CLI flags, or distribute them through plugins. The following sections cover all configuration options.
​
Configure subagents
​
Use the /agents command
The
/agents
command opens a tabbed interface for managing subagents. The
Running
tab shows live subagents and lets you open or stop them. The
Library
tab lets you:
View all available subagents (built-in, user, project, and plugin)
Create new subagents with guided setup or Claude generation
Edit existing subagent configuration and tool access
Delete custom subagents
See which subagents are active when duplicates exist
This is the recommended way to create and manage subagents. For manual creation or automation, you can also add subagent files directly.
​
Choose the subagent scope
Subagents are Markdown files with YAML frontmatter. Store them in different locations depending on scope. When multiple subagents share the same name, the higher-priority location wins.
Location
Scope
Priority
How to create
Managed settings
Organization-wide
1 (highest)
Deployed via
managed settings
--agents
CLI flag
Current session
2
Pass JSON when launching Claude Code
.claude/agents/
Current project
3
Interactive or manual
~/.claude/agents/
All your projects
4
Interactive or manual
Plugin’s
agents/
directory
Where plugin is enabled
5 (lowest)
Installed with
plugins
Project subagents
(
.claude/agents/
) are ideal for subagents specific to a codebase. Check them into version control so your team can use and improve them collaboratively.
Project subagents are discovered by walking up from the current working directory. Directories added with
--add-dir
grant file access only
and are not scanned for subagents. To share subagents across projects, use
~/.claude/agents/
or a
plugin
.
User subagents
(
~/.claude/agents/
) are personal subagents available in all your projects.
Claude Code scans
.claude/agents/
and
~/.claude/agents/
recursively, so you can organize definitions into subfolders such as
agents/review/
or
agents/research/
. The subdirectory path does not affect how a subagent is identified or invoked, because identity comes only from the
name
frontmatter field. Keep
name
values unique across the whole tree: if two files within one scope declare the same name, Claude Code keeps one and discards the other without warning.
Plugin
agents/
directories are also scanned recursively. Unlike project and user scopes, a subfolder inside a plugin’s
agents/
directory becomes part of the
scoped identifier
: a file at
agents/review/security.md
in plugin
my-plugin
registers as
my-plugin:review:security
.
CLI-defined subagents
are passed as JSON when launching Claude Code. They exist only for that session and aren’t saved to disk, making them useful for quick testing or automation scripts. You can define multiple subagents in a single
--agents
call:
macOS, Linux, WSL
Windows PowerShell
claude
--agents
'{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
},
"debugger": {
"description": "Debugging specialist for errors and test failures.",
"prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."
}
}'
claude
--
agents
@'
{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
},
"debugger": {
"description": "Debugging specialist for errors and test failures.",
"prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."
}
}
'@
The
--agents
flag accepts JSON with the same
frontmatter
fields as file-based subagents:
description
,
prompt
,
tools
,
disallowedTools
,
model
,
permissionMode
,
mcpServers
,
hooks
,
maxTurns
,
skills
,
initialPrompt
,
memory
,
effort
,
background
,
isolation
, and
color
. Use
prompt
for the system prompt, equivalent to the markdown body in file-based subagents.
Managed subagents
are deployed by organization administrators. Place markdown files in
.claude/agents/
inside the
managed settings directory
, using the same frontmatter format as project and user subagents. Managed definitions take precedence over project and user subagents with the same name.
Plugin subagents
come from
plugins
you’ve installed. They appear in
/agents
alongside your custom subagents. See the
plugin components reference
for details on creating plugin subagents.
For security reasons, plugin subagents do not support the
hooks
,
mcpServers
, or
permissionMode
frontmatter fields. These fields are ignored when loading agents from a plugin. If you need them, copy the agent file into
.claude/agents/
or
~/.claude/agents/
. You can also add rules to
permissions.allow
in
settings.json
or
settings.local.json
, but these rules apply to the entire session, not just the plugin subagent.
Subagent definitions from any of these scopes are also available to
agent teams
: when spawning a teammate, you can reference a subagent type and the teammate uses its
tools
and
model
, with the definition’s body appended to the teammate’s system prompt as additional instructions. See
agent teams
for which frontmatter fields apply on that path.
​
Write subagent files
Subagent files use YAML frontmatter for configuration, followed by the system prompt in Markdown:
Subagents are loaded at session start. If you add or edit a subagent file directly on disk, restart your session to load it. Subagents created through the
/agents
interface take effect immediately without a restart.
---
name
:
code-reviewer
description
:
Reviews code for quality and best practices
tools
:
Read, Glob, Grep
model
:
sonnet
---
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
The frontmatter defines the subagent’s metadata and configuration. The body becomes the system prompt that guides the subagent’s behavior. Subagents receive only this system prompt (plus basic environment details like working directory), not the full Claude Code system prompt.
A subagent starts in the main conversation’s current working directory. Within a subagent,
cd
commands do not persist between Bash or PowerShell tool calls and do not affect the main conversation’s working directory. To give the subagent an isolated copy of the repository instead, set
isolation: worktree
.
​
Supported frontmatter fields
The following fields can be used in the YAML frontmatter. Only
name
and
description
are required.
Field
Required
Description
name
Yes
Unique identifier using lowercase letters and hyphens.
Hooks
receive this value as
agent_type
. The filename does not have to match
description
Yes
When Claude should delegate to this subagent
tools
No
Tools
the subagent can use. Inherits all tools if omitted. To preload Skills into context, use the
skills
field rather than listing
Skill
here
disallowedTools
No
Tools to deny, removed from inherited or specified list
model
No
Model
to use:
sonnet
,
opus
,
haiku
, a full model ID (for example,
claude-opus-4-7
), or
inherit
. Defaults to
inherit
permissionMode
No
Permission mode
:
default
,
acceptEdits
,
auto
,
dontAsk
,
bypassPermissions
, or
plan
. Ignored for
plugin subagents
maxTurns
No
Maximum number of agentic turns before the subagent stops
skills
No
Skills
to preload into the subagent’s context at startup. The full skill content is injected, not just the description. Subagents can still invoke unlisted project, user, and plugin skills through the Skill tool
mcpServers
No
MCP servers
available to this subagent. Each entry is either a server name referencing an already-configured server (e.g.,
"slack"
) or an inline definition with the server name as key and a full
MCP server config
as value. Ignored for
plugin subagents
hooks
No
Lifecycle hooks
scoped to this subagent. Ignored for
plugin subagents
memory
No
Persistent memory scope
:
user
,
project
, or
local
. Enables cross-session learning
background
No
Set to
true
to always run this subagent as a
background task
. Default:
false
effort
No
Effort level when this subagent is active. Overrides the session effort level. Default: inherits from session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model
isolation
No
Set to
worktree
to run the subagent in a temporary
git worktree
, giving it an isolated copy of the repository. The worktree is automatically cleaned up if the subagent makes no changes
color
No
Display color for the subagent in the task list and transcript. Accepts
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
, or
cyan
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main session agent (via
--agent
or the
agent
setting).
Commands
and
skills
are processed. Prepended to any user-provided prompt
​
Choose a model
The
model
field controls which
AI model
the subagent uses:
Model alias
: Use one of the available aliases:
sonnet
,
opus
, or
haiku
Full model ID
: Use a full model ID such as
claude-opus-4-7
or
claude-sonnet-4-6
. Accepts the same values as the
--model
flag
inherit
: Use the same model as the main conversation
Omitted
: If not specified, defaults to
inherit
(uses the same model as the main conversation)
When Claude invokes a subagent, it can also pass a
model
parameter for that specific invocation. Claude Code resolves the subagent’s model in this order:
The
CLAUDE_CODE_SUBAGENT_MODEL
environment variable, if set
The per-invocation
model
parameter
The subagent definition’s
model
frontmatter
The main conversation’s model
​
Control subagent capabilities
You can control what subagents can do through tool access, permission modes, and conditional rules.
​
Available tools
Subagents can use any of Claude Code’s
internal tools
. By default, subagents inherit all tools from the main conversation, including MCP tools.
To restrict tools, use either the
tools
field (allowlist) or the
disallowedTools
field (denylist). This example uses
tools
to exclusively allow Read, Grep, Glob, and Bash. The subagent can’t edit files, write files, or use any MCP tools:
---
name
:
safe-researcher
description
:
Research agent with restricted capabilities
tools
:
Read, Grep, Glob, Bash
---
This example uses
disallowedTools
to inherit every tool from the main conversation except Write and Edit. The subagent keeps Bash, MCP tools, and everything else:
---
name
:
no-writes
description
:
Inherits every tool except file writes
disallowedTools
:
Write, Edit
---
If both are set,
disallowedTools
is applied first, then
tools
is resolved against the remaining pool. A tool listed in both is removed.
​
Restrict which subagents can be spawned
When an agent runs as the main thread with
claude --agent
, it can spawn subagents using the Agent tool. To restrict which subagent types it can spawn, use
Agent(agent_type)
syntax in the
tools
field.
In version 2.1.63, the Task tool was renamed to Agent. Existing
Task(...)
references in settings and agent definitions still work as aliases.
---
name
:
coordinator
description
:
Coordinates work across specialized agents
tools
:
Agent(worker, researcher), Read, Bash
---
This is an allowlist: only the
worker
and
researcher
subagents can be spawned. If the agent tries to spawn any other type, the request fails and the agent sees only the allowed types in its prompt. To block specific agents while allowing all others, use
permissions.deny
instead.
To allow spawning any subagent without restrictions, use
Agent
without parentheses:
tools
:
Agent, Read, Bash
If
Agent
is omitted from the
tools
list entirely, the agent cannot spawn any subagents. This restriction only applies to agents running as the main thread with
claude --agent
. Subagents cannot spawn other subagents, so
Agent(agent_type)
has no effect in subagent definitions.
​
Scope MCP servers to a subagent
Use the
mcpServers
field to give a subagent access to
MCP
servers that aren’t available in the main conversation. Inline servers defined here are connected when the subagent starts and disconnected when it finishes. String references share the parent session’s connection.
The
mcpServers
field applies in both contexts where an agent file can run:
As a subagent, spawned through the Agent tool or an @-mention
As the main session, launched with
--agent
or the
agent
setting
When the agent is the main session, inline server definitions connect at startup alongside servers from
.mcp.json
and settings files.
Each entry in the list is either an inline server definition or a string referencing an MCP server already configured in your session:
---
name
:
browser-tester
description
:
Tests features in a real browser using Playwright
mcpServers
:
# Inline definition: scoped to this subagent only
-
playwright
:
type
:
stdio
command
:
npx
args
: [
"-y"
,
"@playwright/mcp@latest"
]
# Reference by name: reuses an already-configured server
-
github
---
Use the Playwright tools to navigate, screenshot, and interact with pages.
Inline definitions use the same schema as
.mcp.json
server entries (
stdio
,
http
,
sse
,
ws
), keyed by the server name.
To keep an MCP server out of the main conversation entirely and avoid its tool descriptions consuming context there, define it inline here rather than in
.mcp.json
. The subagent gets the tools; the parent conversation does not.
​
Permission modes
The
permissionMode
field controls how the subagent handles permission prompts. Subagents inherit the permission context from the main conversation and can override the mode, except when the parent mode takes precedence as described below.
Mode
Behavior
default
Standard permission checking with prompts
acceptEdits
Auto-accept file edits and common filesystem commands for paths in the working directory or
additionalDirectories
auto
Auto mode
: a background classifier reviews commands and protected-directory writes
dontAsk
Auto-deny permission prompts (explicitly allowed tools still work)
bypassPermissions
Skip permission prompts
plan
Plan mode (read-only exploration)
Use
bypassPermissions
with caution. It skips all permission prompts, allowing the subagent to execute operations without approval, including writes to
.git
,
.claude
,
.vscode
,
.idea
, and
.husky
. Root and home directory removals such as
rm -rf /
still prompt as a circuit breaker. See
permission modes
for details.
If the parent uses
bypassPermissions
or
acceptEdits
, this takes precedence and cannot be overridden. If the parent uses
auto mode
, the subagent inherits auto mode and any
permissionMode
in its frontmatter is ignored: the classifier evaluates the subagent’s tool calls with the same block and allow rules as the parent session.
​
Preload skills into subagents
Use the
skills
field to inject skill content into a subagent’s context at startup. This gives the subagent domain knowledge without requiring it to discover and load skills during execution.
---
name
:
api-developer
description
:
Implement API endpoints following team conventions
skills
:
-
api-conventions
-
error-handling-patterns
---
Implement API endpoints. Follow the conventions and patterns from the preloaded skills.
The full content of each listed skill is injected into the subagent’s context at startup. This field controls which skills are preloaded, not which skills the subagent can access: without it, the subagent can still discover and invoke project, user, and plugin skills through the Skill tool during execution. To prevent a subagent from invoking skills entirely, omit
Skill
from the
tools
list or add it to
disallowedTools
.
You cannot preload skills that set
disable-model-invocation: true
, since preloading draws from the same set of skills Claude can invoke. If a listed skill is missing or disabled, Claude Code skips it and logs a warning to the debug log.
This is the inverse of
running a skill in a subagent
. With
skills
in a subagent, the subagent controls the system prompt and loads skill content. With
context: fork
in a skill, the skill content is injected into the agent you specify. Both use the same underlying system.
​
Enable persistent memory
The
memory
field gives the subagent a persistent directory that survives across conversations. The subagent uses this directory to build up knowledge over time, such as codebase patterns, debugging insights, and architectural decisions.
---
name
:
code-reviewer
description
:
Reviews code for quality and best practices
memory
:
user
---
You are a code reviewer. As you review code, update your agent memory with
patterns, conventions, and recurring issues you discover.
Choose a scope based on how broadly the memory should apply:
Scope
Location
Use when
user
~/.claude/agent-memory/<name-of-agent>/
the subagent should remember learnings across all projects
project
.claude/agent-memory/<name-of-agent>/
the subagent’s knowledge is project-specific and shareable via version control
local
.claude/agent-memory-local/<name-of-agent>/
the subagent’s knowledge is project-specific but should not be checked into version control
When memory is enabled:
The subagent’s system prompt includes instructions for reading and writing to the memory directory.
The subagent’s system prompt also includes the first 200 lines or 25KB of
MEMORY.md
in the memory directory, whichever comes first, with instructions to curate
MEMORY.md
if it exceeds that limit.
Read, Write, and Edit tools are automatically enabled so the subagent can manage its memory files.
Persistent memory tips
project
is the recommended default scope. It makes subagent knowledge shareable via version control. Use
user
when the subagent’s knowledge is broadly applicable across projects, or
local
when the knowledge should not be checked into version control.
Ask the subagent to consult its memory before starting work: “Review this PR, and check your memory for patterns you’ve seen before.”
Ask the subagent to update its memory after completing a task: “Now that you’re done, save what you learned to your memory.” Over time, this builds a knowledge base that makes the subagent more effective.
Include memory instructions directly in the subagent’s markdown file so it proactively maintains its own knowledge base:
Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.
​
Conditional rules with hooks
For more dynamic control over tool usage, use
PreToolUse
hooks to validate operations before they execute. This is useful when you need to allow some operations of a tool while blocking others.
This example creates a subagent that only allows read-only database queries. The
PreToolUse
hook runs the script specified in
command
before each Bash command executes:
---
name
:
db-reader
description
:
Execute read-only database queries
tools
:
Bash
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-readonly-query.sh"
---
Claude Code
passes hook input as JSON
via stdin to hook commands. The validation script reads this JSON, extracts the Bash command, and
exits with code 2
to block write operations:
#!/bin/bash
# ./scripts/validate-readonly-query.sh
INPUT
=
$(
cat
)
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command // empty'
)
# Block SQL write operations (case-insensitive)
if
echo
"
$COMMAND
"
|
grep
-iE
'\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE)\b'
>
/dev/null
;
then
echo
"Blocked: Only SELECT queries are allowed"
>&2
exit
2
fi
exit
0
See
Hook input
for the complete input schema and
exit codes
for how exit codes affect behavior. On Windows, write hook scripts in PowerShell and add
shell: powershell
to the hook entry as shown in
running hooks in PowerShell
.
​
Disable specific subagents
You can prevent Claude from using specific subagents by adding them to the
deny
array in your
settings
. Use the format
Agent(subagent-name)
where
subagent-name
matches the subagent’s name field.
{
"permissions"
: {
"deny"
: [
"Agent(Explore)"
,
"Agent(my-custom-agent)"
]
}
}
This works for both built-in and custom subagents. You can also use the
--disallowedTools
CLI flag:
claude
--disallowedTools
"Agent(Explore)"
See
Permissions documentation
for more details on permission rules.
​
Define hooks for subagents
Subagents can define
hooks
that run during the subagent’s lifecycle. There are two ways to configure hooks:
In the subagent’s frontmatter
: Define hooks that run only while that subagent is active
In
settings.json
: Define hooks that run in the main session when subagents start or stop
​
Hooks in subagent frontmatter
Define hooks directly in the subagent’s markdown file. These hooks only run while that specific subagent is active and are cleaned up when it finishes.
Frontmatter hooks fire when the agent is spawned as a subagent through the Agent tool or an @-mention, and when the agent runs as the main session via
--agent
or the
agent
setting. In the main-session case they run alongside any hooks defined in
settings.json
.
All
hook events
are supported. The most common events for subagents are:
Event
Matcher input
When it fires
PreToolUse
Tool name
Before the subagent uses a tool
PostToolUse
Tool name
After the subagent uses a tool
Stop
(none)
When the subagent finishes (converted to
SubagentStop
at runtime)
This example validates Bash commands with the
PreToolUse
hook and runs a linter after file edits with
PostToolUse
:
---
name
:
code-reviewer
description
:
Review code changes with automatic linting
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-command.sh $TOOL_INPUT"
PostToolUse
:
-
matcher
:
"Edit|Write"
hooks
:
-
type
:
command
command
:
"./scripts/run-linter.sh"
---
When the agent is invoked as a subagent,
Stop
hooks in frontmatter are automatically converted to
SubagentStop
events.
​
Project-level hooks for subagent events
Configure hooks in
settings.json
that respond to subagent lifecycle events in the main session.
Event
Matcher input
When it fires
SubagentStart
Agent type name
When a subagent begins execution
SubagentStop
Agent type name
When a subagent completes
Both events support matchers to target specific agent types by name. This example runs a setup script only when the
db-agent
subagent starts, and a cleanup script when any subagent stops:
{
"hooks"
: {
"SubagentStart"
: [
{
"matcher"
:
"db-agent"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"./scripts/setup-db-connection.sh"
}
]
}
],
"SubagentStop"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"./scripts/cleanup-db-connection.sh"
}
]
}
]
}
}
See
Hooks
for the complete hook configuration format.
​
Work with subagents
​
Understand automatic delegation
Claude automatically delegates tasks based on the task description in your request, the
description
field in subagent configurations, and current context. To encourage proactive delegation, include phrases like “use proactively” in your subagent’s description field.
​
Invoke subagents explicitly
When automatic delegation isn’t enough, you can request a subagent yourself. Three patterns escalate from a one-off suggestion to a session-wide default:
Natural language
: name the subagent in your prompt; Claude decides whether to delegate
@-mention
: guarantees the subagent runs for one task
Session-wide
: the whole session uses that subagent’s system prompt, tool restrictions, and model via the
--agent
flag or the
agent
setting
For natural language, there’s no special syntax. Name the subagent and Claude typically delegates:
Use the test-runner subagent to fix failing tests
Have the code-reviewer subagent look at my recent changes
@-mention the subagent.
Type
@
and pick the subagent from the typeahead, the same way you @-mention files. This ensures that specific subagent runs rather than leaving the choice to Claude:
@"code-reviewer (agent)" look at the auth changes
Your full message still goes to Claude, which writes the subagent’s task prompt based on what you asked. The @-mention controls which subagent Claude invokes, not what prompt it receives.
Subagents provided by an enabled
plugin
appear in the typeahead under their scoped name, such as
my-plugin:code-reviewer
or
my-plugin:review:security
when the plugin
organizes agents into subfolders
. Named background subagents currently running in the session also appear in the typeahead, showing their status next to the name. You can also type the mention manually without using the picker:
@agent-<name>
for local subagents, or
@agent-
followed by the scoped name for plugin subagents, for example
@agent-my-plugin:code-reviewer
.
Run the whole session as a subagent.
Pass
--agent <name>
to start a session where the main thread itself takes on that subagent’s system prompt, tool restrictions, and model:
claude
--agent
code-reviewer
The subagent’s system prompt replaces the default Claude Code system prompt entirely, the same way
--system-prompt
does.
CLAUDE.md
files and project memory still load through the normal message flow. The agent name appears as
@<name>
in the startup header so you can confirm it’s active.
This works with built-in and custom subagents, and the choice persists when you resume the session.
For a plugin-provided subagent, pass the scoped name:
claude --agent <plugin-name>:<agent-name>
. If the plugin places the agent in a subfolder of its
agents/
directory, include the subfolder in the scoped name, for example
claude --agent my-plugin:review:security
.
To make it the default for every session in a project, set
agent
in
.claude/settings.json
:
{
"agent"
:
"code-reviewer"
}
The CLI flag overrides the setting if both are present.
​
Run subagents in foreground or background
Subagents can run in the foreground (blocking) or background (concurrent):
Foreground subagents
block the main conversation until complete. Permission prompts are passed through to you as they come up.
Background subagents
run concurrently while you continue working. They run with the permissions already granted in the session and auto-deny any tool call that would otherwise prompt. If a background subagent needs to ask clarifying questions, that tool call fails but the subagent continues.
If a background subagent fails due to missing permissions, you can start a new foreground subagent with the same task to retry with interactive prompts.
Claude decides whether to run subagents in the foreground or background based on the task. You can also:
Ask Claude to “run this in the background”
Press
Ctrl+B
to background a running task
To disable all background task functionality, set the
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
environment variable to
1
. See
Environment variables
.
When
fork mode
is enabled, every subagent spawn runs in the background regardless of the
background
field. Forks still surface permission prompts in your terminal as they occur; named subagents auto-deny anything that would prompt, as described above.
​
Common patterns
​
Isolate high-volume operations
One of the most effective uses for subagents is isolating operations that produce large amounts of output. Running tests, fetching documentation, or processing log files can consume significant context. By delegating these to a subagent, the verbose output stays in the subagent’s context while only the relevant summary returns to your main conversation.
Use a subagent to run the test suite and report only the failing tests with their error messages
​
Run parallel research
For independent investigations, spawn multiple subagents to work simultaneously:
Research the authentication, database, and API modules in parallel using separate subagents
Each subagent explores its area independently, then Claude synthesizes the findings. This works best when the research paths don’t depend on each other.
When subagents complete, their results return to your main conversation. Running many subagents that each return detailed results can consume significant context.
For tasks that need sustained parallelism or exceed your context window,
agent teams
give each worker its own independent context.
​
Chain subagents
For multi-step workflows, ask Claude to use subagents in sequence. Each subagent completes its task and returns results to Claude, which then passes relevant context to the next subagent.
Use the code-reviewer subagent to find performance issues, then use the optimizer subagent to fix them
​
Choose between subagents and main conversation
Use the
main conversation
when:
The task needs frequent back-and-forth or iterative refinement
Multiple phases share significant context (planning → implementation → testing)
You’re making a quick, targeted change
Latency matters. Subagents start fresh and may need time to gather context
Use
subagents
when:
The task produces verbose output you don’t need in your main context
You want to enforce specific tool restrictions or permissions
The work is self-contained and can return a summary
Consider
Skills
instead when you want reusable prompts or workflows that run in the main conversation context rather than isolated subagent context.
For a quick question about something already in your conversation, use
/btw
instead of a subagent. It sees your full context but has no tool access, and the answer is discarded rather than added to history.
Subagents cannot spawn other subagents. If your workflow requires nested delegation, use
Skills
or
chain subagents
from the main conversation.
​
Manage subagent context
​
Resume subagents
Each subagent invocation creates a new instance with fresh context. To continue an existing subagent’s work instead of starting over, ask Claude to resume it.
Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.
When a subagent completes, Claude receives its agent ID. Claude uses the
SendMessage
tool with the agent’s ID as the
to
field to resume it. The
SendMessage
tool is only available when
agent teams
are enabled via
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
.
To resume a subagent, ask Claude to continue the previous work:
Use the code-reviewer subagent to review the authentication module
[Agent completes]
Continue that code review and now analyze the authorization logic
[Claude resumes the subagent with full context from previous conversation]
If a stopped subagent receives a
SendMessage
, it auto-resumes in the background without requiring a new
Agent
invocation.
You can also ask Claude for the agent ID if you want to reference it explicitly, or find IDs in the transcript files at
~/.claude/projects/{project}/{sessionId}/subagents/
. Each transcript is stored as
agent-{agentId}.jsonl
.
Subagent transcripts persist independently of the main conversation:
Main conversation compaction
: When the main conversation compacts, subagent transcripts are unaffected. They’re stored in separate files.
Session persistence
: Subagent transcripts persist within their session. You can
resume a subagent
after restarting Claude Code by resuming the same session.
Automatic cleanup
: Transcripts are cleaned up based on the
cleanupPeriodDays
setting (default: 30 days).
​
Auto-compaction
Subagents support automatic compaction using the same logic as the main conversation. By default, auto-compaction triggers at approximately 95% capacity. To trigger compaction earlier, set
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
to a lower percentage (for example,
50
). See
environment variables
for details.
Compaction events are logged in subagent transcript files:
{
"type"
:
"system"
,
"subtype"
:
"compact_boundary"
,
"compactMetadata"
: {
"trigger"
:
"auto"
,
"preTokens"
:
167189
}
}
The
preTokens
value shows how many tokens were used before compaction occurred.
​
Fork the current conversation
Forked subagents are experimental and require Claude Code v2.1.117 or later. Behavior and configuration may change in future releases. Enable them by setting the
CLAUDE_CODE_FORK_SUBAGENT
environment variable to
1
. The variable is honored in interactive mode and via the SDK or
claude -p
.
A fork is a subagent that inherits the entire conversation so far instead of starting fresh. This drops the input isolation that subagents otherwise provide: a fork sees the same system prompt, tools, model, and message history as the main session, so you can hand it a side task without re-explaining the situation. The fork’s own tool calls still stay out of your conversation and only its final result comes back, so your main context window stays clean. Use a fork when a named subagent would need too much background to be useful, or when you want to try several approaches in parallel from the same starting point.
Enabling fork mode changes Claude Code in three ways:
Claude spawns a fork whenever it would otherwise use the
general-purpose
subagent. Named subagents such as Explore still spawn as before.
Every subagent spawn runs in the
background
, whether it is a fork or a named subagent. Set
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
to
1
to keep spawns synchronous.
The
/fork
command spawns a fork instead of acting as an alias for
/branch
.
You can start a fork yourself with
/fork
followed by a directive. Claude Code names the fork from the first words of the directive. The following example forks the conversation to draft test cases while you continue with the implementation in the main session:
/fork draft unit tests for the parser changes so far
The fork appears in a panel below your prompt and runs in the background while you keep working. When it finishes, its result arrives as a message in your main conversation. The next section covers the panel controls for watching and steering forks while they run.
​
Observe and steer running forks
Running forks appear in a panel below the prompt input, with one row for the main session and one for each fork. Use these keys to interact with the panel:
Key
Action
↑
/
↓
Move between rows
Enter
Open the selected fork’s transcript and send it follow-up messages
x
Dismiss a finished fork or stop a running one
Esc
Return focus to the prompt input
​
How forks differ from named subagents
A fork inherits everything the main session has at the moment it spawns. A named subagent starts from its own definition.
Fork
Named subagent
Context
Full conversation history
Fresh context with the prompt you pass
System prompt and tools
Same as main session
From the subagent’s
definition file
Model
Same as main session
From the subagent’s
model
field
Permissions
Prompts surface in your terminal
Auto-denied
when running in the background
Prompt cache
Shared with main session
Separate cache
Because a fork’s system prompt and tool definitions are identical to the parent, its first request reuses the parent’s prompt cache. This makes forking cheaper than spawning a fresh subagent for tasks that need the same context.
When Claude spawns a fork through the Agent tool, it can pass
isolation: "worktree"
so the fork’s file edits are written to a separate git worktree instead of your checkout.
​
Limitations
Setting
CLAUDE_CODE_FORK_SUBAGENT=1
enables fork mode in interactive sessions,
non-interactive mode
, and the Agent SDK. A fork cannot spawn further forks.
​
Example subagents
These examples demonstrate effective patterns for building subagents. Use them as starting points, or generate a customized version with Claude.
Best practices:
Design focused subagents:
each subagent should excel at one specific task
Write detailed descriptions:
Claude uses the description to decide when to delegate
Limit tool access:
grant only necessary permissions for security and focus
Check into version control:
share project subagents with your team
​
Code reviewer
A read-only subagent that reviews code without modifying it. This example shows how to design a focused subagent with limited tool access (no Edit or Write) and a detailed prompt that specifies exactly what to look for and how to format output.
---
name
:
code-reviewer
description
:
Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools
:
Read, Grep, Glob, Bash
model
:
inherit
---
You are a senior code reviewer ensuring high standards of code quality and security.
When invoked:
1.
Run git diff to see recent changes
2.
Focus on modified files
3.
Begin review immediately
Review checklist:
-
Code is clear and readable
-
Functions and variables are well-named
-
No duplicated code
-
Proper error handling
-
No exposed secrets or API keys
-
Input validation implemented
-
Good test coverage
-
Performance considerations addressed
Provide feedback organized by priority:
-
Critical issues (must fix)
-
Warnings (should fix)
-
Suggestions (consider improving)
Include specific examples of how to fix issues.
​
Debugger
A subagent that can both analyze and fix issues. Unlike the code reviewer, this one includes Edit because fixing bugs requires modifying code. The prompt provides a clear workflow from diagnosis to verification.
---
name
:
debugger
description
:
Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
tools
:
Read, Edit, Bash, Grep, Glob
---
You are an expert debugger specializing in root cause analysis.
When invoked:
1.
Capture error message and stack trace
2.
Identify reproduction steps
3.
Isolate the failure location
4.
Implement minimal fix
5.
Verify solution works
Debugging process:
-
Analyze error messages and logs
-
Check recent code changes
-
Form and test hypotheses
-
Add strategic debug logging
-
Inspect variable states
For each issue, provide:
-
Root cause explanation
-
Evidence supporting the diagnosis
-
Specific code fix
-
Testing approach
-
Prevention recommendations
Focus on fixing the underlying issue, not the symptoms.
​
Data scientist
A domain-specific subagent for data analysis work. This example shows how to create subagents for specialized workflows outside of typical coding tasks. It explicitly sets
model: sonnet
for more capable analysis.
---
name
:
data-scientist
description
:
Data analysis expert for SQL queries, BigQuery operations, and data insights. Use proactively for data analysis tasks and queries.
tools
:
Bash, Read, Write
model
:
sonnet
---
You are a data scientist specializing in SQL and BigQuery analysis.
When invoked:
1.
Understand the data analysis requirement
2.
Write efficient SQL queries
3.
Use BigQuery command line tools (bq) when appropriate
4.
Analyze and summarize results
5.
Present findings clearly
Key practices:
-
Write optimized SQL queries with proper filters
-
Use appropriate aggregations and joins
-
Include comments explaining complex logic
-
Format results for readability
-
Provide data-driven recommendations
For each analysis:
-
Explain the query approach
-
Document any assumptions
-
Highlight key findings
-
Suggest next steps based on data
Always ensure queries are efficient and cost-effective.
​
Database query validator
A subagent that allows Bash access but validates commands to permit only read-only SQL queries. This example shows how to use
PreToolUse
hooks for conditional validation when you need finer control than the
tools
field provides.
---
name
:
db-reader
description
:
Execute read-only database queries. Use when analyzing data or generating reports.
tools
:
Bash
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-readonly-query.sh"
---
You are a database analyst with read-only access. Execute SELECT queries to answer questions about the data.
When asked to analyze data:
1.
Identify which tables contain the relevant data
2.
Write efficient SELECT queries with appropriate filters
3.
Present results clearly with context
You cannot modify data. If asked to INSERT, UPDATE, DELETE, or modify schema, explain that you only have read access.
Claude Code
passes hook input as JSON
via stdin to hook commands. The validation script reads this JSON, extracts the command being executed, and checks it against a list of SQL write operations. If a write operation is detected, the script
exits with code 2
to block execution and returns an error message to Claude via stderr.
Create the validation script anywhere in your project. The path must match the
command
field in your hook configuration:
#!/bin/bash
# Blocks SQL write operations, allows SELECT queries
# Read JSON input from stdin
INPUT
=
$(
cat
)
# Extract the command field from tool_input using jq
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command // empty'
)
if
[
-z
"
$COMMAND
"
];
then
exit
0
fi
# Block write operations (case-insensitive)
if
echo
"
$COMMAND
"
|
grep
-iE
'\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE|REPLACE|MERGE)\b'
>
/dev/null
;
then
echo
"Blocked: Write operations not allowed. Use SELECT queries only."
>&2
exit
2
fi
exit
0
On macOS and Linux, make the script executable:
chmod
+x
./scripts/validate-readonly-query.sh
On Windows, write the validation script in PowerShell and add
shell: powershell
to the hook entry. See
running hooks in PowerShell
.
The hook receives JSON via stdin with the Bash command in
tool_input.command
. Exit code 2 blocks the operation and feeds the error message back to Claude. See
Hooks
for details on exit codes and
Hook input
for the complete input schema.
​
Next steps
Now that you understand subagents, explore these related features:
Distribute subagents with plugins
to share subagents across teams or projects
Run Claude Code programmatically
with the Agent SDK for CI/CD and automation
Use MCP servers
to give subagents access to external tools and data
Was this page helpful?
Yes
No
Overview
Agent view
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/sub-agents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Create custom subagents
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Create custom subagents
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents are specialized AI assistants that handle specific types of tasks. Use one when a side task would flood your main conversation with search results, logs, or file contents you won’t reference again: the subagent does that work in its own context and returns only the summary. Define a custom subagent when you keep spawning the same kind of worker with the same instructions.
Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent’s description, it delegates to that subagent, which works independently and returns results. To see the context savings in practice, the
context window visualization
walks through a session where a subagent handles research in its own separate window.
Subagents work within a single session. To run many independent sessions in parallel and monitor them from one place, see
background agents
. For sessions that communicate with each other, see
agent teams
.
Subagents help you:
Preserve context
by keeping exploration and implementation out of your main conversation
Enforce constraints
by limiting which tools a subagent can use
Reuse configurations
across projects with user-level subagents
Specialize behavior
with focused system prompts for specific domains
Control costs
by routing tasks to faster, cheaper models like Haiku
Claude uses each subagent’s description to decide when to delegate tasks. When you create a subagent, write a clear description so Claude knows when to use it.
Claude Code includes several built-in subagents like
Explore
,
Plan
, and
general-purpose
. You can also create custom subagents to handle specific tasks. This page covers:
Built-in subagents
How to create your own
Full configuration options
Patterns for working with subagents
Forked subagents
Example subagents
​
Built-in subagents
Claude Code includes built-in subagents that Claude automatically uses when appropriate. Each inherits the parent conversation’s permissions with additional tool restrictions.
Explore
Plan
General-purpose
Other
A fast, read-only agent optimized for searching and analyzing codebases.
Model
: Haiku (fast, low-latency)
Tools
: Read-only tools (denied access to Write and Edit tools)
Purpose
: File discovery, code search, codebase exploration
Claude delegates to Explore when it needs to search or understand a codebase without making changes. This keeps exploration results out of your main conversation context.
When invoking Explore, Claude specifies a thoroughness level:
quick
for targeted lookups,
medium
for balanced exploration, or
very thorough
for comprehensive analysis.
A research agent used during
plan mode
to gather context before presenting a plan.
Model
: Inherits from main conversation
Tools
: Read-only tools (denied access to Write and Edit tools)
Purpose
: Codebase research for planning
When you’re in plan mode and Claude needs to understand your codebase, it delegates research to the Plan subagent. This prevents infinite nesting (subagents cannot spawn other subagents) while still gathering necessary context.
A capable agent for complex, multi-step tasks that require both exploration and action.
Model
: Inherits from main conversation
Tools
: All tools
Purpose
: Complex research, multi-step operations, code modifications
Claude delegates to general-purpose when the task requires both exploration and modification, complex reasoning to interpret results, or multiple dependent steps.
Claude Code includes additional helper agents for specific tasks. These are typically invoked automatically, so you don’t need to use them directly.
Agent
Model
When Claude uses it
statusline-setup
Sonnet
When you run
/statusline
to configure your status line
claude-code-guide
Haiku
When you ask questions about Claude Code features
Beyond these built-in subagents, you can create your own with custom prompts, tool restrictions, permission modes, hooks, and skills. The following sections show how to get started and customize subagents.
​
Quickstart: create your first subagent
Subagents are defined in Markdown files with YAML frontmatter. You can
create them manually
or use the
/agents
command.
This walkthrough guides you through creating a user-level subagent with the
/agents
command. The subagent reviews code and suggests improvements for the codebase.
1
Open the subagents interface
In Claude Code, run:
/agents
2
Choose a location
Switch to the
Library
tab, select
Create new agent
, then choose
Personal
. This saves the subagent to
~/.claude/agents/
so it’s available in all your projects.
3
Generate with Claude
Select
Generate with Claude
. When prompted, describe the subagent:
A code improvement agent that scans files and suggests improvements
for readability, performance, and best practices. It should explain
each issue, show the current code, and provide an improved version.
Claude generates the identifier, description, and system prompt for you.
4
Select tools
For a read-only reviewer, deselect everything except
Read-only tools
. If you keep all tools selected, the subagent inherits all tools available to the main conversation.
5
Select model
Choose which model the subagent uses. For this example agent, select
Sonnet
, which balances capability and speed for analyzing code patterns.
6
Choose a color
Pick a background color for the subagent. This helps you identify which subagent is running in the UI.
7
Configure memory
Select
User scope
to give the subagent a
persistent memory directory
at
~/.claude/agent-memory/
. The subagent uses this to accumulate insights across conversations, such as codebase patterns and recurring issues. Select
None
if you don’t want the subagent to persist learnings.
8
Save and try it out
Review the configuration summary. Press
s
or
Enter
to save, or press
e
to save and edit the file in your editor. The subagent is available immediately. Try it:
Use the code-improver agent to suggest improvements in this project
Claude delegates to your new subagent, which scans the codebase and returns improvement suggestions.
You now have a subagent you can use in any project on your machine to analyze codebases and suggest improvements.
You can also create subagents manually as Markdown files, define them via CLI flags, or distribute them through plugins. The following sections cover all configuration options.
​
Configure subagents
​
Use the /agents command
The
/agents
command opens a tabbed interface for managing subagents. The
Running
tab shows live subagents and lets you open or stop them. The
Library
tab lets you:
View all available subagents (built-in, user, project, and plugin)
Create new subagents with guided setup or Claude generation
Edit existing subagent configuration and tool access
Delete custom subagents
See which subagents are active when duplicates exist
This is the recommended way to create and manage subagents. For manual creation or automation, you can also add subagent files directly.
​
Choose the subagent scope
Subagents are Markdown files with YAML frontmatter. Store them in different locations depending on scope. When multiple subagents share the same name, the higher-priority location wins.
Location
Scope
Priority
How to create
Managed settings
Organization-wide
1 (highest)
Deployed via
managed settings
--agents
CLI flag
Current session
2
Pass JSON when launching Claude Code
.claude/agents/
Current project
3
Interactive or manual
~/.claude/agents/
All your projects
4
Interactive or manual
Plugin’s
agents/
directory
Where plugin is enabled
5 (lowest)
Installed with
plugins
Project subagents
(
.claude/agents/
) are ideal for subagents specific to a codebase. Check them into version control so your team can use and improve them collaboratively.
Project subagents are discovered by walking up from the current working directory. Directories added with
--add-dir
grant file access only
and are not scanned for subagents. To share subagents across projects, use
~/.claude/agents/
or a
plugin
.
User subagents
(
~/.claude/agents/
) are personal subagents available in all your projects.
Claude Code scans
.claude/agents/
and
~/.claude/agents/
recursively, so you can organize definitions into subfolders such as
agents/review/
or
agents/research/
. The subdirectory path does not affect how a subagent is identified or invoked, because identity comes only from the
name
frontmatter field. Keep
name
values unique across the whole tree: if two files within one scope declare the same name, Claude Code keeps one and discards the other without warning.
Plugin
agents/
directories are also scanned recursively. Unlike project and user scopes, a subfolder inside a plugin’s
agents/
directory becomes part of the
scoped identifier
: a file at
agents/review/security.md
in plugin
my-plugin
registers as
my-plugin:review:security
.
CLI-defined subagents
are passed as JSON when launching Claude Code. They exist only for that session and aren’t saved to disk, making them useful for quick testing or automation scripts. You can define multiple subagents in a single
--agents
call:
macOS, Linux, WSL
Windows PowerShell
claude
--agents
'{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
},
"debugger": {
"description": "Debugging specialist for errors and test failures.",
"prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."
}
}'
claude
--
agents
@'
{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
},
"debugger": {
"description": "Debugging specialist for errors and test failures.",
"prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."
}
}
'@
The
--agents
flag accepts JSON with the same
frontmatter
fields as file-based subagents:
description
,
prompt
,
tools
,
disallowedTools
,
model
,
permissionMode
,
mcpServers
,
hooks
,
maxTurns
,
skills
,
initialPrompt
,
memory
,
effort
,
background
,
isolation
, and
color
. Use
prompt
for the system prompt, equivalent to the markdown body in file-based subagents.
Managed subagents
are deployed by organization administrators. Place markdown files in
.claude/agents/
inside the
managed settings directory
, using the same frontmatter format as project and user subagents. Managed definitions take precedence over project and user subagents with the same name.
Plugin subagents
come from
plugins
you’ve installed. They appear in
/agents
alongside your custom subagents. See the
plugin components reference
for details on creating plugin subagents.
For security reasons, plugin subagents do not support the
hooks
,
mcpServers
, or
permissionMode
frontmatter fields. These fields are ignored when loading agents from a plugin. If you need them, copy the agent file into
.claude/agents/
or
~/.claude/agents/
. You can also add rules to
permissions.allow
in
settings.json
or
settings.local.json
, but these rules apply to the entire session, not just the plugin subagent.
Subagent definitions from any of these scopes are also available to
agent teams
: when spawning a teammate, you can reference a subagent type and the teammate uses its
tools
and
model
, with the definition’s body appended to the teammate’s system prompt as additional instructions. See
agent teams
for which frontmatter fields apply on that path.
​
Write subagent files
Subagent files use YAML frontmatter for configuration, followed by the system prompt in Markdown:
Subagents are loaded at session start. If you add or edit a subagent file directly on disk, restart your session to load it. Subagents created through the
/agents
interface take effect immediately without a restart.
---
name
:
code-reviewer
description
:
Reviews code for quality and best practices
tools
:
Read, Glob, Grep
model
:
sonnet
---
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
The frontmatter defines the subagent’s metadata and configuration. The body becomes the system prompt that guides the subagent’s behavior. Subagents receive only this system prompt (plus basic environment details like working directory), not the full Claude Code system prompt.
A subagent starts in the main conversation’s current working directory. Within a subagent,
cd
commands do not persist between Bash or PowerShell tool calls and do not affect the main conversation’s working directory. To give the subagent an isolated copy of the repository instead, set
isolation: worktree
.
​
Supported frontmatter fields
The following fields can be used in the YAML frontmatter. Only
name
and
description
are required.
Field
Required
Description
name
Yes
Unique identifier using lowercase letters and hyphens.
Hooks
receive this value as
agent_type
. The filename does not have to match
description
Yes
When Claude should delegate to this subagent
tools
No
Tools
the subagent can use. Inherits all tools if omitted. To preload Skills into context, use the
skills
field rather than listing
Skill
here
disallowedTools
No
Tools to deny, removed from inherited or specified list
model
No
Model
to use:
sonnet
,
opus
,
haiku
, a full model ID (for example,
claude-opus-4-7
), or
inherit
. Defaults to
inherit
permissionMode
No
Permission mode
:
default
,
acceptEdits
,
auto
,
dontAsk
,
bypassPermissions
, or
plan
. Ignored for
plugin subagents
maxTurns
No
Maximum number of agentic turns before the subagent stops
skills
No
Skills
to preload into the subagent’s context at startup. The full skill content is injected, not just the description. Subagents can still invoke unlisted project, user, and plugin skills through the Skill tool
mcpServers
No
MCP servers
available to this subagent. Each entry is either a server name referencing an already-configured server (e.g.,
"slack"
) or an inline definition with the server name as key and a full
MCP server config
as value. Ignored for
plugin subagents
hooks
No
Lifecycle hooks
scoped to this subagent. Ignored for
plugin subagents
memory
No
Persistent memory scope
:
user
,
project
, or
local
. Enables cross-session learning
background
No
Set to
true
to always run this subagent as a
background task
. Default:
false
effort
No
Effort level when this subagent is active. Overrides the session effort level. Default: inherits from session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model
isolation
No
Set to
worktree
to run the subagent in a temporary
git worktree
, giving it an isolated copy of the repository. The worktree is automatically cleaned up if the subagent makes no changes
color
No
Display color for the subagent in the task list and transcript. Accepts
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
, or
cyan
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main session agent (via
--agent
or the
agent
setting).
Commands
and
skills
are processed. Prepended to any user-provided prompt
​
Choose a model
The
model
field controls which
AI model
the subagent uses:
Model alias
: Use one of the available aliases:
sonnet
,
opus
, or
haiku
Full model ID
: Use a full model ID such as
claude-opus-4-7
or
claude-sonnet-4-6
. Accepts the same values as the
--model
flag
inherit
: Use the same model as the main conversation
Omitted
: If not specified, defaults to
inherit
(uses the same model as the main conversation)
When Claude invokes a subagent, it can also pass a
model
parameter for that specific invocation. Claude Code resolves the subagent’s model in this order:
The
CLAUDE_CODE_SUBAGENT_MODEL
environment variable, if set
The per-invocation
model
parameter
The subagent definition’s
model
frontmatter
The main conversation’s model
​
Control subagent capabilities
You can control what subagents can do through tool access, permission modes, and conditional rules.
​
Available tools
Subagents can use any of Claude Code’s
internal tools
. By default, subagents inherit all tools from the main conversation, including MCP tools.
To restrict tools, use either the
tools
field (allowlist) or the
disallowedTools
field (denylist). This example uses
tools
to exclusively allow Read, Grep, Glob, and Bash. The subagent can’t edit files, write files, or use any MCP tools:
---
name
:
safe-researcher
description
:
Research agent with restricted capabilities
tools
:
Read, Grep, Glob, Bash
---
This example uses
disallowedTools
to inherit every tool from the main conversation except Write and Edit. The subagent keeps Bash, MCP tools, and everything else:
---
name
:
no-writes
description
:
Inherits every tool except file writes
disallowedTools
:
Write, Edit
---
If both are set,
disallowedTools
is applied first, then
tools
is resolved against the remaining pool. A tool listed in both is removed.
​
Restrict which subagents can be spawned
When an agent runs as the main thread with
claude --agent
, it can spawn subagents using the Agent tool. To restrict which subagent types it can spawn, use
Agent(agent_type)
syntax in the
tools
field.
In version 2.1.63, the Task tool was renamed to Agent. Existing
Task(...)
references in settings and agent definitions still work as aliases.
---
name
:
coordinator
description
:
Coordinates work across specialized agents
tools
:
Agent(worker, researcher), Read, Bash
---
This is an allowlist: only the
worker
and
researcher
subagents can be spawned. If the agent tries to spawn any other type, the request fails and the agent sees only the allowed types in its prompt. To block specific agents while allowing all others, use
permissions.deny
instead.
To allow spawning any subagent without restrictions, use
Agent
without parentheses:
tools
:
Agent, Read, Bash
If
Agent
is omitted from the
tools
list entirely, the agent cannot spawn any subagents. This restriction only applies to agents running as the main thread with
claude --agent
. Subagents cannot spawn other subagents, so
Agent(agent_type)
has no effect in subagent definitions.
​
Scope MCP servers to a subagent
Use the
mcpServers
field to give a subagent access to
MCP
servers that aren’t available in the main conversation. Inline servers defined here are connected when the subagent starts and disconnected when it finishes. String references share the parent session’s connection.
The
mcpServers
field applies in both contexts where an agent file can run:
As a subagent, spawned through the Agent tool or an @-mention
As the main session, launched with
--agent
or the
agent
setting
When the agent is the main session, inline server definitions connect at startup alongside servers from
.mcp.json
and settings files.
Each entry in the list is either an inline server definition or a string referencing an MCP server already configured in your session:
---
name
:
browser-tester
description
:
Tests features in a real browser using Playwright
mcpServers
:
# Inline definition: scoped to this subagent only
-
playwright
:
type
:
stdio
command
:
npx
args
: [
"-y"
,
"@playwright/mcp@latest"
]
# Reference by name: reuses an already-configured server
-
github
---
Use the Playwright tools to navigate, screenshot, and interact with pages.
Inline definitions use the same schema as
.mcp.json
server entries (
stdio
,
http
,
sse
,
ws
), keyed by the server name.
To keep an MCP server out of the main conversation entirely and avoid its tool descriptions consuming context there, define it inline here rather than in
.mcp.json
. The subagent gets the tools; the parent conversation does not.
​
Permission modes
The
permissionMode
field controls how the subagent handles permission prompts. Subagents inherit the permission context from the main conversation and can override the mode, except when the parent mode takes precedence as described below.
Mode
Behavior
default
Standard permission checking with prompts
acceptEdits
Auto-accept file edits and common filesystem commands for paths in the working directory or
additionalDirectories
auto
Auto mode
: a background classifier reviews commands and protected-directory writes
dontAsk
Auto-deny permission prompts (explicitly allowed tools still work)
bypassPermissions
Skip permission prompts
plan
Plan mode (read-only exploration)
Use
bypassPermissions
with caution. It skips all permission prompts, allowing the subagent to execute operations without approval, including writes to
.git
,
.claude
,
.vscode
,
.idea
, and
.husky
. Root and home directory removals such as
rm -rf /
still prompt as a circuit breaker. See
permission modes
for details.
If the parent uses
bypassPermissions
or
acceptEdits
, this takes precedence and cannot be overridden. If the parent uses
auto mode
, the subagent inherits auto mode and any
permissionMode
in its frontmatter is ignored: the classifier evaluates the subagent’s tool calls with the same block and allow rules as the parent session.
​
Preload skills into subagents
Use the
skills
field to inject skill content into a subagent’s context at startup. This gives the subagent domain knowledge without requiring it to discover and load skills during execution.
---
name
:
api-developer
description
:
Implement API endpoints following team conventions
skills
:
-
api-conventions
-
error-handling-patterns
---
Implement API endpoints. Follow the conventions and patterns from the preloaded skills.
The full content of each listed skill is injected into the subagent’s context at startup. This field controls which skills are preloaded, not which skills the subagent can access: without it, the subagent can still discover and invoke project, user, and plugin skills through the Skill tool during execution. To prevent a subagent from invoking skills entirely, omit
Skill
from the
tools
list or add it to
disallowedTools
.
You cannot preload skills that set
disable-model-invocation: true
, since preloading draws from the same set of skills Claude can invoke. If a listed skill is missing or disabled, Claude Code skips it and logs a warning to the debug log.
This is the inverse of
running a skill in a subagent
. With
skills
in a subagent, the subagent controls the system prompt and loads skill content. With
context: fork
in a skill, the skill content is injected into the agent you specify. Both use the same underlying system.
​
Enable persistent memory
The
memory
field gives the subagent a persistent directory that survives across conversations. The subagent uses this directory to build up knowledge over time, such as codebase patterns, debugging insights, and architectural decisions.
---
name
:
code-reviewer
description
:
Reviews code for quality and best practices
memory
:
user
---
You are a code reviewer. As you review code, update your agent memory with
patterns, conventions, and recurring issues you discover.
Choose a scope based on how broadly the memory should apply:
Scope
Location
Use when
user
~/.claude/agent-memory/<name-of-agent>/
the subagent should remember learnings across all projects
project
.claude/agent-memory/<name-of-agent>/
the subagent’s knowledge is project-specific and shareable via version control
local
.claude/agent-memory-local/<name-of-agent>/
the subagent’s knowledge is project-specific but should not be checked into version control
When memory is enabled:
The subagent’s system prompt includes instructions for reading and writing to the memory directory.
The subagent’s system prompt also includes the first 200 lines or 25KB of
MEMORY.md
in the memory directory, whichever comes first, with instructions to curate
MEMORY.md
if it exceeds that limit.
Read, Write, and Edit tools are automatically enabled so the subagent can manage its memory files.
Persistent memory tips
project
is the recommended default scope. It makes subagent knowledge shareable via version control. Use
user
when the subagent’s knowledge is broadly applicable across projects, or
local
when the knowledge should not be checked into version control.
Ask the subagent to consult its memory before starting work: “Review this PR, and check your memory for patterns you’ve seen before.”
Ask the subagent to update its memory after completing a task: “Now that you’re done, save what you learned to your memory.” Over time, this builds a knowledge base that makes the subagent more effective.
Include memory instructions directly in the subagent’s markdown file so it proactively maintains its own knowledge base:
Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.
​
Conditional rules with hooks
For more dynamic control over tool usage, use
PreToolUse
hooks to validate operations before they execute. This is useful when you need to allow some operations of a tool while blocking others.
This example creates a subagent that only allows read-only database queries. The
PreToolUse
hook runs the script specified in
command
before each Bash command executes:
---
name
:
db-reader
description
:
Execute read-only database queries
tools
:
Bash
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-readonly-query.sh"
---
Claude Code
passes hook input as JSON
via stdin to hook commands. The validation script reads this JSON, extracts the Bash command, and
exits with code 2
to block write operations:
#!/bin/bash
# ./scripts/validate-readonly-query.sh
INPUT
=
$(
cat
)
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command // empty'
)
# Block SQL write operations (case-insensitive)
if
echo
"
$COMMAND
"
|
grep
-iE
'\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE)\b'
>
/dev/null
;
then
echo
"Blocked: Only SELECT queries are allowed"
>&2
exit
2
fi
exit
0
See
Hook input
for the complete input schema and
exit codes
for how exit codes affect behavior. On Windows, write hook scripts in PowerShell and add
shell: powershell
to the hook entry as shown in
running hooks in PowerShell
.
​
Disable specific subagents
You can prevent Claude from using specific subagents by adding them to the
deny
array in your
settings
. Use the format
Agent(subagent-name)
where
subagent-name
matches the subagent’s name field.
{
"permissions"
: {
"deny"
: [
"Agent(Explore)"
,
"Agent(my-custom-agent)"
]
}
}
This works for both built-in and custom subagents. You can also use the
--disallowedTools
CLI flag:
claude
--disallowedTools
"Agent(Explore)"
See
Permissions documentation
for more details on permission rules.
​
Define hooks for subagents
Subagents can define
hooks
that run during the subagent’s lifecycle. There are two ways to configure hooks:
In the subagent’s frontmatter
: Define hooks that run only while that subagent is active
In
settings.json
: Define hooks that run in the main session when subagents start or stop
​
Hooks in subagent frontmatter
Define hooks directly in the subagent’s markdown file. These hooks only run while that specific subagent is active and are cleaned up when it finishes.
Frontmatter hooks fire when the agent is spawned as a subagent through the Agent tool or an @-mention, and when the agent runs as the main session via
--agent
or the
agent
setting. In the main-session case they run alongside any hooks defined in
settings.json
.
All
hook events
are supported. The most common events for subagents are:
Event
Matcher input
When it fires
PreToolUse
Tool name
Before the subagent uses a tool
PostToolUse
Tool name
After the subagent uses a tool
Stop
(none)
When the subagent finishes (converted to
SubagentStop
at runtime)
This example validates Bash commands with the
PreToolUse
hook and runs a linter after file edits with
PostToolUse
:
---
name
:
code-reviewer
description
:
Review code changes with automatic linting
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-command.sh $TOOL_INPUT"
PostToolUse
:
-
matcher
:
"Edit|Write"
hooks
:
-
type
:
command
command
:
"./scripts/run-linter.sh"
---
When the agent is invoked as a subagent,
Stop
hooks in frontmatter are automatically converted to
SubagentStop
events.
​
Project-level hooks for subagent events
Configure hooks in
settings.json
that respond to subagent lifecycle events in the main session.
Event
Matcher input
When it fires
SubagentStart
Agent type name
When a subagent begins execution
SubagentStop
Agent type name
When a subagent completes
Both events support matchers to target specific agent types by name. This example runs a setup script only when the
db-agent
subagent starts, and a cleanup script when any subagent stops:
{
"hooks"
: {
"SubagentStart"
: [
{
"matcher"
:
"db-agent"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"./scripts/setup-db-connection.sh"
}
]
}
],
"SubagentStop"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"./scripts/cleanup-db-connection.sh"
}
]
}
]
}
}
See
Hooks
for the complete hook configuration format.
​
Work with subagents
​
Understand automatic delegation
Claude automatically delegates tasks based on the task description in your request, the
description
field in subagent configurations, and current context. To encourage proactive delegation, include phrases like “use proactively” in your subagent’s description field.
​
Invoke subagents explicitly
When automatic delegation isn’t enough, you can request a subagent yourself. Three patterns escalate from a one-off suggestion to a session-wide default:
Natural language
: name the subagent in your prompt; Claude decides whether to delegate
@-mention
: guarantees the subagent runs for one task
Session-wide
: the whole session uses that subagent’s system prompt, tool restrictions, and model via the
--agent
flag or the
agent
setting
For natural language, there’s no special syntax. Name the subagent and Claude typically delegates:
Use the test-runner subagent to fix failing tests
Have the code-reviewer subagent look at my recent changes
@-mention the subagent.
Type
@
and pick the subagent from the typeahead, the same way you @-mention files. This ensures that specific subagent runs rather than leaving the choice to Claude:
@"code-reviewer (agent)" look at the auth changes
Your full message still goes to Claude, which writes the subagent’s task prompt based on what you asked. The @-mention controls which subagent Claude invokes, not what prompt it receives.
Subagents provided by an enabled
plugin
appear in the typeahead under their scoped name, such as
my-plugin:code-reviewer
or
my-plugin:review:security
when the plugin
organizes agents into subfolders
. Named background subagents currently running in the session also appear in the typeahead, showing their status next to the name. You can also type the mention manually without using the picker:
@agent-<name>
for local subagents, or
@agent-
followed by the scoped name for plugin subagents, for example
@agent-my-plugin:code-reviewer
.
Run the whole session as a subagent.
Pass
--agent <name>
to start a session where the main thread itself takes on that subagent’s system prompt, tool restrictions, and model:
claude
--agent
code-reviewer
The subagent’s system prompt replaces the default Claude Code system prompt entirely, the same way
--system-prompt
does.
CLAUDE.md
files and project memory still load through the normal message flow. The agent name appears as
@<name>
in the startup header so you can confirm it’s active.
This works with built-in and custom subagents, and the choice persists when you resume the session.
For a plugin-provided subagent, pass the scoped name:
claude --agent <plugin-name>:<agent-name>
. If the plugin places the agent in a subfolder of its
agents/
directory, include the subfolder in the scoped name, for example
claude --agent my-plugin:review:security
.
To make it the default for every session in a project, set
agent
in
.claude/settings.json
:
{
"agent"
:
"code-reviewer"
}
The CLI flag overrides the setting if both are present.
​
Run subagents in foreground or background
Subagents can run in the foreground (blocking) or background (concurrent):
Foreground subagents
block the main conversation until complete. Permission prompts are passed through to you as they come up.
Background subagents
run concurrently while you continue working. They run with the permissions already granted in the session and auto-deny any tool call that would otherwise prompt. If a background subagent needs to ask clarifying questions, that tool call fails but the subagent continues.
If a background subagent fails due to missing permissions, you can start a new foreground subagent with the same task to retry with interactive prompts.
Claude decides whether to run subagents in the foreground or background based on the task. You can also:
Ask Claude to “run this in the background”
Press
Ctrl+B
to background a running task
To disable all background task functionality, set the
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
environment variable to
1
. See
Environment variables
.
When
fork mode
is enabled, every subagent spawn runs in the background regardless of the
background
field. Forks still surface permission prompts in your terminal as they occur; named subagents auto-deny anything that would prompt, as described above.
​
Common patterns
​
Isolate high-volume operations
One of the most effective uses for subagents is isolating operations that produce large amounts of output. Running tests, fetching documentation, or processing log files can consume significant context. By delegating these to a subagent, the verbose output stays in the subagent’s context while only the relevant summary returns to your main conversation.
Use a subagent to run the test suite and report only the failing tests with their error messages
​
Run parallel research
For independent investigations, spawn multiple subagents to work simultaneously:
Research the authentication, database, and API modules in parallel using separate subagents
Each subagent explores its area independently, then Claude synthesizes the findings. This works best when the research paths don’t depend on each other.
When subagents complete, their results return to your main conversation. Running many subagents that each return detailed results can consume significant context.
For tasks that need sustained parallelism or exceed your context window,
agent teams
give each worker its own independent context.
​
Chain subagents
For multi-step workflows, ask Claude to use subagents in sequence. Each subagent completes its task and returns results to Claude, which then passes relevant context to the next subagent.
Use the code-reviewer subagent to find performance issues, then use the optimizer subagent to fix them
​
Choose between subagents and main conversation
Use the
main conversation
when:
The task needs frequent back-and-forth or iterative refinement
Multiple phases share significant context (planning → implementation → testing)
You’re making a quick, targeted change
Latency matters. Subagents start fresh and may need time to gather context
Use
subagents
when:
The task produces verbose output you don’t need in your main context
You want to enforce specific tool restrictions or permissions
The work is self-contained and can return a summary
Consider
Skills
instead when you want reusable prompts or workflows that run in the main conversation context rather than isolated subagent context.
For a quick question about something already in your conversation, use
/btw
instead of a subagent. It sees your full context but has no tool access, and the answer is discarded rather than added to history.
Subagents cannot spawn other subagents. If your workflow requires nested delegation, use
Skills
or
chain subagents
from the main conversation.
​
Manage subagent context
​
Resume subagents
Each subagent invocation creates a new instance with fresh context. To continue an existing subagent’s work instead of starting over, ask Claude to resume it.
Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.
When a subagent completes, Claude receives its agent ID. Claude uses the
SendMessage
tool with the agent’s ID as the
to
field to resume it. The
SendMessage
tool is only available when
agent teams
are enabled via
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
.
To resume a subagent, ask Claude to continue the previous work:
Use the code-reviewer subagent to review the authentication module
[Agent completes]
Continue that code review and now analyze the authorization logic
[Claude resumes the subagent with full context from previous conversation]
If a stopped subagent receives a
SendMessage
, it auto-resumes in the background without requiring a new
Agent
invocation.
You can also ask Claude for the agent ID if you want to reference it explicitly, or find IDs in the transcript files at
~/.claude/projects/{project}/{sessionId}/subagents/
. Each transcript is stored as
agent-{agentId}.jsonl
.
Subagent transcripts persist independently of the main conversation:
Main conversation compaction
: When the main conversation compacts, subagent transcripts are unaffected. They’re stored in separate files.
Session persistence
: Subagent transcripts persist within their session. You can
resume a subagent
after restarting Claude Code by resuming the same session.
Automatic cleanup
: Transcripts are cleaned up based on the
cleanupPeriodDays
setting (default: 30 days).
​
Auto-compaction
Subagents support automatic compaction using the same logic as the main conversation. By default, auto-compaction triggers at approximately 95% capacity. To trigger compaction earlier, set
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
to a lower percentage (for example,
50
). See
environment variables
for details.
Compaction events are logged in subagent transcript files:
{
"type"
:
"system"
,
"subtype"
:
"compact_boundary"
,
"compactMetadata"
: {
"trigger"
:
"auto"
,
"preTokens"
:
167189
}
}
The
preTokens
value shows how many tokens were used before compaction occurred.
​
Fork the current conversation
Forked subagents are experimental and require Claude Code v2.1.117 or later. Behavior and configuration may change in future releases. Enable them by setting the
CLAUDE_CODE_FORK_SUBAGENT
environment variable to
1
. The variable is honored in interactive mode and via the SDK or
claude -p
.
A fork is a subagent that inherits the entire conversation so far instead of starting fresh. This drops the input isolation that subagents otherwise provide: a fork sees the same system prompt, tools, model, and message history as the main session, so you can hand it a side task without re-explaining the situation. The fork’s own tool calls still stay out of your conversation and only its final result comes back, so your main context window stays clean. Use a fork when a named subagent would need too much background to be useful, or when you want to try several approaches in parallel from the same starting point.
Enabling fork mode changes Claude Code in three ways:
Claude spawns a fork whenever it would otherwise use the
general-purpose
subagent. Named subagents such as Explore still spawn as before.
Every subagent spawn runs in the
background
, whether it is a fork or a named subagent. Set
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
to
1
to keep spawns synchronous.
The
/fork
command spawns a fork instead of acting as an alias for
/branch
.
You can start a fork yourself with
/fork
followed by a directive. Claude Code names the fork from the first words of the directive. The following example forks the conversation to draft test cases while you continue with the implementation in the main session:
/fork draft unit tests for the parser changes so far
The fork appears in a panel below your prompt and runs in the background while you keep working. When it finishes, its result arrives as a message in your main conversation. The next section covers the panel controls for watching and steering forks while they run.
​
Observe and steer running forks
Running forks appear in a panel below the prompt input, with one row for the main session and one for each fork. Use these keys to interact with the panel:
Key
Action
↑
/
↓
Move between rows
Enter
Open the selected fork’s transcript and send it follow-up messages
x
Dismiss a finished fork or stop a running one
Esc
Return focus to the prompt input
​
How forks differ from named subagents
A fork inherits everything the main session has at the moment it spawns. A named subagent starts from its own definition.
Fork
Named subagent
Context
Full conversation history
Fresh context with the prompt you pass
System prompt and tools
Same as main session
From the subagent’s
definition file
Model
Same as main session
From the subagent’s
model
field
Permissions
Prompts surface in your terminal
Auto-denied
when running in the background
Prompt cache
Shared with main session
Separate cache
Because a fork’s system prompt and tool definitions are identical to the parent, its first request reuses the parent’s prompt cache. This makes forking cheaper than spawning a fresh subagent for tasks that need the same context.
When Claude spawns a fork through the Agent tool, it can pass
isolation: "worktree"
so the fork’s file edits are written to a separate git worktree instead of your checkout.
​
Limitations
Setting
CLAUDE_CODE_FORK_SUBAGENT=1
enables fork mode in interactive sessions,
non-interactive mode
, and the Agent SDK. A fork cannot spawn further forks.
​
Example subagents
These examples demonstrate effective patterns for building subagents. Use them as starting points, or generate a customized version with Claude.
Best practices:
Design focused subagents:
each subagent should excel at one specific task
Write detailed descriptions:
Claude uses the description to decide when to delegate
Limit tool access:
grant only necessary permissions for security and focus
Check into version control:
share project subagents with your team
​
Code reviewer
A read-only subagent that reviews code without modifying it. This example shows how to design a focused subagent with limited tool access (no Edit or Write) and a detailed prompt that specifies exactly what to look for and how to format output.
---
name
:
code-reviewer
description
:
Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools
:
Read, Grep, Glob, Bash
model
:
inherit
---
You are a senior code reviewer ensuring high standards of code quality and security.
When invoked:
1.
Run git diff to see recent changes
2.
Focus on modified files
3.
Begin review immediately
Review checklist:
-
Code is clear and readable
-
Functions and variables are well-named
-
No duplicated code
-
Proper error handling
-
No exposed secrets or API keys
-
Input validation implemented
-
Good test coverage
-
Performance considerations addressed
Provide feedback organized by priority:
-
Critical issues (must fix)
-
Warnings (should fix)
-
Suggestions (consider improving)
Include specific examples of how to fix issues.
​
Debugger
A subagent that can both analyze and fix issues. Unlike the code reviewer, this one includes Edit because fixing bugs requires modifying code. The prompt provides a clear workflow from diagnosis to verification.
---
name
:
debugger
description
:
Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
tools
:
Read, Edit, Bash, Grep, Glob
---
You are an expert debugger specializing in root cause analysis.
When invoked:
1.
Capture error message and stack trace
2.
Identify reproduction steps
3.
Isolate the failure location
4.
Implement minimal fix
5.
Verify solution works
Debugging process:
-
Analyze error messages and logs
-
Check recent code changes
-
Form and test hypotheses
-
Add strategic debug logging
-
Inspect variable states
For each issue, provide:
-
Root cause explanation
-
Evidence supporting the diagnosis
-
Specific code fix
-
Testing approach
-
Prevention recommendations
Focus on fixing the underlying issue, not the symptoms.
​
Data scientist
A domain-specific subagent for data analysis work. This example shows how to create subagents for specialized workflows outside of typical coding tasks. It explicitly sets
model: sonnet
for more capable analysis.
---
name
:
data-scientist
description
:
Data analysis expert for SQL queries, BigQuery operations, and data insights. Use proactively for data analysis tasks and queries.
tools
:
Bash, Read, Write
model
:
sonnet
---
You are a data scientist specializing in SQL and BigQuery analysis.
When invoked:
1.
Understand the data analysis requirement
2.
Write efficient SQL queries
3.
Use BigQuery command line tools (bq) when appropriate
4.
Analyze and summarize results
5.
Present findings clearly
Key practices:
-
Write optimized SQL queries with proper filters
-
Use appropriate aggregations and joins
-
Include comments explaining complex logic
-
Format results for readability
-
Provide data-driven recommendations
For each analysis:
-
Explain the query approach
-
Document any assumptions
-
Highlight key findings
-
Suggest next steps based on data
Always ensure queries are efficient and cost-effective.
​
Database query validator
A subagent that allows Bash access but validates commands to permit only read-only SQL queries. This example shows how to use
PreToolUse
hooks for conditional validation when you need finer control than the
tools
field provides.
---
name
:
db-reader
description
:
Execute read-only database queries. Use when analyzing data or generating reports.
tools
:
Bash
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/validate-readonly-query.sh"
---
You are a database analyst with read-only access. Execute SELECT queries to answer questions about the data.
When asked to analyze data:
1.
Identify which tables contain the relevant data
2.
Write efficient SELECT queries with appropriate filters
3.
Present results clearly with context
You cannot modify data. If asked to INSERT, UPDATE, DELETE, or modify schema, explain that you only have read access.
Claude Code
passes hook input as JSON
via stdin to hook commands. The validation script reads this JSON, extracts the command being executed, and checks it against a list of SQL write operations. If a write operation is detected, the script
exits with code 2
to block execution and returns an error message to Claude via stderr.
Create the validation script anywhere in your project. The path must match the
command
field in your hook configuration:
#!/bin/bash
# Blocks SQL write operations, allows SELECT queries
# Read JSON input from stdin
INPUT
=
$(
cat
)
# Extract the command field from tool_input using jq
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command // empty'
)
if
[
-z
"
$COMMAND
"
];
then
exit
0
fi
# Block write operations (case-insensitive)
if
echo
"
$COMMAND
"
|
grep
-iE
'\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE|REPLACE|MERGE)\b'
>
/dev/null
;
then
echo
"Blocked: Write operations not allowed. Use SELECT queries only."
>&2
exit
2
fi
exit
0
On macOS and Linux, make the script executable:
chmod
+x
./scripts/validate-readonly-query.sh
On Windows, write the validation script in PowerShell and add
shell: powershell
to the hook entry. See
running hooks in PowerShell
.
The hook receives JSON via stdin with the Bash command in
tool_input.command
. Exit code 2 blocks the operation and feeds the error message back to Claude. See
Hooks
for details on exit codes and
Hook input
for the complete input schema.
​
Next steps
Now that you understand subagents, explore these related features:
Distribute subagents with plugins
to share subagents across teams or projects
Run Claude Code programmatically
with the Agent SDK for CI/CD and automation
Use MCP servers
to give subagents access to external tools and data
Was this page helpful?
Yes
No
Overview
Agent view
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/sub-agents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Troubleshooting</title>
  <link>https://code.claude.com/docs/en/troubleshooting</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/troubleshooting</guid>
  <pubDate>Tue, 06 Aug 2024 00:00:00 +0000</pubDate>
  <category>Troubleshooting</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshooting
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troub...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshooting
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers performance, stability, and search problems once Claude Code is running. For other issues, start with the page that matches where you’re stuck:
Symptom
Go to
command not found
, install fails, PATH issues,
EACCES
, TLS errors
Troubleshoot installation and login
Login loops, OAuth errors,
403 Forbidden
, “organization disabled”, Bedrock/Vertex/Foundry credentials
Troubleshoot installation and login
Settings not applying, hooks not firing, MCP servers not loading
Debug your configuration
API Error: 5xx
,
529 Overloaded
,
429
, request validation errors
Error reference
model not found
or
you may not have access to it
Error reference
VS Code extension not connecting or detecting Claude
VS Code integration
JetBrains plugin or IDE not detected
JetBrains integration
High CPU or memory, slow responses, hangs, search not finding files
Performance and stability
below
If you’re not sure which applies, run
/doctor
inside Claude Code for an automated check of your installation, settings, MCP servers, and context usage. If
claude
won’t start at all, run
claude doctor
from your shell instead.
​
Performance and stability
These sections cover issues related to resource usage, responsiveness, and search behavior.
​
High CPU or memory usage
Claude Code is designed to work with most development environments, but may consume significant resources when processing large codebases. If you’re experiencing performance issues:
Use
/compact
regularly to reduce context size
Close and restart Claude Code between major tasks
Consider adding large build directories to your
.gitignore
file
If memory usage stays high after these steps, run
/heapdump
to write a JavaScript heap snapshot and a memory breakdown to
~/Desktop
. On Linux without a Desktop folder, the files are written to your home directory.
The breakdown shows resident set size, JS heap, array buffers, and unaccounted native memory, which helps identify whether the growth is in JavaScript objects or in native code. To inspect retainers, open the
.heapsnapshot
file in Chrome DevTools under Memory → Load. Attach both files when reporting a memory issue on
GitHub
.
​
Auto-compaction stops with a thrashing error
If you see
Autocompact is thrashing: the context refilled to the limit...
, automatic compaction succeeded but a file or tool output immediately refilled the context window several times in a row. Claude Code stops retrying to avoid wasting API calls on a loop that isn’t making progress.
To recover:
Ask Claude to read the oversized file in smaller chunks, such as a specific line range or function, instead of the whole file
Run
/compact
with a focus that drops the large output, for example
/compact keep only the plan and the diff
Move the large-file work to a
subagent
so it runs in a separate context window
Run
/clear
if the earlier conversation is no longer needed
​
Command hangs or freezes
If Claude Code seems unresponsive:
Press Ctrl+C to attempt to cancel the current operation
If unresponsive, you may need to close the terminal and restart
Restarting doesn’t lose your conversation. Run
claude --resume
in the same directory to pick the session back up.
​
Search and discovery issues
If the Search tool,
@file
mentions, custom agents, or custom skills aren’t finding files, the bundled
ripgrep
binary may not run on your system. Install your platform’s
ripgrep
package and tell Claude Code to use it instead:
macOS
Ubuntu/Debian
Alpine
Arch
Windows
brew
install
ripgrep
sudo
apt
install
ripgrep
apk
add
ripgrep
pacman
-S
ripgrep
winget install BurntSushi.ripgrep.MSVC
Then set
USE_BUILTIN_RIPGREP=0
in your
environment
.
​
Slow or incomplete search results on WSL
Disk read performance penalties when
working across file systems on WSL
may result in fewer-than-expected matches when using Claude Code on WSL. Search still functions, but returns fewer results than on a native filesystem.
/doctor
will show Search as OK in this case.
Solutions:
Submit more specific searches
: reduce the number of files searched by specifying directories or file types: “Search for JWT validation logic in the auth-service package” or “Find use of md5 hash in JS files”.
Move project to Linux filesystem
: if possible, ensure your project is located on the Linux filesystem (
/home/
) rather than the Windows filesystem (
/mnt/c/
).
Use native Windows instead
: consider running Claude Code natively on Windows instead of through WSL, for better file system performance.
​
Get more help
If you’re experiencing issues not covered here:
Run
/doctor
to check installation health, settings validity, MCP configuration, and context usage in one pass
Use the
/feedback
command within Claude Code to report problems directly to Anthropic
Check the
GitHub repository
for known issues
Ask Claude directly about its capabilities and features. Claude has built-in access to its documentation.
Was this page helpful?
Yes
No
Troubleshoot installation and login
Debug configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/troubleshooting" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshooting
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troub...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshooting
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers performance, stability, and search problems once Claude Code is running. For other issues, start with the page that matches where you’re stuck:
Symptom
Go to
command not found
, install fails, PATH issues,
EACCES
, TLS errors
Troubleshoot installation and login
Login loops, OAuth errors,
403 Forbidden
, “organization disabled”, Bedrock/Vertex/Foundry credentials
Troubleshoot installation and login
Settings not applying, hooks not firing, MCP servers not loading
Debug your configuration
API Error: 5xx
,
529 Overloaded
,
429
, request validation errors
Error reference
model not found
or
you may not have access to it
Error reference
VS Code extension not connecting or detecting Claude
VS Code integration
JetBrains plugin or IDE not detected
JetBrains integration
High CPU or memory, slow responses, hangs, search not finding files
Performance and stability
below
If you’re not sure which applies, run
/doctor
inside Claude Code for an automated check of your installation, settings, MCP servers, and context usage. If
claude
won’t start at all, run
claude doctor
from your shell instead.
​
Performance and stability
These sections cover issues related to resource usage, responsiveness, and search behavior.
​
High CPU or memory usage
Claude Code is designed to work with most development environments, but may consume significant resources when processing large codebases. If you’re experiencing performance issues:
Use
/compact
regularly to reduce context size
Close and restart Claude Code between major tasks
Consider adding large build directories to your
.gitignore
file
If memory usage stays high after these steps, run
/heapdump
to write a JavaScript heap snapshot and a memory breakdown to
~/Desktop
. On Linux without a Desktop folder, the files are written to your home directory.
The breakdown shows resident set size, JS heap, array buffers, and unaccounted native memory, which helps identify whether the growth is in JavaScript objects or in native code. To inspect retainers, open the
.heapsnapshot
file in Chrome DevTools under Memory → Load. Attach both files when reporting a memory issue on
GitHub
.
​
Auto-compaction stops with a thrashing error
If you see
Autocompact is thrashing: the context refilled to the limit...
, automatic compaction succeeded but a file or tool output immediately refilled the context window several times in a row. Claude Code stops retrying to avoid wasting API calls on a loop that isn’t making progress.
To recover:
Ask Claude to read the oversized file in smaller chunks, such as a specific line range or function, instead of the whole file
Run
/compact
with a focus that drops the large output, for example
/compact keep only the plan and the diff
Move the large-file work to a
subagent
so it runs in a separate context window
Run
/clear
if the earlier conversation is no longer needed
​
Command hangs or freezes
If Claude Code seems unresponsive:
Press Ctrl+C to attempt to cancel the current operation
If unresponsive, you may need to close the terminal and restart
Restarting doesn’t lose your conversation. Run
claude --resume
in the same directory to pick the session back up.
​
Search and discovery issues
If the Search tool,
@file
mentions, custom agents, or custom skills aren’t finding files, the bundled
ripgrep
binary may not run on your system. Install your platform’s
ripgrep
package and tell Claude Code to use it instead:
macOS
Ubuntu/Debian
Alpine
Arch
Windows
brew
install
ripgrep
sudo
apt
install
ripgrep
apk
add
ripgrep
pacman
-S
ripgrep
winget install BurntSushi.ripgrep.MSVC
Then set
USE_BUILTIN_RIPGREP=0
in your
environment
.
​
Slow or incomplete search results on WSL
Disk read performance penalties when
working across file systems on WSL
may result in fewer-than-expected matches when using Claude Code on WSL. Search still functions, but returns fewer results than on a native filesystem.
/doctor
will show Search as OK in this case.
Solutions:
Submit more specific searches
: reduce the number of files searched by specifying directories or file types: “Search for JWT validation logic in the auth-service package” or “Find use of md5 hash in JS files”.
Move project to Linux filesystem
: if possible, ensure your project is located on the Linux filesystem (
/home/
) rather than the Windows filesystem (
/mnt/c/
).
Use native Windows instead
: consider running Claude Code natively on Windows instead of through WSL, for better file system performance.
​
Get more help
If you’re experiencing issues not covered here:
Run
/doctor
to check installation health, settings validity, MCP configuration, and context usage in one pass
Use the
/feedback
command within Claude Code to report problems directly to Anthropic
Check the
GitHub repository
for known issues
Ask Claude directly about its capabilities and features. Claude has built-in access to its documentation.
Was this page helpful?
Yes
No
Troubleshoot installation and login
Debug configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/troubleshooting" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Extend Claude Code</title>
  <link>https://code.claude.com/docs/en/features-overview</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/features-overview</guid>
  <pubDate>Mon, 29 Jul 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Extend Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer us...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Extend Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code combines a model that reasons about your code with
built-in tools
for file operations, search, execution, and web access. The built-in tools cover most coding tasks. This guide covers the extension layer: features you add to customize what Claude knows, connect it to external services, and automate workflows.
For how the core agentic loop works, see
How Claude Code works
.
New to Claude Code?
Start with
CLAUDE.md
for project conventions, then add other extensions
as specific triggers come up
.
​
Overview
Extensions plug into different parts of the agentic loop:
CLAUDE.md
adds persistent context Claude sees every session
Skills
add reusable knowledge and invocable workflows
MCP
connects Claude to external services and tools
Subagents
run their own loops in isolated context, returning summaries
Agent teams
coordinate multiple independent sessions with shared tasks and peer-to-peer messaging
Hooks
fire on lifecycle events and can run a script, HTTP request, prompt, or subagent
Plugins
and
marketplaces
package and distribute these features
Skills
are the most flexible extension. A skill is a markdown file containing knowledge, workflows, or instructions. You can invoke skills with a command like
/deploy
, or Claude can load them automatically when relevant. Skills can run in your current conversation or in an isolated context via subagents.
​
Match features to your goal
Features range from always-on context that Claude sees every session, to on-demand capabilities you or Claude can invoke, to background automation that runs on specific events. The table below shows what’s available and when each one makes sense.
Feature
What it does
When to use it
Example
CLAUDE.md
Persistent context loaded every conversation
Project conventions, “always do X” rules
”Use pnpm, not npm. Run tests before committing.”
Skill
Instructions, knowledge, and workflows Claude can use
Reusable content, reference docs, repeatable tasks
/deploy
runs your deployment checklist; API docs skill with endpoint patterns
Subagent
Isolated execution context that returns summarized results
Context isolation, parallel tasks, specialized workers
Research task that reads many files but returns only key findings
Agent teams
Coordinate multiple independent Claude Code sessions
Parallel research, new feature development, debugging with competing hypotheses
Spawn reviewers to check security, performance, and tests simultaneously
MCP
Connect to external services
External data or actions
Query your database, post to Slack, control a browser
Hook
Script, HTTP request, prompt, or subagent triggered by events
Automation that must run on every matching event
Run ESLint after every file edit
Plugins
are the packaging layer. A plugin bundles skills, hooks, subagents, and MCP servers into a single installable unit. Plugin skills are namespaced (like
/my-plugin:review
) so multiple plugins can coexist. Use plugins when you want to reuse the same setup across multiple repositories or distribute to others via a
marketplace
.
​
Build your setup over time
You don’t need to configure everything up front. Each feature has a recognizable trigger, and most teams add them in roughly this order:
Trigger
Add
Claude gets a convention or command wrong twice
Add it to
CLAUDE.md
You keep typing the same prompt to start a task
Save it as a user-invocable
skill
You paste the same playbook or multi-step procedure into chat for the third time
Capture it as a
skill
You keep copying data from a browser tab Claude can’t see
Connect that system as an
MCP server
A side task floods your conversation with output you won’t reference again
Route it through a
subagent
You want something to happen every time without asking
Write a
hook
A second repository needs the same setup
Package it as a
plugin
The same triggers tell you when to update what you already have. A repeated mistake or a recurring review comment is a CLAUDE.md edit, not a one-off correction in chat. A workflow you keep tweaking by hand is a skill that needs another revision.
​
Compare similar features
Some features can seem similar. Here’s how to tell them apart.
Skill vs Subagent
CLAUDE.md vs Skill
CLAUDE.md vs Rules vs Skills
Subagent vs Agent team
MCP vs Skill
Hook vs Skill
Skills and subagents solve different problems:
Skills
are reusable content you can load into any context
Subagents
are isolated workers that run separately from your main conversation
Aspect
Skill
Subagent
What it is
Reusable instructions, knowledge, or workflows
Isolated worker with its own context
Key benefit
Share content across contexts
Context isolation. Work happens separately, only summary returns
Context window
impact
Adds to your main window
Uses a separate window with its own input and output tokens
Best for
Reference material, invocable workflows
Tasks that read many files, parallel work, specialized workers
Skills can be reference or action.
Reference skills provide knowledge Claude uses throughout your session (like your API style guide). Action skills tell Claude to do something specific (like
/deploy
that runs your deployment workflow).
Use a subagent
when you need context isolation or when your context window is getting full. The subagent might read dozens of files or run extensive searches, but your main conversation only receives a summary. Since subagent work doesn’t consume your main context, this is also useful when you don’t need the intermediate work to remain visible. Custom subagents can have their own instructions and can preload skills.
They can combine.
A subagent can preload specific skills (
skills:
field). A skill can run in isolated context using
context: fork
. See
Skills
for details.
Both store instructions, but they load differently and serve different purposes.
Aspect
CLAUDE.md
Skill
Loads
Every session, automatically
On demand
Can include files
Yes, with
@path
imports
Yes, with
@path
imports
Can trigger workflows
No
Yes, with
/<name>
Best for
”Always do X” rules
Reference material, invocable workflows
Put it in CLAUDE.md
if Claude should always know it: coding conventions, build commands, project structure, “never do X” rules.
Put it in a skill
if it’s reference material Claude needs sometimes (API docs, style guides) or a workflow you trigger with
/<name>
(deploy, review, release).
Rule of thumb:
Keep CLAUDE.md under 200 lines. If it’s growing, move reference content to skills or split into
.claude/rules/
files.
All three store instructions, but they load differently:
Aspect
CLAUDE.md
.claude/rules/
Skill
Loads
Every session
Every session, or when matching files are opened
On demand, when invoked or relevant
Scope
Whole project
Can be scoped to file paths
Task-specific
Best for
Core conventions and build commands
Language-specific or directory-specific guidelines
Reference material, repeatable workflows
Use CLAUDE.md
for instructions every session needs: build commands, test conventions, project architecture.
Use rules
to keep CLAUDE.md focused. Rules with
paths
frontmatter
only load when Claude works with matching files, saving context.
Use skills
for content Claude only needs sometimes, like API documentation or a deployment checklist you trigger with
/<name>
.
Both parallelize work, but they’re architecturally different:
Subagents
run inside your session and report results back to your main context
Agent teams
are independent Claude Code sessions that communicate with each other
Aspect
Subagent
Agent team
Context
Own context window; results return to the caller
Own context window; fully independent
Communication
Reports results back to the main agent only
Teammates message each other directly
Coordination
Main agent manages all work
Shared task list with self-coordination
Best for
Focused tasks where only the result matters
Complex work requiring discussion and collaboration
Token cost
Lower: results summarized back to main context
Higher: each teammate is a separate Claude instance
Use a subagent
when you need a quick, focused worker: research a question, verify a claim, review a file. The subagent does the work and returns a summary. Your main conversation stays clean.
Use an agent team
when teammates need to share findings, challenge each other, and coordinate independently. Agent teams are best for research with competing hypotheses, parallel code review, and new feature development where each teammate owns a separate piece.
Transition point:
If you’re running parallel subagents but hitting context limits, or if your subagents need to communicate with each other, agent teams are the natural next step.
Agent teams are experimental and disabled by default. See
agent teams
for setup and current limitations.
MCP connects Claude to external services. Skills extend what Claude knows, including how to use those services effectively.
Aspect
MCP
Skill
What it is
Protocol for connecting to external services
Knowledge, workflows, and reference material
Provides
Tools and data access
Knowledge, workflows, reference material
Examples
Slack integration, database queries, browser control
Code review checklist, deploy workflow, API style guide
These solve different problems and work well together:
MCP
gives Claude the ability to interact with external systems. Without MCP, Claude can’t query your database or post to Slack.
Skills
give Claude knowledge about how to use those tools effectively, plus workflows you can trigger with
/<name>
. A skill might include your team’s database schema and query patterns, or a
/post-to-slack
workflow with your team’s message formatting rules.
Example: An MCP server connects Claude to your database. A skill teaches Claude your data model, common query patterns, and which tables to use for different tasks.
A hook fires on a lifecycle event; a skill is loaded into context for Claude to apply.
Aspect
Hook
Skill
Runs
A shell command, HTTP request, LLM prompt, or subagent
Instructions Claude reads and follows
Triggered by
Lifecycle events
such as
PostToolUse
or
SessionStart
You typing
/<name>
, or Claude matching the description to your task
Determinism
Always fires on its event; the trigger is guaranteed
Claude interprets the instructions; outcome can vary
Context cost
Zero unless the hook returns output
Description loads each session; full content loads when used
Best for
Linting after edits, blocking unsafe commands, logging, notifications
Workflows that need reasoning, reference material, multi-step tasks
Use a hook
when the action must happen the same way every time and doesn’t need Claude to think. For example: format on save, reject
rm -rf /
, post a Slack message when a session ends.
Use a skill
when Claude should decide how to apply the steps, or when the content is knowledge rather than a script. For example: a
/release
checklist, your API style guide, a debugging playbook.
Put guardrails in hooks.
An instruction like “never edit
.env
” in CLAUDE.md or a skill is a request, not a guarantee. A
PreToolUse
hook that blocks the edit is enforcement. If a rule must hold every time, make it a hook rather than a prompt instruction.
Hook output lands in context.
A
PostToolUse
hook that runs your linter feeds results back as text Claude reads; a
/fix-lint
skill tells Claude how to resolve them.
​
Understand how features layer
Features can be defined at multiple levels: user-wide, per-project, via plugins, or through managed policies. You can also nest CLAUDE.md files in subdirectories or place skills in specific packages of a monorepo. When the same feature exists at multiple levels, here’s how they layer:
CLAUDE.md files
are additive: all levels contribute content to Claude’s context simultaneously. Files from your working directory and above load at launch; subdirectories load as you work in them. When instructions conflict, Claude uses judgment to reconcile them, with more specific instructions typically taking precedence. See
how CLAUDE.md files load
.
Skills and subagents
override by name: when the same name exists at multiple levels, one definition wins based on priority (managed > user > project for skills; managed > CLI flag > project > user > plugin for subagents). Plugin skills are
namespaced
to avoid conflicts. See
skill discovery
and
subagent scope
.
MCP servers
override by name: local > project > user. See
MCP scope
.
Hooks
merge: all registered hooks fire for their matching events regardless of source. See
hooks
.
​
Combine features
Each extension solves a different problem: CLAUDE.md handles always-on context, skills handle on-demand knowledge and workflows, MCP handles external connections, subagents handle isolation, and hooks handle automation. Real setups combine them based on your workflow.
For example, you might use CLAUDE.md for project conventions, a skill for your deployment workflow, MCP to connect to your database, and a hook to run linting after every edit. Each feature handles what it’s best at.
Pattern
How it works
Example
Skill + MCP
MCP provides the connection; a skill teaches Claude how to use it well
MCP connects to your database, a skill documents your schema and query patterns
Skill + Subagent
A skill spawns subagents for parallel work
/audit
skill kicks off security, performance, and style subagents that work in isolated context
CLAUDE.md + Skills
CLAUDE.md holds always-on rules; skills hold reference material loaded on demand
CLAUDE.md says “follow our API conventions,” a skill contains the full API style guide
Hook + MCP
A hook triggers external actions through MCP
Post-edit hook sends a Slack notification when Claude modifies critical files
​
Understand context costs
Every feature you add consumes some of Claude’s context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup. For an interactive view of how these features combine in a running session, see
Explore the context window
.
​
Context cost by feature
Each feature has a different loading strategy and context cost:
Feature
When it loads
What loads
Context cost
CLAUDE.md
Session start
Full content
Every request
Skills
Session start + when used
Descriptions at start, full content when used
Low (descriptions every request)*
MCP servers
Session start
Tool names; full schemas on demand
Low until a tool is used
Subagents
When spawned
Fresh context with specified skills
Isolated from main session
Hooks
On trigger
Nothing (runs externally)
Zero, unless hook returns additional context
*By default, skill descriptions load at session start so Claude can decide when to use them. Set
disable-model-invocation: true
in a skill’s frontmatter to hide it from Claude entirely until you invoke it manually. This reduces context cost to zero for skills you only trigger yourself. For a skill you didn’t write, set
skillOverrides
in settings to do the same without editing its file.
​
Understand how features load
Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.
CLAUDE.md
Skills
MCP servers
Subagents
Hooks
When:
Session start
What loads:
Full content of all CLAUDE.md files (managed, user, and project levels).
Inheritance:
Claude reads CLAUDE.md files from your working directory up to the root, and discovers nested ones in subdirectories as it accesses those files. See
How CLAUDE.md files load
for details.
Keep CLAUDE.md under 200 lines. Move reference material to skills, which load on-demand.
Skills are extra capabilities in Claude’s toolkit. They can be reference material (like an API style guide) or invocable workflows you trigger with
/<name>
(like
/deploy
). Claude Code includes
bundled skills
like
/simplify
,
/batch
, and
/debug
that work out of the box. You can also create your own. Claude uses skills when appropriate, or you can invoke one directly.
When:
Depends on the skill’s configuration. By default, descriptions load at session start and full content loads when used. For user-only skills (
disable-model-invocation: true
), nothing loads until you invoke them.
What loads:
For model-invocable skills, Claude sees names and descriptions in every request. When you invoke a skill with
/<name>
or Claude loads it automatically, the full content loads into your conversation.
How Claude chooses skills:
Claude matches your task against skill descriptions to decide which are relevant. If descriptions are vague or overlap, Claude may load the wrong skill or miss one that would help. To tell Claude to use a specific skill, invoke it with
/<name>
. Skills with
disable-model-invocation: true
are invisible to Claude until you invoke them.
Context cost:
Low until used. User-only skills have zero cost until invoked.
In subagents:
Skills work differently in subagents. Instead of on-demand loading, skills listed in the subagent’s
skills
field are fully preloaded into its context at launch. Subagents can still discover and invoke unlisted project, user, and plugin skills through the Skill tool.
Use
disable-model-invocation: true
for skills with side effects. This saves context and ensures only you trigger them.
When:
Session start.
What loads:
Tool names from connected servers. Full JSON schemas stay deferred until Claude needs a specific tool.
Context cost:
Tool search
is on by default, so idle MCP tools consume minimal context.
Reliability note:
MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with
/mcp
.
Run
/mcp
to see token costs per server. Disconnect servers you’re not actively using.
When:
On demand, when you or Claude spawns one for a task.
What loads:
Fresh, isolated context containing:
The system prompt (shared with parent for cache efficiency)
Full content of skills listed in the agent’s
skills:
field
CLAUDE.md and git status (inherited from parent)
Whatever context the lead agent passes in the prompt
Context cost:
Isolated from main session. Subagents don’t inherit your conversation history or invoked skills.
Use subagents for work that doesn’t need your full conversation context. Their isolation prevents bloating your main session.
When:
On trigger. Hooks fire at specific lifecycle events like tool execution, session boundaries, prompt submission, permission requests, and compaction. See
Hooks
for the full list.
What loads:
Nothing by default. Hooks execute outside the main conversation.
Context cost:
Zero, unless the hook returns output that gets added as messages to your conversation.
Hooks are ideal for side effects (linting, logging) that don’t need to affect Claude’s context.
​
Learn more
Each feature has its own guide with setup instructions, examples, and configuration options.
CLAUDE.md
Store project context, conventions, and instructions
Skills
Give Claude domain expertise and reusable workflows
Subagents
Offload work to isolated context
Agent teams
Coordinate multiple sessions working in parallel
MCP
Connect Claude to external services
Hooks
Automate workflows with hooks
Plugins
Bundle and share feature sets
Marketplaces
Host and distribute plugin collections
Was this page helpful?
Yes
No
How Claude Code works
Explore the .claude directory
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/features-overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Extend Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer us...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Extend Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code combines a model that reasons about your code with
built-in tools
for file operations, search, execution, and web access. The built-in tools cover most coding tasks. This guide covers the extension layer: features you add to customize what Claude knows, connect it to external services, and automate workflows.
For how the core agentic loop works, see
How Claude Code works
.
New to Claude Code?
Start with
CLAUDE.md
for project conventions, then add other extensions
as specific triggers come up
.
​
Overview
Extensions plug into different parts of the agentic loop:
CLAUDE.md
adds persistent context Claude sees every session
Skills
add reusable knowledge and invocable workflows
MCP
connects Claude to external services and tools
Subagents
run their own loops in isolated context, returning summaries
Agent teams
coordinate multiple independent sessions with shared tasks and peer-to-peer messaging
Hooks
fire on lifecycle events and can run a script, HTTP request, prompt, or subagent
Plugins
and
marketplaces
package and distribute these features
Skills
are the most flexible extension. A skill is a markdown file containing knowledge, workflows, or instructions. You can invoke skills with a command like
/deploy
, or Claude can load them automatically when relevant. Skills can run in your current conversation or in an isolated context via subagents.
​
Match features to your goal
Features range from always-on context that Claude sees every session, to on-demand capabilities you or Claude can invoke, to background automation that runs on specific events. The table below shows what’s available and when each one makes sense.
Feature
What it does
When to use it
Example
CLAUDE.md
Persistent context loaded every conversation
Project conventions, “always do X” rules
”Use pnpm, not npm. Run tests before committing.”
Skill
Instructions, knowledge, and workflows Claude can use
Reusable content, reference docs, repeatable tasks
/deploy
runs your deployment checklist; API docs skill with endpoint patterns
Subagent
Isolated execution context that returns summarized results
Context isolation, parallel tasks, specialized workers
Research task that reads many files but returns only key findings
Agent teams
Coordinate multiple independent Claude Code sessions
Parallel research, new feature development, debugging with competing hypotheses
Spawn reviewers to check security, performance, and tests simultaneously
MCP
Connect to external services
External data or actions
Query your database, post to Slack, control a browser
Hook
Script, HTTP request, prompt, or subagent triggered by events
Automation that must run on every matching event
Run ESLint after every file edit
Plugins
are the packaging layer. A plugin bundles skills, hooks, subagents, and MCP servers into a single installable unit. Plugin skills are namespaced (like
/my-plugin:review
) so multiple plugins can coexist. Use plugins when you want to reuse the same setup across multiple repositories or distribute to others via a
marketplace
.
​
Build your setup over time
You don’t need to configure everything up front. Each feature has a recognizable trigger, and most teams add them in roughly this order:
Trigger
Add
Claude gets a convention or command wrong twice
Add it to
CLAUDE.md
You keep typing the same prompt to start a task
Save it as a user-invocable
skill
You paste the same playbook or multi-step procedure into chat for the third time
Capture it as a
skill
You keep copying data from a browser tab Claude can’t see
Connect that system as an
MCP server
A side task floods your conversation with output you won’t reference again
Route it through a
subagent
You want something to happen every time without asking
Write a
hook
A second repository needs the same setup
Package it as a
plugin
The same triggers tell you when to update what you already have. A repeated mistake or a recurring review comment is a CLAUDE.md edit, not a one-off correction in chat. A workflow you keep tweaking by hand is a skill that needs another revision.
​
Compare similar features
Some features can seem similar. Here’s how to tell them apart.
Skill vs Subagent
CLAUDE.md vs Skill
CLAUDE.md vs Rules vs Skills
Subagent vs Agent team
MCP vs Skill
Hook vs Skill
Skills and subagents solve different problems:
Skills
are reusable content you can load into any context
Subagents
are isolated workers that run separately from your main conversation
Aspect
Skill
Subagent
What it is
Reusable instructions, knowledge, or workflows
Isolated worker with its own context
Key benefit
Share content across contexts
Context isolation. Work happens separately, only summary returns
Context window
impact
Adds to your main window
Uses a separate window with its own input and output tokens
Best for
Reference material, invocable workflows
Tasks that read many files, parallel work, specialized workers
Skills can be reference or action.
Reference skills provide knowledge Claude uses throughout your session (like your API style guide). Action skills tell Claude to do something specific (like
/deploy
that runs your deployment workflow).
Use a subagent
when you need context isolation or when your context window is getting full. The subagent might read dozens of files or run extensive searches, but your main conversation only receives a summary. Since subagent work doesn’t consume your main context, this is also useful when you don’t need the intermediate work to remain visible. Custom subagents can have their own instructions and can preload skills.
They can combine.
A subagent can preload specific skills (
skills:
field). A skill can run in isolated context using
context: fork
. See
Skills
for details.
Both store instructions, but they load differently and serve different purposes.
Aspect
CLAUDE.md
Skill
Loads
Every session, automatically
On demand
Can include files
Yes, with
@path
imports
Yes, with
@path
imports
Can trigger workflows
No
Yes, with
/<name>
Best for
”Always do X” rules
Reference material, invocable workflows
Put it in CLAUDE.md
if Claude should always know it: coding conventions, build commands, project structure, “never do X” rules.
Put it in a skill
if it’s reference material Claude needs sometimes (API docs, style guides) or a workflow you trigger with
/<name>
(deploy, review, release).
Rule of thumb:
Keep CLAUDE.md under 200 lines. If it’s growing, move reference content to skills or split into
.claude/rules/
files.
All three store instructions, but they load differently:
Aspect
CLAUDE.md
.claude/rules/
Skill
Loads
Every session
Every session, or when matching files are opened
On demand, when invoked or relevant
Scope
Whole project
Can be scoped to file paths
Task-specific
Best for
Core conventions and build commands
Language-specific or directory-specific guidelines
Reference material, repeatable workflows
Use CLAUDE.md
for instructions every session needs: build commands, test conventions, project architecture.
Use rules
to keep CLAUDE.md focused. Rules with
paths
frontmatter
only load when Claude works with matching files, saving context.
Use skills
for content Claude only needs sometimes, like API documentation or a deployment checklist you trigger with
/<name>
.
Both parallelize work, but they’re architecturally different:
Subagents
run inside your session and report results back to your main context
Agent teams
are independent Claude Code sessions that communicate with each other
Aspect
Subagent
Agent team
Context
Own context window; results return to the caller
Own context window; fully independent
Communication
Reports results back to the main agent only
Teammates message each other directly
Coordination
Main agent manages all work
Shared task list with self-coordination
Best for
Focused tasks where only the result matters
Complex work requiring discussion and collaboration
Token cost
Lower: results summarized back to main context
Higher: each teammate is a separate Claude instance
Use a subagent
when you need a quick, focused worker: research a question, verify a claim, review a file. The subagent does the work and returns a summary. Your main conversation stays clean.
Use an agent team
when teammates need to share findings, challenge each other, and coordinate independently. Agent teams are best for research with competing hypotheses, parallel code review, and new feature development where each teammate owns a separate piece.
Transition point:
If you’re running parallel subagents but hitting context limits, or if your subagents need to communicate with each other, agent teams are the natural next step.
Agent teams are experimental and disabled by default. See
agent teams
for setup and current limitations.
MCP connects Claude to external services. Skills extend what Claude knows, including how to use those services effectively.
Aspect
MCP
Skill
What it is
Protocol for connecting to external services
Knowledge, workflows, and reference material
Provides
Tools and data access
Knowledge, workflows, reference material
Examples
Slack integration, database queries, browser control
Code review checklist, deploy workflow, API style guide
These solve different problems and work well together:
MCP
gives Claude the ability to interact with external systems. Without MCP, Claude can’t query your database or post to Slack.
Skills
give Claude knowledge about how to use those tools effectively, plus workflows you can trigger with
/<name>
. A skill might include your team’s database schema and query patterns, or a
/post-to-slack
workflow with your team’s message formatting rules.
Example: An MCP server connects Claude to your database. A skill teaches Claude your data model, common query patterns, and which tables to use for different tasks.
A hook fires on a lifecycle event; a skill is loaded into context for Claude to apply.
Aspect
Hook
Skill
Runs
A shell command, HTTP request, LLM prompt, or subagent
Instructions Claude reads and follows
Triggered by
Lifecycle events
such as
PostToolUse
or
SessionStart
You typing
/<name>
, or Claude matching the description to your task
Determinism
Always fires on its event; the trigger is guaranteed
Claude interprets the instructions; outcome can vary
Context cost
Zero unless the hook returns output
Description loads each session; full content loads when used
Best for
Linting after edits, blocking unsafe commands, logging, notifications
Workflows that need reasoning, reference material, multi-step tasks
Use a hook
when the action must happen the same way every time and doesn’t need Claude to think. For example: format on save, reject
rm -rf /
, post a Slack message when a session ends.
Use a skill
when Claude should decide how to apply the steps, or when the content is knowledge rather than a script. For example: a
/release
checklist, your API style guide, a debugging playbook.
Put guardrails in hooks.
An instruction like “never edit
.env
” in CLAUDE.md or a skill is a request, not a guarantee. A
PreToolUse
hook that blocks the edit is enforcement. If a rule must hold every time, make it a hook rather than a prompt instruction.
Hook output lands in context.
A
PostToolUse
hook that runs your linter feeds results back as text Claude reads; a
/fix-lint
skill tells Claude how to resolve them.
​
Understand how features layer
Features can be defined at multiple levels: user-wide, per-project, via plugins, or through managed policies. You can also nest CLAUDE.md files in subdirectories or place skills in specific packages of a monorepo. When the same feature exists at multiple levels, here’s how they layer:
CLAUDE.md files
are additive: all levels contribute content to Claude’s context simultaneously. Files from your working directory and above load at launch; subdirectories load as you work in them. When instructions conflict, Claude uses judgment to reconcile them, with more specific instructions typically taking precedence. See
how CLAUDE.md files load
.
Skills and subagents
override by name: when the same name exists at multiple levels, one definition wins based on priority (managed > user > project for skills; managed > CLI flag > project > user > plugin for subagents). Plugin skills are
namespaced
to avoid conflicts. See
skill discovery
and
subagent scope
.
MCP servers
override by name: local > project > user. See
MCP scope
.
Hooks
merge: all registered hooks fire for their matching events regardless of source. See
hooks
.
​
Combine features
Each extension solves a different problem: CLAUDE.md handles always-on context, skills handle on-demand knowledge and workflows, MCP handles external connections, subagents handle isolation, and hooks handle automation. Real setups combine them based on your workflow.
For example, you might use CLAUDE.md for project conventions, a skill for your deployment workflow, MCP to connect to your database, and a hook to run linting after every edit. Each feature handles what it’s best at.
Pattern
How it works
Example
Skill + MCP
MCP provides the connection; a skill teaches Claude how to use it well
MCP connects to your database, a skill documents your schema and query patterns
Skill + Subagent
A skill spawns subagents for parallel work
/audit
skill kicks off security, performance, and style subagents that work in isolated context
CLAUDE.md + Skills
CLAUDE.md holds always-on rules; skills hold reference material loaded on demand
CLAUDE.md says “follow our API conventions,” a skill contains the full API style guide
Hook + MCP
A hook triggers external actions through MCP
Post-edit hook sends a Slack notification when Claude modifies critical files
​
Understand context costs
Every feature you add consumes some of Claude’s context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup. For an interactive view of how these features combine in a running session, see
Explore the context window
.
​
Context cost by feature
Each feature has a different loading strategy and context cost:
Feature
When it loads
What loads
Context cost
CLAUDE.md
Session start
Full content
Every request
Skills
Session start + when used
Descriptions at start, full content when used
Low (descriptions every request)*
MCP servers
Session start
Tool names; full schemas on demand
Low until a tool is used
Subagents
When spawned
Fresh context with specified skills
Isolated from main session
Hooks
On trigger
Nothing (runs externally)
Zero, unless hook returns additional context
*By default, skill descriptions load at session start so Claude can decide when to use them. Set
disable-model-invocation: true
in a skill’s frontmatter to hide it from Claude entirely until you invoke it manually. This reduces context cost to zero for skills you only trigger yourself. For a skill you didn’t write, set
skillOverrides
in settings to do the same without editing its file.
​
Understand how features load
Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.
CLAUDE.md
Skills
MCP servers
Subagents
Hooks
When:
Session start
What loads:
Full content of all CLAUDE.md files (managed, user, and project levels).
Inheritance:
Claude reads CLAUDE.md files from your working directory up to the root, and discovers nested ones in subdirectories as it accesses those files. See
How CLAUDE.md files load
for details.
Keep CLAUDE.md under 200 lines. Move reference material to skills, which load on-demand.
Skills are extra capabilities in Claude’s toolkit. They can be reference material (like an API style guide) or invocable workflows you trigger with
/<name>
(like
/deploy
). Claude Code includes
bundled skills
like
/simplify
,
/batch
, and
/debug
that work out of the box. You can also create your own. Claude uses skills when appropriate, or you can invoke one directly.
When:
Depends on the skill’s configuration. By default, descriptions load at session start and full content loads when used. For user-only skills (
disable-model-invocation: true
), nothing loads until you invoke them.
What loads:
For model-invocable skills, Claude sees names and descriptions in every request. When you invoke a skill with
/<name>
or Claude loads it automatically, the full content loads into your conversation.
How Claude chooses skills:
Claude matches your task against skill descriptions to decide which are relevant. If descriptions are vague or overlap, Claude may load the wrong skill or miss one that would help. To tell Claude to use a specific skill, invoke it with
/<name>
. Skills with
disable-model-invocation: true
are invisible to Claude until you invoke them.
Context cost:
Low until used. User-only skills have zero cost until invoked.
In subagents:
Skills work differently in subagents. Instead of on-demand loading, skills listed in the subagent’s
skills
field are fully preloaded into its context at launch. Subagents can still discover and invoke unlisted project, user, and plugin skills through the Skill tool.
Use
disable-model-invocation: true
for skills with side effects. This saves context and ensures only you trigger them.
When:
Session start.
What loads:
Tool names from connected servers. Full JSON schemas stay deferred until Claude needs a specific tool.
Context cost:
Tool search
is on by default, so idle MCP tools consume minimal context.
Reliability note:
MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with
/mcp
.
Run
/mcp
to see token costs per server. Disconnect servers you’re not actively using.
When:
On demand, when you or Claude spawns one for a task.
What loads:
Fresh, isolated context containing:
The system prompt (shared with parent for cache efficiency)
Full content of skills listed in the agent’s
skills:
field
CLAUDE.md and git status (inherited from parent)
Whatever context the lead agent passes in the prompt
Context cost:
Isolated from main session. Subagents don’t inherit your conversation history or invoked skills.
Use subagents for work that doesn’t need your full conversation context. Their isolation prevents bloating your main session.
When:
On trigger. Hooks fire at specific lifecycle events like tool execution, session boundaries, prompt submission, permission requests, and compaction. See
Hooks
for the full list.
What loads:
Nothing by default. Hooks execute outside the main conversation.
Context cost:
Zero, unless the hook returns output that gets added as messages to your conversation.
Hooks are ideal for side effects (linting, logging) that don’t need to affect Claude’s context.
​
Learn more
Each feature has its own guide with setup instructions, examples, and configuration options.
CLAUDE.md
Store project context, conventions, and instructions
Skills
Give Claude domain expertise and reusable workflows
Subagents
Offload work to isolated context
Agent teams
Coordinate multiple sessions working in parallel
MCP
Connect Claude to external services
Hooks
Automate workflows with hooks
Plugins
Bundle and share feature sets
Marketplaces
Host and distribute plugin collections
Was this page helpful?
Yes
No
How Claude Code works
Explore the .claude directory
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/features-overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code GitHub Actions</title>
  <link>https://code.claude.com/docs/en/github-actions</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/github-actions</guid>
  <pubDate>Fri, 26 Jul 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code GitHub Actions
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (bet...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code GitHub Actions
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code GitHub Actions brings AI-powered automation to your GitHub workflow. With a simple
@claude
mention in any PR or issue, Claude can analyze your code, create pull requests, implement features, and fix bugs - all while following your project’s standards. For automatic reviews posted on every PR without a trigger, see
GitHub Code Review
.
Claude Code GitHub Actions is built on top of the
Claude Agent SDK
, which enables programmatic integration of Claude Code into your applications. You can use the SDK to build custom automation workflows beyond GitHub Actions.
Claude Opus 4.7 is now available.
Claude Code GitHub Actions default to Sonnet. To use Opus 4.7, configure the
model parameter
to use
claude-opus-4-7
.
​
Why use Claude Code GitHub Actions?
Instant PR creation
: Describe what you need, and Claude creates a complete PR with all necessary changes
Automated code implementation
: Turn issues into working code with a single command
Follows your standards
: Claude respects your
CLAUDE.md
guidelines and existing code patterns
Simple setup
: Get started in minutes with our installer and API key
Secure by default
: Your code stays on Github’s runners
​
What can Claude do?
Claude Code provides a powerful GitHub Action that transforms how you work with code:
​
Claude Code Action
This GitHub Action allows you to run Claude Code within your GitHub Actions workflows. You can use this to build any custom workflow on top of Claude Code.
View repository →
​
Setup
​
Quick setup
The easiest way to set up this action is through Claude Code in the terminal. Just open claude and run
/install-github-app
.
This command will guide you through setting up the GitHub app and required secrets.
You must be a repository admin to install the GitHub app and add secrets
The GitHub app will request read & write permissions for Contents, Issues, and Pull requests
This quickstart method is only available for direct Claude API users. If
you’re using Amazon Bedrock or Google Vertex AI, see the
Using with Amazon
Bedrock & Google Vertex AI
section.
​
Manual setup
If the
/install-github-app
command fails or you prefer manual setup, please follow these manual setup instructions:
Install the Claude GitHub app
to your repository:
https://github.com/apps/claude
The Claude GitHub app requires the following repository permissions:
Contents
: Read & write (to modify repository files)
Issues
: Read & write (to respond to issues)
Pull requests
: Read & write (to create PRs and push changes)
For more details on security and permissions, see the
security documentation
.
Add ANTHROPIC_API_KEY
to your repository secrets (
Learn how to use secrets in GitHub Actions
)
Copy the workflow file
from
examples/claude.yml
into your repository’s
.github/workflows/
After completing either the quickstart or manual setup, test the action by tagging
@claude
in an issue or PR comment.
​
Upgrading from Beta
Claude Code GitHub Actions v1.0 introduces breaking changes that require updating your workflow files in order to upgrade to v1.0 from the beta version.
If you’re currently using the beta version of Claude Code GitHub Actions, we recommend that you update your workflows to use the GA version. The new version simplifies configuration while adding powerful new features like automatic mode detection.
​
Essential changes
All beta users must make these changes to their workflow files in order to upgrade:
Update the action version
: Change
@beta
to
@v1
Remove mode configuration
: Delete
mode: "tag"
or
mode: "agent"
(now auto-detected)
Update prompt inputs
: Replace
direct_prompt
with
prompt
Move CLI options
: Convert
max_turns
,
model
,
custom_instructions
, etc. to
claude_args
​
Breaking Changes Reference
Old Beta Input
New v1.0 Input
mode
(Removed - auto-detected)
direct_prompt
prompt
override_prompt
prompt
with GitHub variables
custom_instructions
claude_args: --append-system-prompt
max_turns
claude_args: --max-turns
model
claude_args: --model
allowed_tools
claude_args: --allowedTools
disallowed_tools
claude_args: --disallowedTools
claude_env
settings
JSON format
​
Before and After Example
Beta version:
-
uses
:
anthropics/claude-code-action@beta
with
:
mode
:
"tag"
direct_prompt
:
"Review this PR for security issues"
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
custom_instructions
:
"Follow our coding standards"
max_turns
:
"10"
model
:
"claude-sonnet-4-6"
GA version (v1.0):
-
uses
:
anthropics/claude-code-action@v1
with
:
prompt
:
"Review this PR for security issues"
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
claude_args
:
|
--append-system-prompt "Follow our coding standards"
--max-turns 10
--model claude-sonnet-4-6
The action now automatically detects whether to run in interactive mode (responds to
@claude
mentions) or automation mode (runs immediately with a prompt) based on your configuration.
​
Example use cases
Claude Code GitHub Actions can help you with a variety of tasks. The
examples directory
contains ready-to-use workflows for different scenarios.
​
Basic workflow
name
:
Claude Code
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
jobs
:
claude
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
# Responds to @claude mentions in comments
​
Using skills
The
prompt
input accepts a
skill
invocation as well as plain text:
For a skill in your repository’s
.claude/skills/
directory, run
actions/checkout
before the action step and pass
/skill-name
.
For a skill packaged in a plugin, install the plugin with the
plugin_marketplaces
and
plugins
inputs and pass the namespaced
/plugin-name:skill-name
.
The following workflow installs the
code-review
plugin and runs its skill on each new or updated pull request:
name
:
Code Review
on
:
pull_request
:
types
: [
opened
,
synchronize
]
jobs
:
review
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
plugin_marketplaces
:
"https://github.com/anthropics/claude-code.git"
plugins
:
"code-review@claude-code-plugins"
prompt
:
"/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
​
Custom automation with prompts
name
:
Daily Report
on
:
schedule
:
-
cron
:
"0 9 * * *"
jobs
:
report
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
prompt
:
"Generate a summary of yesterday's commits and open issues"
claude_args
:
"--model opus"
​
Common use cases
In issue or PR comments:
@claude implement this feature based on the issue description
@claude how should I implement user authentication for this endpoint?
@claude fix the TypeError in the user dashboard component
Claude will automatically analyze the context and respond appropriately.
​
Best practices
​
CLAUDE.md configuration
Create a
CLAUDE.md
file in your repository root to define code style guidelines, review criteria, project-specific rules, and preferred patterns. This file guides Claude’s understanding of your project standards.
​
Security considerations
Never commit API keys directly to your repository.
For comprehensive security guidance including permissions, authentication, and best practices, see the
Claude Code Action security documentation
.
Always use GitHub Secrets for API keys:
Add your API key as a repository secret named
ANTHROPIC_API_KEY
Reference it in workflows:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
Limit action permissions to only what’s necessary
Review Claude’s suggestions before merging
Always use GitHub Secrets (for example,
${{ secrets.ANTHROPIC_API_KEY }}
) rather than hardcoding API keys directly in your workflow files.
​
Optimizing performance
Use issue templates to provide context, keep your
CLAUDE.md
concise and focused, and configure appropriate timeouts for your workflows.
​
CI costs
When using Claude Code GitHub Actions, be aware of the associated costs:
GitHub Actions costs:
Claude Code runs on GitHub-hosted runners, which consume your GitHub Actions minutes
See
GitHub’s billing documentation
for detailed pricing and minute limits
API costs:
Each Claude interaction consumes API tokens based on the length of prompts and responses
Token usage varies by task complexity and codebase size
See
Claude’s pricing page
for current token rates
Cost optimization tips:
Use specific
@claude
commands to reduce unnecessary API calls
Configure appropriate
--max-turns
in
claude_args
to prevent excessive iterations
Set workflow-level timeouts to avoid runaway jobs
Consider using GitHub’s concurrency controls to limit parallel runs
​
Configuration examples
The Claude Code Action v1 simplifies configuration with unified parameters:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
prompt
:
"Your instructions here"
# Optional
claude_args
:
"--max-turns 5"
# Optional CLI arguments
Key features:
Unified prompt interface
- Use
prompt
for all instructions
Skills
- Invoke installed
skills
directly from the prompt
CLI passthrough
- Any Claude Code CLI argument via
claude_args
Flexible triggers
- Works with any GitHub event
Visit the
examples directory
for complete workflow files.
When responding to issue or PR comments, Claude automatically responds to @claude mentions. For other events, use the
prompt
parameter to provide instructions.
​
Using with Amazon Bedrock & Google Vertex AI
For enterprise environments, you can use Claude Code GitHub Actions with your own cloud infrastructure. This approach gives you control over data residency and billing while maintaining the same functionality.
​
Prerequisites
Before setting up Claude Code GitHub Actions with cloud providers, you need:
​
For Google Cloud Vertex AI:
A Google Cloud Project with Vertex AI enabled
Workload Identity Federation configured for GitHub Actions
A service account with the required permissions
A GitHub App (recommended) or use the default GITHUB_TOKEN
​
For Amazon Bedrock:
An AWS account with Amazon Bedrock enabled
GitHub OIDC Identity Provider configured in AWS
An IAM role with Bedrock permissions
A GitHub App (recommended) or use the default GITHUB_TOKEN
1
Create a custom GitHub App (Recommended for 3P Providers)
For best control and security when using 3P providers like Vertex AI or Bedrock, we recommend creating your own GitHub App:
Go to
https://github.com/settings/apps/new
Fill in the basic information:
GitHub App name
: Choose a unique name (e.g., “YourOrg Claude Assistant”)
Homepage URL
: Your organization’s website or the repository URL
Configure the app settings:
Webhooks
: Uncheck “Active” (not needed for this integration)
Set the required permissions:
Repository permissions
:
Contents: Read & Write
Issues: Read & Write
Pull requests: Read & Write
Click “Create GitHub App”
After creation, click “Generate a private key” and save the downloaded
.pem
file
Note your App ID from the app settings page
Install the app to your repository:
From your app’s settings page, click “Install App” in the left sidebar
Select your account or organization
Choose “Only select repositories” and select the specific repository
Click “Install”
Add the private key as a secret to your repository:
Go to your repository’s Settings → Secrets and variables → Actions
Create a new secret named
APP_PRIVATE_KEY
with the contents of the
.pem
file
Add the App ID as a secret:
Create a new secret named
APP_ID
with your GitHub App’s ID
This app will be used with the
actions/create-github-app-token
action to generate authentication tokens in your workflows.
Alternative for Claude API or if you don’t want to setup your own Github app
: Use the official Anthropic app:
Install from:
https://github.com/apps/claude
No additional configuration needed for authentication
2
Configure cloud provider authentication
Choose your cloud provider and set up secure authentication:
Amazon Bedrock
Configure AWS to allow GitHub Actions to authenticate securely without storing credentials.
Security Note
: Use repository-specific configurations and grant only the minimum required permissions.
Required Setup
:
Enable Amazon Bedrock
:
Request access to Claude models in Amazon Bedrock
For cross-region models, request access in all required regions
Set up GitHub OIDC Identity Provider
:
Provider URL:
https://token.actions.githubusercontent.com
Audience:
sts.amazonaws.com
Create IAM Role for GitHub Actions
:
Trusted entity type: Web identity
Identity provider:
token.actions.githubusercontent.com
Permissions:
AmazonBedrockFullAccess
policy
Configure trust policy for your specific repository
Required Values
:
After setup, you’ll need:
AWS_ROLE_TO_ASSUME
: The ARN of the IAM role you created
OIDC is more secure than using static AWS access keys because credentials are temporary and automatically rotated.
See
AWS documentation
for detailed OIDC setup instructions.
Google Vertex AI
Configure Google Cloud to allow GitHub Actions to authenticate securely without storing credentials.
Security Note
: Use repository-specific configurations and grant only the minimum required permissions.
Required Setup
:
Enable APIs
in your Google Cloud project:
IAM Credentials API
Security Token Service (STS) API
Vertex AI API
Create Workload Identity Federation resources
:
Create a Workload Identity Pool
Add a GitHub OIDC provider with:
Issuer:
https://token.actions.githubusercontent.com
Attribute mappings for repository and owner
Security recommendation
: Use repository-specific attribute conditions
Create a Service Account
:
Grant only
Vertex AI User
role
Security recommendation
: Create a dedicated service account per repository
Configure IAM bindings
:
Allow the Workload Identity Pool to impersonate the service account
Security recommendation
: Use repository-specific principal sets
Required Values
:
After setup, you’ll need:
GCP_WORKLOAD_IDENTITY_PROVIDER
: The full provider resource name
GCP_SERVICE_ACCOUNT
: The service account email address
Workload Identity Federation eliminates the need for downloadable service account keys, improving security.
For detailed setup instructions, consult the
Google Cloud Workload Identity Federation documentation
.
3
Add Required Secrets
Add the following secrets to your repository (Settings → Secrets and variables → Actions):
​
For Claude API (Direct):
For API Authentication
:
ANTHROPIC_API_KEY
: Your Claude API key from
console.anthropic.com
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
​
For Google Cloud Vertex AI
For GCP Authentication
:
GCP_WORKLOAD_IDENTITY_PROVIDER
GCP_SERVICE_ACCOUNT
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
​
For Amazon Bedrock
For AWS Authentication
:
AWS_ROLE_TO_ASSUME
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
4
Create workflow files
Create GitHub Actions workflow files that integrate with your cloud provider. The examples below show complete configurations for both Amazon Bedrock and Google Vertex AI:
Amazon Bedrock workflow
Prerequisites:
Amazon Bedrock access enabled with Claude model permissions
GitHub configured as an OIDC identity provider in AWS
IAM role with Bedrock permissions that trusts GitHub Actions
Required GitHub secrets:
Secret Name
Description
AWS_ROLE_TO_ASSUME
ARN of the IAM role for Bedrock access
APP_ID
Your GitHub App ID (from app settings)
APP_PRIVATE_KEY
The private key you generated for your GitHub App
name
:
Claude PR Action
permissions
:
contents
:
write
pull-requests
:
write
issues
:
write
id-token
:
write
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
issues
:
types
: [
opened
,
assigned
]
jobs
:
claude-pr
:
if
:
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on
:
ubuntu-latest
env
:
AWS_REGION
:
us-west-2
steps
:
-
name
:
Checkout repository
uses
:
actions/checkout@v4
-
name
:
Generate GitHub App token
id
:
app-token
uses
:
actions/create-github-app-token@v2
with
:
app-id
:
${{ secrets.APP_ID }}
private-key
:
${{ secrets.APP_PRIVATE_KEY }}
-
name
:
Configure AWS Credentials (OIDC)
uses
:
aws-actions/configure-aws-credentials@v4
with
:
role-to-assume
:
${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region
:
us-west-2
-
uses
:
anthropics/claude-code-action@v1
with
:
github_token
:
${{ steps.app-token.outputs.token }}
use_bedrock
:
"true"
claude_args
:
'--model us.anthropic.claude-sonnet-4-6 --max-turns 10'
The model ID format for Bedrock includes a region prefix (for example,
us.anthropic.claude-sonnet-4-6
).
Google Vertex AI workflow
Prerequisites:
Vertex AI API enabled in your GCP project
Workload Identity Federation configured for GitHub
Service account with Vertex AI permissions
Required GitHub secrets:
Secret Name
Description
GCP_WORKLOAD_IDENTITY_PROVIDER
Workload identity provider resource name
GCP_SERVICE_ACCOUNT
Service account email with Vertex AI access
APP_ID
Your GitHub App ID (from app settings)
APP_PRIVATE_KEY
The private key you generated for your GitHub App
name
:
Claude PR Action
permissions
:
contents
:
write
pull-requests
:
write
issues
:
write
id-token
:
write
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
issues
:
types
: [
opened
,
assigned
]
jobs
:
claude-pr
:
if
:
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on
:
ubuntu-latest
steps
:
-
name
:
Checkout repository
uses
:
actions/checkout@v4
-
name
:
Generate GitHub App token
id
:
app-token
uses
:
actions/create-github-app-token@v2
with
:
app-id
:
${{ secrets.APP_ID }}
private-key
:
${{ secrets.APP_PRIVATE_KEY }}
-
name
:
Authenticate to Google Cloud
id
:
auth
uses
:
google-github-actions/auth@v2
with
:
workload_identity_provider
:
${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account
:
${{ secrets.GCP_SERVICE_ACCOUNT }}
-
uses
:
anthropics/claude-code-action@v1
with
:
github_token
:
${{ steps.app-token.outputs.token }}
trigger_phrase
:
"@claude"
use_vertex
:
"true"
claude_args
:
'--model claude-sonnet-4-5@20250929 --max-turns 10'
env
:
ANTHROPIC_VERTEX_PROJECT_ID
:
${{ steps.auth.outputs.project_id }}
CLOUD_ML_REGION
:
us-east5
VERTEX_REGION_CLAUDE_4_5_SONNET
:
us-east5
The project ID is automatically retrieved from the Google Cloud authentication step, so you don’t need to hardcode it.
​
Troubleshooting
​
Claude not responding to @claude commands
Verify the GitHub App is installed correctly, check that workflows are enabled, ensure API key is set in repository secrets, and confirm the comment contains
@claude
(not
/claude
).
​
CI not running on Claude’s commits
Ensure you’re using the GitHub App or custom app (not Actions user), check workflow triggers include the necessary events, and verify app permissions include CI triggers.
​
Authentication errors
Confirm API key is valid and has sufficient permissions. For Bedrock/Vertex, check credentials configuration and ensure secrets are named correctly in workflows.
​
Advanced configuration
​
Action parameters
The Claude Code Action v1 uses a simplified configuration:
Parameter
Description
Required
prompt
Instructions for Claude (plain text or a
skill
name)
No*
claude_args
CLI arguments passed to Claude Code
No
plugin_marketplaces
Newline-separated list of plugin marketplace Git URLs
No
plugins
Newline-separated list of plugin names to install before execution
No
anthropic_api_key
Claude API key
Yes**
github_token
GitHub token for API access
No
trigger_phrase
Custom trigger phrase (default: “@claude”)
No
use_bedrock
Use Amazon Bedrock instead of Claude API
No
use_vertex
Use Google Vertex AI instead of Claude API
No
*Prompt is optional - when omitted for issue/PR comments, Claude responds to trigger phrase
**Required for direct Claude API, not for Bedrock/Vertex
​
Pass CLI arguments
The
claude_args
parameter accepts any Claude Code CLI arguments:
claude_args
:
"--max-turns 5 --model claude-sonnet-4-6 --mcp-config /path/to/config.json"
Common arguments:
--max-turns
: Maximum conversation turns (default: 10)
--model
: Model to use (for example,
claude-sonnet-4-6
)
--mcp-config
: Path to MCP configuration
--allowedTools
: Comma-separated list of allowed tools. The
--allowed-tools
alias also works.
--debug
: Enable debug output
​
Alternative integration methods
While the
/install-github-app
command is the recommended approach, you can also:
Custom GitHub App
: For organizations needing branded usernames or custom authentication flows. Create your own GitHub App with required permissions (contents, issues, pull requests) and use the actions/create-github-app-token action to generate tokens in your workflows.
Manual GitHub Actions
: Direct workflow configuration for maximum flexibility
MCP Configuration
: Dynamic loading of Model Context Protocol servers
See the
Claude Code Action documentation
for detailed guides on authentication, security, and advanced configuration.
​
Customizing Claude’s behavior
You can configure Claude’s behavior in two ways:
CLAUDE.md
: Define coding standards, review criteria, and project-specific rules in a
CLAUDE.md
file at the root of your repository. Claude will follow these guidelines when creating PRs and responding to requests. Check out our
Memory documentation
for more details.
Custom prompts
: Use the
prompt
parameter in the workflow file to provide workflow-specific instructions. This allows you to customize Claude’s behavior for different workflows or tasks.
Claude will follow these guidelines when creating PRs and responding to requests.
Was this page helpful?
Yes
No
Code Review
GitHub Enterprise Server
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/github-actions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review &amp; CI/CD
Claude Code GitHub Actions
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (bet...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Code review & CI/CD
Claude Code GitHub Actions
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Code Review
GitHub Actions
GitHub Enterprise Server
GitLab CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code GitHub Actions brings AI-powered automation to your GitHub workflow. With a simple
@claude
mention in any PR or issue, Claude can analyze your code, create pull requests, implement features, and fix bugs - all while following your project’s standards. For automatic reviews posted on every PR without a trigger, see
GitHub Code Review
.
Claude Code GitHub Actions is built on top of the
Claude Agent SDK
, which enables programmatic integration of Claude Code into your applications. You can use the SDK to build custom automation workflows beyond GitHub Actions.
Claude Opus 4.7 is now available.
Claude Code GitHub Actions default to Sonnet. To use Opus 4.7, configure the
model parameter
to use
claude-opus-4-7
.
​
Why use Claude Code GitHub Actions?
Instant PR creation
: Describe what you need, and Claude creates a complete PR with all necessary changes
Automated code implementation
: Turn issues into working code with a single command
Follows your standards
: Claude respects your
CLAUDE.md
guidelines and existing code patterns
Simple setup
: Get started in minutes with our installer and API key
Secure by default
: Your code stays on Github’s runners
​
What can Claude do?
Claude Code provides a powerful GitHub Action that transforms how you work with code:
​
Claude Code Action
This GitHub Action allows you to run Claude Code within your GitHub Actions workflows. You can use this to build any custom workflow on top of Claude Code.
View repository →
​
Setup
​
Quick setup
The easiest way to set up this action is through Claude Code in the terminal. Just open claude and run
/install-github-app
.
This command will guide you through setting up the GitHub app and required secrets.
You must be a repository admin to install the GitHub app and add secrets
The GitHub app will request read & write permissions for Contents, Issues, and Pull requests
This quickstart method is only available for direct Claude API users. If
you’re using Amazon Bedrock or Google Vertex AI, see the
Using with Amazon
Bedrock & Google Vertex AI
section.
​
Manual setup
If the
/install-github-app
command fails or you prefer manual setup, please follow these manual setup instructions:
Install the Claude GitHub app
to your repository:
https://github.com/apps/claude
The Claude GitHub app requires the following repository permissions:
Contents
: Read & write (to modify repository files)
Issues
: Read & write (to respond to issues)
Pull requests
: Read & write (to create PRs and push changes)
For more details on security and permissions, see the
security documentation
.
Add ANTHROPIC_API_KEY
to your repository secrets (
Learn how to use secrets in GitHub Actions
)
Copy the workflow file
from
examples/claude.yml
into your repository’s
.github/workflows/
After completing either the quickstart or manual setup, test the action by tagging
@claude
in an issue or PR comment.
​
Upgrading from Beta
Claude Code GitHub Actions v1.0 introduces breaking changes that require updating your workflow files in order to upgrade to v1.0 from the beta version.
If you’re currently using the beta version of Claude Code GitHub Actions, we recommend that you update your workflows to use the GA version. The new version simplifies configuration while adding powerful new features like automatic mode detection.
​
Essential changes
All beta users must make these changes to their workflow files in order to upgrade:
Update the action version
: Change
@beta
to
@v1
Remove mode configuration
: Delete
mode: "tag"
or
mode: "agent"
(now auto-detected)
Update prompt inputs
: Replace
direct_prompt
with
prompt
Move CLI options
: Convert
max_turns
,
model
,
custom_instructions
, etc. to
claude_args
​
Breaking Changes Reference
Old Beta Input
New v1.0 Input
mode
(Removed - auto-detected)
direct_prompt
prompt
override_prompt
prompt
with GitHub variables
custom_instructions
claude_args: --append-system-prompt
max_turns
claude_args: --max-turns
model
claude_args: --model
allowed_tools
claude_args: --allowedTools
disallowed_tools
claude_args: --disallowedTools
claude_env
settings
JSON format
​
Before and After Example
Beta version:
-
uses
:
anthropics/claude-code-action@beta
with
:
mode
:
"tag"
direct_prompt
:
"Review this PR for security issues"
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
custom_instructions
:
"Follow our coding standards"
max_turns
:
"10"
model
:
"claude-sonnet-4-6"
GA version (v1.0):
-
uses
:
anthropics/claude-code-action@v1
with
:
prompt
:
"Review this PR for security issues"
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
claude_args
:
|
--append-system-prompt "Follow our coding standards"
--max-turns 10
--model claude-sonnet-4-6
The action now automatically detects whether to run in interactive mode (responds to
@claude
mentions) or automation mode (runs immediately with a prompt) based on your configuration.
​
Example use cases
Claude Code GitHub Actions can help you with a variety of tasks. The
examples directory
contains ready-to-use workflows for different scenarios.
​
Basic workflow
name
:
Claude Code
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
jobs
:
claude
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
# Responds to @claude mentions in comments
​
Using skills
The
prompt
input accepts a
skill
invocation as well as plain text:
For a skill in your repository’s
.claude/skills/
directory, run
actions/checkout
before the action step and pass
/skill-name
.
For a skill packaged in a plugin, install the plugin with the
plugin_marketplaces
and
plugins
inputs and pass the namespaced
/plugin-name:skill-name
.
The following workflow installs the
code-review
plugin and runs its skill on each new or updated pull request:
name
:
Code Review
on
:
pull_request
:
types
: [
opened
,
synchronize
]
jobs
:
review
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
plugin_marketplaces
:
"https://github.com/anthropics/claude-code.git"
plugins
:
"code-review@claude-code-plugins"
prompt
:
"/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
​
Custom automation with prompts
name
:
Daily Report
on
:
schedule
:
-
cron
:
"0 9 * * *"
jobs
:
report
:
runs-on
:
ubuntu-latest
steps
:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
prompt
:
"Generate a summary of yesterday's commits and open issues"
claude_args
:
"--model opus"
​
Common use cases
In issue or PR comments:
@claude implement this feature based on the issue description
@claude how should I implement user authentication for this endpoint?
@claude fix the TypeError in the user dashboard component
Claude will automatically analyze the context and respond appropriately.
​
Best practices
​
CLAUDE.md configuration
Create a
CLAUDE.md
file in your repository root to define code style guidelines, review criteria, project-specific rules, and preferred patterns. This file guides Claude’s understanding of your project standards.
​
Security considerations
Never commit API keys directly to your repository.
For comprehensive security guidance including permissions, authentication, and best practices, see the
Claude Code Action security documentation
.
Always use GitHub Secrets for API keys:
Add your API key as a repository secret named
ANTHROPIC_API_KEY
Reference it in workflows:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
Limit action permissions to only what’s necessary
Review Claude’s suggestions before merging
Always use GitHub Secrets (for example,
${{ secrets.ANTHROPIC_API_KEY }}
) rather than hardcoding API keys directly in your workflow files.
​
Optimizing performance
Use issue templates to provide context, keep your
CLAUDE.md
concise and focused, and configure appropriate timeouts for your workflows.
​
CI costs
When using Claude Code GitHub Actions, be aware of the associated costs:
GitHub Actions costs:
Claude Code runs on GitHub-hosted runners, which consume your GitHub Actions minutes
See
GitHub’s billing documentation
for detailed pricing and minute limits
API costs:
Each Claude interaction consumes API tokens based on the length of prompts and responses
Token usage varies by task complexity and codebase size
See
Claude’s pricing page
for current token rates
Cost optimization tips:
Use specific
@claude
commands to reduce unnecessary API calls
Configure appropriate
--max-turns
in
claude_args
to prevent excessive iterations
Set workflow-level timeouts to avoid runaway jobs
Consider using GitHub’s concurrency controls to limit parallel runs
​
Configuration examples
The Claude Code Action v1 simplifies configuration with unified parameters:
-
uses
:
anthropics/claude-code-action@v1
with
:
anthropic_api_key
:
${{ secrets.ANTHROPIC_API_KEY }}
prompt
:
"Your instructions here"
# Optional
claude_args
:
"--max-turns 5"
# Optional CLI arguments
Key features:
Unified prompt interface
- Use
prompt
for all instructions
Skills
- Invoke installed
skills
directly from the prompt
CLI passthrough
- Any Claude Code CLI argument via
claude_args
Flexible triggers
- Works with any GitHub event
Visit the
examples directory
for complete workflow files.
When responding to issue or PR comments, Claude automatically responds to @claude mentions. For other events, use the
prompt
parameter to provide instructions.
​
Using with Amazon Bedrock & Google Vertex AI
For enterprise environments, you can use Claude Code GitHub Actions with your own cloud infrastructure. This approach gives you control over data residency and billing while maintaining the same functionality.
​
Prerequisites
Before setting up Claude Code GitHub Actions with cloud providers, you need:
​
For Google Cloud Vertex AI:
A Google Cloud Project with Vertex AI enabled
Workload Identity Federation configured for GitHub Actions
A service account with the required permissions
A GitHub App (recommended) or use the default GITHUB_TOKEN
​
For Amazon Bedrock:
An AWS account with Amazon Bedrock enabled
GitHub OIDC Identity Provider configured in AWS
An IAM role with Bedrock permissions
A GitHub App (recommended) or use the default GITHUB_TOKEN
1
Create a custom GitHub App (Recommended for 3P Providers)
For best control and security when using 3P providers like Vertex AI or Bedrock, we recommend creating your own GitHub App:
Go to
https://github.com/settings/apps/new
Fill in the basic information:
GitHub App name
: Choose a unique name (e.g., “YourOrg Claude Assistant”)
Homepage URL
: Your organization’s website or the repository URL
Configure the app settings:
Webhooks
: Uncheck “Active” (not needed for this integration)
Set the required permissions:
Repository permissions
:
Contents: Read & Write
Issues: Read & Write
Pull requests: Read & Write
Click “Create GitHub App”
After creation, click “Generate a private key” and save the downloaded
.pem
file
Note your App ID from the app settings page
Install the app to your repository:
From your app’s settings page, click “Install App” in the left sidebar
Select your account or organization
Choose “Only select repositories” and select the specific repository
Click “Install”
Add the private key as a secret to your repository:
Go to your repository’s Settings → Secrets and variables → Actions
Create a new secret named
APP_PRIVATE_KEY
with the contents of the
.pem
file
Add the App ID as a secret:
Create a new secret named
APP_ID
with your GitHub App’s ID
This app will be used with the
actions/create-github-app-token
action to generate authentication tokens in your workflows.
Alternative for Claude API or if you don’t want to setup your own Github app
: Use the official Anthropic app:
Install from:
https://github.com/apps/claude
No additional configuration needed for authentication
2
Configure cloud provider authentication
Choose your cloud provider and set up secure authentication:
Amazon Bedrock
Configure AWS to allow GitHub Actions to authenticate securely without storing credentials.
Security Note
: Use repository-specific configurations and grant only the minimum required permissions.
Required Setup
:
Enable Amazon Bedrock
:
Request access to Claude models in Amazon Bedrock
For cross-region models, request access in all required regions
Set up GitHub OIDC Identity Provider
:
Provider URL:
https://token.actions.githubusercontent.com
Audience:
sts.amazonaws.com
Create IAM Role for GitHub Actions
:
Trusted entity type: Web identity
Identity provider:
token.actions.githubusercontent.com
Permissions:
AmazonBedrockFullAccess
policy
Configure trust policy for your specific repository
Required Values
:
After setup, you’ll need:
AWS_ROLE_TO_ASSUME
: The ARN of the IAM role you created
OIDC is more secure than using static AWS access keys because credentials are temporary and automatically rotated.
See
AWS documentation
for detailed OIDC setup instructions.
Google Vertex AI
Configure Google Cloud to allow GitHub Actions to authenticate securely without storing credentials.
Security Note
: Use repository-specific configurations and grant only the minimum required permissions.
Required Setup
:
Enable APIs
in your Google Cloud project:
IAM Credentials API
Security Token Service (STS) API
Vertex AI API
Create Workload Identity Federation resources
:
Create a Workload Identity Pool
Add a GitHub OIDC provider with:
Issuer:
https://token.actions.githubusercontent.com
Attribute mappings for repository and owner
Security recommendation
: Use repository-specific attribute conditions
Create a Service Account
:
Grant only
Vertex AI User
role
Security recommendation
: Create a dedicated service account per repository
Configure IAM bindings
:
Allow the Workload Identity Pool to impersonate the service account
Security recommendation
: Use repository-specific principal sets
Required Values
:
After setup, you’ll need:
GCP_WORKLOAD_IDENTITY_PROVIDER
: The full provider resource name
GCP_SERVICE_ACCOUNT
: The service account email address
Workload Identity Federation eliminates the need for downloadable service account keys, improving security.
For detailed setup instructions, consult the
Google Cloud Workload Identity Federation documentation
.
3
Add Required Secrets
Add the following secrets to your repository (Settings → Secrets and variables → Actions):
​
For Claude API (Direct):
For API Authentication
:
ANTHROPIC_API_KEY
: Your Claude API key from
console.anthropic.com
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
​
For Google Cloud Vertex AI
For GCP Authentication
:
GCP_WORKLOAD_IDENTITY_PROVIDER
GCP_SERVICE_ACCOUNT
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
​
For Amazon Bedrock
For AWS Authentication
:
AWS_ROLE_TO_ASSUME
For GitHub App (if using your own app)
:
APP_ID
: Your GitHub App’s ID
APP_PRIVATE_KEY
: The private key (.pem) content
4
Create workflow files
Create GitHub Actions workflow files that integrate with your cloud provider. The examples below show complete configurations for both Amazon Bedrock and Google Vertex AI:
Amazon Bedrock workflow
Prerequisites:
Amazon Bedrock access enabled with Claude model permissions
GitHub configured as an OIDC identity provider in AWS
IAM role with Bedrock permissions that trusts GitHub Actions
Required GitHub secrets:
Secret Name
Description
AWS_ROLE_TO_ASSUME
ARN of the IAM role for Bedrock access
APP_ID
Your GitHub App ID (from app settings)
APP_PRIVATE_KEY
The private key you generated for your GitHub App
name
:
Claude PR Action
permissions
:
contents
:
write
pull-requests
:
write
issues
:
write
id-token
:
write
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
issues
:
types
: [
opened
,
assigned
]
jobs
:
claude-pr
:
if
:
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on
:
ubuntu-latest
env
:
AWS_REGION
:
us-west-2
steps
:
-
name
:
Checkout repository
uses
:
actions/checkout@v4
-
name
:
Generate GitHub App token
id
:
app-token
uses
:
actions/create-github-app-token@v2
with
:
app-id
:
${{ secrets.APP_ID }}
private-key
:
${{ secrets.APP_PRIVATE_KEY }}
-
name
:
Configure AWS Credentials (OIDC)
uses
:
aws-actions/configure-aws-credentials@v4
with
:
role-to-assume
:
${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region
:
us-west-2
-
uses
:
anthropics/claude-code-action@v1
with
:
github_token
:
${{ steps.app-token.outputs.token }}
use_bedrock
:
"true"
claude_args
:
'--model us.anthropic.claude-sonnet-4-6 --max-turns 10'
The model ID format for Bedrock includes a region prefix (for example,
us.anthropic.claude-sonnet-4-6
).
Google Vertex AI workflow
Prerequisites:
Vertex AI API enabled in your GCP project
Workload Identity Federation configured for GitHub
Service account with Vertex AI permissions
Required GitHub secrets:
Secret Name
Description
GCP_WORKLOAD_IDENTITY_PROVIDER
Workload identity provider resource name
GCP_SERVICE_ACCOUNT
Service account email with Vertex AI access
APP_ID
Your GitHub App ID (from app settings)
APP_PRIVATE_KEY
The private key you generated for your GitHub App
name
:
Claude PR Action
permissions
:
contents
:
write
pull-requests
:
write
issues
:
write
id-token
:
write
on
:
issue_comment
:
types
: [
created
]
pull_request_review_comment
:
types
: [
created
]
issues
:
types
: [
opened
,
assigned
]
jobs
:
claude-pr
:
if
:
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on
:
ubuntu-latest
steps
:
-
name
:
Checkout repository
uses
:
actions/checkout@v4
-
name
:
Generate GitHub App token
id
:
app-token
uses
:
actions/create-github-app-token@v2
with
:
app-id
:
${{ secrets.APP_ID }}
private-key
:
${{ secrets.APP_PRIVATE_KEY }}
-
name
:
Authenticate to Google Cloud
id
:
auth
uses
:
google-github-actions/auth@v2
with
:
workload_identity_provider
:
${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account
:
${{ secrets.GCP_SERVICE_ACCOUNT }}
-
uses
:
anthropics/claude-code-action@v1
with
:
github_token
:
${{ steps.app-token.outputs.token }}
trigger_phrase
:
"@claude"
use_vertex
:
"true"
claude_args
:
'--model claude-sonnet-4-5@20250929 --max-turns 10'
env
:
ANTHROPIC_VERTEX_PROJECT_ID
:
${{ steps.auth.outputs.project_id }}
CLOUD_ML_REGION
:
us-east5
VERTEX_REGION_CLAUDE_4_5_SONNET
:
us-east5
The project ID is automatically retrieved from the Google Cloud authentication step, so you don’t need to hardcode it.
​
Troubleshooting
​
Claude not responding to @claude commands
Verify the GitHub App is installed correctly, check that workflows are enabled, ensure API key is set in repository secrets, and confirm the comment contains
@claude
(not
/claude
).
​
CI not running on Claude’s commits
Ensure you’re using the GitHub App or custom app (not Actions user), check workflow triggers include the necessary events, and verify app permissions include CI triggers.
​
Authentication errors
Confirm API key is valid and has sufficient permissions. For Bedrock/Vertex, check credentials configuration and ensure secrets are named correctly in workflows.
​
Advanced configuration
​
Action parameters
The Claude Code Action v1 uses a simplified configuration:
Parameter
Description
Required
prompt
Instructions for Claude (plain text or a
skill
name)
No*
claude_args
CLI arguments passed to Claude Code
No
plugin_marketplaces
Newline-separated list of plugin marketplace Git URLs
No
plugins
Newline-separated list of plugin names to install before execution
No
anthropic_api_key
Claude API key
Yes**
github_token
GitHub token for API access
No
trigger_phrase
Custom trigger phrase (default: “@claude”)
No
use_bedrock
Use Amazon Bedrock instead of Claude API
No
use_vertex
Use Google Vertex AI instead of Claude API
No
*Prompt is optional - when omitted for issue/PR comments, Claude responds to trigger phrase
**Required for direct Claude API, not for Bedrock/Vertex
​
Pass CLI arguments
The
claude_args
parameter accepts any Claude Code CLI arguments:
claude_args
:
"--max-turns 5 --model claude-sonnet-4-6 --mcp-config /path/to/config.json"
Common arguments:
--max-turns
: Maximum conversation turns (default: 10)
--model
: Model to use (for example,
claude-sonnet-4-6
)
--mcp-config
: Path to MCP configuration
--allowedTools
: Comma-separated list of allowed tools. The
--allowed-tools
alias also works.
--debug
: Enable debug output
​
Alternative integration methods
While the
/install-github-app
command is the recommended approach, you can also:
Custom GitHub App
: For organizations needing branded usernames or custom authentication flows. Create your own GitHub App with required permissions (contents, issues, pull requests) and use the actions/create-github-app-token action to generate tokens in your workflows.
Manual GitHub Actions
: Direct workflow configuration for maximum flexibility
MCP Configuration
: Dynamic loading of Model Context Protocol servers
See the
Claude Code Action documentation
for detailed guides on authentication, security, and advanced configuration.
​
Customizing Claude’s behavior
You can configure Claude’s behavior in two ways:
CLAUDE.md
: Define coding standards, review criteria, and project-specific rules in a
CLAUDE.md
file at the root of your repository. Claude will follow these guidelines when creating PRs and responding to requests. Check out our
Memory documentation
for more details.
Custom prompts
: Use the
prompt
parameter in the workflow file to provide workflow-specific instructions. This allows you to customize Claude’s behavior for different workflows or tasks.
Claude will follow these guidelines when creating PRs and responding to requests.
Was this page helpful?
Yes
No
Code Review
GitHub Enterprise Server
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/github-actions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Todo Lists</title>
  <link>https://code.claude.com/docs/en/agent-sdk/todo-tracking</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/todo-tracking</guid>
  <pubDate>Thu, 25 Jul 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Todo Lists
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Custo...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Todo Lists
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Todo tracking provides a structured way to manage tasks and display progress to users. The Claude Agent SDK includes built-in todo functionality that helps organize complex workflows and keep users informed about task progression.
TodoWrite
is the current default in the Agent SDK and the examples on this page use it. The replacement Task tools are available now behind
CLAUDE_CODE_ENABLE_TASKS=1
and will become the default in a future release. See
Migrate to Task tools
for how monitoring code changes.
​
Todo Lifecycle
Todos follow a predictable lifecycle:
Created
as
pending
when tasks are identified
Activated
to
in_progress
when work begins
Completed
when the task finishes successfully
Removed
when all tasks in a group are completed
​
When Todos Are Used
The SDK automatically creates todos for:
Complex multi-step tasks
requiring 3 or more distinct actions
User-provided task lists
when multiple items are mentioned
Non-trivial operations
that benefit from progress tracking
Explicit requests
when users ask for todo organization
​
Examples
​
Monitoring Todo Changes
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Optimize my React app performance and track progress with todos"
,
options:
{
maxTurns:
15
}
})) {
// Todo updates are reflected in the message stream
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
===
"TodoWrite"
) {
const
todos
=
block
.
input
.
todos
;
console
.
log
(
"Todo Status Update:"
);
todos
.
forEach
((
todo
,
index
)
=>
{
const
status
=
todo
.
status
===
"completed"
?
"✅"
:
todo
.
status
===
"in_progress"
?
"🔧"
:
"❌"
;
console
.
log
(
`
${
index
+
1
}
.
${
status
}
${
todo
.
content
}
`
);
});
}
}
}
}
​
Real-time Progress Display
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
class
TodoTracker
{
private
todos
:
any
[]
=
[];
displayProgress
() {
if
(
this
.
todos
.
length
===
0
)
return
;
const
completed
=
this
.
todos
.
filter
((
t
)
=>
t
.
status
===
"completed"
).
length
;
const
inProgress
=
this
.
todos
.
filter
((
t
)
=>
t
.
status
===
"in_progress"
).
length
;
const
total
=
this
.
todos
.
length
;
console
.
log
(
`
\n
Progress:
${
completed
}
/
${
total
}
completed`
);
console
.
log
(
`Currently working on:
${
inProgress
}
task(s)
\n
`
);
this
.
todos
.
forEach
((
todo
,
index
)
=>
{
const
icon
=
todo
.
status
===
"completed"
?
"✅"
:
todo
.
status
===
"in_progress"
?
"🔧"
:
"❌"
;
const
text
=
todo
.
status
===
"in_progress"
?
todo
.
activeForm
:
todo
.
content
;
console
.
log
(
`
${
index
+
1
}
.
${
icon
}
${
text
}
`
);
});
}
async
trackQuery
(
prompt
:
string
) {
for
await
(
const
message
of
query
({
prompt
,
options:
{
maxTurns:
20
}
})) {
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
===
"TodoWrite"
) {
this
.
todos
=
block
.
input
.
todos
;
this
.
displayProgress
();
}
}
}
}
}
}
// Usage
const
tracker
=
new
TodoTracker
();
await
tracker
.
trackQuery
(
"Build a complete authentication system with todos"
);
​
Migrate to Task tools
The Task tools split the single
TodoWrite
call into
TaskCreate
for each new item and
TaskUpdate
for each status change, with
TaskList
and
TaskGet
available for the model to read back the current list. Your monitoring code still inspects
tool_use
blocks in the assistant stream, but maintains a map keyed by task ID instead of replacing the whole list on every call. To opt in before the Task tools become the default, set
CLAUDE_CODE_ENABLE_TASKS=1
in
options.env
.
With
TodoWrite
With Task tools
One tool call rewrites the full
todos
array
TaskCreate
adds one item,
TaskUpdate
patches one item by
taskId
Match
block.name === "TodoWrite"
Match
block.name === "TaskCreate"
or
"TaskUpdate"
Item shape:
{ content, status, activeForm }
TaskCreate
input:
{ subject, description, activeForm?, metadata? }
.
TaskUpdate
input:
{ taskId, status?, subject?, description?, activeForm?, addBlocks?, addBlockedBy?, owner?, metadata? }
.
status
is
"pending"
,
"in_progress"
, or
"completed"
; set
status: "deleted"
to delete
Render
block.input.todos
directly
Accumulate items across calls, or read a snapshot from a
TaskList
tool result
The assigned task ID is not in the
TaskCreate
input. It comes back in the matching
tool_result
as
{ task: { id, subject } }
, so capture it from the result block to key your map. The following example shows the minimal change to the
Monitoring Todo Changes
loop. To render a complete list, watch for a
TaskList
tool result in the stream or accumulate
TaskCreate
results and
TaskUpdate
inputs into a map:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Optimize my React app performance"
,
options:
{
env:
{
...
process
.
env
,
CLAUDE_CODE_ENABLE_TASKS:
"1"
} },
})) {
if
(
message
.
type
!==
"assistant"
)
continue
;
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
!==
"tool_use"
)
continue
;
if
(
block
.
name
===
"TaskCreate"
) {
const
input
=
block
.
input
as
{
subject
:
string
};
console
.
log
(
`+
${
input
.
subject
}
`
);
}
else
if
(
block
.
name
===
"TaskUpdate"
) {
const
input
=
block
.
input
as
{
taskId
:
string
;
status
?:
string
};
if
(
input
.
status
)
console
.
log
(
`
${
input
.
taskId
}
->
${
input
.
status
}
`
);
}
}
}
​
Related Documentation
TypeScript SDK Reference
Python SDK Reference
Streaming vs Single Mode
Custom Tools
Was this page helpful?
Yes
No
Observability with OpenTelemetry
Hosting the Agent SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/todo-tracking" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Todo Lists
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Custo...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Todo Lists
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Todo tracking provides a structured way to manage tasks and display progress to users. The Claude Agent SDK includes built-in todo functionality that helps organize complex workflows and keep users informed about task progression.
TodoWrite
is the current default in the Agent SDK and the examples on this page use it. The replacement Task tools are available now behind
CLAUDE_CODE_ENABLE_TASKS=1
and will become the default in a future release. See
Migrate to Task tools
for how monitoring code changes.
​
Todo Lifecycle
Todos follow a predictable lifecycle:
Created
as
pending
when tasks are identified
Activated
to
in_progress
when work begins
Completed
when the task finishes successfully
Removed
when all tasks in a group are completed
​
When Todos Are Used
The SDK automatically creates todos for:
Complex multi-step tasks
requiring 3 or more distinct actions
User-provided task lists
when multiple items are mentioned
Non-trivial operations
that benefit from progress tracking
Explicit requests
when users ask for todo organization
​
Examples
​
Monitoring Todo Changes
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Optimize my React app performance and track progress with todos"
,
options:
{
maxTurns:
15
}
})) {
// Todo updates are reflected in the message stream
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
===
"TodoWrite"
) {
const
todos
=
block
.
input
.
todos
;
console
.
log
(
"Todo Status Update:"
);
todos
.
forEach
((
todo
,
index
)
=>
{
const
status
=
todo
.
status
===
"completed"
?
"✅"
:
todo
.
status
===
"in_progress"
?
"🔧"
:
"❌"
;
console
.
log
(
`
${
index
+
1
}
.
${
status
}
${
todo
.
content
}
`
);
});
}
}
}
}
​
Real-time Progress Display
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
class
TodoTracker
{
private
todos
:
any
[]
=
[];
displayProgress
() {
if
(
this
.
todos
.
length
===
0
)
return
;
const
completed
=
this
.
todos
.
filter
((
t
)
=>
t
.
status
===
"completed"
).
length
;
const
inProgress
=
this
.
todos
.
filter
((
t
)
=>
t
.
status
===
"in_progress"
).
length
;
const
total
=
this
.
todos
.
length
;
console
.
log
(
`
\n
Progress:
${
completed
}
/
${
total
}
completed`
);
console
.
log
(
`Currently working on:
${
inProgress
}
task(s)
\n
`
);
this
.
todos
.
forEach
((
todo
,
index
)
=>
{
const
icon
=
todo
.
status
===
"completed"
?
"✅"
:
todo
.
status
===
"in_progress"
?
"🔧"
:
"❌"
;
const
text
=
todo
.
status
===
"in_progress"
?
todo
.
activeForm
:
todo
.
content
;
console
.
log
(
`
${
index
+
1
}
.
${
icon
}
${
text
}
`
);
});
}
async
trackQuery
(
prompt
:
string
) {
for
await
(
const
message
of
query
({
prompt
,
options:
{
maxTurns:
20
}
})) {
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
===
"TodoWrite"
) {
this
.
todos
=
block
.
input
.
todos
;
this
.
displayProgress
();
}
}
}
}
}
}
// Usage
const
tracker
=
new
TodoTracker
();
await
tracker
.
trackQuery
(
"Build a complete authentication system with todos"
);
​
Migrate to Task tools
The Task tools split the single
TodoWrite
call into
TaskCreate
for each new item and
TaskUpdate
for each status change, with
TaskList
and
TaskGet
available for the model to read back the current list. Your monitoring code still inspects
tool_use
blocks in the assistant stream, but maintains a map keyed by task ID instead of replacing the whole list on every call. To opt in before the Task tools become the default, set
CLAUDE_CODE_ENABLE_TASKS=1
in
options.env
.
With
TodoWrite
With Task tools
One tool call rewrites the full
todos
array
TaskCreate
adds one item,
TaskUpdate
patches one item by
taskId
Match
block.name === "TodoWrite"
Match
block.name === "TaskCreate"
or
"TaskUpdate"
Item shape:
{ content, status, activeForm }
TaskCreate
input:
{ subject, description, activeForm?, metadata? }
.
TaskUpdate
input:
{ taskId, status?, subject?, description?, activeForm?, addBlocks?, addBlockedBy?, owner?, metadata? }
.
status
is
"pending"
,
"in_progress"
, or
"completed"
; set
status: "deleted"
to delete
Render
block.input.todos
directly
Accumulate items across calls, or read a snapshot from a
TaskList
tool result
The assigned task ID is not in the
TaskCreate
input. It comes back in the matching
tool_result
as
{ task: { id, subject } }
, so capture it from the result block to key your map. The following example shows the minimal change to the
Monitoring Todo Changes
loop. To render a complete list, watch for a
TaskList
tool result in the stream or accumulate
TaskCreate
results and
TaskUpdate
inputs into a map:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Optimize my React app performance"
,
options:
{
env:
{
...
process
.
env
,
CLAUDE_CODE_ENABLE_TASKS:
"1"
} },
})) {
if
(
message
.
type
!==
"assistant"
)
continue
;
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
!==
"tool_use"
)
continue
;
if
(
block
.
name
===
"TaskCreate"
) {
const
input
=
block
.
input
as
{
subject
:
string
};
console
.
log
(
`+
${
input
.
subject
}
`
);
}
else
if
(
block
.
name
===
"TaskUpdate"
) {
const
input
=
block
.
input
as
{
taskId
:
string
;
status
?:
string
};
if
(
input
.
status
)
console
.
log
(
`
${
input
.
taskId
}
->
${
input
.
status
}
`
);
}
}
}
​
Related Documentation
TypeScript SDK Reference
Python SDK Reference
Streaming vs Single Mode
Custom Tools
Was this page helpful?
Yes
No
Observability with OpenTelemetry
Hosting the Agent SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/todo-tracking" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Speed up responses with fast mode</title>
  <link>https://code.claude.com/docs/en/fast-mode</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/fast-mode</guid>
  <pubDate>Tue, 23 Jul 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Speed up responses with fast mode
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Speed up responses with fast mode
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Fast mode is in
research preview
. The feature, pricing, and availability may change based on feedback.
Fast mode is a high-speed configuration for Claude Opus, making the model 2.5x faster at a higher cost per token. Toggle it on with
/fast
when you need speed for interactive work like rapid iteration or live debugging, and toggle it off when cost matters more than latency.
Fast mode is not a different model. It uses Claude Opus with a different API configuration that prioritizes speed over cost efficiency. You get identical quality and capabilities, just faster responses. Fast mode is supported on Opus 4.6 and Opus 4.7. It is not available on Sonnet, Haiku, or other models.
Fast mode requires Claude Code v2.1.36 or later. Check your version with
claude --version
.
What to know:
Use
/fast
to toggle on fast mode in Claude Code CLI. Also available via
/fast
in Claude Code VS Code Extension.
By default,
/fast
runs on Opus 4.6. To run fast mode on Opus 4.7 instead, set the
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
environment variable.
Fast mode pricing is
30
/
30/
30/
150 MTok on both Opus 4.6 and Opus 4.7.
Available to all Claude Code users on subscription plans (Pro/Max/Team/Enterprise) and Claude Console.
For Claude Code users on subscription plans (Pro/Max/Team/Enterprise), fast mode is available via extra usage only and not included in the subscription rate limits.
This page covers how to
toggle fast mode
,
use fast mode on Opus 4.7
, the
cost tradeoff
,
when to use it
,
requirements
,
per-session opt-in
, and
rate limit behavior
.
​
Toggle fast mode
Toggle fast mode in either of these ways:
Type
/fast
and press Tab to toggle on or off
Set
"fastMode": true
in your
user settings file
By default, fast mode persists across sessions. Administrators can configure fast mode to reset each session. See
require per-session opt-in
for details.
For the best cost efficiency, enable fast mode at the start of a session rather than switching mid-conversation. See
understand the cost tradeoff
for details.
When you enable fast mode:
If you’re on a different model, Claude Code automatically switches to the fast mode model: Opus 4.6 by default, or Opus 4.7 when
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
is set.
You’ll see a confirmation message: “Fast mode ON”
A small
↯
icon appears next to the prompt while fast mode is active
Run
/fast
again at any time to check whether fast mode is on or off
When you disable fast mode with
/fast
again, you remain on the same Opus version that fast mode was running on. The model does not revert to your previous model. To switch to a different model, use
/model
.
​
Use fast mode on Opus 4.7
Fast mode on Opus 4.7 requires Claude Code v2.1.139 or later.
Fast mode for Claude Opus 4.7 is in research preview. It runs at the same 2.5x speed and the same price as fast mode for Opus 4.6, with no other behavior changes.
On May 14, 2026, Opus 4.7 becomes the default fast mode model. Until then, opt in by setting
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE=1
.
To opt in, set
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE=1
before launching Claude Code. With the variable set,
/fast
runs on Opus 4.7. Without it,
/fast
continues to run on Opus 4.6.
You can set the variable as a shell export:
export
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
=
1
Or in any Claude Code
settings file
, including user, project, and managed settings, to scope the opt-in:
{
"env"
: {
"CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE"
:
"1"
}
}
Fast mode for Opus 4.6 remains available alongside Opus 4.7. The two share the same fast mode rate limit pool: usage on either model draws from the same limits.
To pin fast mode to Opus 4.6 explicitly, set
CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE=1
. This variable takes precedence, so fast mode runs on Opus 4.6 regardless of whether
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
is set.
​
Understand the cost tradeoff
Fast mode has higher per-token pricing than standard Opus:
Mode
Input (MTok)
Output (MTok)
Fast mode on Opus 4.6
$30
$150
Fast mode on Opus 4.7
$30
$150
Fast mode pricing is flat across the full 1M token context window.
When you switch into fast mode mid-conversation, you pay the full fast mode uncached input token price for the entire conversation context. This costs more than if you had enabled fast mode from the start.
​
Decide when to use fast mode
Fast mode is best for interactive work where response latency matters more than cost:
Rapid iteration on code changes
Live debugging sessions
Time-sensitive work with tight deadlines
Standard mode is better for:
Long autonomous tasks where speed matters less
Batch processing or CI/CD pipelines
Cost-sensitive workloads
​
Fast mode vs effort level
Fast mode and effort level both affect response speed, but differently:
Setting
Effect
Fast mode
Same model quality, lower latency, higher cost
Lower effort level
Less thinking time, faster responses, potentially lower quality on complex tasks
You can combine both: use fast mode with a lower
effort level
for maximum speed on straightforward tasks.
​
Requirements
Fast mode requires all of the following:
Not available on third-party cloud providers
: fast mode is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Azure Foundry. Fast mode is available through the Anthropic Console API and for Claude subscription plans using extra usage.
Extra usage enabled
: your account must have extra usage enabled, which allows billing beyond your plan’s included usage. For individual accounts, enable this in your
Console billing settings
. For Team and Enterprise, an admin must enable extra usage for the organization.
Fast mode usage is billed directly to extra usage, even if you have remaining usage on your plan. This means fast mode tokens do not count against your plan’s included usage and are charged at the fast mode rate from the first token.
Admin enablement for Team and Enterprise
: fast mode is disabled by default for Team and Enterprise organizations. An admin must explicitly
enable fast mode
before users can access it.
If your admin has not enabled fast mode for your organization, the
/fast
command will show “Fast mode has been disabled by your organization.”
​
Enable fast mode for your organization
Admins can enable fast mode in:
Console
(API customers):
Claude Code preferences
Claude AI
(Team and Enterprise):
Admin Settings > Claude Code
Another option to disable fast mode entirely is to set
CLAUDE_CODE_DISABLE_FAST_MODE=1
. See
Environment variables
.
​
Require per-session opt-in
By default, fast mode persists across sessions: if a user enables fast mode, it stays on in future sessions. Administrators on
Team
or
Enterprise
plans can prevent this by setting
fastModePerSessionOptIn
to
true
in
managed settings
or
server-managed settings
. This causes each session to start with fast mode off, requiring users to explicitly enable it with
/fast
.
{
"fastModePerSessionOptIn"
:
true
}
This is useful for controlling costs in organizations where users run multiple concurrent sessions. Users can still enable fast mode with
/fast
when they need speed, but it resets at the start of each new session. The user’s fast mode preference is still saved, so removing this setting restores the default persistent behavior.
​
Handle rate limits
Fast mode has separate rate limits from standard Opus. Fast mode for Opus 4.6 and Opus 4.7 share the same rate limit pool: usage on either model draws from the same limits. When you hit the fast mode rate limit or run out of extra usage:
Fast mode automatically falls back to standard speed on the same Opus version
The
↯
icon turns gray to indicate cooldown
You continue working at standard speed and pricing
When the cooldown expires, fast mode automatically re-enables
To disable fast mode manually instead of waiting for cooldown, run
/fast
again.
​
Research preview
Fast mode is a research preview feature. This means:
The feature may change based on feedback
Availability and pricing are subject to change
The underlying API configuration may evolve
Report issues or feedback through your usual Anthropic support channels.
​
See also
Model configuration
: switch models and adjust effort levels
Manage costs effectively
: track token usage and reduce costs
Status line configuration
: display model and context information
Was this page helpful?
Yes
No
Model configuration
Output styles
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/fast-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Speed up responses with fast mode
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Speed up responses with fast mode
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Fast mode is in
research preview
. The feature, pricing, and availability may change based on feedback.
Fast mode is a high-speed configuration for Claude Opus, making the model 2.5x faster at a higher cost per token. Toggle it on with
/fast
when you need speed for interactive work like rapid iteration or live debugging, and toggle it off when cost matters more than latency.
Fast mode is not a different model. It uses Claude Opus with a different API configuration that prioritizes speed over cost efficiency. You get identical quality and capabilities, just faster responses. Fast mode is supported on Opus 4.6 and Opus 4.7. It is not available on Sonnet, Haiku, or other models.
Fast mode requires Claude Code v2.1.36 or later. Check your version with
claude --version
.
What to know:
Use
/fast
to toggle on fast mode in Claude Code CLI. Also available via
/fast
in Claude Code VS Code Extension.
By default,
/fast
runs on Opus 4.6. To run fast mode on Opus 4.7 instead, set the
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
environment variable.
Fast mode pricing is
30
/
30/
30/
150 MTok on both Opus 4.6 and Opus 4.7.
Available to all Claude Code users on subscription plans (Pro/Max/Team/Enterprise) and Claude Console.
For Claude Code users on subscription plans (Pro/Max/Team/Enterprise), fast mode is available via extra usage only and not included in the subscription rate limits.
This page covers how to
toggle fast mode
,
use fast mode on Opus 4.7
, the
cost tradeoff
,
when to use it
,
requirements
,
per-session opt-in
, and
rate limit behavior
.
​
Toggle fast mode
Toggle fast mode in either of these ways:
Type
/fast
and press Tab to toggle on or off
Set
"fastMode": true
in your
user settings file
By default, fast mode persists across sessions. Administrators can configure fast mode to reset each session. See
require per-session opt-in
for details.
For the best cost efficiency, enable fast mode at the start of a session rather than switching mid-conversation. See
understand the cost tradeoff
for details.
When you enable fast mode:
If you’re on a different model, Claude Code automatically switches to the fast mode model: Opus 4.6 by default, or Opus 4.7 when
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
is set.
You’ll see a confirmation message: “Fast mode ON”
A small
↯
icon appears next to the prompt while fast mode is active
Run
/fast
again at any time to check whether fast mode is on or off
When you disable fast mode with
/fast
again, you remain on the same Opus version that fast mode was running on. The model does not revert to your previous model. To switch to a different model, use
/model
.
​
Use fast mode on Opus 4.7
Fast mode on Opus 4.7 requires Claude Code v2.1.139 or later.
Fast mode for Claude Opus 4.7 is in research preview. It runs at the same 2.5x speed and the same price as fast mode for Opus 4.6, with no other behavior changes.
On May 14, 2026, Opus 4.7 becomes the default fast mode model. Until then, opt in by setting
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE=1
.
To opt in, set
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE=1
before launching Claude Code. With the variable set,
/fast
runs on Opus 4.7. Without it,
/fast
continues to run on Opus 4.6.
You can set the variable as a shell export:
export
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
=
1
Or in any Claude Code
settings file
, including user, project, and managed settings, to scope the opt-in:
{
"env"
: {
"CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE"
:
"1"
}
}
Fast mode for Opus 4.6 remains available alongside Opus 4.7. The two share the same fast mode rate limit pool: usage on either model draws from the same limits.
To pin fast mode to Opus 4.6 explicitly, set
CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE=1
. This variable takes precedence, so fast mode runs on Opus 4.6 regardless of whether
CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE
is set.
​
Understand the cost tradeoff
Fast mode has higher per-token pricing than standard Opus:
Mode
Input (MTok)
Output (MTok)
Fast mode on Opus 4.6
$30
$150
Fast mode on Opus 4.7
$30
$150
Fast mode pricing is flat across the full 1M token context window.
When you switch into fast mode mid-conversation, you pay the full fast mode uncached input token price for the entire conversation context. This costs more than if you had enabled fast mode from the start.
​
Decide when to use fast mode
Fast mode is best for interactive work where response latency matters more than cost:
Rapid iteration on code changes
Live debugging sessions
Time-sensitive work with tight deadlines
Standard mode is better for:
Long autonomous tasks where speed matters less
Batch processing or CI/CD pipelines
Cost-sensitive workloads
​
Fast mode vs effort level
Fast mode and effort level both affect response speed, but differently:
Setting
Effect
Fast mode
Same model quality, lower latency, higher cost
Lower effort level
Less thinking time, faster responses, potentially lower quality on complex tasks
You can combine both: use fast mode with a lower
effort level
for maximum speed on straightforward tasks.
​
Requirements
Fast mode requires all of the following:
Not available on third-party cloud providers
: fast mode is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Azure Foundry. Fast mode is available through the Anthropic Console API and for Claude subscription plans using extra usage.
Extra usage enabled
: your account must have extra usage enabled, which allows billing beyond your plan’s included usage. For individual accounts, enable this in your
Console billing settings
. For Team and Enterprise, an admin must enable extra usage for the organization.
Fast mode usage is billed directly to extra usage, even if you have remaining usage on your plan. This means fast mode tokens do not count against your plan’s included usage and are charged at the fast mode rate from the first token.
Admin enablement for Team and Enterprise
: fast mode is disabled by default for Team and Enterprise organizations. An admin must explicitly
enable fast mode
before users can access it.
If your admin has not enabled fast mode for your organization, the
/fast
command will show “Fast mode has been disabled by your organization.”
​
Enable fast mode for your organization
Admins can enable fast mode in:
Console
(API customers):
Claude Code preferences
Claude AI
(Team and Enterprise):
Admin Settings > Claude Code
Another option to disable fast mode entirely is to set
CLAUDE_CODE_DISABLE_FAST_MODE=1
. See
Environment variables
.
​
Require per-session opt-in
By default, fast mode persists across sessions: if a user enables fast mode, it stays on in future sessions. Administrators on
Team
or
Enterprise
plans can prevent this by setting
fastModePerSessionOptIn
to
true
in
managed settings
or
server-managed settings
. This causes each session to start with fast mode off, requiring users to explicitly enable it with
/fast
.
{
"fastModePerSessionOptIn"
:
true
}
This is useful for controlling costs in organizations where users run multiple concurrent sessions. Users can still enable fast mode with
/fast
when they need speed, but it resets at the start of each new session. The user’s fast mode preference is still saved, so removing this setting restores the default persistent behavior.
​
Handle rate limits
Fast mode has separate rate limits from standard Opus. Fast mode for Opus 4.6 and Opus 4.7 share the same rate limit pool: usage on either model draws from the same limits. When you hit the fast mode rate limit or run out of extra usage:
Fast mode automatically falls back to standard speed on the same Opus version
The
↯
icon turns gray to indicate cooldown
You continue working at standard speed and pricing
When the cooldown expires, fast mode automatically re-enables
To disable fast mode manually instead of waiting for cooldown, run
/fast
again.
​
Research preview
Fast mode is a research preview feature. This means:
The feature may change based on feedback
Availability and pricing are subject to change
The underlying API configuration may evolve
Report issues or feedback through your usual Anthropic support channels.
​
See also
Model configuration
: switch models and adjust effort levels
Manage costs effectively
: track token usage and reduce costs
Status line configuration
: display model and context information
Was this page helpful?
Yes
No
Model configuration
Output styles
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/fast-mode" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Agent SDK reference - Python</title>
  <link>https://code.claude.com/docs/en/agent-sdk/python</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/python</guid>
  <pubDate>Sun, 21 Jul 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - Python
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SD...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - Python
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Installation
pip
install
claude-agent-sdk
​
Choosing between
query()
and
ClaudeSDKClient
The Python SDK provides two ways to interact with Claude Code:
​
Quick comparison
Feature
query()
ClaudeSDKClient
Session
Creates new session each time
Reuses same session
Conversation
Single exchange
Multiple exchanges in same context
Connection
Managed automatically
Manual control
Streaming Input
✅ Supported
✅ Supported
Interrupts
❌ Not supported
✅ Supported
Hooks
✅ Supported
✅ Supported
Custom Tools
✅ Supported
✅ Supported
Continue Chat
❌ New session each time
✅ Maintains conversation
Use Case
One-off tasks
Continuous conversations
​
When to use
query()
(new session each time)
Best for:
One-off questions where you don’t need conversation history
Independent tasks that don’t require context from previous exchanges
Simple automation scripts
When you want a fresh start each time
​
When to use
ClaudeSDKClient
(continuous conversation)
Best for:
Continuing conversations
- When you need Claude to remember context
Follow-up questions
- Building on previous responses
Interactive applications
- Chat interfaces, REPLs
Response-driven logic
- When next action depends on Claude’s response
Session control
- Managing conversation lifecycle explicitly
​
Functions
​
query()
Creates a new session for each interaction with Claude Code. Returns an async iterator that yields messages as they arrive. Each call to
query()
starts fresh with no memory of previous interactions.
async
def
query
(
*
,
prompt
:
str
|
AsyncIterable[dict[
str
, Any]],
options
: ClaudeAgentOptions
|
None
=
None
,
transport
: Transport
|
None
=
None
) -> AsyncIterator[Message]
​
Parameters
Parameter
Type
Description
prompt
str | AsyncIterable[dict]
The input prompt as a string or async iterable for streaming mode
options
ClaudeAgentOptions | None
Optional configuration object (defaults to
ClaudeAgentOptions()
if None)
transport
Transport | None
Optional custom transport for communicating with the CLI process
​
Returns
Returns an
AsyncIterator[Message]
that yields messages from the conversation.
​
Example - With options
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
options
=
ClaudeAgentOptions(
system_prompt
=
"You are an expert Python developer"
,
permission_mode
=
"acceptEdits"
,
cwd
=
"/home/user/project"
,
)
async
for
message
in
query(
prompt
=
"Create a Python web server"
,
options
=
options):
print
(message)
asyncio.run(main())
​
tool()
Decorator for defining MCP tools with type safety.
def
tool
(
name
:
str
,
description
:
str
,
input_schema
:
type
|
dict[
str
, Any],
annotations
: ToolAnnotations
|
None
=
None
) -> Callable[[Callable[[Any], Awaitable[dict[
str
, Any]]]], SdkMcpTool[Any]]
​
Parameters
Parameter
Type
Description
name
str
Unique identifier for the tool
description
str
Human-readable description of what the tool does
input_schema
type | dict[str, Any]
Schema defining the tool’s input parameters (see below)
annotations
ToolAnnotations
| None
Optional MCP tool annotations providing behavioral hints to clients
​
Input schema options
Simple type mapping
(recommended):
{
"text"
:
str
,
"count"
:
int
,
"enabled"
:
bool
}
JSON Schema format
(for complex validation):
{
"type"
:
"object"
,
"properties"
: {
"text"
: {
"type"
:
"string"
},
"count"
: {
"type"
:
"integer"
,
"minimum"
:
0
},
},
"required"
: [
"text"
],
}
​
Returns
A decorator function that wraps the tool implementation and returns an
SdkMcpTool
instance.
​
Example
from
claude_agent_sdk
import
tool
from
typing
import
Any
@tool
(
"greet"
,
"Greet a user"
, {
"name"
:
str
})
async
def
greet
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Hello,
{
args[
'name'
]
}
!"
}]}
​
ToolAnnotations
Re-exported from
mcp.types
(also available as
from claude_agent_sdk import ToolAnnotations
). All fields are optional hints; clients should not rely on them for security decisions.
Field
Type
Default
Description
title
str | None
None
Human-readable title for the tool
readOnlyHint
bool | None
False
If
True
, the tool does not modify its environment
destructiveHint
bool | None
True
If
True
, the tool may perform destructive updates (only meaningful when
readOnlyHint
is
False
)
idempotentHint
bool | None
False
If
True
, repeated calls with the same arguments have no additional effect (only meaningful when
readOnlyHint
is
False
)
openWorldHint
bool | None
True
If
True
, the tool interacts with external entities (for example, web search). If
False
, the tool’s domain is closed (for example, a memory tool)
from
claude_agent_sdk
import
tool, ToolAnnotations
from
typing
import
Any
@tool
(
"search"
,
"Search the web"
,
{
"query"
:
str
},
annotations
=
ToolAnnotations(
readOnlyHint
=
True
,
openWorldHint
=
True
),
)
async
def
search
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Results for:
{
args[
'query'
]
}
"
}]}
​
create_sdk_mcp_server()
Create an in-process MCP server that runs within your Python application.
def
create_sdk_mcp_server
(
name
:
str
,
version
:
str
=
"1.0.0"
,
tools
: list[SdkMcpTool[Any]]
|
None
=
None
) -> McpSdkServerConfig
​
Parameters
Parameter
Type
Default
Description
name
str
-
Unique identifier for the server
version
str
"1.0.0"
Server version string
tools
list[SdkMcpTool[Any]] | None
None
List of tool functions created with
@tool
decorator
​
Returns
Returns an
McpSdkServerConfig
object that can be passed to
ClaudeAgentOptions.mcp_servers
.
​
Example
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
@tool
(
"add"
,
"Add two numbers"
, {
"a"
:
float
,
"b"
:
float
})
async
def
add
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Sum:
{
args[
'a'
]
+
args[
'b'
]
}
"
}]}
@tool
(
"multiply"
,
"Multiply two numbers"
, {
"a"
:
float
,
"b"
:
float
})
async
def
multiply
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Product:
{
args[
'a'
]
*
args[
'b'
]
}
"
}]}
calculator
=
create_sdk_mcp_server(
name
=
"calculator"
,
version
=
"2.0.0"
,
tools
=
[add, multiply],
# Pass decorated functions
)
# Use with Claude
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"calc"
: calculator},
allowed_tools
=
[
"mcp__calc__add"
,
"mcp__calc__multiply"
],
)
​
list_sessions()
Lists past sessions with metadata. Filter by project directory or list sessions across all projects. Synchronous; returns immediately.
def
list_sessions
(
directory
:
str
|
None
=
None
,
limit
:
int
|
None
=
None
,
include_worktrees
:
bool
=
True
) -> list[SDKSessionInfo]
​
Parameters
Parameter
Type
Default
Description
directory
str | None
None
Directory to list sessions for. When omitted, returns sessions across all projects
limit
int | None
None
Maximum number of sessions to return
include_worktrees
bool
True
When
directory
is inside a git repository, include sessions from all worktree paths
​
Return type:
SDKSessionInfo
Property
Type
Description
session_id
str
Unique session identifier
summary
str
Display title: custom title, auto-generated summary, or first prompt
last_modified
int
Last modified time in milliseconds since epoch
file_size
int | None
Session file size in bytes (
None
for remote storage backends)
custom_title
str | None
User-set session title
first_prompt
str | None
First meaningful user prompt in the session
git_branch
str | None
Git branch at the end of the session
cwd
str | None
Working directory for the session
tag
str | None
User-set session tag (see
tag_session()
)
created_at
int | None
Session creation time in milliseconds since epoch
​
Example
Print the 10 most recent sessions for a project. Results are sorted by
last_modified
descending, so the first item is the newest. Omit
directory
to search across all projects.
from
claude_agent_sdk
import
list_sessions
for
session
in
list_sessions(
directory
=
"/path/to/project"
,
limit
=
10
):
print
(
f
"
{
session.summary
}
(
{
session.session_id
}
)"
)
​
get_session_messages()
Retrieves messages from a past session. Synchronous; returns immediately.
def
get_session_messages
(
session_id
:
str
,
directory
:
str
|
None
=
None
,
limit
:
int
|
None
=
None
,
offset
:
int
=
0
) -> list[SessionMessage]
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
The session ID to retrieve messages for
directory
str | None
None
Project directory to look in. When omitted, searches all projects
limit
int | None
None
Maximum number of messages to return
offset
int
0
Number of messages to skip from the start
​
Return type:
SessionMessage
Property
Type
Description
type
Literal["user", "assistant"]
Message role
uuid
str
Unique message identifier
session_id
str
Session identifier
message
Any
Raw message content
parent_tool_use_id
None
Reserved for future use
​
Example
from
claude_agent_sdk
import
list_sessions, get_session_messages
sessions
=
list_sessions(
limit
=
1
)
if
sessions:
messages
=
get_session_messages(sessions[
0
].session_id)
for
msg
in
messages:
print
(
f
"[
{
msg.type
}
]
{
msg.uuid
}
"
)
​
get_session_info()
Reads metadata for a single session by ID without scanning the full project directory. Synchronous; returns immediately.
def
get_session_info
(
session_id
:
str
,
directory
:
str
|
None
=
None
,
) -> SDKSessionInfo
|
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to look up
directory
str | None
None
Project directory path. When omitted, searches all project directories
Returns
SDKSessionInfo
, or
None
if the session is not found.
​
Example
Look up a single session’s metadata without scanning the project directory. Useful when you already have a session ID from a previous run.
from
claude_agent_sdk
import
get_session_info
info
=
get_session_info(
"550e8400-e29b-41d4-a716-446655440000"
)
if
info:
print
(
f
"
{
info.summary
}
(branch:
{
info.git_branch
}
, tag:
{
info.tag
}
)"
)
​
rename_session()
Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins. Synchronous.
def
rename_session
(
session_id
:
str
,
title
:
str
,
directory
:
str
|
None
=
None
,
) ->
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to rename
title
str
required
New title. Must be non-empty after stripping whitespace
directory
str | None
None
Project directory path. When omitted, searches all project directories
Raises
ValueError
if
session_id
is not a valid UUID or
title
is empty;
FileNotFoundError
if the session cannot be found.
​
Example
Rename the most recent session so it’s easier to find later. The new title appears in
SDKSessionInfo.custom_title
on subsequent reads.
from
claude_agent_sdk
import
list_sessions, rename_session
sessions
=
list_sessions(
directory
=
"/path/to/project"
,
limit
=
1
)
if
sessions:
rename_session(sessions[
0
].session_id,
"Refactor auth module"
)
​
tag_session()
Tags a session. Pass
None
to clear the tag. Repeated calls are safe; the most recent tag wins. Synchronous.
def
tag_session
(
session_id
:
str
,
tag
:
str
|
None
,
directory
:
str
|
None
=
None
,
) ->
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to tag
tag
str | None
required
Tag string, or
None
to clear. Unicode-sanitized before storing
directory
str | None
None
Project directory path. When omitted, searches all project directories
Raises
ValueError
if
session_id
is not a valid UUID or
tag
is empty after sanitization;
FileNotFoundError
if the session cannot be found.
​
Example
Tag a session, then filter by that tag on a later read. Pass
None
to clear an existing tag.
from
claude_agent_sdk
import
list_sessions, tag_session
# Tag a session
tag_session(
"550e8400-e29b-41d4-a716-446655440000"
,
"needs-review"
)
# Later: find all sessions with that tag
for
session
in
list_sessions(
directory
=
"/path/to/project"
):
if
session.tag
==
"needs-review"
:
print
(session.summary)
​
Classes
​
ClaudeSDKClient
Maintains a conversation session across multiple exchanges.
This is the Python equivalent of how the TypeScript SDK’s
query()
function works internally - it creates a client object that can continue conversations.
​
Key Features
Session continuity
: Maintains conversation context across multiple
query()
calls
Same conversation
: The session retains previous messages
Interrupt support
: Can stop execution mid-task
Explicit lifecycle
: You control when the session starts and ends
Response-driven flow
: Can react to responses and send follow-ups
Custom tools and hooks
: Supports custom tools (created with
@tool
decorator) and hooks
class
ClaudeSDKClient
:
def
__init__
(
self
,
options
: ClaudeAgentOptions
|
None
=
None
,
transport
: Transport
|
None
=
None
)
async
def
connect
(
self
,
prompt
:
str
|
AsyncIterable[
dict
]
|
None
=
None
) ->
None
async
def
query(
self
, prompt:
str
|
AsyncIterable[
dict
], session_id:
str
=
"default"
)
->
None
async
def
receive_messages(
self
)
->
AsyncIterator[Message]
async
def
receive_response(
self
)
->
AsyncIterator[Message]
async
def
interrupt(
self
)
->
None
async
def
set_permission_mode(
self
, mode:
str
)
->
None
async
def
set_model(
self
, model:
str
|
None
=
None
)
->
None
async
def
rewind_files(
self
, user_message_id:
str
)
->
None
async
def
get_mcp_status(
self
)
->
McpStatusResponse
async
def
reconnect_mcp_server(
self
, server_name:
str
)
->
None
async
def
toggle_mcp_server(
self
, server_name:
str
, enabled:
bool
)
->
None
async
def
stop_task(
self
, task_id:
str
)
->
None
async
def
get_server_info(
self
)
->
dict[
str
, Any]
|
None
async
def
disconnect(
self
)
->
None
​
Methods
Method
Description
__init__(options)
Initialize the client with optional configuration
connect(prompt)
Connect to Claude with an optional initial prompt or message stream
query(prompt, session_id)
Send a new request in streaming mode
receive_messages()
Receive all messages from Claude as an async iterator
receive_response()
Receive messages until and including a ResultMessage
interrupt()
Send interrupt signal (only works in streaming mode)
set_permission_mode(mode)
Change the permission mode for the current session
set_model(model)
Change the model for the current session. Pass
None
to reset to default
rewind_files(user_message_id)
Restore files to their state at the specified user message. Requires
enable_file_checkpointing=True
. See
File checkpointing
get_mcp_status()
Get the status of all configured MCP servers. Returns
McpStatusResponse
reconnect_mcp_server(server_name)
Retry connecting to an MCP server that failed or was disconnected
toggle_mcp_server(server_name, enabled)
Enable or disable an MCP server mid-session. Disabling removes its tools
stop_task(task_id)
Stop a running background task. A
TaskNotificationMessage
with status
"stopped"
follows in the message stream
get_server_info()
Get server information including session ID and capabilities
disconnect()
Disconnect from Claude
​
Context Manager Support
The client can be used as an async context manager for automatic connection management:
async
with
ClaudeSDKClient()
as
client:
await
client.query(
"Hello Claude"
)
async
for
message
in
client.receive_response():
print
(message)
Important:
When iterating over messages, avoid using
break
to exit early as this can cause asyncio cleanup issues. Instead, let the iteration complete naturally or use flags to track when you’ve found what you need.
​
Example - Continuing a conversation
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async
def
main
():
async
with
ClaudeSDKClient()
as
client:
# First question
await
client.query(
"What's the capital of France?"
)
# Process response
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
# Follow-up question - the session retains the previous context
await
client.query(
"What's the population of that city?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
# Another follow-up - still in the same conversation
await
client.query(
"What are some famous landmarks there?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
asyncio.run(main())
​
Example - Streaming input with ClaudeSDKClient
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient
async
def
message_stream
():
"""Generate messages dynamically."""
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Analyze the following data:"
},
}
await
asyncio.sleep(
0.5
)
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Temperature: 25°C, Humidity: 60%"
},
}
await
asyncio.sleep(
0.5
)
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"What patterns do you see?"
},
}
async
def
main
():
async
with
ClaudeSDKClient()
as
client:
# Stream input to Claude
await
client.query(message_stream())
# Process response
async
for
message
in
client.receive_response():
print
(message)
# Follow-up in same session
await
client.query(
"Should we be concerned about these readings?"
)
async
for
message
in
client.receive_response():
print
(message)
asyncio.run(main())
​
Example - Using interrupts
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async
def
interruptible_task
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Bash"
],
permission_mode
=
"acceptEdits"
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
# Start a long-running task
await
client.query(
"Count from 1 to 100 slowly, using the bash sleep command"
)
# Let it run for a bit
await
asyncio.sleep(
2
)
# Interrupt the task
await
client.interrupt()
print
(
"Task interrupted!"
)
# Drain the interrupted task's messages (including its ResultMessage)
async
for
message
in
client.receive_response():
if
isinstance
(message, ResultMessage):
print
(
f
"Interrupted task finished with subtype=
{
message.subtype
!r}
"
)
# subtype is "error_during_execution" for interrupted tasks
# Send a new command
await
client.query(
"Just say hello instead"
)
# Now receive the new response
async
for
message
in
client.receive_response():
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"New result:
{
message.result
}
"
)
asyncio.run(interruptible_task())
Buffer behavior after interrupt:
interrupt()
sends a stop signal but does not clear the message buffer. Messages already produced by the interrupted task, including its
ResultMessage
(with
subtype="error_during_execution"
), remain in the stream. You must drain them with
receive_response()
before reading the response to a new query. If you send a new query immediately after
interrupt()
and call
receive_response()
only once, you’ll receive the interrupted task’s messages, not the new query’s response.
​
Example - Advanced permission control
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions
from
claude_agent_sdk.types
import
(
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
custom_permission_handler
(
tool_name
:
str
,
input_data
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
"""Custom logic for tool permissions."""
# Block writes to system directories
if
tool_name
==
"Write"
and
input_data.get(
"file_path"
,
""
).startswith(
"/system/"
):
return
PermissionResultDeny(
message
=
"System directory write not allowed"
,
interrupt
=
True
)
# Redirect sensitive file operations
if
tool_name
in
[
"Write"
,
"Edit"
]
and
"config"
in
input_data.get(
"file_path"
,
""
):
safe_path
=
f
"./sandbox/
{
input_data[
'file_path'
]
}
"
return
PermissionResultAllow(
updated_input
=
{
**
input_data,
"file_path"
: safe_path}
)
# Allow everything else
return
PermissionResultAllow(
updated_input
=
input_data)
async
def
main
():
options
=
ClaudeAgentOptions(
can_use_tool
=
custom_permission_handler,
allowed_tools
=
[
"Read"
,
"Write"
,
"Edit"
]
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Update the system config file"
)
async
for
message
in
client.receive_response():
# Will use sandbox path instead
print
(message)
asyncio.run(main())
​
Types
@dataclass
vs
TypedDict
:
This SDK uses two kinds of types. Classes decorated with
@dataclass
(such as
ResultMessage
,
AgentDefinition
,
TextBlock
) are object instances at runtime and support attribute access:
msg.result
. Classes defined with
TypedDict
(such as
ThinkingConfigEnabled
,
McpStdioServerConfig
,
SyncHookJSONOutput
) are
plain dicts at runtime
and require key access:
config["budget_tokens"]
, not
config.budget_tokens
. The
ClassName(field=value)
call syntax works for both, but only dataclasses produce objects with attributes.
​
SdkMcpTool
Definition for an SDK MCP tool created with the
@tool
decorator.
@dataclass
class
SdkMcpTool
(Generic[T]):
name:
str
description:
str
input_schema: type[T]
|
dict[
str
, Any]
handler: Callable[[T], Awaitable[dict[
str
, Any]]]
annotations: ToolAnnotations
|
None
=
None
Property
Type
Description
name
str
Unique identifier for the tool
description
str
Human-readable description
input_schema
type[T] | dict[str, Any]
Schema for input validation
handler
Callable[[T], Awaitable[dict[str, Any]]]
Async function that handles tool execution
annotations
ToolAnnotations | None
Optional MCP tool annotations (e.g.,
readOnlyHint
,
destructiveHint
,
openWorldHint
). From
mcp.types
​
Transport
Abstract base class for custom transport implementations. Use this to communicate with the Claude process over a custom channel (for example, a remote connection instead of a local subprocess).
This is a low-level internal API. The interface may change in future releases. Custom implementations must be updated to match any interface changes.
from
abc
import
ABC
, abstractmethod
from
collections.abc
import
AsyncIterator
from
typing
import
Any
class
Transport
(
ABC
):
@abstractmethod
async
def
connect
(
self
) ->
None
:
...
@abstractmethod
async
def
write
(
self
,
data
:
str
) ->
None
:
...
@abstractmethod
def
read_messages
(
self
) -> AsyncIterator[dict[
str
, Any]]:
...
@abstractmethod
async
def
close
(
self
) ->
None
:
...
@abstractmethod
def
is_ready
(
self
) ->
bool
:
...
@abstractmethod
async
def
end_input
(
self
) ->
None
:
...
Method
Description
connect()
Connect the transport and prepare for communication
write(data)
Write raw data (JSON + newline) to the transport
read_messages()
Async iterator that yields parsed JSON messages
close()
Close the connection and clean up resources
is_ready()
Returns
True
if the transport can send and receive
end_input()
Close the input stream (for example, close stdin for subprocess transports)
Import:
from claude_agent_sdk import Transport
​
ClaudeAgentOptions
Configuration dataclass for Claude Code queries.
@dataclass
class
ClaudeAgentOptions
:
tools: list[
str
]
|
ToolsPreset
|
None
=
None
allowed_tools: list[
str
]
=
field(
default_factory
=
list
)
system_prompt:
str
|
SystemPromptPreset
|
None
=
None
mcp_servers: dict[
str
, McpServerConfig]
|
str
|
Path
=
field(
default_factory
=
dict
)
strict_mcp_config:
bool
=
False
permission_mode: PermissionMode
|
None
=
None
continue_conversation:
bool
=
False
resume:
str
|
None
=
None
max_turns:
int
|
None
=
None
max_budget_usd:
float
|
None
=
None
disallowed_tools: list[
str
]
=
field(
default_factory
=
list
)
model:
str
|
None
=
None
fallback_model:
str
|
None
=
None
betas: list[SdkBeta]
=
field(
default_factory
=
list
)
output_format: dict[
str
, Any]
|
None
=
None
permission_prompt_tool_name:
str
|
None
=
None
cwd:
str
|
Path
|
None
=
None
cli_path:
str
|
Path
|
None
=
None
settings:
str
|
None
=
None
add_dirs: list[
str
|
Path]
=
field(
default_factory
=
list
)
env: dict[
str
,
str
]
=
field(
default_factory
=
dict
)
extra_args: dict[
str
,
str
|
None
]
=
field(
default_factory
=
dict
)
max_buffer_size:
int
|
None
=
None
debug_stderr: Any
=
sys.stderr
# Deprecated
stderr: Callable[[
str
],
None
]
|
None
=
None
can_use_tool: CanUseTool
|
None
=
None
hooks: dict[HookEvent, list[HookMatcher]]
|
None
=
None
user:
str
|
None
=
None
include_partial_messages:
bool
=
False
include_hook_events:
bool
=
False
fork_session:
bool
=
False
agents: dict[
str
, AgentDefinition]
|
None
=
None
setting_sources: list[SettingSource]
|
None
=
None
sandbox: SandboxSettings
|
None
=
None
plugins: list[SdkPluginConfig]
=
field(
default_factory
=
list
)
max_thinking_tokens:
int
|
None
=
None
# Deprecated: use thinking instead
thinking: ThinkingConfig
|
None
=
None
effort: Literal[
"low"
,
"medium"
,
"high"
,
"xhigh"
,
"max"
]
|
None
=
None
enable_file_checkpointing:
bool
=
False
session_store: SessionStore
|
None
=
None
session_store_flush: SessionStoreFlushMode
=
"batched"
Property
Type
Default
Description
tools
list[str] | ToolsPreset | None
None
Tools configuration. Use
{"type": "preset", "preset": "claude_code"}
for Claude Code’s default tools
allowed_tools
list[str]
[]
Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to
permission_mode
and
can_use_tool
. Use
disallowed_tools
to block tools. See
Permissions
system_prompt
str | SystemPromptPreset | None
None
System prompt configuration. Pass a string for custom prompt, or use
{"type": "preset", "preset": "claude_code"}
for Claude Code’s system prompt. Add
"append"
to extend the preset
mcp_servers
dict[str, McpServerConfig] | str | Path
{}
MCP server configurations or path to config file
strict_mcp_config
bool
False
When
True
, use only the servers passed in
mcp_servers
and ignore project
.mcp.json
, user settings, and plugin-provided MCP servers. Maps to the CLI
--strict-mcp-config
flag
permission_mode
PermissionMode | None
None
Permission mode for tool usage
continue_conversation
bool
False
Continue the most recent conversation
resume
str | None
None
Session ID to resume
max_turns
int | None
None
Maximum agentic turns (tool-use round trips)
max_budget_usd
float | None
None
Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as
total_cost_usd
; see
Track cost and usage
for accuracy caveats
disallowed_tools
list[str]
[]
Tools to always deny. Deny rules are checked first and override
allowed_tools
and
permission_mode
(including
bypassPermissions
)
enable_file_checkpointing
bool
False
Enable file change tracking for rewinding. See
File checkpointing
model
str | None
None
Claude model to use
fallback_model
str | None
None
Fallback model to use if the primary model fails
betas
list[SdkBeta]
[]
Beta features to enable. See
SdkBeta
for available options
output_format
dict[str, Any] | None
None
Output format for structured responses (e.g.,
{"type": "json_schema", "schema": {...}}
). See
Structured outputs
for details
permission_prompt_tool_name
str | None
None
MCP tool name for permission prompts
cwd
str | Path | None
None
Current working directory
cli_path
str | Path | None
None
Custom path to the Claude Code CLI executable
settings
str | None
None
Path to settings file
add_dirs
list[str | Path]
[]
Additional directories Claude can access
env
dict[str, str]
{}
Environment variables merged on top of the inherited process environment. See
Environment variables
for variables the underlying CLI reads, and
Handle slow or stalled API responses
for timeout-related variables
extra_args
dict[str, str | None]
{}
Additional CLI arguments to pass directly to the CLI
max_buffer_size
int | None
None
Maximum bytes when buffering CLI stdout
debug_stderr
Any
sys.stderr
Deprecated
- File-like object for debug output. Use
stderr
callback instead
stderr
Callable[[str], None] | None
None
Callback function for stderr output from CLI
can_use_tool
CanUseTool
| None
None
Tool permission callback function. See
Permission types
for details
hooks
dict[HookEvent, list[HookMatcher]] | None
None
Hook configurations for intercepting events
user
str | None
None
User identifier
include_partial_messages
bool
False
Include partial message streaming events. When enabled,
StreamEvent
messages are yielded
include_hook_events
bool
False
Include hook lifecycle events in the message stream as
HookEventMessage
objects
fork_session
bool
False
When resuming with
resume
, fork to a new session ID instead of continuing the original session
agents
dict[str, AgentDefinition] | None
None
Programmatically defined subagents
plugins
list[SdkPluginConfig]
[]
Load custom plugins from local paths. See
Plugins
for details
sandbox
SandboxSettings
| None
None
Configure sandbox behavior programmatically. See
Sandbox settings
for details
setting_sources
list[SettingSource] | None
None
(CLI defaults: all sources)
Control which filesystem settings to load. Pass
[]
to disable user, project, and local settings. Managed policy settings load regardless. See
Use Claude Code features
skills
list[str] | Literal["all"] | None
None
Skills available to the session. Pass
"all"
to enable every discovered skill, or a list of skill names. When set, the SDK enables the Skill tool automatically without listing it in
allowed_tools
. See
Skills
max_thinking_tokens
int | None
None
Deprecated
- Maximum tokens for thinking blocks. Use
thinking
instead
thinking
ThinkingConfig
| None
None
Controls extended thinking behavior. Takes precedence over
max_thinking_tokens
effort
Literal["low", "medium", "high", "xhigh", "max"] | None
None
Effort level for thinking depth
session_store
SessionStore
| None
None
Mirror session transcripts to an external backend so any host can resume them. See
Persist sessions to external storage
session_store_flush
Literal["batched", "eager"]
"batched"
When to flush mirrored transcript entries to
session_store
.
"batched"
flushes once per turn or when the buffer fills;
"eager"
triggers a background flush after every frame. Ignored when
session_store
is
None
​
Handle slow or stalled API responses
The CLI subprocess reads several environment variables that control API timeouts and stall detection. Pass them through
ClaudeAgentOptions.env
:
options
=
ClaudeAgentOptions(
env
=
{
"API_TIMEOUT_MS"
:
"120000"
,
"CLAUDE_CODE_MAX_RETRIES"
:
"2"
,
"CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS"
:
"120000"
,
},
)
API_TIMEOUT_MS
: per-request timeout on the Anthropic client, in milliseconds. Default
600000
. Applies to the main loop and all subagents.
CLAUDE_CODE_MAX_RETRIES
: maximum API retries. Default
10
. Each retry gets its own
API_TIMEOUT_MS
window, so worst-case wall time is roughly
API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)
plus backoff.
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
: stall watchdog for subagents launched with
run_in_background
. Default
600000
. Resets on each stream event; on stall it aborts the subagent, marks the task failed, and surfaces the error to the parent with any partial result. Does not apply to synchronous subagents.
CLAUDE_ENABLE_STREAM_WATCHDOG=1
with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
: aborts the request when headers have arrived but the response body stops streaming. Off by default.
CLAUDE_STREAM_IDLE_TIMEOUT_MS
defaults to
300000
and is clamped to that minimum. The aborted request goes through the normal retry path.
​
OutputFormat
Configuration for structured output validation. Pass this as a
dict
to the
output_format
field on
ClaudeAgentOptions
:
# Expected dict shape for output_format
{
"type"
:
"json_schema"
,
"schema"
: {
...
},
# Your JSON Schema definition
}
Field
Required
Description
type
Yes
Must be
"json_schema"
for JSON Schema validation
schema
Yes
JSON Schema definition for output validation
​
SystemPromptPreset
Configuration for using Claude Code’s preset system prompt with optional additions.
class
SystemPromptPreset
(
TypedDict
):
type
: Literal[
"preset"
]
preset: Literal[
"claude_code"
]
append: NotRequired[
str
]
exclude_dynamic_sections: NotRequired[
bool
]
Field
Required
Description
type
Yes
Must be
"preset"
to use a preset system prompt
preset
Yes
Must be
"claude_code"
to use Claude Code’s system prompt
append
No
Additional instructions to append to the preset system prompt
exclude_dynamic_sections
No
Move per-session context such as working directory, the git-repo flag, and auto-memory paths from the system prompt into the first user message. Improves prompt-cache reuse across users and machines. See
Modify system prompts
​
SettingSource
Controls which filesystem-based configuration sources the SDK loads settings from.
SettingSource
=
Literal[
"user"
,
"project"
,
"local"
]
Value
Description
Location
"user"
Global user settings
~/.claude/settings.json
"project"
Shared project settings (version controlled)
.claude/settings.json
"local"
Local project settings (gitignored)
.claude/settings.local.json
​
Default behavior
When
setting_sources
is omitted or
None
,
query()
loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See
What settingSources does not control
for inputs that are read regardless of this option, and how to disable them.
​
Why use setting_sources
Disable filesystem settings:
# Do not load user, project, or local settings from disk
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
for
message
in
query(
prompt
=
"Analyze this code"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[]
),
):
print
(message)
In Python SDK 0.1.59 and earlier, an empty list was treated the same as omitting the option, so
setting_sources=[]
did not disable filesystem settings. Upgrade to a newer release if you need an empty list to take effect. The TypeScript SDK is not affected.
Load all filesystem settings explicitly:
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
for
message
in
query(
prompt
=
"Analyze this code"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
,
"local"
]
),
):
print
(message)
Load only specific setting sources:
# Load only project settings, ignore user and local
async
for
message
in
query(
prompt
=
"Run CI checks"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
]
# Only .claude/settings.json
),
):
print
(message)
Testing and CI environments:
# Ensure consistent behavior in CI by excluding local settings
async
for
message
in
query(
prompt
=
"Run tests"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Only team-shared settings
permission_mode
=
"bypassPermissions"
,
),
):
print
(message)
SDK-only applications:
# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
async
for
message
in
query(
prompt
=
"Review this PR"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[],
agents
=
{
...
},
mcp_servers
=
{
...
},
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
),
):
print
(message)
Loading CLAUDE.md project instructions:
# Load project settings to include CLAUDE.md files
async
for
message
in
query(
prompt
=
"Add a new feature following project conventions"
,
options
=
ClaudeAgentOptions(
system_prompt
=
{
"type"
:
"preset"
,
"preset"
:
"claude_code"
,
# Use Claude Code's system prompt
},
setting_sources
=
[
"project"
],
# Loads CLAUDE.md from project
allowed_tools
=
[
"Read"
,
"Write"
,
"Edit"
],
),
):
print
(message)
​
Settings precedence
When multiple sources are loaded, settings are merged with this precedence (highest to lowest):
Local settings (
.claude/settings.local.json
)
Project settings (
.claude/settings.json
)
User settings (
~/.claude/settings.json
)
Programmatic options such as
agents
and
allowed_tools
override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.
​
AgentDefinition
Configuration for a subagent defined programmatically.
@dataclass
class
AgentDefinition
:
description:
str
prompt:
str
tools: list[
str
]
|
None
=
None
disallowedTools: list[
str
]
|
None
=
None
model:
str
|
None
=
None
skills: list[
str
]
|
None
=
None
memory: Literal[
"user"
,
"project"
,
"local"
]
|
None
=
None
mcpServers: list[
str
|
dict[
str
, Any]]
|
None
=
None
initialPrompt:
str
|
None
=
None
maxTurns:
int
|
None
=
None
background:
bool
|
None
=
None
effort: Literal[
"low"
,
"medium"
,
"high"
,
"xhigh"
,
"max"
]
|
int
|
None
=
None
permissionMode: PermissionMode
|
None
=
None
Field
Required
Description
description
Yes
Natural language description of when to use this agent
prompt
Yes
The agent’s system prompt
tools
No
Array of allowed tool names. If omitted, inherits all tools
disallowedTools
No
Array of tool names to remove from the agent’s tool set
model
No
Model override for this agent. Accepts an alias such as
"sonnet"
,
"opus"
,
"haiku"
, or
"inherit"
, or a full model ID. If omitted, uses the main model
skills
No
List of skill names to preload into the agent’s context at startup. Unlisted skills remain invocable through the Skill tool
memory
No
Memory source for this agent:
"user"
,
"project"
, or
"local"
mcpServers
No
MCP servers available to this agent. Each entry is a server name or an inline
{name: config}
dict
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main thread agent
maxTurns
No
Maximum number of agentic turns before the agent stops
background
No
Run this agent as a non-blocking background task when invoked
effort
No
Reasoning effort level for this agent. Accepts a named level or an integer
permissionMode
No
Permission mode for tool execution within this agent. See
PermissionMode
AgentDefinition
field names use camelCase, such as
disallowedTools
,
permissionMode
, and
maxTurns
. These names map directly to the wire format shared with the TypeScript SDK. This differs from
ClaudeAgentOptions
, which uses Python snake_case for the equivalent top-level fields such as
disallowed_tools
and
permission_mode
. Because
AgentDefinition
is a dataclass, passing a snake_case keyword raises a
TypeError
at construction time.
​
PermissionMode
Permission modes for controlling tool execution.
PermissionMode
=
Literal[
"default"
,
# Standard permission behavior
"acceptEdits"
,
# Auto-accept file edits
"plan"
,
# Planning mode - read-only tools only
"dontAsk"
,
# Deny anything not pre-approved instead of prompting
"bypassPermissions"
,
# Bypass all permission checks (use with caution)
]
​
CanUseTool
Type alias for tool permission callback functions.
CanUseTool
=
Callable[
[
str
, dict[
str
, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
The callback receives:
tool_name
: Name of the tool being called
input_data
: The tool’s input parameters
context
: A
ToolPermissionContext
with additional information
Returns a
PermissionResult
(either
PermissionResultAllow
or
PermissionResultDeny
).
​
ToolPermissionContext
Context information passed to tool permission callbacks.
@dataclass
class
ToolPermissionContext
:
signal: Any
|
None
=
None
# Future: abort signal support
suggestions: list[PermissionUpdate]
=
field(
default_factory
=
list
)
blocked_path:
str
|
None
=
None
decision_reason:
str
|
None
=
None
title:
str
|
None
=
None
display_name:
str
|
None
=
None
description:
str
|
None
=
None
Field
Type
Description
signal
Any | None
Reserved for future abort signal support
suggestions
list[PermissionUpdate]
Permission update suggestions from the CLI. Bash prompts include a suggestion with the
localSettings
destination, so returning it in
updated_permissions
writes the rule to
.claude/settings.local.json
and persists across sessions.
blocked_path
str | None
File path that triggered the permission request, when applicable. For example, when a Bash command tries to access a path outside allowed directories
decision_reason
str | None
Reason this permission request was triggered. Forwarded from a PreToolUse hook’s
permissionDecisionReason
when the hook returned
"ask"
title
str | None
Full permission prompt sentence, such as
Claude wants to read foo.txt
. Use as the primary prompt text when present
display_name
str | None
Short noun phrase for the tool action, such as
Read file
, suitable for button labels
description
str | None
Human-readable subtitle for the permission UI
​
PermissionResult
Union type for permission callback results.
PermissionResult
=
PermissionResultAllow
|
PermissionResultDeny
​
PermissionResultAllow
Result indicating the tool call should be allowed.
@dataclass
class
PermissionResultAllow
:
behavior: Literal[
"allow"
]
=
"allow"
updated_input: dict[
str
, Any]
|
None
=
None
updated_permissions: list[PermissionUpdate]
|
None
=
None
Field
Type
Default
Description
behavior
Literal["allow"]
"allow"
Must be “allow”
updated_input
dict[str, Any] | None
None
Modified input to use instead of original
updated_permissions
list[PermissionUpdate] | None
None
Permission updates to apply
​
PermissionResultDeny
Result indicating the tool call should be denied.
@dataclass
class
PermissionResultDeny
:
behavior: Literal[
"deny"
]
=
"deny"
message:
str
=
""
interrupt:
bool
=
False
Field
Type
Default
Description
behavior
Literal["deny"]
"deny"
Must be “deny”
message
str
""
Message explaining why the tool was denied
interrupt
bool
False
Whether to interrupt the current execution
​
PermissionUpdate
Configuration for updating permissions programmatically.
@dataclass
class
PermissionUpdate
:
type
: Literal[
"addRules"
,
"replaceRules"
,
"removeRules"
,
"setMode"
,
"addDirectories"
,
"removeDirectories"
,
]
rules: list[PermissionRuleValue]
|
None
=
None
behavior: Literal[
"allow"
,
"deny"
,
"ask"
]
|
None
=
None
mode: PermissionMode
|
None
=
None
directories: list[
str
]
|
None
=
None
destination: (
Literal[
"userSettings"
,
"projectSettings"
,
"localSettings"
,
"session"
]
|
None
)
=
None
Field
Type
Description
type
Literal[...]
The type of permission update operation
rules
list[PermissionRuleValue] | None
Rules for add/replace/remove operations
behavior
Literal["allow", "deny", "ask"] | None
Behavior for rule-based operations
mode
PermissionMode | None
Mode for setMode operation
directories
list[str] | None
Directories for add/remove directory operations
destination
Literal[...] | None
Where to apply the permission update
​
PermissionRuleValue
A rule to add, replace, or remove in a permission update.
@dataclass
class
PermissionRuleValue
:
tool_name:
str
rule_content:
str
|
None
=
None
​
ToolsPreset
Preset tools configuration for using Claude Code’s default tool set.
class
ToolsPreset
(
TypedDict
):
type
: Literal[
"preset"
]
preset: Literal[
"claude_code"
]
​
ThinkingConfig
Controls extended thinking behavior. A union of three configurations:
class
ThinkingConfigAdaptive
(
TypedDict
):
type
: Literal[
"adaptive"
]
class
ThinkingConfigEnabled
(
TypedDict
):
type
: Literal[
"enabled"
]
budget_tokens:
int
class
ThinkingConfigDisabled
(
TypedDict
):
type
: Literal[
"disabled"
]
ThinkingConfig
=
ThinkingConfigAdaptive
|
ThinkingConfigEnabled
|
ThinkingConfigDisabled
Variant
Fields
Description
adaptive
type
Claude adaptively decides when to think
enabled
type
,
budget_tokens
Enable thinking with a specific token budget
disabled
type
Disable thinking
Because these are
TypedDict
classes, they’re plain dicts at runtime. Either construct them as dict literals or call the class like a constructor; both produce a
dict
. Access fields with
config["budget_tokens"]
, not
config.budget_tokens
:
from
claude_agent_sdk
import
ClaudeAgentOptions, ThinkingConfigEnabled
# Option 1: dict literal (recommended, no import needed)
options
=
ClaudeAgentOptions(
thinking
=
{
"type"
:
"enabled"
,
"budget_tokens"
:
20000
})
# Option 2: constructor-style (returns a plain dict)
config
=
ThinkingConfigEnabled(
type
=
"enabled"
,
budget_tokens
=
20000
)
print
(config[
"budget_tokens"
])
# 20000
# config.budget_tokens would raise AttributeError
​
SdkBeta
Literal type for SDK beta features.
SdkBeta
=
Literal[
"context-1m-2025-08-07"
]
Use with the
betas
field in
ClaudeAgentOptions
to enable beta features.
The
context-1m-2025-08-07
beta is retired as of April 30, 2026. Passing this header with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to
Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7
, which include 1M context at standard pricing with no beta header required.
​
McpSdkServerConfig
Configuration for SDK MCP servers created with
create_sdk_mcp_server()
.
class
McpSdkServerConfig
(
TypedDict
):
type
: Literal[
"sdk"
]
name:
str
instance: Any
# MCP Server instance
​
McpServerConfig
Union type for MCP server configurations.
McpServerConfig
=
(
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfig
)
​
McpStdioServerConfig
class
McpStdioServerConfig
(
TypedDict
):
type
: NotRequired[Literal[
"stdio"
]]
# Optional for backwards compatibility
command:
str
args: NotRequired[list[
str
]]
env: NotRequired[dict[
str
,
str
]]
​
McpSSEServerConfig
class
McpSSEServerConfig
(
TypedDict
):
type
: Literal[
"sse"
]
url:
str
headers: NotRequired[dict[
str
,
str
]]
​
McpHttpServerConfig
class
McpHttpServerConfig
(
TypedDict
):
type
: Literal[
"http"
]
url:
str
headers: NotRequired[dict[
str
,
str
]]
​
McpServerStatusConfig
The configuration of an MCP server as reported by
get_mcp_status()
. This is the union of all
McpServerConfig
transport variants plus an output-only
claudeai-proxy
variant for servers proxied through claude.ai.
McpServerStatusConfig
=
(
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfigStatus
|
McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus
is the serializable form of
McpSdkServerConfig
with only
type
(
"sdk"
) and
name
(
str
) fields; the in-process
instance
is omitted.
McpClaudeAIProxyServerConfig
has
type
(
"claudeai-proxy"
),
url
(
str
), and
id
(
str
) fields.
​
McpStatusResponse
Response from
ClaudeSDKClient.get_mcp_status()
. Wraps the list of server statuses under the
mcpServers
key.
class
McpStatusResponse
(
TypedDict
):
mcpServers: list[McpServerStatus]
​
McpServerStatus
Status of a connected MCP server, contained in
McpStatusResponse
.
class
McpServerStatus
(
TypedDict
):
name:
str
status: McpServerConnectionStatus
# "connected" | "failed" | "needs-auth" | "pending" | "disabled"
serverInfo: NotRequired[McpServerInfo]
error: NotRequired[
str
]
config: NotRequired[McpServerStatusConfig]
scope: NotRequired[
str
]
tools: NotRequired[list[McpToolInfo]]
Field
Type
Description
name
str
Server name
status
str
One of
"connected"
,
"failed"
,
"needs-auth"
,
"pending"
, or
"disabled"
serverInfo
dict
(optional)
Server name and version (
{"name": str, "version": str}
)
error
str
(optional)
Error message if the server failed to connect
config
McpServerStatusConfig
(optional)
Server configuration. Same shape as
McpServerConfig
(stdio, SSE, HTTP, or SDK), plus a
claudeai-proxy
variant for servers connected through claude.ai
scope
str
(optional)
Configuration scope
tools
list
(optional)
Tools provided by this server, each with
name
,
description
, and
annotations
fields
​
SdkPluginConfig
Configuration for loading plugins in the SDK.
class
SdkPluginConfig
(
TypedDict
):
type
: Literal[
"local"
]
path:
str
Field
Type
Description
type
Literal["local"]
Must be
"local"
(only local plugins currently supported)
path
str
Absolute or relative path to the plugin directory
Example:
plugins
=
[
{
"type"
:
"local"
,
"path"
:
"./my-plugin"
},
{
"type"
:
"local"
,
"path"
:
"/absolute/path/to/plugin"
},
]
For complete information on creating and using plugins, see
Plugins
.
​
Message Types
​
Message
Union type of all possible messages.
Message
=
(
UserMessage
|
AssistantMessage
|
SystemMessage
|
ResultMessage
|
StreamEvent
|
RateLimitEvent
)
​
UserMessage
User input message.
@dataclass
class
UserMessage
:
content:
str
|
list[ContentBlock]
uuid:
str
|
None
=
None
parent_tool_use_id:
str
|
None
=
None
tool_use_result: dict[
str
, Any]
|
None
=
None
Field
Type
Description
content
str | list[ContentBlock]
Message content as text or content blocks
uuid
str | None
Unique message identifier
parent_tool_use_id
str | None
Tool use ID if this message is a tool result response
tool_use_result
dict[str, Any] | None
Tool result data if applicable
​
AssistantMessage
Assistant response message with content blocks.
@dataclass
class
AssistantMessage
:
content: list[ContentBlock]
model:
str
parent_tool_use_id:
str
|
None
=
None
error: AssistantMessageError
|
None
=
None
usage: dict[
str
, Any]
|
None
=
None
message_id:
str
|
None
=
None
Field
Type
Description
content
list[ContentBlock]
List of content blocks in the response
model
str
Model that generated the response
parent_tool_use_id
str | None
Tool use ID if this is a nested response
error
AssistantMessageError
| None
Error type if the response encountered an error
usage
dict[str, Any] | None
Per-message token usage (same keys as
ResultMessage.usage
)
message_id
str | None
API message ID. Multiple messages from one turn share the same ID
​
AssistantMessageError
Possible error types for assistant messages.
AssistantMessageError
=
Literal[
"authentication_failed"
,
"billing_error"
,
"rate_limit"
,
"invalid_request"
,
"server_error"
,
"max_output_tokens"
,
"unknown"
,
]
​
SystemMessage
System message with metadata.
@dataclass
class
SystemMessage
:
subtype:
str
data: dict[
str
, Any]
​
ResultMessage
Final result message with cost and usage information.
@dataclass
class
ResultMessage
:
subtype:
str
duration_ms:
int
duration_api_ms:
int
is_error:
bool
num_turns:
int
session_id:
str
stop_reason:
str
|
None
=
None
total_cost_usd:
float
|
None
=
None
usage: dict[
str
, Any]
|
None
=
None
result:
str
|
None
=
None
structured_output: Any
=
None
model_usage: dict[
str
, Any]
|
None
=
None
permission_denials: list[Any]
|
None
=
None
deferred_tool_use: DeferredToolUse
|
None
=
None
errors: list[
str
]
|
None
=
None
api_error_status:
int
|
None
=
None
uuid:
str
|
None
=
None
The
usage
dict contains the following keys when present:
Key
Type
Description
input_tokens
int
Total input tokens consumed.
output_tokens
int
Total output tokens generated.
cache_creation_input_tokens
int
Tokens used to create new cache entries.
cache_read_input_tokens
int
Tokens read from existing cache entries.
The
model_usage
dict maps model names to per-model usage. The inner dict keys use camelCase because the value is passed through unmodified from the underlying CLI process, matching the TypeScript
ModelUsage
type:
Key
Type
Description
inputTokens
int
Input tokens for this model.
outputTokens
int
Output tokens for this model.
cacheReadInputTokens
int
Cache read tokens for this model.
cacheCreationInputTokens
int
Cache creation tokens for this model.
webSearchRequests
int
Web search requests made by this model.
costUSD
float
Estimated cost in USD for this model, computed client-side. See
Track cost and usage
for billing caveats.
contextWindow
int
Context window size for this model.
maxOutputTokens
int
Maximum output token limit for this model.
​
StreamEvent
Stream event for partial message updates during streaming. Only received when
include_partial_messages=True
in
ClaudeAgentOptions
. Import via
from claude_agent_sdk.types import StreamEvent
.
@dataclass
class
StreamEvent
:
uuid:
str
session_id:
str
event: dict[
str
, Any]
# The raw Claude API stream event
parent_tool_use_id:
str
|
None
=
None
Field
Type
Description
uuid
str
Unique identifier for this event
session_id
str
Session identifier
event
dict[str, Any]
The raw Claude API stream event data
parent_tool_use_id
str | None
Parent tool use ID if this event is from a subagent
​
RateLimitEvent
Emitted when rate limit status changes (for example, from
"allowed"
to
"allowed_warning"
). Use this to warn users before they hit a hard limit, or to back off when status is
"rejected"
.
@dataclass
class
RateLimitEvent
:
rate_limit_info: RateLimitInfo
uuid:
str
session_id:
str
Field
Type
Description
rate_limit_info
RateLimitInfo
Current rate limit state
uuid
str
Unique event identifier
session_id
str
Session identifier
​
RateLimitInfo
Rate limit state carried by
RateLimitEvent
.
RateLimitStatus
=
Literal[
"allowed"
,
"allowed_warning"
,
"rejected"
]
RateLimitType
=
Literal[
"five_hour"
,
"seven_day"
,
"seven_day_opus"
,
"seven_day_sonnet"
,
"overage"
]
@dataclass
class
RateLimitInfo
:
status: RateLimitStatus
resets_at:
int
|
None
=
None
rate_limit_type: RateLimitType
|
None
=
None
utilization:
float
|
None
=
None
overage_status: RateLimitStatus
|
None
=
None
overage_resets_at:
int
|
None
=
None
overage_disabled_reason:
str
|
None
=
None
raw: dict[
str
, Any]
=
field(
default_factory
=
dict
)
Field
Type
Description
status
RateLimitStatus
Current status.
"allowed_warning"
means approaching the limit;
"rejected"
means the limit was hit
resets_at
int | None
Unix timestamp when the rate limit window resets
rate_limit_type
RateLimitType | None
Which rate limit window applies
utilization
float | None
Fraction of the rate limit consumed (0.0 to 1.0)
overage_status
RateLimitStatus | None
Status of pay-as-you-go overage usage, if applicable
overage_resets_at
int | None
Unix timestamp when the overage window resets
overage_disabled_reason
str | None
Why overage is unavailable, if status is
"rejected"
raw
dict[str, Any]
Full raw dict from the CLI, including fields not modeled above
​
TaskStartedMessage
Emitted when a background task starts. A background task is anything tracked outside the main turn: a backgrounded Bash command, a
Monitor
watch, a subagent spawned via the Agent tool, or a remote agent. The
task_type
field tells you which. This naming is unrelated to the
Task
-to-
Agent
tool rename.
@dataclass
class
TaskStartedMessage
(
SystemMessage
):
task_id:
str
description:
str
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
task_type:
str
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
description
str
Description of the task
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
task_type
str | None
Which kind of background task:
"local_bash"
for background Bash and Monitor watches,
"local_agent"
, or
"remote_agent"
​
TaskUsage
Token and timing data for a background task.
class
TaskUsage
(
TypedDict
):
total_tokens:
int
tool_uses:
int
duration_ms:
int
​
TaskProgressMessage
Emitted periodically with progress updates for a running background task.
@dataclass
class
TaskProgressMessage
(
SystemMessage
):
task_id:
str
description:
str
usage: TaskUsage
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
last_tool_name:
str
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
description
str
Current status description
usage
TaskUsage
Token usage for this task so far
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
last_tool_name
str | None
Name of the last tool the task used
​
TaskNotificationMessage
Emitted when a background task completes, fails, or is stopped. Background tasks include
run_in_background
Bash commands, Monitor watches, and background subagents.
@dataclass
class
TaskNotificationMessage
(
SystemMessage
):
task_id:
str
status: TaskNotificationStatus
# "completed" | "failed" | "stopped"
output_file:
str
summary:
str
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
usage: TaskUsage
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
status
TaskNotificationStatus
One of
"completed"
,
"failed"
, or
"stopped"
output_file
str
Path to the task output file
summary
str
Summary of the task result
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
usage
TaskUsage | None
Final token usage for the task
​
Content Block Types
​
ContentBlock
Union type of all content blocks.
ContentBlock
=
TextBlock
|
ThinkingBlock
|
ToolUseBlock
|
ToolResultBlock
​
TextBlock
Text content block.
@dataclass
class
TextBlock
:
text:
str
​
ThinkingBlock
Thinking content block (for models with thinking capability).
@dataclass
class
ThinkingBlock
:
thinking:
str
signature:
str
​
ToolUseBlock
Tool use request block.
@dataclass
class
ToolUseBlock
:
id
:
str
name:
str
input
: dict[
str
, Any]
​
ToolResultBlock
Tool execution result block.
@dataclass
class
ToolResultBlock
:
tool_use_id:
str
content:
str
|
list[dict[
str
, Any]]
|
None
=
None
is_error:
bool
|
None
=
None
​
Error Types
​
ClaudeSDKError
Base exception class for all SDK errors.
class
ClaudeSDKError
(
Exception
):
"""Base error for Claude SDK."""
​
CLINotFoundError
Raised when Claude Code CLI is not installed or not found.
class
CLINotFoundError
(
CLIConnectionError
):
def
__init__
(
self
,
message
:
str
=
"Claude Code not found"
,
cli_path
:
str
|
None
=
None
):
"""
Args:
message: Error message (default: "Claude Code not found")
cli_path: Optional path to the CLI that was not found
"""
​
CLIConnectionError
Raised when connection to Claude Code fails.
class
CLIConnectionError
(
ClaudeSDKError
):
"""Failed to connect to Claude Code."""
​
ProcessError
Raised when the Claude Code process fails.
class
ProcessError
(
ClaudeSDKError
):
def
__init__
(
self
,
message
:
str
,
exit_code
:
int
|
None
=
None
,
stderr
:
str
|
None
=
None
):
self
.exit_code
=
exit_code
self
.stderr
=
stderr
​
CLIJSONDecodeError
Raised when JSON parsing fails.
class
CLIJSONDecodeError
(
ClaudeSDKError
):
def
__init__
(
self
,
line
:
str
,
original_error
:
Exception
):
"""
Args:
line: The line that failed to parse
original_error: The original JSON decode exception
"""
self
.line
=
line
self
.original_error
=
original_error
​
Hook Types
For a comprehensive guide on using hooks with examples and common patterns, see the
Hooks guide
.
​
HookEvent
Supported hook event types.
HookEvent
=
Literal[
"PreToolUse"
,
# Called before tool execution
"PostToolUse"
,
# Called after tool execution
"PostToolUseFailure"
,
# Called when a tool execution fails
"UserPromptSubmit"
,
# Called when user submits a prompt
"Stop"
,
# Called when stopping execution
"SubagentStop"
,
# Called when a subagent stops
"PreCompact"
,
# Called before message compaction
"Notification"
,
# Called for notification events
"SubagentStart"
,
# Called when a subagent starts
"PermissionRequest"
,
# Called when a permission decision is needed
]
The TypeScript SDK supports additional hook events not yet available in Python:
SessionStart
,
SessionEnd
,
Setup
,
TeammateIdle
,
TaskCompleted
,
ConfigChange
,
WorktreeCreate
,
WorktreeRemove
, and
PostToolBatch
.
​
HookCallback
Type definition for hook callback functions.
HookCallback
=
Callable[[HookInput,
str
|
None
, HookContext], Awaitable[HookJSONOutput]]
Parameters:
input
: Strongly-typed hook input with discriminated unions based on
hook_event_name
(see
HookInput
)
tool_use_id
: Optional tool use identifier (for tool-related hooks)
context
: Hook context with additional information
Returns a
HookJSONOutput
that may contain:
decision
:
"block"
to block the action
systemMessage
: warning message shown to the user
hookSpecificOutput
: Hook-specific output data
​
HookContext
Context information passed to hook callbacks.
class
HookContext
(
TypedDict
):
signal: Any
|
None
# Future: abort signal support
​
HookMatcher
Configuration for matching hooks to specific events or tools.
@dataclass
class
HookMatcher
:
matcher:
str
|
None
=
(
None
# Tool name or pattern to match (e.g., "Bash", "Write|Edit")
)
hooks: list[HookCallback]
=
field(
default_factory
=
list
)
# List of callbacks to execute
timeout:
float
|
None
=
(
None
# Timeout in seconds for all hooks in this matcher (default: 60)
)
​
HookInput
Union type of all hook input types. The actual type depends on the
hook_event_name
field.
HookInput
=
(
PreToolUseHookInput
|
PostToolUseHookInput
|
PostToolUseFailureHookInput
|
UserPromptSubmitHookInput
|
StopHookInput
|
SubagentStopHookInput
|
PreCompactHookInput
|
NotificationHookInput
|
SubagentStartHookInput
|
PermissionRequestHookInput
)
​
BaseHookInput
Base fields present in all hook input types.
class
BaseHookInput
(
TypedDict
):
session_id:
str
transcript_path:
str
cwd:
str
permission_mode: NotRequired[
str
]
Field
Type
Description
session_id
str
Current session identifier
transcript_path
str
Path to the session transcript file
cwd
str
Current working directory
permission_mode
str
(optional)
Current permission mode
​
PreToolUseHookInput
Input data for
PreToolUse
hook events.
class
PreToolUseHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PreToolUse"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_use_id:
str
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PreToolUse"]
Always “PreToolUse”
tool_name
str
Name of the tool about to be executed
tool_input
dict[str, Any]
Input parameters for the tool
tool_use_id
str
Unique identifier for this tool use
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
PostToolUseHookInput
Input data for
PostToolUse
hook events.
class
PostToolUseHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PostToolUse"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_response: Any
tool_use_id:
str
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PostToolUse"]
Always “PostToolUse”
tool_name
str
Name of the tool that was executed
tool_input
dict[str, Any]
Input parameters that were used
tool_response
Any
Response from the tool execution
tool_use_id
str
Unique identifier for this tool use
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
PostToolUseFailureHookInput
Input data for
PostToolUseFailure
hook events. Called when a tool execution fails.
class
PostToolUseFailureHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PostToolUseFailure"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_use_id:
str
error:
str
is_interrupt: NotRequired[
bool
]
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PostToolUseFailure"]
Always “PostToolUseFailure”
tool_name
str
Name of the tool that failed
tool_input
dict[str, Any]
Input parameters that were used
tool_use_id
str
Unique identifier for this tool use
error
str
Error message from the failed execution
is_interrupt
bool
(optional)
Whether the failure was caused by an interrupt
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
UserPromptSubmitHookInput
Input data for
UserPromptSubmit
hook events.
class
UserPromptSubmitHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"UserPromptSubmit"
]
prompt:
str
Field
Type
Description
hook_event_name
Literal["UserPromptSubmit"]
Always “UserPromptSubmit”
prompt
str
The user’s submitted prompt
​
StopHookInput
Input data for
Stop
hook events.
class
StopHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"Stop"
]
stop_hook_active:
bool
Field
Type
Description
hook_event_name
Literal["Stop"]
Always “Stop”
stop_hook_active
bool
Whether the stop hook is active
​
SubagentStopHookInput
Input data for
SubagentStop
hook events.
class
SubagentStopHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"SubagentStop"
]
stop_hook_active:
bool
agent_id:
str
agent_transcript_path:
str
agent_type:
str
Field
Type
Description
hook_event_name
Literal["SubagentStop"]
Always “SubagentStop”
stop_hook_active
bool
Whether the stop hook is active
agent_id
str
Unique identifier for the subagent
agent_transcript_path
str
Path to the subagent’s transcript file
agent_type
str
Type of the subagent
​
PreCompactHookInput
Input data for
PreCompact
hook events.
class
PreCompactHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PreCompact"
]
trigger: Literal[
"manual"
,
"auto"
]
custom_instructions:
str
|
None
Field
Type
Description
hook_event_name
Literal["PreCompact"]
Always “PreCompact”
trigger
Literal["manual", "auto"]
What triggered the compaction
custom_instructions
str | None
Custom instructions for compaction
​
NotificationHookInput
Input data for
Notification
hook events.
class
NotificationHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"Notification"
]
message:
str
title: NotRequired[
str
]
notification_type:
str
Field
Type
Description
hook_event_name
Literal["Notification"]
Always “Notification”
message
str
Notification message content
title
str
(optional)
Notification title
notification_type
str
Type of notification
​
SubagentStartHookInput
Input data for
SubagentStart
hook events.
class
SubagentStartHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"SubagentStart"
]
agent_id:
str
agent_type:
str
Field
Type
Description
hook_event_name
Literal["SubagentStart"]
Always “SubagentStart”
agent_id
str
Unique identifier for the subagent
agent_type
str
Type of the subagent
​
PermissionRequestHookInput
Input data for
PermissionRequest
hook events. Allows hooks to handle permission decisions programmatically.
class
PermissionRequestHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PermissionRequest"
]
tool_name:
str
tool_input: dict[
str
, Any]
permission_suggestions: NotRequired[list[Any]]
Field
Type
Description
hook_event_name
Literal["PermissionRequest"]
Always “PermissionRequest”
tool_name
str
Name of the tool requesting permission
tool_input
dict[str, Any]
Input parameters for the tool
permission_suggestions
list[Any]
(optional)
Suggested permission updates from the CLI
​
HookJSONOutput
Union type for hook callback return values.
HookJSONOutput
=
AsyncHookJSONOutput
|
SyncHookJSONOutput
​
SyncHookJSONOutput
Synchronous hook output with control and decision fields.
class
SyncHookJSONOutput
(
TypedDict
):
# Control fields
continue_: NotRequired[
bool
]
# Whether to proceed (default: True)
suppressOutput: NotRequired[
bool
]
# Hide stdout from transcript
stopReason: NotRequired[
str
]
# Message when continue is False
# Decision fields
decision: NotRequired[Literal[
"block"
]]
systemMessage: NotRequired[
str
]
# Warning message for user
reason: NotRequired[
str
]
# Feedback for Claude
# Hook-specific output
hookSpecificOutput: NotRequired[HookSpecificOutput]
Use
continue_
(with underscore) in Python code. It is automatically converted to
continue
when sent to the CLI.
​
HookSpecificOutput
A
TypedDict
containing the hook event name and event-specific fields. The shape depends on the
hookEventName
value. For full details on available fields per hook event, see
Control execution with hooks
.
A discriminated union of event-specific output types. The
hookEventName
field determines which fields are valid.
class
PreToolUseHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PreToolUse"
]
permissionDecision: NotRequired[Literal[
"allow"
,
"deny"
,
"ask"
,
"defer"
]]
permissionDecisionReason: NotRequired[
str
]
updatedInput: NotRequired[dict[
str
, Any]]
additionalContext: NotRequired[
str
]
class
PostToolUseHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PostToolUse"
]
additionalContext: NotRequired[
str
]
updatedToolOutput: NotRequired[Any]
updatedMCPToolOutput: NotRequired[Any]
class
PostToolUseFailureHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PostToolUseFailure"
]
additionalContext: NotRequired[
str
]
class
UserPromptSubmitHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"UserPromptSubmit"
]
additionalContext: NotRequired[
str
]
class
NotificationHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"Notification"
]
additionalContext: NotRequired[
str
]
class
SubagentStartHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"SubagentStart"
]
additionalContext: NotRequired[
str
]
class
PermissionRequestHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PermissionRequest"
]
decision: dict[
str
, Any]
HookSpecificOutput
=
(
PreToolUseHookSpecificOutput
|
PostToolUseHookSpecificOutput
|
PostToolUseFailureHookSpecificOutput
|
UserPromptSubmitHookSpecificOutput
|
NotificationHookSpecificOutput
|
SubagentStartHookSpecificOutput
|
PermissionRequestHookSpecificOutput
)
​
AsyncHookJSONOutput
Async hook output that defers hook execution.
class
AsyncHookJSONOutput
(
TypedDict
):
async_: Literal[
True
]
# Set to True to defer execution
asyncTimeout: NotRequired[
int
]
# Timeout in milliseconds
Use
async_
(with underscore) in Python code. It is automatically converted to
async
when sent to the CLI.
​
Hook Usage Example
This example registers two hooks: one that blocks dangerous bash commands like
rm -rf /
, and another that logs all tool usage for auditing. The security hook only runs on Bash commands (via the
matcher
), while the logging hook runs on all tools.
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher, HookContext
from
typing
import
Any
async
def
validate_bash_command
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Validate and potentially block dangerous bash commands."""
if
input_data[
"tool_name"
]
==
"Bash"
:
command
=
input_data[
"tool_input"
].get(
"command"
,
""
)
if
"rm -rf /"
in
command:
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Dangerous command blocked"
,
}
}
return
{}
async
def
log_tool_use
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log all tool usage for auditing."""
print
(
f
"Tool used:
{
input_data.get(
'tool_name'
)
}
"
)
return
{}
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[validate_bash_command],
timeout
=
120
),
# 2 min for validation
HookMatcher(
hooks
=
[log_tool_use]
),
# Applies to all tools (default 60s timeout)
],
"PostToolUse"
: [HookMatcher(
hooks
=
[log_tool_use])],
}
)
async
for
message
in
query(
prompt
=
"Analyze this codebase"
,
options
=
options):
print
(message)
​
Tool Input/Output Types
Documentation of input/output schemas for all built-in Claude Code tools. While the Python SDK doesn’t export these as types, they represent the structure of tool inputs and outputs in messages.
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
Input:
{
"description"
:
str
,
# A short (3-5 word) description of the task
"prompt"
:
str
,
# The task for the agent to perform
"subagent_type"
:
str
,
# The type of specialized agent to use
}
Output:
{
"result"
:
str
,
# Final result from the subagent
"usage"
:
dict
|
None
,
# Token usage statistics
"total_cost_usd"
:
float
|
None
,
# Estimated total cost in USD
"duration_ms"
:
int
|
None
,
# Execution duration in milliseconds
}
​
AskUserQuestion
Tool name:
AskUserQuestion
Asks the user clarifying questions during execution. See
Handle approvals and user input
for usage details.
Input:
{
"questions"
: [
# Questions to ask the user (1-4 questions)
{
"question"
:
str
,
# The complete question to ask the user
"header"
:
str
,
# Very short label displayed as a chip/tag (max 12 chars)
"options"
: [
# The available choices (2-4 options)
{
"label"
:
str
,
# Display text for this option (1-5 words)
"description"
:
str
,
# Explanation of what this option means
}
],
"multiSelect"
:
bool
,
# Set to true to allow multiple selections
}
],
"answers"
: dict[
str
,
str
|
list[
str
]]
|
None
,
# User answers populated by the permission system. Multi-select
# answers may be a list of labels or a comma-joined string
}
Output:
{
"questions"
: [
# The questions that were asked
{
"question"
:
str
,
"header"
:
str
,
"options"
: [{
"label"
:
str
,
"description"
:
str
}],
"multiSelect"
:
bool
,
}
],
"answers"
: dict[
str
,
str
],
# Maps question text to answer string
# Multi-select answers are comma-separated
}
​
Bash
Tool name:
Bash
Input:
{
"command"
:
str
,
# The command to execute
"timeout"
:
int
|
None
,
# Optional timeout in milliseconds (max 600000)
"description"
:
str
|
None
,
# Clear, concise description (5-10 words)
"run_in_background"
:
bool
|
None
,
# Set to true to run in background
}
Output:
{
"output"
:
str
,
# Combined stdout and stderr output
"exitCode"
:
int
,
# Exit code of the command
"killed"
:
bool
|
None
,
# Whether command was killed due to timeout
"shellId"
:
str
|
None
,
# Shell ID for background processes
}
​
Monitor
Tool name:
Monitor
Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Monitor follows the same permission rules as Bash. See the
Monitor tool reference
for behavior and provider availability.
Input:
{
"command"
:
str
,
# Shell script; each stdout line is an event, exit ends the watch
"description"
:
str
,
# Short description shown in notifications
"timeout_ms"
:
int
|
None
,
# Kill after this deadline (default 300000, max 3600000)
"persistent"
:
bool
|
None
,
# Run for the lifetime of the session; stop with TaskStop
}
Output:
{
"taskId"
:
str
,
# ID of the background monitor task
"timeoutMs"
:
int
,
# Timeout deadline in milliseconds (0 when persistent)
"persistent"
:
bool
|
None
,
# True when running until TaskStop or session end
}
​
Edit
Tool name:
Edit
Input:
{
"file_path"
:
str
,
# The absolute path to the file to modify
"old_string"
:
str
,
# The text to replace
"new_string"
:
str
,
# The text to replace it with
"replace_all"
:
bool
|
None
,
# Replace all occurrences (default False)
}
Output:
{
"message"
:
str
,
# Confirmation message
"replacements"
:
int
,
# Number of replacements made
"file_path"
:
str
,
# File path that was edited
}
​
Read
Tool name:
Read
Input:
{
"file_path"
:
str
,
# The absolute path to the file to read
"offset"
:
int
|
None
,
# The line number to start reading from
"limit"
:
int
|
None
,
# The number of lines to read
}
Output (Text files):
{
"content"
:
str
,
# File contents with line numbers
"total_lines"
:
int
,
# Total number of lines in file
"lines_returned"
:
int
,
# Lines actually returned
}
Output (Images):
{
"image"
:
str
,
# Base64 encoded image data
"mime_type"
:
str
,
# Image MIME type
"file_size"
:
int
,
# File size in bytes
}
​
Write
Tool name:
Write
Input:
{
"file_path"
:
str
,
# The absolute path to the file to write
"content"
:
str
,
# The content to write to the file
}
Output:
{
"message"
:
str
,
# Success message
"bytes_written"
:
int
,
# Number of bytes written
"file_path"
:
str
,
# File path that was written
}
​
Glob
Tool name:
Glob
Input:
{
"pattern"
:
str
,
# The glob pattern to match files against
"path"
:
str
|
None
,
# The directory to search in (defaults to cwd)
}
Output:
{
"matches"
: list[
str
],
# Array of matching file paths
"count"
:
int
,
# Number of matches found
"search_path"
:
str
,
# Search directory used
}
​
Grep
Tool name:
Grep
Input:
{
"pattern"
:
str
,
# The regular expression pattern
"path"
:
str
|
None
,
# File or directory to search in
"glob"
:
str
|
None
,
# Glob pattern to filter files
"type"
:
str
|
None
,
# File type to search
"output_mode"
:
str
|
None
,
# "content", "files_with_matches", or "count"
"-i"
:
bool
|
None
,
# Case insensitive search
"-n"
:
bool
|
None
,
# Show line numbers
"-B"
:
int
|
None
,
# Lines to show before each match
"-A"
:
int
|
None
,
# Lines to show after each match
"-C"
:
int
|
None
,
# Lines to show before and after
"head_limit"
:
int
|
None
,
# Limit output to first N lines/entries
"multiline"
:
bool
|
None
,
# Enable multiline mode
}
Output (content mode):
{
"matches"
: [
{
"file"
:
str
,
"line_number"
:
int
|
None
,
"line"
:
str
,
"before_context"
: list[
str
]
|
None
,
"after_context"
: list[
str
]
|
None
,
}
],
"total_matches"
:
int
,
}
Output (files_with_matches mode):
{
"files"
: list[
str
],
# Files containing matches
"count"
:
int
,
# Number of files with matches
}
​
NotebookEdit
Tool name:
NotebookEdit
Input:
{
"notebook_path"
:
str
,
# Absolute path to the Jupyter notebook
"cell_id"
:
str
|
None
,
# The ID of the cell to edit
"new_source"
:
str
,
# The new source for the cell
"cell_type"
:
"code"
|
"markdown"
|
None
,
# The type of the cell
"edit_mode"
:
"replace"
|
"insert"
|
"delete"
|
None
,
# Edit operation type
}
Output:
{
"message"
:
str
,
# Success message
"edit_type"
:
"replaced"
|
"inserted"
|
"deleted"
,
# Type of edit performed
"cell_id"
:
str
|
None
,
# Cell ID that was affected
"total_cells"
:
int
,
# Total cells in notebook after edit
}
​
WebFetch
Tool name:
WebFetch
Input:
{
"url"
:
str
,
# The URL to fetch content from
"prompt"
:
str
,
# The prompt to run on the fetched content
}
Output:
{
"bytes"
:
int
,
# Size of the fetched content in bytes
"code"
:
int
,
# HTTP response code
"codeText"
:
str
,
# HTTP response code text
"result"
:
str
,
# Processed result from applying the prompt to the content
"durationMs"
:
int
,
# Time to fetch and process the content, in milliseconds
"url"
:
str
,
# URL that was fetched
}
​
WebSearch
Tool name:
WebSearch
Input:
{
"query"
:
str
,
# The search query to use
"allowed_domains"
: list[
str
]
|
None
,
# Only include results from these domains
"blocked_domains"
: list[
str
]
|
None
,
# Never include results from these domains
}
Output:
{
"query"
:
str
,
# The search query
"results"
: list[
str
|
{
"tool_use_id"
:
str
,
"content"
: list[{
"title"
:
str
,
"url"
:
str
}]}],
"durationSeconds"
:
float
,
# Search duration in seconds
}
​
TodoWrite
Tool name:
TodoWrite
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
Input:
{
"todos"
: [
{
"content"
:
str
,
# The task description
"status"
:
"pending"
|
"in_progress"
|
"completed"
,
# Task status
"activeForm"
:
str
,
# Active form of the description
}
]
}
Output:
{
"message"
:
str
,
# Success message
"stats"
: {
"total"
:
int
,
"pending"
:
int
,
"in_progress"
:
int
,
"completed"
:
int
},
}
​
TaskCreate
Tool name:
TaskCreate
Input:
{
"subject"
:
str
,
# Short task title
"description"
:
str
,
# Detailed task body
"activeForm"
:
str
|
None
,
# Present-tense label shown while in progress
"metadata"
:
dict
|
None
,
# Arbitrary caller metadata
}
Output:
{
"task"
: {
"id"
:
str
,
"subject"
:
str
},
# Created task with assigned ID
}
​
TaskUpdate
Tool name:
TaskUpdate
Input:
{
"taskId"
:
str
,
# ID of the task to patch
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
,
"deleted"
]
|
None
,
"subject"
:
str
|
None
,
"description"
:
str
|
None
,
"activeForm"
:
str
|
None
,
"addBlocks"
: list[
str
]
|
None
,
# Task IDs this task now blocks
"addBlockedBy"
: list[
str
]
|
None
,
# Task IDs that now block this task
"owner"
:
str
|
None
,
"metadata"
:
dict
|
None
,
}
Output:
{
"success"
:
bool
,
"taskId"
:
str
,
"updatedFields"
: list[
str
],
# Names of fields that changed
"error"
:
str
|
None
,
"statusChange"
: {
"from"
:
str
,
"to"
:
str
}
|
None
,
}
​
TaskGet
Tool name:
TaskGet
Input:
{
"taskId"
:
str
,
# ID of the task to read
}
Output:
{
"task"
: {
"id"
:
str
,
"subject"
:
str
,
"description"
:
str
,
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
],
"blocks"
: list[
str
],
"blockedBy"
: list[
str
],
}
|
None
,
# None when the ID is not found
}
​
TaskList
Tool name:
TaskList
Input:
{}
Output:
{
"tasks"
: [
{
"id"
:
str
,
"subject"
:
str
,
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
],
"owner"
:
str
|
None
,
"blockedBy"
: list[
str
],
}
],
}
​
BashOutput
Tool name:
BashOutput
Input:
{
"bash_id"
:
str
,
# The ID of the background shell
"filter"
:
str
|
None
,
# Optional regex to filter output lines
}
Output:
{
"output"
:
str
,
# New output since last check
"status"
:
"running"
|
"completed"
|
"failed"
,
# Current shell status
"exitCode"
:
int
|
None
,
# Exit code when completed
}
​
KillBash
Tool name:
KillBash
Input:
{
"shell_id"
:
str
# The ID of the background shell to kill
}
Output:
{
"message"
:
str
,
# Success message
"shell_id"
:
str
,
# ID of the killed shell
}
​
ExitPlanMode
Tool name:
ExitPlanMode
Input:
{
"plan"
:
str
# The plan to run by the user for approval
}
Output:
{
"message"
:
str
,
# Confirmation message
"approved"
:
bool
|
None
,
# Whether user approved the plan
}
​
ListMcpResources
Tool name:
ListMcpResources
Input:
{
"server"
:
str
|
None
# Optional server name to filter resources by
}
Output:
{
"resources"
: [
{
"uri"
:
str
,
"name"
:
str
,
"description"
:
str
|
None
,
"mimeType"
:
str
|
None
,
"server"
:
str
,
}
],
"total"
:
int
,
}
​
ReadMcpResource
Tool name:
ReadMcpResource
Input:
{
"server"
:
str
,
# The MCP server name
"uri"
:
str
,
# The resource URI to read
}
Output:
{
"contents"
: [
{
"uri"
:
str
,
"mimeType"
:
str
|
None
,
"text"
:
str
|
None
,
"blob"
:
str
|
None
}
],
"server"
:
str
,
}
​
Advanced Features with ClaudeSDKClient
​
Building a Continuous Conversation Interface
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
TextBlock,
)
import
asyncio
class
ConversationSession
:
"""Maintains a single conversation session with Claude."""
def
__init__
(
self
,
options
: ClaudeAgentOptions
|
None
=
None
):
self
.client
=
ClaudeSDKClient(options)
self
.turn_count
=
0
async
def
start
(
self
):
await
self
.client.connect()
print
(
"Starting conversation session. Claude will remember context."
)
print
(
"Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"
)
while
True
:
user_input
=
input
(
f
"
\n
[Turn
{
self
.turn_count
+
1
}
] You: "
)
if
user_input.lower()
==
"exit"
:
break
elif
user_input.lower()
==
"interrupt"
:
await
self
.client.interrupt()
print
(
"Task interrupted!"
)
continue
elif
user_input.lower()
==
"new"
:
# Disconnect and reconnect for a fresh session
await
self
.client.disconnect()
await
self
.client.connect()
self
.turn_count
=
0
print
(
"Started new conversation session (previous context cleared)"
)
continue
# Send message - the session retains all previous messages
await
self
.client.query(user_input)
self
.turn_count
+=
1
# Process response
print
(
f
"[Turn
{
self
.turn_count
}
] Claude: "
,
end
=
""
)
async
for
message
in
self
.client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(block.text,
end
=
""
)
print
()
# New line after response
await
self
.client.disconnect()
print
(
f
"Conversation ended after
{
self
.turn_count
}
turns."
)
async
def
main
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
session
=
ConversationSession(options)
await
session.start()
# Example conversation:
# Turn 1 - You: "Create a file called hello.py"
# Turn 1 - Claude: "I'll create a hello.py file for you..."
# Turn 2 - You: "What's in that file?"
# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
# Turn 3 - You: "Add a main function to it"
# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())
​
Using Hooks for Behavior Modification
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
HookContext,
)
import
asyncio
from
typing
import
Any
async
def
pre_tool_logger
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log all tool usage before execution."""
tool_name
=
input_data.get(
"tool_name"
,
"unknown"
)
print
(
f
"[PRE-TOOL] About to use:
{
tool_name
}
"
)
# You can modify or block the tool execution here
if
tool_name
==
"Bash"
and
"rm -rf"
in
str
(input_data.get(
"tool_input"
, {})):
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Dangerous command blocked"
,
}
}
return
{}
async
def
post_tool_logger
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log results after tool execution."""
tool_name
=
input_data.get(
"tool_name"
,
"unknown"
)
print
(
f
"[POST-TOOL] Completed:
{
tool_name
}
"
)
return
{}
async
def
user_prompt_modifier
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Add context to user prompts."""
original_prompt
=
input_data.get(
"prompt"
,
""
)
# Add a timestamp as additional context for Claude to see
from
datetime
import
datetime
timestamp
=
datetime.now().strftime(
"%Y-%m-
%d
%H:%M:%S"
)
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptSubmit"
,
"additionalContext"
:
f
"[Submitted at
{
timestamp
}
] Original prompt:
{
original_prompt
}
"
,
}
}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
hooks
=
[pre_tool_logger]),
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[pre_tool_logger]),
],
"PostToolUse"
: [HookMatcher(
hooks
=
[post_tool_logger])],
"UserPromptSubmit"
: [HookMatcher(
hooks
=
[user_prompt_modifier])],
},
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"List files in current directory"
)
async
for
message
in
client.receive_response():
# Hooks will automatically log tool usage
pass
asyncio.run(main())
​
Real-time Progress Monitoring
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ToolUseBlock,
ToolResultBlock,
TextBlock,
)
import
asyncio
async
def
monitor_progress
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Create 5 Python files with different sorting algorithms"
)
# Monitor progress in real-time
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
if
block.name
==
"Write"
:
file_path
=
block.input.get(
"file_path"
,
""
)
print
(
f
"Creating:
{
file_path
}
"
)
elif
isinstance
(block, ToolResultBlock):
print
(
"Completed tool execution"
)
elif
isinstance
(block, TextBlock):
print
(
f
"Claude says:
{
block.text[:
100
]
}
..."
)
print
(
"Task completed!"
)
asyncio.run(monitor_progress())
​
Example Usage
​
Basic file operations (using query)
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
import
asyncio
async
def
create_project
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
,
cwd
=
"/home/user/project"
,
)
async
for
message
in
query(
prompt
=
"Create a Python project structure with setup.py"
,
options
=
options
):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
print
(
f
"Using tool:
{
block.name
}
"
)
asyncio.run(create_project())
​
Error handling
from
claude_agent_sdk
import
query, CLINotFoundError, ProcessError, CLIJSONDecodeError
try
:
async
for
message
in
query(
prompt
=
"Hello"
):
print
(message)
except
CLINotFoundError:
print
(
"Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
)
except
ProcessError
as
e:
print
(
f
"Process failed with exit code:
{
e.exit_code
}
"
)
except
CLIJSONDecodeError
as
e:
print
(
f
"Failed to parse response:
{
e
}
"
)
​
Streaming mode with client
from
claude_agent_sdk
import
ClaudeSDKClient
import
asyncio
async
def
interactive_session
():
async
with
ClaudeSDKClient()
as
client:
# Send initial message
await
client.query(
"What's the weather like?"
)
# Process responses
async
for
msg
in
client.receive_response():
print
(msg)
# Send follow-up
await
client.query(
"Tell me more about that"
)
# Process follow-up response
async
for
msg
in
client.receive_response():
print
(msg)
asyncio.run(interactive_session())
​
Using custom tools with ClaudeSDKClient
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
tool,
create_sdk_mcp_server,
AssistantMessage,
TextBlock,
)
import
asyncio
from
typing
import
Any
# Define custom tools with @tool decorator
@tool
(
"calculate"
,
"Perform mathematical calculations"
, {
"expression"
:
str
})
async
def
calculate
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
try
:
result
=
eval
(args[
"expression"
], {
"__builtins__"
: {}})
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Result:
{
result
}
"
}]}
except
Exception
as
e:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Error:
{
str
(e)
}
"
}],
"is_error"
:
True
,
}
@tool
(
"get_time"
,
"Get current time"
, {})
async
def
get_time
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
from
datetime
import
datetime
current_time
=
datetime.now().strftime(
"%Y-%m-
%d
%H:%M:%S"
)
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Current time:
{
current_time
}
"
}]}
async
def
main
():
# Create SDK MCP server with custom tools
my_server
=
create_sdk_mcp_server(
name
=
"utilities"
,
version
=
"1.0.0"
,
tools
=
[calculate, get_time]
)
# Configure options with the server
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"utils"
: my_server},
allowed_tools
=
[
"mcp__utils__calculate"
,
"mcp__utils__get_time"
],
)
# Use ClaudeSDKClient for interactive tool usage
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"What's 123 * 456?"
)
# Process calculation response
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Calculation:
{
block.text
}
"
)
# Follow up with time query
await
client.query(
"What time is it now?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Time:
{
block.text
}
"
)
asyncio.run(main())
​
Sandbox Configuration
​
SandboxSettings
Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.
class
SandboxSettings
(
TypedDict
,
total
=
False
):
enabled:
bool
autoAllowBashIfSandboxed:
bool
excludedCommands: list[
str
]
allowUnsandboxedCommands:
bool
network: SandboxNetworkConfig
ignoreViolations: SandboxIgnoreViolations
enableWeakerNestedSandbox:
bool
Property
Type
Default
Description
enabled
bool
False
Enable sandbox mode for command execution
autoAllowBashIfSandboxed
bool
True
Auto-approve bash commands when sandbox is enabled
excludedCommands
list[str]
[]
Commands that always bypass sandbox restrictions (e.g.,
["docker"]
). These run unsandboxed automatically without model involvement
allowUnsandboxedCommands
bool
True
Allow the model to request running commands outside the sandbox. When
True
, the model can set
dangerouslyDisableSandbox
in tool input, which falls back to the
permissions system
network
SandboxNetworkConfig
None
Network-specific sandbox configuration
ignoreViolations
SandboxIgnoreViolations
None
Configure which sandbox violations to ignore
enableWeakerNestedSandbox
bool
False
Enable a weaker nested sandbox for compatibility
​
Example usage
from
claude_agent_sdk
import
query, ClaudeAgentOptions, SandboxSettings
sandbox_settings: SandboxSettings
=
{
"enabled"
:
True
,
"autoAllowBashIfSandboxed"
:
True
,
"network"
: {
"allowLocalBinding"
:
True
},
}
async
for
message
in
query(
prompt
=
"Build and test my project"
,
options
=
ClaudeAgentOptions(
sandbox
=
sandbox_settings),
):
print
(message)
Unix socket security
: The
allowUnixSockets
option can grant access to powerful system services. For example, allowing
/var/run/docker.sock
effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.
​
SandboxNetworkConfig
Network-specific configuration for sandbox mode.
class
SandboxNetworkConfig
(
TypedDict
,
total
=
False
):
allowedDomains: list[
str
]
deniedDomains: list[
str
]
allowManagedDomainsOnly:
bool
allowUnixSockets: list[
str
]
allowAllUnixSockets:
bool
allowLocalBinding:
bool
allowMachLookup: list[
str
]
httpProxyPort:
int
socksProxyPort:
int
Property
Type
Default
Description
allowedDomains
list[str]
[]
Domain names that sandboxed processes can access
deniedDomains
list[str]
[]
Domain names that sandboxed processes cannot access. Takes precedence over
allowedDomains
allowManagedDomainsOnly
bool
False
Managed-settings only: when set in managed settings, ignore
allowedDomains
from non-managed settings sources. Has no effect when set via SDK options
allowUnixSockets
list[str]
[]
Unix socket paths that processes can access (e.g., Docker socket)
allowAllUnixSockets
bool
False
Allow access to all Unix sockets
allowLocalBinding
bool
False
Allow processes to bind to local ports (e.g., for dev servers)
allowMachLookup
list[str]
[]
macOS only: XPC/Mach service names to allow. Supports a trailing wildcard
httpProxyPort
int
None
HTTP proxy port for network requests
socksProxyPort
int
None
SOCKS proxy port for network requests
The built-in sandbox proxy enforces the network allowlist based on the requested hostname and does not terminate or inspect TLS traffic, so techniques such as
domain fronting
can potentially bypass it. See
Sandboxing security limitations
for details and
Secure deployment
for configuring a TLS-terminating proxy.
​
SandboxIgnoreViolations
Configuration for ignoring specific sandbox violations.
class
SandboxIgnoreViolations
(
TypedDict
,
total
=
False
):
file
: list[
str
]
network: list[
str
]
Property
Type
Default
Description
file
list[str]
[]
File path patterns to ignore violations for
network
list[str]
[]
Network patterns to ignore violations for
​
Permissions Fallback for Unsandboxed Commands
When
allowUnsandboxedCommands
is enabled, the model can request to run commands outside the sandbox by setting
dangerouslyDisableSandbox: True
in the tool input. These requests fall back to the existing permissions system, meaning your
can_use_tool
handler will be invoked, allowing you to implement custom authorization logic.
excludedCommands
vs
allowUnsandboxedCommands
:
excludedCommands
: A static list of commands that always bypass the sandbox automatically (e.g.,
["docker"]
). The model has no control over this.
allowUnsandboxedCommands
: Lets the model decide at runtime whether to request unsandboxed execution by setting
dangerouslyDisableSandbox: True
in the tool input.
from
claude_agent_sdk
import
(
query,
ClaudeAgentOptions,
HookMatcher,
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
can_use_tool
(
tool
:
str
,
input
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
# Check if the model is requesting to bypass the sandbox
if
tool
==
"Bash"
and
input
.get(
"dangerouslyDisableSandbox"
):
# The model is requesting to run this command outside the sandbox
print
(
f
"Unsandboxed command requested:
{
input
.get(
'command'
)
}
"
)
if
is_command_authorized(
input
.get(
"command"
)):
return
PermissionResultAllow()
return
PermissionResultDeny(
message
=
"Command not authorized for unsandboxed execution"
)
return
PermissionResultAllow()
# Required: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Deploy my application"
},
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
sandbox
=
{
"enabled"
:
True
,
"allowUnsandboxedCommands"
:
True
,
# Model can request unsandboxed execution
},
permission_mode
=
"default"
,
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
print
(message)
This pattern enables you to:
Audit model requests
: Log when the model requests unsandboxed execution
Implement allowlists
: Only permit specific commands to run unsandboxed
Add approval workflows
: Require explicit authorization for privileged operations
Commands running with
dangerouslyDisableSandbox: True
have full system access. Ensure your
can_use_tool
handler validates these requests carefully.
If
permission_mode
is set to
bypassPermissions
and
allow_unsandboxed_commands
is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.
​
See also
SDK overview
- General SDK concepts
TypeScript SDK reference
- TypeScript SDK documentation
CLI reference
- Command-line interface
Common workflows
- Step-by-step guides
Was this page helpful?
Yes
No
TypeScript V2 (deprecated)
Migration Guide
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/python" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - Python
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SD...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - Python
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Installation
pip
install
claude-agent-sdk
​
Choosing between
query()
and
ClaudeSDKClient
The Python SDK provides two ways to interact with Claude Code:
​
Quick comparison
Feature
query()
ClaudeSDKClient
Session
Creates new session each time
Reuses same session
Conversation
Single exchange
Multiple exchanges in same context
Connection
Managed automatically
Manual control
Streaming Input
✅ Supported
✅ Supported
Interrupts
❌ Not supported
✅ Supported
Hooks
✅ Supported
✅ Supported
Custom Tools
✅ Supported
✅ Supported
Continue Chat
❌ New session each time
✅ Maintains conversation
Use Case
One-off tasks
Continuous conversations
​
When to use
query()
(new session each time)
Best for:
One-off questions where you don’t need conversation history
Independent tasks that don’t require context from previous exchanges
Simple automation scripts
When you want a fresh start each time
​
When to use
ClaudeSDKClient
(continuous conversation)
Best for:
Continuing conversations
- When you need Claude to remember context
Follow-up questions
- Building on previous responses
Interactive applications
- Chat interfaces, REPLs
Response-driven logic
- When next action depends on Claude’s response
Session control
- Managing conversation lifecycle explicitly
​
Functions
​
query()
Creates a new session for each interaction with Claude Code. Returns an async iterator that yields messages as they arrive. Each call to
query()
starts fresh with no memory of previous interactions.
async
def
query
(
*
,
prompt
:
str
|
AsyncIterable[dict[
str
, Any]],
options
: ClaudeAgentOptions
|
None
=
None
,
transport
: Transport
|
None
=
None
) -> AsyncIterator[Message]
​
Parameters
Parameter
Type
Description
prompt
str | AsyncIterable[dict]
The input prompt as a string or async iterable for streaming mode
options
ClaudeAgentOptions | None
Optional configuration object (defaults to
ClaudeAgentOptions()
if None)
transport
Transport | None
Optional custom transport for communicating with the CLI process
​
Returns
Returns an
AsyncIterator[Message]
that yields messages from the conversation.
​
Example - With options
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
options
=
ClaudeAgentOptions(
system_prompt
=
"You are an expert Python developer"
,
permission_mode
=
"acceptEdits"
,
cwd
=
"/home/user/project"
,
)
async
for
message
in
query(
prompt
=
"Create a Python web server"
,
options
=
options):
print
(message)
asyncio.run(main())
​
tool()
Decorator for defining MCP tools with type safety.
def
tool
(
name
:
str
,
description
:
str
,
input_schema
:
type
|
dict[
str
, Any],
annotations
: ToolAnnotations
|
None
=
None
) -> Callable[[Callable[[Any], Awaitable[dict[
str
, Any]]]], SdkMcpTool[Any]]
​
Parameters
Parameter
Type
Description
name
str
Unique identifier for the tool
description
str
Human-readable description of what the tool does
input_schema
type | dict[str, Any]
Schema defining the tool’s input parameters (see below)
annotations
ToolAnnotations
| None
Optional MCP tool annotations providing behavioral hints to clients
​
Input schema options
Simple type mapping
(recommended):
{
"text"
:
str
,
"count"
:
int
,
"enabled"
:
bool
}
JSON Schema format
(for complex validation):
{
"type"
:
"object"
,
"properties"
: {
"text"
: {
"type"
:
"string"
},
"count"
: {
"type"
:
"integer"
,
"minimum"
:
0
},
},
"required"
: [
"text"
],
}
​
Returns
A decorator function that wraps the tool implementation and returns an
SdkMcpTool
instance.
​
Example
from
claude_agent_sdk
import
tool
from
typing
import
Any
@tool
(
"greet"
,
"Greet a user"
, {
"name"
:
str
})
async
def
greet
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Hello,
{
args[
'name'
]
}
!"
}]}
​
ToolAnnotations
Re-exported from
mcp.types
(also available as
from claude_agent_sdk import ToolAnnotations
). All fields are optional hints; clients should not rely on them for security decisions.
Field
Type
Default
Description
title
str | None
None
Human-readable title for the tool
readOnlyHint
bool | None
False
If
True
, the tool does not modify its environment
destructiveHint
bool | None
True
If
True
, the tool may perform destructive updates (only meaningful when
readOnlyHint
is
False
)
idempotentHint
bool | None
False
If
True
, repeated calls with the same arguments have no additional effect (only meaningful when
readOnlyHint
is
False
)
openWorldHint
bool | None
True
If
True
, the tool interacts with external entities (for example, web search). If
False
, the tool’s domain is closed (for example, a memory tool)
from
claude_agent_sdk
import
tool, ToolAnnotations
from
typing
import
Any
@tool
(
"search"
,
"Search the web"
,
{
"query"
:
str
},
annotations
=
ToolAnnotations(
readOnlyHint
=
True
,
openWorldHint
=
True
),
)
async
def
search
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Results for:
{
args[
'query'
]
}
"
}]}
​
create_sdk_mcp_server()
Create an in-process MCP server that runs within your Python application.
def
create_sdk_mcp_server
(
name
:
str
,
version
:
str
=
"1.0.0"
,
tools
: list[SdkMcpTool[Any]]
|
None
=
None
) -> McpSdkServerConfig
​
Parameters
Parameter
Type
Default
Description
name
str
-
Unique identifier for the server
version
str
"1.0.0"
Server version string
tools
list[SdkMcpTool[Any]] | None
None
List of tool functions created with
@tool
decorator
​
Returns
Returns an
McpSdkServerConfig
object that can be passed to
ClaudeAgentOptions.mcp_servers
.
​
Example
from
claude_agent_sdk
import
tool, create_sdk_mcp_server
@tool
(
"add"
,
"Add two numbers"
, {
"a"
:
float
,
"b"
:
float
})
async
def
add
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Sum:
{
args[
'a'
]
+
args[
'b'
]
}
"
}]}
@tool
(
"multiply"
,
"Multiply two numbers"
, {
"a"
:
float
,
"b"
:
float
})
async
def
multiply
(
args
):
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Product:
{
args[
'a'
]
*
args[
'b'
]
}
"
}]}
calculator
=
create_sdk_mcp_server(
name
=
"calculator"
,
version
=
"2.0.0"
,
tools
=
[add, multiply],
# Pass decorated functions
)
# Use with Claude
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"calc"
: calculator},
allowed_tools
=
[
"mcp__calc__add"
,
"mcp__calc__multiply"
],
)
​
list_sessions()
Lists past sessions with metadata. Filter by project directory or list sessions across all projects. Synchronous; returns immediately.
def
list_sessions
(
directory
:
str
|
None
=
None
,
limit
:
int
|
None
=
None
,
include_worktrees
:
bool
=
True
) -> list[SDKSessionInfo]
​
Parameters
Parameter
Type
Default
Description
directory
str | None
None
Directory to list sessions for. When omitted, returns sessions across all projects
limit
int | None
None
Maximum number of sessions to return
include_worktrees
bool
True
When
directory
is inside a git repository, include sessions from all worktree paths
​
Return type:
SDKSessionInfo
Property
Type
Description
session_id
str
Unique session identifier
summary
str
Display title: custom title, auto-generated summary, or first prompt
last_modified
int
Last modified time in milliseconds since epoch
file_size
int | None
Session file size in bytes (
None
for remote storage backends)
custom_title
str | None
User-set session title
first_prompt
str | None
First meaningful user prompt in the session
git_branch
str | None
Git branch at the end of the session
cwd
str | None
Working directory for the session
tag
str | None
User-set session tag (see
tag_session()
)
created_at
int | None
Session creation time in milliseconds since epoch
​
Example
Print the 10 most recent sessions for a project. Results are sorted by
last_modified
descending, so the first item is the newest. Omit
directory
to search across all projects.
from
claude_agent_sdk
import
list_sessions
for
session
in
list_sessions(
directory
=
"/path/to/project"
,
limit
=
10
):
print
(
f
"
{
session.summary
}
(
{
session.session_id
}
)"
)
​
get_session_messages()
Retrieves messages from a past session. Synchronous; returns immediately.
def
get_session_messages
(
session_id
:
str
,
directory
:
str
|
None
=
None
,
limit
:
int
|
None
=
None
,
offset
:
int
=
0
) -> list[SessionMessage]
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
The session ID to retrieve messages for
directory
str | None
None
Project directory to look in. When omitted, searches all projects
limit
int | None
None
Maximum number of messages to return
offset
int
0
Number of messages to skip from the start
​
Return type:
SessionMessage
Property
Type
Description
type
Literal["user", "assistant"]
Message role
uuid
str
Unique message identifier
session_id
str
Session identifier
message
Any
Raw message content
parent_tool_use_id
None
Reserved for future use
​
Example
from
claude_agent_sdk
import
list_sessions, get_session_messages
sessions
=
list_sessions(
limit
=
1
)
if
sessions:
messages
=
get_session_messages(sessions[
0
].session_id)
for
msg
in
messages:
print
(
f
"[
{
msg.type
}
]
{
msg.uuid
}
"
)
​
get_session_info()
Reads metadata for a single session by ID without scanning the full project directory. Synchronous; returns immediately.
def
get_session_info
(
session_id
:
str
,
directory
:
str
|
None
=
None
,
) -> SDKSessionInfo
|
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to look up
directory
str | None
None
Project directory path. When omitted, searches all project directories
Returns
SDKSessionInfo
, or
None
if the session is not found.
​
Example
Look up a single session’s metadata without scanning the project directory. Useful when you already have a session ID from a previous run.
from
claude_agent_sdk
import
get_session_info
info
=
get_session_info(
"550e8400-e29b-41d4-a716-446655440000"
)
if
info:
print
(
f
"
{
info.summary
}
(branch:
{
info.git_branch
}
, tag:
{
info.tag
}
)"
)
​
rename_session()
Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins. Synchronous.
def
rename_session
(
session_id
:
str
,
title
:
str
,
directory
:
str
|
None
=
None
,
) ->
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to rename
title
str
required
New title. Must be non-empty after stripping whitespace
directory
str | None
None
Project directory path. When omitted, searches all project directories
Raises
ValueError
if
session_id
is not a valid UUID or
title
is empty;
FileNotFoundError
if the session cannot be found.
​
Example
Rename the most recent session so it’s easier to find later. The new title appears in
SDKSessionInfo.custom_title
on subsequent reads.
from
claude_agent_sdk
import
list_sessions, rename_session
sessions
=
list_sessions(
directory
=
"/path/to/project"
,
limit
=
1
)
if
sessions:
rename_session(sessions[
0
].session_id,
"Refactor auth module"
)
​
tag_session()
Tags a session. Pass
None
to clear the tag. Repeated calls are safe; the most recent tag wins. Synchronous.
def
tag_session
(
session_id
:
str
,
tag
:
str
|
None
,
directory
:
str
|
None
=
None
,
) ->
None
​
Parameters
Parameter
Type
Default
Description
session_id
str
required
UUID of the session to tag
tag
str | None
required
Tag string, or
None
to clear. Unicode-sanitized before storing
directory
str | None
None
Project directory path. When omitted, searches all project directories
Raises
ValueError
if
session_id
is not a valid UUID or
tag
is empty after sanitization;
FileNotFoundError
if the session cannot be found.
​
Example
Tag a session, then filter by that tag on a later read. Pass
None
to clear an existing tag.
from
claude_agent_sdk
import
list_sessions, tag_session
# Tag a session
tag_session(
"550e8400-e29b-41d4-a716-446655440000"
,
"needs-review"
)
# Later: find all sessions with that tag
for
session
in
list_sessions(
directory
=
"/path/to/project"
):
if
session.tag
==
"needs-review"
:
print
(session.summary)
​
Classes
​
ClaudeSDKClient
Maintains a conversation session across multiple exchanges.
This is the Python equivalent of how the TypeScript SDK’s
query()
function works internally - it creates a client object that can continue conversations.
​
Key Features
Session continuity
: Maintains conversation context across multiple
query()
calls
Same conversation
: The session retains previous messages
Interrupt support
: Can stop execution mid-task
Explicit lifecycle
: You control when the session starts and ends
Response-driven flow
: Can react to responses and send follow-ups
Custom tools and hooks
: Supports custom tools (created with
@tool
decorator) and hooks
class
ClaudeSDKClient
:
def
__init__
(
self
,
options
: ClaudeAgentOptions
|
None
=
None
,
transport
: Transport
|
None
=
None
)
async
def
connect
(
self
,
prompt
:
str
|
AsyncIterable[
dict
]
|
None
=
None
) ->
None
async
def
query(
self
, prompt:
str
|
AsyncIterable[
dict
], session_id:
str
=
"default"
)
->
None
async
def
receive_messages(
self
)
->
AsyncIterator[Message]
async
def
receive_response(
self
)
->
AsyncIterator[Message]
async
def
interrupt(
self
)
->
None
async
def
set_permission_mode(
self
, mode:
str
)
->
None
async
def
set_model(
self
, model:
str
|
None
=
None
)
->
None
async
def
rewind_files(
self
, user_message_id:
str
)
->
None
async
def
get_mcp_status(
self
)
->
McpStatusResponse
async
def
reconnect_mcp_server(
self
, server_name:
str
)
->
None
async
def
toggle_mcp_server(
self
, server_name:
str
, enabled:
bool
)
->
None
async
def
stop_task(
self
, task_id:
str
)
->
None
async
def
get_server_info(
self
)
->
dict[
str
, Any]
|
None
async
def
disconnect(
self
)
->
None
​
Methods
Method
Description
__init__(options)
Initialize the client with optional configuration
connect(prompt)
Connect to Claude with an optional initial prompt or message stream
query(prompt, session_id)
Send a new request in streaming mode
receive_messages()
Receive all messages from Claude as an async iterator
receive_response()
Receive messages until and including a ResultMessage
interrupt()
Send interrupt signal (only works in streaming mode)
set_permission_mode(mode)
Change the permission mode for the current session
set_model(model)
Change the model for the current session. Pass
None
to reset to default
rewind_files(user_message_id)
Restore files to their state at the specified user message. Requires
enable_file_checkpointing=True
. See
File checkpointing
get_mcp_status()
Get the status of all configured MCP servers. Returns
McpStatusResponse
reconnect_mcp_server(server_name)
Retry connecting to an MCP server that failed or was disconnected
toggle_mcp_server(server_name, enabled)
Enable or disable an MCP server mid-session. Disabling removes its tools
stop_task(task_id)
Stop a running background task. A
TaskNotificationMessage
with status
"stopped"
follows in the message stream
get_server_info()
Get server information including session ID and capabilities
disconnect()
Disconnect from Claude
​
Context Manager Support
The client can be used as an async context manager for automatic connection management:
async
with
ClaudeSDKClient()
as
client:
await
client.query(
"Hello Claude"
)
async
for
message
in
client.receive_response():
print
(message)
Important:
When iterating over messages, avoid using
break
to exit early as this can cause asyncio cleanup issues. Instead, let the iteration complete naturally or use flags to track when you’ve found what you need.
​
Example - Continuing a conversation
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async
def
main
():
async
with
ClaudeSDKClient()
as
client:
# First question
await
client.query(
"What's the capital of France?"
)
# Process response
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
# Follow-up question - the session retains the previous context
await
client.query(
"What's the population of that city?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
# Another follow-up - still in the same conversation
await
client.query(
"What are some famous landmarks there?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Claude:
{
block.text
}
"
)
asyncio.run(main())
​
Example - Streaming input with ClaudeSDKClient
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient
async
def
message_stream
():
"""Generate messages dynamically."""
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Analyze the following data:"
},
}
await
asyncio.sleep(
0.5
)
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Temperature: 25°C, Humidity: 60%"
},
}
await
asyncio.sleep(
0.5
)
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"What patterns do you see?"
},
}
async
def
main
():
async
with
ClaudeSDKClient()
as
client:
# Stream input to Claude
await
client.query(message_stream())
# Process response
async
for
message
in
client.receive_response():
print
(message)
# Follow-up in same session
await
client.query(
"Should we be concerned about these readings?"
)
async
for
message
in
client.receive_response():
print
(message)
asyncio.run(main())
​
Example - Using interrupts
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async
def
interruptible_task
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Bash"
],
permission_mode
=
"acceptEdits"
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
# Start a long-running task
await
client.query(
"Count from 1 to 100 slowly, using the bash sleep command"
)
# Let it run for a bit
await
asyncio.sleep(
2
)
# Interrupt the task
await
client.interrupt()
print
(
"Task interrupted!"
)
# Drain the interrupted task's messages (including its ResultMessage)
async
for
message
in
client.receive_response():
if
isinstance
(message, ResultMessage):
print
(
f
"Interrupted task finished with subtype=
{
message.subtype
!r}
"
)
# subtype is "error_during_execution" for interrupted tasks
# Send a new command
await
client.query(
"Just say hello instead"
)
# Now receive the new response
async
for
message
in
client.receive_response():
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"New result:
{
message.result
}
"
)
asyncio.run(interruptible_task())
Buffer behavior after interrupt:
interrupt()
sends a stop signal but does not clear the message buffer. Messages already produced by the interrupted task, including its
ResultMessage
(with
subtype="error_during_execution"
), remain in the stream. You must drain them with
receive_response()
before reading the response to a new query. If you send a new query immediately after
interrupt()
and call
receive_response()
only once, you’ll receive the interrupted task’s messages, not the new query’s response.
​
Example - Advanced permission control
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions
from
claude_agent_sdk.types
import
(
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
custom_permission_handler
(
tool_name
:
str
,
input_data
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
"""Custom logic for tool permissions."""
# Block writes to system directories
if
tool_name
==
"Write"
and
input_data.get(
"file_path"
,
""
).startswith(
"/system/"
):
return
PermissionResultDeny(
message
=
"System directory write not allowed"
,
interrupt
=
True
)
# Redirect sensitive file operations
if
tool_name
in
[
"Write"
,
"Edit"
]
and
"config"
in
input_data.get(
"file_path"
,
""
):
safe_path
=
f
"./sandbox/
{
input_data[
'file_path'
]
}
"
return
PermissionResultAllow(
updated_input
=
{
**
input_data,
"file_path"
: safe_path}
)
# Allow everything else
return
PermissionResultAllow(
updated_input
=
input_data)
async
def
main
():
options
=
ClaudeAgentOptions(
can_use_tool
=
custom_permission_handler,
allowed_tools
=
[
"Read"
,
"Write"
,
"Edit"
]
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Update the system config file"
)
async
for
message
in
client.receive_response():
# Will use sandbox path instead
print
(message)
asyncio.run(main())
​
Types
@dataclass
vs
TypedDict
:
This SDK uses two kinds of types. Classes decorated with
@dataclass
(such as
ResultMessage
,
AgentDefinition
,
TextBlock
) are object instances at runtime and support attribute access:
msg.result
. Classes defined with
TypedDict
(such as
ThinkingConfigEnabled
,
McpStdioServerConfig
,
SyncHookJSONOutput
) are
plain dicts at runtime
and require key access:
config["budget_tokens"]
, not
config.budget_tokens
. The
ClassName(field=value)
call syntax works for both, but only dataclasses produce objects with attributes.
​
SdkMcpTool
Definition for an SDK MCP tool created with the
@tool
decorator.
@dataclass
class
SdkMcpTool
(Generic[T]):
name:
str
description:
str
input_schema: type[T]
|
dict[
str
, Any]
handler: Callable[[T], Awaitable[dict[
str
, Any]]]
annotations: ToolAnnotations
|
None
=
None
Property
Type
Description
name
str
Unique identifier for the tool
description
str
Human-readable description
input_schema
type[T] | dict[str, Any]
Schema for input validation
handler
Callable[[T], Awaitable[dict[str, Any]]]
Async function that handles tool execution
annotations
ToolAnnotations | None
Optional MCP tool annotations (e.g.,
readOnlyHint
,
destructiveHint
,
openWorldHint
). From
mcp.types
​
Transport
Abstract base class for custom transport implementations. Use this to communicate with the Claude process over a custom channel (for example, a remote connection instead of a local subprocess).
This is a low-level internal API. The interface may change in future releases. Custom implementations must be updated to match any interface changes.
from
abc
import
ABC
, abstractmethod
from
collections.abc
import
AsyncIterator
from
typing
import
Any
class
Transport
(
ABC
):
@abstractmethod
async
def
connect
(
self
) ->
None
:
...
@abstractmethod
async
def
write
(
self
,
data
:
str
) ->
None
:
...
@abstractmethod
def
read_messages
(
self
) -> AsyncIterator[dict[
str
, Any]]:
...
@abstractmethod
async
def
close
(
self
) ->
None
:
...
@abstractmethod
def
is_ready
(
self
) ->
bool
:
...
@abstractmethod
async
def
end_input
(
self
) ->
None
:
...
Method
Description
connect()
Connect the transport and prepare for communication
write(data)
Write raw data (JSON + newline) to the transport
read_messages()
Async iterator that yields parsed JSON messages
close()
Close the connection and clean up resources
is_ready()
Returns
True
if the transport can send and receive
end_input()
Close the input stream (for example, close stdin for subprocess transports)
Import:
from claude_agent_sdk import Transport
​
ClaudeAgentOptions
Configuration dataclass for Claude Code queries.
@dataclass
class
ClaudeAgentOptions
:
tools: list[
str
]
|
ToolsPreset
|
None
=
None
allowed_tools: list[
str
]
=
field(
default_factory
=
list
)
system_prompt:
str
|
SystemPromptPreset
|
None
=
None
mcp_servers: dict[
str
, McpServerConfig]
|
str
|
Path
=
field(
default_factory
=
dict
)
strict_mcp_config:
bool
=
False
permission_mode: PermissionMode
|
None
=
None
continue_conversation:
bool
=
False
resume:
str
|
None
=
None
max_turns:
int
|
None
=
None
max_budget_usd:
float
|
None
=
None
disallowed_tools: list[
str
]
=
field(
default_factory
=
list
)
model:
str
|
None
=
None
fallback_model:
str
|
None
=
None
betas: list[SdkBeta]
=
field(
default_factory
=
list
)
output_format: dict[
str
, Any]
|
None
=
None
permission_prompt_tool_name:
str
|
None
=
None
cwd:
str
|
Path
|
None
=
None
cli_path:
str
|
Path
|
None
=
None
settings:
str
|
None
=
None
add_dirs: list[
str
|
Path]
=
field(
default_factory
=
list
)
env: dict[
str
,
str
]
=
field(
default_factory
=
dict
)
extra_args: dict[
str
,
str
|
None
]
=
field(
default_factory
=
dict
)
max_buffer_size:
int
|
None
=
None
debug_stderr: Any
=
sys.stderr
# Deprecated
stderr: Callable[[
str
],
None
]
|
None
=
None
can_use_tool: CanUseTool
|
None
=
None
hooks: dict[HookEvent, list[HookMatcher]]
|
None
=
None
user:
str
|
None
=
None
include_partial_messages:
bool
=
False
include_hook_events:
bool
=
False
fork_session:
bool
=
False
agents: dict[
str
, AgentDefinition]
|
None
=
None
setting_sources: list[SettingSource]
|
None
=
None
sandbox: SandboxSettings
|
None
=
None
plugins: list[SdkPluginConfig]
=
field(
default_factory
=
list
)
max_thinking_tokens:
int
|
None
=
None
# Deprecated: use thinking instead
thinking: ThinkingConfig
|
None
=
None
effort: Literal[
"low"
,
"medium"
,
"high"
,
"xhigh"
,
"max"
]
|
None
=
None
enable_file_checkpointing:
bool
=
False
session_store: SessionStore
|
None
=
None
session_store_flush: SessionStoreFlushMode
=
"batched"
Property
Type
Default
Description
tools
list[str] | ToolsPreset | None
None
Tools configuration. Use
{"type": "preset", "preset": "claude_code"}
for Claude Code’s default tools
allowed_tools
list[str]
[]
Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to
permission_mode
and
can_use_tool
. Use
disallowed_tools
to block tools. See
Permissions
system_prompt
str | SystemPromptPreset | None
None
System prompt configuration. Pass a string for custom prompt, or use
{"type": "preset", "preset": "claude_code"}
for Claude Code’s system prompt. Add
"append"
to extend the preset
mcp_servers
dict[str, McpServerConfig] | str | Path
{}
MCP server configurations or path to config file
strict_mcp_config
bool
False
When
True
, use only the servers passed in
mcp_servers
and ignore project
.mcp.json
, user settings, and plugin-provided MCP servers. Maps to the CLI
--strict-mcp-config
flag
permission_mode
PermissionMode | None
None
Permission mode for tool usage
continue_conversation
bool
False
Continue the most recent conversation
resume
str | None
None
Session ID to resume
max_turns
int | None
None
Maximum agentic turns (tool-use round trips)
max_budget_usd
float | None
None
Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as
total_cost_usd
; see
Track cost and usage
for accuracy caveats
disallowed_tools
list[str]
[]
Tools to always deny. Deny rules are checked first and override
allowed_tools
and
permission_mode
(including
bypassPermissions
)
enable_file_checkpointing
bool
False
Enable file change tracking for rewinding. See
File checkpointing
model
str | None
None
Claude model to use
fallback_model
str | None
None
Fallback model to use if the primary model fails
betas
list[SdkBeta]
[]
Beta features to enable. See
SdkBeta
for available options
output_format
dict[str, Any] | None
None
Output format for structured responses (e.g.,
{"type": "json_schema", "schema": {...}}
). See
Structured outputs
for details
permission_prompt_tool_name
str | None
None
MCP tool name for permission prompts
cwd
str | Path | None
None
Current working directory
cli_path
str | Path | None
None
Custom path to the Claude Code CLI executable
settings
str | None
None
Path to settings file
add_dirs
list[str | Path]
[]
Additional directories Claude can access
env
dict[str, str]
{}
Environment variables merged on top of the inherited process environment. See
Environment variables
for variables the underlying CLI reads, and
Handle slow or stalled API responses
for timeout-related variables
extra_args
dict[str, str | None]
{}
Additional CLI arguments to pass directly to the CLI
max_buffer_size
int | None
None
Maximum bytes when buffering CLI stdout
debug_stderr
Any
sys.stderr
Deprecated
- File-like object for debug output. Use
stderr
callback instead
stderr
Callable[[str], None] | None
None
Callback function for stderr output from CLI
can_use_tool
CanUseTool
| None
None
Tool permission callback function. See
Permission types
for details
hooks
dict[HookEvent, list[HookMatcher]] | None
None
Hook configurations for intercepting events
user
str | None
None
User identifier
include_partial_messages
bool
False
Include partial message streaming events. When enabled,
StreamEvent
messages are yielded
include_hook_events
bool
False
Include hook lifecycle events in the message stream as
HookEventMessage
objects
fork_session
bool
False
When resuming with
resume
, fork to a new session ID instead of continuing the original session
agents
dict[str, AgentDefinition] | None
None
Programmatically defined subagents
plugins
list[SdkPluginConfig]
[]
Load custom plugins from local paths. See
Plugins
for details
sandbox
SandboxSettings
| None
None
Configure sandbox behavior programmatically. See
Sandbox settings
for details
setting_sources
list[SettingSource] | None
None
(CLI defaults: all sources)
Control which filesystem settings to load. Pass
[]
to disable user, project, and local settings. Managed policy settings load regardless. See
Use Claude Code features
skills
list[str] | Literal["all"] | None
None
Skills available to the session. Pass
"all"
to enable every discovered skill, or a list of skill names. When set, the SDK enables the Skill tool automatically without listing it in
allowed_tools
. See
Skills
max_thinking_tokens
int | None
None
Deprecated
- Maximum tokens for thinking blocks. Use
thinking
instead
thinking
ThinkingConfig
| None
None
Controls extended thinking behavior. Takes precedence over
max_thinking_tokens
effort
Literal["low", "medium", "high", "xhigh", "max"] | None
None
Effort level for thinking depth
session_store
SessionStore
| None
None
Mirror session transcripts to an external backend so any host can resume them. See
Persist sessions to external storage
session_store_flush
Literal["batched", "eager"]
"batched"
When to flush mirrored transcript entries to
session_store
.
"batched"
flushes once per turn or when the buffer fills;
"eager"
triggers a background flush after every frame. Ignored when
session_store
is
None
​
Handle slow or stalled API responses
The CLI subprocess reads several environment variables that control API timeouts and stall detection. Pass them through
ClaudeAgentOptions.env
:
options
=
ClaudeAgentOptions(
env
=
{
"API_TIMEOUT_MS"
:
"120000"
,
"CLAUDE_CODE_MAX_RETRIES"
:
"2"
,
"CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS"
:
"120000"
,
},
)
API_TIMEOUT_MS
: per-request timeout on the Anthropic client, in milliseconds. Default
600000
. Applies to the main loop and all subagents.
CLAUDE_CODE_MAX_RETRIES
: maximum API retries. Default
10
. Each retry gets its own
API_TIMEOUT_MS
window, so worst-case wall time is roughly
API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)
plus backoff.
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
: stall watchdog for subagents launched with
run_in_background
. Default
600000
. Resets on each stream event; on stall it aborts the subagent, marks the task failed, and surfaces the error to the parent with any partial result. Does not apply to synchronous subagents.
CLAUDE_ENABLE_STREAM_WATCHDOG=1
with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
: aborts the request when headers have arrived but the response body stops streaming. Off by default.
CLAUDE_STREAM_IDLE_TIMEOUT_MS
defaults to
300000
and is clamped to that minimum. The aborted request goes through the normal retry path.
​
OutputFormat
Configuration for structured output validation. Pass this as a
dict
to the
output_format
field on
ClaudeAgentOptions
:
# Expected dict shape for output_format
{
"type"
:
"json_schema"
,
"schema"
: {
...
},
# Your JSON Schema definition
}
Field
Required
Description
type
Yes
Must be
"json_schema"
for JSON Schema validation
schema
Yes
JSON Schema definition for output validation
​
SystemPromptPreset
Configuration for using Claude Code’s preset system prompt with optional additions.
class
SystemPromptPreset
(
TypedDict
):
type
: Literal[
"preset"
]
preset: Literal[
"claude_code"
]
append: NotRequired[
str
]
exclude_dynamic_sections: NotRequired[
bool
]
Field
Required
Description
type
Yes
Must be
"preset"
to use a preset system prompt
preset
Yes
Must be
"claude_code"
to use Claude Code’s system prompt
append
No
Additional instructions to append to the preset system prompt
exclude_dynamic_sections
No
Move per-session context such as working directory, the git-repo flag, and auto-memory paths from the system prompt into the first user message. Improves prompt-cache reuse across users and machines. See
Modify system prompts
​
SettingSource
Controls which filesystem-based configuration sources the SDK loads settings from.
SettingSource
=
Literal[
"user"
,
"project"
,
"local"
]
Value
Description
Location
"user"
Global user settings
~/.claude/settings.json
"project"
Shared project settings (version controlled)
.claude/settings.json
"local"
Local project settings (gitignored)
.claude/settings.local.json
​
Default behavior
When
setting_sources
is omitted or
None
,
query()
loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See
What settingSources does not control
for inputs that are read regardless of this option, and how to disable them.
​
Why use setting_sources
Disable filesystem settings:
# Do not load user, project, or local settings from disk
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
for
message
in
query(
prompt
=
"Analyze this code"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[]
),
):
print
(message)
In Python SDK 0.1.59 and earlier, an empty list was treated the same as omitting the option, so
setting_sources=[]
did not disable filesystem settings. Upgrade to a newer release if you need an empty list to take effect. The TypeScript SDK is not affected.
Load all filesystem settings explicitly:
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
for
message
in
query(
prompt
=
"Analyze this code"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
,
"local"
]
),
):
print
(message)
Load only specific setting sources:
# Load only project settings, ignore user and local
async
for
message
in
query(
prompt
=
"Run CI checks"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
]
# Only .claude/settings.json
),
):
print
(message)
Testing and CI environments:
# Ensure consistent behavior in CI by excluding local settings
async
for
message
in
query(
prompt
=
"Run tests"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Only team-shared settings
permission_mode
=
"bypassPermissions"
,
),
):
print
(message)
SDK-only applications:
# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
async
for
message
in
query(
prompt
=
"Review this PR"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[],
agents
=
{
...
},
mcp_servers
=
{
...
},
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
),
):
print
(message)
Loading CLAUDE.md project instructions:
# Load project settings to include CLAUDE.md files
async
for
message
in
query(
prompt
=
"Add a new feature following project conventions"
,
options
=
ClaudeAgentOptions(
system_prompt
=
{
"type"
:
"preset"
,
"preset"
:
"claude_code"
,
# Use Claude Code's system prompt
},
setting_sources
=
[
"project"
],
# Loads CLAUDE.md from project
allowed_tools
=
[
"Read"
,
"Write"
,
"Edit"
],
),
):
print
(message)
​
Settings precedence
When multiple sources are loaded, settings are merged with this precedence (highest to lowest):
Local settings (
.claude/settings.local.json
)
Project settings (
.claude/settings.json
)
User settings (
~/.claude/settings.json
)
Programmatic options such as
agents
and
allowed_tools
override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.
​
AgentDefinition
Configuration for a subagent defined programmatically.
@dataclass
class
AgentDefinition
:
description:
str
prompt:
str
tools: list[
str
]
|
None
=
None
disallowedTools: list[
str
]
|
None
=
None
model:
str
|
None
=
None
skills: list[
str
]
|
None
=
None
memory: Literal[
"user"
,
"project"
,
"local"
]
|
None
=
None
mcpServers: list[
str
|
dict[
str
, Any]]
|
None
=
None
initialPrompt:
str
|
None
=
None
maxTurns:
int
|
None
=
None
background:
bool
|
None
=
None
effort: Literal[
"low"
,
"medium"
,
"high"
,
"xhigh"
,
"max"
]
|
int
|
None
=
None
permissionMode: PermissionMode
|
None
=
None
Field
Required
Description
description
Yes
Natural language description of when to use this agent
prompt
Yes
The agent’s system prompt
tools
No
Array of allowed tool names. If omitted, inherits all tools
disallowedTools
No
Array of tool names to remove from the agent’s tool set
model
No
Model override for this agent. Accepts an alias such as
"sonnet"
,
"opus"
,
"haiku"
, or
"inherit"
, or a full model ID. If omitted, uses the main model
skills
No
List of skill names to preload into the agent’s context at startup. Unlisted skills remain invocable through the Skill tool
memory
No
Memory source for this agent:
"user"
,
"project"
, or
"local"
mcpServers
No
MCP servers available to this agent. Each entry is a server name or an inline
{name: config}
dict
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main thread agent
maxTurns
No
Maximum number of agentic turns before the agent stops
background
No
Run this agent as a non-blocking background task when invoked
effort
No
Reasoning effort level for this agent. Accepts a named level or an integer
permissionMode
No
Permission mode for tool execution within this agent. See
PermissionMode
AgentDefinition
field names use camelCase, such as
disallowedTools
,
permissionMode
, and
maxTurns
. These names map directly to the wire format shared with the TypeScript SDK. This differs from
ClaudeAgentOptions
, which uses Python snake_case for the equivalent top-level fields such as
disallowed_tools
and
permission_mode
. Because
AgentDefinition
is a dataclass, passing a snake_case keyword raises a
TypeError
at construction time.
​
PermissionMode
Permission modes for controlling tool execution.
PermissionMode
=
Literal[
"default"
,
# Standard permission behavior
"acceptEdits"
,
# Auto-accept file edits
"plan"
,
# Planning mode - read-only tools only
"dontAsk"
,
# Deny anything not pre-approved instead of prompting
"bypassPermissions"
,
# Bypass all permission checks (use with caution)
]
​
CanUseTool
Type alias for tool permission callback functions.
CanUseTool
=
Callable[
[
str
, dict[
str
, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
The callback receives:
tool_name
: Name of the tool being called
input_data
: The tool’s input parameters
context
: A
ToolPermissionContext
with additional information
Returns a
PermissionResult
(either
PermissionResultAllow
or
PermissionResultDeny
).
​
ToolPermissionContext
Context information passed to tool permission callbacks.
@dataclass
class
ToolPermissionContext
:
signal: Any
|
None
=
None
# Future: abort signal support
suggestions: list[PermissionUpdate]
=
field(
default_factory
=
list
)
blocked_path:
str
|
None
=
None
decision_reason:
str
|
None
=
None
title:
str
|
None
=
None
display_name:
str
|
None
=
None
description:
str
|
None
=
None
Field
Type
Description
signal
Any | None
Reserved for future abort signal support
suggestions
list[PermissionUpdate]
Permission update suggestions from the CLI. Bash prompts include a suggestion with the
localSettings
destination, so returning it in
updated_permissions
writes the rule to
.claude/settings.local.json
and persists across sessions.
blocked_path
str | None
File path that triggered the permission request, when applicable. For example, when a Bash command tries to access a path outside allowed directories
decision_reason
str | None
Reason this permission request was triggered. Forwarded from a PreToolUse hook’s
permissionDecisionReason
when the hook returned
"ask"
title
str | None
Full permission prompt sentence, such as
Claude wants to read foo.txt
. Use as the primary prompt text when present
display_name
str | None
Short noun phrase for the tool action, such as
Read file
, suitable for button labels
description
str | None
Human-readable subtitle for the permission UI
​
PermissionResult
Union type for permission callback results.
PermissionResult
=
PermissionResultAllow
|
PermissionResultDeny
​
PermissionResultAllow
Result indicating the tool call should be allowed.
@dataclass
class
PermissionResultAllow
:
behavior: Literal[
"allow"
]
=
"allow"
updated_input: dict[
str
, Any]
|
None
=
None
updated_permissions: list[PermissionUpdate]
|
None
=
None
Field
Type
Default
Description
behavior
Literal["allow"]
"allow"
Must be “allow”
updated_input
dict[str, Any] | None
None
Modified input to use instead of original
updated_permissions
list[PermissionUpdate] | None
None
Permission updates to apply
​
PermissionResultDeny
Result indicating the tool call should be denied.
@dataclass
class
PermissionResultDeny
:
behavior: Literal[
"deny"
]
=
"deny"
message:
str
=
""
interrupt:
bool
=
False
Field
Type
Default
Description
behavior
Literal["deny"]
"deny"
Must be “deny”
message
str
""
Message explaining why the tool was denied
interrupt
bool
False
Whether to interrupt the current execution
​
PermissionUpdate
Configuration for updating permissions programmatically.
@dataclass
class
PermissionUpdate
:
type
: Literal[
"addRules"
,
"replaceRules"
,
"removeRules"
,
"setMode"
,
"addDirectories"
,
"removeDirectories"
,
]
rules: list[PermissionRuleValue]
|
None
=
None
behavior: Literal[
"allow"
,
"deny"
,
"ask"
]
|
None
=
None
mode: PermissionMode
|
None
=
None
directories: list[
str
]
|
None
=
None
destination: (
Literal[
"userSettings"
,
"projectSettings"
,
"localSettings"
,
"session"
]
|
None
)
=
None
Field
Type
Description
type
Literal[...]
The type of permission update operation
rules
list[PermissionRuleValue] | None
Rules for add/replace/remove operations
behavior
Literal["allow", "deny", "ask"] | None
Behavior for rule-based operations
mode
PermissionMode | None
Mode for setMode operation
directories
list[str] | None
Directories for add/remove directory operations
destination
Literal[...] | None
Where to apply the permission update
​
PermissionRuleValue
A rule to add, replace, or remove in a permission update.
@dataclass
class
PermissionRuleValue
:
tool_name:
str
rule_content:
str
|
None
=
None
​
ToolsPreset
Preset tools configuration for using Claude Code’s default tool set.
class
ToolsPreset
(
TypedDict
):
type
: Literal[
"preset"
]
preset: Literal[
"claude_code"
]
​
ThinkingConfig
Controls extended thinking behavior. A union of three configurations:
class
ThinkingConfigAdaptive
(
TypedDict
):
type
: Literal[
"adaptive"
]
class
ThinkingConfigEnabled
(
TypedDict
):
type
: Literal[
"enabled"
]
budget_tokens:
int
class
ThinkingConfigDisabled
(
TypedDict
):
type
: Literal[
"disabled"
]
ThinkingConfig
=
ThinkingConfigAdaptive
|
ThinkingConfigEnabled
|
ThinkingConfigDisabled
Variant
Fields
Description
adaptive
type
Claude adaptively decides when to think
enabled
type
,
budget_tokens
Enable thinking with a specific token budget
disabled
type
Disable thinking
Because these are
TypedDict
classes, they’re plain dicts at runtime. Either construct them as dict literals or call the class like a constructor; both produce a
dict
. Access fields with
config["budget_tokens"]
, not
config.budget_tokens
:
from
claude_agent_sdk
import
ClaudeAgentOptions, ThinkingConfigEnabled
# Option 1: dict literal (recommended, no import needed)
options
=
ClaudeAgentOptions(
thinking
=
{
"type"
:
"enabled"
,
"budget_tokens"
:
20000
})
# Option 2: constructor-style (returns a plain dict)
config
=
ThinkingConfigEnabled(
type
=
"enabled"
,
budget_tokens
=
20000
)
print
(config[
"budget_tokens"
])
# 20000
# config.budget_tokens would raise AttributeError
​
SdkBeta
Literal type for SDK beta features.
SdkBeta
=
Literal[
"context-1m-2025-08-07"
]
Use with the
betas
field in
ClaudeAgentOptions
to enable beta features.
The
context-1m-2025-08-07
beta is retired as of April 30, 2026. Passing this header with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to
Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7
, which include 1M context at standard pricing with no beta header required.
​
McpSdkServerConfig
Configuration for SDK MCP servers created with
create_sdk_mcp_server()
.
class
McpSdkServerConfig
(
TypedDict
):
type
: Literal[
"sdk"
]
name:
str
instance: Any
# MCP Server instance
​
McpServerConfig
Union type for MCP server configurations.
McpServerConfig
=
(
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfig
)
​
McpStdioServerConfig
class
McpStdioServerConfig
(
TypedDict
):
type
: NotRequired[Literal[
"stdio"
]]
# Optional for backwards compatibility
command:
str
args: NotRequired[list[
str
]]
env: NotRequired[dict[
str
,
str
]]
​
McpSSEServerConfig
class
McpSSEServerConfig
(
TypedDict
):
type
: Literal[
"sse"
]
url:
str
headers: NotRequired[dict[
str
,
str
]]
​
McpHttpServerConfig
class
McpHttpServerConfig
(
TypedDict
):
type
: Literal[
"http"
]
url:
str
headers: NotRequired[dict[
str
,
str
]]
​
McpServerStatusConfig
The configuration of an MCP server as reported by
get_mcp_status()
. This is the union of all
McpServerConfig
transport variants plus an output-only
claudeai-proxy
variant for servers proxied through claude.ai.
McpServerStatusConfig
=
(
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfigStatus
|
McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus
is the serializable form of
McpSdkServerConfig
with only
type
(
"sdk"
) and
name
(
str
) fields; the in-process
instance
is omitted.
McpClaudeAIProxyServerConfig
has
type
(
"claudeai-proxy"
),
url
(
str
), and
id
(
str
) fields.
​
McpStatusResponse
Response from
ClaudeSDKClient.get_mcp_status()
. Wraps the list of server statuses under the
mcpServers
key.
class
McpStatusResponse
(
TypedDict
):
mcpServers: list[McpServerStatus]
​
McpServerStatus
Status of a connected MCP server, contained in
McpStatusResponse
.
class
McpServerStatus
(
TypedDict
):
name:
str
status: McpServerConnectionStatus
# "connected" | "failed" | "needs-auth" | "pending" | "disabled"
serverInfo: NotRequired[McpServerInfo]
error: NotRequired[
str
]
config: NotRequired[McpServerStatusConfig]
scope: NotRequired[
str
]
tools: NotRequired[list[McpToolInfo]]
Field
Type
Description
name
str
Server name
status
str
One of
"connected"
,
"failed"
,
"needs-auth"
,
"pending"
, or
"disabled"
serverInfo
dict
(optional)
Server name and version (
{"name": str, "version": str}
)
error
str
(optional)
Error message if the server failed to connect
config
McpServerStatusConfig
(optional)
Server configuration. Same shape as
McpServerConfig
(stdio, SSE, HTTP, or SDK), plus a
claudeai-proxy
variant for servers connected through claude.ai
scope
str
(optional)
Configuration scope
tools
list
(optional)
Tools provided by this server, each with
name
,
description
, and
annotations
fields
​
SdkPluginConfig
Configuration for loading plugins in the SDK.
class
SdkPluginConfig
(
TypedDict
):
type
: Literal[
"local"
]
path:
str
Field
Type
Description
type
Literal["local"]
Must be
"local"
(only local plugins currently supported)
path
str
Absolute or relative path to the plugin directory
Example:
plugins
=
[
{
"type"
:
"local"
,
"path"
:
"./my-plugin"
},
{
"type"
:
"local"
,
"path"
:
"/absolute/path/to/plugin"
},
]
For complete information on creating and using plugins, see
Plugins
.
​
Message Types
​
Message
Union type of all possible messages.
Message
=
(
UserMessage
|
AssistantMessage
|
SystemMessage
|
ResultMessage
|
StreamEvent
|
RateLimitEvent
)
​
UserMessage
User input message.
@dataclass
class
UserMessage
:
content:
str
|
list[ContentBlock]
uuid:
str
|
None
=
None
parent_tool_use_id:
str
|
None
=
None
tool_use_result: dict[
str
, Any]
|
None
=
None
Field
Type
Description
content
str | list[ContentBlock]
Message content as text or content blocks
uuid
str | None
Unique message identifier
parent_tool_use_id
str | None
Tool use ID if this message is a tool result response
tool_use_result
dict[str, Any] | None
Tool result data if applicable
​
AssistantMessage
Assistant response message with content blocks.
@dataclass
class
AssistantMessage
:
content: list[ContentBlock]
model:
str
parent_tool_use_id:
str
|
None
=
None
error: AssistantMessageError
|
None
=
None
usage: dict[
str
, Any]
|
None
=
None
message_id:
str
|
None
=
None
Field
Type
Description
content
list[ContentBlock]
List of content blocks in the response
model
str
Model that generated the response
parent_tool_use_id
str | None
Tool use ID if this is a nested response
error
AssistantMessageError
| None
Error type if the response encountered an error
usage
dict[str, Any] | None
Per-message token usage (same keys as
ResultMessage.usage
)
message_id
str | None
API message ID. Multiple messages from one turn share the same ID
​
AssistantMessageError
Possible error types for assistant messages.
AssistantMessageError
=
Literal[
"authentication_failed"
,
"billing_error"
,
"rate_limit"
,
"invalid_request"
,
"server_error"
,
"max_output_tokens"
,
"unknown"
,
]
​
SystemMessage
System message with metadata.
@dataclass
class
SystemMessage
:
subtype:
str
data: dict[
str
, Any]
​
ResultMessage
Final result message with cost and usage information.
@dataclass
class
ResultMessage
:
subtype:
str
duration_ms:
int
duration_api_ms:
int
is_error:
bool
num_turns:
int
session_id:
str
stop_reason:
str
|
None
=
None
total_cost_usd:
float
|
None
=
None
usage: dict[
str
, Any]
|
None
=
None
result:
str
|
None
=
None
structured_output: Any
=
None
model_usage: dict[
str
, Any]
|
None
=
None
permission_denials: list[Any]
|
None
=
None
deferred_tool_use: DeferredToolUse
|
None
=
None
errors: list[
str
]
|
None
=
None
api_error_status:
int
|
None
=
None
uuid:
str
|
None
=
None
The
usage
dict contains the following keys when present:
Key
Type
Description
input_tokens
int
Total input tokens consumed.
output_tokens
int
Total output tokens generated.
cache_creation_input_tokens
int
Tokens used to create new cache entries.
cache_read_input_tokens
int
Tokens read from existing cache entries.
The
model_usage
dict maps model names to per-model usage. The inner dict keys use camelCase because the value is passed through unmodified from the underlying CLI process, matching the TypeScript
ModelUsage
type:
Key
Type
Description
inputTokens
int
Input tokens for this model.
outputTokens
int
Output tokens for this model.
cacheReadInputTokens
int
Cache read tokens for this model.
cacheCreationInputTokens
int
Cache creation tokens for this model.
webSearchRequests
int
Web search requests made by this model.
costUSD
float
Estimated cost in USD for this model, computed client-side. See
Track cost and usage
for billing caveats.
contextWindow
int
Context window size for this model.
maxOutputTokens
int
Maximum output token limit for this model.
​
StreamEvent
Stream event for partial message updates during streaming. Only received when
include_partial_messages=True
in
ClaudeAgentOptions
. Import via
from claude_agent_sdk.types import StreamEvent
.
@dataclass
class
StreamEvent
:
uuid:
str
session_id:
str
event: dict[
str
, Any]
# The raw Claude API stream event
parent_tool_use_id:
str
|
None
=
None
Field
Type
Description
uuid
str
Unique identifier for this event
session_id
str
Session identifier
event
dict[str, Any]
The raw Claude API stream event data
parent_tool_use_id
str | None
Parent tool use ID if this event is from a subagent
​
RateLimitEvent
Emitted when rate limit status changes (for example, from
"allowed"
to
"allowed_warning"
). Use this to warn users before they hit a hard limit, or to back off when status is
"rejected"
.
@dataclass
class
RateLimitEvent
:
rate_limit_info: RateLimitInfo
uuid:
str
session_id:
str
Field
Type
Description
rate_limit_info
RateLimitInfo
Current rate limit state
uuid
str
Unique event identifier
session_id
str
Session identifier
​
RateLimitInfo
Rate limit state carried by
RateLimitEvent
.
RateLimitStatus
=
Literal[
"allowed"
,
"allowed_warning"
,
"rejected"
]
RateLimitType
=
Literal[
"five_hour"
,
"seven_day"
,
"seven_day_opus"
,
"seven_day_sonnet"
,
"overage"
]
@dataclass
class
RateLimitInfo
:
status: RateLimitStatus
resets_at:
int
|
None
=
None
rate_limit_type: RateLimitType
|
None
=
None
utilization:
float
|
None
=
None
overage_status: RateLimitStatus
|
None
=
None
overage_resets_at:
int
|
None
=
None
overage_disabled_reason:
str
|
None
=
None
raw: dict[
str
, Any]
=
field(
default_factory
=
dict
)
Field
Type
Description
status
RateLimitStatus
Current status.
"allowed_warning"
means approaching the limit;
"rejected"
means the limit was hit
resets_at
int | None
Unix timestamp when the rate limit window resets
rate_limit_type
RateLimitType | None
Which rate limit window applies
utilization
float | None
Fraction of the rate limit consumed (0.0 to 1.0)
overage_status
RateLimitStatus | None
Status of pay-as-you-go overage usage, if applicable
overage_resets_at
int | None
Unix timestamp when the overage window resets
overage_disabled_reason
str | None
Why overage is unavailable, if status is
"rejected"
raw
dict[str, Any]
Full raw dict from the CLI, including fields not modeled above
​
TaskStartedMessage
Emitted when a background task starts. A background task is anything tracked outside the main turn: a backgrounded Bash command, a
Monitor
watch, a subagent spawned via the Agent tool, or a remote agent. The
task_type
field tells you which. This naming is unrelated to the
Task
-to-
Agent
tool rename.
@dataclass
class
TaskStartedMessage
(
SystemMessage
):
task_id:
str
description:
str
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
task_type:
str
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
description
str
Description of the task
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
task_type
str | None
Which kind of background task:
"local_bash"
for background Bash and Monitor watches,
"local_agent"
, or
"remote_agent"
​
TaskUsage
Token and timing data for a background task.
class
TaskUsage
(
TypedDict
):
total_tokens:
int
tool_uses:
int
duration_ms:
int
​
TaskProgressMessage
Emitted periodically with progress updates for a running background task.
@dataclass
class
TaskProgressMessage
(
SystemMessage
):
task_id:
str
description:
str
usage: TaskUsage
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
last_tool_name:
str
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
description
str
Current status description
usage
TaskUsage
Token usage for this task so far
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
last_tool_name
str | None
Name of the last tool the task used
​
TaskNotificationMessage
Emitted when a background task completes, fails, or is stopped. Background tasks include
run_in_background
Bash commands, Monitor watches, and background subagents.
@dataclass
class
TaskNotificationMessage
(
SystemMessage
):
task_id:
str
status: TaskNotificationStatus
# "completed" | "failed" | "stopped"
output_file:
str
summary:
str
uuid:
str
session_id:
str
tool_use_id:
str
|
None
=
None
usage: TaskUsage
|
None
=
None
Field
Type
Description
task_id
str
Unique identifier for the task
status
TaskNotificationStatus
One of
"completed"
,
"failed"
, or
"stopped"
output_file
str
Path to the task output file
summary
str
Summary of the task result
uuid
str
Unique message identifier
session_id
str
Session identifier
tool_use_id
str | None
Associated tool use ID
usage
TaskUsage | None
Final token usage for the task
​
Content Block Types
​
ContentBlock
Union type of all content blocks.
ContentBlock
=
TextBlock
|
ThinkingBlock
|
ToolUseBlock
|
ToolResultBlock
​
TextBlock
Text content block.
@dataclass
class
TextBlock
:
text:
str
​
ThinkingBlock
Thinking content block (for models with thinking capability).
@dataclass
class
ThinkingBlock
:
thinking:
str
signature:
str
​
ToolUseBlock
Tool use request block.
@dataclass
class
ToolUseBlock
:
id
:
str
name:
str
input
: dict[
str
, Any]
​
ToolResultBlock
Tool execution result block.
@dataclass
class
ToolResultBlock
:
tool_use_id:
str
content:
str
|
list[dict[
str
, Any]]
|
None
=
None
is_error:
bool
|
None
=
None
​
Error Types
​
ClaudeSDKError
Base exception class for all SDK errors.
class
ClaudeSDKError
(
Exception
):
"""Base error for Claude SDK."""
​
CLINotFoundError
Raised when Claude Code CLI is not installed or not found.
class
CLINotFoundError
(
CLIConnectionError
):
def
__init__
(
self
,
message
:
str
=
"Claude Code not found"
,
cli_path
:
str
|
None
=
None
):
"""
Args:
message: Error message (default: "Claude Code not found")
cli_path: Optional path to the CLI that was not found
"""
​
CLIConnectionError
Raised when connection to Claude Code fails.
class
CLIConnectionError
(
ClaudeSDKError
):
"""Failed to connect to Claude Code."""
​
ProcessError
Raised when the Claude Code process fails.
class
ProcessError
(
ClaudeSDKError
):
def
__init__
(
self
,
message
:
str
,
exit_code
:
int
|
None
=
None
,
stderr
:
str
|
None
=
None
):
self
.exit_code
=
exit_code
self
.stderr
=
stderr
​
CLIJSONDecodeError
Raised when JSON parsing fails.
class
CLIJSONDecodeError
(
ClaudeSDKError
):
def
__init__
(
self
,
line
:
str
,
original_error
:
Exception
):
"""
Args:
line: The line that failed to parse
original_error: The original JSON decode exception
"""
self
.line
=
line
self
.original_error
=
original_error
​
Hook Types
For a comprehensive guide on using hooks with examples and common patterns, see the
Hooks guide
.
​
HookEvent
Supported hook event types.
HookEvent
=
Literal[
"PreToolUse"
,
# Called before tool execution
"PostToolUse"
,
# Called after tool execution
"PostToolUseFailure"
,
# Called when a tool execution fails
"UserPromptSubmit"
,
# Called when user submits a prompt
"Stop"
,
# Called when stopping execution
"SubagentStop"
,
# Called when a subagent stops
"PreCompact"
,
# Called before message compaction
"Notification"
,
# Called for notification events
"SubagentStart"
,
# Called when a subagent starts
"PermissionRequest"
,
# Called when a permission decision is needed
]
The TypeScript SDK supports additional hook events not yet available in Python:
SessionStart
,
SessionEnd
,
Setup
,
TeammateIdle
,
TaskCompleted
,
ConfigChange
,
WorktreeCreate
,
WorktreeRemove
, and
PostToolBatch
.
​
HookCallback
Type definition for hook callback functions.
HookCallback
=
Callable[[HookInput,
str
|
None
, HookContext], Awaitable[HookJSONOutput]]
Parameters:
input
: Strongly-typed hook input with discriminated unions based on
hook_event_name
(see
HookInput
)
tool_use_id
: Optional tool use identifier (for tool-related hooks)
context
: Hook context with additional information
Returns a
HookJSONOutput
that may contain:
decision
:
"block"
to block the action
systemMessage
: warning message shown to the user
hookSpecificOutput
: Hook-specific output data
​
HookContext
Context information passed to hook callbacks.
class
HookContext
(
TypedDict
):
signal: Any
|
None
# Future: abort signal support
​
HookMatcher
Configuration for matching hooks to specific events or tools.
@dataclass
class
HookMatcher
:
matcher:
str
|
None
=
(
None
# Tool name or pattern to match (e.g., "Bash", "Write|Edit")
)
hooks: list[HookCallback]
=
field(
default_factory
=
list
)
# List of callbacks to execute
timeout:
float
|
None
=
(
None
# Timeout in seconds for all hooks in this matcher (default: 60)
)
​
HookInput
Union type of all hook input types. The actual type depends on the
hook_event_name
field.
HookInput
=
(
PreToolUseHookInput
|
PostToolUseHookInput
|
PostToolUseFailureHookInput
|
UserPromptSubmitHookInput
|
StopHookInput
|
SubagentStopHookInput
|
PreCompactHookInput
|
NotificationHookInput
|
SubagentStartHookInput
|
PermissionRequestHookInput
)
​
BaseHookInput
Base fields present in all hook input types.
class
BaseHookInput
(
TypedDict
):
session_id:
str
transcript_path:
str
cwd:
str
permission_mode: NotRequired[
str
]
Field
Type
Description
session_id
str
Current session identifier
transcript_path
str
Path to the session transcript file
cwd
str
Current working directory
permission_mode
str
(optional)
Current permission mode
​
PreToolUseHookInput
Input data for
PreToolUse
hook events.
class
PreToolUseHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PreToolUse"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_use_id:
str
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PreToolUse"]
Always “PreToolUse”
tool_name
str
Name of the tool about to be executed
tool_input
dict[str, Any]
Input parameters for the tool
tool_use_id
str
Unique identifier for this tool use
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
PostToolUseHookInput
Input data for
PostToolUse
hook events.
class
PostToolUseHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PostToolUse"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_response: Any
tool_use_id:
str
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PostToolUse"]
Always “PostToolUse”
tool_name
str
Name of the tool that was executed
tool_input
dict[str, Any]
Input parameters that were used
tool_response
Any
Response from the tool execution
tool_use_id
str
Unique identifier for this tool use
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
PostToolUseFailureHookInput
Input data for
PostToolUseFailure
hook events. Called when a tool execution fails.
class
PostToolUseFailureHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PostToolUseFailure"
]
tool_name:
str
tool_input: dict[
str
, Any]
tool_use_id:
str
error:
str
is_interrupt: NotRequired[
bool
]
agent_id: NotRequired[
str
]
agent_type: NotRequired[
str
]
Field
Type
Description
hook_event_name
Literal["PostToolUseFailure"]
Always “PostToolUseFailure”
tool_name
str
Name of the tool that failed
tool_input
dict[str, Any]
Input parameters that were used
tool_use_id
str
Unique identifier for this tool use
error
str
Error message from the failed execution
is_interrupt
bool
(optional)
Whether the failure was caused by an interrupt
agent_id
str
(optional)
Subagent identifier, present when the hook fires inside a subagent
agent_type
str
(optional)
Subagent type, present when the hook fires inside a subagent
​
UserPromptSubmitHookInput
Input data for
UserPromptSubmit
hook events.
class
UserPromptSubmitHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"UserPromptSubmit"
]
prompt:
str
Field
Type
Description
hook_event_name
Literal["UserPromptSubmit"]
Always “UserPromptSubmit”
prompt
str
The user’s submitted prompt
​
StopHookInput
Input data for
Stop
hook events.
class
StopHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"Stop"
]
stop_hook_active:
bool
Field
Type
Description
hook_event_name
Literal["Stop"]
Always “Stop”
stop_hook_active
bool
Whether the stop hook is active
​
SubagentStopHookInput
Input data for
SubagentStop
hook events.
class
SubagentStopHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"SubagentStop"
]
stop_hook_active:
bool
agent_id:
str
agent_transcript_path:
str
agent_type:
str
Field
Type
Description
hook_event_name
Literal["SubagentStop"]
Always “SubagentStop”
stop_hook_active
bool
Whether the stop hook is active
agent_id
str
Unique identifier for the subagent
agent_transcript_path
str
Path to the subagent’s transcript file
agent_type
str
Type of the subagent
​
PreCompactHookInput
Input data for
PreCompact
hook events.
class
PreCompactHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PreCompact"
]
trigger: Literal[
"manual"
,
"auto"
]
custom_instructions:
str
|
None
Field
Type
Description
hook_event_name
Literal["PreCompact"]
Always “PreCompact”
trigger
Literal["manual", "auto"]
What triggered the compaction
custom_instructions
str | None
Custom instructions for compaction
​
NotificationHookInput
Input data for
Notification
hook events.
class
NotificationHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"Notification"
]
message:
str
title: NotRequired[
str
]
notification_type:
str
Field
Type
Description
hook_event_name
Literal["Notification"]
Always “Notification”
message
str
Notification message content
title
str
(optional)
Notification title
notification_type
str
Type of notification
​
SubagentStartHookInput
Input data for
SubagentStart
hook events.
class
SubagentStartHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"SubagentStart"
]
agent_id:
str
agent_type:
str
Field
Type
Description
hook_event_name
Literal["SubagentStart"]
Always “SubagentStart”
agent_id
str
Unique identifier for the subagent
agent_type
str
Type of the subagent
​
PermissionRequestHookInput
Input data for
PermissionRequest
hook events. Allows hooks to handle permission decisions programmatically.
class
PermissionRequestHookInput
(
BaseHookInput
):
hook_event_name: Literal[
"PermissionRequest"
]
tool_name:
str
tool_input: dict[
str
, Any]
permission_suggestions: NotRequired[list[Any]]
Field
Type
Description
hook_event_name
Literal["PermissionRequest"]
Always “PermissionRequest”
tool_name
str
Name of the tool requesting permission
tool_input
dict[str, Any]
Input parameters for the tool
permission_suggestions
list[Any]
(optional)
Suggested permission updates from the CLI
​
HookJSONOutput
Union type for hook callback return values.
HookJSONOutput
=
AsyncHookJSONOutput
|
SyncHookJSONOutput
​
SyncHookJSONOutput
Synchronous hook output with control and decision fields.
class
SyncHookJSONOutput
(
TypedDict
):
# Control fields
continue_: NotRequired[
bool
]
# Whether to proceed (default: True)
suppressOutput: NotRequired[
bool
]
# Hide stdout from transcript
stopReason: NotRequired[
str
]
# Message when continue is False
# Decision fields
decision: NotRequired[Literal[
"block"
]]
systemMessage: NotRequired[
str
]
# Warning message for user
reason: NotRequired[
str
]
# Feedback for Claude
# Hook-specific output
hookSpecificOutput: NotRequired[HookSpecificOutput]
Use
continue_
(with underscore) in Python code. It is automatically converted to
continue
when sent to the CLI.
​
HookSpecificOutput
A
TypedDict
containing the hook event name and event-specific fields. The shape depends on the
hookEventName
value. For full details on available fields per hook event, see
Control execution with hooks
.
A discriminated union of event-specific output types. The
hookEventName
field determines which fields are valid.
class
PreToolUseHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PreToolUse"
]
permissionDecision: NotRequired[Literal[
"allow"
,
"deny"
,
"ask"
,
"defer"
]]
permissionDecisionReason: NotRequired[
str
]
updatedInput: NotRequired[dict[
str
, Any]]
additionalContext: NotRequired[
str
]
class
PostToolUseHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PostToolUse"
]
additionalContext: NotRequired[
str
]
updatedToolOutput: NotRequired[Any]
updatedMCPToolOutput: NotRequired[Any]
class
PostToolUseFailureHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PostToolUseFailure"
]
additionalContext: NotRequired[
str
]
class
UserPromptSubmitHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"UserPromptSubmit"
]
additionalContext: NotRequired[
str
]
class
NotificationHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"Notification"
]
additionalContext: NotRequired[
str
]
class
SubagentStartHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"SubagentStart"
]
additionalContext: NotRequired[
str
]
class
PermissionRequestHookSpecificOutput
(
TypedDict
):
hookEventName: Literal[
"PermissionRequest"
]
decision: dict[
str
, Any]
HookSpecificOutput
=
(
PreToolUseHookSpecificOutput
|
PostToolUseHookSpecificOutput
|
PostToolUseFailureHookSpecificOutput
|
UserPromptSubmitHookSpecificOutput
|
NotificationHookSpecificOutput
|
SubagentStartHookSpecificOutput
|
PermissionRequestHookSpecificOutput
)
​
AsyncHookJSONOutput
Async hook output that defers hook execution.
class
AsyncHookJSONOutput
(
TypedDict
):
async_: Literal[
True
]
# Set to True to defer execution
asyncTimeout: NotRequired[
int
]
# Timeout in milliseconds
Use
async_
(with underscore) in Python code. It is automatically converted to
async
when sent to the CLI.
​
Hook Usage Example
This example registers two hooks: one that blocks dangerous bash commands like
rm -rf /
, and another that logs all tool usage for auditing. The security hook only runs on Bash commands (via the
matcher
), while the logging hook runs on all tools.
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher, HookContext
from
typing
import
Any
async
def
validate_bash_command
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Validate and potentially block dangerous bash commands."""
if
input_data[
"tool_name"
]
==
"Bash"
:
command
=
input_data[
"tool_input"
].get(
"command"
,
""
)
if
"rm -rf /"
in
command:
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Dangerous command blocked"
,
}
}
return
{}
async
def
log_tool_use
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log all tool usage for auditing."""
print
(
f
"Tool used:
{
input_data.get(
'tool_name'
)
}
"
)
return
{}
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[validate_bash_command],
timeout
=
120
),
# 2 min for validation
HookMatcher(
hooks
=
[log_tool_use]
),
# Applies to all tools (default 60s timeout)
],
"PostToolUse"
: [HookMatcher(
hooks
=
[log_tool_use])],
}
)
async
for
message
in
query(
prompt
=
"Analyze this codebase"
,
options
=
options):
print
(message)
​
Tool Input/Output Types
Documentation of input/output schemas for all built-in Claude Code tools. While the Python SDK doesn’t export these as types, they represent the structure of tool inputs and outputs in messages.
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
Input:
{
"description"
:
str
,
# A short (3-5 word) description of the task
"prompt"
:
str
,
# The task for the agent to perform
"subagent_type"
:
str
,
# The type of specialized agent to use
}
Output:
{
"result"
:
str
,
# Final result from the subagent
"usage"
:
dict
|
None
,
# Token usage statistics
"total_cost_usd"
:
float
|
None
,
# Estimated total cost in USD
"duration_ms"
:
int
|
None
,
# Execution duration in milliseconds
}
​
AskUserQuestion
Tool name:
AskUserQuestion
Asks the user clarifying questions during execution. See
Handle approvals and user input
for usage details.
Input:
{
"questions"
: [
# Questions to ask the user (1-4 questions)
{
"question"
:
str
,
# The complete question to ask the user
"header"
:
str
,
# Very short label displayed as a chip/tag (max 12 chars)
"options"
: [
# The available choices (2-4 options)
{
"label"
:
str
,
# Display text for this option (1-5 words)
"description"
:
str
,
# Explanation of what this option means
}
],
"multiSelect"
:
bool
,
# Set to true to allow multiple selections
}
],
"answers"
: dict[
str
,
str
|
list[
str
]]
|
None
,
# User answers populated by the permission system. Multi-select
# answers may be a list of labels or a comma-joined string
}
Output:
{
"questions"
: [
# The questions that were asked
{
"question"
:
str
,
"header"
:
str
,
"options"
: [{
"label"
:
str
,
"description"
:
str
}],
"multiSelect"
:
bool
,
}
],
"answers"
: dict[
str
,
str
],
# Maps question text to answer string
# Multi-select answers are comma-separated
}
​
Bash
Tool name:
Bash
Input:
{
"command"
:
str
,
# The command to execute
"timeout"
:
int
|
None
,
# Optional timeout in milliseconds (max 600000)
"description"
:
str
|
None
,
# Clear, concise description (5-10 words)
"run_in_background"
:
bool
|
None
,
# Set to true to run in background
}
Output:
{
"output"
:
str
,
# Combined stdout and stderr output
"exitCode"
:
int
,
# Exit code of the command
"killed"
:
bool
|
None
,
# Whether command was killed due to timeout
"shellId"
:
str
|
None
,
# Shell ID for background processes
}
​
Monitor
Tool name:
Monitor
Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Monitor follows the same permission rules as Bash. See the
Monitor tool reference
for behavior and provider availability.
Input:
{
"command"
:
str
,
# Shell script; each stdout line is an event, exit ends the watch
"description"
:
str
,
# Short description shown in notifications
"timeout_ms"
:
int
|
None
,
# Kill after this deadline (default 300000, max 3600000)
"persistent"
:
bool
|
None
,
# Run for the lifetime of the session; stop with TaskStop
}
Output:
{
"taskId"
:
str
,
# ID of the background monitor task
"timeoutMs"
:
int
,
# Timeout deadline in milliseconds (0 when persistent)
"persistent"
:
bool
|
None
,
# True when running until TaskStop or session end
}
​
Edit
Tool name:
Edit
Input:
{
"file_path"
:
str
,
# The absolute path to the file to modify
"old_string"
:
str
,
# The text to replace
"new_string"
:
str
,
# The text to replace it with
"replace_all"
:
bool
|
None
,
# Replace all occurrences (default False)
}
Output:
{
"message"
:
str
,
# Confirmation message
"replacements"
:
int
,
# Number of replacements made
"file_path"
:
str
,
# File path that was edited
}
​
Read
Tool name:
Read
Input:
{
"file_path"
:
str
,
# The absolute path to the file to read
"offset"
:
int
|
None
,
# The line number to start reading from
"limit"
:
int
|
None
,
# The number of lines to read
}
Output (Text files):
{
"content"
:
str
,
# File contents with line numbers
"total_lines"
:
int
,
# Total number of lines in file
"lines_returned"
:
int
,
# Lines actually returned
}
Output (Images):
{
"image"
:
str
,
# Base64 encoded image data
"mime_type"
:
str
,
# Image MIME type
"file_size"
:
int
,
# File size in bytes
}
​
Write
Tool name:
Write
Input:
{
"file_path"
:
str
,
# The absolute path to the file to write
"content"
:
str
,
# The content to write to the file
}
Output:
{
"message"
:
str
,
# Success message
"bytes_written"
:
int
,
# Number of bytes written
"file_path"
:
str
,
# File path that was written
}
​
Glob
Tool name:
Glob
Input:
{
"pattern"
:
str
,
# The glob pattern to match files against
"path"
:
str
|
None
,
# The directory to search in (defaults to cwd)
}
Output:
{
"matches"
: list[
str
],
# Array of matching file paths
"count"
:
int
,
# Number of matches found
"search_path"
:
str
,
# Search directory used
}
​
Grep
Tool name:
Grep
Input:
{
"pattern"
:
str
,
# The regular expression pattern
"path"
:
str
|
None
,
# File or directory to search in
"glob"
:
str
|
None
,
# Glob pattern to filter files
"type"
:
str
|
None
,
# File type to search
"output_mode"
:
str
|
None
,
# "content", "files_with_matches", or "count"
"-i"
:
bool
|
None
,
# Case insensitive search
"-n"
:
bool
|
None
,
# Show line numbers
"-B"
:
int
|
None
,
# Lines to show before each match
"-A"
:
int
|
None
,
# Lines to show after each match
"-C"
:
int
|
None
,
# Lines to show before and after
"head_limit"
:
int
|
None
,
# Limit output to first N lines/entries
"multiline"
:
bool
|
None
,
# Enable multiline mode
}
Output (content mode):
{
"matches"
: [
{
"file"
:
str
,
"line_number"
:
int
|
None
,
"line"
:
str
,
"before_context"
: list[
str
]
|
None
,
"after_context"
: list[
str
]
|
None
,
}
],
"total_matches"
:
int
,
}
Output (files_with_matches mode):
{
"files"
: list[
str
],
# Files containing matches
"count"
:
int
,
# Number of files with matches
}
​
NotebookEdit
Tool name:
NotebookEdit
Input:
{
"notebook_path"
:
str
,
# Absolute path to the Jupyter notebook
"cell_id"
:
str
|
None
,
# The ID of the cell to edit
"new_source"
:
str
,
# The new source for the cell
"cell_type"
:
"code"
|
"markdown"
|
None
,
# The type of the cell
"edit_mode"
:
"replace"
|
"insert"
|
"delete"
|
None
,
# Edit operation type
}
Output:
{
"message"
:
str
,
# Success message
"edit_type"
:
"replaced"
|
"inserted"
|
"deleted"
,
# Type of edit performed
"cell_id"
:
str
|
None
,
# Cell ID that was affected
"total_cells"
:
int
,
# Total cells in notebook after edit
}
​
WebFetch
Tool name:
WebFetch
Input:
{
"url"
:
str
,
# The URL to fetch content from
"prompt"
:
str
,
# The prompt to run on the fetched content
}
Output:
{
"bytes"
:
int
,
# Size of the fetched content in bytes
"code"
:
int
,
# HTTP response code
"codeText"
:
str
,
# HTTP response code text
"result"
:
str
,
# Processed result from applying the prompt to the content
"durationMs"
:
int
,
# Time to fetch and process the content, in milliseconds
"url"
:
str
,
# URL that was fetched
}
​
WebSearch
Tool name:
WebSearch
Input:
{
"query"
:
str
,
# The search query to use
"allowed_domains"
: list[
str
]
|
None
,
# Only include results from these domains
"blocked_domains"
: list[
str
]
|
None
,
# Never include results from these domains
}
Output:
{
"query"
:
str
,
# The search query
"results"
: list[
str
|
{
"tool_use_id"
:
str
,
"content"
: list[{
"title"
:
str
,
"url"
:
str
}]}],
"durationSeconds"
:
float
,
# Search duration in seconds
}
​
TodoWrite
Tool name:
TodoWrite
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
Input:
{
"todos"
: [
{
"content"
:
str
,
# The task description
"status"
:
"pending"
|
"in_progress"
|
"completed"
,
# Task status
"activeForm"
:
str
,
# Active form of the description
}
]
}
Output:
{
"message"
:
str
,
# Success message
"stats"
: {
"total"
:
int
,
"pending"
:
int
,
"in_progress"
:
int
,
"completed"
:
int
},
}
​
TaskCreate
Tool name:
TaskCreate
Input:
{
"subject"
:
str
,
# Short task title
"description"
:
str
,
# Detailed task body
"activeForm"
:
str
|
None
,
# Present-tense label shown while in progress
"metadata"
:
dict
|
None
,
# Arbitrary caller metadata
}
Output:
{
"task"
: {
"id"
:
str
,
"subject"
:
str
},
# Created task with assigned ID
}
​
TaskUpdate
Tool name:
TaskUpdate
Input:
{
"taskId"
:
str
,
# ID of the task to patch
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
,
"deleted"
]
|
None
,
"subject"
:
str
|
None
,
"description"
:
str
|
None
,
"activeForm"
:
str
|
None
,
"addBlocks"
: list[
str
]
|
None
,
# Task IDs this task now blocks
"addBlockedBy"
: list[
str
]
|
None
,
# Task IDs that now block this task
"owner"
:
str
|
None
,
"metadata"
:
dict
|
None
,
}
Output:
{
"success"
:
bool
,
"taskId"
:
str
,
"updatedFields"
: list[
str
],
# Names of fields that changed
"error"
:
str
|
None
,
"statusChange"
: {
"from"
:
str
,
"to"
:
str
}
|
None
,
}
​
TaskGet
Tool name:
TaskGet
Input:
{
"taskId"
:
str
,
# ID of the task to read
}
Output:
{
"task"
: {
"id"
:
str
,
"subject"
:
str
,
"description"
:
str
,
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
],
"blocks"
: list[
str
],
"blockedBy"
: list[
str
],
}
|
None
,
# None when the ID is not found
}
​
TaskList
Tool name:
TaskList
Input:
{}
Output:
{
"tasks"
: [
{
"id"
:
str
,
"subject"
:
str
,
"status"
: Literal[
"pending"
,
"in_progress"
,
"completed"
],
"owner"
:
str
|
None
,
"blockedBy"
: list[
str
],
}
],
}
​
BashOutput
Tool name:
BashOutput
Input:
{
"bash_id"
:
str
,
# The ID of the background shell
"filter"
:
str
|
None
,
# Optional regex to filter output lines
}
Output:
{
"output"
:
str
,
# New output since last check
"status"
:
"running"
|
"completed"
|
"failed"
,
# Current shell status
"exitCode"
:
int
|
None
,
# Exit code when completed
}
​
KillBash
Tool name:
KillBash
Input:
{
"shell_id"
:
str
# The ID of the background shell to kill
}
Output:
{
"message"
:
str
,
# Success message
"shell_id"
:
str
,
# ID of the killed shell
}
​
ExitPlanMode
Tool name:
ExitPlanMode
Input:
{
"plan"
:
str
# The plan to run by the user for approval
}
Output:
{
"message"
:
str
,
# Confirmation message
"approved"
:
bool
|
None
,
# Whether user approved the plan
}
​
ListMcpResources
Tool name:
ListMcpResources
Input:
{
"server"
:
str
|
None
# Optional server name to filter resources by
}
Output:
{
"resources"
: [
{
"uri"
:
str
,
"name"
:
str
,
"description"
:
str
|
None
,
"mimeType"
:
str
|
None
,
"server"
:
str
,
}
],
"total"
:
int
,
}
​
ReadMcpResource
Tool name:
ReadMcpResource
Input:
{
"server"
:
str
,
# The MCP server name
"uri"
:
str
,
# The resource URI to read
}
Output:
{
"contents"
: [
{
"uri"
:
str
,
"mimeType"
:
str
|
None
,
"text"
:
str
|
None
,
"blob"
:
str
|
None
}
],
"server"
:
str
,
}
​
Advanced Features with ClaudeSDKClient
​
Building a Continuous Conversation Interface
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
TextBlock,
)
import
asyncio
class
ConversationSession
:
"""Maintains a single conversation session with Claude."""
def
__init__
(
self
,
options
: ClaudeAgentOptions
|
None
=
None
):
self
.client
=
ClaudeSDKClient(options)
self
.turn_count
=
0
async
def
start
(
self
):
await
self
.client.connect()
print
(
"Starting conversation session. Claude will remember context."
)
print
(
"Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"
)
while
True
:
user_input
=
input
(
f
"
\n
[Turn
{
self
.turn_count
+
1
}
] You: "
)
if
user_input.lower()
==
"exit"
:
break
elif
user_input.lower()
==
"interrupt"
:
await
self
.client.interrupt()
print
(
"Task interrupted!"
)
continue
elif
user_input.lower()
==
"new"
:
# Disconnect and reconnect for a fresh session
await
self
.client.disconnect()
await
self
.client.connect()
self
.turn_count
=
0
print
(
"Started new conversation session (previous context cleared)"
)
continue
# Send message - the session retains all previous messages
await
self
.client.query(user_input)
self
.turn_count
+=
1
# Process response
print
(
f
"[Turn
{
self
.turn_count
}
] Claude: "
,
end
=
""
)
async
for
message
in
self
.client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(block.text,
end
=
""
)
print
()
# New line after response
await
self
.client.disconnect()
print
(
f
"Conversation ended after
{
self
.turn_count
}
turns."
)
async
def
main
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
session
=
ConversationSession(options)
await
session.start()
# Example conversation:
# Turn 1 - You: "Create a file called hello.py"
# Turn 1 - Claude: "I'll create a hello.py file for you..."
# Turn 2 - You: "What's in that file?"
# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
# Turn 3 - You: "Add a main function to it"
# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())
​
Using Hooks for Behavior Modification
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
HookContext,
)
import
asyncio
from
typing
import
Any
async
def
pre_tool_logger
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log all tool usage before execution."""
tool_name
=
input_data.get(
"tool_name"
,
"unknown"
)
print
(
f
"[PRE-TOOL] About to use:
{
tool_name
}
"
)
# You can modify or block the tool execution here
if
tool_name
==
"Bash"
and
"rm -rf"
in
str
(input_data.get(
"tool_input"
, {})):
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Dangerous command blocked"
,
}
}
return
{}
async
def
post_tool_logger
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Log results after tool execution."""
tool_name
=
input_data.get(
"tool_name"
,
"unknown"
)
print
(
f
"[POST-TOOL] Completed:
{
tool_name
}
"
)
return
{}
async
def
user_prompt_modifier
(
input_data
: dict[
str
, Any],
tool_use_id
:
str
|
None
,
context
: HookContext
) -> dict[
str
, Any]:
"""Add context to user prompts."""
original_prompt
=
input_data.get(
"prompt"
,
""
)
# Add a timestamp as additional context for Claude to see
from
datetime
import
datetime
timestamp
=
datetime.now().strftime(
"%Y-%m-
%d
%H:%M:%S"
)
return
{
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptSubmit"
,
"additionalContext"
:
f
"[Submitted at
{
timestamp
}
] Original prompt:
{
original_prompt
}
"
,
}
}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
hooks
=
[pre_tool_logger]),
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[pre_tool_logger]),
],
"PostToolUse"
: [HookMatcher(
hooks
=
[post_tool_logger])],
"UserPromptSubmit"
: [HookMatcher(
hooks
=
[user_prompt_modifier])],
},
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"List files in current directory"
)
async
for
message
in
client.receive_response():
# Hooks will automatically log tool usage
pass
asyncio.run(main())
​
Real-time Progress Monitoring
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ToolUseBlock,
ToolResultBlock,
TextBlock,
)
import
asyncio
async
def
monitor_progress
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Create 5 Python files with different sorting algorithms"
)
# Monitor progress in real-time
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
if
block.name
==
"Write"
:
file_path
=
block.input.get(
"file_path"
,
""
)
print
(
f
"Creating:
{
file_path
}
"
)
elif
isinstance
(block, ToolResultBlock):
print
(
"Completed tool execution"
)
elif
isinstance
(block, TextBlock):
print
(
f
"Claude says:
{
block.text[:
100
]
}
..."
)
print
(
"Task completed!"
)
asyncio.run(monitor_progress())
​
Example Usage
​
Basic file operations (using query)
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
import
asyncio
async
def
create_project
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
permission_mode
=
"acceptEdits"
,
cwd
=
"/home/user/project"
,
)
async
for
message
in
query(
prompt
=
"Create a Python project structure with setup.py"
,
options
=
options
):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock):
print
(
f
"Using tool:
{
block.name
}
"
)
asyncio.run(create_project())
​
Error handling
from
claude_agent_sdk
import
query, CLINotFoundError, ProcessError, CLIJSONDecodeError
try
:
async
for
message
in
query(
prompt
=
"Hello"
):
print
(message)
except
CLINotFoundError:
print
(
"Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
)
except
ProcessError
as
e:
print
(
f
"Process failed with exit code:
{
e.exit_code
}
"
)
except
CLIJSONDecodeError
as
e:
print
(
f
"Failed to parse response:
{
e
}
"
)
​
Streaming mode with client
from
claude_agent_sdk
import
ClaudeSDKClient
import
asyncio
async
def
interactive_session
():
async
with
ClaudeSDKClient()
as
client:
# Send initial message
await
client.query(
"What's the weather like?"
)
# Process responses
async
for
msg
in
client.receive_response():
print
(msg)
# Send follow-up
await
client.query(
"Tell me more about that"
)
# Process follow-up response
async
for
msg
in
client.receive_response():
print
(msg)
asyncio.run(interactive_session())
​
Using custom tools with ClaudeSDKClient
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
tool,
create_sdk_mcp_server,
AssistantMessage,
TextBlock,
)
import
asyncio
from
typing
import
Any
# Define custom tools with @tool decorator
@tool
(
"calculate"
,
"Perform mathematical calculations"
, {
"expression"
:
str
})
async
def
calculate
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
try
:
result
=
eval
(args[
"expression"
], {
"__builtins__"
: {}})
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Result:
{
result
}
"
}]}
except
Exception
as
e:
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Error:
{
str
(e)
}
"
}],
"is_error"
:
True
,
}
@tool
(
"get_time"
,
"Get current time"
, {})
async
def
get_time
(
args
: dict[
str
, Any]) -> dict[
str
, Any]:
from
datetime
import
datetime
current_time
=
datetime.now().strftime(
"%Y-%m-
%d
%H:%M:%S"
)
return
{
"content"
: [{
"type"
:
"text"
,
"text"
:
f
"Current time:
{
current_time
}
"
}]}
async
def
main
():
# Create SDK MCP server with custom tools
my_server
=
create_sdk_mcp_server(
name
=
"utilities"
,
version
=
"1.0.0"
,
tools
=
[calculate, get_time]
)
# Configure options with the server
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"utils"
: my_server},
allowed_tools
=
[
"mcp__utils__calculate"
,
"mcp__utils__get_time"
],
)
# Use ClaudeSDKClient for interactive tool usage
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"What's 123 * 456?"
)
# Process calculation response
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Calculation:
{
block.text
}
"
)
# Follow up with time query
await
client.query(
"What time is it now?"
)
async
for
message
in
client.receive_response():
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(
f
"Time:
{
block.text
}
"
)
asyncio.run(main())
​
Sandbox Configuration
​
SandboxSettings
Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.
class
SandboxSettings
(
TypedDict
,
total
=
False
):
enabled:
bool
autoAllowBashIfSandboxed:
bool
excludedCommands: list[
str
]
allowUnsandboxedCommands:
bool
network: SandboxNetworkConfig
ignoreViolations: SandboxIgnoreViolations
enableWeakerNestedSandbox:
bool
Property
Type
Default
Description
enabled
bool
False
Enable sandbox mode for command execution
autoAllowBashIfSandboxed
bool
True
Auto-approve bash commands when sandbox is enabled
excludedCommands
list[str]
[]
Commands that always bypass sandbox restrictions (e.g.,
["docker"]
). These run unsandboxed automatically without model involvement
allowUnsandboxedCommands
bool
True
Allow the model to request running commands outside the sandbox. When
True
, the model can set
dangerouslyDisableSandbox
in tool input, which falls back to the
permissions system
network
SandboxNetworkConfig
None
Network-specific sandbox configuration
ignoreViolations
SandboxIgnoreViolations
None
Configure which sandbox violations to ignore
enableWeakerNestedSandbox
bool
False
Enable a weaker nested sandbox for compatibility
​
Example usage
from
claude_agent_sdk
import
query, ClaudeAgentOptions, SandboxSettings
sandbox_settings: SandboxSettings
=
{
"enabled"
:
True
,
"autoAllowBashIfSandboxed"
:
True
,
"network"
: {
"allowLocalBinding"
:
True
},
}
async
for
message
in
query(
prompt
=
"Build and test my project"
,
options
=
ClaudeAgentOptions(
sandbox
=
sandbox_settings),
):
print
(message)
Unix socket security
: The
allowUnixSockets
option can grant access to powerful system services. For example, allowing
/var/run/docker.sock
effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.
​
SandboxNetworkConfig
Network-specific configuration for sandbox mode.
class
SandboxNetworkConfig
(
TypedDict
,
total
=
False
):
allowedDomains: list[
str
]
deniedDomains: list[
str
]
allowManagedDomainsOnly:
bool
allowUnixSockets: list[
str
]
allowAllUnixSockets:
bool
allowLocalBinding:
bool
allowMachLookup: list[
str
]
httpProxyPort:
int
socksProxyPort:
int
Property
Type
Default
Description
allowedDomains
list[str]
[]
Domain names that sandboxed processes can access
deniedDomains
list[str]
[]
Domain names that sandboxed processes cannot access. Takes precedence over
allowedDomains
allowManagedDomainsOnly
bool
False
Managed-settings only: when set in managed settings, ignore
allowedDomains
from non-managed settings sources. Has no effect when set via SDK options
allowUnixSockets
list[str]
[]
Unix socket paths that processes can access (e.g., Docker socket)
allowAllUnixSockets
bool
False
Allow access to all Unix sockets
allowLocalBinding
bool
False
Allow processes to bind to local ports (e.g., for dev servers)
allowMachLookup
list[str]
[]
macOS only: XPC/Mach service names to allow. Supports a trailing wildcard
httpProxyPort
int
None
HTTP proxy port for network requests
socksProxyPort
int
None
SOCKS proxy port for network requests
The built-in sandbox proxy enforces the network allowlist based on the requested hostname and does not terminate or inspect TLS traffic, so techniques such as
domain fronting
can potentially bypass it. See
Sandboxing security limitations
for details and
Secure deployment
for configuring a TLS-terminating proxy.
​
SandboxIgnoreViolations
Configuration for ignoring specific sandbox violations.
class
SandboxIgnoreViolations
(
TypedDict
,
total
=
False
):
file
: list[
str
]
network: list[
str
]
Property
Type
Default
Description
file
list[str]
[]
File path patterns to ignore violations for
network
list[str]
[]
Network patterns to ignore violations for
​
Permissions Fallback for Unsandboxed Commands
When
allowUnsandboxedCommands
is enabled, the model can request to run commands outside the sandbox by setting
dangerouslyDisableSandbox: True
in the tool input. These requests fall back to the existing permissions system, meaning your
can_use_tool
handler will be invoked, allowing you to implement custom authorization logic.
excludedCommands
vs
allowUnsandboxedCommands
:
excludedCommands
: A static list of commands that always bypass the sandbox automatically (e.g.,
["docker"]
). The model has no control over this.
allowUnsandboxedCommands
: Lets the model decide at runtime whether to request unsandboxed execution by setting
dangerouslyDisableSandbox: True
in the tool input.
from
claude_agent_sdk
import
(
query,
ClaudeAgentOptions,
HookMatcher,
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async
def
can_use_tool
(
tool
:
str
,
input
:
dict
,
context
: ToolPermissionContext
) -> PermissionResultAllow
|
PermissionResultDeny:
# Check if the model is requesting to bypass the sandbox
if
tool
==
"Bash"
and
input
.get(
"dangerouslyDisableSandbox"
):
# The model is requesting to run this command outside the sandbox
print
(
f
"Unsandboxed command requested:
{
input
.get(
'command'
)
}
"
)
if
is_command_authorized(
input
.get(
"command"
)):
return
PermissionResultAllow()
return
PermissionResultDeny(
message
=
"Command not authorized for unsandboxed execution"
)
return
PermissionResultAllow()
# Required: dummy hook keeps the stream open for can_use_tool
async
def
dummy_hook
(
input_data
,
tool_use_id
,
context
):
return
{
"continue_"
:
True
}
async
def
prompt_stream
():
yield
{
"type"
:
"user"
,
"message"
: {
"role"
:
"user"
,
"content"
:
"Deploy my application"
},
}
async
def
main
():
async
for
message
in
query(
prompt
=
prompt_stream(),
options
=
ClaudeAgentOptions(
sandbox
=
{
"enabled"
:
True
,
"allowUnsandboxedCommands"
:
True
,
# Model can request unsandboxed execution
},
permission_mode
=
"default"
,
can_use_tool
=
can_use_tool,
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
None
,
hooks
=
[dummy_hook])]},
),
):
print
(message)
This pattern enables you to:
Audit model requests
: Log when the model requests unsandboxed execution
Implement allowlists
: Only permit specific commands to run unsandboxed
Add approval workflows
: Require explicit authorization for privileged operations
Commands running with
dangerouslyDisableSandbox: True
have full system access. Ensure your
can_use_tool
handler validates these requests carefully.
If
permission_mode
is set to
bypassPermissions
and
allow_unsandboxed_commands
is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.
​
See also
SDK overview
- General SDK concepts
TypeScript SDK reference
- TypeScript SDK documentation
CLI reference
- Command-line interface
Common workflows
- Step-by-step guides
Was this page helpful?
Yes
No
TypeScript V2 (deprecated)
Migration Guide
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/python" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Best practices for Claude Code</title>
  <link>https://code.claude.com/docs/en/best-practices</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/best-practices</guid>
  <pubDate>Tue, 16 Jul 2024 00:00:00 +0000</pubDate>
  <category>Best Practices</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Best practices for Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (bet...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Best practices for Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an agentic coding environment. Unlike a chatbot that answers questions and waits, Claude Code can read your files, run commands, make changes, and autonomously work through problems while you watch, redirect, or step away entirely.
This changes how you work. Instead of writing code yourself and asking Claude to review it, you describe what you want and Claude figures out how to build it. Claude explores, plans, and implements.
But this autonomy still comes with a learning curve. Claude works within certain constraints you need to understand.
This guide covers patterns that have proven effective across Anthropic’s internal teams and for engineers using Claude Code across various codebases, languages, and environments. For how the agentic loop works under the hood, see
How Claude Code works
.
Most best practices are based on one constraint: Claude’s context window fills up fast, and performance degrades as it fills.
Claude’s context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.
This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start “forgetting” earlier instructions or making more mistakes. The context window is the most important resource to manage. To see how a session fills up in practice,
watch an interactive walkthrough
of what loads at startup and what each file read costs. Track context usage continuously with a
custom status line
, and see
Reduce token usage
for strategies on reducing token usage.
​
Give Claude a way to verify its work
Include tests, screenshots, or expected outputs so Claude can check itself. This is the single highest-leverage thing you can do.
Claude performs dramatically better when it can verify its own work, like run tests, compare screenshots, and validate outputs.
Without clear success criteria, it might produce something that looks right but actually doesn’t work. You become the only feedback loop, and every mistake requires your attention.
Strategy
Before
After
Provide verification criteria
”implement a function that validates email addresses"
"write a validateEmail function. example test cases:
user@example.com
is true, invalid is false,
user@.com
is false. run the tests after implementing”
Verify UI changes visually
”make the dashboard look better"
"[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them”
Address root causes, not symptoms
”the build is failing"
"the build fails with this error: [paste error]. fix it and verify the build succeeds. address the root cause, don’t suppress the error”
UI changes can be verified using the
Claude in Chrome extension
. It opens new tabs in your browser, tests the UI, and iterates until the code works.
Your verification can also be a test suite, a linter, or a Bash command that checks output. Invest in making your verification rock-solid.
​
Explore first, then plan, then code
Separate research and planning from implementation to avoid solving the wrong problem.
Letting Claude jump straight to coding can produce code that solves the wrong problem. Use
plan mode
to separate exploration from execution.
The recommended workflow has four phases:
1
Explore
Enter plan mode. Claude reads files and answers questions without making changes.
claude (plan mode)
read /src/auth and understand how we handle sessions and login.
also look at how we manage environment variables for secrets.
2
Plan
Ask Claude to create a detailed implementation plan.
claude (plan mode)
I want to add Google OAuth. What files need to change?
What's the session flow? Create a plan.
Press
Ctrl+G
to open the plan in your text editor for direct editing before Claude proceeds.
3
Implement
Switch out of plan mode and let Claude code, verifying against its plan.
claude (default mode)
implement the OAuth flow from your plan. write tests for the
callback handler, run the test suite and fix any failures.
4
Commit
Ask Claude to commit with a descriptive message and create a PR.
claude (default mode)
commit with a descriptive message and open a PR
Plan mode is useful, but also adds overhead.
For tasks where the scope is clear and the fix is small (like fixing a typo, adding a log line, or renaming a variable) ask Claude to do it directly.
Planning is most useful when you’re uncertain about the approach, when the change modifies multiple files, or when you’re unfamiliar with the code being modified. If you could describe the diff in one sentence, skip the plan.
​
Provide specific context in your prompts
The more precise your instructions, the fewer corrections you’ll need.
Claude can infer intent, but it can’t read your mind. Reference specific files, mention constraints, and point to example patterns.
Strategy
Before
After
Scope the task.
Specify which file, what scenario, and testing preferences.
”add tests for foo.py"
"write a test for foo.py covering the edge case where the user is logged out. avoid mocks.”
Point to sources.
Direct Claude to the source that can answer a question.
”why does ExecutionFactory have such a weird api?"
"look through ExecutionFactory’s git history and summarize how its api came to be”
Reference existing patterns.
Point Claude to patterns in your codebase.
”add a calendar widget"
"look at how existing widgets are implemented on the home page to understand the patterns. HotDogWidget.php is a good example. follow the pattern to implement a new calendar widget that lets the user select a month and paginate forwards/backwards to pick a year. build from scratch without libraries other than the ones already used in the codebase.”
Describe the symptom.
Provide the symptom, the likely location, and what “fixed” looks like.
”fix the login bug"
"users report that login fails after session timeout. check the auth flow in src/auth/, especially token refresh. write a failing test that reproduces the issue, then fix it”
Vague prompts can be useful when you’re exploring and can afford to course-correct. A prompt like
"what would you improve in this file?"
can surface things you wouldn’t have thought to ask about.
​
Provide rich content
Use
@
to reference files, paste screenshots/images, or pipe data directly.
You can provide rich data to Claude in several ways:
Reference files with
@
instead of describing where code lives. Claude reads the file before responding.
Paste images directly
. Copy/paste or drag and drop images into the prompt.
Give URLs
for documentation and API references. Use
/permissions
to allowlist frequently-used domains.
Pipe in data
by running
cat error.log | claude
to send file contents directly.
Let Claude fetch what it needs
. Tell Claude to pull context itself using Bash commands, MCP tools, or by reading files.
​
Configure your environment
A few setup steps make Claude Code significantly more effective across all your sessions. For a full overview of extension features and when to use each one, see
Extend Claude Code
.
​
Write an effective CLAUDE.md
Run
/init
to generate a starter CLAUDE.md file based on your current project structure, then refine over time.
CLAUDE.md is a special file that Claude reads at the start of every conversation. Include Bash commands, code style, and workflow rules. This gives Claude persistent context it can’t infer from code alone.
The
/init
command analyzes your codebase to detect build systems, test frameworks, and code patterns, giving you a solid foundation to refine.
There’s no required format for CLAUDE.md files, but keep it short and human-readable. For example:
CLAUDE.md
# Code style
-
Use ES modules (import/export) syntax, not CommonJS (require)
-
Destructure imports when possible (eg. import { foo } from 'bar')
# Workflow
-
Be sure to typecheck when you're done making a series of code changes
-
Prefer running single tests, and not the whole test suite, for performance
CLAUDE.md is loaded every session, so only include things that apply broadly. For domain knowledge or workflows that are only relevant sometimes, use
skills
instead. Claude loads them on demand without bloating every conversation.
Keep it concise. For each line, ask:
“Would removing this cause Claude to make mistakes?”
If not, cut it. Bloated CLAUDE.md files cause Claude to ignore your actual instructions!
✅ Include
❌ Exclude
Bash commands Claude can’t guess
Anything Claude can figure out by reading code
Code style rules that differ from defaults
Standard language conventions Claude already knows
Testing instructions and preferred test runners
Detailed API documentation (link to docs instead)
Repository etiquette (branch naming, PR conventions)
Information that changes frequently
Architectural decisions specific to your project
Long explanations or tutorials
Developer environment quirks (required env vars)
File-by-file descriptions of the codebase
Common gotchas or non-obvious behaviors
Self-evident practices like “write clean code”
If Claude keeps doing something you don’t want despite having a rule against it, the file is probably too long and the rule is getting lost. If Claude asks you questions that are answered in CLAUDE.md, the phrasing might be ambiguous. Treat CLAUDE.md like code: review it when things go wrong, prune it regularly, and test changes by observing whether Claude’s behavior actually shifts.
You can tune instructions by adding emphasis (e.g., “IMPORTANT” or “YOU MUST”) to improve adherence. Check CLAUDE.md into git so your team can contribute. The file compounds in value over time.
CLAUDE.md files can import additional files using
@path/to/import
syntax:
CLAUDE.md
See @README.md for project overview and @package.json for available npm commands.
# Additional Instructions
-
Git workflow: @docs/git-instructions.md
-
Personal overrides: @~/.claude/my-project-instructions.md
You can place CLAUDE.md files in several locations:
Home folder (
~/.claude/CLAUDE.md
)
: applies to all Claude sessions
Project root (
./CLAUDE.md
)
: check into git to share with your team
Project root (
./CLAUDE.local.md
)
: personal project-specific notes; add this file to your
.gitignore
so it isn’t shared with your team
Parent directories
: useful for monorepos where both
root/CLAUDE.md
and
root/foo/CLAUDE.md
are pulled in automatically
Child directories
: Claude pulls in child CLAUDE.md files on demand when working with files in those directories
​
Configure permissions
Use
auto mode
to let a classifier handle approvals,
/permissions
to allowlist specific commands, or
/sandbox
for OS-level isolation. Each reduces interruptions while keeping you in control.
By default, Claude Code requests permission for actions that might modify your system: file writes, Bash commands, MCP tools, etc. This is safe but tedious. After the tenth approval you’re not really reviewing anymore, you’re just clicking through. There are three ways to reduce these interruptions:
Auto mode
: a separate classifier model reviews commands and blocks only what looks risky: scope escalation, unknown infrastructure, or hostile-content-driven actions. Best when you trust the general direction of a task but don’t want to click through every step
Permission allowlists
: permit specific tools you know are safe, like
npm run lint
or
git commit
Sandboxing
: enable OS-level isolation that restricts filesystem and network access, allowing Claude to work more freely within defined boundaries
Read more about
permission modes
,
permission rules
, and
sandboxing
.
​
Use CLI tools
Tell Claude Code to use CLI tools like
gh
,
aws
,
gcloud
, and
sentry-cli
when interacting with external services.
CLI tools are the most context-efficient way to interact with external services. If you use GitHub, install the
gh
CLI. Claude knows how to use it for creating issues, opening pull requests, and reading comments. Without
gh
, Claude can still use the GitHub API, but unauthenticated requests often hit rate limits.
Claude is also effective at learning CLI tools it doesn’t already know. Try prompts like
Use 'foo-cli-tool --help' to learn about foo tool, then use it to solve A, B, C.
​
Connect MCP servers
Run
claude mcp add
to connect external tools like Notion, Figma, or your database.
With
MCP servers
, you can ask Claude to implement features from issue trackers, query databases, analyze monitoring data, integrate designs from Figma, and automate workflows.
​
Set up hooks
Use hooks for actions that must happen every time with zero exceptions.
Hooks
run scripts automatically at specific points in Claude’s workflow. Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens.
Claude can write hooks for you. Try prompts like
“Write a hook that runs eslint after every file edit”
or
“Write a hook that blocks writes to the migrations folder.”
Edit
.claude/settings.json
directly to configure hooks by hand, and run
/hooks
to browse what’s configured.
​
Create skills
Create
SKILL.md
files in
.claude/skills/
to give Claude domain knowledge and reusable workflows.
Skills
extend Claude’s knowledge with information specific to your project, team, or domain. Claude applies them automatically when relevant, or you can invoke them directly with
/skill-name
.
Create a skill by adding a directory with a
SKILL.md
to
.claude/skills/
:
.claude/skills/api-conventions/SKILL.md
---
name
:
api-conventions
description
:
REST API design conventions for our services
---
# API Conventions
-
Use kebab-case for URL paths
-
Use camelCase for JSON properties
-
Always include pagination for list endpoints
-
Version APIs in the URL path (/v1/, /v2/)
Skills can also define repeatable workflows you invoke directly:
.claude/skills/fix-issue/SKILL.md
---
name
:
fix-issue
description
:
Fix a GitHub issue
disable-model-invocation
:
true
---
Analyze and fix the GitHub issue: $ARGUMENTS.
1.
Use
`gh issue view`
to get the issue details
2.
Understand the problem described in the issue
3.
Search the codebase for relevant files
4.
Implement the necessary changes to fix the issue
5.
Write and run tests to verify the fix
6.
Ensure code passes linting and type checking
7.
Create a descriptive commit message
8.
Push and create a PR
Run
/fix-issue 1234
to invoke it. Use
disable-model-invocation: true
for workflows with side effects that you want to trigger manually.
​
Create custom subagents
Define specialized assistants in
.claude/agents/
that Claude can delegate to for isolated tasks.
Subagents
run in their own context with their own set of allowed tools. They’re useful for tasks that read many files or need specialized focus without cluttering your main conversation.
.claude/agents/security-reviewer.md
---
name
:
security-reviewer
description
:
Reviews code for security vulnerabilities
tools
:
Read, Grep, Glob, Bash
model
:
opus
---
You are a senior security engineer. Review code for:
-
Injection vulnerabilities (SQL, XSS, command injection)
-
Authentication and authorization flaws
-
Secrets or credentials in code
-
Insecure data handling
Provide specific line references and suggested fixes.
Tell Claude to use subagents explicitly:
“Use a subagent to review this code for security issues.”
​
Install plugins
Run
/plugin
to browse the marketplace. Plugins add skills, tools, and integrations without configuration.
Plugins
bundle skills, hooks, subagents, and MCP servers into a single installable unit from the community and Anthropic. If you work with a typed language, install a
code intelligence plugin
to give Claude precise symbol navigation and automatic error detection after edits.
For guidance on choosing between skills, subagents, hooks, and MCP, see
Extend Claude Code
.
​
Communicate effectively
The way you communicate with Claude Code significantly impacts the quality of results.
​
Ask codebase questions
Ask Claude questions you’d ask a senior engineer.
When onboarding to a new codebase, use Claude Code for learning and exploration. You can ask Claude the same sorts of questions you would ask another engineer:
How does logging work?
How do I make a new API endpoint?
What does
async move { ... }
do on line 134 of
foo.rs
?
What edge cases does
CustomerOnboardingFlowImpl
handle?
Why does this code call
foo()
instead of
bar()
on line 333?
Using Claude Code this way is an effective onboarding workflow, improving ramp-up time and reducing load on other engineers. No special prompting required: ask questions directly.
​
Let Claude interview you
For larger features, have Claude interview you first. Start with a minimal prompt and ask Claude to interview you using the
AskUserQuestion
tool.
Claude asks about things you might not have considered yet, including technical implementation, UI/UX, edge cases, and tradeoffs.
I want to build [brief description]. Interview me in detail using the AskUserQuestion tool.
Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs. Don't ask obvious questions, dig into the hard parts I might not have considered.
Keep interviewing until we've covered everything, then write a complete spec to SPEC.md.
Once the spec is complete, start a fresh session to execute it. The new session has clean context focused entirely on implementation, and you have a written spec to reference.
​
Manage your session
Conversations are persistent and reversible. Use this to your advantage!
​
Course-correct early and often
Correct Claude as soon as you notice it going off track.
The best results come from tight feedback loops. Though Claude occasionally solves problems perfectly on the first attempt, correcting it quickly generally produces better solutions faster.
Esc
: stop Claude mid-action with the
Esc
key. Context is preserved, so you can redirect.
Esc + Esc
or
/rewind
: press
Esc
twice or run
/rewind
to open the rewind menu and restore previous conversation and code state, or summarize from a selected message.
"Undo that"
: have Claude revert its changes.
/clear
: reset context between unrelated tasks. Long sessions with irrelevant context can reduce performance.
If you’ve corrected Claude more than twice on the same issue in one session, the context is cluttered with failed approaches. Run
/clear
and start fresh with a more specific prompt that incorporates what you learned. A clean session with a better prompt almost always outperforms a long session with accumulated corrections.
​
Manage context aggressively
Run
/clear
between unrelated tasks to reset context.
Claude Code automatically compacts conversation history when you approach context limits, which preserves important code and decisions while freeing space.
During long sessions, Claude’s context window can fill with irrelevant conversation, file contents, and commands. This can reduce performance and sometimes distract Claude.
Use
/clear
frequently between tasks to reset the context window entirely
When auto compaction triggers, Claude summarizes what matters most, including code patterns, file states, and key decisions
For more control, run
/compact <instructions>
, like
/compact Focus on the API changes
To compact only part of the conversation, use
Esc + Esc
or
/rewind
, select a message checkpoint, and choose
Summarize from here
or
Summarize up to here
. The first condenses messages from that point forward while keeping earlier context intact; the second condenses earlier messages while keeping recent ones in full. See
Restore vs. summarize
.
Customize compaction behavior in CLAUDE.md with instructions like
"When compacting, always preserve the full list of modified files and any test commands"
to ensure critical context survives summarization
For quick questions that don’t need to stay in context, use
/btw
. The answer appears in a dismissible overlay and never enters conversation history, so you can check a detail without growing context.
​
Use subagents for investigation
Delegate research with
"use subagents to investigate X"
. They explore in a separate context, keeping your main conversation clean for implementation.
Since context is your fundamental constraint, subagents are one of the most powerful tools available. When Claude researches a codebase it reads lots of files, all of which consume your context. Subagents run in separate context windows and report back summaries:
Use subagents to investigate how our authentication system handles token
refresh, and whether we have any existing OAuth utilities I should reuse.
The subagent explores the codebase, reads relevant files, and reports back with findings, all without cluttering your main conversation.
You can also use subagents for verification after Claude implements something:
use a subagent to review this code for edge cases
​
Rewind with checkpoints
Every prompt you send creates a checkpoint. You can restore conversation, code, or both to any previous checkpoint.
Claude automatically snapshots files before each change so a checkpoint can restore them. Double-tap
Escape
or run
/rewind
to open the rewind menu. You can restore conversation only, restore code only, restore both, or summarize from a selected message. See
Checkpointing
for details.
Instead of carefully planning every move, you can tell Claude to try something risky. If it doesn’t work, rewind and try a different approach. Checkpoints persist across sessions, so you can close your terminal and still rewind later.
Checkpoints only track changes made
by Claude
, not external processes. This isn’t a replacement for git.
​
Resume conversations
Name sessions with
/rename
and treat them like branches: each workstream gets its own persistent context.
Claude Code saves conversations locally, so when a task spans multiple sittings you don’t have to re-explain the context. Run
claude --continue
to pick up the most recent session, or
claude --resume
to choose from a list. Give sessions descriptive names like
oauth-migration
so you can find them later. See
Manage sessions
for the full set of resume, branch, and naming controls.
​
Automate and scale
Once you’re effective with one Claude, multiply your output with parallel sessions, non-interactive mode, and fan-out patterns.
Everything so far assumes one human, one Claude, and one conversation. But Claude Code scales horizontally. The techniques in this section show how you can get more done.
​
Run non-interactive mode
Use
claude -p "prompt"
in CI, pre-commit hooks, or scripts. Add
--output-format stream-json
for streaming JSON output.
With
claude -p "your prompt"
, you can run Claude non-interactively, without a session.
Non-interactive mode
is how you integrate Claude into CI pipelines, pre-commit hooks, or any automated workflow. The output formats let you parse results programmatically: plain text, JSON, or streaming JSON.
# One-off queries
claude
-p
"Explain what this project does"
# Structured output for scripts
claude
-p
"List all API endpoints"
--output-format
json
# Streaming for real-time processing
claude
-p
"Analyze this log file"
--output-format
stream-json
​
Run multiple Claude sessions
Run multiple Claude sessions in parallel to speed up development, run isolated experiments, or start complex workflows.
Pick the parallel approach that fits how much coordination you want to do yourself:
Worktrees
: run separate CLI sessions in isolated git checkouts so edits don’t collide
Desktop app
: manage multiple local sessions visually, each in its own worktree
Claude Code on the web
: run sessions on Anthropic-managed cloud infrastructure in isolated VMs
Agent teams
: automated coordination of multiple sessions with shared tasks, messaging, and a team lead
Beyond parallelizing work, multiple sessions enable quality-focused workflows. A fresh context improves code review since Claude won’t be biased toward code it just wrote.
For example, use a Writer/Reviewer pattern:
Session A (Writer)
Session B (Reviewer)
Implement a rate limiter for our API endpoints
Review the rate limiter implementation in @src/middleware/rateLimiter.ts. Look for edge cases, race conditions, and consistency with our existing middleware patterns.
Here's the review feedback: [Session B output]. Address these issues.
You can do something similar with tests: have one Claude write tests, then another write code to pass them.
​
Fan out across files
Loop through tasks calling
claude -p
for each. Use
--allowedTools
to scope permissions for batch operations.
For large migrations or analyses, you can distribute work across many parallel Claude invocations:
1
Generate a task list
Have Claude list all files that need migrating (e.g.,
list all 2,000 Python files that need migrating
)
2
Write a script to loop through the list
for
file
in
$(
cat
files.txt
);
do
claude
-p
"Migrate
$file
from React to Vue. Return OK or FAIL."
\
--allowedTools
"Edit,Bash(git commit *)"
done
3
Test on a few files, then run at scale
Refine your prompt based on what goes wrong with the first 2-3 files, then run on the full set. The
--allowedTools
flag restricts what Claude can do, which matters when you’re running unattended.
You can also integrate Claude into existing data/processing pipelines:
claude
-p
"<your prompt>"
--output-format
json
|
your_command
Use
--verbose
for debugging during development, and turn it off in production.
​
Run autonomously with auto mode
For uninterrupted execution with background safety checks, use
auto mode
. A classifier model reviews commands before they run, blocking scope escalation, unknown infrastructure, and hostile-content-driven actions while letting routine work proceed without prompts.
claude
--permission-mode
auto
-p
"fix all lint errors"
For non-interactive runs with the
-p
flag, auto mode aborts if the classifier repeatedly blocks actions, since there is no user to fall back to. See
when auto mode falls back
for thresholds.
​
Avoid common failure patterns
These are common mistakes. Recognizing them early saves time:
The kitchen sink session.
You start with one task, then ask Claude something unrelated, then go back to the first task. Context is full of irrelevant information.
Fix
:
/clear
between unrelated tasks.
Correcting over and over.
Claude does something wrong, you correct it, it’s still wrong, you correct again. Context is polluted with failed approaches.
Fix
: After two failed corrections,
/clear
and write a better initial prompt incorporating what you learned.
The over-specified CLAUDE.md.
If your CLAUDE.md is too long, Claude ignores half of it because important rules get lost in the noise.
Fix
: Ruthlessly prune. If Claude already does something correctly without the instruction, delete it or convert it to a hook.
The trust-then-verify gap.
Claude produces a plausible-looking implementation that doesn’t handle edge cases.
Fix
: Always provide verification (tests, scripts, screenshots). If you can’t verify it, don’t ship it.
The infinite exploration.
You ask Claude to “investigate” something without scoping it. Claude reads hundreds of files, filling the context.
Fix
: Scope investigations narrowly or use subagents so the exploration doesn’t consume your main context.
​
Develop your intuition
The patterns in this guide aren’t set in stone. They’re starting points that work well in general, but might not be optimal for every situation.
Sometimes you
should
let context accumulate because you’re deep in one complex problem and the history is valuable. Sometimes you should skip planning and let Claude figure it out because the task is exploratory. Sometimes a vague prompt is exactly right because you want to see how Claude interprets the problem before constraining it.
Pay attention to what works. When Claude produces great output, notice what you did: the prompt structure, the context you provided, the mode you were in. When Claude struggles, ask why. Was the context too noisy? The prompt too vague? The task too big for one pass?
Over time, you’ll develop intuition that no guide can capture. You’ll know when to be specific and when to be open-ended, when to plan and when to explore, when to clear context and when to let it accumulate.
​
Related resources
How Claude Code works
: the agentic loop, tools, and context management
Extend Claude Code
: skills, hooks, MCP, subagents, and plugins
Common workflows
: step-by-step recipes for debugging, testing, PRs, and more
CLAUDE.md
: store project conventions and persistent context
Was this page helpful?
Yes
No
Common workflows
Overview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/best-practices" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Best practices for Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (bet...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Best practices for Claude Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code is an agentic coding environment. Unlike a chatbot that answers questions and waits, Claude Code can read your files, run commands, make changes, and autonomously work through problems while you watch, redirect, or step away entirely.
This changes how you work. Instead of writing code yourself and asking Claude to review it, you describe what you want and Claude figures out how to build it. Claude explores, plans, and implements.
But this autonomy still comes with a learning curve. Claude works within certain constraints you need to understand.
This guide covers patterns that have proven effective across Anthropic’s internal teams and for engineers using Claude Code across various codebases, languages, and environments. For how the agentic loop works under the hood, see
How Claude Code works
.
Most best practices are based on one constraint: Claude’s context window fills up fast, and performance degrades as it fills.
Claude’s context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.
This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start “forgetting” earlier instructions or making more mistakes. The context window is the most important resource to manage. To see how a session fills up in practice,
watch an interactive walkthrough
of what loads at startup and what each file read costs. Track context usage continuously with a
custom status line
, and see
Reduce token usage
for strategies on reducing token usage.
​
Give Claude a way to verify its work
Include tests, screenshots, or expected outputs so Claude can check itself. This is the single highest-leverage thing you can do.
Claude performs dramatically better when it can verify its own work, like run tests, compare screenshots, and validate outputs.
Without clear success criteria, it might produce something that looks right but actually doesn’t work. You become the only feedback loop, and every mistake requires your attention.
Strategy
Before
After
Provide verification criteria
”implement a function that validates email addresses"
"write a validateEmail function. example test cases:
user@example.com
is true, invalid is false,
user@.com
is false. run the tests after implementing”
Verify UI changes visually
”make the dashboard look better"
"[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them”
Address root causes, not symptoms
”the build is failing"
"the build fails with this error: [paste error]. fix it and verify the build succeeds. address the root cause, don’t suppress the error”
UI changes can be verified using the
Claude in Chrome extension
. It opens new tabs in your browser, tests the UI, and iterates until the code works.
Your verification can also be a test suite, a linter, or a Bash command that checks output. Invest in making your verification rock-solid.
​
Explore first, then plan, then code
Separate research and planning from implementation to avoid solving the wrong problem.
Letting Claude jump straight to coding can produce code that solves the wrong problem. Use
plan mode
to separate exploration from execution.
The recommended workflow has four phases:
1
Explore
Enter plan mode. Claude reads files and answers questions without making changes.
claude (plan mode)
read /src/auth and understand how we handle sessions and login.
also look at how we manage environment variables for secrets.
2
Plan
Ask Claude to create a detailed implementation plan.
claude (plan mode)
I want to add Google OAuth. What files need to change?
What's the session flow? Create a plan.
Press
Ctrl+G
to open the plan in your text editor for direct editing before Claude proceeds.
3
Implement
Switch out of plan mode and let Claude code, verifying against its plan.
claude (default mode)
implement the OAuth flow from your plan. write tests for the
callback handler, run the test suite and fix any failures.
4
Commit
Ask Claude to commit with a descriptive message and create a PR.
claude (default mode)
commit with a descriptive message and open a PR
Plan mode is useful, but also adds overhead.
For tasks where the scope is clear and the fix is small (like fixing a typo, adding a log line, or renaming a variable) ask Claude to do it directly.
Planning is most useful when you’re uncertain about the approach, when the change modifies multiple files, or when you’re unfamiliar with the code being modified. If you could describe the diff in one sentence, skip the plan.
​
Provide specific context in your prompts
The more precise your instructions, the fewer corrections you’ll need.
Claude can infer intent, but it can’t read your mind. Reference specific files, mention constraints, and point to example patterns.
Strategy
Before
After
Scope the task.
Specify which file, what scenario, and testing preferences.
”add tests for foo.py"
"write a test for foo.py covering the edge case where the user is logged out. avoid mocks.”
Point to sources.
Direct Claude to the source that can answer a question.
”why does ExecutionFactory have such a weird api?"
"look through ExecutionFactory’s git history and summarize how its api came to be”
Reference existing patterns.
Point Claude to patterns in your codebase.
”add a calendar widget"
"look at how existing widgets are implemented on the home page to understand the patterns. HotDogWidget.php is a good example. follow the pattern to implement a new calendar widget that lets the user select a month and paginate forwards/backwards to pick a year. build from scratch without libraries other than the ones already used in the codebase.”
Describe the symptom.
Provide the symptom, the likely location, and what “fixed” looks like.
”fix the login bug"
"users report that login fails after session timeout. check the auth flow in src/auth/, especially token refresh. write a failing test that reproduces the issue, then fix it”
Vague prompts can be useful when you’re exploring and can afford to course-correct. A prompt like
"what would you improve in this file?"
can surface things you wouldn’t have thought to ask about.
​
Provide rich content
Use
@
to reference files, paste screenshots/images, or pipe data directly.
You can provide rich data to Claude in several ways:
Reference files with
@
instead of describing where code lives. Claude reads the file before responding.
Paste images directly
. Copy/paste or drag and drop images into the prompt.
Give URLs
for documentation and API references. Use
/permissions
to allowlist frequently-used domains.
Pipe in data
by running
cat error.log | claude
to send file contents directly.
Let Claude fetch what it needs
. Tell Claude to pull context itself using Bash commands, MCP tools, or by reading files.
​
Configure your environment
A few setup steps make Claude Code significantly more effective across all your sessions. For a full overview of extension features and when to use each one, see
Extend Claude Code
.
​
Write an effective CLAUDE.md
Run
/init
to generate a starter CLAUDE.md file based on your current project structure, then refine over time.
CLAUDE.md is a special file that Claude reads at the start of every conversation. Include Bash commands, code style, and workflow rules. This gives Claude persistent context it can’t infer from code alone.
The
/init
command analyzes your codebase to detect build systems, test frameworks, and code patterns, giving you a solid foundation to refine.
There’s no required format for CLAUDE.md files, but keep it short and human-readable. For example:
CLAUDE.md
# Code style
-
Use ES modules (import/export) syntax, not CommonJS (require)
-
Destructure imports when possible (eg. import { foo } from 'bar')
# Workflow
-
Be sure to typecheck when you're done making a series of code changes
-
Prefer running single tests, and not the whole test suite, for performance
CLAUDE.md is loaded every session, so only include things that apply broadly. For domain knowledge or workflows that are only relevant sometimes, use
skills
instead. Claude loads them on demand without bloating every conversation.
Keep it concise. For each line, ask:
“Would removing this cause Claude to make mistakes?”
If not, cut it. Bloated CLAUDE.md files cause Claude to ignore your actual instructions!
✅ Include
❌ Exclude
Bash commands Claude can’t guess
Anything Claude can figure out by reading code
Code style rules that differ from defaults
Standard language conventions Claude already knows
Testing instructions and preferred test runners
Detailed API documentation (link to docs instead)
Repository etiquette (branch naming, PR conventions)
Information that changes frequently
Architectural decisions specific to your project
Long explanations or tutorials
Developer environment quirks (required env vars)
File-by-file descriptions of the codebase
Common gotchas or non-obvious behaviors
Self-evident practices like “write clean code”
If Claude keeps doing something you don’t want despite having a rule against it, the file is probably too long and the rule is getting lost. If Claude asks you questions that are answered in CLAUDE.md, the phrasing might be ambiguous. Treat CLAUDE.md like code: review it when things go wrong, prune it regularly, and test changes by observing whether Claude’s behavior actually shifts.
You can tune instructions by adding emphasis (e.g., “IMPORTANT” or “YOU MUST”) to improve adherence. Check CLAUDE.md into git so your team can contribute. The file compounds in value over time.
CLAUDE.md files can import additional files using
@path/to/import
syntax:
CLAUDE.md
See @README.md for project overview and @package.json for available npm commands.
# Additional Instructions
-
Git workflow: @docs/git-instructions.md
-
Personal overrides: @~/.claude/my-project-instructions.md
You can place CLAUDE.md files in several locations:
Home folder (
~/.claude/CLAUDE.md
)
: applies to all Claude sessions
Project root (
./CLAUDE.md
)
: check into git to share with your team
Project root (
./CLAUDE.local.md
)
: personal project-specific notes; add this file to your
.gitignore
so it isn’t shared with your team
Parent directories
: useful for monorepos where both
root/CLAUDE.md
and
root/foo/CLAUDE.md
are pulled in automatically
Child directories
: Claude pulls in child CLAUDE.md files on demand when working with files in those directories
​
Configure permissions
Use
auto mode
to let a classifier handle approvals,
/permissions
to allowlist specific commands, or
/sandbox
for OS-level isolation. Each reduces interruptions while keeping you in control.
By default, Claude Code requests permission for actions that might modify your system: file writes, Bash commands, MCP tools, etc. This is safe but tedious. After the tenth approval you’re not really reviewing anymore, you’re just clicking through. There are three ways to reduce these interruptions:
Auto mode
: a separate classifier model reviews commands and blocks only what looks risky: scope escalation, unknown infrastructure, or hostile-content-driven actions. Best when you trust the general direction of a task but don’t want to click through every step
Permission allowlists
: permit specific tools you know are safe, like
npm run lint
or
git commit
Sandboxing
: enable OS-level isolation that restricts filesystem and network access, allowing Claude to work more freely within defined boundaries
Read more about
permission modes
,
permission rules
, and
sandboxing
.
​
Use CLI tools
Tell Claude Code to use CLI tools like
gh
,
aws
,
gcloud
, and
sentry-cli
when interacting with external services.
CLI tools are the most context-efficient way to interact with external services. If you use GitHub, install the
gh
CLI. Claude knows how to use it for creating issues, opening pull requests, and reading comments. Without
gh
, Claude can still use the GitHub API, but unauthenticated requests often hit rate limits.
Claude is also effective at learning CLI tools it doesn’t already know. Try prompts like
Use 'foo-cli-tool --help' to learn about foo tool, then use it to solve A, B, C.
​
Connect MCP servers
Run
claude mcp add
to connect external tools like Notion, Figma, or your database.
With
MCP servers
, you can ask Claude to implement features from issue trackers, query databases, analyze monitoring data, integrate designs from Figma, and automate workflows.
​
Set up hooks
Use hooks for actions that must happen every time with zero exceptions.
Hooks
run scripts automatically at specific points in Claude’s workflow. Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens.
Claude can write hooks for you. Try prompts like
“Write a hook that runs eslint after every file edit”
or
“Write a hook that blocks writes to the migrations folder.”
Edit
.claude/settings.json
directly to configure hooks by hand, and run
/hooks
to browse what’s configured.
​
Create skills
Create
SKILL.md
files in
.claude/skills/
to give Claude domain knowledge and reusable workflows.
Skills
extend Claude’s knowledge with information specific to your project, team, or domain. Claude applies them automatically when relevant, or you can invoke them directly with
/skill-name
.
Create a skill by adding a directory with a
SKILL.md
to
.claude/skills/
:
.claude/skills/api-conventions/SKILL.md
---
name
:
api-conventions
description
:
REST API design conventions for our services
---
# API Conventions
-
Use kebab-case for URL paths
-
Use camelCase for JSON properties
-
Always include pagination for list endpoints
-
Version APIs in the URL path (/v1/, /v2/)
Skills can also define repeatable workflows you invoke directly:
.claude/skills/fix-issue/SKILL.md
---
name
:
fix-issue
description
:
Fix a GitHub issue
disable-model-invocation
:
true
---
Analyze and fix the GitHub issue: $ARGUMENTS.
1.
Use
`gh issue view`
to get the issue details
2.
Understand the problem described in the issue
3.
Search the codebase for relevant files
4.
Implement the necessary changes to fix the issue
5.
Write and run tests to verify the fix
6.
Ensure code passes linting and type checking
7.
Create a descriptive commit message
8.
Push and create a PR
Run
/fix-issue 1234
to invoke it. Use
disable-model-invocation: true
for workflows with side effects that you want to trigger manually.
​
Create custom subagents
Define specialized assistants in
.claude/agents/
that Claude can delegate to for isolated tasks.
Subagents
run in their own context with their own set of allowed tools. They’re useful for tasks that read many files or need specialized focus without cluttering your main conversation.
.claude/agents/security-reviewer.md
---
name
:
security-reviewer
description
:
Reviews code for security vulnerabilities
tools
:
Read, Grep, Glob, Bash
model
:
opus
---
You are a senior security engineer. Review code for:
-
Injection vulnerabilities (SQL, XSS, command injection)
-
Authentication and authorization flaws
-
Secrets or credentials in code
-
Insecure data handling
Provide specific line references and suggested fixes.
Tell Claude to use subagents explicitly:
“Use a subagent to review this code for security issues.”
​
Install plugins
Run
/plugin
to browse the marketplace. Plugins add skills, tools, and integrations without configuration.
Plugins
bundle skills, hooks, subagents, and MCP servers into a single installable unit from the community and Anthropic. If you work with a typed language, install a
code intelligence plugin
to give Claude precise symbol navigation and automatic error detection after edits.
For guidance on choosing between skills, subagents, hooks, and MCP, see
Extend Claude Code
.
​
Communicate effectively
The way you communicate with Claude Code significantly impacts the quality of results.
​
Ask codebase questions
Ask Claude questions you’d ask a senior engineer.
When onboarding to a new codebase, use Claude Code for learning and exploration. You can ask Claude the same sorts of questions you would ask another engineer:
How does logging work?
How do I make a new API endpoint?
What does
async move { ... }
do on line 134 of
foo.rs
?
What edge cases does
CustomerOnboardingFlowImpl
handle?
Why does this code call
foo()
instead of
bar()
on line 333?
Using Claude Code this way is an effective onboarding workflow, improving ramp-up time and reducing load on other engineers. No special prompting required: ask questions directly.
​
Let Claude interview you
For larger features, have Claude interview you first. Start with a minimal prompt and ask Claude to interview you using the
AskUserQuestion
tool.
Claude asks about things you might not have considered yet, including technical implementation, UI/UX, edge cases, and tradeoffs.
I want to build [brief description]. Interview me in detail using the AskUserQuestion tool.
Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs. Don't ask obvious questions, dig into the hard parts I might not have considered.
Keep interviewing until we've covered everything, then write a complete spec to SPEC.md.
Once the spec is complete, start a fresh session to execute it. The new session has clean context focused entirely on implementation, and you have a written spec to reference.
​
Manage your session
Conversations are persistent and reversible. Use this to your advantage!
​
Course-correct early and often
Correct Claude as soon as you notice it going off track.
The best results come from tight feedback loops. Though Claude occasionally solves problems perfectly on the first attempt, correcting it quickly generally produces better solutions faster.
Esc
: stop Claude mid-action with the
Esc
key. Context is preserved, so you can redirect.
Esc + Esc
or
/rewind
: press
Esc
twice or run
/rewind
to open the rewind menu and restore previous conversation and code state, or summarize from a selected message.
"Undo that"
: have Claude revert its changes.
/clear
: reset context between unrelated tasks. Long sessions with irrelevant context can reduce performance.
If you’ve corrected Claude more than twice on the same issue in one session, the context is cluttered with failed approaches. Run
/clear
and start fresh with a more specific prompt that incorporates what you learned. A clean session with a better prompt almost always outperforms a long session with accumulated corrections.
​
Manage context aggressively
Run
/clear
between unrelated tasks to reset context.
Claude Code automatically compacts conversation history when you approach context limits, which preserves important code and decisions while freeing space.
During long sessions, Claude’s context window can fill with irrelevant conversation, file contents, and commands. This can reduce performance and sometimes distract Claude.
Use
/clear
frequently between tasks to reset the context window entirely
When auto compaction triggers, Claude summarizes what matters most, including code patterns, file states, and key decisions
For more control, run
/compact <instructions>
, like
/compact Focus on the API changes
To compact only part of the conversation, use
Esc + Esc
or
/rewind
, select a message checkpoint, and choose
Summarize from here
or
Summarize up to here
. The first condenses messages from that point forward while keeping earlier context intact; the second condenses earlier messages while keeping recent ones in full. See
Restore vs. summarize
.
Customize compaction behavior in CLAUDE.md with instructions like
"When compacting, always preserve the full list of modified files and any test commands"
to ensure critical context survives summarization
For quick questions that don’t need to stay in context, use
/btw
. The answer appears in a dismissible overlay and never enters conversation history, so you can check a detail without growing context.
​
Use subagents for investigation
Delegate research with
"use subagents to investigate X"
. They explore in a separate context, keeping your main conversation clean for implementation.
Since context is your fundamental constraint, subagents are one of the most powerful tools available. When Claude researches a codebase it reads lots of files, all of which consume your context. Subagents run in separate context windows and report back summaries:
Use subagents to investigate how our authentication system handles token
refresh, and whether we have any existing OAuth utilities I should reuse.
The subagent explores the codebase, reads relevant files, and reports back with findings, all without cluttering your main conversation.
You can also use subagents for verification after Claude implements something:
use a subagent to review this code for edge cases
​
Rewind with checkpoints
Every prompt you send creates a checkpoint. You can restore conversation, code, or both to any previous checkpoint.
Claude automatically snapshots files before each change so a checkpoint can restore them. Double-tap
Escape
or run
/rewind
to open the rewind menu. You can restore conversation only, restore code only, restore both, or summarize from a selected message. See
Checkpointing
for details.
Instead of carefully planning every move, you can tell Claude to try something risky. If it doesn’t work, rewind and try a different approach. Checkpoints persist across sessions, so you can close your terminal and still rewind later.
Checkpoints only track changes made
by Claude
, not external processes. This isn’t a replacement for git.
​
Resume conversations
Name sessions with
/rename
and treat them like branches: each workstream gets its own persistent context.
Claude Code saves conversations locally, so when a task spans multiple sittings you don’t have to re-explain the context. Run
claude --continue
to pick up the most recent session, or
claude --resume
to choose from a list. Give sessions descriptive names like
oauth-migration
so you can find them later. See
Manage sessions
for the full set of resume, branch, and naming controls.
​
Automate and scale
Once you’re effective with one Claude, multiply your output with parallel sessions, non-interactive mode, and fan-out patterns.
Everything so far assumes one human, one Claude, and one conversation. But Claude Code scales horizontally. The techniques in this section show how you can get more done.
​
Run non-interactive mode
Use
claude -p "prompt"
in CI, pre-commit hooks, or scripts. Add
--output-format stream-json
for streaming JSON output.
With
claude -p "your prompt"
, you can run Claude non-interactively, without a session.
Non-interactive mode
is how you integrate Claude into CI pipelines, pre-commit hooks, or any automated workflow. The output formats let you parse results programmatically: plain text, JSON, or streaming JSON.
# One-off queries
claude
-p
"Explain what this project does"
# Structured output for scripts
claude
-p
"List all API endpoints"
--output-format
json
# Streaming for real-time processing
claude
-p
"Analyze this log file"
--output-format
stream-json
​
Run multiple Claude sessions
Run multiple Claude sessions in parallel to speed up development, run isolated experiments, or start complex workflows.
Pick the parallel approach that fits how much coordination you want to do yourself:
Worktrees
: run separate CLI sessions in isolated git checkouts so edits don’t collide
Desktop app
: manage multiple local sessions visually, each in its own worktree
Claude Code on the web
: run sessions on Anthropic-managed cloud infrastructure in isolated VMs
Agent teams
: automated coordination of multiple sessions with shared tasks, messaging, and a team lead
Beyond parallelizing work, multiple sessions enable quality-focused workflows. A fresh context improves code review since Claude won’t be biased toward code it just wrote.
For example, use a Writer/Reviewer pattern:
Session A (Writer)
Session B (Reviewer)
Implement a rate limiter for our API endpoints
Review the rate limiter implementation in @src/middleware/rateLimiter.ts. Look for edge cases, race conditions, and consistency with our existing middleware patterns.
Here's the review feedback: [Session B output]. Address these issues.
You can do something similar with tests: have one Claude write tests, then another write code to pass them.
​
Fan out across files
Loop through tasks calling
claude -p
for each. Use
--allowedTools
to scope permissions for batch operations.
For large migrations or analyses, you can distribute work across many parallel Claude invocations:
1
Generate a task list
Have Claude list all files that need migrating (e.g.,
list all 2,000 Python files that need migrating
)
2
Write a script to loop through the list
for
file
in
$(
cat
files.txt
);
do
claude
-p
"Migrate
$file
from React to Vue. Return OK or FAIL."
\
--allowedTools
"Edit,Bash(git commit *)"
done
3
Test on a few files, then run at scale
Refine your prompt based on what goes wrong with the first 2-3 files, then run on the full set. The
--allowedTools
flag restricts what Claude can do, which matters when you’re running unattended.
You can also integrate Claude into existing data/processing pipelines:
claude
-p
"<your prompt>"
--output-format
json
|
your_command
Use
--verbose
for debugging during development, and turn it off in production.
​
Run autonomously with auto mode
For uninterrupted execution with background safety checks, use
auto mode
. A classifier model reviews commands before they run, blocking scope escalation, unknown infrastructure, and hostile-content-driven actions while letting routine work proceed without prompts.
claude
--permission-mode
auto
-p
"fix all lint errors"
For non-interactive runs with the
-p
flag, auto mode aborts if the classifier repeatedly blocks actions, since there is no user to fall back to. See
when auto mode falls back
for thresholds.
​
Avoid common failure patterns
These are common mistakes. Recognizing them early saves time:
The kitchen sink session.
You start with one task, then ask Claude something unrelated, then go back to the first task. Context is full of irrelevant information.
Fix
:
/clear
between unrelated tasks.
Correcting over and over.
Claude does something wrong, you correct it, it’s still wrong, you correct again. Context is polluted with failed approaches.
Fix
: After two failed corrections,
/clear
and write a better initial prompt incorporating what you learned.
The over-specified CLAUDE.md.
If your CLAUDE.md is too long, Claude ignores half of it because important rules get lost in the noise.
Fix
: Ruthlessly prune. If Claude already does something correctly without the instruction, delete it or convert it to a hook.
The trust-then-verify gap.
Claude produces a plausible-looking implementation that doesn’t handle edge cases.
Fix
: Always provide verification (tests, scripts, screenshots). If you can’t verify it, don’t ship it.
The infinite exploration.
You ask Claude to “investigate” something without scoping it. Claude reads hundreds of files, filling the context.
Fix
: Scope investigations narrowly or use subagents so the exploration doesn’t consume your main context.
​
Develop your intuition
The patterns in this guide aren’t set in stone. They’re starting points that work well in general, but might not be optimal for every situation.
Sometimes you
should
let context accumulate because you’re deep in one complex problem and the history is valuable. Sometimes you should skip planning and let Claude figure it out because the task is exploratory. Sometimes a vague prompt is exactly right because you want to see how Claude interprets the problem before constraining it.
Pay attention to what works. When Claude produces great output, notice what you did: the prompt structure, the context you provided, the mode you were in. When Claude struggles, ask why. Was the context too noisy? The prompt too vague? The task too big for one pass?
Over time, you’ll develop intuition that no guide can capture. You’ll know when to be specific and when to be open-ended, when to plan and when to explore, when to clear context and when to let it accumulate.
​
Related resources
How Claude Code works
: the agentic loop, tools, and context management
Extend Claude Code
: skills, hooks, MCP, subagents, and plugins
Common workflows
: step-by-step recipes for debugging, testing, PRs, and more
CLAUDE.md
: store project conventions and persistent context
Was this page helpful?
Yes
No
Common workflows
Overview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/best-practices" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Agent Skills in the SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/skills</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/skills</guid>
  <pubDate>Sat, 13 Jul 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Agent Skills in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Agent Skills in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
Agent Skills extend Claude with specialized capabilities that Claude autonomously invokes when relevant. Skills are packaged as
SKILL.md
files containing instructions, descriptions, and optional supporting resources.
For comprehensive information about Skills, including benefits, architecture, and authoring guidelines, see the
Agent Skills overview
.
​
How Skills Work with the SDK
When using the Claude Agent SDK, Skills are:
Defined as filesystem artifacts
: Created as
SKILL.md
files in specific directories (
.claude/skills/
)
Loaded from filesystem
: Skills are loaded from filesystem locations governed by
settingSources
(TypeScript) or
setting_sources
(Python)
Automatically discovered
: Once filesystem settings are loaded, Skill metadata is discovered at startup from user and project directories; full content loaded when triggered
Model-invoked
: Claude autonomously chooses when to use them based on context
Filtered via the
skills
option
: Discovered skills are enabled by default. Pass a list of skill names,
"all"
, or
[]
to control which are available in the session
Unlike subagents (which can be defined programmatically), Skills must be created as filesystem artifacts. The SDK does not provide a programmatic API for registering Skills.
Skills are discovered through the filesystem setting sources. With default
query()
options, the SDK loads user and project sources, so skills in
~/.claude/skills/
,
<cwd>/.claude/skills/
, and
.claude/skills/
in any parent directory of
<cwd>
up to the repository root are available. If you set
settingSources
explicitly, include
'user'
or
'project'
to keep skill discovery, or use the
plugins
option
to load skills from a specific path.
​
Using Skills with the SDK
Set the
skills
option on
query()
to control which Skills are available to the session. When omitted, discovered Skills are enabled and the Skill tool is available, matching CLI behavior. Pass
"all"
to enable every discovered Skill, a list of Skill names to enable only those, or
[]
to disable all. When you set
skills
, the SDK enables the Skill tool automatically, so you do not need to list it in
allowedTools
.
Once configured, Claude automatically discovers Skills from the filesystem and invokes them when relevant to the user’s request.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
# Project with .claude/skills/
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
# Enable every discovered Skill
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
)
async
for
message
in
query(
prompt
=
"Help me process this PDF document"
,
options
=
options
):
print
(message)
asyncio.run(main())
To enable only specific Skills, pass their names. Names match the
name
field in
SKILL.md
or the Skill’s directory name. Use
plugin:skill
for plugin-provided Skills.
Python
TypeScript
options
=
ClaudeAgentOptions(
skills
=
[
"pdf"
,
"docx"
])
The
skills
option is a context filter, not a sandbox. Unlisted Skills are hidden from the model and rejected by the Skill tool, but their files remain on disk and are reachable through Read and Bash.
​
Skill Locations
Skills are loaded from filesystem directories based on your
settingSources
/
setting_sources
configuration:
Project Skills
(
.claude/skills/
): Shared with your team via git - loaded when
setting_sources
includes
"project"
User Skills
(
~/.claude/skills/
): Personal Skills across all projects - loaded when
setting_sources
includes
"user"
Plugin Skills
: Bundled with installed Claude Code plugins
​
Creating Skills
Skills are defined as directories containing a
SKILL.md
file with YAML frontmatter and Markdown content. The
description
field determines when Claude invokes your Skill.
Example directory structure
:
.claude/skills/processing-pdfs/
└──
SKILL.md
For complete guidance on creating Skills, including SKILL.md structure, multi-file Skills, and examples, see:
Agent Skills in Claude Code
: Complete guide with examples
Agent Skills Best Practices
: Authoring guidelines and naming conventions
​
Tool Restrictions
The
allowed-tools
frontmatter field in SKILL.md is only supported when using Claude Code CLI directly.
It does not apply when using Skills through the SDK
.
When using the SDK, control tool access through the main
allowedTools
option in your query configuration.
To control tool access for Skills in SDK applications, use
allowedTools
to pre-approve specific tools. Without a
canUseTool
callback, anything not in the list is denied:
Import statements from the first example are assumed in the following code snippets.
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
)
async
for
message
in
query(
prompt
=
"Analyze the codebase structure"
,
options
=
options):
print
(message)
​
Discovering Available Skills
To see which Skills are available in your SDK application, simply ask Claude:
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
)
async
for
message
in
query(
prompt
=
"What Skills are available?"
,
options
=
options):
print
(message)
Claude will list the available Skills based on your current working directory and installed plugins.
​
Testing Skills
Test Skills by asking questions that match their descriptions:
Python
TypeScript
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Bash"
],
)
async
for
message
in
query(
prompt
=
"Extract text from invoice.pdf"
,
options
=
options):
print
(message)
Claude automatically invokes the relevant Skill if the description matches your request.
​
Troubleshooting
​
Skills Not Found
Check settingSources configuration
: Skills are discovered through the
user
and
project
setting sources. If you set
settingSources
/
setting_sources
explicitly and omit those sources, skills are not loaded:
Python
TypeScript
# Skills not loaded: setting_sources excludes user and project
options
=
ClaudeAgentOptions(
setting_sources
=
[],
skills
=
"all"
)
# Skills loaded: user and project sources included
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
skills
=
"all"
,
)
For more details on
settingSources
/
setting_sources
, see the
TypeScript SDK reference
or
Python SDK reference
.
Check working directory
: The SDK loads Skills from
.claude/skills/
in the
cwd
option and in every parent directory up to the repository root. Ensure
cwd
points at or below the directory containing
.claude/skills/
, within the same repository:
Python
TypeScript
# Ensure your cwd points to the directory containing .claude/skills/
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
# .claude/skills/ here or in a parent directory
setting_sources
=
[
"user"
,
"project"
],
# Loads skills from these sources
skills
=
"all"
,
)
See the “Using Skills with the SDK” section above for the complete pattern.
Verify filesystem location
:
# Check project Skills
ls
.claude/skills/
*
/SKILL.md
# Check personal Skills
ls
~/.claude/skills/
*
/SKILL.md
​
Skill Not Being Used
Check the
skills
option
: If you passed a
skills
list, confirm the skill’s name is included. Passing
[]
disables all skills.
Check the description
: Ensure it’s specific and includes relevant keywords. See
Agent Skills Best Practices
for guidance on writing effective descriptions.
​
Additional Troubleshooting
For general Skills troubleshooting (YAML syntax, debugging, etc.), see the
Claude Code Skills troubleshooting section
.
​
Related Documentation
​
Skills Guides
Agent Skills in Claude Code
: Complete Skills guide with creation, examples, and troubleshooting
Agent Skills Overview
: Conceptual overview, benefits, and architecture
Agent Skills Best Practices
: Authoring guidelines for effective Skills
Agent Skills Cookbook
: Example Skills and templates
​
SDK Resources
Subagents in the SDK
: Similar filesystem-based agents with programmatic options
Slash Commands in the SDK
: User-invoked commands
SDK Overview
: General SDK concepts
TypeScript SDK Reference
: Complete API documentation
Python SDK Reference
: Complete API documentation
Was this page helpful?
Yes
No
Slash Commands in the SDK
Plugins in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/skills" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Agent Skills in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Agent Skills in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
Agent Skills extend Claude with specialized capabilities that Claude autonomously invokes when relevant. Skills are packaged as
SKILL.md
files containing instructions, descriptions, and optional supporting resources.
For comprehensive information about Skills, including benefits, architecture, and authoring guidelines, see the
Agent Skills overview
.
​
How Skills Work with the SDK
When using the Claude Agent SDK, Skills are:
Defined as filesystem artifacts
: Created as
SKILL.md
files in specific directories (
.claude/skills/
)
Loaded from filesystem
: Skills are loaded from filesystem locations governed by
settingSources
(TypeScript) or
setting_sources
(Python)
Automatically discovered
: Once filesystem settings are loaded, Skill metadata is discovered at startup from user and project directories; full content loaded when triggered
Model-invoked
: Claude autonomously chooses when to use them based on context
Filtered via the
skills
option
: Discovered skills are enabled by default. Pass a list of skill names,
"all"
, or
[]
to control which are available in the session
Unlike subagents (which can be defined programmatically), Skills must be created as filesystem artifacts. The SDK does not provide a programmatic API for registering Skills.
Skills are discovered through the filesystem setting sources. With default
query()
options, the SDK loads user and project sources, so skills in
~/.claude/skills/
,
<cwd>/.claude/skills/
, and
.claude/skills/
in any parent directory of
<cwd>
up to the repository root are available. If you set
settingSources
explicitly, include
'user'
or
'project'
to keep skill discovery, or use the
plugins
option
to load skills from a specific path.
​
Using Skills with the SDK
Set the
skills
option on
query()
to control which Skills are available to the session. When omitted, discovered Skills are enabled and the Skill tool is available, matching CLI behavior. Pass
"all"
to enable every discovered Skill, a list of Skill names to enable only those, or
[]
to disable all. When you set
skills
, the SDK enables the Skill tool automatically, so you do not need to list it in
allowedTools
.
Once configured, Claude automatically discovers Skills from the filesystem and invokes them when relevant to the user’s request.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
# Project with .claude/skills/
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
# Enable every discovered Skill
allowed_tools
=
[
"Read"
,
"Write"
,
"Bash"
],
)
async
for
message
in
query(
prompt
=
"Help me process this PDF document"
,
options
=
options
):
print
(message)
asyncio.run(main())
To enable only specific Skills, pass their names. Names match the
name
field in
SKILL.md
or the Skill’s directory name. Use
plugin:skill
for plugin-provided Skills.
Python
TypeScript
options
=
ClaudeAgentOptions(
skills
=
[
"pdf"
,
"docx"
])
The
skills
option is a context filter, not a sandbox. Unlisted Skills are hidden from the model and rejected by the Skill tool, but their files remain on disk and are reachable through Read and Bash.
​
Skill Locations
Skills are loaded from filesystem directories based on your
settingSources
/
setting_sources
configuration:
Project Skills
(
.claude/skills/
): Shared with your team via git - loaded when
setting_sources
includes
"project"
User Skills
(
~/.claude/skills/
): Personal Skills across all projects - loaded when
setting_sources
includes
"user"
Plugin Skills
: Bundled with installed Claude Code plugins
​
Creating Skills
Skills are defined as directories containing a
SKILL.md
file with YAML frontmatter and Markdown content. The
description
field determines when Claude invokes your Skill.
Example directory structure
:
.claude/skills/processing-pdfs/
└──
SKILL.md
For complete guidance on creating Skills, including SKILL.md structure, multi-file Skills, and examples, see:
Agent Skills in Claude Code
: Complete guide with examples
Agent Skills Best Practices
: Authoring guidelines and naming conventions
​
Tool Restrictions
The
allowed-tools
frontmatter field in SKILL.md is only supported when using Claude Code CLI directly.
It does not apply when using Skills through the SDK
.
When using the SDK, control tool access through the main
allowedTools
option in your query configuration.
To control tool access for Skills in SDK applications, use
allowedTools
to pre-approve specific tools. Without a
canUseTool
callback, anything not in the list is denied:
Import statements from the first example are assumed in the following code snippets.
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
)
async
for
message
in
query(
prompt
=
"Analyze the codebase structure"
,
options
=
options):
print
(message)
​
Discovering Available Skills
To see which Skills are available in your SDK application, simply ask Claude:
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
)
async
for
message
in
query(
prompt
=
"What Skills are available?"
,
options
=
options):
print
(message)
Claude will list the available Skills based on your current working directory and installed plugins.
​
Testing Skills
Test Skills by asking questions that match their descriptions:
Python
TypeScript
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
setting_sources
=
[
"user"
,
"project"
],
# Load Skills from filesystem
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Bash"
],
)
async
for
message
in
query(
prompt
=
"Extract text from invoice.pdf"
,
options
=
options):
print
(message)
Claude automatically invokes the relevant Skill if the description matches your request.
​
Troubleshooting
​
Skills Not Found
Check settingSources configuration
: Skills are discovered through the
user
and
project
setting sources. If you set
settingSources
/
setting_sources
explicitly and omit those sources, skills are not loaded:
Python
TypeScript
# Skills not loaded: setting_sources excludes user and project
options
=
ClaudeAgentOptions(
setting_sources
=
[],
skills
=
"all"
)
# Skills loaded: user and project sources included
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
skills
=
"all"
,
)
For more details on
settingSources
/
setting_sources
, see the
TypeScript SDK reference
or
Python SDK reference
.
Check working directory
: The SDK loads Skills from
.claude/skills/
in the
cwd
option and in every parent directory up to the repository root. Ensure
cwd
points at or below the directory containing
.claude/skills/
, within the same repository:
Python
TypeScript
# Ensure your cwd points to the directory containing .claude/skills/
options
=
ClaudeAgentOptions(
cwd
=
"/path/to/project"
,
# .claude/skills/ here or in a parent directory
setting_sources
=
[
"user"
,
"project"
],
# Loads skills from these sources
skills
=
"all"
,
)
See the “Using Skills with the SDK” section above for the complete pattern.
Verify filesystem location
:
# Check project Skills
ls
.claude/skills/
*
/SKILL.md
# Check personal Skills
ls
~/.claude/skills/
*
/SKILL.md
​
Skill Not Being Used
Check the
skills
option
: If you passed a
skills
list, confirm the skill’s name is included. Passing
[]
disables all skills.
Check the description
: Ensure it’s specific and includes relevant keywords. See
Agent Skills Best Practices
for guidance on writing effective descriptions.
​
Additional Troubleshooting
For general Skills troubleshooting (YAML syntax, debugging, etc.), see the
Claude Code Skills troubleshooting section
.
​
Related Documentation
​
Skills Guides
Agent Skills in Claude Code
: Complete Skills guide with creation, examples, and troubleshooting
Agent Skills Overview
: Conceptual overview, benefits, and architecture
Agent Skills Best Practices
: Authoring guidelines for effective Skills
Agent Skills Cookbook
: Example Skills and templates
​
SDK Resources
Subagents in the SDK
: Similar filesystem-based agents with programmatic options
Slash Commands in the SDK
: User-invoked commands
SDK Overview
: General SDK concepts
TypeScript SDK Reference
: Complete API documentation
Python SDK Reference
: Complete API documentation
Was this page helpful?
Yes
No
Slash Commands in the SDK
Plugins in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/skills" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Channels reference</title>
  <link>https://code.claude.com/docs/en/channels-reference</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/channels-reference</guid>
  <pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate>
  <category>Reference</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Channels reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Channels reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require Claude Code v2.1.80 or later. Team and Enterprise organizations must
explicitly enable them
.
A channel is an MCP server that pushes events into a Claude Code session so Claude can react to things happening outside the terminal.
You can build a one-way or two-way channel. One-way channels forward alerts, webhooks, or monitoring events for Claude to act on. Two-way channels like chat bridges also
expose a reply tool
so Claude can send messages back. A channel with a trusted sender path can also opt in to
relay permission prompts
so you can approve or deny tool use remotely.
This page covers:
Overview
: how channels work
What you need
: requirements and general steps
Example: build a webhook receiver
: a minimal one-way walkthrough
Server options
: the constructor fields
Notification format
: the event payload and delivery behavior
Expose a reply tool
: let Claude send messages back
Gate inbound messages
: sender checks to prevent prompt injection
Relay permission prompts
: forward tool approval prompts to remote channels
To use an existing channel instead of building one, see
Channels
. Telegram, Discord, iMessage, and fakechat are included in the research preview.
​
Overview
A channel is an
MCP
server that runs on the same machine as Claude Code. Claude Code spawns it as a subprocess and communicates over stdio. Your channel server is the bridge between external systems and the Claude Code session:
Chat platforms
(Telegram, Discord): your plugin runs locally and polls the platform’s API for new messages. When someone DMs your bot, the plugin receives the message and forwards it to Claude. No URL to expose.
Webhooks
(CI, monitoring): your server listens on a local HTTP port. External systems POST to that port, and your server pushes the payload to Claude.
​
What you need
The only hard requirement is the
@modelcontextprotocol/sdk
package and a Node.js-compatible runtime.
Bun
,
Node
, and
Deno
all work. The pre-built plugins in the research preview use Bun, but your channel doesn’t have to.
Your server needs to:
Declare the
claude/channel
capability so Claude Code registers a notification listener
Emit
notifications/claude/channel
events when something happens
Connect over
stdio transport
(Claude Code spawns your server as a subprocess)
The
Server options
and
Notification format
sections cover each of these in detail. See
Example: build a webhook receiver
for a full walkthrough.
During the research preview, custom channels aren’t on the
approved allowlist
. Use
--dangerously-load-development-channels
to test locally. See
Test during the research preview
for details.
​
Example: build a webhook receiver
This walkthrough builds a single-file server that listens for HTTP requests and forwards them into your Claude Code session. By the end, anything that can send an HTTP POST, like a CI pipeline, a monitoring alert, or a
curl
command, can push events to Claude.
This example uses
Bun
as the runtime for its built-in HTTP server and TypeScript support. You can use
Node
or
Deno
instead; the only requirement is the
MCP SDK
.
1
Create the project
Create a new directory and install the MCP SDK:
mkdir
webhook-channel
&&
cd
webhook-channel
bun
add
@modelcontextprotocol/sdk
2
Write the channel server
Create a file called
webhook.ts
. This is your entire channel server: it connects to Claude Code over stdio, and it listens for HTTP POSTs on port 8788. When a request arrives, it pushes the body to Claude as a channel event.
webhook.ts
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
// Create the MCP server and declare it as a channel
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
// this key is what makes it a channel — Claude Code registers a listener for it
capabilities:
{
experimental:
{
'claude/channel'
:
{} } },
// added to Claude's system prompt so it knows how to handle these events
instructions:
'Events from the webhook channel arrive as <channel source="webhook" ...>. They are one-way: read them and act, no reply expected.'
,
},
)
// Connect to Claude Code over stdio (Claude Code spawns this process)
await
mcp
.
connect
(
new
StdioServerTransport
())
// Start an HTTP server that forwards every POST to Claude
Bun
.
serve
({
port:
8788
,
// any open port works
// localhost-only: nothing outside this machine can POST
hostname:
'127.0.0.1'
,
async
fetch
(
req
) {
const
body
=
await
req
.
text
()
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
// becomes the body of the <channel> tag
// each key becomes a tag attribute, e.g. <channel path="/" method="POST">
meta:
{
path:
new
URL
(
req
.
url
).
pathname
,
method:
req
.
method
},
},
})
return
new
Response
(
'ok'
)
},
})
The file does three things in order:
Server configuration
: creates the MCP server with
claude/channel
in its capabilities, which is what tells Claude Code this is a channel. The
instructions
string goes into Claude’s system prompt: tell Claude what events to expect, whether to reply, and how to route replies if it should.
Stdio connection
: connects to Claude Code over stdin/stdout. This is standard for any
MCP server
: Claude Code spawns it as a subprocess.
HTTP listener
: starts a local web server on port 8788. Every POST body gets forwarded to Claude as a channel event via
mcp.notification()
. The
content
becomes the event body, and each
meta
entry becomes an attribute on the
<channel>
tag. The listener needs access to the
mcp
instance, so it runs in the same process. You could split it into separate modules for a larger project.
3
Register your server with Claude Code
Add the server to your MCP config so Claude Code knows how to start it. For a project-level
.mcp.json
in the same directory, use a relative path. For user-level config in
~/.claude.json
, use the full absolute path so the server can be found from any project:
.mcp.json
{
"mcpServers"
: {
"webhook"
: {
"command"
:
"bun"
,
"args"
: [
"./webhook.ts"
] }
}
}
Claude Code reads your MCP config at startup and spawns each server as a subprocess.
4
Test it
During the research preview, custom channels aren’t on the allowlist, so start Claude Code with the development flag:
claude
--dangerously-load-development-channels
server:webhook
When Claude Code starts, it reads your MCP config, spawns your
webhook.ts
as a subprocess, and the HTTP listener starts automatically on the port you configured (8788 in this example). You don’t need to run the server yourself.
If you see “blocked by org policy,” your organization admin needs to
enable channels
first.
In a separate terminal, simulate a webhook by sending an HTTP POST with a message to your server. This example sends a CI failure alert to port 8788 (or whichever port you configured):
curl
-X
POST
localhost:8788
-d
"build failed on main: https://ci.example.com/run/1234"
The payload arrives in your Claude Code session as a
<channel>
tag:
<channel source="webhook" path="/" method="POST">build failed on main: https://ci.example.com/run/1234</channel>
In your Claude Code terminal, you’ll see Claude receive the message and start responding: reading files, running commands, or whatever the message calls for. This is a one-way channel, so Claude acts in your session but doesn’t send anything back through the webhook. To add replies, see
Expose a reply tool
.
If the event doesn’t arrive, the diagnosis depends on what
curl
returned:
curl
succeeds but nothing reaches Claude
: run
/mcp
in your session to check the server’s status. “Failed to connect” usually means a dependency or import error in your server file; check the debug log at
~/.claude/debug/<session-id>.txt
for the stderr trace.
curl
fails with “connection refused”
: the port is either not bound yet or a stale process from an earlier run is holding it.
lsof -i :<port>
shows what’s listening;
kill
the stale process before restarting your session.
The
fakechat server
extends this pattern with a web UI, file attachments, and a reply tool for two-way chat.
​
Test during the research preview
During the research preview, every channel must be on the
approved allowlist
to register. The development flag bypasses the allowlist for specific entries after a confirmation prompt. This example shows both entry types:
# Testing a plugin you're developing
claude
--dangerously-load-development-channels
plugin:yourplugin@yourmarketplace
# Testing a bare .mcp.json server (no plugin wrapper yet)
claude
--dangerously-load-development-channels
server:webhook
The bypass is per-entry. Combining this flag with
--channels
doesn’t extend the bypass to the
--channels
entries. During the research preview, the approved allowlist is Anthropic-curated, so your channel stays on the development flag while you build and test.
This flag skips the allowlist only. The
channelsEnabled
organization policy still applies. Don’t use it to run channels from untrusted sources.
​
Server options
A channel sets these options in the
Server
constructor. The
instructions
and
capabilities.tools
fields are
standard MCP
;
capabilities.experimental['claude/channel']
and
capabilities.experimental['claude/channel/permission']
are the channel-specific additions:
Field
Type
Description
capabilities.experimental['claude/channel']
object
Required. Always
{}
. Presence registers the notification listener.
capabilities.experimental['claude/channel/permission']
object
Optional. Always
{}
. Declares that this channel can receive permission relay requests. When declared, Claude Code forwards tool approval prompts to your channel so you can approve or deny them remotely. See
Relay permission prompts
.
capabilities.tools
object
Two-way only. Always
{}
. Standard MCP tool capability. See
Expose a reply tool
.
instructions
string
Recommended. Added to Claude’s system prompt. Tell Claude what events to expect, what the
<channel>
tag attributes mean, whether to reply, and if so which tool to use and which attribute to pass back (like
chat_id
).
To create a one-way channel, omit
capabilities.tools
. This example shows a two-way setup with the channel capability, tools, and instructions set:
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
const
mcp
=
new
Server
(
{
name:
'your-channel'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{} },
// registers the channel listener
tools:
{},
// omit for one-way channels
},
// added to Claude's system prompt so it knows how to handle your events
instructions:
'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.'
,
},
)
To push an event, call
mcp.notification()
with method
notifications/claude/channel
. The params are in the next section.
​
Notification format
Your server emits
notifications/claude/channel
with two params:
Field
Type
Description
content
string
The event body. Delivered as the body of the
<channel>
tag.
meta
Record<string, string>
Optional. Each entry becomes an attribute on the
<channel>
tag for routing context like chat ID, sender name, or alert severity. Keys must be identifiers: letters, digits, and underscores only. Keys containing hyphens or other characters are silently dropped.
Your server pushes events by calling
mcp.notification()
on the
Server
instance. This example pushes a CI failure alert with two meta keys:
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
'build failed on main: https://ci.example.com/run/1234'
,
meta:
{
severity:
'high'
,
run_id:
'1234'
},
},
})
The event arrives in Claude’s context wrapped in a
<channel>
tag. The
source
attribute is set automatically from your server’s configured name:
<channel source="your-channel" severity="high" run_id="1234">
build failed on main: https://ci.example.com/run/1234
</channel>
Notifications are not acknowledged. The
await
on
mcp.notification()
resolves when the message is written to the transport, not when Claude has processed it. If the session hasn’t loaded your server as a channel, or the organization policy blocks it, events are dropped silently with no error returned to your server.
If you need delivery confirmation, track event state in your server and expose a
reply tool
that Claude can call to report status back.
Events queue into the session and are processed in order. If several notifications arrive while Claude is busy, they’re delivered together on the next turn and Claude handles them as a group. To process independent event streams concurrently, run separate sessions.
​
Expose a reply tool
If your channel is two-way, like a chat bridge rather than an alert forwarder, expose a standard
MCP tool
that Claude can call to send messages back. Nothing about the tool registration is channel-specific. A reply tool has three components:
A
tools: {}
entry in your
Server
constructor capabilities so Claude Code discovers the tool
Tool handlers that define the tool’s schema and implement the send logic
An
instructions
string in your
Server
constructor that tells Claude when and how to call the tool
To add these to the
webhook receiver above
:
1
Enable tool discovery
In your
Server
constructor in
webhook.ts
, add
tools: {}
to the capabilities so Claude Code knows your server offers tools:
capabilities
: {
experimental
: {
'claude/channel'
: {} },
tools
: {},
// enables tool discovery
},
2
Register the reply tool
Add the following to
webhook.ts
. The
import
goes at the top of the file with your other imports; the two handlers go between the
Server
constructor and
mcp.connect()
. This registers a
reply
tool that Claude can call with a
chat_id
and
text
:
// Add this import at the top of webhook.ts
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
// Claude queries this at startup to discover what tools your server offers
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
// inputSchema tells Claude what arguments to pass
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
// Claude calls this when it wants to invoke a tool
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
// send() is your outbound: POST to your chat platform, or for local
// testing the SSE broadcast shown in the full example below.
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
3
Update the instructions
Update the
instructions
string in your
Server
constructor so Claude knows to route replies back through the tool. This example tells Claude to pass
chat_id
from the inbound tag:
instructions
:
'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'
Here’s the complete
webhook.ts
with two-way support. Outbound replies stream over
GET /events
using
Server-Sent Events
(SSE), so
curl -N localhost:8788/events
can watch them live; inbound chat arrives on
POST /
:
Full webhook.ts with reply tool
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
// --- Outbound: write to any curl -N listeners on /events --------------------
// A real bridge would POST to your chat platform instead.
const
listeners
=
new
Set
<(
chunk
:
string
)
=>
void
>()
function
send
(
text
:
string
) {
const
chunk
=
text
.
split
(
'
\n
'
).
map
(
l
=>
`data:
${
l
}
\n
`
).
join
(
''
)
+
'
\n
'
for
(
const
emit
of
listeners
)
emit
(
chunk
)
}
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{} },
tools:
{},
},
instructions:
'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'
,
},
)
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
await
mcp
.
connect
(
new
StdioServerTransport
())
let
nextId
=
1
Bun
.
serve
({
port:
8788
,
hostname:
'127.0.0.1'
,
idleTimeout:
0
,
// don't close idle SSE streams
async
fetch
(
req
) {
const
url
=
new
URL
(
req
.
url
)
// GET /events: SSE stream so curl -N can watch Claude's replies live
if
(
req
.
method
===
'GET'
&&
url
.
pathname
===
'/events'
) {
const
stream
=
new
ReadableStream
({
start
(
ctrl
) {
ctrl
.
enqueue
(
': connected
\n\n
'
)
// so curl shows something immediately
const
emit
=
(
chunk
:
string
)
=>
ctrl
.
enqueue
(
chunk
)
listeners
.
add
(
emit
)
req
.
signal
.
addEventListener
(
'abort'
, ()
=>
listeners
.
delete
(
emit
))
},
})
return
new
Response
(
stream
, {
headers:
{
'Content-Type'
:
'text/event-stream'
,
'Cache-Control'
:
'no-cache'
},
})
}
// POST: forward to Claude as a channel event
const
body
=
await
req
.
text
()
const
chat_id
=
String
(
nextId
++
)
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
meta:
{
chat_id
,
path:
url
.
pathname
,
method:
req
.
method
},
},
})
return
new
Response
(
'ok'
)
},
})
See all 86 lines
The
fakechat server
shows a more complete example with file attachments and message editing.
​
Gate inbound messages
An ungated channel is a prompt injection vector. Anyone who can reach your endpoint can put text in front of Claude. A channel listening to a chat platform or a public endpoint needs a real sender check before it emits anything.
Check the sender against an allowlist before calling
mcp.notification()
. This example drops any message from a sender not in the set:
const
allowed
=
new
Set
(
loadAllowlist
())
// from your access.json or equivalent
// inside your message handler, before emitting:
if
(
!
allowed
.
has
(
message
.
from
.
id
)) {
// sender, not room
return
// drop silently
}
await
mcp
.
notification
({
...
})
Gate on the sender’s identity, not the chat or room identity:
message.from.id
in the example, not
message.chat.id
. In group chats, these differ, and gating on the room would let anyone in an allowlisted group inject messages into the session.
The
Telegram
and
Discord
channels gate on a sender allowlist the same way. They bootstrap the list by pairing: the user DMs the bot, the bot replies with a pairing code, the user approves it in their Claude Code session, and their platform ID is added. See either implementation for the full pairing flow. The
iMessage
channel takes a different approach: it detects the user’s own addresses from the Messages database at startup and lets them through automatically, with other senders added by handle.
​
Relay permission prompts
Permission relay requires Claude Code v2.1.81 or later. Earlier versions ignore the
claude/channel/permission
capability.
When Claude calls a tool that needs approval, the local terminal dialog opens and the session waits. A two-way channel can opt in to receive the same prompt in parallel and relay it to you on another device. Both stay live: you can answer in the terminal or on your phone, and Claude Code applies whichever answer arrives first and closes the other.
Relay covers tool-use approvals like
Bash
,
Write
, and
Edit
. Project trust and MCP server consent dialogs don’t relay; those only appear in the local terminal.
​
How relay works
When a permission prompt opens, the relay loop has four steps:
Claude Code generates a short request ID and notifies your server
Your server forwards the prompt and ID to your chat app
The remote user replies with a yes or no and that ID
Your inbound handler parses the reply into a verdict, and Claude Code applies it only if the ID matches an open request
The local terminal dialog stays open through all of this. If someone at the terminal answers before the remote verdict arrives, that answer is applied instead and the pending remote request is dropped.
​
Permission request fields
The outbound notification from Claude Code is
notifications/claude/channel/permission_request
. Like the
channel notification
, the transport is standard MCP but the method and schema are Claude Code extensions. The
params
object has four string fields your server formats into the outgoing prompt:
Field
Description
request_id
Five lowercase letters drawn from
a
-
z
without
l
, so it never reads as a
1
or
I
when typed on a phone. Include it in your outgoing prompt so it can be echoed in the reply. Claude Code only accepts a verdict that carries an ID it issued. The local terminal dialog doesn’t display this ID, so your outbound handler is the only way to learn it.
tool_name
Name of the tool Claude wants to use, for example
Bash
or
Write
.
description
Human-readable summary of what this specific tool call does, the same text the local terminal dialog shows. For a Bash call this is Claude’s description of the command, or the command itself if none was given.
input_preview
The tool’s arguments as a JSON string, truncated to 200 characters. For Bash this is the command; for Write it’s the file path and a prefix of the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show.
The verdict your server sends back is
notifications/claude/channel/permission
with two fields:
request_id
echoing the ID above, and
behavior
set to
'allow'
or
'deny'
. Allow lets the tool call proceed; deny rejects it, the same as answering No in the local dialog. Neither verdict affects future calls.
​
Add relay to a chat bridge
Adding permission relay to a two-way channel takes three components:
A
claude/channel/permission: {}
entry under
experimental
capabilities in your
Server
constructor so Claude Code knows to forward prompts
A notification handler for
notifications/claude/channel/permission_request
that formats the prompt and sends it out through your platform API
A check in your inbound message handler that recognizes
yes <id>
or
no <id>
and emits a
notifications/claude/channel/permission
verdict instead of forwarding the text to Claude
Only declare the capability if your channel
authenticates the sender
, because anyone who can reply through your channel can approve or deny tool use in your session.
To add these to a two-way chat bridge like the one assembled in
Expose a reply tool
:
1
Declare the permission capability
In your
Server
constructor, add
claude/channel/permission: {}
alongside
claude/channel
under
experimental
:
capabilities
: {
experimental
: {
'claude/channel'
: {},
'claude/channel/permission'
: {},
// opt in to permission relay
},
tools
: {},
},
2
Handle the incoming request
Register a notification handler between your
Server
constructor and
mcp.connect()
. Claude Code calls it with the
four request fields
when a permission dialog opens. Your handler formats the prompt for your platform and includes instructions for replying with the ID:
import
{
z
}
from
'zod'
// setNotificationHandler routes by z.literal on the method field,
// so this schema is both the validator and the dispatch key
const
PermissionRequestSchema
=
z
.
object
({
method:
z
.
literal
(
'notifications/claude/channel/permission_request'
),
params:
z
.
object
({
request_id:
z
.
string
(),
// five lowercase letters, include verbatim in your prompt
tool_name:
z
.
string
(),
// e.g. "Bash", "Write"
description:
z
.
string
(),
// human-readable summary of this call
input_preview:
z
.
string
(),
// tool args as JSON, truncated to ~200 chars
}),
})
mcp
.
setNotificationHandler
(
PermissionRequestSchema
,
async
({
params
})
=>
{
// send() is your outbound: POST to your chat platform, or for local
// testing the SSE broadcast shown in the full example below.
send
(
`Claude wants to run
${
params
.
tool_name
}
:
${
params
.
description
}
\n\n
`
+
// the ID in the instruction is what your inbound handler parses in Step 3
`Reply "yes
${
params
.
request_id
}
" or "no
${
params
.
request_id
}
"`
,
)
})
3
Intercept the verdict in your inbound handler
Your inbound handler is the loop or callback that receives messages from your platform: the same place you
gate on sender
and emit
notifications/claude/channel
to forward chat to Claude. Add a check before the chat-forwarding call that recognizes the verdict format and emits the permission notification instead.
The regex matches the ID format Claude Code generates: five letters, never
l
. The
/i
flag tolerates phone autocorrect capitalizing the reply; lowercase the captured ID before sending it back.
// matches "y abcde", "yes abcde", "n abcde", "no abcde"
// [a-km-z] is the ID alphabet Claude Code uses (lowercase, skips 'l')
// /i tolerates phone autocorrect; lowercase the capture before sending
const
PERMISSION_REPLY_RE
=
/
^
\s
*
(
y
|
yes
|
n
|
no
)
\s
+
(
[
a-km-z
]
{5}
)
\s
*
$
/
i
async
function
onInbound
(
message
:
PlatformMessage
) {
if
(
!
allowed
.
has
(
message
.
from
.
id
))
return
// gate on sender first
const
m
=
PERMISSION_REPLY_RE
.
exec
(
message
.
text
)
if
(
m
) {
// m[1] is the verdict word, m[2] is the request ID
// emit the verdict notification back to Claude Code instead of chat
await
mcp
.
notification
({
method:
'notifications/claude/channel/permission'
,
params:
{
request_id:
m
[
2
].
toLowerCase
(),
// normalize in case of autocorrect caps
behavior:
m
[
1
].
toLowerCase
().
startsWith
(
'y'
)
?
'allow'
:
'deny'
,
},
})
return
// handled as verdict, don't also forward as chat
}
// didn't match verdict format: fall through to the normal chat path
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
message
.
text
,
meta:
{
chat_id:
String
(
message
.
chat
.
id
) } },
})
}
Claude Code also keeps the local terminal dialog open, so you can answer in either place, and the first answer to arrive is applied. A remote reply that doesn’t exactly match the expected format fails in one of two ways, and in both cases the dialog stays open:
Different format
: your inbound handler’s regex fails to match, so text like
approve it
or
yes
without an ID falls through as a normal message to Claude.
Right format, wrong ID
: your server emits a verdict, but Claude Code finds no open request with that ID and drops it silently.
​
Full example
The assembled
webhook.ts
below combines all three extensions from this page: the reply tool, sender gating, and permission relay. If you’re starting here, you’ll also need the
project setup and
.mcp.json
entry
from the initial walkthrough.
To make both directions testable from curl, the HTTP listener serves two paths:
GET /events
: holds an SSE stream open and pushes each outbound message as a
data:
line, so
curl -N
can watch Claude’s replies and permission prompts arrive live.
POST /
: the inbound side, the same handler as earlier, now with the verdict-format check inserted before the chat-forward branch.
Full webhook.ts with permission relay
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
import
{
z
}
from
'zod'
// --- Outbound: write to any curl -N listeners on /events --------------------
// A real bridge would POST to your chat platform instead.
const
listeners
=
new
Set
<(
chunk
:
string
)
=>
void
>()
function
send
(
text
:
string
) {
const
chunk
=
text
.
split
(
'
\n
'
).
map
(
l
=>
`data:
${
l
}
\n
`
).
join
(
''
)
+
'
\n
'
for
(
const
emit
of
listeners
)
emit
(
chunk
)
}
// Sender allowlist. For the local walkthrough we trust the single X-Sender
// header value "dev"; a real bridge would check the platform's user ID.
const
allowed
=
new
Set
([
'dev'
])
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{},
'claude/channel/permission'
:
{},
// opt in to permission relay
},
tools:
{},
},
instructions:
'Messages arrive as <channel source="webhook" chat_id="...">. '
+
'Reply with the reply tool, passing the chat_id from the tag.'
,
},
)
// --- reply tool: Claude calls this to send a message back -------------------
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
// --- permission relay: Claude Code (not Claude) calls this when a dialog opens
const
PermissionRequestSchema
=
z
.
object
({
method:
z
.
literal
(
'notifications/claude/channel/permission_request'
),
params:
z
.
object
({
request_id:
z
.
string
(),
tool_name:
z
.
string
(),
description:
z
.
string
(),
input_preview:
z
.
string
(),
}),
})
mcp
.
setNotificationHandler
(
PermissionRequestSchema
,
async
({
params
})
=>
{
send
(
`Claude wants to run
${
params
.
tool_name
}
:
${
params
.
description
}
\n\n
`
+
`Reply "yes
${
params
.
request_id
}
" or "no
${
params
.
request_id
}
"`
,
)
})
await
mcp
.
connect
(
new
StdioServerTransport
())
// --- HTTP on :8788: GET /events streams outbound, POST routes inbound -------
const
PERMISSION_REPLY_RE
=
/
^
\s
*
(
y
|
yes
|
n
|
no
)
\s
+
(
[
a-km-z
]
{5}
)
\s
*
$
/
i
let
nextId
=
1
Bun
.
serve
({
port:
8788
,
hostname:
'127.0.0.1'
,
idleTimeout:
0
,
// don't close idle SSE streams
async
fetch
(
req
) {
const
url
=
new
URL
(
req
.
url
)
// GET /events: SSE stream so curl -N can watch replies and prompts live
if
(
req
.
method
===
'GET'
&&
url
.
pathname
===
'/events'
) {
const
stream
=
new
ReadableStream
({
start
(
ctrl
) {
ctrl
.
enqueue
(
': connected
\n\n
'
)
// so curl shows something immediately
const
emit
=
(
chunk
:
string
)
=>
ctrl
.
enqueue
(
chunk
)
listeners
.
add
(
emit
)
req
.
signal
.
addEventListener
(
'abort'
, ()
=>
listeners
.
delete
(
emit
))
},
})
return
new
Response
(
stream
, {
headers:
{
'Content-Type'
:
'text/event-stream'
,
'Cache-Control'
:
'no-cache'
},
})
}
// everything else is inbound: gate on sender first
const
body
=
await
req
.
text
()
const
sender
=
req
.
headers
.
get
(
'X-Sender'
)
??
''
if
(
!
allowed
.
has
(
sender
))
return
new
Response
(
'forbidden'
, {
status:
403
})
// check for verdict format before treating as chat
const
m
=
PERMISSION_REPLY_RE
.
exec
(
body
)
if
(
m
) {
await
mcp
.
notification
({
method:
'notifications/claude/channel/permission'
,
params:
{
request_id:
m
[
2
].
toLowerCase
(),
behavior:
m
[
1
].
toLowerCase
().
startsWith
(
'y'
)
?
'allow'
:
'deny'
,
},
})
return
new
Response
(
'verdict recorded'
)
}
// normal chat: forward to Claude as a channel event
const
chat_id
=
String
(
nextId
++
)
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
meta:
{
chat_id
,
path:
url
.
pathname
} },
})
return
new
Response
(
'ok'
)
},
})
See all 132 lines
Test the verdict path in three terminals. The first is your Claude Code session, started with the
development flag
so it spawns
webhook.ts
:
claude
--dangerously-load-development-channels
server:webhook
In the second, stream the outbound side so you can see Claude’s replies and any permission prompts as they fire:
curl
-N
localhost:8788/events
In the third, send a message that will make Claude try to run a command:
curl
-d
"list the files in this directory"
-H
"X-Sender: dev"
localhost:8788
The local permission dialog opens in your Claude Code terminal. A moment later the prompt appears in the
/events
stream, including the five-letter ID. Approve it from the remote side:
curl
-d
"yes <id>"
-H
"X-Sender: dev"
localhost:8788
The local dialog closes and the tool runs. Claude’s reply comes back through the
reply
tool and lands in the stream too.
The three channel-specific pieces in this file:
Capabilities
in the
Server
constructor:
claude/channel
registers the notification listener,
claude/channel/permission
opts in to permission relay,
tools
lets Claude discover the reply tool.
Outbound paths
: the
reply
tool handler is what Claude calls for conversational responses; the
PermissionRequestSchema
notification handler is what Claude Code calls when a permission dialog opens. Both call
send()
to broadcast over
/events
, but they’re triggered by different parts of the system.
HTTP handler
:
GET /events
holds an SSE stream open so curl can watch outbound live;
POST
is inbound, gated on the
X-Sender
header. A
yes <id>
or
no <id>
body goes to Claude Code as a verdict notification and never reaches Claude; anything else is forwarded to Claude as a channel event.
​
Package as a plugin
To make your channel installable and shareable, wrap it in a
plugin
and publish it to a
marketplace
. Users install it with
/plugin install
, then enable it per session with
--channels plugin:<name>@<marketplace>
.
A channel published to your own marketplace still needs
--dangerously-load-development-channels
to run, since it isn’t on the
approved allowlist
. To get it added,
submit it to the official marketplace
. Channel plugins go through security review before being approved. On Team and Enterprise plans, an admin can instead include your plugin in the organization’s own
allowedChannelPlugins
list, which replaces the default Anthropic allowlist.
​
See also
Channels
to install and use Telegram, Discord, iMessage, or the fakechat demo, and to enable channels for a Team or Enterprise org
Working channel implementations
for complete server code with pairing flows, reply tools, and file attachments
MCP
for the underlying protocol that channel servers implement
Plugins
to package your channel so users can install it with
/plugin install
Was this page helpful?
Yes
No
Plugins reference
Glossary
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/channels-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Channels reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Channels reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Channels are in
research preview
and require Claude Code v2.1.80 or later. Team and Enterprise organizations must
explicitly enable them
.
A channel is an MCP server that pushes events into a Claude Code session so Claude can react to things happening outside the terminal.
You can build a one-way or two-way channel. One-way channels forward alerts, webhooks, or monitoring events for Claude to act on. Two-way channels like chat bridges also
expose a reply tool
so Claude can send messages back. A channel with a trusted sender path can also opt in to
relay permission prompts
so you can approve or deny tool use remotely.
This page covers:
Overview
: how channels work
What you need
: requirements and general steps
Example: build a webhook receiver
: a minimal one-way walkthrough
Server options
: the constructor fields
Notification format
: the event payload and delivery behavior
Expose a reply tool
: let Claude send messages back
Gate inbound messages
: sender checks to prevent prompt injection
Relay permission prompts
: forward tool approval prompts to remote channels
To use an existing channel instead of building one, see
Channels
. Telegram, Discord, iMessage, and fakechat are included in the research preview.
​
Overview
A channel is an
MCP
server that runs on the same machine as Claude Code. Claude Code spawns it as a subprocess and communicates over stdio. Your channel server is the bridge between external systems and the Claude Code session:
Chat platforms
(Telegram, Discord): your plugin runs locally and polls the platform’s API for new messages. When someone DMs your bot, the plugin receives the message and forwards it to Claude. No URL to expose.
Webhooks
(CI, monitoring): your server listens on a local HTTP port. External systems POST to that port, and your server pushes the payload to Claude.
​
What you need
The only hard requirement is the
@modelcontextprotocol/sdk
package and a Node.js-compatible runtime.
Bun
,
Node
, and
Deno
all work. The pre-built plugins in the research preview use Bun, but your channel doesn’t have to.
Your server needs to:
Declare the
claude/channel
capability so Claude Code registers a notification listener
Emit
notifications/claude/channel
events when something happens
Connect over
stdio transport
(Claude Code spawns your server as a subprocess)
The
Server options
and
Notification format
sections cover each of these in detail. See
Example: build a webhook receiver
for a full walkthrough.
During the research preview, custom channels aren’t on the
approved allowlist
. Use
--dangerously-load-development-channels
to test locally. See
Test during the research preview
for details.
​
Example: build a webhook receiver
This walkthrough builds a single-file server that listens for HTTP requests and forwards them into your Claude Code session. By the end, anything that can send an HTTP POST, like a CI pipeline, a monitoring alert, or a
curl
command, can push events to Claude.
This example uses
Bun
as the runtime for its built-in HTTP server and TypeScript support. You can use
Node
or
Deno
instead; the only requirement is the
MCP SDK
.
1
Create the project
Create a new directory and install the MCP SDK:
mkdir
webhook-channel
&&
cd
webhook-channel
bun
add
@modelcontextprotocol/sdk
2
Write the channel server
Create a file called
webhook.ts
. This is your entire channel server: it connects to Claude Code over stdio, and it listens for HTTP POSTs on port 8788. When a request arrives, it pushes the body to Claude as a channel event.
webhook.ts
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
// Create the MCP server and declare it as a channel
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
// this key is what makes it a channel — Claude Code registers a listener for it
capabilities:
{
experimental:
{
'claude/channel'
:
{} } },
// added to Claude's system prompt so it knows how to handle these events
instructions:
'Events from the webhook channel arrive as <channel source="webhook" ...>. They are one-way: read them and act, no reply expected.'
,
},
)
// Connect to Claude Code over stdio (Claude Code spawns this process)
await
mcp
.
connect
(
new
StdioServerTransport
())
// Start an HTTP server that forwards every POST to Claude
Bun
.
serve
({
port:
8788
,
// any open port works
// localhost-only: nothing outside this machine can POST
hostname:
'127.0.0.1'
,
async
fetch
(
req
) {
const
body
=
await
req
.
text
()
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
// becomes the body of the <channel> tag
// each key becomes a tag attribute, e.g. <channel path="/" method="POST">
meta:
{
path:
new
URL
(
req
.
url
).
pathname
,
method:
req
.
method
},
},
})
return
new
Response
(
'ok'
)
},
})
The file does three things in order:
Server configuration
: creates the MCP server with
claude/channel
in its capabilities, which is what tells Claude Code this is a channel. The
instructions
string goes into Claude’s system prompt: tell Claude what events to expect, whether to reply, and how to route replies if it should.
Stdio connection
: connects to Claude Code over stdin/stdout. This is standard for any
MCP server
: Claude Code spawns it as a subprocess.
HTTP listener
: starts a local web server on port 8788. Every POST body gets forwarded to Claude as a channel event via
mcp.notification()
. The
content
becomes the event body, and each
meta
entry becomes an attribute on the
<channel>
tag. The listener needs access to the
mcp
instance, so it runs in the same process. You could split it into separate modules for a larger project.
3
Register your server with Claude Code
Add the server to your MCP config so Claude Code knows how to start it. For a project-level
.mcp.json
in the same directory, use a relative path. For user-level config in
~/.claude.json
, use the full absolute path so the server can be found from any project:
.mcp.json
{
"mcpServers"
: {
"webhook"
: {
"command"
:
"bun"
,
"args"
: [
"./webhook.ts"
] }
}
}
Claude Code reads your MCP config at startup and spawns each server as a subprocess.
4
Test it
During the research preview, custom channels aren’t on the allowlist, so start Claude Code with the development flag:
claude
--dangerously-load-development-channels
server:webhook
When Claude Code starts, it reads your MCP config, spawns your
webhook.ts
as a subprocess, and the HTTP listener starts automatically on the port you configured (8788 in this example). You don’t need to run the server yourself.
If you see “blocked by org policy,” your organization admin needs to
enable channels
first.
In a separate terminal, simulate a webhook by sending an HTTP POST with a message to your server. This example sends a CI failure alert to port 8788 (or whichever port you configured):
curl
-X
POST
localhost:8788
-d
"build failed on main: https://ci.example.com/run/1234"
The payload arrives in your Claude Code session as a
<channel>
tag:
<channel source="webhook" path="/" method="POST">build failed on main: https://ci.example.com/run/1234</channel>
In your Claude Code terminal, you’ll see Claude receive the message and start responding: reading files, running commands, or whatever the message calls for. This is a one-way channel, so Claude acts in your session but doesn’t send anything back through the webhook. To add replies, see
Expose a reply tool
.
If the event doesn’t arrive, the diagnosis depends on what
curl
returned:
curl
succeeds but nothing reaches Claude
: run
/mcp
in your session to check the server’s status. “Failed to connect” usually means a dependency or import error in your server file; check the debug log at
~/.claude/debug/<session-id>.txt
for the stderr trace.
curl
fails with “connection refused”
: the port is either not bound yet or a stale process from an earlier run is holding it.
lsof -i :<port>
shows what’s listening;
kill
the stale process before restarting your session.
The
fakechat server
extends this pattern with a web UI, file attachments, and a reply tool for two-way chat.
​
Test during the research preview
During the research preview, every channel must be on the
approved allowlist
to register. The development flag bypasses the allowlist for specific entries after a confirmation prompt. This example shows both entry types:
# Testing a plugin you're developing
claude
--dangerously-load-development-channels
plugin:yourplugin@yourmarketplace
# Testing a bare .mcp.json server (no plugin wrapper yet)
claude
--dangerously-load-development-channels
server:webhook
The bypass is per-entry. Combining this flag with
--channels
doesn’t extend the bypass to the
--channels
entries. During the research preview, the approved allowlist is Anthropic-curated, so your channel stays on the development flag while you build and test.
This flag skips the allowlist only. The
channelsEnabled
organization policy still applies. Don’t use it to run channels from untrusted sources.
​
Server options
A channel sets these options in the
Server
constructor. The
instructions
and
capabilities.tools
fields are
standard MCP
;
capabilities.experimental['claude/channel']
and
capabilities.experimental['claude/channel/permission']
are the channel-specific additions:
Field
Type
Description
capabilities.experimental['claude/channel']
object
Required. Always
{}
. Presence registers the notification listener.
capabilities.experimental['claude/channel/permission']
object
Optional. Always
{}
. Declares that this channel can receive permission relay requests. When declared, Claude Code forwards tool approval prompts to your channel so you can approve or deny them remotely. See
Relay permission prompts
.
capabilities.tools
object
Two-way only. Always
{}
. Standard MCP tool capability. See
Expose a reply tool
.
instructions
string
Recommended. Added to Claude’s system prompt. Tell Claude what events to expect, what the
<channel>
tag attributes mean, whether to reply, and if so which tool to use and which attribute to pass back (like
chat_id
).
To create a one-way channel, omit
capabilities.tools
. This example shows a two-way setup with the channel capability, tools, and instructions set:
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
const
mcp
=
new
Server
(
{
name:
'your-channel'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{} },
// registers the channel listener
tools:
{},
// omit for one-way channels
},
// added to Claude's system prompt so it knows how to handle your events
instructions:
'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.'
,
},
)
To push an event, call
mcp.notification()
with method
notifications/claude/channel
. The params are in the next section.
​
Notification format
Your server emits
notifications/claude/channel
with two params:
Field
Type
Description
content
string
The event body. Delivered as the body of the
<channel>
tag.
meta
Record<string, string>
Optional. Each entry becomes an attribute on the
<channel>
tag for routing context like chat ID, sender name, or alert severity. Keys must be identifiers: letters, digits, and underscores only. Keys containing hyphens or other characters are silently dropped.
Your server pushes events by calling
mcp.notification()
on the
Server
instance. This example pushes a CI failure alert with two meta keys:
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
'build failed on main: https://ci.example.com/run/1234'
,
meta:
{
severity:
'high'
,
run_id:
'1234'
},
},
})
The event arrives in Claude’s context wrapped in a
<channel>
tag. The
source
attribute is set automatically from your server’s configured name:
<channel source="your-channel" severity="high" run_id="1234">
build failed on main: https://ci.example.com/run/1234
</channel>
Notifications are not acknowledged. The
await
on
mcp.notification()
resolves when the message is written to the transport, not when Claude has processed it. If the session hasn’t loaded your server as a channel, or the organization policy blocks it, events are dropped silently with no error returned to your server.
If you need delivery confirmation, track event state in your server and expose a
reply tool
that Claude can call to report status back.
Events queue into the session and are processed in order. If several notifications arrive while Claude is busy, they’re delivered together on the next turn and Claude handles them as a group. To process independent event streams concurrently, run separate sessions.
​
Expose a reply tool
If your channel is two-way, like a chat bridge rather than an alert forwarder, expose a standard
MCP tool
that Claude can call to send messages back. Nothing about the tool registration is channel-specific. A reply tool has three components:
A
tools: {}
entry in your
Server
constructor capabilities so Claude Code discovers the tool
Tool handlers that define the tool’s schema and implement the send logic
An
instructions
string in your
Server
constructor that tells Claude when and how to call the tool
To add these to the
webhook receiver above
:
1
Enable tool discovery
In your
Server
constructor in
webhook.ts
, add
tools: {}
to the capabilities so Claude Code knows your server offers tools:
capabilities
: {
experimental
: {
'claude/channel'
: {} },
tools
: {},
// enables tool discovery
},
2
Register the reply tool
Add the following to
webhook.ts
. The
import
goes at the top of the file with your other imports; the two handlers go between the
Server
constructor and
mcp.connect()
. This registers a
reply
tool that Claude can call with a
chat_id
and
text
:
// Add this import at the top of webhook.ts
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
// Claude queries this at startup to discover what tools your server offers
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
// inputSchema tells Claude what arguments to pass
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
// Claude calls this when it wants to invoke a tool
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
// send() is your outbound: POST to your chat platform, or for local
// testing the SSE broadcast shown in the full example below.
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
3
Update the instructions
Update the
instructions
string in your
Server
constructor so Claude knows to route replies back through the tool. This example tells Claude to pass
chat_id
from the inbound tag:
instructions
:
'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'
Here’s the complete
webhook.ts
with two-way support. Outbound replies stream over
GET /events
using
Server-Sent Events
(SSE), so
curl -N localhost:8788/events
can watch them live; inbound chat arrives on
POST /
:
Full webhook.ts with reply tool
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
// --- Outbound: write to any curl -N listeners on /events --------------------
// A real bridge would POST to your chat platform instead.
const
listeners
=
new
Set
<(
chunk
:
string
)
=>
void
>()
function
send
(
text
:
string
) {
const
chunk
=
text
.
split
(
'
\n
'
).
map
(
l
=>
`data:
${
l
}
\n
`
).
join
(
''
)
+
'
\n
'
for
(
const
emit
of
listeners
)
emit
(
chunk
)
}
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{} },
tools:
{},
},
instructions:
'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'
,
},
)
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
await
mcp
.
connect
(
new
StdioServerTransport
())
let
nextId
=
1
Bun
.
serve
({
port:
8788
,
hostname:
'127.0.0.1'
,
idleTimeout:
0
,
// don't close idle SSE streams
async
fetch
(
req
) {
const
url
=
new
URL
(
req
.
url
)
// GET /events: SSE stream so curl -N can watch Claude's replies live
if
(
req
.
method
===
'GET'
&&
url
.
pathname
===
'/events'
) {
const
stream
=
new
ReadableStream
({
start
(
ctrl
) {
ctrl
.
enqueue
(
': connected
\n\n
'
)
// so curl shows something immediately
const
emit
=
(
chunk
:
string
)
=>
ctrl
.
enqueue
(
chunk
)
listeners
.
add
(
emit
)
req
.
signal
.
addEventListener
(
'abort'
, ()
=>
listeners
.
delete
(
emit
))
},
})
return
new
Response
(
stream
, {
headers:
{
'Content-Type'
:
'text/event-stream'
,
'Cache-Control'
:
'no-cache'
},
})
}
// POST: forward to Claude as a channel event
const
body
=
await
req
.
text
()
const
chat_id
=
String
(
nextId
++
)
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
meta:
{
chat_id
,
path:
url
.
pathname
,
method:
req
.
method
},
},
})
return
new
Response
(
'ok'
)
},
})
See all 86 lines
The
fakechat server
shows a more complete example with file attachments and message editing.
​
Gate inbound messages
An ungated channel is a prompt injection vector. Anyone who can reach your endpoint can put text in front of Claude. A channel listening to a chat platform or a public endpoint needs a real sender check before it emits anything.
Check the sender against an allowlist before calling
mcp.notification()
. This example drops any message from a sender not in the set:
const
allowed
=
new
Set
(
loadAllowlist
())
// from your access.json or equivalent
// inside your message handler, before emitting:
if
(
!
allowed
.
has
(
message
.
from
.
id
)) {
// sender, not room
return
// drop silently
}
await
mcp
.
notification
({
...
})
Gate on the sender’s identity, not the chat or room identity:
message.from.id
in the example, not
message.chat.id
. In group chats, these differ, and gating on the room would let anyone in an allowlisted group inject messages into the session.
The
Telegram
and
Discord
channels gate on a sender allowlist the same way. They bootstrap the list by pairing: the user DMs the bot, the bot replies with a pairing code, the user approves it in their Claude Code session, and their platform ID is added. See either implementation for the full pairing flow. The
iMessage
channel takes a different approach: it detects the user’s own addresses from the Messages database at startup and lets them through automatically, with other senders added by handle.
​
Relay permission prompts
Permission relay requires Claude Code v2.1.81 or later. Earlier versions ignore the
claude/channel/permission
capability.
When Claude calls a tool that needs approval, the local terminal dialog opens and the session waits. A two-way channel can opt in to receive the same prompt in parallel and relay it to you on another device. Both stay live: you can answer in the terminal or on your phone, and Claude Code applies whichever answer arrives first and closes the other.
Relay covers tool-use approvals like
Bash
,
Write
, and
Edit
. Project trust and MCP server consent dialogs don’t relay; those only appear in the local terminal.
​
How relay works
When a permission prompt opens, the relay loop has four steps:
Claude Code generates a short request ID and notifies your server
Your server forwards the prompt and ID to your chat app
The remote user replies with a yes or no and that ID
Your inbound handler parses the reply into a verdict, and Claude Code applies it only if the ID matches an open request
The local terminal dialog stays open through all of this. If someone at the terminal answers before the remote verdict arrives, that answer is applied instead and the pending remote request is dropped.
​
Permission request fields
The outbound notification from Claude Code is
notifications/claude/channel/permission_request
. Like the
channel notification
, the transport is standard MCP but the method and schema are Claude Code extensions. The
params
object has four string fields your server formats into the outgoing prompt:
Field
Description
request_id
Five lowercase letters drawn from
a
-
z
without
l
, so it never reads as a
1
or
I
when typed on a phone. Include it in your outgoing prompt so it can be echoed in the reply. Claude Code only accepts a verdict that carries an ID it issued. The local terminal dialog doesn’t display this ID, so your outbound handler is the only way to learn it.
tool_name
Name of the tool Claude wants to use, for example
Bash
or
Write
.
description
Human-readable summary of what this specific tool call does, the same text the local terminal dialog shows. For a Bash call this is Claude’s description of the command, or the command itself if none was given.
input_preview
The tool’s arguments as a JSON string, truncated to 200 characters. For Bash this is the command; for Write it’s the file path and a prefix of the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show.
The verdict your server sends back is
notifications/claude/channel/permission
with two fields:
request_id
echoing the ID above, and
behavior
set to
'allow'
or
'deny'
. Allow lets the tool call proceed; deny rejects it, the same as answering No in the local dialog. Neither verdict affects future calls.
​
Add relay to a chat bridge
Adding permission relay to a two-way channel takes three components:
A
claude/channel/permission: {}
entry under
experimental
capabilities in your
Server
constructor so Claude Code knows to forward prompts
A notification handler for
notifications/claude/channel/permission_request
that formats the prompt and sends it out through your platform API
A check in your inbound message handler that recognizes
yes <id>
or
no <id>
and emits a
notifications/claude/channel/permission
verdict instead of forwarding the text to Claude
Only declare the capability if your channel
authenticates the sender
, because anyone who can reply through your channel can approve or deny tool use in your session.
To add these to a two-way chat bridge like the one assembled in
Expose a reply tool
:
1
Declare the permission capability
In your
Server
constructor, add
claude/channel/permission: {}
alongside
claude/channel
under
experimental
:
capabilities
: {
experimental
: {
'claude/channel'
: {},
'claude/channel/permission'
: {},
// opt in to permission relay
},
tools
: {},
},
2
Handle the incoming request
Register a notification handler between your
Server
constructor and
mcp.connect()
. Claude Code calls it with the
four request fields
when a permission dialog opens. Your handler formats the prompt for your platform and includes instructions for replying with the ID:
import
{
z
}
from
'zod'
// setNotificationHandler routes by z.literal on the method field,
// so this schema is both the validator and the dispatch key
const
PermissionRequestSchema
=
z
.
object
({
method:
z
.
literal
(
'notifications/claude/channel/permission_request'
),
params:
z
.
object
({
request_id:
z
.
string
(),
// five lowercase letters, include verbatim in your prompt
tool_name:
z
.
string
(),
// e.g. "Bash", "Write"
description:
z
.
string
(),
// human-readable summary of this call
input_preview:
z
.
string
(),
// tool args as JSON, truncated to ~200 chars
}),
})
mcp
.
setNotificationHandler
(
PermissionRequestSchema
,
async
({
params
})
=>
{
// send() is your outbound: POST to your chat platform, or for local
// testing the SSE broadcast shown in the full example below.
send
(
`Claude wants to run
${
params
.
tool_name
}
:
${
params
.
description
}
\n\n
`
+
// the ID in the instruction is what your inbound handler parses in Step 3
`Reply "yes
${
params
.
request_id
}
" or "no
${
params
.
request_id
}
"`
,
)
})
3
Intercept the verdict in your inbound handler
Your inbound handler is the loop or callback that receives messages from your platform: the same place you
gate on sender
and emit
notifications/claude/channel
to forward chat to Claude. Add a check before the chat-forwarding call that recognizes the verdict format and emits the permission notification instead.
The regex matches the ID format Claude Code generates: five letters, never
l
. The
/i
flag tolerates phone autocorrect capitalizing the reply; lowercase the captured ID before sending it back.
// matches "y abcde", "yes abcde", "n abcde", "no abcde"
// [a-km-z] is the ID alphabet Claude Code uses (lowercase, skips 'l')
// /i tolerates phone autocorrect; lowercase the capture before sending
const
PERMISSION_REPLY_RE
=
/
^
\s
*
(
y
|
yes
|
n
|
no
)
\s
+
(
[
a-km-z
]
{5}
)
\s
*
$
/
i
async
function
onInbound
(
message
:
PlatformMessage
) {
if
(
!
allowed
.
has
(
message
.
from
.
id
))
return
// gate on sender first
const
m
=
PERMISSION_REPLY_RE
.
exec
(
message
.
text
)
if
(
m
) {
// m[1] is the verdict word, m[2] is the request ID
// emit the verdict notification back to Claude Code instead of chat
await
mcp
.
notification
({
method:
'notifications/claude/channel/permission'
,
params:
{
request_id:
m
[
2
].
toLowerCase
(),
// normalize in case of autocorrect caps
behavior:
m
[
1
].
toLowerCase
().
startsWith
(
'y'
)
?
'allow'
:
'deny'
,
},
})
return
// handled as verdict, don't also forward as chat
}
// didn't match verdict format: fall through to the normal chat path
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
message
.
text
,
meta:
{
chat_id:
String
(
message
.
chat
.
id
) } },
})
}
Claude Code also keeps the local terminal dialog open, so you can answer in either place, and the first answer to arrive is applied. A remote reply that doesn’t exactly match the expected format fails in one of two ways, and in both cases the dialog stays open:
Different format
: your inbound handler’s regex fails to match, so text like
approve it
or
yes
without an ID falls through as a normal message to Claude.
Right format, wrong ID
: your server emits a verdict, but Claude Code finds no open request with that ID and drops it silently.
​
Full example
The assembled
webhook.ts
below combines all three extensions from this page: the reply tool, sender gating, and permission relay. If you’re starting here, you’ll also need the
project setup and
.mcp.json
entry
from the initial walkthrough.
To make both directions testable from curl, the HTTP listener serves two paths:
GET /events
: holds an SSE stream open and pushes each outbound message as a
data:
line, so
curl -N
can watch Claude’s replies and permission prompts arrive live.
POST /
: the inbound side, the same handler as earlier, now with the verdict-format check inserted before the chat-forward branch.
Full webhook.ts with permission relay
#!/usr/bin/env bun
import
{
Server
}
from
'@modelcontextprotocol/sdk/server/index.js'
import
{
StdioServerTransport
}
from
'@modelcontextprotocol/sdk/server/stdio.js'
import
{
ListToolsRequestSchema
,
CallToolRequestSchema
}
from
'@modelcontextprotocol/sdk/types.js'
import
{
z
}
from
'zod'
// --- Outbound: write to any curl -N listeners on /events --------------------
// A real bridge would POST to your chat platform instead.
const
listeners
=
new
Set
<(
chunk
:
string
)
=>
void
>()
function
send
(
text
:
string
) {
const
chunk
=
text
.
split
(
'
\n
'
).
map
(
l
=>
`data:
${
l
}
\n
`
).
join
(
''
)
+
'
\n
'
for
(
const
emit
of
listeners
)
emit
(
chunk
)
}
// Sender allowlist. For the local walkthrough we trust the single X-Sender
// header value "dev"; a real bridge would check the platform's user ID.
const
allowed
=
new
Set
([
'dev'
])
const
mcp
=
new
Server
(
{
name:
'webhook'
,
version:
'0.0.1'
},
{
capabilities:
{
experimental:
{
'claude/channel'
:
{},
'claude/channel/permission'
:
{},
// opt in to permission relay
},
tools:
{},
},
instructions:
'Messages arrive as <channel source="webhook" chat_id="...">. '
+
'Reply with the reply tool, passing the chat_id from the tag.'
,
},
)
// --- reply tool: Claude calls this to send a message back -------------------
mcp
.
setRequestHandler
(
ListToolsRequestSchema
,
async
()
=>
({
tools:
[{
name:
'reply'
,
description:
'Send a message back over this channel'
,
inputSchema:
{
type:
'object'
,
properties:
{
chat_id:
{
type:
'string'
,
description:
'The conversation to reply in'
},
text:
{
type:
'string'
,
description:
'The message to send'
},
},
required:
[
'chat_id'
,
'text'
],
},
}],
}))
mcp
.
setRequestHandler
(
CallToolRequestSchema
,
async
req
=>
{
if
(
req
.
params
.
name
===
'reply'
) {
const
{
chat_id
,
text
}
=
req
.
params
.
arguments
as
{
chat_id
:
string
;
text
:
string
}
send
(
`Reply to
${
chat_id
}
:
${
text
}
`
)
return
{
content:
[{
type:
'text'
,
text:
'sent'
}] }
}
throw
new
Error
(
`unknown tool:
${
req
.
params
.
name
}
`
)
})
// --- permission relay: Claude Code (not Claude) calls this when a dialog opens
const
PermissionRequestSchema
=
z
.
object
({
method:
z
.
literal
(
'notifications/claude/channel/permission_request'
),
params:
z
.
object
({
request_id:
z
.
string
(),
tool_name:
z
.
string
(),
description:
z
.
string
(),
input_preview:
z
.
string
(),
}),
})
mcp
.
setNotificationHandler
(
PermissionRequestSchema
,
async
({
params
})
=>
{
send
(
`Claude wants to run
${
params
.
tool_name
}
:
${
params
.
description
}
\n\n
`
+
`Reply "yes
${
params
.
request_id
}
" or "no
${
params
.
request_id
}
"`
,
)
})
await
mcp
.
connect
(
new
StdioServerTransport
())
// --- HTTP on :8788: GET /events streams outbound, POST routes inbound -------
const
PERMISSION_REPLY_RE
=
/
^
\s
*
(
y
|
yes
|
n
|
no
)
\s
+
(
[
a-km-z
]
{5}
)
\s
*
$
/
i
let
nextId
=
1
Bun
.
serve
({
port:
8788
,
hostname:
'127.0.0.1'
,
idleTimeout:
0
,
// don't close idle SSE streams
async
fetch
(
req
) {
const
url
=
new
URL
(
req
.
url
)
// GET /events: SSE stream so curl -N can watch replies and prompts live
if
(
req
.
method
===
'GET'
&&
url
.
pathname
===
'/events'
) {
const
stream
=
new
ReadableStream
({
start
(
ctrl
) {
ctrl
.
enqueue
(
': connected
\n\n
'
)
// so curl shows something immediately
const
emit
=
(
chunk
:
string
)
=>
ctrl
.
enqueue
(
chunk
)
listeners
.
add
(
emit
)
req
.
signal
.
addEventListener
(
'abort'
, ()
=>
listeners
.
delete
(
emit
))
},
})
return
new
Response
(
stream
, {
headers:
{
'Content-Type'
:
'text/event-stream'
,
'Cache-Control'
:
'no-cache'
},
})
}
// everything else is inbound: gate on sender first
const
body
=
await
req
.
text
()
const
sender
=
req
.
headers
.
get
(
'X-Sender'
)
??
''
if
(
!
allowed
.
has
(
sender
))
return
new
Response
(
'forbidden'
, {
status:
403
})
// check for verdict format before treating as chat
const
m
=
PERMISSION_REPLY_RE
.
exec
(
body
)
if
(
m
) {
await
mcp
.
notification
({
method:
'notifications/claude/channel/permission'
,
params:
{
request_id:
m
[
2
].
toLowerCase
(),
behavior:
m
[
1
].
toLowerCase
().
startsWith
(
'y'
)
?
'allow'
:
'deny'
,
},
})
return
new
Response
(
'verdict recorded'
)
}
// normal chat: forward to Claude as a channel event
const
chat_id
=
String
(
nextId
++
)
await
mcp
.
notification
({
method:
'notifications/claude/channel'
,
params:
{
content:
body
,
meta:
{
chat_id
,
path:
url
.
pathname
} },
})
return
new
Response
(
'ok'
)
},
})
See all 132 lines
Test the verdict path in three terminals. The first is your Claude Code session, started with the
development flag
so it spawns
webhook.ts
:
claude
--dangerously-load-development-channels
server:webhook
In the second, stream the outbound side so you can see Claude’s replies and any permission prompts as they fire:
curl
-N
localhost:8788/events
In the third, send a message that will make Claude try to run a command:
curl
-d
"list the files in this directory"
-H
"X-Sender: dev"
localhost:8788
The local permission dialog opens in your Claude Code terminal. A moment later the prompt appears in the
/events
stream, including the five-letter ID. Approve it from the remote side:
curl
-d
"yes <id>"
-H
"X-Sender: dev"
localhost:8788
The local dialog closes and the tool runs. Claude’s reply comes back through the
reply
tool and lands in the stream too.
The three channel-specific pieces in this file:
Capabilities
in the
Server
constructor:
claude/channel
registers the notification listener,
claude/channel/permission
opts in to permission relay,
tools
lets Claude discover the reply tool.
Outbound paths
: the
reply
tool handler is what Claude calls for conversational responses; the
PermissionRequestSchema
notification handler is what Claude Code calls when a permission dialog opens. Both call
send()
to broadcast over
/events
, but they’re triggered by different parts of the system.
HTTP handler
:
GET /events
holds an SSE stream open so curl can watch outbound live;
POST
is inbound, gated on the
X-Sender
header. A
yes <id>
or
no <id>
body goes to Claude Code as a verdict notification and never reaches Claude; anything else is forwarded to Claude as a channel event.
​
Package as a plugin
To make your channel installable and shareable, wrap it in a
plugin
and publish it to a
marketplace
. Users install it with
/plugin install
, then enable it per session with
--channels plugin:<name>@<marketplace>
.
A channel published to your own marketplace still needs
--dangerously-load-development-channels
to run, since it isn’t on the
approved allowlist
. To get it added,
submit it to the official marketplace
. Channel plugins go through security review before being approved. On Team and Enterprise plans, an admin can instead include your plugin in the organization’s own
allowedChannelPlugins
list, which replaces the default Anthropic allowlist.
​
See also
Channels
to install and use Telegram, Discord, iMessage, or the fakechat demo, and to enable channels for a Team or Enterprise org
Working channel implementations
for complete server code with pairing flows, reply tools, and file attachments
MCP
for the underlying protocol that channel servers implement
Plugins
to package your channel so users can install it with
/plugin install
Was this page helpful?
Yes
No
Plugins reference
Glossary
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/channels-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Intercept and control agent behavior with hooks</title>
  <link>https://code.claude.com/docs/en/agent-sdk/hooks</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/hooks</guid>
  <pubDate>Tue, 02 Jul 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Intercept and control agent behavior with hooks
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Intercept and control agent behavior with hooks
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Hooks are callback functions that run your code in response to agent events, like a tool being called, a session starting, or execution stopping. With hooks, you can:
Block dangerous operations
before they execute, like destructive shell commands or unauthorized file access
Log and audit
every tool call for compliance, debugging, or analytics
Transform inputs and outputs
to sanitize data, inject credentials, or redirect file paths
Require human approval
for sensitive actions like database writes or API calls
Track session lifecycle
to manage state, clean up resources, or send notifications
This guide covers how hooks work, how to configure them, and provides examples for common patterns like blocking tools, modifying inputs, and forwarding notifications.
​
How hooks work
1
An event fires
Something happens during agent execution and the SDK fires an event: a tool is about to be called (
PreToolUse
), a tool returned a result (
PostToolUse
), a subagent started or stopped, the agent is idle, or execution finished. See the
full list of events
.
2
The SDK collects registered hooks
The SDK checks for hooks registered for that event type. This includes callback hooks you pass in
options.hooks
and shell command hooks from settings files when the corresponding
settingSources
or
setting_sources
entry is enabled, which it is for default
query()
options.
3
Matchers filter which hooks run
If a hook has a
matcher
pattern (like
"Write|Edit"
), the SDK tests it against the event’s target (for example, the tool name). Hooks without a matcher run for every event of that type.
4
Callback functions execute
Each matching hook’s
callback function
receives input about what’s happening: the tool name, its arguments, the session ID, and other event-specific details.
5
Your callback returns a decision
After performing any operations (logging, API calls, validation), your callback returns an
output object
that tells the agent what to do: allow the operation, block it, modify the input, or inject context into the conversation.
The following example puts these steps together. It registers a
PreToolUse
hook (step 1) with a
"Write|Edit"
matcher (step 3) so the callback only fires for file-writing tools. When triggered, the callback receives the tool’s input (step 4), checks if the file path targets a
.env
file, and returns
permissionDecision: "deny"
to block the operation (step 5):
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
AssistantMessage,
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
ResultMessage,
)
# Define a hook callback that receives tool call details
async
def
protect_env_files
(
input_data
,
tool_use_id
,
context
):
# Extract the file path from the tool's input arguments
file_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
file_name
=
file_path.split(
"/"
)[
-
1
]
# Block the operation if targeting a .env file
if
file_name
==
".env"
:
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Cannot modify .env files"
,
}
}
# Return empty object to allow the operation
return
{}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
# Register the hook for PreToolUse events
# The matcher filters to only Write and Edit tool calls
"PreToolUse"
: [HookMatcher(
matcher
=
"Write|Edit"
,
hooks
=
[protect_env_files])]
}
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Update the database configuration"
)
async
for
message
in
client.receive_response():
# Filter for assistant and result messages
if
isinstance
(message, (AssistantMessage, ResultMessage)):
print
(message)
asyncio.run(main())
​
Available hooks
The SDK provides hooks for different stages of agent execution. Some hooks are available in both SDKs, while others are TypeScript-only.
Hook Event
Python SDK
TypeScript SDK
What triggers it
Example use case
PreToolUse
Yes
Yes
Tool call request (can block or modify)
Block dangerous shell commands
PostToolUse
Yes
Yes
Tool execution result
Log all file changes to audit trail
PostToolUseFailure
Yes
Yes
Tool execution failure
Handle or log tool errors
PostToolBatch
No
Yes
A full batch of tool calls resolves, once per batch before the next model call
Inject conventions once for the whole batch
UserPromptSubmit
Yes
Yes
User prompt submission
Inject additional context into prompts
Stop
Yes
Yes
Agent execution stop
Save session state before exit
SubagentStart
Yes
Yes
Subagent initialization
Track parallel task spawning
SubagentStop
Yes
Yes
Subagent completion
Aggregate results from parallel tasks
PreCompact
Yes
Yes
Conversation compaction request
Archive full transcript before summarizing
PermissionRequest
Yes
Yes
Permission dialog would be displayed
Custom permission handling
SessionStart
No
Yes
Session initialization
Initialize logging and telemetry
SessionEnd
No
Yes
Session termination
Clean up temporary resources
Notification
Yes
Yes
Agent status messages
Send agent status updates to Slack or PagerDuty
Setup
No
Yes
Session setup/maintenance
Run initialization tasks
TeammateIdle
No
Yes
Teammate becomes idle
Reassign work or notify
TaskCompleted
No
Yes
Background task completes
Aggregate results from parallel tasks
ConfigChange
No
Yes
Configuration file changes
Reload settings dynamically
WorktreeCreate
No
Yes
Git worktree created
Track isolated workspaces
WorktreeRemove
No
Yes
Git worktree removed
Clean up workspace resources
​
Configure hooks
To configure a hook, pass it in the
hooks
field of your agent options (
ClaudeAgentOptions
in Python, the
options
object in TypeScript):
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
"Bash"
,
hooks
=
[my_callback])]}
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Your prompt"
)
async
for
message
in
client.receive_response():
print
(message)
The
hooks
option is a dictionary (Python) or object (TypeScript) where:
Keys
are
hook event names
(e.g.,
'PreToolUse'
,
'PostToolUse'
,
'Stop'
)
Values
are arrays of
matchers
, each containing an optional filter pattern and your
callback functions
​
Matchers
Use matchers to filter when your callbacks fire. The
matcher
field is a regex string that matches against a different value depending on the hook event type. For example, tool-based hooks match against the tool name, while
Notification
hooks match against the notification type. See the
Claude Code hooks reference
for the full list of matcher values for each event type.
Option
Type
Default
Description
matcher
string
undefined
Regex pattern matched against the event’s filter field. For tool hooks, this is the tool name. Built-in tools include
Bash
,
Read
,
Write
,
Edit
,
Glob
,
Grep
,
WebFetch
,
Agent
, and others (see
Tool Input Types
for the full list). MCP tools use the pattern
mcp__<server>__<action>
.
hooks
HookCallback[]
-
Required. Array of callback functions to execute when the pattern matches
timeout
number
60
Timeout in seconds
Use the
matcher
pattern to target specific tools whenever possible. A matcher with
'Bash'
only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event. Note that for tool-based hooks, matchers only filter by
tool name
, not by file paths or other arguments. To filter by file path, check
tool_input.file_path
inside your callback.
Discovering tool names:
See
Tool Input Types
for the full list of built-in tool names, or add a hook without a matcher to log all tool calls your session makes.
MCP tool naming:
MCP tools always start with
mcp__
followed by the server name and action:
mcp__<server>__<action>
. For example, if you configure a server named
playwright
, its tools will be named
mcp__playwright__browser_screenshot
,
mcp__playwright__browser_click
, etc. The server name comes from the key you use in the
mcpServers
configuration.
​
Callback functions
​
Inputs
Every hook callback receives three arguments:
Input data:
a typed object containing event details. Each hook type has its own input shape (for example,
PreToolUseHookInput
includes
tool_name
and
tool_input
, while
NotificationHookInput
includes
message
). See the full type definitions in the
TypeScript
and
Python
SDK references.
All hook inputs share
session_id
,
cwd
, and
hook_event_name
.
agent_id
and
agent_type
are populated when the hook fires inside a subagent. In TypeScript, these are on the base hook input and available to all hook types. In Python, they are on
PreToolUse
,
PostToolUse
, and
PostToolUseFailure
only.
Tool use ID
(
str | None
/
string | undefined
): correlates
PreToolUse
and
PostToolUse
events for the same tool call.
Context:
in TypeScript, contains a
signal
property (
AbortSignal
) for cancellation. In Python, this argument is reserved for future use.
​
Outputs
Your callback returns an object with two categories of fields:
Top-level fields
work the same on every event:
systemMessage
shows a message to the user, and
continue
(
continue_
in Python) determines whether the agent keeps running after this hook.
hookSpecificOutput
controls the current operation. The fields inside depend on the hook event type. For
PreToolUse
hooks, this is where you set
permissionDecision
(
"allow"
,
"deny"
,
"ask"
, or
"defer"
),
permissionDecisionReason
, and
updatedInput
. Returning
"defer"
ends the query so you can
resume it later
. For
PostToolUse
hooks, you can set
additionalContext
to append information to the tool result, or
updatedToolOutput
to replace the tool’s output entirely before Claude sees it.
Return
{}
to allow the operation without changes. SDK callback hooks use the same JSON output format as
Claude Code shell command hooks
, which documents every field and event-specific option. For the SDK type definitions, see the
TypeScript
and
Python
SDK references.
When multiple hooks or permission rules apply,
deny
takes priority over
defer
, which takes priority over
ask
, which takes priority over
allow
. If any hook returns
deny
, the operation is blocked regardless of other hooks.
​
Asynchronous output
By default, the agent waits for your hook to return before proceeding. If your hook performs a side effect (logging, sending a webhook) and doesn’t need to influence the agent’s behavior, you can return an async output instead. This tells the agent to continue immediately without waiting for the hook to finish:
Python
TypeScript
async
def
async_hook
(
input_data
,
tool_use_id
,
context
):
# Start a background task, then return immediately
asyncio.create_task(send_to_logging_service(input_data))
return
{
"async_"
:
True
,
"asyncTimeout"
:
30000
}
Field
Type
Description
async
true
Signals async mode. The agent proceeds without waiting. In Python, use
async_
to avoid the reserved keyword.
asyncTimeout
number
Optional timeout in milliseconds for the background operation
Async outputs cannot block, modify, or inject context into the operation since the agent has already moved on. Use them only for side effects like logging, metrics, or notifications.
​
Examples
​
Modify tool input
This example intercepts Write tool calls and rewrites the
file_path
argument to prepend
/sandbox
, redirecting all file writes to a sandboxed directory. The callback returns
updatedInput
with the modified path and
permissionDecision: 'allow'
to auto-approve the rewritten operation:
Python
TypeScript
async
def
redirect_to_sandbox
(
input_data
,
tool_use_id
,
context
):
if
input_data[
"hook_event_name"
]
!=
"PreToolUse"
:
return
{}
if
input_data[
"tool_name"
]
==
"Write"
:
original_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"allow"
,
"updatedInput"
: {
**
input_data[
"tool_input"
],
"file_path"
:
f
"/sandbox
{
original_path
}
"
,
},
}
}
return
{}
When using
updatedInput
, you must also include
permissionDecision: 'allow'
to auto-approve the modified input or
permissionDecision: 'ask'
to show it to the user. With
'defer'
,
updatedInput
is ignored. Always return a new object rather than mutating the original
tool_input
.
​
Add context and block a tool
This example blocks writes to the
/etc
directory and explains why to both the model and the user:
permissionDecision: 'deny'
stops the tool call.
permissionDecisionReason
tells the model why, so it avoids retrying.
systemMessage
shows the user what happened.
Python
TypeScript
async
def
block_etc_writes
(
input_data
,
tool_use_id
,
context
):
file_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
if
file_path.startswith(
"/etc"
):
return
{
# Top-level field: message shown to the user
"systemMessage"
:
"Remember: system directories like /etc are protected."
,
# hookSpecificOutput: block the operation
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Writing to /etc is not allowed"
,
},
}
return
{}
​
Auto-approve specific tools
By default, the agent may prompt for permission before using certain tools. This example auto-approves read-only filesystem tools (Read, Glob, Grep) by returning
permissionDecision: 'allow'
, letting them run without user confirmation while leaving all other tools subject to normal permission checks:
Python
TypeScript
async
def
auto_approve_read_only
(
input_data
,
tool_use_id
,
context
):
if
input_data[
"hook_event_name"
]
!=
"PreToolUse"
:
return
{}
read_only_tools
=
[
"Read"
,
"Glob"
,
"Grep"
]
if
input_data[
"tool_name"
]
in
read_only_tools:
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"allow"
,
"permissionDecisionReason"
:
"Read-only tool auto-approved"
,
}
}
return
{}
​
Register multiple hooks
When an event fires, all matching hooks run in parallel. For permission decisions, the most restrictive result wins: a single
deny
blocks the tool call regardless of what the other hooks return. Because completion order is non-deterministic, write each hook to act independently rather than relying on another hook having run first.
The example below registers three independent checks for every tool call:
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
hooks
=
[authorization_check]),
HookMatcher(
hooks
=
[input_validator]),
HookMatcher(
hooks
=
[audit_logger]),
]
}
)
​
Filter with regex matchers
Use regex patterns to match multiple tools. This example registers three matchers with different scopes: the first triggers
file_security_hook
only for file modification tools, the second triggers
mcp_audit_hook
for any MCP tool (tools whose names start with
mcp__
), and the third triggers
global_logger
for every tool call regardless of name:
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
# Match file modification tools
HookMatcher(
matcher
=
"Write|Edit|Delete"
,
hooks
=
[file_security_hook]),
# Match all MCP tools
HookMatcher(
matcher
=
"^mcp__"
,
hooks
=
[mcp_audit_hook]),
# Match everything (no matcher)
HookMatcher(
hooks
=
[global_logger]),
]
}
)
​
Track subagent activity
Use
SubagentStop
hooks to monitor when subagents finish their work. See the full input type in the
TypeScript
and
Python
SDK references. This example logs a summary each time a subagent completes:
Python
TypeScript
async
def
subagent_tracker
(
input_data
,
tool_use_id
,
context
):
# Log subagent details when it finishes
print
(
f
"[SUBAGENT] Completed:
{
input_data[
'agent_id'
]
}
"
)
print
(
f
"  Transcript:
{
input_data[
'agent_transcript_path'
]
}
"
)
print
(
f
"  Tool use ID:
{
tool_use_id
}
"
)
print
(
f
"  Stop hook active:
{
input_data.get(
'stop_hook_active'
)
}
"
)
return
{}
options
=
ClaudeAgentOptions(
hooks
=
{
"SubagentStop"
: [HookMatcher(
hooks
=
[subagent_tracker])]}
)
​
Make HTTP requests from hooks
Hooks can perform asynchronous operations like HTTP requests. Catch errors inside your hook instead of letting them propagate, since an unhandled exception can interrupt the agent.
This example sends a webhook after each tool completes, logging which tool ran and when. The hook catches errors so a failed webhook doesn’t interrupt the agent:
Python
TypeScript
import
asyncio
import
json
import
urllib.request
from
datetime
import
datetime
def
_send_webhook
(
tool_name
):
"""Synchronous helper that POSTs tool usage data to an external webhook."""
data
=
json.dumps(
{
"tool"
: tool_name,
"timestamp"
: datetime.now().isoformat(),
}
).encode()
req
=
urllib.request.Request(
"https://api.example.com/webhook"
,
data
=
data,
headers
=
{
"Content-Type"
:
"application/json"
},
method
=
"POST"
,
)
urllib.request.urlopen(req)
async
def
webhook_notifier
(
input_data
,
tool_use_id
,
context
):
# Only fire after a tool completes (PostToolUse), not before
if
input_data[
"hook_event_name"
]
!=
"PostToolUse"
:
return
{}
try
:
# Run the blocking HTTP call in a thread to avoid blocking the event loop
await
asyncio.to_thread(_send_webhook, input_data[
"tool_name"
])
except
Exception
as
e:
# Log the error but don't raise. A failed webhook shouldn't stop the agent
print
(
f
"Webhook request failed:
{
e
}
"
)
return
{}
​
Forward notifications to Slack
Use
Notification
hooks to receive system notifications from the agent and forward them to external services. Notifications fire for specific event types:
permission_prompt
(Claude needs permission),
idle_prompt
(Claude is waiting for input),
auth_success
(authentication completed),
elicitation_dialog
(Claude is prompting the user),
elicitation_response
(the user answered an elicitation), and
elicitation_complete
(an elicitation closed). Each notification includes a
message
field with a human-readable description and optionally a
title
.
This example forwards every notification to a Slack channel. It requires a
Slack incoming webhook URL
, which you create by adding an app to your Slack workspace and enabling incoming webhooks:
Python
TypeScript
import
asyncio
import
json
import
urllib.request
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, HookMatcher
def
_send_slack_notification
(
message
):
"""Synchronous helper that sends a message to Slack via incoming webhook."""
data
=
json.dumps({
"text"
:
f
"Agent status:
{
message
}
"
}).encode()
req
=
urllib.request.Request(
"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
,
data
=
data,
headers
=
{
"Content-Type"
:
"application/json"
},
method
=
"POST"
,
)
urllib.request.urlopen(req)
async
def
notification_handler
(
input_data
,
tool_use_id
,
context
):
try
:
# Run the blocking HTTP call in a thread to avoid blocking the event loop
await
asyncio.to_thread(_send_slack_notification, input_data.get(
"message"
,
""
))
except
Exception
as
e:
print
(
f
"Failed to send notification:
{
e
}
"
)
# Return empty object. Notification hooks don't modify agent behavior
return
{}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
# Register the hook for Notification events (no matcher needed)
"Notification"
: [HookMatcher(
hooks
=
[notification_handler])],
},
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Analyze this codebase"
)
async
for
message
in
client.receive_response():
print
(message)
asyncio.run(main())
​
Fix common issues
​
Hook not firing
Verify the hook event name is correct and case-sensitive (
PreToolUse
, not
preToolUse
)
Check that your matcher pattern matches the tool name exactly
Ensure the hook is under the correct event type in
options.hooks
For non-tool hooks like
Stop
and
SubagentStop
, matchers match against different fields (see
matcher patterns
)
Hooks may not fire when the agent hits the
max_turns
limit because the session ends before hooks can execute
​
Matcher not filtering as expected
Matchers only match
tool names
, not file paths or other arguments. To filter by file path, check
tool_input.file_path
inside your hook:
const
myHook
:
HookCallback
=
async
(
input
,
toolUseID
, {
signal
})
=>
{
const
preInput
=
input
as
PreToolUseHookInput
;
const
toolInput
=
preInput
.
tool_input
as
Record
<
string
,
unknown
>;
const
filePath
=
toolInput
?.
file_path
as
string
;
if
(
!
filePath
?.
endsWith
(
".md"
))
return
{};
// Skip non-markdown files
// Process markdown files...
return
{};
};
​
Hook timeout
Increase the
timeout
value in the
HookMatcher
configuration
Use the
AbortSignal
from the third callback argument to handle cancellation gracefully in TypeScript
​
Tool blocked unexpectedly
Check all
PreToolUse
hooks for
permissionDecision: 'deny'
returns
Add logging to your hooks to see what
permissionDecisionReason
they’re returning
Verify matcher patterns aren’t too broad (an empty matcher matches all tools)
​
Modified input not applied
Ensure
updatedInput
is inside
hookSpecificOutput
, not at the top level:
return
{
hookSpecificOutput:
{
hookEventName:
"PreToolUse"
,
permissionDecision:
"allow"
,
updatedInput:
{
command:
"new command"
}
}
};
You must also return
permissionDecision: 'allow'
or
'ask'
for the input modification to take effect
Include
hookEventName
in
hookSpecificOutput
to identify which hook type the output is for
​
Session hooks not available in Python
SessionStart
and
SessionEnd
can be registered as SDK callback hooks in TypeScript, but are not available in the Python SDK (
HookEvent
omits them). In Python, they are only available as
shell command hooks
defined in settings files (for example,
.claude/settings.json
). To load shell command hooks from your SDK application, include the appropriate setting source with
setting_sources
or
settingSources
:
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Loads .claude/settings.json including hooks
)
To run initialization logic as a Python SDK callback instead, use the first message from
client.receive_response()
as your trigger.
​
Subagent permission prompts multiplying
When spawning multiple subagents, each one may request permissions separately. Subagents do not automatically inherit parent agent permissions. To avoid repeated prompts, use
PreToolUse
hooks to auto-approve specific tools, or configure permission rules that apply to subagent sessions.
​
Recursive hook loops with subagents
A
UserPromptSubmit
hook that spawns subagents can create infinite loops if those subagents trigger the same hook. To prevent this:
Check for a subagent indicator in the hook input before spawning
Use a shared variable or session state to track whether you’re already inside a subagent
Scope hooks to only run for the top-level agent session
​
systemMessage not appearing in output
The
systemMessage
field shows a message to the user, not the model. By default the SDK does not surface hook output in the message stream, so the message may not appear unless you set
includeHookEvents
(
include_hook_events
in Python). To pass context to the model instead, return
additionalContext
.
If you need to surface hook decisions to your application reliably, log them separately or use a dedicated output channel.
​
Related resources
Claude Code hooks reference
: full JSON input/output schemas, event documentation, and matcher patterns
Claude Code hooks guide
: shell command hook examples and walkthroughs
TypeScript SDK reference
: hook types, input/output definitions, and configuration options
Python SDK reference
: hook types, input/output definitions, and configuration options
Permissions
: control what your agent can do
Custom tools
: build tools to extend agent capabilities
Was this page helpful?
Yes
No
Configure permissions
Rewind file changes with checkpointing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/hooks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Intercept and control agent behavior with hooks
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Intercept and control agent behavior with hooks
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Hooks are callback functions that run your code in response to agent events, like a tool being called, a session starting, or execution stopping. With hooks, you can:
Block dangerous operations
before they execute, like destructive shell commands or unauthorized file access
Log and audit
every tool call for compliance, debugging, or analytics
Transform inputs and outputs
to sanitize data, inject credentials, or redirect file paths
Require human approval
for sensitive actions like database writes or API calls
Track session lifecycle
to manage state, clean up resources, or send notifications
This guide covers how hooks work, how to configure them, and provides examples for common patterns like blocking tools, modifying inputs, and forwarding notifications.
​
How hooks work
1
An event fires
Something happens during agent execution and the SDK fires an event: a tool is about to be called (
PreToolUse
), a tool returned a result (
PostToolUse
), a subagent started or stopped, the agent is idle, or execution finished. See the
full list of events
.
2
The SDK collects registered hooks
The SDK checks for hooks registered for that event type. This includes callback hooks you pass in
options.hooks
and shell command hooks from settings files when the corresponding
settingSources
or
setting_sources
entry is enabled, which it is for default
query()
options.
3
Matchers filter which hooks run
If a hook has a
matcher
pattern (like
"Write|Edit"
), the SDK tests it against the event’s target (for example, the tool name). Hooks without a matcher run for every event of that type.
4
Callback functions execute
Each matching hook’s
callback function
receives input about what’s happening: the tool name, its arguments, the session ID, and other event-specific details.
5
Your callback returns a decision
After performing any operations (logging, API calls, validation), your callback returns an
output object
that tells the agent what to do: allow the operation, block it, modify the input, or inject context into the conversation.
The following example puts these steps together. It registers a
PreToolUse
hook (step 1) with a
"Write|Edit"
matcher (step 3) so the callback only fires for file-writing tools. When triggered, the callback receives the tool’s input (step 4), checks if the file path targets a
.env
file, and returns
permissionDecision: "deny"
to block the operation (step 5):
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
(
AssistantMessage,
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
ResultMessage,
)
# Define a hook callback that receives tool call details
async
def
protect_env_files
(
input_data
,
tool_use_id
,
context
):
# Extract the file path from the tool's input arguments
file_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
file_name
=
file_path.split(
"/"
)[
-
1
]
# Block the operation if targeting a .env file
if
file_name
==
".env"
:
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Cannot modify .env files"
,
}
}
# Return empty object to allow the operation
return
{}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
# Register the hook for PreToolUse events
# The matcher filters to only Write and Edit tool calls
"PreToolUse"
: [HookMatcher(
matcher
=
"Write|Edit"
,
hooks
=
[protect_env_files])]
}
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Update the database configuration"
)
async
for
message
in
client.receive_response():
# Filter for assistant and result messages
if
isinstance
(message, (AssistantMessage, ResultMessage)):
print
(message)
asyncio.run(main())
​
Available hooks
The SDK provides hooks for different stages of agent execution. Some hooks are available in both SDKs, while others are TypeScript-only.
Hook Event
Python SDK
TypeScript SDK
What triggers it
Example use case
PreToolUse
Yes
Yes
Tool call request (can block or modify)
Block dangerous shell commands
PostToolUse
Yes
Yes
Tool execution result
Log all file changes to audit trail
PostToolUseFailure
Yes
Yes
Tool execution failure
Handle or log tool errors
PostToolBatch
No
Yes
A full batch of tool calls resolves, once per batch before the next model call
Inject conventions once for the whole batch
UserPromptSubmit
Yes
Yes
User prompt submission
Inject additional context into prompts
Stop
Yes
Yes
Agent execution stop
Save session state before exit
SubagentStart
Yes
Yes
Subagent initialization
Track parallel task spawning
SubagentStop
Yes
Yes
Subagent completion
Aggregate results from parallel tasks
PreCompact
Yes
Yes
Conversation compaction request
Archive full transcript before summarizing
PermissionRequest
Yes
Yes
Permission dialog would be displayed
Custom permission handling
SessionStart
No
Yes
Session initialization
Initialize logging and telemetry
SessionEnd
No
Yes
Session termination
Clean up temporary resources
Notification
Yes
Yes
Agent status messages
Send agent status updates to Slack or PagerDuty
Setup
No
Yes
Session setup/maintenance
Run initialization tasks
TeammateIdle
No
Yes
Teammate becomes idle
Reassign work or notify
TaskCompleted
No
Yes
Background task completes
Aggregate results from parallel tasks
ConfigChange
No
Yes
Configuration file changes
Reload settings dynamically
WorktreeCreate
No
Yes
Git worktree created
Track isolated workspaces
WorktreeRemove
No
Yes
Git worktree removed
Clean up workspace resources
​
Configure hooks
To configure a hook, pass it in the
hooks
field of your agent options (
ClaudeAgentOptions
in Python, the
options
object in TypeScript):
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [HookMatcher(
matcher
=
"Bash"
,
hooks
=
[my_callback])]}
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Your prompt"
)
async
for
message
in
client.receive_response():
print
(message)
The
hooks
option is a dictionary (Python) or object (TypeScript) where:
Keys
are
hook event names
(e.g.,
'PreToolUse'
,
'PostToolUse'
,
'Stop'
)
Values
are arrays of
matchers
, each containing an optional filter pattern and your
callback functions
​
Matchers
Use matchers to filter when your callbacks fire. The
matcher
field is a regex string that matches against a different value depending on the hook event type. For example, tool-based hooks match against the tool name, while
Notification
hooks match against the notification type. See the
Claude Code hooks reference
for the full list of matcher values for each event type.
Option
Type
Default
Description
matcher
string
undefined
Regex pattern matched against the event’s filter field. For tool hooks, this is the tool name. Built-in tools include
Bash
,
Read
,
Write
,
Edit
,
Glob
,
Grep
,
WebFetch
,
Agent
, and others (see
Tool Input Types
for the full list). MCP tools use the pattern
mcp__<server>__<action>
.
hooks
HookCallback[]
-
Required. Array of callback functions to execute when the pattern matches
timeout
number
60
Timeout in seconds
Use the
matcher
pattern to target specific tools whenever possible. A matcher with
'Bash'
only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event. Note that for tool-based hooks, matchers only filter by
tool name
, not by file paths or other arguments. To filter by file path, check
tool_input.file_path
inside your callback.
Discovering tool names:
See
Tool Input Types
for the full list of built-in tool names, or add a hook without a matcher to log all tool calls your session makes.
MCP tool naming:
MCP tools always start with
mcp__
followed by the server name and action:
mcp__<server>__<action>
. For example, if you configure a server named
playwright
, its tools will be named
mcp__playwright__browser_screenshot
,
mcp__playwright__browser_click
, etc. The server name comes from the key you use in the
mcpServers
configuration.
​
Callback functions
​
Inputs
Every hook callback receives three arguments:
Input data:
a typed object containing event details. Each hook type has its own input shape (for example,
PreToolUseHookInput
includes
tool_name
and
tool_input
, while
NotificationHookInput
includes
message
). See the full type definitions in the
TypeScript
and
Python
SDK references.
All hook inputs share
session_id
,
cwd
, and
hook_event_name
.
agent_id
and
agent_type
are populated when the hook fires inside a subagent. In TypeScript, these are on the base hook input and available to all hook types. In Python, they are on
PreToolUse
,
PostToolUse
, and
PostToolUseFailure
only.
Tool use ID
(
str | None
/
string | undefined
): correlates
PreToolUse
and
PostToolUse
events for the same tool call.
Context:
in TypeScript, contains a
signal
property (
AbortSignal
) for cancellation. In Python, this argument is reserved for future use.
​
Outputs
Your callback returns an object with two categories of fields:
Top-level fields
work the same on every event:
systemMessage
shows a message to the user, and
continue
(
continue_
in Python) determines whether the agent keeps running after this hook.
hookSpecificOutput
controls the current operation. The fields inside depend on the hook event type. For
PreToolUse
hooks, this is where you set
permissionDecision
(
"allow"
,
"deny"
,
"ask"
, or
"defer"
),
permissionDecisionReason
, and
updatedInput
. Returning
"defer"
ends the query so you can
resume it later
. For
PostToolUse
hooks, you can set
additionalContext
to append information to the tool result, or
updatedToolOutput
to replace the tool’s output entirely before Claude sees it.
Return
{}
to allow the operation without changes. SDK callback hooks use the same JSON output format as
Claude Code shell command hooks
, which documents every field and event-specific option. For the SDK type definitions, see the
TypeScript
and
Python
SDK references.
When multiple hooks or permission rules apply,
deny
takes priority over
defer
, which takes priority over
ask
, which takes priority over
allow
. If any hook returns
deny
, the operation is blocked regardless of other hooks.
​
Asynchronous output
By default, the agent waits for your hook to return before proceeding. If your hook performs a side effect (logging, sending a webhook) and doesn’t need to influence the agent’s behavior, you can return an async output instead. This tells the agent to continue immediately without waiting for the hook to finish:
Python
TypeScript
async
def
async_hook
(
input_data
,
tool_use_id
,
context
):
# Start a background task, then return immediately
asyncio.create_task(send_to_logging_service(input_data))
return
{
"async_"
:
True
,
"asyncTimeout"
:
30000
}
Field
Type
Description
async
true
Signals async mode. The agent proceeds without waiting. In Python, use
async_
to avoid the reserved keyword.
asyncTimeout
number
Optional timeout in milliseconds for the background operation
Async outputs cannot block, modify, or inject context into the operation since the agent has already moved on. Use them only for side effects like logging, metrics, or notifications.
​
Examples
​
Modify tool input
This example intercepts Write tool calls and rewrites the
file_path
argument to prepend
/sandbox
, redirecting all file writes to a sandboxed directory. The callback returns
updatedInput
with the modified path and
permissionDecision: 'allow'
to auto-approve the rewritten operation:
Python
TypeScript
async
def
redirect_to_sandbox
(
input_data
,
tool_use_id
,
context
):
if
input_data[
"hook_event_name"
]
!=
"PreToolUse"
:
return
{}
if
input_data[
"tool_name"
]
==
"Write"
:
original_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"allow"
,
"updatedInput"
: {
**
input_data[
"tool_input"
],
"file_path"
:
f
"/sandbox
{
original_path
}
"
,
},
}
}
return
{}
When using
updatedInput
, you must also include
permissionDecision: 'allow'
to auto-approve the modified input or
permissionDecision: 'ask'
to show it to the user. With
'defer'
,
updatedInput
is ignored. Always return a new object rather than mutating the original
tool_input
.
​
Add context and block a tool
This example blocks writes to the
/etc
directory and explains why to both the model and the user:
permissionDecision: 'deny'
stops the tool call.
permissionDecisionReason
tells the model why, so it avoids retrying.
systemMessage
shows the user what happened.
Python
TypeScript
async
def
block_etc_writes
(
input_data
,
tool_use_id
,
context
):
file_path
=
input_data[
"tool_input"
].get(
"file_path"
,
""
)
if
file_path.startswith(
"/etc"
):
return
{
# Top-level field: message shown to the user
"systemMessage"
:
"Remember: system directories like /etc are protected."
,
# hookSpecificOutput: block the operation
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Writing to /etc is not allowed"
,
},
}
return
{}
​
Auto-approve specific tools
By default, the agent may prompt for permission before using certain tools. This example auto-approves read-only filesystem tools (Read, Glob, Grep) by returning
permissionDecision: 'allow'
, letting them run without user confirmation while leaving all other tools subject to normal permission checks:
Python
TypeScript
async
def
auto_approve_read_only
(
input_data
,
tool_use_id
,
context
):
if
input_data[
"hook_event_name"
]
!=
"PreToolUse"
:
return
{}
read_only_tools
=
[
"Read"
,
"Glob"
,
"Grep"
]
if
input_data[
"tool_name"
]
in
read_only_tools:
return
{
"hookSpecificOutput"
: {
"hookEventName"
: input_data[
"hook_event_name"
],
"permissionDecision"
:
"allow"
,
"permissionDecisionReason"
:
"Read-only tool auto-approved"
,
}
}
return
{}
​
Register multiple hooks
When an event fires, all matching hooks run in parallel. For permission decisions, the most restrictive result wins: a single
deny
blocks the tool call regardless of what the other hooks return. Because completion order is non-deterministic, write each hook to act independently rather than relying on another hook having run first.
The example below registers three independent checks for every tool call:
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
HookMatcher(
hooks
=
[authorization_check]),
HookMatcher(
hooks
=
[input_validator]),
HookMatcher(
hooks
=
[audit_logger]),
]
}
)
​
Filter with regex matchers
Use regex patterns to match multiple tools. This example registers three matchers with different scopes: the first triggers
file_security_hook
only for file modification tools, the second triggers
mcp_audit_hook
for any MCP tool (tools whose names start with
mcp__
), and the third triggers
global_logger
for every tool call regardless of name:
Python
TypeScript
options
=
ClaudeAgentOptions(
hooks
=
{
"PreToolUse"
: [
# Match file modification tools
HookMatcher(
matcher
=
"Write|Edit|Delete"
,
hooks
=
[file_security_hook]),
# Match all MCP tools
HookMatcher(
matcher
=
"^mcp__"
,
hooks
=
[mcp_audit_hook]),
# Match everything (no matcher)
HookMatcher(
hooks
=
[global_logger]),
]
}
)
​
Track subagent activity
Use
SubagentStop
hooks to monitor when subagents finish their work. See the full input type in the
TypeScript
and
Python
SDK references. This example logs a summary each time a subagent completes:
Python
TypeScript
async
def
subagent_tracker
(
input_data
,
tool_use_id
,
context
):
# Log subagent details when it finishes
print
(
f
"[SUBAGENT] Completed:
{
input_data[
'agent_id'
]
}
"
)
print
(
f
"  Transcript:
{
input_data[
'agent_transcript_path'
]
}
"
)
print
(
f
"  Tool use ID:
{
tool_use_id
}
"
)
print
(
f
"  Stop hook active:
{
input_data.get(
'stop_hook_active'
)
}
"
)
return
{}
options
=
ClaudeAgentOptions(
hooks
=
{
"SubagentStop"
: [HookMatcher(
hooks
=
[subagent_tracker])]}
)
​
Make HTTP requests from hooks
Hooks can perform asynchronous operations like HTTP requests. Catch errors inside your hook instead of letting them propagate, since an unhandled exception can interrupt the agent.
This example sends a webhook after each tool completes, logging which tool ran and when. The hook catches errors so a failed webhook doesn’t interrupt the agent:
Python
TypeScript
import
asyncio
import
json
import
urllib.request
from
datetime
import
datetime
def
_send_webhook
(
tool_name
):
"""Synchronous helper that POSTs tool usage data to an external webhook."""
data
=
json.dumps(
{
"tool"
: tool_name,
"timestamp"
: datetime.now().isoformat(),
}
).encode()
req
=
urllib.request.Request(
"https://api.example.com/webhook"
,
data
=
data,
headers
=
{
"Content-Type"
:
"application/json"
},
method
=
"POST"
,
)
urllib.request.urlopen(req)
async
def
webhook_notifier
(
input_data
,
tool_use_id
,
context
):
# Only fire after a tool completes (PostToolUse), not before
if
input_data[
"hook_event_name"
]
!=
"PostToolUse"
:
return
{}
try
:
# Run the blocking HTTP call in a thread to avoid blocking the event loop
await
asyncio.to_thread(_send_webhook, input_data[
"tool_name"
])
except
Exception
as
e:
# Log the error but don't raise. A failed webhook shouldn't stop the agent
print
(
f
"Webhook request failed:
{
e
}
"
)
return
{}
​
Forward notifications to Slack
Use
Notification
hooks to receive system notifications from the agent and forward them to external services. Notifications fire for specific event types:
permission_prompt
(Claude needs permission),
idle_prompt
(Claude is waiting for input),
auth_success
(authentication completed),
elicitation_dialog
(Claude is prompting the user),
elicitation_response
(the user answered an elicitation), and
elicitation_complete
(an elicitation closed). Each notification includes a
message
field with a human-readable description and optionally a
title
.
This example forwards every notification to a Slack channel. It requires a
Slack incoming webhook URL
, which you create by adding an app to your Slack workspace and enabling incoming webhooks:
Python
TypeScript
import
asyncio
import
json
import
urllib.request
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions, HookMatcher
def
_send_slack_notification
(
message
):
"""Synchronous helper that sends a message to Slack via incoming webhook."""
data
=
json.dumps({
"text"
:
f
"Agent status:
{
message
}
"
}).encode()
req
=
urllib.request.Request(
"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
,
data
=
data,
headers
=
{
"Content-Type"
:
"application/json"
},
method
=
"POST"
,
)
urllib.request.urlopen(req)
async
def
notification_handler
(
input_data
,
tool_use_id
,
context
):
try
:
# Run the blocking HTTP call in a thread to avoid blocking the event loop
await
asyncio.to_thread(_send_slack_notification, input_data.get(
"message"
,
""
))
except
Exception
as
e:
print
(
f
"Failed to send notification:
{
e
}
"
)
# Return empty object. Notification hooks don't modify agent behavior
return
{}
async
def
main
():
options
=
ClaudeAgentOptions(
hooks
=
{
# Register the hook for Notification events (no matcher needed)
"Notification"
: [HookMatcher(
hooks
=
[notification_handler])],
},
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
await
client.query(
"Analyze this codebase"
)
async
for
message
in
client.receive_response():
print
(message)
asyncio.run(main())
​
Fix common issues
​
Hook not firing
Verify the hook event name is correct and case-sensitive (
PreToolUse
, not
preToolUse
)
Check that your matcher pattern matches the tool name exactly
Ensure the hook is under the correct event type in
options.hooks
For non-tool hooks like
Stop
and
SubagentStop
, matchers match against different fields (see
matcher patterns
)
Hooks may not fire when the agent hits the
max_turns
limit because the session ends before hooks can execute
​
Matcher not filtering as expected
Matchers only match
tool names
, not file paths or other arguments. To filter by file path, check
tool_input.file_path
inside your hook:
const
myHook
:
HookCallback
=
async
(
input
,
toolUseID
, {
signal
})
=>
{
const
preInput
=
input
as
PreToolUseHookInput
;
const
toolInput
=
preInput
.
tool_input
as
Record
<
string
,
unknown
>;
const
filePath
=
toolInput
?.
file_path
as
string
;
if
(
!
filePath
?.
endsWith
(
".md"
))
return
{};
// Skip non-markdown files
// Process markdown files...
return
{};
};
​
Hook timeout
Increase the
timeout
value in the
HookMatcher
configuration
Use the
AbortSignal
from the third callback argument to handle cancellation gracefully in TypeScript
​
Tool blocked unexpectedly
Check all
PreToolUse
hooks for
permissionDecision: 'deny'
returns
Add logging to your hooks to see what
permissionDecisionReason
they’re returning
Verify matcher patterns aren’t too broad (an empty matcher matches all tools)
​
Modified input not applied
Ensure
updatedInput
is inside
hookSpecificOutput
, not at the top level:
return
{
hookSpecificOutput:
{
hookEventName:
"PreToolUse"
,
permissionDecision:
"allow"
,
updatedInput:
{
command:
"new command"
}
}
};
You must also return
permissionDecision: 'allow'
or
'ask'
for the input modification to take effect
Include
hookEventName
in
hookSpecificOutput
to identify which hook type the output is for
​
Session hooks not available in Python
SessionStart
and
SessionEnd
can be registered as SDK callback hooks in TypeScript, but are not available in the Python SDK (
HookEvent
omits them). In Python, they are only available as
shell command hooks
defined in settings files (for example,
.claude/settings.json
). To load shell command hooks from your SDK application, include the appropriate setting source with
setting_sources
or
settingSources
:
Python
TypeScript
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Loads .claude/settings.json including hooks
)
To run initialization logic as a Python SDK callback instead, use the first message from
client.receive_response()
as your trigger.
​
Subagent permission prompts multiplying
When spawning multiple subagents, each one may request permissions separately. Subagents do not automatically inherit parent agent permissions. To avoid repeated prompts, use
PreToolUse
hooks to auto-approve specific tools, or configure permission rules that apply to subagent sessions.
​
Recursive hook loops with subagents
A
UserPromptSubmit
hook that spawns subagents can create infinite loops if those subagents trigger the same hook. To prevent this:
Check for a subagent indicator in the hook input before spawning
Use a shared variable or session state to track whether you’re already inside a subagent
Scope hooks to only run for the top-level agent session
​
systemMessage not appearing in output
The
systemMessage
field shows a message to the user, not the model. By default the SDK does not surface hook output in the message stream, so the message may not appear unless you set
includeHookEvents
(
include_hook_events
in Python). To pass context to the model instead, return
additionalContext
.
If you need to surface hook decisions to your application reliably, log them separately or use a dedicated output channel.
​
Related resources
Claude Code hooks reference
: full JSON input/output schemas, event documentation, and matcher patterns
Claude Code hooks guide
: shell command hook examples and walkthroughs
TypeScript SDK reference
: hook types, input/output definitions, and configuration options
Python SDK reference
: hook types, input/output definitions, and configuration options
Permissions
: control what your agent can do
Custom tools
: build tools to extend agent capabilities
Was this page helpful?
Yes
No
Configure permissions
Rewind file changes with checkpointing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/hooks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Use Claude Code features in the SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/claude-code-features</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/claude-code-features</guid>
  <pubDate>Sat, 29 Jun 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Use Claude Code features in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Use Claude Code features in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Agent SDK is built on the same foundation as Claude Code, which means your SDK agents have access to the same filesystem-based features: project instructions (
CLAUDE.md
and rules), skills, hooks, and more.
When you omit
settingSources
,
query()
reads the same filesystem settings as the Claude Code CLI: user, project, and local settings, CLAUDE.md files, and
.claude/
skills, agents, and commands. To run without these, pass
settingSources: []
, which limits the agent to what you configure programmatically. Managed policy settings and the global
~/.claude.json
config are read regardless of this option. See
What settingSources does not control
.
For a conceptual overview of what each feature does and when to use it, see
Extend Claude Code
.
​
Control filesystem settings with settingSources
The setting sources option (
setting_sources
in Python,
settingSources
in TypeScript) controls which filesystem-based settings the SDK loads. Pass an explicit list to opt in to specific sources, or pass an empty array to disable user, project, and local settings.
This example loads both user-level and project-level settings by setting
settingSources
to
["user", "project"]
:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async
for
message
in
query(
prompt
=
"Help me refactor the auth module"
,
options
=
ClaudeAgentOptions(
# "user" loads from ~/.claude/, "project" loads from ./.claude/ in cwd.
# Together they give the agent access to CLAUDE.md, skills, hooks, and
# permissions from both locations.
setting_sources
=
[
"user"
,
"project"
],
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
],
),
):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
hasattr
(block,
"text"
):
print
(block.text)
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"
\n
Result:
{
message.result
}
"
)
Each source loads settings from a specific location, where
<cwd>
is the working directory you pass via the
cwd
option, or the process’s current directory if unset. For the full type definition, see
SettingSource
(TypeScript) or
SettingSource
(Python).
Source
What it loads
Location
"project"
Project CLAUDE.md,
.claude/rules/*.md
, project skills, project hooks, project
settings.json
<cwd>/.claude/
for
settings.json
and hooks;
<cwd>
and every parent directory for CLAUDE.md and rules;
<cwd>
and every parent directory up to the repository root for skills
"user"
User CLAUDE.md,
~/.claude/rules/*.md
, user skills, user settings
~/.claude/
"local"
CLAUDE.local.md,
.claude/settings.local.json
<cwd>/.claude/
for
settings.local.json
;
<cwd>
and every parent directory for CLAUDE.local.md
Omitting
settingSources
is equivalent to
["user", "project", "local"]
.
The
cwd
option determines where the SDK looks for project-level inputs. CLAUDE.md and rules load from
<cwd>
and from every parent directory. Skills load from
<cwd>
and from every parent directory up to the repository root. Project
settings.json
and hooks load only from
<cwd>/.claude/
with no parent-directory fallback.
​
What settingSources does not control
settingSources
covers user, project, and local settings. A few inputs are read regardless of its value:
Input
Behavior
To disable
Managed policy settings
Always loaded when present on the host
Remove the managed settings file
~/.claude.json
global config
Always read
Relocate with
CLAUDE_CONFIG_DIR
in
env
Auto memory at
~/.claude/projects/<project>/memory/
Loaded by default into the system prompt
Set
autoMemoryEnabled: false
in settings, or
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
in
env
Do not rely on default
query()
options for multi-tenant isolation. Because the inputs above are read regardless of
settingSources
, an SDK process can pick up host-level configuration and per-directory memory. For multi-tenant deployments, run each tenant in its own filesystem and set
settingSources: []
plus
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
in
env
. See
Secure deployment
.
​
Project instructions (CLAUDE.md and rules)
CLAUDE.md
files and
.claude/rules/*.md
files give your agent persistent context about your project: coding conventions, build commands, architecture decisions, and instructions. When
settingSources
includes
"project"
(as in the example above), the SDK loads these files into context at session start. The agent then follows your project conventions without you repeating them in every prompt.
​
CLAUDE.md load locations
Level
Location
When loaded
Project (root)
<cwd>/CLAUDE.md
or
<cwd>/.claude/CLAUDE.md
settingSources
includes
"project"
Project rules
<cwd>/.claude/rules/*.md
and
.claude/rules/*.md
in every parent directory
settingSources
includes
"project"
Project (parent dirs)
CLAUDE.md
files in directories above
cwd
settingSources
includes
"project"
, loaded at session start
Project (child dirs)
CLAUDE.md
files in subdirectories of
cwd
settingSources
includes
"project"
, loaded on demand when the agent reads a file in that subtree
Local
<cwd>/CLAUDE.local.md
and
CLAUDE.local.md
in every parent directory
settingSources
includes
"local"
User
~/.claude/CLAUDE.md
settingSources
includes
"user"
User rules
~/.claude/rules/*.md
settingSources
includes
"user"
All levels are additive: if both project and user CLAUDE.md files exist, the agent sees both. There is no hard precedence rule between levels; if instructions conflict, the outcome depends on how Claude interprets them. Write non-conflicting rules, or state precedence explicitly in the more specific file (“These project instructions override any conflicting user-level defaults”).
You can also inject context directly via
systemPrompt
without using CLAUDE.md files. See
Modify system prompts
. Use CLAUDE.md when you want the same context shared between interactive Claude Code sessions and your SDK agents.
For how to structure and organize CLAUDE.md content, see
Manage Claude’s memory
.
​
Skills
Skills are markdown files that give your agent specialized knowledge and invocable workflows. Unlike
CLAUDE.md
(which loads every session), skills load on demand. The agent receives skill descriptions at startup and loads the full content when relevant.
Skills are discovered from the filesystem through
settingSources
. When the
skills
option on
query()
is omitted, discovered user and project skills are enabled and the Skill tool is available, matching CLI behavior. To control which skills are enabled, pass
skills
as
"all"
, a list of skill names, or
[]
to disable all. The SDK enables the Skill tool automatically when
skills
is set, so you do not need to add it to
allowedTools
.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
# Skills in .claude/skills/ are discovered automatically
# when settingSources includes "project"
async
for
message
in
query(
prompt
=
"Review this PR using our code review checklist"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
Skills must be created as filesystem artifacts (
.claude/skills/<name>/SKILL.md
). The SDK does not have a programmatic API for registering skills. See
Agent Skills in the SDK
for full details.
For more on creating and using skills, see
Agent Skills in the SDK
.
​
Hooks
The SDK supports two ways to define hooks, and they run side by side:
Filesystem hooks:
shell commands defined in
settings.json
, loaded when
settingSources
includes the relevant source. These are the same hooks you’d configure for
interactive Claude Code sessions
.
Programmatic hooks:
callback functions passed directly to
query()
. These run in your application process and can return structured decisions. See
Control execution with hooks
.
Both types execute during the same hook lifecycle. If you already have hooks in your project’s
.claude/settings.json
and you set
settingSources: ["project"]
, those hooks run automatically in the SDK with no extra configuration.
Hook callbacks receive the tool input and return a decision dict. Returning
{}
(an empty dict) means allow the tool to proceed. Returning
{"decision": "block", "reason": "..."}
prevents execution and the reason is sent to Claude as the tool result. See the
hooks guide
for the full callback signature and return types.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher, ResultMessage
# PreToolUse hook callback. Positional args:
#   input_data: HookInput dict with tool_name, tool_input, hook_event_name
#   tool_use_id: str | None, the ID of the tool call being intercepted
#   context: HookContext, carries session metadata
async
def
audit_bash
(
input_data
,
tool_use_id
,
context
):
command
=
input_data.get(
"tool_input"
, {}).get(
"command"
,
""
)
if
"rm -rf"
in
command:
return
{
"decision"
:
"block"
,
"reason"
:
"Destructive command blocked"
}
return
{}
# Empty dict: allow the tool to proceed
# Filesystem hooks from .claude/settings.json run automatically
# when settingSources loads them. You can also add programmatic hooks:
async
for
message
in
query(
prompt
=
"Refactor the auth module"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Loads hooks from .claude/settings.json
hooks
=
{
"PreToolUse"
: [
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[audit_bash]),
]
},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
​
When to use which hook type
Hook type
Best for
Filesystem
(
settings.json
)
Sharing hooks between CLI and SDK sessions. Supports
"command"
(shell scripts),
"http"
(POST to an endpoint),
"mcp_tool"
(call a connected MCP server’s tool),
"prompt"
(LLM evaluates a prompt), and
"agent"
(spawns a verifier agent). These fire in the main agent and any subagents it spawns.
Programmatic
(callbacks in
query()
)
Application-specific logic; returning structured decisions; in-process integration. Scoped to the main session only.
The TypeScript SDK supports additional hook events beyond Python, including
SessionStart
,
SessionEnd
,
TeammateIdle
, and
TaskCompleted
. See the
hooks guide
for the full event compatibility table.
For full details on programmatic hooks, see
Control execution with hooks
. For filesystem hook syntax, see
Hooks
.
​
Choose the right feature
The Agent SDK gives you access to several ways to extend your agent’s behavior. If you’re unsure which to use, this table maps common goals to the right approach.
You want to…
Use
SDK surface
Set project conventions your agent always follows
CLAUDE.md
settingSources: ["project"]
loads it automatically
Give the agent reference material it loads when relevant
Skills
settingSources
+
skills
option
Run a reusable workflow (deploy, review, release)
User-invocable skills
settingSources
+
skills
option
Delegate an isolated subtask to a fresh context (research, review)
Subagents
agents
parameter +
allowedTools: ["Agent"]
Coordinate multiple Claude Code instances with shared task lists and direct inter-agent messaging
Agent teams
Not directly configured via SDK options. Agent teams are a CLI feature where one session acts as the team lead, coordinating work across independent teammates
Run deterministic logic on tool calls (audit, block, transform)
Hooks
hooks
parameter with callbacks, or shell scripts loaded via
settingSources
Give Claude structured tool access to an external service
MCP
mcpServers
parameter
Subagents versus agent teams:
Subagents are ephemeral and isolated: fresh conversation, one task, summary returned to parent. Agent teams coordinate multiple independent Claude Code instances that share a task list and message each other directly. Agent teams are a CLI feature. See
What subagents inherit
and the
agent teams comparison
for details.
Every feature you enable adds to your agent’s context window. For per-feature costs and how these features layer together, see
Extend Claude Code
.
​
Related resources
Extend Claude Code
: Conceptual overview of all extension features, with comparison tables and context cost analysis
Skills in the SDK
: Full guide to using skills programmatically
Subagents
: Define and invoke subagents for isolated subtasks
Hooks
: Intercept and control agent behavior at key execution points
Permissions
: Control tool access with modes, rules, and callbacks
System prompts
: Inject context without CLAUDE.md files
Was this page helpful?
Yes
No
How the agent loop works
Work with sessions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/claude-code-features" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Use Claude Code features in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Use Claude Code features in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Agent SDK is built on the same foundation as Claude Code, which means your SDK agents have access to the same filesystem-based features: project instructions (
CLAUDE.md
and rules), skills, hooks, and more.
When you omit
settingSources
,
query()
reads the same filesystem settings as the Claude Code CLI: user, project, and local settings, CLAUDE.md files, and
.claude/
skills, agents, and commands. To run without these, pass
settingSources: []
, which limits the agent to what you configure programmatically. Managed policy settings and the global
~/.claude.json
config are read regardless of this option. See
What settingSources does not control
.
For a conceptual overview of what each feature does and when to use it, see
Extend Claude Code
.
​
Control filesystem settings with settingSources
The setting sources option (
setting_sources
in Python,
settingSources
in TypeScript) controls which filesystem-based settings the SDK loads. Pass an explicit list to opt in to specific sources, or pass an empty array to disable user, project, and local settings.
This example loads both user-level and project-level settings by setting
settingSources
to
["user", "project"]
:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async
for
message
in
query(
prompt
=
"Help me refactor the auth module"
,
options
=
ClaudeAgentOptions(
# "user" loads from ~/.claude/, "project" loads from ./.claude/ in cwd.
# Together they give the agent access to CLAUDE.md, skills, hooks, and
# permissions from both locations.
setting_sources
=
[
"user"
,
"project"
],
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
],
),
):
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
hasattr
(block,
"text"
):
print
(block.text)
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(
f
"
\n
Result:
{
message.result
}
"
)
Each source loads settings from a specific location, where
<cwd>
is the working directory you pass via the
cwd
option, or the process’s current directory if unset. For the full type definition, see
SettingSource
(TypeScript) or
SettingSource
(Python).
Source
What it loads
Location
"project"
Project CLAUDE.md,
.claude/rules/*.md
, project skills, project hooks, project
settings.json
<cwd>/.claude/
for
settings.json
and hooks;
<cwd>
and every parent directory for CLAUDE.md and rules;
<cwd>
and every parent directory up to the repository root for skills
"user"
User CLAUDE.md,
~/.claude/rules/*.md
, user skills, user settings
~/.claude/
"local"
CLAUDE.local.md,
.claude/settings.local.json
<cwd>/.claude/
for
settings.local.json
;
<cwd>
and every parent directory for CLAUDE.local.md
Omitting
settingSources
is equivalent to
["user", "project", "local"]
.
The
cwd
option determines where the SDK looks for project-level inputs. CLAUDE.md and rules load from
<cwd>
and from every parent directory. Skills load from
<cwd>
and from every parent directory up to the repository root. Project
settings.json
and hooks load only from
<cwd>/.claude/
with no parent-directory fallback.
​
What settingSources does not control
settingSources
covers user, project, and local settings. A few inputs are read regardless of its value:
Input
Behavior
To disable
Managed policy settings
Always loaded when present on the host
Remove the managed settings file
~/.claude.json
global config
Always read
Relocate with
CLAUDE_CONFIG_DIR
in
env
Auto memory at
~/.claude/projects/<project>/memory/
Loaded by default into the system prompt
Set
autoMemoryEnabled: false
in settings, or
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
in
env
Do not rely on default
query()
options for multi-tenant isolation. Because the inputs above are read regardless of
settingSources
, an SDK process can pick up host-level configuration and per-directory memory. For multi-tenant deployments, run each tenant in its own filesystem and set
settingSources: []
plus
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
in
env
. See
Secure deployment
.
​
Project instructions (CLAUDE.md and rules)
CLAUDE.md
files and
.claude/rules/*.md
files give your agent persistent context about your project: coding conventions, build commands, architecture decisions, and instructions. When
settingSources
includes
"project"
(as in the example above), the SDK loads these files into context at session start. The agent then follows your project conventions without you repeating them in every prompt.
​
CLAUDE.md load locations
Level
Location
When loaded
Project (root)
<cwd>/CLAUDE.md
or
<cwd>/.claude/CLAUDE.md
settingSources
includes
"project"
Project rules
<cwd>/.claude/rules/*.md
and
.claude/rules/*.md
in every parent directory
settingSources
includes
"project"
Project (parent dirs)
CLAUDE.md
files in directories above
cwd
settingSources
includes
"project"
, loaded at session start
Project (child dirs)
CLAUDE.md
files in subdirectories of
cwd
settingSources
includes
"project"
, loaded on demand when the agent reads a file in that subtree
Local
<cwd>/CLAUDE.local.md
and
CLAUDE.local.md
in every parent directory
settingSources
includes
"local"
User
~/.claude/CLAUDE.md
settingSources
includes
"user"
User rules
~/.claude/rules/*.md
settingSources
includes
"user"
All levels are additive: if both project and user CLAUDE.md files exist, the agent sees both. There is no hard precedence rule between levels; if instructions conflict, the outcome depends on how Claude interprets them. Write non-conflicting rules, or state precedence explicitly in the more specific file (“These project instructions override any conflicting user-level defaults”).
You can also inject context directly via
systemPrompt
without using CLAUDE.md files. See
Modify system prompts
. Use CLAUDE.md when you want the same context shared between interactive Claude Code sessions and your SDK agents.
For how to structure and organize CLAUDE.md content, see
Manage Claude’s memory
.
​
Skills
Skills are markdown files that give your agent specialized knowledge and invocable workflows. Unlike
CLAUDE.md
(which loads every session), skills load on demand. The agent receives skill descriptions at startup and loads the full content when relevant.
Skills are discovered from the filesystem through
settingSources
. When the
skills
option on
query()
is omitted, discovered user and project skills are enabled and the Skill tool is available, matching CLI behavior. To control which skills are enabled, pass
skills
as
"all"
, a list of skill names, or
[]
to disable all. The SDK enables the Skill tool automatically when
skills
is set, so you do not need to add it to
allowedTools
.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
# Skills in .claude/skills/ are discovered automatically
# when settingSources includes "project"
async
for
message
in
query(
prompt
=
"Review this PR using our code review checklist"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"user"
,
"project"
],
skills
=
"all"
,
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
Skills must be created as filesystem artifacts (
.claude/skills/<name>/SKILL.md
). The SDK does not have a programmatic API for registering skills. See
Agent Skills in the SDK
for full details.
For more on creating and using skills, see
Agent Skills in the SDK
.
​
Hooks
The SDK supports two ways to define hooks, and they run side by side:
Filesystem hooks:
shell commands defined in
settings.json
, loaded when
settingSources
includes the relevant source. These are the same hooks you’d configure for
interactive Claude Code sessions
.
Programmatic hooks:
callback functions passed directly to
query()
. These run in your application process and can return structured decisions. See
Control execution with hooks
.
Both types execute during the same hook lifecycle. If you already have hooks in your project’s
.claude/settings.json
and you set
settingSources: ["project"]
, those hooks run automatically in the SDK with no extra configuration.
Hook callbacks receive the tool input and return a decision dict. Returning
{}
(an empty dict) means allow the tool to proceed. Returning
{"decision": "block", "reason": "..."}
prevents execution and the reason is sent to Claude as the tool result. See the
hooks guide
for the full callback signature and return types.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher, ResultMessage
# PreToolUse hook callback. Positional args:
#   input_data: HookInput dict with tool_name, tool_input, hook_event_name
#   tool_use_id: str | None, the ID of the tool call being intercepted
#   context: HookContext, carries session metadata
async
def
audit_bash
(
input_data
,
tool_use_id
,
context
):
command
=
input_data.get(
"tool_input"
, {}).get(
"command"
,
""
)
if
"rm -rf"
in
command:
return
{
"decision"
:
"block"
,
"reason"
:
"Destructive command blocked"
}
return
{}
# Empty dict: allow the tool to proceed
# Filesystem hooks from .claude/settings.json run automatically
# when settingSources loads them. You can also add programmatic hooks:
async
for
message
in
query(
prompt
=
"Refactor the auth module"
,
options
=
ClaudeAgentOptions(
setting_sources
=
[
"project"
],
# Loads hooks from .claude/settings.json
hooks
=
{
"PreToolUse"
: [
HookMatcher(
matcher
=
"Bash"
,
hooks
=
[audit_bash]),
]
},
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
​
When to use which hook type
Hook type
Best for
Filesystem
(
settings.json
)
Sharing hooks between CLI and SDK sessions. Supports
"command"
(shell scripts),
"http"
(POST to an endpoint),
"mcp_tool"
(call a connected MCP server’s tool),
"prompt"
(LLM evaluates a prompt), and
"agent"
(spawns a verifier agent). These fire in the main agent and any subagents it spawns.
Programmatic
(callbacks in
query()
)
Application-specific logic; returning structured decisions; in-process integration. Scoped to the main session only.
The TypeScript SDK supports additional hook events beyond Python, including
SessionStart
,
SessionEnd
,
TeammateIdle
, and
TaskCompleted
. See the
hooks guide
for the full event compatibility table.
For full details on programmatic hooks, see
Control execution with hooks
. For filesystem hook syntax, see
Hooks
.
​
Choose the right feature
The Agent SDK gives you access to several ways to extend your agent’s behavior. If you’re unsure which to use, this table maps common goals to the right approach.
You want to…
Use
SDK surface
Set project conventions your agent always follows
CLAUDE.md
settingSources: ["project"]
loads it automatically
Give the agent reference material it loads when relevant
Skills
settingSources
+
skills
option
Run a reusable workflow (deploy, review, release)
User-invocable skills
settingSources
+
skills
option
Delegate an isolated subtask to a fresh context (research, review)
Subagents
agents
parameter +
allowedTools: ["Agent"]
Coordinate multiple Claude Code instances with shared task lists and direct inter-agent messaging
Agent teams
Not directly configured via SDK options. Agent teams are a CLI feature where one session acts as the team lead, coordinating work across independent teammates
Run deterministic logic on tool calls (audit, block, transform)
Hooks
hooks
parameter with callbacks, or shell scripts loaded via
settingSources
Give Claude structured tool access to an external service
MCP
mcpServers
parameter
Subagents versus agent teams:
Subagents are ephemeral and isolated: fresh conversation, one task, summary returned to parent. Agent teams coordinate multiple independent Claude Code instances that share a task list and message each other directly. Agent teams are a CLI feature. See
What subagents inherit
and the
agent teams comparison
for details.
Every feature you enable adds to your agent’s context window. For per-feature costs and how these features layer together, see
Extend Claude Code
.
​
Related resources
Extend Claude Code
: Conceptual overview of all extension features, with comparison tables and context cost analysis
Skills in the SDK
: Full guide to using skills programmatically
Subagents
: Define and invoke subagents for isolated subtasks
Hooks
: Intercept and control agent behavior at key execution points
Permissions
: Control tool access with modes, rules, and callbacks
System prompts
: Inject context without CLAUDE.md files
Was this page helpful?
Yes
No
How the agent loop works
Work with sessions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/claude-code-features" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Configure permissions</title>
  <link>https://code.claude.com/docs/en/permissions</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/permissions</guid>
  <pubDate>Mon, 24 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Configure permissions
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Configure permissions
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports fine-grained permissions so that you can specify exactly what the agent is allowed to do and what it cannot. Permission settings can be checked into version control and distributed to all developers in your organization, as well as customized by individual developers.
​
Permission system
Claude Code uses a tiered permission system to balance power and safety:
Tool type
Example
Approval required
”Yes, don’t ask again” behavior
Read-only
File reads, Grep
No
N/A
Bash commands
Shell execution
Yes
Permanently per project directory and command
File modification
Edit/write files
Yes
Until session end
​
Manage permissions
You can view and manage Claude Code’s tool permissions with
/permissions
. This UI lists all permission rules and the settings.json file they are sourced from.
Allow
rules let Claude Code use the specified tool without manual approval.
Ask
rules prompt for confirmation whenever Claude Code tries to use the specified tool.
Deny
rules prevent Claude Code from using the specified tool.
Rules are evaluated in order:
deny -> ask -> allow
. The first matching rule wins, so deny rules always take precedence.
Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or
CLAUDE.md
shape what Claude tries to do, but they don’t change what Claude Code allows. To grant or revoke access, use
/permissions
, the rules described here, a
permission mode
, or a
PreToolUse hook
.
​
Permission modes
Claude Code supports several permission modes that control how tools are approved. See
Permission modes
for when to use each one. Set the
defaultMode
in your
settings files
:
Mode
Description
default
Standard behavior: prompts for permission on first use of each tool
acceptEdits
Automatically accepts file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.) for paths in the working directory or
additionalDirectories
plan
Plan Mode: Claude reads files and runs read-only shell commands to explore but does not edit your source files
auto
Auto-approves tool calls with background safety checks that verify actions align with your request. Currently a research preview
dontAsk
Auto-denies tools unless pre-approved via
/permissions
or
permissions.allow
rules
bypassPermissions
Skips all permission prompts. Root and home directory removals such as
rm -rf /
still prompt as a circuit breaker
bypassPermissions
mode skips all permission prompts, including writes to
.git
,
.claude
,
.vscode
,
.idea
, and
.husky
. Removals targeting the filesystem root or home directory, such as
rm -rf /
and
rm -rf ~
, still prompt as a circuit breaker against model error. Only use this mode in isolated environments like containers or VMs where Claude Code cannot cause damage. Administrators can prevent this mode by setting
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
To prevent
bypassPermissions
or
auto
mode from being used, set
permissions.disableBypassPermissionsMode
or
permissions.disableAutoMode
to
"disable"
in any
settings file
. These are most useful in
managed settings
where they cannot be overridden.
​
Permission rule syntax
Permission rules follow the format
Tool
or
Tool(specifier)
.
​
Match all uses of a tool
To match all uses of a tool, use just the tool name without parentheses:
Rule
Effect
Bash
Matches all Bash commands
WebFetch
Matches all web fetch requests
Read
Matches all file reads
Bash(*)
is equivalent to
Bash
and matches all Bash commands.
​
Use specifiers for fine-grained control
Add a specifier in parentheses to match specific tool uses:
Rule
Effect
Bash(npm run build)
Matches the exact command
npm run build
Read(./.env)
Matches reading the
.env
file in the current directory
WebFetch(domain:example.com)
Matches fetch requests to example.com
​
Wildcard patterns
Bash rules support glob patterns with
*
. Wildcards can appear at any position in the command. This configuration allows npm and git commit commands while blocking git push:
{
"permissions"
: {
"allow"
: [
"Bash(npm run *)"
,
"Bash(git commit *)"
,
"Bash(git * main)"
,
"Bash(* --version)"
,
"Bash(* --help *)"
],
"deny"
: [
"Bash(git push *)"
]
}
}
The space before
*
matters:
Bash(ls *)
matches
ls -la
but not
lsof
, while
Bash(ls*)
matches both. The
:*
suffix is an equivalent way to write a trailing wildcard, so
Bash(ls:*)
matches the same commands as
Bash(ls *)
.
The permission dialog writes the space-separated form when you select “Yes, don’t ask again” for a command prefix. The
:*
form is only recognized at the end of a pattern. In a pattern like
Bash(git:* push)
, the colon is treated as a literal character and won’t match git commands.
​
Tool-specific permission rules
​
Bash
Bash permission rules support wildcard matching with
*
. Wildcards can appear at any position in the command, including at the beginning, middle, or end:
Bash(npm run build)
matches the exact Bash command
npm run build
Bash(npm run test *)
matches Bash commands starting with
npm run test
Bash(npm *)
matches any command starting with
npm
Bash(* install)
matches any command ending with
install
Bash(git * main)
matches commands like
git checkout main
and
git log --oneline main
A single
*
matches any sequence of characters including spaces, so one wildcard can span multiple arguments.
Bash(git *)
matches
git log --oneline --all
, and
Bash(git * main)
matches
git push origin main
as well as
git merge main
.
When
*
appears at the end with a space before it (like
Bash(ls *)
), it enforces a word boundary, requiring the prefix to be followed by a space or end-of-string. For example,
Bash(ls *)
matches
ls -la
but not
lsof
. In contrast,
Bash(ls*)
without a space matches both
ls -la
and
lsof
because there’s no word boundary constraint.
​
Compound commands
Claude Code is aware of shell operators, so a rule like
Bash(safe-cmd *)
won’t give it permission to run the command
safe-cmd && other-cmd
. The recognized command separators are
&&
,
||
,
;
,
|
,
|&
,
&
, and newlines. A rule must match each subcommand independently.
When you approve a compound command with “Yes, don’t ask again”, Claude Code saves a separate rule for each subcommand that requires approval, rather than a single rule for the full compound string. For example, approving
git status && npm test
saves a rule for
npm test
, so future
npm test
invocations are recognized regardless of what precedes the
&&
. Subcommands like
cd
into a subdirectory generate their own Read rule for that path. Up to 5 rules may be saved for a single compound command.
​
Process wrappers
Before matching Bash rules, Claude Code strips a fixed set of process wrappers so a rule like
Bash(npm test *)
also matches
timeout 30 npm test
. The recognized wrappers are
timeout
,
time
,
nice
,
nohup
, and
stdbuf
.
Bare
xargs
is also stripped, so
Bash(grep *)
matches
xargs grep pattern
. Stripping applies only when
xargs
has no flags: an invocation like
xargs -n1 grep pattern
is matched as an
xargs
command, so rules written for the inner command do not cover it.
This wrapper list is built in and is not configurable. Development environment runners such as
direnv exec
,
devbox run
,
mise exec
,
npx
, and
docker exec
are not in the list. Because these tools execute their arguments as a command, a rule like
Bash(devbox run *)
matches whatever comes after
run
, including
devbox run rm -rf .
. To approve work inside an environment runner, write a specific rule that includes both the runner and the inner command, such as
Bash(devbox run npm test)
. Add one rule per inner command you want to allow.
Exec wrappers such as
watch
,
setsid
,
ionice
, and
flock
always prompt and cannot be auto-approved by a prefix rule like
Bash(watch *)
. The same applies to
find
with
-exec
or
-delete
: a
Bash(find *)
rule does not cover these forms. To approve a specific invocation, write an exact-match rule for the full command string.
​
Read-only commands
Claude Code recognizes a built-in set of Bash commands as read-only and runs them without a permission prompt in every mode. These include
ls
,
cat
,
echo
,
pwd
,
head
,
tail
,
grep
,
find
,
wc
,
which
,
diff
,
stat
,
du
,
cd
, and read-only forms of
git
. The set is not configurable; to require a prompt for one of these commands, add an
ask
or
deny
rule for it.
Unquoted glob patterns are permitted for commands whose every flag is read-only, so
ls *.ts
and
wc -l src/*.py
run without a prompt. Commands with write-capable or exec-capable flags, such as
find
,
sort
,
sed
, and
git
, still prompt when an unquoted glob is present because the glob could expand to a flag like
-delete
.
A
cd
into a path inside your working directory or an
additional directory
is also read-only. A compound command like
cd packages/api && ls
runs without a prompt when each part qualifies on its own. Combining
cd
with
git
in one compound command always prompts, regardless of the target directory.
Bash permission patterns that try to constrain command arguments are fragile. For example,
Bash(curl http://github.com/ *)
intends to restrict curl to GitHub URLs, but won’t match variations like:
Options before URL:
curl -X GET http://github.com/...
Different protocol:
curl https://github.com/...
Redirects:
curl -L http://bit.ly/xyz
(redirects to github)
Variables:
URL=http://github.com && curl $URL
Extra spaces:
curl  http://github.com
For more reliable URL filtering, consider:
Restrict Bash network tools
: use deny rules to block
curl
,
wget
, and similar commands, then use the WebFetch tool with
WebFetch(domain:github.com)
permission for allowed domains
Use PreToolUse hooks
: implement a hook that validates URLs in Bash commands and blocks disallowed domains
Add CLAUDE.md guidance
: describe your allowed curl patterns in
CLAUDE.md
. This shapes what Claude tries but doesn’t enforce a boundary, so pair it with one of the options above
Note that using WebFetch alone does not prevent network access. If Bash is allowed, Claude can still use
curl
,
wget
, or other tools to reach any URL.
​
PowerShell
PowerShell permission rules use the same shape as Bash rules. Wildcards with
*
match at any position, the
:*
suffix is equivalent to a trailing
*
, and a bare
PowerShell
or
PowerShell(*)
matches every command. This configuration allows
Get-ChildItem
and
git commit
commands while blocking
Remove-Item
:
{
"permissions"
: {
"allow"
: [
"PowerShell(Get-ChildItem *)"
,
"PowerShell(git commit *)"
],
"deny"
: [
"PowerShell(Remove-Item *)"
]
}
}
Common aliases are canonicalized before matching. A rule written for the cmdlet name also matches its aliases, so
PowerShell(Get-ChildItem *)
matches
gci
,
ls
, and
dir
as well. Matching is case-insensitive.
Claude Code parses the PowerShell AST and checks each command in a compound command independently. Pipeline operators
|
, statement separators
;
, and on PowerShell 7+ the chain operators
&&
and
||
split a compound command into subcommands. A rule must match every subcommand for the compound command to be allowed.
​
Read and Edit
Edit
rules apply to all built-in tools that edit files. Claude makes a best-effort attempt to apply
Read
rules to all built-in tools that read files like Grep and Glob.
Read and Edit deny rules apply to Claude’s built-in file tools and to file commands Claude Code recognizes in Bash, such as
cat
,
head
,
tail
, and
sed
. They do not apply to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that blocks all processes from accessing a path,
enable the sandbox
.
Read and Edit rules both follow the
gitignore
specification with four distinct pattern types:
Pattern
Meaning
Example
Matches
//path
Absolute
path from filesystem root
Read(//Users/alice/secrets/**)
/Users/alice/secrets/**
~/path
Path from
home
directory
Read(~/Documents/*.pdf)
/Users/alice/Documents/*.pdf
/path
Path
relative to project root
Edit(/src/**/*.ts)
<project root>/src/**/*.ts
path
or
./path
Path
relative to current directory
Read(*.env)
<cwd>/*.env
A pattern like
/Users/alice/file
is NOT an absolute path. It’s relative to the project root. Use
//Users/alice/file
for absolute paths.
On Windows, paths are normalized to POSIX form before matching.
C:\Users\alice
becomes
/c/Users/alice
, so use
//c/**/.env
to match
.env
files anywhere on that drive. To match across all drives, use
//**/.env
.
Examples:
Edit(/docs/**)
: edits in
<project>/docs/
(NOT
/docs/
and NOT
<project>/.claude/docs/
)
Read(~/.zshrc)
: reads your home directory’s
.zshrc
Edit(//tmp/scratch.txt)
: edits the absolute path
/tmp/scratch.txt
Read(src/**)
: reads from
<current-directory>/src/
A rule only matches files under its anchor, so the anchor determines how far a deny rule reaches. Bare filenames follow gitignore semantics and match at any depth, so
Read(.env)
and
Read(**/.env)
are equivalent:
Deny rule
Blocks
Does not block
Read(.env)
or
Read(**/.env)
any
.env
at or under the current directory
.env
in a parent directory or another project
Read(//**/.env)
any
.env
anywhere on the filesystem
nothing; the rule is anchored at the filesystem root
In gitignore patterns,
*
matches files in a single directory while
**
matches recursively across directories. To allow all file access, use just the tool name without parentheses:
Read
,
Edit
, or
Write
.
When Claude accesses a symlink, permission rules check two paths: the symlink itself and the file it resolves to. Allow and deny rules treat that pair differently: allow rules fall back to prompting you, while deny rules block outright.
Allow rules
: apply only when both the symlink path and its target match. A symlink inside an allowed directory that points outside it still prompts you.
Deny rules
: apply when either the symlink path or its target matches. A symlink that points to a denied file is itself denied.
For example, with
Read(./project/**)
allowed and
Read(~/.ssh/**)
denied, a symlink at
./project/key
pointing to
~/.ssh/id_rsa
is blocked: the target fails the allow rule and matches the deny rule.
​
WebFetch
WebFetch(domain:example.com)
matches fetch requests to example.com
​
MCP
mcp__puppeteer
matches any tool provided by the
puppeteer
server (name configured in Claude Code)
mcp__puppeteer__*
wildcard syntax that also matches all tools from the
puppeteer
server
mcp__puppeteer__puppeteer_navigate
matches the
puppeteer_navigate
tool provided by the
puppeteer
server
​
Agent (subagents)
Use
Agent(AgentName)
rules to control which
subagents
Claude can use:
Agent(Explore)
matches the Explore subagent
Agent(Plan)
matches the Plan subagent
Agent(my-custom-agent)
matches a custom subagent named
my-custom-agent
Add these rules to the
deny
array in your settings or use the
--disallowedTools
CLI flag to disable specific agents. To disable the Explore agent:
{
"permissions"
: {
"deny"
: [
"Agent(Explore)"
]
}
}
​
Extend permissions with hooks
Claude Code hooks
provide a way to register custom shell commands to perform permission evaluation at runtime. When Claude Code makes a tool call, PreToolUse hooks run before the permission prompt. The hook output can deny the tool call, force a prompt, or skip the prompt to let the call proceed.
Hook decisions do not bypass permission rules. Deny and ask rules are evaluated regardless of what a PreToolUse hook returns, so a matching deny rule blocks the call and a matching ask rule still prompts even when the hook returned
"allow"
or
"ask"
. This preserves the deny-first precedence described in
Manage permissions
, including deny rules set in managed settings.
A blocking hook also takes precedence over allow rules. A hook that exits with code 2 stops the tool call before permission rules are evaluated, so the block applies even when an allow rule would otherwise let the call proceed. To run all Bash commands without prompts except for a few you want blocked, add
"Bash"
to your allow list and register a PreToolUse hook that rejects those specific commands. See
Block edits to protected files
for a hook script you can adapt.
​
Working directories
By default, Claude has access to files in the directory where it was launched. You can extend this access:
During startup
: use
--add-dir <path>
CLI argument
During session
: use
/add-dir
command
Persistent configuration
: add to
additionalDirectories
in
settings files
Files in additional directories follow the same permission rules as the original working directory: they become readable without prompts, and file editing permissions follow the current permission mode.
​
Additional directories grant file access, not configuration
Adding a directory extends where Claude can read and edit files. It does not make that directory a full configuration root: most
.claude/
configuration is not discovered from additional directories, though a few types are loaded as exceptions.
The following configuration types are loaded from
--add-dir
directories:
Configuration
Loaded from
--add-dir
Skills
in
.claude/skills/
Yes, with live reload
Plugin settings in
.claude/settings.json
enabledPlugins
and
extraKnownMarketplaces
only
CLAUDE.md
files,
.claude/rules/
, and
CLAUDE.local.md
Only when
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1
is set.
CLAUDE.local.md
additionally requires the
local
setting source, which is enabled by default
Subagents, commands, and output styles are discovered from the current working directory and its parents, your user directory at
~/.claude/
, and managed settings. Hooks and other
settings.json
keys load from the current working directory’s
.claude/
folder with no parent-directory fallback, alongside your user
~/.claude/settings.json
and managed settings. To share that configuration across projects, use one of these approaches:
User-level configuration
: place files in
~/.claude/agents/
,
~/.claude/output-styles/
, or
~/.claude/settings.json
to make them available in every project
Plugins
: package and distribute configuration as a
plugin
that teams can install
Launch from the config directory
: run Claude Code from the directory containing the
.claude/
configuration you want
​
How permissions interact with sandboxing
Permissions and
sandboxing
are complementary security layers:
Permissions
control which tools Claude Code can use and which files or domains it can access. They apply to all tools (Bash, Read, Edit, WebFetch, MCP, and others).
Sandboxing
provides OS-level enforcement that restricts the Bash tool’s filesystem and network access. It applies only to Bash commands and their child processes.
Use both for defense-in-depth:
Permission deny rules block Claude from even attempting to access restricted resources
Sandbox restrictions prevent Bash commands from reaching resources outside defined boundaries, even if a prompt injection bypasses Claude’s decision-making
Filesystem restrictions in the sandbox combine the
sandbox.filesystem
settings with Read and Edit deny rules; both are merged into the final sandbox boundary
Network restrictions combine WebFetch permission rules with the sandbox’s
allowedDomains
and
deniedDomains
lists
When sandboxing is enabled with
autoAllowBashIfSandboxed: true
, which is the default, sandboxed Bash commands run without prompting even if your permissions include
ask: Bash(*)
. The sandbox boundary substitutes for the per-command prompt. Explicit deny rules still apply, and
rm
or
rmdir
commands that target
/
, your home directory, or other critical system paths still trigger a prompt. See
sandbox modes
to change this behavior.
​
Managed settings
For organizations that need centralized control over Claude Code configuration, administrators can deploy managed settings that cannot be overridden by user or project settings. These policy settings follow the same format as regular settings files and can be delivered through MDM/OS-level policies, managed settings files, or
server-managed settings
. See
settings files
for delivery mechanisms and file locations.
​
Managed-only settings
The following settings are only read from managed settings. Placing them in user or project settings files has no effect.
Setting
Description
allowedChannelPlugins
Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires
channelsEnabled: true
. See
Restrict which channel plugins can run
allowManagedHooksOnly
When
true
, only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. User, project, and all other plugin hooks are blocked
allowManagedMcpServersOnly
When
true
, only
allowedMcpServers
from managed settings are respected.
deniedMcpServers
still merges from all sources. See
Managed MCP configuration
allowManagedPermissionRulesOnly
When
true
, prevents user and project settings from defining
allow
,
ask
, or
deny
permission rules. Only rules in managed settings apply
blockedMarketplaces
Blocklist of marketplace sources. Blocked sources are checked before downloading, so they never touch the filesystem. See
managed marketplace restrictions
channelsEnabled
Allow
channels
for the organization. See
enterprise controls
for the default on each plan
forceRemoteSettingsRefresh
When
true
, blocks CLI startup until remote managed settings are freshly fetched and exits if the fetch fails. See
fail-closed enforcement
pluginTrustMessage
Custom message appended to the plugin trust warning shown before installation
sandbox.filesystem.allowManagedReadPathsOnly
When
true
, only
filesystem.allowRead
paths from managed settings are respected.
denyRead
still merges from all sources
sandbox.network.allowManagedDomainsOnly
When
true
, only
allowedDomains
and
WebFetch(domain:...)
allow rules from managed settings are respected. Non-allowed domains are blocked automatically without prompting the user. Denied domains still merge from all sources
strictKnownMarketplaces
Controls which plugin marketplace sources users can add and install plugins from. See
managed marketplace restrictions
wslInheritsWindowsSettings
When
true
in the Windows HKLM registry key or
C:\Program Files\ClaudeCode\managed-settings.json
, WSL reads managed settings from the Windows policy chain in addition to
/etc/claude-code
. See
Settings files
disableBypassPermissionsMode
is typically placed in managed settings to enforce organizational policy, but it works from any scope. A user can set it in their own settings to lock themselves out of bypass mode.
On Team and Enterprise plans, an admin enables or disables
Remote Control
and
web sessions
organization-wide in
Claude Code admin settings
. Remote Control can additionally be disabled per device with the
disableRemoteControl
managed setting. Web sessions have no per-device managed settings key.
​
Settings precedence
Permission rules follow the same
settings precedence
as all other Claude Code settings:
Managed settings
: cannot be overridden by any other level, including command line arguments
Command line arguments
: temporary session overrides
Local project settings
(
.claude/settings.local.json
)
Shared project settings
(
.claude/settings.json
)
User settings
(
~/.claude/settings.json
)
If a tool is denied at any level, no other level can allow it. For example, a managed settings deny cannot be overridden by
--allowedTools
, and
--disallowedTools
can add restrictions beyond what managed settings define.
Embedding hosts can supply additional managed policy via the SDK
managedSettings
option when
parentSettingsBehavior
is set to
"merge"
; embedder values can tighten policy but not loosen it.
For example, if user settings allow a permission and project settings deny it, the deny rule blocks it. The reverse is also true: a user-level deny blocks a project-level allow, because deny rules from any scope are evaluated before allow rules.
​
Example configurations
This
repository
includes starter settings configurations for common deployment scenarios. Use these as starting points and adjust them to fit your needs.
​
See also
Settings
: complete configuration reference including the permission settings table
Configure auto mode
: tell the auto mode classifier which infrastructure your organization trusts
Sandboxing
: OS-level filesystem and network isolation for Bash commands
Authentication
: set up user access to Claude Code
Security
: security safeguards and best practices
Hooks
: automate workflows and extend permission evaluation
Was this page helpful?
Yes
No
Settings
Sandboxing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/permissions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Configure permissions
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Configure permissions
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code supports fine-grained permissions so that you can specify exactly what the agent is allowed to do and what it cannot. Permission settings can be checked into version control and distributed to all developers in your organization, as well as customized by individual developers.
​
Permission system
Claude Code uses a tiered permission system to balance power and safety:
Tool type
Example
Approval required
”Yes, don’t ask again” behavior
Read-only
File reads, Grep
No
N/A
Bash commands
Shell execution
Yes
Permanently per project directory and command
File modification
Edit/write files
Yes
Until session end
​
Manage permissions
You can view and manage Claude Code’s tool permissions with
/permissions
. This UI lists all permission rules and the settings.json file they are sourced from.
Allow
rules let Claude Code use the specified tool without manual approval.
Ask
rules prompt for confirmation whenever Claude Code tries to use the specified tool.
Deny
rules prevent Claude Code from using the specified tool.
Rules are evaluated in order:
deny -> ask -> allow
. The first matching rule wins, so deny rules always take precedence.
Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or
CLAUDE.md
shape what Claude tries to do, but they don’t change what Claude Code allows. To grant or revoke access, use
/permissions
, the rules described here, a
permission mode
, or a
PreToolUse hook
.
​
Permission modes
Claude Code supports several permission modes that control how tools are approved. See
Permission modes
for when to use each one. Set the
defaultMode
in your
settings files
:
Mode
Description
default
Standard behavior: prompts for permission on first use of each tool
acceptEdits
Automatically accepts file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.) for paths in the working directory or
additionalDirectories
plan
Plan Mode: Claude reads files and runs read-only shell commands to explore but does not edit your source files
auto
Auto-approves tool calls with background safety checks that verify actions align with your request. Currently a research preview
dontAsk
Auto-denies tools unless pre-approved via
/permissions
or
permissions.allow
rules
bypassPermissions
Skips all permission prompts. Root and home directory removals such as
rm -rf /
still prompt as a circuit breaker
bypassPermissions
mode skips all permission prompts, including writes to
.git
,
.claude
,
.vscode
,
.idea
, and
.husky
. Removals targeting the filesystem root or home directory, such as
rm -rf /
and
rm -rf ~
, still prompt as a circuit breaker against model error. Only use this mode in isolated environments like containers or VMs where Claude Code cannot cause damage. Administrators can prevent this mode by setting
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
To prevent
bypassPermissions
or
auto
mode from being used, set
permissions.disableBypassPermissionsMode
or
permissions.disableAutoMode
to
"disable"
in any
settings file
. These are most useful in
managed settings
where they cannot be overridden.
​
Permission rule syntax
Permission rules follow the format
Tool
or
Tool(specifier)
.
​
Match all uses of a tool
To match all uses of a tool, use just the tool name without parentheses:
Rule
Effect
Bash
Matches all Bash commands
WebFetch
Matches all web fetch requests
Read
Matches all file reads
Bash(*)
is equivalent to
Bash
and matches all Bash commands.
​
Use specifiers for fine-grained control
Add a specifier in parentheses to match specific tool uses:
Rule
Effect
Bash(npm run build)
Matches the exact command
npm run build
Read(./.env)
Matches reading the
.env
file in the current directory
WebFetch(domain:example.com)
Matches fetch requests to example.com
​
Wildcard patterns
Bash rules support glob patterns with
*
. Wildcards can appear at any position in the command. This configuration allows npm and git commit commands while blocking git push:
{
"permissions"
: {
"allow"
: [
"Bash(npm run *)"
,
"Bash(git commit *)"
,
"Bash(git * main)"
,
"Bash(* --version)"
,
"Bash(* --help *)"
],
"deny"
: [
"Bash(git push *)"
]
}
}
The space before
*
matters:
Bash(ls *)
matches
ls -la
but not
lsof
, while
Bash(ls*)
matches both. The
:*
suffix is an equivalent way to write a trailing wildcard, so
Bash(ls:*)
matches the same commands as
Bash(ls *)
.
The permission dialog writes the space-separated form when you select “Yes, don’t ask again” for a command prefix. The
:*
form is only recognized at the end of a pattern. In a pattern like
Bash(git:* push)
, the colon is treated as a literal character and won’t match git commands.
​
Tool-specific permission rules
​
Bash
Bash permission rules support wildcard matching with
*
. Wildcards can appear at any position in the command, including at the beginning, middle, or end:
Bash(npm run build)
matches the exact Bash command
npm run build
Bash(npm run test *)
matches Bash commands starting with
npm run test
Bash(npm *)
matches any command starting with
npm
Bash(* install)
matches any command ending with
install
Bash(git * main)
matches commands like
git checkout main
and
git log --oneline main
A single
*
matches any sequence of characters including spaces, so one wildcard can span multiple arguments.
Bash(git *)
matches
git log --oneline --all
, and
Bash(git * main)
matches
git push origin main
as well as
git merge main
.
When
*
appears at the end with a space before it (like
Bash(ls *)
), it enforces a word boundary, requiring the prefix to be followed by a space or end-of-string. For example,
Bash(ls *)
matches
ls -la
but not
lsof
. In contrast,
Bash(ls*)
without a space matches both
ls -la
and
lsof
because there’s no word boundary constraint.
​
Compound commands
Claude Code is aware of shell operators, so a rule like
Bash(safe-cmd *)
won’t give it permission to run the command
safe-cmd && other-cmd
. The recognized command separators are
&&
,
||
,
;
,
|
,
|&
,
&
, and newlines. A rule must match each subcommand independently.
When you approve a compound command with “Yes, don’t ask again”, Claude Code saves a separate rule for each subcommand that requires approval, rather than a single rule for the full compound string. For example, approving
git status && npm test
saves a rule for
npm test
, so future
npm test
invocations are recognized regardless of what precedes the
&&
. Subcommands like
cd
into a subdirectory generate their own Read rule for that path. Up to 5 rules may be saved for a single compound command.
​
Process wrappers
Before matching Bash rules, Claude Code strips a fixed set of process wrappers so a rule like
Bash(npm test *)
also matches
timeout 30 npm test
. The recognized wrappers are
timeout
,
time
,
nice
,
nohup
, and
stdbuf
.
Bare
xargs
is also stripped, so
Bash(grep *)
matches
xargs grep pattern
. Stripping applies only when
xargs
has no flags: an invocation like
xargs -n1 grep pattern
is matched as an
xargs
command, so rules written for the inner command do not cover it.
This wrapper list is built in and is not configurable. Development environment runners such as
direnv exec
,
devbox run
,
mise exec
,
npx
, and
docker exec
are not in the list. Because these tools execute their arguments as a command, a rule like
Bash(devbox run *)
matches whatever comes after
run
, including
devbox run rm -rf .
. To approve work inside an environment runner, write a specific rule that includes both the runner and the inner command, such as
Bash(devbox run npm test)
. Add one rule per inner command you want to allow.
Exec wrappers such as
watch
,
setsid
,
ionice
, and
flock
always prompt and cannot be auto-approved by a prefix rule like
Bash(watch *)
. The same applies to
find
with
-exec
or
-delete
: a
Bash(find *)
rule does not cover these forms. To approve a specific invocation, write an exact-match rule for the full command string.
​
Read-only commands
Claude Code recognizes a built-in set of Bash commands as read-only and runs them without a permission prompt in every mode. These include
ls
,
cat
,
echo
,
pwd
,
head
,
tail
,
grep
,
find
,
wc
,
which
,
diff
,
stat
,
du
,
cd
, and read-only forms of
git
. The set is not configurable; to require a prompt for one of these commands, add an
ask
or
deny
rule for it.
Unquoted glob patterns are permitted for commands whose every flag is read-only, so
ls *.ts
and
wc -l src/*.py
run without a prompt. Commands with write-capable or exec-capable flags, such as
find
,
sort
,
sed
, and
git
, still prompt when an unquoted glob is present because the glob could expand to a flag like
-delete
.
A
cd
into a path inside your working directory or an
additional directory
is also read-only. A compound command like
cd packages/api && ls
runs without a prompt when each part qualifies on its own. Combining
cd
with
git
in one compound command always prompts, regardless of the target directory.
Bash permission patterns that try to constrain command arguments are fragile. For example,
Bash(curl http://github.com/ *)
intends to restrict curl to GitHub URLs, but won’t match variations like:
Options before URL:
curl -X GET http://github.com/...
Different protocol:
curl https://github.com/...
Redirects:
curl -L http://bit.ly/xyz
(redirects to github)
Variables:
URL=http://github.com && curl $URL
Extra spaces:
curl  http://github.com
For more reliable URL filtering, consider:
Restrict Bash network tools
: use deny rules to block
curl
,
wget
, and similar commands, then use the WebFetch tool with
WebFetch(domain:github.com)
permission for allowed domains
Use PreToolUse hooks
: implement a hook that validates URLs in Bash commands and blocks disallowed domains
Add CLAUDE.md guidance
: describe your allowed curl patterns in
CLAUDE.md
. This shapes what Claude tries but doesn’t enforce a boundary, so pair it with one of the options above
Note that using WebFetch alone does not prevent network access. If Bash is allowed, Claude can still use
curl
,
wget
, or other tools to reach any URL.
​
PowerShell
PowerShell permission rules use the same shape as Bash rules. Wildcards with
*
match at any position, the
:*
suffix is equivalent to a trailing
*
, and a bare
PowerShell
or
PowerShell(*)
matches every command. This configuration allows
Get-ChildItem
and
git commit
commands while blocking
Remove-Item
:
{
"permissions"
: {
"allow"
: [
"PowerShell(Get-ChildItem *)"
,
"PowerShell(git commit *)"
],
"deny"
: [
"PowerShell(Remove-Item *)"
]
}
}
Common aliases are canonicalized before matching. A rule written for the cmdlet name also matches its aliases, so
PowerShell(Get-ChildItem *)
matches
gci
,
ls
, and
dir
as well. Matching is case-insensitive.
Claude Code parses the PowerShell AST and checks each command in a compound command independently. Pipeline operators
|
, statement separators
;
, and on PowerShell 7+ the chain operators
&&
and
||
split a compound command into subcommands. A rule must match every subcommand for the compound command to be allowed.
​
Read and Edit
Edit
rules apply to all built-in tools that edit files. Claude makes a best-effort attempt to apply
Read
rules to all built-in tools that read files like Grep and Glob.
Read and Edit deny rules apply to Claude’s built-in file tools and to file commands Claude Code recognizes in Bash, such as
cat
,
head
,
tail
, and
sed
. They do not apply to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that blocks all processes from accessing a path,
enable the sandbox
.
Read and Edit rules both follow the
gitignore
specification with four distinct pattern types:
Pattern
Meaning
Example
Matches
//path
Absolute
path from filesystem root
Read(//Users/alice/secrets/**)
/Users/alice/secrets/**
~/path
Path from
home
directory
Read(~/Documents/*.pdf)
/Users/alice/Documents/*.pdf
/path
Path
relative to project root
Edit(/src/**/*.ts)
<project root>/src/**/*.ts
path
or
./path
Path
relative to current directory
Read(*.env)
<cwd>/*.env
A pattern like
/Users/alice/file
is NOT an absolute path. It’s relative to the project root. Use
//Users/alice/file
for absolute paths.
On Windows, paths are normalized to POSIX form before matching.
C:\Users\alice
becomes
/c/Users/alice
, so use
//c/**/.env
to match
.env
files anywhere on that drive. To match across all drives, use
//**/.env
.
Examples:
Edit(/docs/**)
: edits in
<project>/docs/
(NOT
/docs/
and NOT
<project>/.claude/docs/
)
Read(~/.zshrc)
: reads your home directory’s
.zshrc
Edit(//tmp/scratch.txt)
: edits the absolute path
/tmp/scratch.txt
Read(src/**)
: reads from
<current-directory>/src/
A rule only matches files under its anchor, so the anchor determines how far a deny rule reaches. Bare filenames follow gitignore semantics and match at any depth, so
Read(.env)
and
Read(**/.env)
are equivalent:
Deny rule
Blocks
Does not block
Read(.env)
or
Read(**/.env)
any
.env
at or under the current directory
.env
in a parent directory or another project
Read(//**/.env)
any
.env
anywhere on the filesystem
nothing; the rule is anchored at the filesystem root
In gitignore patterns,
*
matches files in a single directory while
**
matches recursively across directories. To allow all file access, use just the tool name without parentheses:
Read
,
Edit
, or
Write
.
When Claude accesses a symlink, permission rules check two paths: the symlink itself and the file it resolves to. Allow and deny rules treat that pair differently: allow rules fall back to prompting you, while deny rules block outright.
Allow rules
: apply only when both the symlink path and its target match. A symlink inside an allowed directory that points outside it still prompts you.
Deny rules
: apply when either the symlink path or its target matches. A symlink that points to a denied file is itself denied.
For example, with
Read(./project/**)
allowed and
Read(~/.ssh/**)
denied, a symlink at
./project/key
pointing to
~/.ssh/id_rsa
is blocked: the target fails the allow rule and matches the deny rule.
​
WebFetch
WebFetch(domain:example.com)
matches fetch requests to example.com
​
MCP
mcp__puppeteer
matches any tool provided by the
puppeteer
server (name configured in Claude Code)
mcp__puppeteer__*
wildcard syntax that also matches all tools from the
puppeteer
server
mcp__puppeteer__puppeteer_navigate
matches the
puppeteer_navigate
tool provided by the
puppeteer
server
​
Agent (subagents)
Use
Agent(AgentName)
rules to control which
subagents
Claude can use:
Agent(Explore)
matches the Explore subagent
Agent(Plan)
matches the Plan subagent
Agent(my-custom-agent)
matches a custom subagent named
my-custom-agent
Add these rules to the
deny
array in your settings or use the
--disallowedTools
CLI flag to disable specific agents. To disable the Explore agent:
{
"permissions"
: {
"deny"
: [
"Agent(Explore)"
]
}
}
​
Extend permissions with hooks
Claude Code hooks
provide a way to register custom shell commands to perform permission evaluation at runtime. When Claude Code makes a tool call, PreToolUse hooks run before the permission prompt. The hook output can deny the tool call, force a prompt, or skip the prompt to let the call proceed.
Hook decisions do not bypass permission rules. Deny and ask rules are evaluated regardless of what a PreToolUse hook returns, so a matching deny rule blocks the call and a matching ask rule still prompts even when the hook returned
"allow"
or
"ask"
. This preserves the deny-first precedence described in
Manage permissions
, including deny rules set in managed settings.
A blocking hook also takes precedence over allow rules. A hook that exits with code 2 stops the tool call before permission rules are evaluated, so the block applies even when an allow rule would otherwise let the call proceed. To run all Bash commands without prompts except for a few you want blocked, add
"Bash"
to your allow list and register a PreToolUse hook that rejects those specific commands. See
Block edits to protected files
for a hook script you can adapt.
​
Working directories
By default, Claude has access to files in the directory where it was launched. You can extend this access:
During startup
: use
--add-dir <path>
CLI argument
During session
: use
/add-dir
command
Persistent configuration
: add to
additionalDirectories
in
settings files
Files in additional directories follow the same permission rules as the original working directory: they become readable without prompts, and file editing permissions follow the current permission mode.
​
Additional directories grant file access, not configuration
Adding a directory extends where Claude can read and edit files. It does not make that directory a full configuration root: most
.claude/
configuration is not discovered from additional directories, though a few types are loaded as exceptions.
The following configuration types are loaded from
--add-dir
directories:
Configuration
Loaded from
--add-dir
Skills
in
.claude/skills/
Yes, with live reload
Plugin settings in
.claude/settings.json
enabledPlugins
and
extraKnownMarketplaces
only
CLAUDE.md
files,
.claude/rules/
, and
CLAUDE.local.md
Only when
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1
is set.
CLAUDE.local.md
additionally requires the
local
setting source, which is enabled by default
Subagents, commands, and output styles are discovered from the current working directory and its parents, your user directory at
~/.claude/
, and managed settings. Hooks and other
settings.json
keys load from the current working directory’s
.claude/
folder with no parent-directory fallback, alongside your user
~/.claude/settings.json
and managed settings. To share that configuration across projects, use one of these approaches:
User-level configuration
: place files in
~/.claude/agents/
,
~/.claude/output-styles/
, or
~/.claude/settings.json
to make them available in every project
Plugins
: package and distribute configuration as a
plugin
that teams can install
Launch from the config directory
: run Claude Code from the directory containing the
.claude/
configuration you want
​
How permissions interact with sandboxing
Permissions and
sandboxing
are complementary security layers:
Permissions
control which tools Claude Code can use and which files or domains it can access. They apply to all tools (Bash, Read, Edit, WebFetch, MCP, and others).
Sandboxing
provides OS-level enforcement that restricts the Bash tool’s filesystem and network access. It applies only to Bash commands and their child processes.
Use both for defense-in-depth:
Permission deny rules block Claude from even attempting to access restricted resources
Sandbox restrictions prevent Bash commands from reaching resources outside defined boundaries, even if a prompt injection bypasses Claude’s decision-making
Filesystem restrictions in the sandbox combine the
sandbox.filesystem
settings with Read and Edit deny rules; both are merged into the final sandbox boundary
Network restrictions combine WebFetch permission rules with the sandbox’s
allowedDomains
and
deniedDomains
lists
When sandboxing is enabled with
autoAllowBashIfSandboxed: true
, which is the default, sandboxed Bash commands run without prompting even if your permissions include
ask: Bash(*)
. The sandbox boundary substitutes for the per-command prompt. Explicit deny rules still apply, and
rm
or
rmdir
commands that target
/
, your home directory, or other critical system paths still trigger a prompt. See
sandbox modes
to change this behavior.
​
Managed settings
For organizations that need centralized control over Claude Code configuration, administrators can deploy managed settings that cannot be overridden by user or project settings. These policy settings follow the same format as regular settings files and can be delivered through MDM/OS-level policies, managed settings files, or
server-managed settings
. See
settings files
for delivery mechanisms and file locations.
​
Managed-only settings
The following settings are only read from managed settings. Placing them in user or project settings files has no effect.
Setting
Description
allowedChannelPlugins
Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires
channelsEnabled: true
. See
Restrict which channel plugins can run
allowManagedHooksOnly
When
true
, only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. User, project, and all other plugin hooks are blocked
allowManagedMcpServersOnly
When
true
, only
allowedMcpServers
from managed settings are respected.
deniedMcpServers
still merges from all sources. See
Managed MCP configuration
allowManagedPermissionRulesOnly
When
true
, prevents user and project settings from defining
allow
,
ask
, or
deny
permission rules. Only rules in managed settings apply
blockedMarketplaces
Blocklist of marketplace sources. Blocked sources are checked before downloading, so they never touch the filesystem. See
managed marketplace restrictions
channelsEnabled
Allow
channels
for the organization. See
enterprise controls
for the default on each plan
forceRemoteSettingsRefresh
When
true
, blocks CLI startup until remote managed settings are freshly fetched and exits if the fetch fails. See
fail-closed enforcement
pluginTrustMessage
Custom message appended to the plugin trust warning shown before installation
sandbox.filesystem.allowManagedReadPathsOnly
When
true
, only
filesystem.allowRead
paths from managed settings are respected.
denyRead
still merges from all sources
sandbox.network.allowManagedDomainsOnly
When
true
, only
allowedDomains
and
WebFetch(domain:...)
allow rules from managed settings are respected. Non-allowed domains are blocked automatically without prompting the user. Denied domains still merge from all sources
strictKnownMarketplaces
Controls which plugin marketplace sources users can add and install plugins from. See
managed marketplace restrictions
wslInheritsWindowsSettings
When
true
in the Windows HKLM registry key or
C:\Program Files\ClaudeCode\managed-settings.json
, WSL reads managed settings from the Windows policy chain in addition to
/etc/claude-code
. See
Settings files
disableBypassPermissionsMode
is typically placed in managed settings to enforce organizational policy, but it works from any scope. A user can set it in their own settings to lock themselves out of bypass mode.
On Team and Enterprise plans, an admin enables or disables
Remote Control
and
web sessions
organization-wide in
Claude Code admin settings
. Remote Control can additionally be disabled per device with the
disableRemoteControl
managed setting. Web sessions have no per-device managed settings key.
​
Settings precedence
Permission rules follow the same
settings precedence
as all other Claude Code settings:
Managed settings
: cannot be overridden by any other level, including command line arguments
Command line arguments
: temporary session overrides
Local project settings
(
.claude/settings.local.json
)
Shared project settings
(
.claude/settings.json
)
User settings
(
~/.claude/settings.json
)
If a tool is denied at any level, no other level can allow it. For example, a managed settings deny cannot be overridden by
--allowedTools
, and
--disallowedTools
can add restrictions beyond what managed settings define.
Embedding hosts can supply additional managed policy via the SDK
managedSettings
option when
parentSettingsBehavior
is set to
"merge"
; embedder values can tighten policy but not loosen it.
For example, if user settings allow a permission and project settings deny it, the deny rule blocks it. The reverse is also true: a user-level deny blocks a project-level allow, because deny rules from any scope are evaluated before allow rules.
​
Example configurations
This
repository
includes starter settings configurations for common deployment scenarios. Use these as starting points and adjust them to fit your needs.
​
See also
Settings
: complete configuration reference including the permission settings table
Configure auto mode
: tell the auto mode classifier which infrastructure your organization trusts
Sandboxing
: OS-level filesystem and network isolation for Bash commands
Authentication
: set up user access to Claude Code
Security
: security safeguards and best practices
Hooks
: automate workflows and extend permission evaluation
Was this page helpful?
Yes
No
Settings
Sandboxing
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/permissions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Run parallel sessions with worktrees</title>
  <link>https://code.claude.com/docs/en/worktrees</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/worktrees</guid>
  <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run parallel sessions with worktrees
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
La...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run parallel sessions with worktrees
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
git worktree
is a separate working directory with its own files and branch, sharing the same repository history and remote as your main checkout. Running each Claude Code session in its own worktree means edits in one session never touch files in another, so you can have Claude building a feature in one terminal while fixing a bug in a second.
This page covers worktree isolation in the CLI. Everything below assumes a git repository. For other version control systems, see
Non-git version control
. The
desktop app
creates a worktree for every new session automatically.
Worktrees are one of several ways to run Claude in parallel. They isolate file edits, while
subagents
and
agent teams
coordinate the work itself. See
Run agents in parallel
to compare the approaches, or skip ahead to
Isolate subagents with worktrees
to use worktrees and subagents together.
​
Start Claude in a worktree
Pass
--worktree
or
-w
to create an isolated worktree and start Claude in it. By default, the worktree is created under
.claude/worktrees/<value>/
at your repository root, on a new branch named
worktree-<value>
:
claude
--worktree
feature-auth
To put worktrees somewhere else, configure a
WorktreeCreate
hook
. Run the command again with a different name in another terminal to start a second isolated session:
claude
--worktree
bugfix-123
If you omit the name, Claude generates one such as
bright-running-fox
:
claude
--worktree
You can also ask Claude to “work in a worktree” during a session, and it will create one with the
EnterWorktree
tool.
Before using
--worktree
in a directory for the first time, accept the workspace trust dialog by running
claude
once in that directory. If trust has not yet been accepted,
--worktree
exits with an error and prompts you to run
claude
in the directory first, including when combined with
-p
.
Add
.claude/worktrees/
to your
.gitignore
so worktree contents don’t appear as untracked files in your main checkout.
​
Choose the base branch
Worktrees branch from your repository’s default branch,
origin/HEAD
, so they start from a clean tree matching the remote. If no remote is configured or the fetch fails, the worktree falls back to your current local
HEAD
. To always branch from local
HEAD
instead, set
worktree.baseRef
to
"head"
in
settings
. Setting
baseRef
to
"head"
makes new worktrees carry your unpushed commits and feature-branch state, which is useful when isolating subagents that need to operate on in-progress work. The setting accepts only
"fresh"
or
"head"
, not arbitrary git refs:
{
"worktree"
: {
"baseRef"
:
"head"
}
}
To branch from a specific pull request, pass the PR number prefixed with
#
, or a full GitHub pull request URL. Claude Code fetches
pull/<number>/head
from
origin
and creates the worktree at
.claude/worktrees/pr-<number>
:
claude
--worktree
"#1234"
For full control over how worktrees are created, configure a
WorktreeCreate
hook
, which replaces the default
git worktree
logic entirely.
​
Copy gitignored files into worktrees
A worktree is a fresh checkout, so untracked files like
.env
or
.env.local
from your main repository are not present. To copy them automatically when Claude creates a worktree, add a
.worktreeinclude
file to your project root.
The file uses
.gitignore
syntax. Only files that match a pattern and are also gitignored are copied, so tracked files are never duplicated.
This
.worktreeinclude
copies two env files and a secrets config into each new worktree:
.worktreeinclude
.env
.env.local
config/secrets.json
This applies to worktrees created with
--worktree
,
subagent worktrees
, and parallel sessions in the
desktop app
.
​
Isolate subagents with worktrees
Subagents can run in their own worktrees so parallel edits don’t conflict. Ask Claude to “use worktrees for your agents”, or set it permanently on a
custom subagent
by adding
isolation: worktree
to the frontmatter. Each subagent gets a temporary worktree that is removed automatically when the subagent finishes without changes.
​
Clean up worktrees
When you exit a worktree session, cleanup depends on whether you made changes:
No uncommitted changes, no untracked files, and no new commits
: the worktree and its branch are removed automatically. If the session has a
name
, Claude prompts instead so you can keep the worktree for later
Uncommitted changes, untracked files, or new commits exist
: Claude prompts you to keep or remove the worktree. Keeping preserves the directory and branch so you can return later. Removing deletes the worktree directory and its branch, discarding any uncommitted changes, untracked files, and commits
Non-interactive runs
: worktrees created with
--worktree
alongside
-p
are not cleaned up automatically since there is no exit prompt. Remove them with
git worktree remove
Subagent worktrees orphaned by a crash or interrupted run are removed at startup once they are older than your
cleanupPeriodDays
setting, provided they have no uncommitted changes, no untracked files, and no unpushed commits. Worktrees you create with
--worktree
are never removed by this sweep.
​
Manage worktrees manually
For full control over worktree location and branch configuration, create worktrees with Git directly. This is useful when you need to check out a specific existing branch or place the worktree outside the repository.
Create a worktree on a new branch:
git
worktree
add
../project-feature-a
-b
feature-a
Create a worktree from an existing branch:
git
worktree
add
../project-bugfix
bugfix-123
Start Claude in the worktree:
cd
../project-feature-a
&&
claude
List your worktrees:
git
worktree
list
Remove one when you’re done with it:
git
worktree
remove
../project-feature-a
See the
Git worktree documentation
for the full command reference. Remember to initialize your development environment in each new worktree: install dependencies, set up virtual environments, or run whatever your project’s setup requires.
​
Non-git version control
Worktree isolation uses git by default. For SVN, Perforce, Mercurial, or other systems, configure
WorktreeCreate
and
WorktreeRemove
hooks
to provide custom creation and cleanup logic. Because the hook replaces the default git behavior,
.worktreeinclude
is not processed when you use
--worktree
. Copy any local configuration files inside your hook script instead.
This
WorktreeCreate
hook reads the worktree name from stdin, checks out a fresh SVN working copy, and prints the directory path so Claude Code can use it as the session’s working directory:
{
"hooks"
: {
"WorktreeCreate"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'NAME=$(jq -r .name); DIR=
\"
$HOME/.claude/worktrees/$NAME
\"
; svn checkout https://svn.example.com/repo/trunk
\"
$DIR
\"
>&2 && echo
\"
$DIR
\"
'"
}
]
}
]
}
}
Pair it with a
WorktreeRemove
hook to clean up when the session ends. See the
hooks reference
for the input schema and a removal example.
​
See also
Worktrees handle file isolation. The related pages below cover delegating work into those isolated checkouts and switching between the sessions you create:
Subagents
: delegate work to isolated agents within a session
Agent teams
: coordinate multiple Claude sessions automatically
Manage sessions
: name, resume, and switch between conversations
Desktop parallel sessions
: worktree-backed sessions in the desktop app
Was this page helpful?
Yes
No
Run agent teams
Model Context Protocol (MCP)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/worktrees" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run parallel sessions with worktrees
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
La...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run parallel sessions with worktrees
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
git worktree
is a separate working directory with its own files and branch, sharing the same repository history and remote as your main checkout. Running each Claude Code session in its own worktree means edits in one session never touch files in another, so you can have Claude building a feature in one terminal while fixing a bug in a second.
This page covers worktree isolation in the CLI. Everything below assumes a git repository. For other version control systems, see
Non-git version control
. The
desktop app
creates a worktree for every new session automatically.
Worktrees are one of several ways to run Claude in parallel. They isolate file edits, while
subagents
and
agent teams
coordinate the work itself. See
Run agents in parallel
to compare the approaches, or skip ahead to
Isolate subagents with worktrees
to use worktrees and subagents together.
​
Start Claude in a worktree
Pass
--worktree
or
-w
to create an isolated worktree and start Claude in it. By default, the worktree is created under
.claude/worktrees/<value>/
at your repository root, on a new branch named
worktree-<value>
:
claude
--worktree
feature-auth
To put worktrees somewhere else, configure a
WorktreeCreate
hook
. Run the command again with a different name in another terminal to start a second isolated session:
claude
--worktree
bugfix-123
If you omit the name, Claude generates one such as
bright-running-fox
:
claude
--worktree
You can also ask Claude to “work in a worktree” during a session, and it will create one with the
EnterWorktree
tool.
Before using
--worktree
in a directory for the first time, accept the workspace trust dialog by running
claude
once in that directory. If trust has not yet been accepted,
--worktree
exits with an error and prompts you to run
claude
in the directory first, including when combined with
-p
.
Add
.claude/worktrees/
to your
.gitignore
so worktree contents don’t appear as untracked files in your main checkout.
​
Choose the base branch
Worktrees branch from your repository’s default branch,
origin/HEAD
, so they start from a clean tree matching the remote. If no remote is configured or the fetch fails, the worktree falls back to your current local
HEAD
. To always branch from local
HEAD
instead, set
worktree.baseRef
to
"head"
in
settings
. Setting
baseRef
to
"head"
makes new worktrees carry your unpushed commits and feature-branch state, which is useful when isolating subagents that need to operate on in-progress work. The setting accepts only
"fresh"
or
"head"
, not arbitrary git refs:
{
"worktree"
: {
"baseRef"
:
"head"
}
}
To branch from a specific pull request, pass the PR number prefixed with
#
, or a full GitHub pull request URL. Claude Code fetches
pull/<number>/head
from
origin
and creates the worktree at
.claude/worktrees/pr-<number>
:
claude
--worktree
"#1234"
For full control over how worktrees are created, configure a
WorktreeCreate
hook
, which replaces the default
git worktree
logic entirely.
​
Copy gitignored files into worktrees
A worktree is a fresh checkout, so untracked files like
.env
or
.env.local
from your main repository are not present. To copy them automatically when Claude creates a worktree, add a
.worktreeinclude
file to your project root.
The file uses
.gitignore
syntax. Only files that match a pattern and are also gitignored are copied, so tracked files are never duplicated.
This
.worktreeinclude
copies two env files and a secrets config into each new worktree:
.worktreeinclude
.env
.env.local
config/secrets.json
This applies to worktrees created with
--worktree
,
subagent worktrees
, and parallel sessions in the
desktop app
.
​
Isolate subagents with worktrees
Subagents can run in their own worktrees so parallel edits don’t conflict. Ask Claude to “use worktrees for your agents”, or set it permanently on a
custom subagent
by adding
isolation: worktree
to the frontmatter. Each subagent gets a temporary worktree that is removed automatically when the subagent finishes without changes.
​
Clean up worktrees
When you exit a worktree session, cleanup depends on whether you made changes:
No uncommitted changes, no untracked files, and no new commits
: the worktree and its branch are removed automatically. If the session has a
name
, Claude prompts instead so you can keep the worktree for later
Uncommitted changes, untracked files, or new commits exist
: Claude prompts you to keep or remove the worktree. Keeping preserves the directory and branch so you can return later. Removing deletes the worktree directory and its branch, discarding any uncommitted changes, untracked files, and commits
Non-interactive runs
: worktrees created with
--worktree
alongside
-p
are not cleaned up automatically since there is no exit prompt. Remove them with
git worktree remove
Subagent worktrees orphaned by a crash or interrupted run are removed at startup once they are older than your
cleanupPeriodDays
setting, provided they have no uncommitted changes, no untracked files, and no unpushed commits. Worktrees you create with
--worktree
are never removed by this sweep.
​
Manage worktrees manually
For full control over worktree location and branch configuration, create worktrees with Git directly. This is useful when you need to check out a specific existing branch or place the worktree outside the repository.
Create a worktree on a new branch:
git
worktree
add
../project-feature-a
-b
feature-a
Create a worktree from an existing branch:
git
worktree
add
../project-bugfix
bugfix-123
Start Claude in the worktree:
cd
../project-feature-a
&&
claude
List your worktrees:
git
worktree
list
Remove one when you’re done with it:
git
worktree
remove
../project-feature-a
See the
Git worktree documentation
for the full command reference. Remember to initialize your development environment in each new worktree: install dependencies, set up virtual environments, or run whatever your project’s setup requires.
​
Non-git version control
Worktree isolation uses git by default. For SVN, Perforce, Mercurial, or other systems, configure
WorktreeCreate
and
WorktreeRemove
hooks
to provide custom creation and cleanup logic. Because the hook replaces the default git behavior,
.worktreeinclude
is not processed when you use
--worktree
. Copy any local configuration files inside your hook script instead.
This
WorktreeCreate
hook reads the worktree name from stdin, checks out a fresh SVN working copy, and prints the directory path so Claude Code can use it as the session’s working directory:
{
"hooks"
: {
"WorktreeCreate"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'NAME=$(jq -r .name); DIR=
\"
$HOME/.claude/worktrees/$NAME
\"
; svn checkout https://svn.example.com/repo/trunk
\"
$DIR
\"
>&2 && echo
\"
$DIR
\"
'"
}
]
}
]
}
}
Pair it with a
WorktreeRemove
hook to clean up when the session ends. See the
hooks reference
for the input schema and a removal example.
​
See also
Worktrees handle file isolation. The related pages below cover delegating work into those isolated checkouts and switching between the sessions you create:
Subagents
: delegate work to isolated agents within a session
Agent teams
: coordinate multiple Claude sessions automatically
Manage sessions
: name, resume, and switch between conversations
Desktop parallel sessions
: worktree-backed sessions in the desktop app
Was this page helpful?
Yes
No
Run agent teams
Model Context Protocol (MCP)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/worktrees" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 18 · April 27 – May 1, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w18</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w18</guid>
  <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 18 · April 27 – May 1, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.120 → v2.1.126
4 fea...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 18 · April 27 – May 1, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.120 → v2.1.126
4 features · April 27 – May 1
Sign in without a browser callback
v2.1.126
claude auth login
now accepts the OAuth code pasted directly into the terminal when the browser callback can’t reach localhost. That covers WSL2, SSH sessions, and containers, where the redirect to a local port doesn’t work. The same release also fixes login timeouts on slow or proxied connections and in IPv6-only devcontainers.
Sign in, then paste the code from the browser:
claude
auth
login
CLI reference
claude project purge
v2.1.126
Delete all Claude Code state for a project: transcripts, tasks, file history, and the project’s config entry. Supports
--dry-run
to preview,
-y
/
--yes
to skip confirmation,
-i
/
--interactive
to choose, and
--all
to clear every project.
Preview what would be removed:
claude
project
purge
--dry-run
Then run it for real:
claude
project
purge
CLI reference
Resume by PR URL
v2.1.122
When you create a pull request with
gh pr create
, Claude Code links it to the session that produced it. Now you can get back to that session from the PR URL alone, without remembering its name.
Open the session picker:
Claude Code
> /resume
Paste the PR URL into the picker. The first character of the paste drops you into search mode, and the list filters to the session that created that PR. Press Enter to resume it. GitHub, GitHub Enterprise, GitLab, and Bitbucket pull and merge request URLs all work.
Claude Code
https://github.com/your-org/your-repo/pull/1234
To skip the picker, pass the PR number on the command line instead:
claude
--from-pr
1234
Sessions: use the session picker
Windows without Git Bash
Windows
Git for Windows is no longer required. When Bash is absent, Claude Code uses PowerShell as the shell tool, and when the PowerShell tool is enabled it is treated as the primary shell. PowerShell 7 installed via the Microsoft Store, MSI without PATH, or a
.NET
global tool is now detected automatically.
Setup guide
Other wins
MCP servers can opt out of tool-search deferral with
alwaysLoad: true
in their config so all of that server’s tools are always available
New
claude plugin prune
removes orphaned auto-installed plugin dependencies, and
plugin uninstall —prune
cascades
/skills
now has a type-to-filter search box so you can find a skill in a long list without scrolling
PostToolUse
hooks can replace tool output for any tool via
hookSpecificOutput.updatedToolOutput
, not only MCP tools
New
claude ultrareview
subcommand runs
/ultrareview
non-interactively from CI or scripts: prints findings to stdout (
—json
for raw output) and exits 0 on completion or 1 on failure
—dangerously-skip-permissions
now bypasses prompts for writes to
.claude/
,
.git/
,
.vscode/
, shell config files, and other previously protected paths, while catastrophic removal commands still prompt as a safety net
The
/model
picker can list models from your gateway’s
/v1/models
endpoint when
ANTHROPIC_BASE_URL
points at an Anthropic-compatible gateway; opt in with
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
since v2.1.129
MCP servers that hit a transient error during startup now auto-retry up to 3 times instead of staying disconnected
ANTHROPIC_BEDROCK_SERVICE_TIER
selects a Bedrock service tier:
default
,
flex
, or
priority
/terminal-setup
enables iTerm2’s clipboard access setting so
/copy
works, including from tmux
Vertex AI now supports X.509 certificate-based Workload Identity Federation (mTLS ADC)
Significant memory leak fixes: image-heavy sessions,
/usage
on large transcript histories, and long-running tools without progress events
Full changelog for v2.1.120–v2.1.126 →
Was this page helpful?
Yes
No
Week 19 · May 4–8
Week 17 · Apr 20–24
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w18" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 18 · April 27 – May 1, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.120 → v2.1.126
4 fea...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 18 · April 27 – May 1, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.120 → v2.1.126
4 features · April 27 – May 1
Sign in without a browser callback
v2.1.126
claude auth login
now accepts the OAuth code pasted directly into the terminal when the browser callback can’t reach localhost. That covers WSL2, SSH sessions, and containers, where the redirect to a local port doesn’t work. The same release also fixes login timeouts on slow or proxied connections and in IPv6-only devcontainers.
Sign in, then paste the code from the browser:
claude
auth
login
CLI reference
claude project purge
v2.1.126
Delete all Claude Code state for a project: transcripts, tasks, file history, and the project’s config entry. Supports
--dry-run
to preview,
-y
/
--yes
to skip confirmation,
-i
/
--interactive
to choose, and
--all
to clear every project.
Preview what would be removed:
claude
project
purge
--dry-run
Then run it for real:
claude
project
purge
CLI reference
Resume by PR URL
v2.1.122
When you create a pull request with
gh pr create
, Claude Code links it to the session that produced it. Now you can get back to that session from the PR URL alone, without remembering its name.
Open the session picker:
Claude Code
> /resume
Paste the PR URL into the picker. The first character of the paste drops you into search mode, and the list filters to the session that created that PR. Press Enter to resume it. GitHub, GitHub Enterprise, GitLab, and Bitbucket pull and merge request URLs all work.
Claude Code
https://github.com/your-org/your-repo/pull/1234
To skip the picker, pass the PR number on the command line instead:
claude
--from-pr
1234
Sessions: use the session picker
Windows without Git Bash
Windows
Git for Windows is no longer required. When Bash is absent, Claude Code uses PowerShell as the shell tool, and when the PowerShell tool is enabled it is treated as the primary shell. PowerShell 7 installed via the Microsoft Store, MSI without PATH, or a
.NET
global tool is now detected automatically.
Setup guide
Other wins
MCP servers can opt out of tool-search deferral with
alwaysLoad: true
in their config so all of that server’s tools are always available
New
claude plugin prune
removes orphaned auto-installed plugin dependencies, and
plugin uninstall —prune
cascades
/skills
now has a type-to-filter search box so you can find a skill in a long list without scrolling
PostToolUse
hooks can replace tool output for any tool via
hookSpecificOutput.updatedToolOutput
, not only MCP tools
New
claude ultrareview
subcommand runs
/ultrareview
non-interactively from CI or scripts: prints findings to stdout (
—json
for raw output) and exits 0 on completion or 1 on failure
—dangerously-skip-permissions
now bypasses prompts for writes to
.claude/
,
.git/
,
.vscode/
, shell config files, and other previously protected paths, while catastrophic removal commands still prompt as a safety net
The
/model
picker can list models from your gateway’s
/v1/models
endpoint when
ANTHROPIC_BASE_URL
points at an Anthropic-compatible gateway; opt in with
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
since v2.1.129
MCP servers that hit a transient error during startup now auto-retry up to 3 times instead of staying disconnected
ANTHROPIC_BEDROCK_SERVICE_TIER
selects a Bedrock service tier:
default
,
flex
, or
priority
/terminal-setup
enables iTerm2’s clipboard access setting so
/copy
works, including from tmux
Vertex AI now supports X.509 certificate-based Workload Identity Federation (mTLS ADC)
Significant memory leak fixes: image-heavy sessions,
/usage
on large transcript histories, and long-running tools without progress events
Full changelog for v2.1.120–v2.1.126 →
Was this page helpful?
Yes
No
Week 19 · May 4–8
Week 17 · Apr 20–24
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w18" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Use Claude Code in VS Code</title>
  <link>https://code.claude.com/docs/en/vs-code</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/vs-code</guid>
  <pubDate>Wed, 19 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code in VS Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extensi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code in VS Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The VS Code extension provides a native graphical interface for Claude Code, integrated directly into your IDE. This is the recommended way to use Claude Code in VS Code.
With the extension, you can review and edit Claude’s plans before accepting them, auto-accept edits as they’re made, @-mention files with specific line ranges from your selection, access conversation history, and open multiple conversations in separate tabs or windows.
​
Prerequisites
Before installing, make sure you have:
VS Code 1.98.0 or higher
An Anthropic account (you’ll sign in when you first open the extension). If you’re using a third-party provider like Amazon Bedrock or Google Vertex AI, see
Use third-party providers
instead.
The extension includes the CLI (command-line interface), which you can access from VS Code’s integrated terminal for advanced features. See
VS Code extension vs. Claude Code CLI
for details.
​
Install the extension
Click the link for your IDE to install directly:
Install for VS Code
Install for Cursor
Or in VS Code, press
Cmd+Shift+X
(Mac) or
Ctrl+Shift+X
(Windows/Linux) to open the Extensions view, search for “Claude Code”, and click
Install
.
The extension also installs in other VS Code forks like Windsurf or Kiro. Search for “Claude Code” in the editor’s Extensions view, or install from the
Open VSX registry
. If your editor can’t install the extension, run
claude
in its integrated terminal instead. The
CLI
works in any terminal.
If the extension doesn’t appear after installation, restart VS Code or run “Developer: Reload Window” from the Command Palette.
​
Get started
Once installed, you can start using Claude Code through the VS Code interface:
1
Open the Claude Code panel
Throughout VS Code, the Spark icon indicates Claude Code:
The quickest way to open Claude is to click the Spark icon in the
Editor Toolbar
(top-right corner of the editor). The icon only appears when you have a file open.
Other ways to open Claude Code:
Activity Bar
: click the Spark icon in the left sidebar to open the sessions list. Click any session to open it as a full editor tab, or start a new one. This icon is always visible in the Activity Bar.
Command Palette
:
Cmd+Shift+P
(Mac) or
Ctrl+Shift+P
(Windows/Linux), type “Claude Code”, and select an option like “Open in New Tab”
Status Bar
: click
✱ Claude Code
in the bottom-right corner of the window. This works even when no file is open.
You can drag the Claude panel to reposition it anywhere in VS Code. See
Customize your workflow
for details.
2
Sign in
The first time you open the panel, a sign-in screen appears. Click
Sign in
and complete authorization in your browser.
If you see
Not logged in · Please run /login
later, the extension reopens the sign-in screen automatically. If it doesn’t appear, reload the window from the Command Palette with
Developer: Reload Window
.
If you have
ANTHROPIC_API_KEY
set in your shell but still see the sign-in prompt, VS Code may not have inherited your shell environment. Launch VS Code from a terminal with
code .
so it inherits your environment variables, or sign in with your Claude account instead.
After you sign in, a
Learn Claude Code
checklist appears. Work through each item by clicking
Show me
, or dismiss it with the X. To reopen it later, uncheck
Hide Onboarding
in VS Code settings under Extensions → Claude Code.
3
Send a prompt
Ask Claude to help with your code or files, whether that’s explaining how something works, debugging an issue, or making changes.
Claude automatically sees your selected text. Press
Option+K
(Mac) /
Alt+K
(Windows/Linux) to also insert an @-mention reference (like
@file.ts#5-10
) into your prompt.
Here’s an example of asking about a particular line in a file:
4
Review changes
When Claude wants to edit a file, it shows a side-by-side comparison of the original and proposed changes, then asks for permission. You can accept, reject, or tell Claude what to do instead. If you edit the proposed content directly in the diff view before accepting, Claude is told that you modified it so it does not assume the file matches its original proposal.
For more ideas on what you can do with Claude Code, see
Common workflows
.
Run “Claude Code: Open Walkthrough” from the Command Palette for a guided tour of the basics.
​
Use the prompt box
The prompt box supports several features:
Permission modes
: click the mode indicator at the bottom of the prompt box to switch modes. In normal mode, Claude asks permission before each action. In Plan mode, Claude describes what it will do and waits for approval before making changes. VS Code automatically opens the plan as a full markdown document where you can add inline comments to give feedback before Claude begins. In auto-accept mode, Claude makes edits without asking. Set the default in VS Code settings under
claudeCode.initialPermissionMode
.
Command menu
: click
/
or type
/
to open the command menu. Options include attaching files, switching models, toggling extended thinking, viewing plan usage (
/usage
), and starting a
Remote Control
session (
/remote-control
). The Customize section provides access to MCP servers, hooks, memory, permissions, and plugins. Items with a terminal icon open in the integrated terminal.
Context indicator
: the prompt box shows how much of Claude’s context window you’re using. Claude automatically compacts when needed, or you can run
/compact
manually.
Extended thinking
: lets Claude spend more time reasoning through complex problems. Toggle it on via the command menu (
/
). Claude’s reasoning appears in the conversation as collapsed blocks: click a block to read it, or press
Ctrl+O
to expand or collapse every thinking block in the session. See
Extended thinking
for details.
Multi-line input
: press
Shift+Enter
to add a new line without sending. This also works in the “Other” free-text input of question dialogs.
​
Reference files and folders
Use @-mentions to give Claude context about specific files or folders. When you type
@
followed by a file or folder name, Claude reads that content and can answer questions about it or make changes to it. Claude Code supports fuzzy matching, so you can type partial names to find what you need:
> Explain the logic in @auth (fuzzy matches auth.js, AuthService.ts, etc.)
> What's in @src/components/ (include a trailing slash for folders)
For large PDFs, you can ask Claude to read specific pages instead of the whole file: a single page, a range like pages 1-10, or an open-ended range like page 3 onward.
When you select text in the editor, Claude can see your highlighted code automatically. The prompt box footer shows how many lines are selected. Press
Option+K
(Mac) /
Alt+K
(Windows/Linux) to insert an @-mention with the file path and line numbers (e.g.,
@app.ts#5-10
). Click the selection indicator to toggle whether Claude can see your highlighted text - the eye-slash icon means the selection is hidden from Claude.
You can also hold
Shift
while dragging files into the prompt box to add them as attachments. Click the X on any attachment to remove it from context.
​
Resume past conversations
Click the
Session history
button at the top of the Claude Code panel to access your conversation history. You can search by keyword or browse by time (Today, Yesterday, Last 7 days, etc.). Click any conversation to resume it with the full message history. New sessions receive AI-generated titles based on your first message. Hover over a session to reveal rename and remove actions: rename to give it a descriptive title, or remove to delete it from the list. For more on resuming sessions, see
Manage sessions
.
​
Resume remote sessions from Claude.ai
If you use
Claude Code on the web
, you can resume those remote sessions directly in VS Code. This requires signing in with
Claude.ai Subscription
, not Anthropic Console.
1
Open session history
Click the
Session history
button at the top of the Claude Code panel.
2
Select the Remote tab
The dialog shows two tabs: Local and Remote. Click
Remote
to see sessions from claude.ai.
3
Select a session to resume
Browse or search your remote sessions. Click any session to download it and continue the conversation locally.
Only web sessions started with a GitHub repository appear in the Remote tab. Resuming loads the conversation history locally; changes are not synced back to claude.ai.
​
Customize your workflow
Once you’re up and running, you can reposition the Claude panel, run multiple sessions, or switch to terminal mode.
​
Choose where Claude lives
You can drag the Claude panel to reposition it anywhere in VS Code. Grab the panel’s tab or title bar and drag it to:
Secondary sidebar
: the right side of the window. Keeps Claude visible while you code.
Primary sidebar
: the left sidebar with icons for Explorer, Search, etc.
Editor area
: opens Claude as a tab alongside your files. Useful for side tasks.
Use the sidebar for your main Claude session and open additional tabs for side tasks. Claude remembers your preferred location. The Activity Bar sessions list icon is separate from the Claude panel: the sessions list is always visible in the Activity Bar, while the Claude panel icon only appears there when the panel is docked to the left sidebar.
​
Run multiple conversations
Use
Open in New Tab
or
Open in New Window
from the Command Palette to start additional conversations. Each conversation maintains its own history and context, allowing you to work on different tasks in parallel.
When using tabs, a small colored dot on the spark icon indicates status: blue means a permission request is pending, orange means Claude finished while the tab was hidden.
​
Switch to terminal mode
By default, the extension opens a graphical chat panel. If you prefer the CLI-style interface, open the
Use Terminal setting
and check the box.
You can also open VS Code settings (
Cmd+,
on Mac or
Ctrl+,
on Windows/Linux), go to Extensions → Claude Code, and check
Use Terminal
.
​
Manage plugins
The VS Code extension includes a graphical interface for installing and managing
plugins
. Type
/plugins
in the prompt box to open the
Manage plugins
interface.
​
Install plugins
The plugin dialog shows two tabs:
Plugins
and
Marketplaces
.
In the Plugins tab:
Installed plugins
appear at the top with toggle switches to enable or disable them
Available plugins
from your configured marketplaces appear below
Search to filter plugins by name or description
Click
Install
on any available plugin
When you install a plugin, choose the installation scope:
Install for you
: available in all your projects (user scope)
Install for this project
: shared with project collaborators (project scope)
Install locally
: only for you, only in this repository (local scope)
​
Manage marketplaces
Switch to the
Marketplaces
tab to add or remove plugin sources:
Enter a GitHub repo, URL, or local path to add a new marketplace
Click the refresh icon to update a marketplace’s plugin list
Click the trash icon to remove a marketplace
After making changes, a banner prompts you to restart Claude Code to apply the updates.
Plugin management in VS Code uses the same CLI commands under the hood. Plugins and marketplaces you configure in the extension are also available in the CLI, and vice versa.
For more about the plugin system, see
Plugins
and
Plugin marketplaces
.
​
Automate browser tasks with Chrome
Connect Claude to your Chrome browser to test web apps, debug with console logs, and automate browser workflows without leaving VS Code. This requires the
Claude in Chrome extension
version 1.0.36 or higher.
Type
@browser
in the prompt box followed by what you want Claude to do:
@browser go to localhost:3000 and check the console for errors
You can also open the attachment menu to select specific browser tools like opening a new tab or reading page content.
Claude opens new tabs for browser tasks and shares your browser’s login state, so it can access any site you’re already signed into.
For setup instructions, the full list of capabilities, and troubleshooting, see
Use Claude Code with Chrome
.
​
VS Code commands and shortcuts
Open the Command Palette (
Cmd+Shift+P
on Mac or
Ctrl+Shift+P
on Windows/Linux) and type “Claude Code” to see all available VS Code commands for the Claude Code extension.
Some shortcuts depend on which panel is “focused” (receiving keyboard input). When your cursor is in a code file, the editor is focused. When your cursor is in Claude’s prompt box, Claude is focused. Use
Cmd+Esc
/
Ctrl+Esc
to toggle between them.
These are VS Code commands for controlling the extension. Not all built-in Claude Code commands are available in the extension. See
VS Code extension vs. Claude Code CLI
for details.
Command
Shortcut
Description
Focus Input
Cmd+Esc
(Mac) /
Ctrl+Esc
(Windows/Linux)
Toggle focus between editor and Claude
Open in Side Bar
-
Open Claude in the left sidebar
Open in Terminal
-
Open Claude in terminal mode
Open in New Tab
Cmd+Shift+Esc
(Mac) /
Ctrl+Shift+Esc
(Windows/Linux)
Open a new conversation as an editor tab
Open in New Window
-
Open a new conversation in a separate window
New Conversation
Cmd+N
(Mac) /
Ctrl+N
(Windows/Linux)
Start a new conversation. Requires Claude to be focused and
enableNewConversationShortcut
set to
true
Reopen Closed Session
Cmd+Shift+T
(Mac) /
Ctrl+Shift+T
(Windows/Linux)
Reopen the most recently closed Claude session tab. Falls through to VS Code’s normal reopen-closed-editor when the last closed tab wasn’t a Claude session. Disable with
enableReopenClosedSessionShortcut
Insert @-Mention Reference
Option+K
(Mac) /
Alt+K
(Windows/Linux)
Insert a reference to the current file and selection (requires editor to be focused)
Show Logs
-
View extension debug logs
Logout
-
Sign out of your Anthropic account
​
Launch a VS Code tab from other tools
The extension registers a URI handler at
vscode://anthropic.claude-code/open
. Use it to open a new Claude Code tab from your own tooling: a shell alias, a browser bookmarklet, or any script that can open a URL. If VS Code isn’t already running, opening the URL launches it first. If VS Code is already running, the URL opens in whichever window is currently focused.
Invoke the handler with your operating system’s URL opener.
macOS
Linux
Windows
open
"vscode://anthropic.claude-code/open"
xdg-open
"vscode://anthropic.claude-code/open"
In PowerShell:
Start-Process
"vscode://anthropic.claude-code/open"
In
cmd.exe
,
start
treats its first quoted argument as a window title, so pass an empty title before the URL:
start
""
"vscode://anthropic.claude-code/open"
The handler accepts two optional query parameters:
Parameter
Description
prompt
Text to pre-fill in the prompt box. Must be URL-encoded. The prompt is pre-filled but not submitted automatically.
session
A session ID to resume instead of starting a new conversation. The session must belong to the workspace currently open in VS Code. If the session isn’t found, a fresh conversation starts instead. If the session is already open in a tab, that tab is focused. To capture a session ID programmatically, see
Continue conversations
.
For example, to open a tab pre-filled with “review my changes”:
vscode://anthropic.claude-code/open?prompt=review%20my%20changes
To launch a terminal session instead of a VS Code tab, use the CLI’s
claude-cli://
handler. See
Launch sessions from links
.
​
Configure settings
The extension has two types of settings:
Extension settings
in VS Code: control the extension’s behavior within VS Code. Open with
Cmd+,
(Mac) or
Ctrl+,
(Windows/Linux), then go to Extensions → Claude Code. You can also type
/
and select
General Config
to open settings.
Claude Code settings
in
~/.claude/settings.json
: shared between the extension and CLI. Use for allowed commands, environment variables, hooks, and MCP servers. See
Settings
for details.
Add
"$schema": "https://json.schemastore.org/claude-code-settings.json"
to your
settings.json
to get autocomplete and inline validation for all available settings directly in VS Code.
​
Extension settings
Setting
Default
Description
useTerminal
false
Launch Claude in terminal mode instead of graphical panel
initialPermissionMode
default
Controls approval prompts for new conversations:
default
,
plan
,
acceptEdits
, or
bypassPermissions
. See
permission modes
.
preferredLocation
panel
Where Claude opens:
sidebar
(right) or
panel
(new tab)
autosave
true
Auto-save files before Claude reads or writes them
useCtrlEnterToSend
false
Use Ctrl/Cmd+Enter instead of Enter to send prompts
enableNewConversationShortcut
false
Enable Cmd/Ctrl+N to start a new conversation
enableReopenClosedSessionShortcut
true
Use Cmd/Ctrl+Shift+T to reopen the most recently closed Claude session tab. When the last closed tab wasn’t a Claude session, the shortcut runs VS Code’s normal reopen-closed-editor command instead.
hideOnboarding
false
Hide the onboarding checklist (graduation cap icon)
respectGitIgnore
true
Exclude .gitignore patterns from file searches
usePythonEnvironment
true
Activate the workspace’s Python environment when running Claude. Requires the Python extension.
environmentVariables
[]
Set environment variables for the Claude process. Use Claude Code settings instead for shared config.
disableLoginPrompt
false
Skip authentication prompts (for third-party provider setups)
allowDangerouslySkipPermissions
false
Adds
Auto mode
and Bypass permissions to the mode selector. Auto mode has
plan, admin, model, and provider requirements
, so it may remain unavailable even with this toggle on. Use Bypass permissions only in sandboxes with no internet access.
claudeProcessWrapper
-
Executable used to launch the Claude process. The bundled binary path is passed as an argument when present. Set this to a separately installed
claude
binary if the extension build doesn’t include one for your platform.
​
VS Code extension vs. Claude Code CLI
Claude Code is available as both a VS Code extension (graphical panel) and a CLI (command-line interface in the terminal). Some features are only available in the CLI. If you need a CLI-only feature, run
claude
in VS Code’s integrated terminal.
Feature
CLI
VS Code Extension
Commands and skills
All
Subset (type
/
to see available)
MCP server config
Yes
Partial (add servers via CLI; manage existing servers with
/mcp
in the chat panel)
Checkpoints
Yes
Yes
!
bash shortcut
Yes
No
Tab completion
Yes
No
​
Rewind with checkpoints
The VS Code extension supports checkpoints, which track Claude’s file edits and let you rewind to a previous state. Hover over any message to reveal the rewind button, then choose from three options:
Fork conversation from here
: start a new conversation branch from this message while keeping all code changes intact
Rewind code to here
: revert file changes back to this point in the conversation while keeping the full conversation history
Fork conversation and rewind code
: start a new conversation branch and revert file changes to this point
For full details on how checkpoints work and their limitations, see
Checkpointing
.
​
Run CLI in VS Code
To use the CLI while staying in VS Code, open the integrated terminal (
Ctrl+`
on Windows/Linux or
Cmd+`
on Mac) and run
claude
. The CLI automatically integrates with your IDE for features like diff viewing and diagnostic sharing.
If using an external terminal, run
/ide
inside Claude Code to connect it to VS Code.
​
Switch between extension and CLI
The extension and CLI share the same conversation history. To continue an extension conversation in the CLI, run
claude --resume
in the terminal. This opens an interactive picker where you can search for and select your conversation.
​
Include terminal output in prompts
Reference terminal output in your prompts using
@terminal:name
where
name
is the terminal’s title. This lets Claude see command output, error messages, or logs without copy-pasting.
​
Monitor background processes
When Claude runs long-running commands, the extension shows progress in the status bar. However, visibility for background tasks is limited compared to the CLI. For better visibility, have Claude output the command so you can run it in VS Code’s integrated terminal.
​
Connect to external tools with MCP
MCP (Model Context Protocol) servers give Claude access to external tools, databases, and APIs.
To add an MCP server, open the integrated terminal (
Ctrl+`
or
Cmd+`
) and run
claude mcp add
. The example below adds GitHub’s remote MCP server, which authenticates with a
personal access token
passed as a header:
claude
mcp
add
--transport
http
github
https://api.githubcopilot.com/mcp/
\
--header
"Authorization: Bearer YOUR_GITHUB_PAT"
Once configured, ask Claude to use the tools (e.g., “Review PR #456”).
To manage MCP servers without leaving VS Code, type
/mcp
in the chat panel. The MCP management dialog lets you enable or disable servers, reconnect to a server, and manage OAuth authentication. See the
MCP documentation
for available servers.
​
Work with git
Claude Code integrates with git to help with version control workflows directly in VS Code. Ask Claude to commit changes, create pull requests, or work across branches.
​
Create commits and pull requests
Claude can stage changes, write commit messages, and create pull requests based on your work:
> commit my changes with a descriptive message
> create a pr for this feature
> summarize the changes I've made to the auth module
When creating pull requests, Claude generates descriptions based on the actual code changes and can add context about testing or implementation decisions.
​
Use git worktrees for parallel tasks
Use the
--worktree
(
-w
) flag to start Claude in an isolated worktree with its own files and branch:
claude
--worktree
feature-auth
Each worktree maintains independent file state while sharing git history. This prevents Claude instances from interfering with each other when working on different tasks. For more details, see
Run parallel sessions with Git worktrees
.
​
Use third-party providers
By default, Claude Code connects directly to Anthropic’s API. If your organization uses Amazon Bedrock, Google Vertex AI, or Microsoft Foundry to access Claude, configure the extension to use your provider instead:
1
Disable login prompt
Open the
Disable Login Prompt setting
and check the box.
You can also open VS Code settings (
Cmd+,
on Mac or
Ctrl+,
on Windows/Linux), search for “Claude Code login”, and check
Disable Login Prompt
.
2
Configure your provider
Follow the setup guide for your provider:
Claude Code on Amazon Bedrock
Claude Code on Google Vertex AI
Claude Code on Microsoft Foundry
These guides cover configuring your provider in
~/.claude/settings.json
, which ensures your settings are shared between the VS Code extension and the CLI.
​
Security and privacy
Your code stays private. Claude Code processes your code to provide assistance but does not use it to train models. For details on data handling and how to opt out of logging, see
Data and privacy
.
With auto-edit permissions enabled, Claude Code can modify VS Code configuration files (like
settings.json
or
tasks.json
) that VS Code may execute automatically. To reduce risk when working with untrusted code:
Enable
VS Code Restricted Mode
for untrusted workspaces
Use manual approval mode instead of auto-accept for edits
Review changes carefully before accepting them
​
The built-in IDE MCP server
When the extension is active, it runs a local MCP server that the CLI connects to automatically. This is how the CLI opens diffs in VS Code’s native diff viewer, reads your current selection for
@
-mentions, and — when you’re working in a Jupyter notebook — asks VS Code to execute cells.
The server is named
ide
and is hidden from
/mcp
because there’s nothing to configure. If your organization uses a
PreToolUse
hook to allowlist MCP tools, though, you’ll need to know it exists.
Transport and authentication.
The server binds to
127.0.0.1
on a random high port and is not reachable from other machines. Each extension activation generates a fresh random auth token that the CLI must present to connect. The token is written to a lock file under
~/.claude/ide/
with
0600
permissions in a
0700
directory, so only the user running VS Code can read it.
Tools exposed to the model.
The server hosts a dozen tools, but only two are visible to the model. The rest are internal RPC the CLI uses for its own UI — opening diffs, reading selections, saving files — and are filtered out before the tool list reaches Claude.
Tool name (as seen by hooks)
What it does
Writes?
mcp__ide__getDiagnostics
Returns language-server diagnostics — the errors and warnings in VS Code’s Problems panel. Optionally scoped to one file.
No
mcp__ide__executeCode
Runs Python code in the active Jupyter notebook’s kernel. See confirmation flow below.
Yes
Jupyter execution always asks first.
mcp__ide__executeCode
can’t run anything silently. On each call, the code is inserted as a new cell at the end of the active notebook, VS Code scrolls it into view, and a native Quick Pick asks you to
Execute
or
Cancel
. Cancelling — or dismissing the picker with
Esc
— returns an error to Claude and nothing runs. The tool also refuses outright when there’s no active notebook, when the Jupyter extension (
ms-toolsai.jupyter
) isn’t installed, or when the kernel isn’t Python.
The Quick Pick confirmation is separate from
PreToolUse
hooks. An allowlist entry for
mcp__ide__executeCode
lets Claude
propose
running a cell; the Quick Pick inside VS Code is what lets it
actually
run.
​
Fix common issues
​
Extension won’t install
Ensure you have a compatible version of VS Code (1.98.0 or later)
Check that VS Code has permission to install extensions
Try installing directly from the
VS Code Marketplace
​
Spark icon not visible
The Spark icon appears in the
Editor Toolbar
(top-right of editor) when you have a file open. If you don’t see it:
Open a file
: The icon requires a file to be open. Having just a folder open isn’t enough.
Check VS Code version
: Requires 1.98.0 or higher (Help → About)
Restart VS Code
: Run “Developer: Reload Window” from the Command Palette
Disable conflicting extensions
: Temporarily disable other AI extensions (Cline, Continue, etc.)
Check workspace trust
: The extension doesn’t work in Restricted Mode
Alternatively, click ”✱ Claude Code” in the
Status Bar
(bottom-right corner). This works even without a file open. You can also use the
Command Palette
(
Cmd+Shift+P
/
Ctrl+Shift+P
) and type “Claude Code”.
​
Cmd+Esc does nothing on macOS
On macOS Tahoe and later, the system Game Overlay shortcut is bound to
Cmd+Esc
by default and intercepts the keypress before it reaches VS Code. To free the shortcut:
Open System Settings
Go to Keyboard, then Keyboard Shortcuts, then Game Controllers
Clear the Game Overlay checkbox
Alternatively, rebind the extension to a different key: open the VS Code
Keyboard Shortcuts editor
(
Cmd+K Cmd+S
), search for
Claude Code: Focus input
, and assign a new binding.
​
Claude Code never responds
If Claude Code isn’t responding to your prompts:
Check your internet connection
: Ensure you have a stable internet connection
Start a new conversation
: Try starting a fresh conversation to see if the issue persists
Try the CLI
: Run
claude
from the terminal to see if you get more detailed error messages
If problems persist,
file an issue on GitHub
with details about the error.
​
Uninstall the extension
To uninstall the Claude Code extension:
Open the Extensions view (
Cmd+Shift+X
on Mac or
Ctrl+Shift+X
on Windows/Linux)
Search for “Claude Code”
Click
Uninstall
To also remove extension data and reset all settings:
rm
-rf
~/.vscode/globalStorage/anthropic.claude-code
For additional help, see the
troubleshooting guide
.
​
Next steps
Now that you have Claude Code set up in VS Code:
Explore common workflows
to get the most out of Claude Code
Set up MCP servers
to extend Claude’s capabilities with external tools. Add servers using the CLI, then manage them with
/mcp
in the chat panel.
Configure Claude Code settings
to customize allowed commands, hooks, and more. These settings are shared between the extension and CLI.
Was this page helpful?
Yes
No
Computer use (preview)
JetBrains IDEs
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/vs-code" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code in VS Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extensi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code in VS Code
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The VS Code extension provides a native graphical interface for Claude Code, integrated directly into your IDE. This is the recommended way to use Claude Code in VS Code.
With the extension, you can review and edit Claude’s plans before accepting them, auto-accept edits as they’re made, @-mention files with specific line ranges from your selection, access conversation history, and open multiple conversations in separate tabs or windows.
​
Prerequisites
Before installing, make sure you have:
VS Code 1.98.0 or higher
An Anthropic account (you’ll sign in when you first open the extension). If you’re using a third-party provider like Amazon Bedrock or Google Vertex AI, see
Use third-party providers
instead.
The extension includes the CLI (command-line interface), which you can access from VS Code’s integrated terminal for advanced features. See
VS Code extension vs. Claude Code CLI
for details.
​
Install the extension
Click the link for your IDE to install directly:
Install for VS Code
Install for Cursor
Or in VS Code, press
Cmd+Shift+X
(Mac) or
Ctrl+Shift+X
(Windows/Linux) to open the Extensions view, search for “Claude Code”, and click
Install
.
The extension also installs in other VS Code forks like Windsurf or Kiro. Search for “Claude Code” in the editor’s Extensions view, or install from the
Open VSX registry
. If your editor can’t install the extension, run
claude
in its integrated terminal instead. The
CLI
works in any terminal.
If the extension doesn’t appear after installation, restart VS Code or run “Developer: Reload Window” from the Command Palette.
​
Get started
Once installed, you can start using Claude Code through the VS Code interface:
1
Open the Claude Code panel
Throughout VS Code, the Spark icon indicates Claude Code:
The quickest way to open Claude is to click the Spark icon in the
Editor Toolbar
(top-right corner of the editor). The icon only appears when you have a file open.
Other ways to open Claude Code:
Activity Bar
: click the Spark icon in the left sidebar to open the sessions list. Click any session to open it as a full editor tab, or start a new one. This icon is always visible in the Activity Bar.
Command Palette
:
Cmd+Shift+P
(Mac) or
Ctrl+Shift+P
(Windows/Linux), type “Claude Code”, and select an option like “Open in New Tab”
Status Bar
: click
✱ Claude Code
in the bottom-right corner of the window. This works even when no file is open.
You can drag the Claude panel to reposition it anywhere in VS Code. See
Customize your workflow
for details.
2
Sign in
The first time you open the panel, a sign-in screen appears. Click
Sign in
and complete authorization in your browser.
If you see
Not logged in · Please run /login
later, the extension reopens the sign-in screen automatically. If it doesn’t appear, reload the window from the Command Palette with
Developer: Reload Window
.
If you have
ANTHROPIC_API_KEY
set in your shell but still see the sign-in prompt, VS Code may not have inherited your shell environment. Launch VS Code from a terminal with
code .
so it inherits your environment variables, or sign in with your Claude account instead.
After you sign in, a
Learn Claude Code
checklist appears. Work through each item by clicking
Show me
, or dismiss it with the X. To reopen it later, uncheck
Hide Onboarding
in VS Code settings under Extensions → Claude Code.
3
Send a prompt
Ask Claude to help with your code or files, whether that’s explaining how something works, debugging an issue, or making changes.
Claude automatically sees your selected text. Press
Option+K
(Mac) /
Alt+K
(Windows/Linux) to also insert an @-mention reference (like
@file.ts#5-10
) into your prompt.
Here’s an example of asking about a particular line in a file:
4
Review changes
When Claude wants to edit a file, it shows a side-by-side comparison of the original and proposed changes, then asks for permission. You can accept, reject, or tell Claude what to do instead. If you edit the proposed content directly in the diff view before accepting, Claude is told that you modified it so it does not assume the file matches its original proposal.
For more ideas on what you can do with Claude Code, see
Common workflows
.
Run “Claude Code: Open Walkthrough” from the Command Palette for a guided tour of the basics.
​
Use the prompt box
The prompt box supports several features:
Permission modes
: click the mode indicator at the bottom of the prompt box to switch modes. In normal mode, Claude asks permission before each action. In Plan mode, Claude describes what it will do and waits for approval before making changes. VS Code automatically opens the plan as a full markdown document where you can add inline comments to give feedback before Claude begins. In auto-accept mode, Claude makes edits without asking. Set the default in VS Code settings under
claudeCode.initialPermissionMode
.
Command menu
: click
/
or type
/
to open the command menu. Options include attaching files, switching models, toggling extended thinking, viewing plan usage (
/usage
), and starting a
Remote Control
session (
/remote-control
). The Customize section provides access to MCP servers, hooks, memory, permissions, and plugins. Items with a terminal icon open in the integrated terminal.
Context indicator
: the prompt box shows how much of Claude’s context window you’re using. Claude automatically compacts when needed, or you can run
/compact
manually.
Extended thinking
: lets Claude spend more time reasoning through complex problems. Toggle it on via the command menu (
/
). Claude’s reasoning appears in the conversation as collapsed blocks: click a block to read it, or press
Ctrl+O
to expand or collapse every thinking block in the session. See
Extended thinking
for details.
Multi-line input
: press
Shift+Enter
to add a new line without sending. This also works in the “Other” free-text input of question dialogs.
​
Reference files and folders
Use @-mentions to give Claude context about specific files or folders. When you type
@
followed by a file or folder name, Claude reads that content and can answer questions about it or make changes to it. Claude Code supports fuzzy matching, so you can type partial names to find what you need:
> Explain the logic in @auth (fuzzy matches auth.js, AuthService.ts, etc.)
> What's in @src/components/ (include a trailing slash for folders)
For large PDFs, you can ask Claude to read specific pages instead of the whole file: a single page, a range like pages 1-10, or an open-ended range like page 3 onward.
When you select text in the editor, Claude can see your highlighted code automatically. The prompt box footer shows how many lines are selected. Press
Option+K
(Mac) /
Alt+K
(Windows/Linux) to insert an @-mention with the file path and line numbers (e.g.,
@app.ts#5-10
). Click the selection indicator to toggle whether Claude can see your highlighted text - the eye-slash icon means the selection is hidden from Claude.
You can also hold
Shift
while dragging files into the prompt box to add them as attachments. Click the X on any attachment to remove it from context.
​
Resume past conversations
Click the
Session history
button at the top of the Claude Code panel to access your conversation history. You can search by keyword or browse by time (Today, Yesterday, Last 7 days, etc.). Click any conversation to resume it with the full message history. New sessions receive AI-generated titles based on your first message. Hover over a session to reveal rename and remove actions: rename to give it a descriptive title, or remove to delete it from the list. For more on resuming sessions, see
Manage sessions
.
​
Resume remote sessions from Claude.ai
If you use
Claude Code on the web
, you can resume those remote sessions directly in VS Code. This requires signing in with
Claude.ai Subscription
, not Anthropic Console.
1
Open session history
Click the
Session history
button at the top of the Claude Code panel.
2
Select the Remote tab
The dialog shows two tabs: Local and Remote. Click
Remote
to see sessions from claude.ai.
3
Select a session to resume
Browse or search your remote sessions. Click any session to download it and continue the conversation locally.
Only web sessions started with a GitHub repository appear in the Remote tab. Resuming loads the conversation history locally; changes are not synced back to claude.ai.
​
Customize your workflow
Once you’re up and running, you can reposition the Claude panel, run multiple sessions, or switch to terminal mode.
​
Choose where Claude lives
You can drag the Claude panel to reposition it anywhere in VS Code. Grab the panel’s tab or title bar and drag it to:
Secondary sidebar
: the right side of the window. Keeps Claude visible while you code.
Primary sidebar
: the left sidebar with icons for Explorer, Search, etc.
Editor area
: opens Claude as a tab alongside your files. Useful for side tasks.
Use the sidebar for your main Claude session and open additional tabs for side tasks. Claude remembers your preferred location. The Activity Bar sessions list icon is separate from the Claude panel: the sessions list is always visible in the Activity Bar, while the Claude panel icon only appears there when the panel is docked to the left sidebar.
​
Run multiple conversations
Use
Open in New Tab
or
Open in New Window
from the Command Palette to start additional conversations. Each conversation maintains its own history and context, allowing you to work on different tasks in parallel.
When using tabs, a small colored dot on the spark icon indicates status: blue means a permission request is pending, orange means Claude finished while the tab was hidden.
​
Switch to terminal mode
By default, the extension opens a graphical chat panel. If you prefer the CLI-style interface, open the
Use Terminal setting
and check the box.
You can also open VS Code settings (
Cmd+,
on Mac or
Ctrl+,
on Windows/Linux), go to Extensions → Claude Code, and check
Use Terminal
.
​
Manage plugins
The VS Code extension includes a graphical interface for installing and managing
plugins
. Type
/plugins
in the prompt box to open the
Manage plugins
interface.
​
Install plugins
The plugin dialog shows two tabs:
Plugins
and
Marketplaces
.
In the Plugins tab:
Installed plugins
appear at the top with toggle switches to enable or disable them
Available plugins
from your configured marketplaces appear below
Search to filter plugins by name or description
Click
Install
on any available plugin
When you install a plugin, choose the installation scope:
Install for you
: available in all your projects (user scope)
Install for this project
: shared with project collaborators (project scope)
Install locally
: only for you, only in this repository (local scope)
​
Manage marketplaces
Switch to the
Marketplaces
tab to add or remove plugin sources:
Enter a GitHub repo, URL, or local path to add a new marketplace
Click the refresh icon to update a marketplace’s plugin list
Click the trash icon to remove a marketplace
After making changes, a banner prompts you to restart Claude Code to apply the updates.
Plugin management in VS Code uses the same CLI commands under the hood. Plugins and marketplaces you configure in the extension are also available in the CLI, and vice versa.
For more about the plugin system, see
Plugins
and
Plugin marketplaces
.
​
Automate browser tasks with Chrome
Connect Claude to your Chrome browser to test web apps, debug with console logs, and automate browser workflows without leaving VS Code. This requires the
Claude in Chrome extension
version 1.0.36 or higher.
Type
@browser
in the prompt box followed by what you want Claude to do:
@browser go to localhost:3000 and check the console for errors
You can also open the attachment menu to select specific browser tools like opening a new tab or reading page content.
Claude opens new tabs for browser tasks and shares your browser’s login state, so it can access any site you’re already signed into.
For setup instructions, the full list of capabilities, and troubleshooting, see
Use Claude Code with Chrome
.
​
VS Code commands and shortcuts
Open the Command Palette (
Cmd+Shift+P
on Mac or
Ctrl+Shift+P
on Windows/Linux) and type “Claude Code” to see all available VS Code commands for the Claude Code extension.
Some shortcuts depend on which panel is “focused” (receiving keyboard input). When your cursor is in a code file, the editor is focused. When your cursor is in Claude’s prompt box, Claude is focused. Use
Cmd+Esc
/
Ctrl+Esc
to toggle between them.
These are VS Code commands for controlling the extension. Not all built-in Claude Code commands are available in the extension. See
VS Code extension vs. Claude Code CLI
for details.
Command
Shortcut
Description
Focus Input
Cmd+Esc
(Mac) /
Ctrl+Esc
(Windows/Linux)
Toggle focus between editor and Claude
Open in Side Bar
-
Open Claude in the left sidebar
Open in Terminal
-
Open Claude in terminal mode
Open in New Tab
Cmd+Shift+Esc
(Mac) /
Ctrl+Shift+Esc
(Windows/Linux)
Open a new conversation as an editor tab
Open in New Window
-
Open a new conversation in a separate window
New Conversation
Cmd+N
(Mac) /
Ctrl+N
(Windows/Linux)
Start a new conversation. Requires Claude to be focused and
enableNewConversationShortcut
set to
true
Reopen Closed Session
Cmd+Shift+T
(Mac) /
Ctrl+Shift+T
(Windows/Linux)
Reopen the most recently closed Claude session tab. Falls through to VS Code’s normal reopen-closed-editor when the last closed tab wasn’t a Claude session. Disable with
enableReopenClosedSessionShortcut
Insert @-Mention Reference
Option+K
(Mac) /
Alt+K
(Windows/Linux)
Insert a reference to the current file and selection (requires editor to be focused)
Show Logs
-
View extension debug logs
Logout
-
Sign out of your Anthropic account
​
Launch a VS Code tab from other tools
The extension registers a URI handler at
vscode://anthropic.claude-code/open
. Use it to open a new Claude Code tab from your own tooling: a shell alias, a browser bookmarklet, or any script that can open a URL. If VS Code isn’t already running, opening the URL launches it first. If VS Code is already running, the URL opens in whichever window is currently focused.
Invoke the handler with your operating system’s URL opener.
macOS
Linux
Windows
open
"vscode://anthropic.claude-code/open"
xdg-open
"vscode://anthropic.claude-code/open"
In PowerShell:
Start-Process
"vscode://anthropic.claude-code/open"
In
cmd.exe
,
start
treats its first quoted argument as a window title, so pass an empty title before the URL:
start
""
"vscode://anthropic.claude-code/open"
The handler accepts two optional query parameters:
Parameter
Description
prompt
Text to pre-fill in the prompt box. Must be URL-encoded. The prompt is pre-filled but not submitted automatically.
session
A session ID to resume instead of starting a new conversation. The session must belong to the workspace currently open in VS Code. If the session isn’t found, a fresh conversation starts instead. If the session is already open in a tab, that tab is focused. To capture a session ID programmatically, see
Continue conversations
.
For example, to open a tab pre-filled with “review my changes”:
vscode://anthropic.claude-code/open?prompt=review%20my%20changes
To launch a terminal session instead of a VS Code tab, use the CLI’s
claude-cli://
handler. See
Launch sessions from links
.
​
Configure settings
The extension has two types of settings:
Extension settings
in VS Code: control the extension’s behavior within VS Code. Open with
Cmd+,
(Mac) or
Ctrl+,
(Windows/Linux), then go to Extensions → Claude Code. You can also type
/
and select
General Config
to open settings.
Claude Code settings
in
~/.claude/settings.json
: shared between the extension and CLI. Use for allowed commands, environment variables, hooks, and MCP servers. See
Settings
for details.
Add
"$schema": "https://json.schemastore.org/claude-code-settings.json"
to your
settings.json
to get autocomplete and inline validation for all available settings directly in VS Code.
​
Extension settings
Setting
Default
Description
useTerminal
false
Launch Claude in terminal mode instead of graphical panel
initialPermissionMode
default
Controls approval prompts for new conversations:
default
,
plan
,
acceptEdits
, or
bypassPermissions
. See
permission modes
.
preferredLocation
panel
Where Claude opens:
sidebar
(right) or
panel
(new tab)
autosave
true
Auto-save files before Claude reads or writes them
useCtrlEnterToSend
false
Use Ctrl/Cmd+Enter instead of Enter to send prompts
enableNewConversationShortcut
false
Enable Cmd/Ctrl+N to start a new conversation
enableReopenClosedSessionShortcut
true
Use Cmd/Ctrl+Shift+T to reopen the most recently closed Claude session tab. When the last closed tab wasn’t a Claude session, the shortcut runs VS Code’s normal reopen-closed-editor command instead.
hideOnboarding
false
Hide the onboarding checklist (graduation cap icon)
respectGitIgnore
true
Exclude .gitignore patterns from file searches
usePythonEnvironment
true
Activate the workspace’s Python environment when running Claude. Requires the Python extension.
environmentVariables
[]
Set environment variables for the Claude process. Use Claude Code settings instead for shared config.
disableLoginPrompt
false
Skip authentication prompts (for third-party provider setups)
allowDangerouslySkipPermissions
false
Adds
Auto mode
and Bypass permissions to the mode selector. Auto mode has
plan, admin, model, and provider requirements
, so it may remain unavailable even with this toggle on. Use Bypass permissions only in sandboxes with no internet access.
claudeProcessWrapper
-
Executable used to launch the Claude process. The bundled binary path is passed as an argument when present. Set this to a separately installed
claude
binary if the extension build doesn’t include one for your platform.
​
VS Code extension vs. Claude Code CLI
Claude Code is available as both a VS Code extension (graphical panel) and a CLI (command-line interface in the terminal). Some features are only available in the CLI. If you need a CLI-only feature, run
claude
in VS Code’s integrated terminal.
Feature
CLI
VS Code Extension
Commands and skills
All
Subset (type
/
to see available)
MCP server config
Yes
Partial (add servers via CLI; manage existing servers with
/mcp
in the chat panel)
Checkpoints
Yes
Yes
!
bash shortcut
Yes
No
Tab completion
Yes
No
​
Rewind with checkpoints
The VS Code extension supports checkpoints, which track Claude’s file edits and let you rewind to a previous state. Hover over any message to reveal the rewind button, then choose from three options:
Fork conversation from here
: start a new conversation branch from this message while keeping all code changes intact
Rewind code to here
: revert file changes back to this point in the conversation while keeping the full conversation history
Fork conversation and rewind code
: start a new conversation branch and revert file changes to this point
For full details on how checkpoints work and their limitations, see
Checkpointing
.
​
Run CLI in VS Code
To use the CLI while staying in VS Code, open the integrated terminal (
Ctrl+`
on Windows/Linux or
Cmd+`
on Mac) and run
claude
. The CLI automatically integrates with your IDE for features like diff viewing and diagnostic sharing.
If using an external terminal, run
/ide
inside Claude Code to connect it to VS Code.
​
Switch between extension and CLI
The extension and CLI share the same conversation history. To continue an extension conversation in the CLI, run
claude --resume
in the terminal. This opens an interactive picker where you can search for and select your conversation.
​
Include terminal output in prompts
Reference terminal output in your prompts using
@terminal:name
where
name
is the terminal’s title. This lets Claude see command output, error messages, or logs without copy-pasting.
​
Monitor background processes
When Claude runs long-running commands, the extension shows progress in the status bar. However, visibility for background tasks is limited compared to the CLI. For better visibility, have Claude output the command so you can run it in VS Code’s integrated terminal.
​
Connect to external tools with MCP
MCP (Model Context Protocol) servers give Claude access to external tools, databases, and APIs.
To add an MCP server, open the integrated terminal (
Ctrl+`
or
Cmd+`
) and run
claude mcp add
. The example below adds GitHub’s remote MCP server, which authenticates with a
personal access token
passed as a header:
claude
mcp
add
--transport
http
github
https://api.githubcopilot.com/mcp/
\
--header
"Authorization: Bearer YOUR_GITHUB_PAT"
Once configured, ask Claude to use the tools (e.g., “Review PR #456”).
To manage MCP servers without leaving VS Code, type
/mcp
in the chat panel. The MCP management dialog lets you enable or disable servers, reconnect to a server, and manage OAuth authentication. See the
MCP documentation
for available servers.
​
Work with git
Claude Code integrates with git to help with version control workflows directly in VS Code. Ask Claude to commit changes, create pull requests, or work across branches.
​
Create commits and pull requests
Claude can stage changes, write commit messages, and create pull requests based on your work:
> commit my changes with a descriptive message
> create a pr for this feature
> summarize the changes I've made to the auth module
When creating pull requests, Claude generates descriptions based on the actual code changes and can add context about testing or implementation decisions.
​
Use git worktrees for parallel tasks
Use the
--worktree
(
-w
) flag to start Claude in an isolated worktree with its own files and branch:
claude
--worktree
feature-auth
Each worktree maintains independent file state while sharing git history. This prevents Claude instances from interfering with each other when working on different tasks. For more details, see
Run parallel sessions with Git worktrees
.
​
Use third-party providers
By default, Claude Code connects directly to Anthropic’s API. If your organization uses Amazon Bedrock, Google Vertex AI, or Microsoft Foundry to access Claude, configure the extension to use your provider instead:
1
Disable login prompt
Open the
Disable Login Prompt setting
and check the box.
You can also open VS Code settings (
Cmd+,
on Mac or
Ctrl+,
on Windows/Linux), search for “Claude Code login”, and check
Disable Login Prompt
.
2
Configure your provider
Follow the setup guide for your provider:
Claude Code on Amazon Bedrock
Claude Code on Google Vertex AI
Claude Code on Microsoft Foundry
These guides cover configuring your provider in
~/.claude/settings.json
, which ensures your settings are shared between the VS Code extension and the CLI.
​
Security and privacy
Your code stays private. Claude Code processes your code to provide assistance but does not use it to train models. For details on data handling and how to opt out of logging, see
Data and privacy
.
With auto-edit permissions enabled, Claude Code can modify VS Code configuration files (like
settings.json
or
tasks.json
) that VS Code may execute automatically. To reduce risk when working with untrusted code:
Enable
VS Code Restricted Mode
for untrusted workspaces
Use manual approval mode instead of auto-accept for edits
Review changes carefully before accepting them
​
The built-in IDE MCP server
When the extension is active, it runs a local MCP server that the CLI connects to automatically. This is how the CLI opens diffs in VS Code’s native diff viewer, reads your current selection for
@
-mentions, and — when you’re working in a Jupyter notebook — asks VS Code to execute cells.
The server is named
ide
and is hidden from
/mcp
because there’s nothing to configure. If your organization uses a
PreToolUse
hook to allowlist MCP tools, though, you’ll need to know it exists.
Transport and authentication.
The server binds to
127.0.0.1
on a random high port and is not reachable from other machines. Each extension activation generates a fresh random auth token that the CLI must present to connect. The token is written to a lock file under
~/.claude/ide/
with
0600
permissions in a
0700
directory, so only the user running VS Code can read it.
Tools exposed to the model.
The server hosts a dozen tools, but only two are visible to the model. The rest are internal RPC the CLI uses for its own UI — opening diffs, reading selections, saving files — and are filtered out before the tool list reaches Claude.
Tool name (as seen by hooks)
What it does
Writes?
mcp__ide__getDiagnostics
Returns language-server diagnostics — the errors and warnings in VS Code’s Problems panel. Optionally scoped to one file.
No
mcp__ide__executeCode
Runs Python code in the active Jupyter notebook’s kernel. See confirmation flow below.
Yes
Jupyter execution always asks first.
mcp__ide__executeCode
can’t run anything silently. On each call, the code is inserted as a new cell at the end of the active notebook, VS Code scrolls it into view, and a native Quick Pick asks you to
Execute
or
Cancel
. Cancelling — or dismissing the picker with
Esc
— returns an error to Claude and nothing runs. The tool also refuses outright when there’s no active notebook, when the Jupyter extension (
ms-toolsai.jupyter
) isn’t installed, or when the kernel isn’t Python.
The Quick Pick confirmation is separate from
PreToolUse
hooks. An allowlist entry for
mcp__ide__executeCode
lets Claude
propose
running a cell; the Quick Pick inside VS Code is what lets it
actually
run.
​
Fix common issues
​
Extension won’t install
Ensure you have a compatible version of VS Code (1.98.0 or later)
Check that VS Code has permission to install extensions
Try installing directly from the
VS Code Marketplace
​
Spark icon not visible
The Spark icon appears in the
Editor Toolbar
(top-right of editor) when you have a file open. If you don’t see it:
Open a file
: The icon requires a file to be open. Having just a folder open isn’t enough.
Check VS Code version
: Requires 1.98.0 or higher (Help → About)
Restart VS Code
: Run “Developer: Reload Window” from the Command Palette
Disable conflicting extensions
: Temporarily disable other AI extensions (Cline, Continue, etc.)
Check workspace trust
: The extension doesn’t work in Restricted Mode
Alternatively, click ”✱ Claude Code” in the
Status Bar
(bottom-right corner). This works even without a file open. You can also use the
Command Palette
(
Cmd+Shift+P
/
Ctrl+Shift+P
) and type “Claude Code”.
​
Cmd+Esc does nothing on macOS
On macOS Tahoe and later, the system Game Overlay shortcut is bound to
Cmd+Esc
by default and intercepts the keypress before it reaches VS Code. To free the shortcut:
Open System Settings
Go to Keyboard, then Keyboard Shortcuts, then Game Controllers
Clear the Game Overlay checkbox
Alternatively, rebind the extension to a different key: open the VS Code
Keyboard Shortcuts editor
(
Cmd+K Cmd+S
), search for
Claude Code: Focus input
, and assign a new binding.
​
Claude Code never responds
If Claude Code isn’t responding to your prompts:
Check your internet connection
: Ensure you have a stable internet connection
Start a new conversation
: Try starting a fresh conversation to see if the issue persists
Try the CLI
: Run
claude
from the terminal to see if you get more detailed error messages
If problems persist,
file an issue on GitHub
with details about the error.
​
Uninstall the extension
To uninstall the Claude Code extension:
Open the Extensions view (
Cmd+Shift+X
on Mac or
Ctrl+Shift+X
on Windows/Linux)
Search for “Claude Code”
Click
Uninstall
To also remove extension data and reset all settings:
rm
-rf
~/.vscode/globalStorage/anthropic.claude-code
For additional help, see the
troubleshooting guide
.
​
Next steps
Now that you have Claude Code set up in VS Code:
Explore common workflows
to get the most out of Claude Code
Set up MCP servers
to extend Claude’s capabilities with external tools. Add servers using the CLI, then manage them with
/mcp
in the chat panel.
Configure Claude Code settings
to customize allowed commands, hooks, and more. These settings are shared between the extension and CLI.
Was this page helpful?
Yes
No
Computer use (preview)
JetBrains IDEs
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/vs-code" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 13 · March 23–27, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w13</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w13</guid>
  <pubDate>Tue, 18 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 13 · March 23–27, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.83 → v2.1.85
6 features ·...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 13 · March 23–27, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.83 → v2.1.85
6 features · March 23–27
Auto mode
research preview
Auto mode hands your permission prompts to a classifier. Safe edits and commands run without interrupting you; anything destructive or suspicious gets blocked and surfaced. It’s the middle ground between approving every file write and running with
—dangerously-skip-permissions
.
Cycle to auto with Shift+Tab, or set it as your default:
.claude/settings.json
{
"permissions"
: {
"defaultMode"
:
"auto"
}
}
Permission modes guide
Computer use
Desktop
Claude can now control your actual desktop from the Claude Code Desktop app: open native apps, click through the iOS simulator, drive hardware control panels, and verify changes on screen. It’s off by default and asks before each action. Best for the things nothing else can reach: apps without an API, proprietary tools, anything that only exists as a GUI.
Enable it in Settings, grant the OS permissions, then ask Claude to verify a change end to end:
Claude Code
> Open the iOS simulator, tap through the onboarding flow, and screenshot each step
Computer use guide
PR auto-fix
Web
Flip a switch when you open a PR and walk away. Claude watches CI, fixes the failures, handles the nits, and pushes until it’s green. No more babysitting a PR through six rounds of lint errors.
After creating a PR on Claude Code web, toggle Auto fix in the CI panel.
Auto-fix pull requests
Transcript search
v2.1.83
Press
/
in transcript mode to search your conversation.
n
and
N
step through matches. Finally a way to find that one Bash command Claude ran 400 messages ago.
Open transcript mode and search:
Claude Code
Ctrl+O    # open transcript
/migrate  # search for "migrate"
n         # next match
N         # previous match
Fullscreen guide
PowerShell tool
preview
v2.1.84
Windows gets a native PowerShell tool alongside Bash. Claude can run cmdlets, pipe objects, and work with Windows-native paths without translating everything through Git Bash.
Opt in from settings:
.claude/settings.json
{
"env"
: {
"CLAUDE_CODE_USE_POWERSHELL_TOOL"
:
"1"
}
}
PowerShell tool docs
Conditional hooks
v2.1.85
Hooks can now declare an
if
field using permission rule syntax. Your pre-commit check only spawns for
Bash(git commit *)
instead of every bash call, cutting the process overhead on busy sessions.
Scope a hook to git commits only:
.claude/settings.json
{
"hooks"
: {
"PreToolUse"
: [{
"hooks"
: [{
"if"
:
"Bash(git commit *)"
,
"type"
:
"command"
,
"command"
:
".claude/hooks/lint-staged.sh"
}]
}]
}
}
Hooks reference
Other wins
Plugin
userConfig
now public: prompt for settings at enable time, keychain-backed secrets
Pasted images insert
[Image #N]
chips you can reference positionally
managed-settings.d/
drop-in directory for layered policy fragments
CwdChanged
and
FileChanged
hook events for direnv-style setups
Agents can declare
initialPrompt
in frontmatter to auto-submit a first turn
Ctrl+X Ctrl+E
opens your external editor, matching readline
Interrupting before any response restores your input automatically
/status
now works while Claude is responding
Deep links open in your preferred terminal, not first-detected
Idle-return nudge to
/clear
after 75+ minutes away
VS Code: rate limit banner, Esc-twice rewind picker
Full changelog for v2.1.83–v2.1.85 →
Was this page helpful?
Yes
No
Week 14 · Mar 30 – Apr 3
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w13" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 13 · March 23–27, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.83 → v2.1.85
6 features ·...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 13 · March 23–27, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.83 → v2.1.85
6 features · March 23–27
Auto mode
research preview
Auto mode hands your permission prompts to a classifier. Safe edits and commands run without interrupting you; anything destructive or suspicious gets blocked and surfaced. It’s the middle ground between approving every file write and running with
—dangerously-skip-permissions
.
Cycle to auto with Shift+Tab, or set it as your default:
.claude/settings.json
{
"permissions"
: {
"defaultMode"
:
"auto"
}
}
Permission modes guide
Computer use
Desktop
Claude can now control your actual desktop from the Claude Code Desktop app: open native apps, click through the iOS simulator, drive hardware control panels, and verify changes on screen. It’s off by default and asks before each action. Best for the things nothing else can reach: apps without an API, proprietary tools, anything that only exists as a GUI.
Enable it in Settings, grant the OS permissions, then ask Claude to verify a change end to end:
Claude Code
> Open the iOS simulator, tap through the onboarding flow, and screenshot each step
Computer use guide
PR auto-fix
Web
Flip a switch when you open a PR and walk away. Claude watches CI, fixes the failures, handles the nits, and pushes until it’s green. No more babysitting a PR through six rounds of lint errors.
After creating a PR on Claude Code web, toggle Auto fix in the CI panel.
Auto-fix pull requests
Transcript search
v2.1.83
Press
/
in transcript mode to search your conversation.
n
and
N
step through matches. Finally a way to find that one Bash command Claude ran 400 messages ago.
Open transcript mode and search:
Claude Code
Ctrl+O    # open transcript
/migrate  # search for "migrate"
n         # next match
N         # previous match
Fullscreen guide
PowerShell tool
preview
v2.1.84
Windows gets a native PowerShell tool alongside Bash. Claude can run cmdlets, pipe objects, and work with Windows-native paths without translating everything through Git Bash.
Opt in from settings:
.claude/settings.json
{
"env"
: {
"CLAUDE_CODE_USE_POWERSHELL_TOOL"
:
"1"
}
}
PowerShell tool docs
Conditional hooks
v2.1.85
Hooks can now declare an
if
field using permission rule syntax. Your pre-commit check only spawns for
Bash(git commit *)
instead of every bash call, cutting the process overhead on busy sessions.
Scope a hook to git commits only:
.claude/settings.json
{
"hooks"
: {
"PreToolUse"
: [{
"hooks"
: [{
"if"
:
"Bash(git commit *)"
,
"type"
:
"command"
,
"command"
:
".claude/hooks/lint-staged.sh"
}]
}]
}
}
Hooks reference
Other wins
Plugin
userConfig
now public: prompt for settings at enable time, keychain-backed secrets
Pasted images insert
[Image #N]
chips you can reference positionally
managed-settings.d/
drop-in directory for layered policy fragments
CwdChanged
and
FileChanged
hook events for direnv-style setups
Agents can declare
initialPrompt
in frontmatter to auto-submit a first turn
Ctrl+X Ctrl+E
opens your external editor, matching readline
Interrupting before any response restores your input automatically
/status
now works while Claude is responding
Deep links open in your preferred terminal, not first-detected
Idle-return nudge to
/clear
after 75+ minutes away
VS Code: rate limit banner, Esc-twice rewind picker
Full changelog for v2.1.83–v2.1.85 →
Was this page helpful?
Yes
No
Week 14 · Mar 30 – Apr 3
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w13" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Configure server-managed settings</title>
  <link>https://code.claude.com/docs/en/server-managed-settings</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/server-managed-settings</guid>
  <pubDate>Mon, 17 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure server-managed settings
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure server-managed settings
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Server-managed settings allow administrators to centrally configure Claude Code through a web-based interface on Claude.ai. Claude Code clients automatically receive these settings when users authenticate with their organization credentials.
This approach is designed for organizations that do not have device management infrastructure in place, or need to manage settings for users on unmanaged devices.
Server-managed settings are available for
Claude for Teams
and
Claude for Enterprise
customers.
​
Requirements
To use server-managed settings, you need:
Claude for Teams or Claude for Enterprise plan
Claude Code version 2.1.38 or later for Claude for Teams, or version 2.1.30 or later for Claude for Enterprise
Network access to
api.anthropic.com
​
Choose between server-managed and endpoint-managed settings
Claude Code supports two approaches for centralized configuration. Server-managed settings deliver configuration from Anthropic’s servers.
Endpoint-managed settings
are deployed directly to devices through native OS policies (macOS managed preferences, Windows registry) or managed settings files.
Approach
Best for
Security model
Server-managed settings
Organizations without MDM, or users on unmanaged devices
Settings delivered from Anthropic’s servers at authentication time
Endpoint-managed settings
Organizations with MDM or endpoint management
Settings deployed to devices via MDM configuration profiles, registry policies, or managed settings files
If your devices are enrolled in an MDM or endpoint management solution, endpoint-managed settings provide stronger security guarantees because the settings file can be protected from user modification at the OS level.
​
Configure server-managed settings
1
Open the admin console
In
Claude.ai
, navigate to
Admin Settings > Claude Code > Managed settings
.
2
Define your settings
Add your configuration as JSON. All
settings available in
settings.json
are supported except those restricted to OS-level policy delivery; see
Current limitations
for that short list. This includes
hooks
,
environment variables
, and
managed-only settings
like
allowManagedPermissionRulesOnly
.
This example enforces a permission deny list, prevents users from bypassing permissions, and restricts permission rules to those defined in managed settings:
{
"permissions"
: {
"deny"
: [
"Bash(curl *)"
,
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
],
"disableBypassPermissionsMode"
:
"disable"
},
"allowManagedPermissionRulesOnly"
:
true
}
Hooks use the same format as in
settings.json
.
This example runs an audit script after every file edit across the organization:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/usr/local/bin/audit-edit.sh"
}
]
}
]
}
}
To configure the
auto mode
classifier so it knows which repos, buckets, and domains your organization trusts:
{
"autoMode"
: {
"environment"
: [
"Source control: github.example.com/acme-corp and all repos under it"
,
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets"
,
"Trusted internal domains: *.corp.example.com"
]
}
}
Because hooks execute shell commands, users see a
security approval dialog
before they’re applied. See
Configure auto mode
for how the
autoMode
entries affect what the classifier blocks and important warnings about the
environment
,
allow
,
soft_deny
, and
hard_deny
fields.
3
Save and deploy
Save your changes. Claude Code clients receive the updated settings on their next startup or hourly polling cycle.
​
Verify settings delivery
To confirm that settings are being applied, ask a user to restart Claude Code. If the configuration includes settings that trigger the
security approval dialog
, the user sees a prompt describing the managed settings on startup. You can also verify that managed permission rules are active by having a user run
/permissions
to view their effective permission rules.
​
Access control
The following roles can manage server-managed settings:
Primary Owner
Owner
Restrict access to trusted personnel, as settings changes apply to all users in the organization.
​
Managed-only settings
Most
settings keys
work in any scope. A handful of keys are only read from managed settings and have no effect when placed in user or project settings files. See
managed-only settings
for the full list. Any setting not on that list can still be placed in managed settings and takes the highest precedence.
​
Current limitations
Server-managed settings have the following limitations:
Settings apply uniformly to all users in the organization. Per-group configurations are not yet supported.
MCP server configurations
cannot be distributed through server-managed settings.
Settings restricted to OS-level policy sources, such as
policyHelper
and
wslInheritsWindowsSettings
, are not honored. Deploy them through MDM or a system
managed-settings.json
file instead.
​
Settings delivery
​
Settings precedence
Server-managed settings and
endpoint-managed settings
both occupy the highest tier in the Claude Code
settings hierarchy
. No other settings level can override them, including command line arguments.
Within the managed tier, the first source that delivers a non-empty configuration wins. Server-managed settings are checked first, then endpoint-managed settings. Sources do not merge: if server-managed settings deliver any keys at all, endpoint-managed settings are ignored entirely. If server-managed settings deliver nothing, endpoint-managed settings apply.
If you clear your server-managed configuration in the admin console with the intent of falling back to an endpoint-managed plist or registry policy, be aware that
cached settings
persist on client machines until the next successful fetch. Run
/status
to see which managed source is active.
​
Fetch and caching behavior
Claude Code fetches settings from Anthropic’s servers at startup and polls for updates hourly during active sessions.
First launch without cached settings:
Claude Code fetches settings asynchronously
If the fetch fails, Claude Code continues without managed settings
There is a brief window before settings load where restrictions are not yet enforced
Subsequent launches with cached settings:
Cached settings apply immediately at startup
Claude Code fetches fresh settings in the background
Cached settings persist through network failures
Claude Code applies settings updates automatically without a restart, except for advanced settings like OpenTelemetry configuration, which require a full restart to take effect.
​
Enforce fail-closed startup
By default, if the remote settings fetch fails at startup, the CLI continues without managed settings. For environments where this brief unenforced window is unacceptable, set
forceRemoteSettingsRefresh: true
in your managed settings.
When this setting is active, the CLI blocks at startup until remote settings are freshly fetched. If the fetch fails, the CLI exits rather than proceeding without the policy. This setting self-perpetuates: once delivered from the server, it is also cached locally so that subsequent startups enforce the same behavior even before the first successful fetch of a new session.
To enable this, add the key to your managed settings configuration:
{
"forceRemoteSettingsRefresh"
:
true
}
Before enabling this setting, ensure your network policies allow connectivity to
api.anthropic.com
. If that endpoint is unreachable, the CLI exits at startup and users cannot start Claude Code.
As of v2.1.139, the
claude auth
subcommands such as
claude auth login
are exempt from this check, so users can re-authenticate when expired credentials are the reason the settings fetch fails.
​
Security approval dialogs
Certain settings that could pose security risks require explicit user approval before being applied:
Shell command settings
: settings that execute shell commands
Custom environment variables
: variables not in the known safe allowlist
Hook configurations
: any hook definition
When these settings are present, users see a security dialog explaining what is being configured. Users must approve to proceed. If a user rejects the settings, Claude Code exits.
In non-interactive mode with the
-p
flag, Claude Code skips security dialogs and applies settings without user approval.
​
Platform availability
Server-managed settings require a direct connection to
api.anthropic.com
and are not available when using third-party model providers:
Amazon Bedrock
Google Vertex AI
Microsoft Foundry
Custom API endpoints via
ANTHROPIC_BASE_URL
or
LLM gateways
​
Audit logging
Audit log events for settings changes are available through the compliance API or audit log export. Contact your Anthropic account team for access.
Audit events include the type of action performed, the account and device that performed the action, and references to the previous and new values.
​
Security considerations
Server-managed settings provide centralized policy enforcement, but they operate as a client-side control. On unmanaged devices, users with admin or sudo access can modify the Claude Code binary, filesystem, or network configuration.
Scenario
Behavior
User edits the cached settings file
Tampered file applies at startup, but correct settings restore on the next server fetch
User deletes the cached settings file
First-launch behavior occurs: settings fetch asynchronously with a brief unenforced window
API is unavailable
Cached settings apply if available, otherwise managed settings are not enforced until the next successful fetch. With
forceRemoteSettingsRefresh: true
, the CLI exits instead of continuing, except for
claude auth
subcommands
User authenticates with a different organization
Settings are not delivered for accounts outside the managed organization
User configures a
third-party model provider
Server-managed settings are bypassed. This includes setting
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_MANTLE
,
CLAUDE_CODE_USE_VERTEX
,
CLAUDE_CODE_USE_FOUNDRY
, or a non-default
ANTHROPIC_BASE_URL
To detect runtime configuration changes, use
ConfigChange
hooks
to log modifications or block unauthorized changes before they take effect.
For stronger enforcement guarantees, use
endpoint-managed settings
on devices enrolled in an MDM solution.
​
See also
Related pages for managing Claude Code configuration:
Settings
: complete configuration reference including all available settings
Endpoint-managed settings
: managed settings deployed to devices by IT
Authentication
: set up user access to Claude Code
Security
: security safeguards and best practices
Was this page helpful?
Yes
No
Authentication
Auto mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/server-managed-settings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure server-managed settings
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure server-managed settings
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Server-managed settings allow administrators to centrally configure Claude Code through a web-based interface on Claude.ai. Claude Code clients automatically receive these settings when users authenticate with their organization credentials.
This approach is designed for organizations that do not have device management infrastructure in place, or need to manage settings for users on unmanaged devices.
Server-managed settings are available for
Claude for Teams
and
Claude for Enterprise
customers.
​
Requirements
To use server-managed settings, you need:
Claude for Teams or Claude for Enterprise plan
Claude Code version 2.1.38 or later for Claude for Teams, or version 2.1.30 or later for Claude for Enterprise
Network access to
api.anthropic.com
​
Choose between server-managed and endpoint-managed settings
Claude Code supports two approaches for centralized configuration. Server-managed settings deliver configuration from Anthropic’s servers.
Endpoint-managed settings
are deployed directly to devices through native OS policies (macOS managed preferences, Windows registry) or managed settings files.
Approach
Best for
Security model
Server-managed settings
Organizations without MDM, or users on unmanaged devices
Settings delivered from Anthropic’s servers at authentication time
Endpoint-managed settings
Organizations with MDM or endpoint management
Settings deployed to devices via MDM configuration profiles, registry policies, or managed settings files
If your devices are enrolled in an MDM or endpoint management solution, endpoint-managed settings provide stronger security guarantees because the settings file can be protected from user modification at the OS level.
​
Configure server-managed settings
1
Open the admin console
In
Claude.ai
, navigate to
Admin Settings > Claude Code > Managed settings
.
2
Define your settings
Add your configuration as JSON. All
settings available in
settings.json
are supported except those restricted to OS-level policy delivery; see
Current limitations
for that short list. This includes
hooks
,
environment variables
, and
managed-only settings
like
allowManagedPermissionRulesOnly
.
This example enforces a permission deny list, prevents users from bypassing permissions, and restricts permission rules to those defined in managed settings:
{
"permissions"
: {
"deny"
: [
"Bash(curl *)"
,
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
],
"disableBypassPermissionsMode"
:
"disable"
},
"allowManagedPermissionRulesOnly"
:
true
}
Hooks use the same format as in
settings.json
.
This example runs an audit script after every file edit across the organization:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/usr/local/bin/audit-edit.sh"
}
]
}
]
}
}
To configure the
auto mode
classifier so it knows which repos, buckets, and domains your organization trusts:
{
"autoMode"
: {
"environment"
: [
"Source control: github.example.com/acme-corp and all repos under it"
,
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets"
,
"Trusted internal domains: *.corp.example.com"
]
}
}
Because hooks execute shell commands, users see a
security approval dialog
before they’re applied. See
Configure auto mode
for how the
autoMode
entries affect what the classifier blocks and important warnings about the
environment
,
allow
,
soft_deny
, and
hard_deny
fields.
3
Save and deploy
Save your changes. Claude Code clients receive the updated settings on their next startup or hourly polling cycle.
​
Verify settings delivery
To confirm that settings are being applied, ask a user to restart Claude Code. If the configuration includes settings that trigger the
security approval dialog
, the user sees a prompt describing the managed settings on startup. You can also verify that managed permission rules are active by having a user run
/permissions
to view their effective permission rules.
​
Access control
The following roles can manage server-managed settings:
Primary Owner
Owner
Restrict access to trusted personnel, as settings changes apply to all users in the organization.
​
Managed-only settings
Most
settings keys
work in any scope. A handful of keys are only read from managed settings and have no effect when placed in user or project settings files. See
managed-only settings
for the full list. Any setting not on that list can still be placed in managed settings and takes the highest precedence.
​
Current limitations
Server-managed settings have the following limitations:
Settings apply uniformly to all users in the organization. Per-group configurations are not yet supported.
MCP server configurations
cannot be distributed through server-managed settings.
Settings restricted to OS-level policy sources, such as
policyHelper
and
wslInheritsWindowsSettings
, are not honored. Deploy them through MDM or a system
managed-settings.json
file instead.
​
Settings delivery
​
Settings precedence
Server-managed settings and
endpoint-managed settings
both occupy the highest tier in the Claude Code
settings hierarchy
. No other settings level can override them, including command line arguments.
Within the managed tier, the first source that delivers a non-empty configuration wins. Server-managed settings are checked first, then endpoint-managed settings. Sources do not merge: if server-managed settings deliver any keys at all, endpoint-managed settings are ignored entirely. If server-managed settings deliver nothing, endpoint-managed settings apply.
If you clear your server-managed configuration in the admin console with the intent of falling back to an endpoint-managed plist or registry policy, be aware that
cached settings
persist on client machines until the next successful fetch. Run
/status
to see which managed source is active.
​
Fetch and caching behavior
Claude Code fetches settings from Anthropic’s servers at startup and polls for updates hourly during active sessions.
First launch without cached settings:
Claude Code fetches settings asynchronously
If the fetch fails, Claude Code continues without managed settings
There is a brief window before settings load where restrictions are not yet enforced
Subsequent launches with cached settings:
Cached settings apply immediately at startup
Claude Code fetches fresh settings in the background
Cached settings persist through network failures
Claude Code applies settings updates automatically without a restart, except for advanced settings like OpenTelemetry configuration, which require a full restart to take effect.
​
Enforce fail-closed startup
By default, if the remote settings fetch fails at startup, the CLI continues without managed settings. For environments where this brief unenforced window is unacceptable, set
forceRemoteSettingsRefresh: true
in your managed settings.
When this setting is active, the CLI blocks at startup until remote settings are freshly fetched. If the fetch fails, the CLI exits rather than proceeding without the policy. This setting self-perpetuates: once delivered from the server, it is also cached locally so that subsequent startups enforce the same behavior even before the first successful fetch of a new session.
To enable this, add the key to your managed settings configuration:
{
"forceRemoteSettingsRefresh"
:
true
}
Before enabling this setting, ensure your network policies allow connectivity to
api.anthropic.com
. If that endpoint is unreachable, the CLI exits at startup and users cannot start Claude Code.
As of v2.1.139, the
claude auth
subcommands such as
claude auth login
are exempt from this check, so users can re-authenticate when expired credentials are the reason the settings fetch fails.
​
Security approval dialogs
Certain settings that could pose security risks require explicit user approval before being applied:
Shell command settings
: settings that execute shell commands
Custom environment variables
: variables not in the known safe allowlist
Hook configurations
: any hook definition
When these settings are present, users see a security dialog explaining what is being configured. Users must approve to proceed. If a user rejects the settings, Claude Code exits.
In non-interactive mode with the
-p
flag, Claude Code skips security dialogs and applies settings without user approval.
​
Platform availability
Server-managed settings require a direct connection to
api.anthropic.com
and are not available when using third-party model providers:
Amazon Bedrock
Google Vertex AI
Microsoft Foundry
Custom API endpoints via
ANTHROPIC_BASE_URL
or
LLM gateways
​
Audit logging
Audit log events for settings changes are available through the compliance API or audit log export. Contact your Anthropic account team for access.
Audit events include the type of action performed, the account and device that performed the action, and references to the previous and new values.
​
Security considerations
Server-managed settings provide centralized policy enforcement, but they operate as a client-side control. On unmanaged devices, users with admin or sudo access can modify the Claude Code binary, filesystem, or network configuration.
Scenario
Behavior
User edits the cached settings file
Tampered file applies at startup, but correct settings restore on the next server fetch
User deletes the cached settings file
First-launch behavior occurs: settings fetch asynchronously with a brief unenforced window
API is unavailable
Cached settings apply if available, otherwise managed settings are not enforced until the next successful fetch. With
forceRemoteSettingsRefresh: true
, the CLI exits instead of continuing, except for
claude auth
subcommands
User authenticates with a different organization
Settings are not delivered for accounts outside the managed organization
User configures a
third-party model provider
Server-managed settings are bypassed. This includes setting
CLAUDE_CODE_USE_BEDROCK
,
CLAUDE_CODE_USE_MANTLE
,
CLAUDE_CODE_USE_VERTEX
,
CLAUDE_CODE_USE_FOUNDRY
, or a non-default
ANTHROPIC_BASE_URL
To detect runtime configuration changes, use
ConfigChange
hooks
to log modifications or block unauthorized changes before they take effect.
For stronger enforcement guarantees, use
endpoint-managed settings
on devices enrolled in an MDM solution.
​
See also
Related pages for managing Claude Code configuration:
Settings
: complete configuration reference including all available settings
Endpoint-managed settings
: managed settings deployed to devices by IT
Authentication
: set up user access to Claude Code
Security
: security safeguards and best practices
Was this page helpful?
Yes
No
Authentication
Auto mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/server-managed-settings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Create plugins</title>
  <link>https://code.claude.com/docs/en/plugins</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/plugins</guid>
  <pubDate>Sun, 16 Jun 2024 00:00:00 +0000</pubDate>
  <category>Plugins</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Create plugins
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Trou...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Create plugins
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins let you extend Claude Code with custom functionality that can be shared across projects and teams. This guide covers creating your own plugins with skills, agents, hooks, and MCP servers.
Looking to install existing plugins? See
Discover and install plugins
. For complete technical specifications, see
Plugins reference
.
​
When to use plugins vs standalone configuration
Claude Code supports two ways to add custom skills, agents, and hooks:
Approach
Skill names
Best for
Standalone
(
.claude/
directory)
/hello
Personal workflows, project-specific customizations, quick experiments
Plugins
(directories with
.claude-plugin/plugin.json
)
/plugin-name:hello
Sharing with teammates, distributing to community, versioned releases, reusable across projects
Use standalone configuration when
:
You’re customizing Claude Code for a single project
The configuration is personal and doesn’t need to be shared
You’re experimenting with skills or hooks before packaging them
You want short skill names like
/hello
or
/deploy
Use plugins when
:
You want to share functionality with your team or community
You need the same skills/agents across multiple projects
You want version control and easy updates for your extensions
You’re distributing through a marketplace
You’re okay with namespaced skills like
/my-plugin:hello
(namespacing prevents conflicts between plugins)
Start with standalone configuration in
.claude/
for quick iteration, then
convert to a plugin
when you’re ready to share.
​
Quickstart
This quickstart walks you through creating a plugin with a custom skill. You’ll create a manifest (the configuration file that defines your plugin), add a skill, and test it locally using the
--plugin-dir
flag.
​
Prerequisites
Claude Code
installed and authenticated
If you don’t see the
/plugin
command, update Claude Code to the latest version. See
Troubleshooting
for upgrade instructions.
​
Create your first plugin
1
Create the plugin directory
Every plugin lives in its own directory containing a manifest and your skills, agents, or hooks. Create one now:
mkdir
my-first-plugin
2
Create the plugin manifest
The manifest file at
.claude-plugin/plugin.json
defines your plugin’s identity: its name, description, and version. Claude Code uses this metadata to display your plugin in the plugin manager.
Create the
.claude-plugin
directory inside your plugin folder:
mkdir
my-first-plugin/.claude-plugin
Then create
my-first-plugin/.claude-plugin/plugin.json
with this content:
my-first-plugin/.claude-plugin/plugin.json
{
"name"
:
"my-first-plugin"
,
"description"
:
"A greeting plugin to learn the basics"
,
"version"
:
"1.0.0"
,
"author"
: {
"name"
:
"Your Name"
}
}
Field
Purpose
name
Unique identifier and skill namespace. Skills are prefixed with this (e.g.,
/my-first-plugin:hello
).
description
Shown in the plugin manager when browsing or installing plugins.
version
Optional. If set, users only receive updates when you bump this field. If omitted and your plugin is distributed via git, the commit SHA is used and every commit counts as a new version. See
version management
.
author
Optional. Helpful for attribution.
For additional fields like
homepage
,
repository
, and
license
, see the
full manifest schema
.
3
Add a skill
Skills live in the
skills/
directory. Each skill is a folder containing a
SKILL.md
file. The folder name becomes the skill name, prefixed with the plugin’s namespace (
hello/
in a plugin named
my-first-plugin
creates
/my-first-plugin:hello
).
Create a skill directory in your plugin folder:
mkdir
-p
my-first-plugin/skills/hello
Then create
my-first-plugin/skills/hello/SKILL.md
with this content:
my-first-plugin/skills/hello/SKILL.md
---
description
:
Greet the user with a friendly message
disable-model-invocation
:
true
---
Greet the user warmly and ask how you can help them today.
4
Test your plugin
Run Claude Code with the
--plugin-dir
flag to load your plugin:
claude
--plugin-dir
./my-first-plugin
Once Claude Code starts, try your new skill:
/my-first-plugin:hello
You’ll see Claude respond with a greeting. Run
/help
to see your skill listed under the plugin namespace.
Why namespacing?
Plugin skills are always namespaced (like
/my-first-plugin:hello
) to prevent conflicts when multiple plugins have skills with the same name.
To change the namespace prefix, update the
name
field in
plugin.json
.
5
Add skill arguments
Make your skill dynamic by accepting user input. The
$ARGUMENTS
placeholder captures any text the user provides after the skill name.
Update your
SKILL.md
file:
my-first-plugin/skills/hello/SKILL.md
---
description
:
Greet the user with a personalized message
---
# Hello Skill
Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.
Run
/reload-plugins
to pick up the changes, then try the skill with your name:
/my-first-plugin:hello
Alex
Claude will greet you by name. For more on passing arguments to skills, see
Skills
.
You’ve successfully created and tested a plugin with these key components:
Plugin manifest
(
.claude-plugin/plugin.json
): describes your plugin’s metadata
Skills directory
(
skills/
): contains your custom skills
Skill arguments
(
$ARGUMENTS
): captures user input for dynamic behavior
The
--plugin-dir
flag is useful for development and testing. When you’re ready to share your plugin with others, see
Create and distribute a plugin marketplace
.
​
Plugin structure overview
You’ve created a plugin with a skill, but plugins can include much more: custom agents, hooks, MCP servers, LSP servers, and background monitors.
Common mistake
: Don’t put
commands/
,
agents/
,
skills/
, or
hooks/
inside the
.claude-plugin/
directory. Only
plugin.json
goes inside
.claude-plugin/
. All other directories must be at the plugin root level.
Directory
Location
Purpose
.claude-plugin/
Plugin root
Contains
plugin.json
manifest (optional if components use default locations)
skills/
Plugin root
Skills as
<name>/SKILL.md
directories
commands/
Plugin root
Skills as flat Markdown files. Use
skills/
for new plugins
agents/
Plugin root
Custom agent definitions
hooks/
Plugin root
Event handlers in
hooks.json
.mcp.json
Plugin root
MCP server configurations
.lsp.json
Plugin root
LSP server configurations for code intelligence
monitors/
Plugin root
Background monitor configurations in
monitors.json
bin/
Plugin root
Executables added to the Bash tool’s
PATH
while the plugin is enabled
settings.json
Plugin root
Default
settings
applied when the plugin is enabled
Next steps
: Ready to add more features? Jump to
Develop more complex plugins
to add agents, hooks, MCP servers, and LSP servers. For complete technical specifications of all plugin components, see
Plugins reference
.
​
Develop more complex plugins
Once you’re comfortable with basic plugins, you can create more sophisticated extensions.
​
Add Skills to your plugin
Plugins can include
Agent Skills
to extend Claude’s capabilities. Skills are model-invoked: Claude automatically uses them based on the task context.
Add a
skills/
directory at your plugin root with Skill folders containing
SKILL.md
files:
my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── skills/
└── code-review/
└── SKILL.md
Each
SKILL.md
contains YAML frontmatter and instructions. Include a
description
so Claude knows when to use the skill:
---
description
:
Reviews code for best practices and potential issues. Use when reviewing code, checking PRs, or analyzing code quality.
---
When reviewing code, check for
:
1. Code organization and structure
2. Error handling
3. Security concerns
4. Test coverage
After installing the plugin, run
/reload-plugins
to load the Skills. For complete Skill authoring guidance including progressive disclosure and tool restrictions, see
Agent Skills
.
​
Add LSP servers to your plugin
For common languages like TypeScript, Python, and Rust, install the pre-built LSP plugins from the official marketplace. Create custom LSP plugins only when you need support for languages not already covered.
LSP (Language Server Protocol) plugins give Claude real-time code intelligence. If you need to support a language that doesn’t have an official LSP plugin, you can create your own by adding an
.lsp.json
file to your plugin:
.lsp.json
{
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
Users installing your plugin must have the language server binary installed on their machine.
For complete LSP configuration options, see
LSP servers
.
​
Add background monitors to your plugin
Background monitors let your plugin watch logs, files, or external status in the background and notify Claude as events arrive. Claude Code starts each monitor automatically when the plugin is active, so you don’t need to instruct Claude to start the watch.
Add a
monitors/monitors.json
file at the plugin root with an array of monitor entries:
monitors/monitors.json
[
{
"name"
:
"error-log"
,
"command"
:
"tail -F ./logs/error.log"
,
"description"
:
"Application error log"
}
]
Each stdout line from
command
is delivered to Claude as a notification during the session. For the full schema, including the
when
trigger and variable substitution, see
Monitors
.
​
Ship default settings with your plugin
Plugins can include a
settings.json
file at the plugin root to apply default configuration when the plugin is enabled. Currently, only the
agent
and
subagentStatusLine
keys are supported.
Setting
agent
activates one of the plugin’s
custom agents
as the main thread, applying its system prompt, tool restrictions, and model. This lets a plugin change how Claude Code behaves by default when enabled.
settings.json
{
"agent"
:
"security-reviewer"
}
This example activates the
security-reviewer
agent defined in the plugin’s
agents/
directory. Settings from
settings.json
take priority over
settings
declared in
plugin.json
. Unknown keys are silently ignored.
​
Organize complex plugins
For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see
Plugin directory structure
.
​
Test your plugins locally
Use the
--plugin-dir
flag to test plugins during development. This loads your plugin directly without requiring installation.
claude
--plugin-dir
./my-plugin
The flag also accepts a
.zip
archive of the plugin directory, which requires Claude Code v2.1.128 or later.
claude
--plugin-dir
./my-plugin.zip
When a
--plugin-dir
plugin has the same name as an installed marketplace plugin, the local copy takes precedence for that session. This lets you test changes to a plugin you already have installed without uninstalling it first. The exception is plugins that managed settings force-enable or force-disable:
--plugin-dir
cannot override those.
As you make changes to your plugin, run
/reload-plugins
to pick up the updates without restarting. This reloads plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers. Test your plugin components:
Try your skills with
/plugin-name:skill-name
Check that agents appear in
/agents
Verify hooks work as expected
You can load multiple plugins at once by specifying the flag multiple times:
claude
--plugin-dir
./plugin-one
--plugin-dir
./plugin-two
To test a plugin that is already packaged as a
.zip
archive and hosted at a URL, such as a CI build artifact, use
--plugin-url
instead. Claude Code fetches the archive at startup and loads it for that session only. If the fetch fails or the archive is invalid, Claude Code reports a plugin load error and starts without it. The same
trust considerations
apply as for any plugin source: only point this flag at archives you control or trust.
To load multiple plugins, repeat the flag for each URL:
claude
--plugin-url
https://example.com/my-plugin.zip
--plugin-url
https://example.com/other.zip
Or pass space-separated URLs as one quoted argument:
claude
--plugin-url
"https://example.com/my-plugin.zip https://example.com/other.zip"
​
Debug plugin issues
If your plugin isn’t working as expected:
Check the structure
: Ensure your directories are at the plugin root, not inside
.claude-plugin/
Test components individually
: Check each skill, agent, and hook separately
Use validation and debugging tools
: See
Debugging and development tools
for CLI commands and troubleshooting techniques
​
Share your plugins
When your plugin is ready to share:
Add documentation
: Include a
README.md
with installation and usage instructions
Choose a versioning strategy
: Decide whether to set an explicit
version
or rely on the git commit SHA. See
version management
Create or use a marketplace
: Distribute through
plugin marketplaces
for installation
Test with others
: Have team members test the plugin before wider distribution
Once your plugin is in a marketplace, others can install it using the instructions in
Discover and install plugins
. To keep a plugin internal to your team, host the marketplace in a
private repository
.
​
Submit your plugin to the official marketplace
To submit a plugin to the official Anthropic marketplace, use one of the in-app submission forms:
Claude.ai
:
claude.ai/settings/plugins/submit
Console
:
platform.claude.com/plugins/submit
Once your plugin is listed, you can have your own CLI prompt Claude Code users to install it. See
Recommend your plugin from your CLI
.
For complete technical specifications, debugging techniques, and distribution strategies, see
Plugins reference
.
​
Convert existing configurations to plugins
If you already have skills or hooks in your
.claude/
directory, you can convert them into a plugin for easier sharing and distribution.
​
Migration steps
1
Create the plugin structure
Create a new plugin directory:
mkdir
-p
my-plugin/.claude-plugin
Create the manifest file at
my-plugin/.claude-plugin/plugin.json
:
my-plugin/.claude-plugin/plugin.json
{
"name"
:
"my-plugin"
,
"description"
:
"Migrated from standalone configuration"
,
"version"
:
"1.0.0"
}
2
Copy your existing files
Copy your existing configurations to the plugin directory:
# Copy commands
cp
-r
.claude/commands
my-plugin/
# Copy agents (if any)
cp
-r
.claude/agents
my-plugin/
# Copy skills (if any)
cp
-r
.claude/skills
my-plugin/
3
Migrate hooks
If you have hooks in your settings, create a hooks directory:
mkdir
my-plugin/hooks
Create
my-plugin/hooks/hooks.json
with your hooks configuration. Copy the
hooks
object from your
.claude/settings.json
or
settings.local.json
, since the format is the same. The command receives hook input as JSON on stdin, so use
jq
to extract the file path:
my-plugin/hooks/hooks.json
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npm run lint:fix"
}]
}
]
}
}
4
Test your migrated plugin
Load your plugin to verify everything works:
claude
--plugin-dir
./my-plugin
Test each component: run your commands, check agents appear in
/agents
, and verify hooks trigger correctly.
​
What changes when migrating
Standalone (
.claude/
)
Plugin
Only available in one project
Can be shared via marketplaces
Files in
.claude/commands/
Files in
plugin-name/commands/
Hooks in
settings.json
Hooks in
hooks/hooks.json
Must manually copy to share
Install with
/plugin install
After migrating, you can remove the original files from
.claude/
to avoid duplicates. The plugin version will take precedence when loaded.
​
Next steps
Now that you understand Claude Code’s plugin system, here are suggested paths for different goals:
​
For plugin users
Discover and install plugins
: browse marketplaces and install plugins
Configure team marketplaces
: set up repository-level plugins for your team
​
For plugin developers
Create and distribute a marketplace
: package and share your plugins
Plugins reference
: complete technical specifications
Dive deeper into specific plugin components:
Skills
: skill development details
Subagents
: agent configuration and capabilities
Hooks
: event handling and automation
MCP
: external tool integration
Was this page helpful?
Yes
No
Discover and install prebuilt plugins
Extend Claude with skills
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Create plugins
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Trou...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Create plugins
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins let you extend Claude Code with custom functionality that can be shared across projects and teams. This guide covers creating your own plugins with skills, agents, hooks, and MCP servers.
Looking to install existing plugins? See
Discover and install plugins
. For complete technical specifications, see
Plugins reference
.
​
When to use plugins vs standalone configuration
Claude Code supports two ways to add custom skills, agents, and hooks:
Approach
Skill names
Best for
Standalone
(
.claude/
directory)
/hello
Personal workflows, project-specific customizations, quick experiments
Plugins
(directories with
.claude-plugin/plugin.json
)
/plugin-name:hello
Sharing with teammates, distributing to community, versioned releases, reusable across projects
Use standalone configuration when
:
You’re customizing Claude Code for a single project
The configuration is personal and doesn’t need to be shared
You’re experimenting with skills or hooks before packaging them
You want short skill names like
/hello
or
/deploy
Use plugins when
:
You want to share functionality with your team or community
You need the same skills/agents across multiple projects
You want version control and easy updates for your extensions
You’re distributing through a marketplace
You’re okay with namespaced skills like
/my-plugin:hello
(namespacing prevents conflicts between plugins)
Start with standalone configuration in
.claude/
for quick iteration, then
convert to a plugin
when you’re ready to share.
​
Quickstart
This quickstart walks you through creating a plugin with a custom skill. You’ll create a manifest (the configuration file that defines your plugin), add a skill, and test it locally using the
--plugin-dir
flag.
​
Prerequisites
Claude Code
installed and authenticated
If you don’t see the
/plugin
command, update Claude Code to the latest version. See
Troubleshooting
for upgrade instructions.
​
Create your first plugin
1
Create the plugin directory
Every plugin lives in its own directory containing a manifest and your skills, agents, or hooks. Create one now:
mkdir
my-first-plugin
2
Create the plugin manifest
The manifest file at
.claude-plugin/plugin.json
defines your plugin’s identity: its name, description, and version. Claude Code uses this metadata to display your plugin in the plugin manager.
Create the
.claude-plugin
directory inside your plugin folder:
mkdir
my-first-plugin/.claude-plugin
Then create
my-first-plugin/.claude-plugin/plugin.json
with this content:
my-first-plugin/.claude-plugin/plugin.json
{
"name"
:
"my-first-plugin"
,
"description"
:
"A greeting plugin to learn the basics"
,
"version"
:
"1.0.0"
,
"author"
: {
"name"
:
"Your Name"
}
}
Field
Purpose
name
Unique identifier and skill namespace. Skills are prefixed with this (e.g.,
/my-first-plugin:hello
).
description
Shown in the plugin manager when browsing or installing plugins.
version
Optional. If set, users only receive updates when you bump this field. If omitted and your plugin is distributed via git, the commit SHA is used and every commit counts as a new version. See
version management
.
author
Optional. Helpful for attribution.
For additional fields like
homepage
,
repository
, and
license
, see the
full manifest schema
.
3
Add a skill
Skills live in the
skills/
directory. Each skill is a folder containing a
SKILL.md
file. The folder name becomes the skill name, prefixed with the plugin’s namespace (
hello/
in a plugin named
my-first-plugin
creates
/my-first-plugin:hello
).
Create a skill directory in your plugin folder:
mkdir
-p
my-first-plugin/skills/hello
Then create
my-first-plugin/skills/hello/SKILL.md
with this content:
my-first-plugin/skills/hello/SKILL.md
---
description
:
Greet the user with a friendly message
disable-model-invocation
:
true
---
Greet the user warmly and ask how you can help them today.
4
Test your plugin
Run Claude Code with the
--plugin-dir
flag to load your plugin:
claude
--plugin-dir
./my-first-plugin
Once Claude Code starts, try your new skill:
/my-first-plugin:hello
You’ll see Claude respond with a greeting. Run
/help
to see your skill listed under the plugin namespace.
Why namespacing?
Plugin skills are always namespaced (like
/my-first-plugin:hello
) to prevent conflicts when multiple plugins have skills with the same name.
To change the namespace prefix, update the
name
field in
plugin.json
.
5
Add skill arguments
Make your skill dynamic by accepting user input. The
$ARGUMENTS
placeholder captures any text the user provides after the skill name.
Update your
SKILL.md
file:
my-first-plugin/skills/hello/SKILL.md
---
description
:
Greet the user with a personalized message
---
# Hello Skill
Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.
Run
/reload-plugins
to pick up the changes, then try the skill with your name:
/my-first-plugin:hello
Alex
Claude will greet you by name. For more on passing arguments to skills, see
Skills
.
You’ve successfully created and tested a plugin with these key components:
Plugin manifest
(
.claude-plugin/plugin.json
): describes your plugin’s metadata
Skills directory
(
skills/
): contains your custom skills
Skill arguments
(
$ARGUMENTS
): captures user input for dynamic behavior
The
--plugin-dir
flag is useful for development and testing. When you’re ready to share your plugin with others, see
Create and distribute a plugin marketplace
.
​
Plugin structure overview
You’ve created a plugin with a skill, but plugins can include much more: custom agents, hooks, MCP servers, LSP servers, and background monitors.
Common mistake
: Don’t put
commands/
,
agents/
,
skills/
, or
hooks/
inside the
.claude-plugin/
directory. Only
plugin.json
goes inside
.claude-plugin/
. All other directories must be at the plugin root level.
Directory
Location
Purpose
.claude-plugin/
Plugin root
Contains
plugin.json
manifest (optional if components use default locations)
skills/
Plugin root
Skills as
<name>/SKILL.md
directories
commands/
Plugin root
Skills as flat Markdown files. Use
skills/
for new plugins
agents/
Plugin root
Custom agent definitions
hooks/
Plugin root
Event handlers in
hooks.json
.mcp.json
Plugin root
MCP server configurations
.lsp.json
Plugin root
LSP server configurations for code intelligence
monitors/
Plugin root
Background monitor configurations in
monitors.json
bin/
Plugin root
Executables added to the Bash tool’s
PATH
while the plugin is enabled
settings.json
Plugin root
Default
settings
applied when the plugin is enabled
Next steps
: Ready to add more features? Jump to
Develop more complex plugins
to add agents, hooks, MCP servers, and LSP servers. For complete technical specifications of all plugin components, see
Plugins reference
.
​
Develop more complex plugins
Once you’re comfortable with basic plugins, you can create more sophisticated extensions.
​
Add Skills to your plugin
Plugins can include
Agent Skills
to extend Claude’s capabilities. Skills are model-invoked: Claude automatically uses them based on the task context.
Add a
skills/
directory at your plugin root with Skill folders containing
SKILL.md
files:
my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── skills/
└── code-review/
└── SKILL.md
Each
SKILL.md
contains YAML frontmatter and instructions. Include a
description
so Claude knows when to use the skill:
---
description
:
Reviews code for best practices and potential issues. Use when reviewing code, checking PRs, or analyzing code quality.
---
When reviewing code, check for
:
1. Code organization and structure
2. Error handling
3. Security concerns
4. Test coverage
After installing the plugin, run
/reload-plugins
to load the Skills. For complete Skill authoring guidance including progressive disclosure and tool restrictions, see
Agent Skills
.
​
Add LSP servers to your plugin
For common languages like TypeScript, Python, and Rust, install the pre-built LSP plugins from the official marketplace. Create custom LSP plugins only when you need support for languages not already covered.
LSP (Language Server Protocol) plugins give Claude real-time code intelligence. If you need to support a language that doesn’t have an official LSP plugin, you can create your own by adding an
.lsp.json
file to your plugin:
.lsp.json
{
"go"
: {
"command"
:
"gopls"
,
"args"
: [
"serve"
],
"extensionToLanguage"
: {
".go"
:
"go"
}
}
}
Users installing your plugin must have the language server binary installed on their machine.
For complete LSP configuration options, see
LSP servers
.
​
Add background monitors to your plugin
Background monitors let your plugin watch logs, files, or external status in the background and notify Claude as events arrive. Claude Code starts each monitor automatically when the plugin is active, so you don’t need to instruct Claude to start the watch.
Add a
monitors/monitors.json
file at the plugin root with an array of monitor entries:
monitors/monitors.json
[
{
"name"
:
"error-log"
,
"command"
:
"tail -F ./logs/error.log"
,
"description"
:
"Application error log"
}
]
Each stdout line from
command
is delivered to Claude as a notification during the session. For the full schema, including the
when
trigger and variable substitution, see
Monitors
.
​
Ship default settings with your plugin
Plugins can include a
settings.json
file at the plugin root to apply default configuration when the plugin is enabled. Currently, only the
agent
and
subagentStatusLine
keys are supported.
Setting
agent
activates one of the plugin’s
custom agents
as the main thread, applying its system prompt, tool restrictions, and model. This lets a plugin change how Claude Code behaves by default when enabled.
settings.json
{
"agent"
:
"security-reviewer"
}
This example activates the
security-reviewer
agent defined in the plugin’s
agents/
directory. Settings from
settings.json
take priority over
settings
declared in
plugin.json
. Unknown keys are silently ignored.
​
Organize complex plugins
For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see
Plugin directory structure
.
​
Test your plugins locally
Use the
--plugin-dir
flag to test plugins during development. This loads your plugin directly without requiring installation.
claude
--plugin-dir
./my-plugin
The flag also accepts a
.zip
archive of the plugin directory, which requires Claude Code v2.1.128 or later.
claude
--plugin-dir
./my-plugin.zip
When a
--plugin-dir
plugin has the same name as an installed marketplace plugin, the local copy takes precedence for that session. This lets you test changes to a plugin you already have installed without uninstalling it first. The exception is plugins that managed settings force-enable or force-disable:
--plugin-dir
cannot override those.
As you make changes to your plugin, run
/reload-plugins
to pick up the updates without restarting. This reloads plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers. Test your plugin components:
Try your skills with
/plugin-name:skill-name
Check that agents appear in
/agents
Verify hooks work as expected
You can load multiple plugins at once by specifying the flag multiple times:
claude
--plugin-dir
./plugin-one
--plugin-dir
./plugin-two
To test a plugin that is already packaged as a
.zip
archive and hosted at a URL, such as a CI build artifact, use
--plugin-url
instead. Claude Code fetches the archive at startup and loads it for that session only. If the fetch fails or the archive is invalid, Claude Code reports a plugin load error and starts without it. The same
trust considerations
apply as for any plugin source: only point this flag at archives you control or trust.
To load multiple plugins, repeat the flag for each URL:
claude
--plugin-url
https://example.com/my-plugin.zip
--plugin-url
https://example.com/other.zip
Or pass space-separated URLs as one quoted argument:
claude
--plugin-url
"https://example.com/my-plugin.zip https://example.com/other.zip"
​
Debug plugin issues
If your plugin isn’t working as expected:
Check the structure
: Ensure your directories are at the plugin root, not inside
.claude-plugin/
Test components individually
: Check each skill, agent, and hook separately
Use validation and debugging tools
: See
Debugging and development tools
for CLI commands and troubleshooting techniques
​
Share your plugins
When your plugin is ready to share:
Add documentation
: Include a
README.md
with installation and usage instructions
Choose a versioning strategy
: Decide whether to set an explicit
version
or rely on the git commit SHA. See
version management
Create or use a marketplace
: Distribute through
plugin marketplaces
for installation
Test with others
: Have team members test the plugin before wider distribution
Once your plugin is in a marketplace, others can install it using the instructions in
Discover and install plugins
. To keep a plugin internal to your team, host the marketplace in a
private repository
.
​
Submit your plugin to the official marketplace
To submit a plugin to the official Anthropic marketplace, use one of the in-app submission forms:
Claude.ai
:
claude.ai/settings/plugins/submit
Console
:
platform.claude.com/plugins/submit
Once your plugin is listed, you can have your own CLI prompt Claude Code users to install it. See
Recommend your plugin from your CLI
.
For complete technical specifications, debugging techniques, and distribution strategies, see
Plugins reference
.
​
Convert existing configurations to plugins
If you already have skills or hooks in your
.claude/
directory, you can convert them into a plugin for easier sharing and distribution.
​
Migration steps
1
Create the plugin structure
Create a new plugin directory:
mkdir
-p
my-plugin/.claude-plugin
Create the manifest file at
my-plugin/.claude-plugin/plugin.json
:
my-plugin/.claude-plugin/plugin.json
{
"name"
:
"my-plugin"
,
"description"
:
"Migrated from standalone configuration"
,
"version"
:
"1.0.0"
}
2
Copy your existing files
Copy your existing configurations to the plugin directory:
# Copy commands
cp
-r
.claude/commands
my-plugin/
# Copy agents (if any)
cp
-r
.claude/agents
my-plugin/
# Copy skills (if any)
cp
-r
.claude/skills
my-plugin/
3
Migrate hooks
If you have hooks in your settings, create a hooks directory:
mkdir
my-plugin/hooks
Create
my-plugin/hooks/hooks.json
with your hooks configuration. Copy the
hooks
object from your
.claude/settings.json
or
settings.local.json
, since the format is the same. The command receives hook input as JSON on stdin, so use
jq
to extract the file path:
my-plugin/hooks/hooks.json
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npm run lint:fix"
}]
}
]
}
}
4
Test your migrated plugin
Load your plugin to verify everything works:
claude
--plugin-dir
./my-plugin
Test each component: run your commands, check agents appear in
/agents
, and verify hooks trigger correctly.
​
What changes when migrating
Standalone (
.claude/
)
Plugin
Only available in one project
Can be shared via marketplaces
Files in
.claude/commands/
Files in
plugin-name/commands/
Hooks in
settings.json
Hooks in
hooks/hooks.json
Must manually copy to share
Install with
/plugin install
After migrating, you can remove the original files from
.claude/
to avoid duplicates. The plugin version will take precedence when loaded.
​
Next steps
Now that you understand Claude Code’s plugin system, here are suggested paths for different goals:
​
For plugin users
Discover and install plugins
: browse marketplaces and install plugins
Configure team marketplaces
: set up repository-level plugins for your team
​
For plugin developers
Create and distribute a marketplace
: package and share your plugins
Plugins reference
: complete technical specifications
Dive deeper into specific plugin components:
Skills
: skill development details
Subagents
: agent configuration and capabilities
Hooks
: event handling and automation
MCP
: external tool integration
Was this page helpful?
Yes
No
Discover and install prebuilt plugins
Extend Claude with skills
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Platforms and integrations</title>
  <link>https://code.claude.com/docs/en/platforms</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/platforms</guid>
  <pubDate>Sun, 16 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Platforms and integrations
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extensi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Platforms and integrations
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code runs the same underlying engine everywhere, but each surface is tuned for a different way of working. This page helps you pick the right platform for your workflow and connect the tools you already use.
​
Where to run Claude Code
Choose a platform based on how you like to work and where your project lives.
Platform
Best for
What you get
CLI
Terminal workflows, scripting, remote servers
Full feature set,
Agent SDK
,
computer use
on macOS (Pro and Max), third-party providers
Desktop
Visual review, parallel sessions, managed setup
Diff viewer, app preview,
computer use
and
Dispatch
on Pro and Max
VS Code
Working inside VS Code without switching to a terminal
Inline diffs, integrated terminal, file context
JetBrains
Working inside IntelliJ, PyCharm, WebStorm, or other JetBrains IDEs
Diff viewer, selection sharing, terminal session
Web
Long-running tasks that don’t need much steering, or work that should continue when you’re offline
Anthropic-managed cloud, continues after you disconnect
Mobile
Starting and monitoring tasks while away from your computer
Cloud sessions from the Claude app for iOS and Android,
Remote Control
for local sessions,
Dispatch
to Desktop on Pro and Max
The CLI is the most complete surface for terminal-native work: scripting and the Agent SDK are CLI-only. Third-party providers also work in
VS Code
. Enterprise
Desktop
deployments support Vertex AI and gateway providers; for Bedrock or Foundry, use the CLI or VS Code instead of Desktop. Desktop and the IDE extensions trade some CLI-only features for visual review and tighter editor integration. The web runs in Anthropic’s cloud, so tasks keep going after you disconnect. Mobile is a thin client into those same cloud sessions or into a local session via Remote Control, and can send tasks to Desktop with Dispatch.
You can mix surfaces on the same project. Configuration, project memory, and MCP servers are shared across the local surfaces.
​
Connect your tools
Integrations let Claude work with services outside your codebase.
Integration
What it does
Use it for
Chrome
Controls your browser with your logged-in sessions
Testing web apps, filling forms, automating sites without an API
GitHub Actions
Runs Claude in your CI pipeline
Automated PR reviews, issue triage, scheduled maintenance
GitLab CI/CD
Same as GitHub Actions for GitLab
CI-driven automation on GitLab
Code Review
Reviews every PR automatically
Catching bugs before human review
Slack
Responds to
@Claude
mentions in your channels
Turning bug reports into pull requests from team chat
For integrations not listed here,
MCP servers
and
connectors
let you connect almost anything: Linear, Notion, Google Drive, or your own internal APIs.
​
Work when you are away from your terminal
Claude Code offers several ways to work when you’re not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.
Trigger
Claude runs on
Setup
Best for
Dispatch
Message a task from the Claude mobile app
Your machine (Desktop)
Pair the mobile app with Desktop
Delegating work while you’re away, minimal setup
Remote Control
Drive a running session from
claude.ai/code
or the Claude mobile app
Your machine (CLI or VS Code)
Run
claude remote-control
Steering in-progress work from another device
Channels
Push events from a chat app like Telegram or Discord, or your own server
Your machine (CLI)
Install a channel plugin
or
build your own
Reacting to external events like CI failures or chat messages
Slack
Mention
@Claude
in a team channel
Anthropic cloud
Install the Slack app
with
Claude Code on the web
enabled
PRs and reviews from team chat
Scheduled tasks
Set a schedule
CLI
,
Desktop
, or
cloud
Pick a frequency
Recurring automation like daily reviews
If you’re not sure where to start,
install the CLI
and run it in a project directory. If you’d rather not use a terminal,
Desktop
gives you the same engine with a graphical interface.
​
Related resources
​
Platforms
CLI quickstart
: install and run your first command in the terminal
Desktop
: visual diff review, parallel sessions, computer use, and Dispatch
VS Code
: the Claude Code extension inside your editor
JetBrains
: the extension for IntelliJ, PyCharm, and other JetBrains IDEs
Claude Code on the web
: cloud sessions that keep running when you disconnect
Mobile: the Claude app for
iOS
and
Android
for starting and monitoring tasks while away from your computer
​
Integrations
Chrome
: automate browser tasks with your logged-in sessions
Computer use
: let Claude open apps and control your screen on macOS
GitHub Actions
: run Claude in your CI pipeline
GitLab CI/CD
: the same for GitLab
Code Review
: automatic review on every pull request
Slack
: send tasks from team chat, get PRs back
​
Remote access
Dispatch
: message a task from your phone and it can spawn a Desktop session
Remote Control
: drive a running session from your phone or browser
Channels
: push events from chat apps or your own servers into a session
Scheduled tasks
: run prompts on a recurring schedule
Was this page helpful?
Yes
No
Best practices
Remote Control
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/platforms" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Platforms and integrations
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extensi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Platforms and integrations
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code runs the same underlying engine everywhere, but each surface is tuned for a different way of working. This page helps you pick the right platform for your workflow and connect the tools you already use.
​
Where to run Claude Code
Choose a platform based on how you like to work and where your project lives.
Platform
Best for
What you get
CLI
Terminal workflows, scripting, remote servers
Full feature set,
Agent SDK
,
computer use
on macOS (Pro and Max), third-party providers
Desktop
Visual review, parallel sessions, managed setup
Diff viewer, app preview,
computer use
and
Dispatch
on Pro and Max
VS Code
Working inside VS Code without switching to a terminal
Inline diffs, integrated terminal, file context
JetBrains
Working inside IntelliJ, PyCharm, WebStorm, or other JetBrains IDEs
Diff viewer, selection sharing, terminal session
Web
Long-running tasks that don’t need much steering, or work that should continue when you’re offline
Anthropic-managed cloud, continues after you disconnect
Mobile
Starting and monitoring tasks while away from your computer
Cloud sessions from the Claude app for iOS and Android,
Remote Control
for local sessions,
Dispatch
to Desktop on Pro and Max
The CLI is the most complete surface for terminal-native work: scripting and the Agent SDK are CLI-only. Third-party providers also work in
VS Code
. Enterprise
Desktop
deployments support Vertex AI and gateway providers; for Bedrock or Foundry, use the CLI or VS Code instead of Desktop. Desktop and the IDE extensions trade some CLI-only features for visual review and tighter editor integration. The web runs in Anthropic’s cloud, so tasks keep going after you disconnect. Mobile is a thin client into those same cloud sessions or into a local session via Remote Control, and can send tasks to Desktop with Dispatch.
You can mix surfaces on the same project. Configuration, project memory, and MCP servers are shared across the local surfaces.
​
Connect your tools
Integrations let Claude work with services outside your codebase.
Integration
What it does
Use it for
Chrome
Controls your browser with your logged-in sessions
Testing web apps, filling forms, automating sites without an API
GitHub Actions
Runs Claude in your CI pipeline
Automated PR reviews, issue triage, scheduled maintenance
GitLab CI/CD
Same as GitHub Actions for GitLab
CI-driven automation on GitLab
Code Review
Reviews every PR automatically
Catching bugs before human review
Slack
Responds to
@Claude
mentions in your channels
Turning bug reports into pull requests from team chat
For integrations not listed here,
MCP servers
and
connectors
let you connect almost anything: Linear, Notion, Google Drive, or your own internal APIs.
​
Work when you are away from your terminal
Claude Code offers several ways to work when you’re not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.
Trigger
Claude runs on
Setup
Best for
Dispatch
Message a task from the Claude mobile app
Your machine (Desktop)
Pair the mobile app with Desktop
Delegating work while you’re away, minimal setup
Remote Control
Drive a running session from
claude.ai/code
or the Claude mobile app
Your machine (CLI or VS Code)
Run
claude remote-control
Steering in-progress work from another device
Channels
Push events from a chat app like Telegram or Discord, or your own server
Your machine (CLI)
Install a channel plugin
or
build your own
Reacting to external events like CI failures or chat messages
Slack
Mention
@Claude
in a team channel
Anthropic cloud
Install the Slack app
with
Claude Code on the web
enabled
PRs and reviews from team chat
Scheduled tasks
Set a schedule
CLI
,
Desktop
, or
cloud
Pick a frequency
Recurring automation like daily reviews
If you’re not sure where to start,
install the CLI
and run it in a project directory. If you’d rather not use a terminal,
Desktop
gives you the same engine with a graphical interface.
​
Related resources
​
Platforms
CLI quickstart
: install and run your first command in the terminal
Desktop
: visual diff review, parallel sessions, computer use, and Dispatch
VS Code
: the Claude Code extension inside your editor
JetBrains
: the extension for IntelliJ, PyCharm, and other JetBrains IDEs
Claude Code on the web
: cloud sessions that keep running when you disconnect
Mobile: the Claude app for
iOS
and
Android
for starting and monitoring tasks while away from your computer
​
Integrations
Chrome
: automate browser tasks with your logged-in sessions
Computer use
: let Claude open apps and control your screen on macOS
GitHub Actions
: run Claude in your CI pipeline
GitLab CI/CD
: the same for GitLab
Code Review
: automatic review on every pull request
Slack
: send tasks from team chat, get PRs back
​
Remote access
Dispatch
: message a task from your phone and it can spawn a Desktop session
Remote Control
: drive a running session from your phone or browser
Channels
: push events from chat apps or your own servers into a session
Scheduled tasks
: run prompts on a recurring schedule
Was this page helpful?
Yes
No
Best practices
Remote Control
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/platforms" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Automate workflows with hooks</title>
  <link>https://code.claude.com/docs/en/hooks-guide</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/hooks-guide</guid>
  <pubDate>Thu, 13 Jun 2024 00:00:00 +0000</pubDate>
  <category>Guides</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Automate workflows with hooks
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from li...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Automate workflows with hooks
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Hooks are user-defined shell commands that execute at specific points in Claude Code’s lifecycle. They provide deterministic control over Claude Code’s behavior, ensuring certain actions always happen rather than relying on the LLM to choose to run them. Use hooks to enforce project rules, automate repetitive tasks, and integrate Claude Code with your existing tools.
For decisions that require judgment rather than deterministic rules, you can also use
prompt-based hooks
or
agent-based hooks
that use a Claude model to evaluate conditions.
For other ways to extend Claude Code, see
skills
for giving Claude additional instructions and executable commands,
subagents
for running tasks in isolated contexts, and
plugins
for packaging extensions to share across projects.
This guide covers common use cases and how to get started. For full event schemas, JSON input/output formats, and advanced features like async hooks and MCP tool hooks, see the
Hooks reference
.
​
Set up your first hook
To create a hook, add a
hooks
block to a
settings file
. This walkthrough creates a desktop notification hook, so you get alerted whenever Claude is waiting for your input instead of watching the terminal.
1
Add the hook to your settings
Open
~/.claude/settings.json
and add a
Notification
hook. The example below uses
osascript
for macOS; see
Get notified when Claude needs input
for Linux and Windows commands.
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}
]
}
]
}
}
If your settings file already has a
hooks
key, add
Notification
as a sibling of the existing event keys rather than replacing the whole object. Each event name is a key inside the single
hooks
object:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npx prettier --write"
}]
}
],
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}]
}
]
}
}
You can also ask Claude to write the hook for you by describing what you want in the CLI.
2
Verify the configuration
Type
/hooks
to open the hooks browser. You’ll see a list of all available hook events, with a count next to each event that has hooks configured. Select
Notification
to confirm your new hook appears in the list. Selecting the hook shows its details: the event, matcher, type, source file, and command.
3
Test the hook
Press
Esc
to return to the CLI. Ask Claude to do something that requires permission, then switch away from the terminal. You should receive a desktop notification.
The
/hooks
menu is read-only. To add, modify, or remove hooks, edit your settings JSON directly or ask Claude to make the change.
​
What you can automate
Hooks let you run code at key points in Claude Code’s lifecycle: format files after edits, block commands before they execute, send notifications when Claude needs input, inject context at session start, and more. For the full list of hook events, see the
Hooks reference
.
Each example includes a ready-to-use configuration block that you add to a
settings file
. The most common patterns:
Get notified when Claude needs input
Auto-format code after edits
Block edits to protected files
Re-inject context after compaction
Audit configuration changes
Reload environment when directory or files change
Auto-approve specific permission prompts
​
Get notified when Claude needs input
Get a desktop notification whenever Claude finishes working and needs your input, so you can switch to other tasks without checking the terminal.
This hook uses the
Notification
event, which fires when Claude is waiting for input or permission. Each tab below uses the platform’s native notification command. Add this to
~/.claude/settings.json
:
macOS
Linux
Windows (PowerShell)
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}
]
}
]
}
}
If no notification appears
osascript
routes notifications through the built-in Script Editor app. If Script Editor doesn’t have notification permission, the command fails silently, and macOS won’t prompt you to grant it. Run this in Terminal once to make Script Editor appear in your notification settings:
osascript
-e
'display notification "test"'
Nothing will appear yet. Open
System Settings > Notifications
, find
Script Editor
in the list, and turn on
Allow Notifications
. Run the command again to confirm the test notification appears.
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"powershell.exe -Command
\"
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')
\"
"
}
]
}
]
}
}
The empty
matcher
fires on all notification types. To fire only on specific events, set it to one of these values:
Matcher
Fires when
permission_prompt
Claude needs you to approve a tool use
idle_prompt
Claude is done and waiting for your next prompt
auth_success
Authentication completes
elicitation_dialog
An MCP server opens an elicitation form
elicitation_complete
An MCP elicitation form is submitted or dismissed
elicitation_response
An MCP elicitation response is sent back to the server
Type
/hooks
and select
Notification
to confirm the hook is registered. For the full event schema, see the
Notification reference
.
​
Auto-format code after edits
Automatically run
Prettier
on every file Claude edits, so formatting stays consistent without manual intervention.
This hook uses the
PostToolUse
event with an
Edit|Write
matcher, so it runs only after file-editing tools. The command extracts the edited file path with
jq
and passes it to Prettier. Add this to
.claude/settings.json
in your project root:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
The Bash examples on this page use
jq
for JSON parsing. Install it with
brew install jq
(macOS),
apt-get install jq
(Debian/Ubuntu), or see
jq
downloads
.
​
Block edits to protected files
Prevent Claude from modifying sensitive files like
.env
,
package-lock.json
, or anything in
.git/
. Claude receives feedback explaining why the edit was blocked, so it can adjust its approach.
This example uses a separate script file that the hook calls. The script checks the target file path against a list of protected patterns and exits with code 2 to block the edit.
1
Create the hook script
Save this to
.claude/hooks/protect-files.sh
:
#!/bin/bash
# protect-files.sh
INPUT
=
$(
cat
)
FILE_PATH
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.file_path // empty'
)
PROTECTED_PATTERNS
=
(
".env"
"package-lock.json"
".git/"
)
for
pattern
in
"${
PROTECTED_PATTERNS
[
@
]}"
;
do
if
[[
"
$FILE_PATH
"
==
*
"
$pattern
"
*
]];
then
echo
"Blocked:
$FILE_PATH
matches protected pattern '
$pattern
'"
>&2
exit
2
fi
done
exit
0
2
Make the script executable (macOS/Linux)
Hook scripts must be executable for Claude Code to run them:
chmod
+x
.claude/hooks/protect-files.sh
3
Register the hook
Add a
PreToolUse
hook to
.claude/settings.json
that runs the script before any
Edit
or
Write
tool call:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
​
Re-inject context after compaction
When Claude’s context window fills up, compaction summarizes the conversation to free space. This can lose important details. Use a
SessionStart
hook with a
compact
matcher to re-inject critical context after every compaction.
Any text your command writes to stdout is added to Claude’s context. This example reminds Claude of project conventions and recent work. Add this to
.claude/settings.json
in your project root:
{
"hooks"
: {
"SessionStart"
: [
{
"matcher"
:
"compact"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
}
]
}
]
}
}
You can replace the
echo
with any command that produces dynamic output, like
git log --oneline -5
to show recent commits. For injecting context on every session start, consider using
CLAUDE.md
instead. For environment variables, see
CLAUDE_ENV_FILE
in the reference.
​
Audit configuration changes
Track when settings or skills files change during a session. The
ConfigChange
event fires when an external process or editor modifies a configuration file, so you can log changes for compliance or block unauthorized modifications.
This example appends each change to an audit log. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"ConfigChange"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
}
]
}
]
}
}
The matcher filters by configuration type:
user_settings
,
project_settings
,
local_settings
,
policy_settings
, or
skills
. To block a change from taking effect, exit with code 2 or return
{"decision": "block"}
. See the
ConfigChange reference
for the full input schema.
​
Reload environment when directory or files change
Some projects set different environment variables depending on which directory you are in. Tools like
direnv
do this automatically in your shell, but Claude’s Bash tool does not pick up those changes on its own.
Pairing a
SessionStart
hook with a
CwdChanged
hook fixes this.
SessionStart
loads the variables for the directory you launch in, and
CwdChanged
reloads them each time Claude changes directory. Both write to
CLAUDE_ENV_FILE
, which Claude Code runs as a script preamble before each Bash command. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
],
"CwdChanged"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
]
}
}
Run
direnv allow
once in each directory that has an
.envrc
so direnv is permitted to load it. If you use devbox or nix instead of direnv, the same pattern works with
devbox shellenv
or
devbox global shellenv
in place of
direnv export bash
.
To react to specific files instead of every directory change, use
FileChanged
with a
matcher
listing the filenames to watch, separated by
|
. To build the watch list, this value is split into literal filenames rather than evaluated as a regex. See
FileChanged
for how the same value also filters which hook groups run when a file changes. This example watches
.envrc
and
.env
in the working directory:
{
"hooks"
: {
"FileChanged"
: [
{
"matcher"
:
".envrc|.env"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
]
}
}
See the
CwdChanged
and
FileChanged
reference entries for input schemas,
watchPaths
output, and
CLAUDE_ENV_FILE
details.
​
Auto-approve specific permission prompts
Skip the approval dialog for tool calls you always allow. This example auto-approves
ExitPlanMode
, the tool Claude calls when it finishes presenting a plan and asks to proceed, so you aren’t prompted every time a plan is ready.
Unlike the exit-code examples above, auto-approval requires your hook to write a JSON decision to stdout. A
PermissionRequest
hook fires when Claude Code is about to show a permission dialog, and returning
"behavior": "allow"
answers it on your behalf.
The matcher scopes the hook to
ExitPlanMode
only, so no other prompts are affected. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"PermissionRequest"
: [
{
"matcher"
:
"ExitPlanMode"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo '{
\"
hookSpecificOutput
\"
: {
\"
hookEventName
\"
:
\"
PermissionRequest
\"
,
\"
decision
\"
: {
\"
behavior
\"
:
\"
allow
\"
}}}'"
}
]
}
]
}
}
When the hook approves, Claude Code exits plan mode and restores whatever permission mode was active before you entered plan mode. The transcript shows “Allowed by PermissionRequest hook” where the dialog would have appeared. The hook path always keeps the current conversation: it cannot clear context and start a fresh implementation session the way the dialog can.
To set a specific permission mode instead, your hook’s output can include an
updatedPermissions
array with a
setMode
entry. The
mode
value is any permission mode like
default
,
acceptEdits
, or
bypassPermissions
, and
destination: "session"
applies it for the current session only.
bypassPermissions
only applies if the session was launched with bypass mode already available:
--dangerously-skip-permissions
,
--permission-mode bypassPermissions
,
--allow-dangerously-skip-permissions
, or
permissions.defaultMode: "bypassPermissions"
in settings, and not disabled by
permissions.disableBypassPermissionsMode
. It is never persisted as
defaultMode
.
To switch the session to
acceptEdits
, your hook writes this JSON to stdout:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedPermissions"
: [
{
"type"
:
"setMode"
,
"mode"
:
"acceptEdits"
,
"destination"
:
"session"
}
]
}
}
}
Keep the matcher as narrow as possible. Matching on
.*
or leaving the matcher empty would auto-approve every permission prompt, including file writes and shell commands. See the
PermissionRequest reference
for the full set of decision fields.
​
How hooks work
Hook events fire at specific lifecycle points in Claude Code. When an event fires, all matching hooks run in parallel, and identical hook commands are automatically deduplicated. The table below shows each event and when it triggers:
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
Each hook has a
type
that determines how it runs. Most hooks use
"type": "command"
, which runs a shell command. Four other types are available:
"type": "http"
: POST event data to a URL. See
HTTP hooks
.
"type": "mcp_tool"
: call a tool on an already-connected MCP server. See
MCP tool hooks
.
"type": "prompt"
: single-turn LLM evaluation. See
Prompt-based hooks
.
"type": "agent"
: multi-turn verification with tool access. Agent hooks are experimental and may change. See
Agent-based hooks
.
​
Combine results from multiple hooks
When multiple hooks match the same event, every hook’s command runs to completion before Claude Code merges the results. One hook returning
deny
does not stop sibling hooks from executing. Don’t rely on one hook’s
deny
to suppress side effects in another hook.
After all matching hooks finish, Claude Code combines their outputs. For
PreToolUse
permission decisions, the most restrictive answer wins:
deny
overrides
ask
, which overrides
allow
. Text from
additionalContext
is kept from every hook and passed to Claude together.
The example below registers two
PreToolUse
hooks on
Bash
. The first appends every command to a log file and exits 0. The second runs a script that exits 2 to deny when the command contains
rm -rf
:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r .tool_input.command >> ~/.claude/bash.log"
},
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/block-rm-rf.sh"
}
]
}
]
}
}
When Claude tries to run
rm -rf /tmp/build
, both hooks execute in parallel. The logging hook writes the command to
~/.claude/bash.log
and exits 0, which reports no decision. The guardrail hook exits 2, which denies the tool call. The deny wins, so Claude Code blocks the command and shows Claude the guardrail’s stderr. The log entry is still written because the logging hook already ran.
​
Read input and return output
Hooks communicate with Claude Code through stdin, stdout, stderr, and exit codes. When an event fires, Claude Code passes event-specific data as JSON to your script’s stdin. Your script reads that data, does its work, and tells Claude Code what to do next via the exit code.
​
Hook input
Every event includes common fields like
session_id
and
cwd
, but each event type adds different data. For example, when Claude runs a Bash command, a
PreToolUse
hook receives something like this on stdin:
{
"session_id"
:
"abc123"
,
// unique ID for this session
"cwd"
:
"/Users/sarah/myproject"
,
// working directory when the event fired
"hook_event_name"
:
"PreToolUse"
,
// which event triggered this hook
"tool_name"
:
"Bash"
,
// the tool Claude is about to use
"tool_input"
: {
// the arguments Claude passed to the tool
"command"
:
"npm test"
// for Bash, this is the shell command
}
}
Your script can parse that JSON and act on any of those fields.
UserPromptSubmit
hooks get the
prompt
text instead,
SessionStart
hooks get the
source
(startup, resume, clear, compact), and so on. See
Common input fields
in the reference for shared fields, and each event’s section for event-specific schemas.
​
Hook output
Your script tells Claude Code what to do next by writing to stdout or stderr and exiting with a specific code. For example, a
PreToolUse
hook that wants to block a command:
#!/bin/bash
INPUT
=
$(
cat
)
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command'
)
if
echo
"
$COMMAND
"
|
grep
-q
"drop table"
;
then
echo
"Blocked: dropping tables is not allowed"
>&2
# stderr becomes Claude's feedback
exit
2
# exit 2 = block the action
fi
exit
0
# exit 0 = let it proceed
The exit code determines what happens next:
Exit 0
: the action proceeds. For
UserPromptSubmit
,
UserPromptExpansion
, and
SessionStart
hooks, anything you write to stdout is added to Claude’s context.
Exit 2
: the action is blocked. Write a reason to stderr, and Claude receives it as feedback so it can adjust. Some events cannot be blocked: for
SessionStart
,
Setup
,
Notification
, and others, exit 2 shows stderr to the user and execution continues. See
exit code 2 behavior per event
for the full list.
Any other exit code
: the action proceeds. The transcript shows a
<hook name> hook error
notice followed by the first line of stderr; the full stderr goes to the
debug log
.
​
Structured JSON output
Exit codes give you two options: allow or block. For more control, exit 0 and print a JSON object to stdout instead.
Use exit 2 to block with a stderr message, or exit 0 with JSON for structured control. Don’t mix them: Claude Code ignores JSON when you exit 2.
For example, a
PreToolUse
hook can deny a tool call and tell Claude why, or escalate it to the user for approval:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Use rg instead of grep for better performance"
}
}
With
"deny"
, Claude Code cancels the tool call and feeds
permissionDecisionReason
back to Claude. These
permissionDecision
values are specific to
PreToolUse
:
"allow"
: skip the interactive permission prompt. Deny and ask rules, including enterprise managed deny lists, still apply
"deny"
: cancel the tool call and send the reason to Claude
"ask"
: show the permission prompt to the user as normal
A fourth value,
"defer"
, is available in
non-interactive mode
with the
-p
flag. It exits the process with the tool call preserved so an Agent SDK wrapper can collect input and resume. See
Defer a tool call for later
in the reference.
Returning
"allow"
skips the interactive prompt but does not override
permission rules
. If a deny rule matches the tool call, the call is blocked even when your hook returns
"allow"
. If an ask rule matches, the user is still prompted. This means deny rules from any settings scope, including
managed settings
, always take precedence over hook approvals.
Other events use different decision patterns. For example,
PostToolUse
and
Stop
hooks use a top-level
decision: "block"
field, while
PermissionRequest
uses
hookSpecificOutput.decision.behavior
. See the
summary table
in the reference for a full breakdown by event.
For
UserPromptSubmit
hooks, use
additionalContext
instead to inject text into Claude’s context. Prompt-based hooks (
type: "prompt"
) handle output differently: see
Prompt-based hooks
.
​
Filter hooks with matchers
Without a matcher, a hook fires on every occurrence of its event. Matchers let you narrow that down. For example, if you want to run a formatter only after file edits (not after every tool call), add a matcher to your
PostToolUse
hook:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"prettier --write ..."
}
]
}
]
}
}
The
"Edit|Write"
matcher fires only when Claude uses the
Edit
or
Write
tool, not when it uses
Bash
,
Read
, or any other tool. See
Matcher patterns
for how plain names and regular expressions are evaluated.
Claude can also create or modify files by running shell commands through the
Bash
tool. If your hook must see every file change, such as for compliance scanning or audit logging, add a
Stop
hook that scans the working tree once per turn. For per-call coverage instead, also match
Bash
and have your script list modified and untracked files with
git status --porcelain
.
Each event type matches on a specific field:
Event
What the matcher filters
Example matcher values
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
tool name
Bash
,
Edit|Write
,
mcp__.*
SessionStart
how the session started
startup
,
resume
,
clear
,
compact
Setup
which CLI flag triggered setup
init
,
maintenance
SessionEnd
why the session ended
clear
,
resume
,
logout
,
prompt_input_exit
,
bypass_permissions_disabled
,
other
Notification
notification type
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
SubagentStart
agent type
general-purpose
,
Explore
,
Plan
, or custom agent names
PreCompact
,
PostCompact
what triggered compaction
manual
,
auto
SubagentStop
agent type
same values as
SubagentStart
ConfigChange
configuration source
user_settings
,
project_settings
,
local_settings
,
policy_settings
,
skills
StopFailure
error type
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
,
unknown
InstructionsLoaded
load reason
session_start
,
nested_traversal
,
path_glob_match
,
include
,
compact
Elicitation
MCP server name
your configured MCP server names
ElicitationResult
MCP server name
same values as
Elicitation
FileChanged
literal filenames to watch (see
FileChanged
)
.envrc|.env
UserPromptExpansion
command name
your skill or command names
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
,
CwdChanged
no matcher support
always fires on every occurrence
A few more examples showing matchers on different event types:
Log every Bash command
Match MCP tools
Clean up on session end
Match only
Bash
tool calls and log each command to a file. The
PostToolUse
event fires after the command completes, so
tool_input.command
contains what ran. The hook receives the event data as JSON on stdin, and
jq -r '.tool_input.command'
extracts just the command string, which
>>
appends to the log file:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}
]
}
]
}
}
MCP tools use a different naming convention than built-in tools:
mcp__<server>__<tool>
, where
<server>
is the MCP server name and
<tool>
is the tool it provides. For example,
mcp__github__search_repositories
or
mcp__filesystem__read_file
. Use a regex matcher to target all tools from a specific server, or match across servers with a pattern like
mcp__.*__write.*
. See
Match MCP tools
in the reference for the full list of examples.
The command below extracts the tool name from the hook’s JSON input with
jq
and writes it to stderr. Writing to stderr keeps stdout clean for JSON output and sends the message to the
debug log
:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"mcp__github__.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo
\"
GitHub tool called: $(jq -r '.tool_name')
\"
>&2"
}
]
}
]
}
}
The
SessionEnd
event supports matchers on the reason the session ended. This hook only fires on
clear
(when you run
/clear
), not on normal exits:
{
"hooks"
: {
"SessionEnd"
: [
{
"matcher"
:
"clear"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"rm -f /tmp/claude-scratch-*.txt"
}
]
}
]
}
}
For full matcher syntax, see the
Hooks reference
.
​
Filter by tool name and arguments with the
if
field
The
if
field requires Claude Code v2.1.85 or later. Earlier versions ignore it and run the hook on every matched call.
The
if
field uses
permission rule syntax
to filter hooks by tool name and arguments together, so the hook process only spawns when the tool call matches, or when a Bash command is too complex to parse. This goes beyond
matcher
, which filters at the group level by tool name only.
For example, to run a hook only when Claude uses
git
commands rather than all Bash commands:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"if"
:
"Bash(git *)"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/check-git-policy.sh"
}
]
}
]
}
}
The hook process only spawns when a subcommand of the Bash command matches
git *
, or when the command is too complex to parse into subcommands. For compound commands like
npm test && git push
, Claude Code evaluates each subcommand and fires the hook because
git push
matches. The
if
field accepts the same patterns as permission rules:
"Bash(git *)"
,
"Edit(*.ts)"
, and so on. To match multiple tool names, use separate handlers each with its own
if
value, or match at the
matcher
level where pipe alternation is supported.
if
only works on tool events:
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
, and
PermissionDenied
. Adding it to any other event prevents the hook from running.
​
Configure hook location
Where you add a hook determines its scope:
Location
Scope
Shareable
~/.claude/settings.json
All your projects
No, local to your machine
.claude/settings.json
Single project
Yes, can be committed to the repo
.claude/settings.local.json
Single project
No, gitignored
Managed policy settings
Organization-wide
Yes, admin-controlled
Plugin
hooks/hooks.json
When plugin is enabled
Yes, bundled with the plugin
Skill
or
agent
frontmatter
While the skill or agent is active
Yes, defined in the component file
Run
/hooks
in Claude Code to browse all configured hooks grouped by event. To disable hooks, set
"disableAllHooks": true
in your settings file. Hooks configured in managed settings still run unless
disableAllHooks
is also set there.
If you edit settings files directly while Claude Code is running, the file watcher normally picks up hook changes automatically.
​
Prompt-based hooks
For decisions that require judgment rather than deterministic rules, use
type: "prompt"
hooks. Instead of running a shell command, Claude Code sends your prompt and the hook’s input data to a Claude model (Haiku by default) to make the decision. You can specify a different model with the
model
field if you need more capability.
The model’s only job is to return a yes/no decision as JSON:
"ok": true
: the action proceeds
"ok": false
: what happens depends on the event:
Stop
and
SubagentStop
: the
reason
is fed back to Claude so it keeps working
PreToolUse
: the tool call is denied and the
reason
is returned to Claude as the tool error, so it can adjust and continue
PostToolUse
,
PostToolBatch
,
UserPromptSubmit
, and
UserPromptExpansion
: the turn ends and the
reason
appears in the chat as a warning line
This example uses a
Stop
hook to ask the model whether all requested tasks are complete. If the model returns
"ok": false
, Claude keeps working and uses the
reason
as its next instruction:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"Check if all tasks are complete. If not, respond with {
\"
ok
\"
: false,
\"
reason
\"
:
\"
what remains to be done
\"
}."
}
]
}
]
}
}
For full configuration options, see
Prompt-based hooks
in the reference.
​
Agent-based hooks
Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer
command hooks
.
When verification requires inspecting files or running commands, use
type: "agent"
hooks. Unlike prompt hooks which make a single LLM call, agent hooks spawn a subagent that can read files, search code, and use other tools to verify conditions before returning a decision.
Agent hooks use the same
"ok"
/
"reason"
response format as prompt hooks, but with a longer default timeout of 60 seconds and up to 50 tool-use turns.
This example verifies that tests pass before allowing Claude to stop:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"agent"
,
"prompt"
:
"Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS"
,
"timeout"
:
120
}
]
}
]
}
}
Use prompt hooks when the hook input data alone is enough to make a decision. Use agent hooks when you need to verify something against the actual state of the codebase.
For full configuration options, see
Agent-based hooks
in the reference.
​
HTTP hooks
Use
type: "http"
hooks to POST event data to an HTTP endpoint instead of running a shell command. The endpoint receives the same JSON that a command hook would receive on stdin, and returns results through the HTTP response body using the same JSON format.
HTTP hooks are useful when you want a web server, cloud function, or external service to handle hook logic: for example, a shared audit service that logs tool use events across a team.
This example posts every tool use to a local logging service:
{
"hooks"
: {
"PostToolUse"
: [
{
"hooks"
: [
{
"type"
:
"http"
,
"url"
:
"http://localhost:8080/hooks/tool-use"
,
"headers"
: {
"Authorization"
:
"Bearer $MY_TOKEN"
},
"allowedEnvVars"
: [
"MY_TOKEN"
]
}
]
}
]
}
}
The endpoint should return a JSON response body using the same
output format
as command hooks. To block a tool call, return a 2xx response with the appropriate
hookSpecificOutput
fields. HTTP status codes alone cannot block actions.
Header values support environment variable interpolation using
$VAR_NAME
or
${VAR_NAME}
syntax. Only variables listed in the
allowedEnvVars
array are resolved; all other
$VAR
references remain empty.
For full configuration options and response handling, see
HTTP hooks
in the reference.
​
Limitations and troubleshooting
​
Limitations
Command hooks communicate through stdout, stderr, and exit codes only. They cannot trigger
/
commands or tool calls. Text returned via
additionalContext
is injected as a system reminder that Claude reads as plain text. HTTP hooks communicate through the response body instead.
Hook timeouts vary by type. Override per hook with the
timeout
field in seconds.
command
,
http
,
mcp_tool
: 10 minutes.
UserPromptSubmit
lowers these to 30 seconds.
prompt
: 30 seconds.
agent
: 60 seconds.
PostToolUse
hooks cannot undo actions since the tool has already executed.
PermissionRequest
hooks do not fire in
non-interactive mode
(
-p
). Use
PreToolUse
hooks for automated permission decisions.
Stop
hooks fire whenever Claude finishes responding, not only at task completion. They do not fire on user interrupts. API errors fire
StopFailure
instead.
When multiple PreToolUse hooks return
updatedInput
to rewrite a tool’s arguments, the last one to finish wins. Since hooks run in parallel, the order is non-deterministic. Avoid having more than one hook modify the same tool’s input.
​
Hooks and permission modes
PreToolUse hooks fire before any permission-mode check. A hook that returns
permissionDecision: "deny"
blocks the tool even in
bypassPermissions
mode or with
--dangerously-skip-permissions
. This lets you enforce policy that users cannot bypass by changing their permission mode.
The reverse is not true: a hook returning
"allow"
does not bypass deny rules from settings. Hooks can tighten restrictions but not loosen them past what permission rules allow.
​
Hook not firing
The hook is configured but never executes.
Run
/hooks
and confirm the hook appears under the correct event
Check that the matcher pattern matches the tool name exactly (matchers are case-sensitive)
Verify you’re triggering the right event type (e.g.,
PreToolUse
fires before tool execution,
PostToolUse
fires after)
If using
PermissionRequest
hooks in non-interactive mode (
-p
), switch to
PreToolUse
instead
​
Hook error in output
You see a message like “PreToolUse hook error: …” in the transcript.
Your script exited with a non-zero code unexpectedly. Test it manually by piping sample JSON:
echo
'{"tool_name":"Bash","tool_input":{"command":"ls"}}'
|
./my-hook.sh
echo
$?
# Check the exit code
If you see “command not found”, use absolute paths or
${CLAUDE_PROJECT_DIR}
to reference scripts. To avoid shell quoting entirely, add
"args": []
to switch to
exec form
, which spawns the script directly without a shell
If you see “jq: command not found”, install
jq
or use Python/Node.js for JSON parsing
If the script isn’t running at all, make it executable:
chmod +x ./my-hook.sh
​
/hooks
shows no hooks configured
You edited a settings file but the hooks don’t appear in the menu.
File edits are normally picked up automatically. If they haven’t appeared after a few seconds, the file watcher may have missed the change: restart your session to force a reload.
Verify your JSON is valid (trailing commas and comments are not allowed)
Confirm the settings file is in the correct location:
.claude/settings.json
for project hooks,
~/.claude/settings.json
for global hooks
​
Stop hook runs forever
Claude keeps working in an infinite loop instead of stopping.
Your Stop hook script needs to check whether it already triggered a continuation. Parse the
stop_hook_active
field from the JSON input and exit early if it’s
true
:
#!/bin/bash
INPUT
=
$(
cat
)
if
[
"$(
echo
"
$INPUT
"
|
jq
-r
'.stop_hook_active')"
=
"true"
];
then
exit
0
# Allow Claude to stop
fi
# ... rest of your hook logic
​
JSON validation failed
Claude Code shows a JSON parsing error even though your hook script outputs valid JSON.
When Claude Code runs a shell-form command hook (one without
args
), it spawns
sh -c
on macOS and Linux or Git Bash on Windows by default. This shell is non-interactive, but Git Bash and some configurations (such as
BASH_ENV
pointing at
~/.bashrc
) still source your profile. If that profile contains unconditional
echo
statements, the output gets prepended to your hook’s JSON:
Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}
Claude Code tries to parse this as JSON and fails. To fix this, wrap echo statements in your shell profile so they only run in interactive shells:
# In ~/.zshrc or ~/.bashrc
if
[[
$-
==
*
i
*
]];
then
echo
"Shell ready"
fi
The
$-
variable contains shell flags, and
i
means interactive. Hooks run in non-interactive shells, so the echo is skipped.
​
Debug techniques
The transcript view, toggled with
Ctrl+O
, shows a one-line summary for each hook that fired: success is silent, blocking errors show stderr, and non-blocking errors show a
<hook name> hook error
notice followed by the first line of stderr.
For full execution details including which hooks matched, their exit codes, stdout, and stderr, read the debug log. Start Claude Code with
claude --debug-file /tmp/claude.log
to write to a known path, then
tail -f /tmp/claude.log
in another terminal. If you started without that flag, run
/debug
mid-session to enable logging and find the log path.
​
Learn more
Hooks reference
: full event schemas, JSON output format, async hooks, and MCP tool hooks
Security considerations
: review before deploying hooks in shared or production environments
Bash command validator example
: complete reference implementation
Was this page helpful?
Yes
No
Extend Claude with skills
Push external events to Claude
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/hooks-guide" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Automate workflows with hooks
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from li...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Automate workflows with hooks
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Hooks are user-defined shell commands that execute at specific points in Claude Code’s lifecycle. They provide deterministic control over Claude Code’s behavior, ensuring certain actions always happen rather than relying on the LLM to choose to run them. Use hooks to enforce project rules, automate repetitive tasks, and integrate Claude Code with your existing tools.
For decisions that require judgment rather than deterministic rules, you can also use
prompt-based hooks
or
agent-based hooks
that use a Claude model to evaluate conditions.
For other ways to extend Claude Code, see
skills
for giving Claude additional instructions and executable commands,
subagents
for running tasks in isolated contexts, and
plugins
for packaging extensions to share across projects.
This guide covers common use cases and how to get started. For full event schemas, JSON input/output formats, and advanced features like async hooks and MCP tool hooks, see the
Hooks reference
.
​
Set up your first hook
To create a hook, add a
hooks
block to a
settings file
. This walkthrough creates a desktop notification hook, so you get alerted whenever Claude is waiting for your input instead of watching the terminal.
1
Add the hook to your settings
Open
~/.claude/settings.json
and add a
Notification
hook. The example below uses
osascript
for macOS; see
Get notified when Claude needs input
for Linux and Windows commands.
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}
]
}
]
}
}
If your settings file already has a
hooks
key, add
Notification
as a sibling of the existing event keys rather than replacing the whole object. Each event name is a key inside the single
hooks
object:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npx prettier --write"
}]
}
],
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}]
}
]
}
}
You can also ask Claude to write the hook for you by describing what you want in the CLI.
2
Verify the configuration
Type
/hooks
to open the hooks browser. You’ll see a list of all available hook events, with a count next to each event that has hooks configured. Select
Notification
to confirm your new hook appears in the list. Selecting the hook shows its details: the event, matcher, type, source file, and command.
3
Test the hook
Press
Esc
to return to the CLI. Ask Claude to do something that requires permission, then switch away from the terminal. You should receive a desktop notification.
The
/hooks
menu is read-only. To add, modify, or remove hooks, edit your settings JSON directly or ask Claude to make the change.
​
What you can automate
Hooks let you run code at key points in Claude Code’s lifecycle: format files after edits, block commands before they execute, send notifications when Claude needs input, inject context at session start, and more. For the full list of hook events, see the
Hooks reference
.
Each example includes a ready-to-use configuration block that you add to a
settings file
. The most common patterns:
Get notified when Claude needs input
Auto-format code after edits
Block edits to protected files
Re-inject context after compaction
Audit configuration changes
Reload environment when directory or files change
Auto-approve specific permission prompts
​
Get notified when Claude needs input
Get a desktop notification whenever Claude finishes working and needs your input, so you can switch to other tasks without checking the terminal.
This hook uses the
Notification
event, which fires when Claude is waiting for input or permission. Each tab below uses the platform’s native notification command. Add this to
~/.claude/settings.json
:
macOS
Linux
Windows (PowerShell)
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"osascript -e 'display notification
\"
Claude Code needs your attention
\"
with title
\"
Claude Code
\"
'"
}
]
}
]
}
}
If no notification appears
osascript
routes notifications through the built-in Script Editor app. If Script Editor doesn’t have notification permission, the command fails silently, and macOS won’t prompt you to grant it. Run this in Terminal once to make Script Editor appear in your notification settings:
osascript
-e
'display notification "test"'
Nothing will appear yet. Open
System Settings > Notifications
, find
Script Editor
in the list, and turn on
Allow Notifications
. Run the command again to confirm the test notification appears.
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"powershell.exe -Command
\"
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')
\"
"
}
]
}
]
}
}
The empty
matcher
fires on all notification types. To fire only on specific events, set it to one of these values:
Matcher
Fires when
permission_prompt
Claude needs you to approve a tool use
idle_prompt
Claude is done and waiting for your next prompt
auth_success
Authentication completes
elicitation_dialog
An MCP server opens an elicitation form
elicitation_complete
An MCP elicitation form is submitted or dismissed
elicitation_response
An MCP elicitation response is sent back to the server
Type
/hooks
and select
Notification
to confirm the hook is registered. For the full event schema, see the
Notification reference
.
​
Auto-format code after edits
Automatically run
Prettier
on every file Claude edits, so formatting stays consistent without manual intervention.
This hook uses the
PostToolUse
event with an
Edit|Write
matcher, so it runs only after file-editing tools. The command extracts the edited file path with
jq
and passes it to Prettier. Add this to
.claude/settings.json
in your project root:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
The Bash examples on this page use
jq
for JSON parsing. Install it with
brew install jq
(macOS),
apt-get install jq
(Debian/Ubuntu), or see
jq
downloads
.
​
Block edits to protected files
Prevent Claude from modifying sensitive files like
.env
,
package-lock.json
, or anything in
.git/
. Claude receives feedback explaining why the edit was blocked, so it can adjust its approach.
This example uses a separate script file that the hook calls. The script checks the target file path against a list of protected patterns and exits with code 2 to block the edit.
1
Create the hook script
Save this to
.claude/hooks/protect-files.sh
:
#!/bin/bash
# protect-files.sh
INPUT
=
$(
cat
)
FILE_PATH
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.file_path // empty'
)
PROTECTED_PATTERNS
=
(
".env"
"package-lock.json"
".git/"
)
for
pattern
in
"${
PROTECTED_PATTERNS
[
@
]}"
;
do
if
[[
"
$FILE_PATH
"
==
*
"
$pattern
"
*
]];
then
echo
"Blocked:
$FILE_PATH
matches protected pattern '
$pattern
'"
>&2
exit
2
fi
done
exit
0
2
Make the script executable (macOS/Linux)
Hook scripts must be executable for Claude Code to run them:
chmod
+x
.claude/hooks/protect-files.sh
3
Register the hook
Add a
PreToolUse
hook to
.claude/settings.json
that runs the script before any
Edit
or
Write
tool call:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
​
Re-inject context after compaction
When Claude’s context window fills up, compaction summarizes the conversation to free space. This can lose important details. Use a
SessionStart
hook with a
compact
matcher to re-inject critical context after every compaction.
Any text your command writes to stdout is added to Claude’s context. This example reminds Claude of project conventions and recent work. Add this to
.claude/settings.json
in your project root:
{
"hooks"
: {
"SessionStart"
: [
{
"matcher"
:
"compact"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
}
]
}
]
}
}
You can replace the
echo
with any command that produces dynamic output, like
git log --oneline -5
to show recent commits. For injecting context on every session start, consider using
CLAUDE.md
instead. For environment variables, see
CLAUDE_ENV_FILE
in the reference.
​
Audit configuration changes
Track when settings or skills files change during a session. The
ConfigChange
event fires when an external process or editor modifies a configuration file, so you can log changes for compliance or block unauthorized modifications.
This example appends each change to an audit log. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"ConfigChange"
: [
{
"matcher"
:
""
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
}
]
}
]
}
}
The matcher filters by configuration type:
user_settings
,
project_settings
,
local_settings
,
policy_settings
, or
skills
. To block a change from taking effect, exit with code 2 or return
{"decision": "block"}
. See the
ConfigChange reference
for the full input schema.
​
Reload environment when directory or files change
Some projects set different environment variables depending on which directory you are in. Tools like
direnv
do this automatically in your shell, but Claude’s Bash tool does not pick up those changes on its own.
Pairing a
SessionStart
hook with a
CwdChanged
hook fixes this.
SessionStart
loads the variables for the directory you launch in, and
CwdChanged
reloads them each time Claude changes directory. Both write to
CLAUDE_ENV_FILE
, which Claude Code runs as a script preamble before each Bash command. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
],
"CwdChanged"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
]
}
}
Run
direnv allow
once in each directory that has an
.envrc
so direnv is permitted to load it. If you use devbox or nix instead of direnv, the same pattern works with
devbox shellenv
or
devbox global shellenv
in place of
direnv export bash
.
To react to specific files instead of every directory change, use
FileChanged
with a
matcher
listing the filenames to watch, separated by
|
. To build the watch list, this value is split into literal filenames rather than evaluated as a regex. See
FileChanged
for how the same value also filters which hook groups run when a file changes. This example watches
.envrc
and
.env
in the working directory:
{
"hooks"
: {
"FileChanged"
: [
{
"matcher"
:
".envrc|.env"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"direnv export bash >
\"
$CLAUDE_ENV_FILE
\"
"
}
]
}
]
}
}
See the
CwdChanged
and
FileChanged
reference entries for input schemas,
watchPaths
output, and
CLAUDE_ENV_FILE
details.
​
Auto-approve specific permission prompts
Skip the approval dialog for tool calls you always allow. This example auto-approves
ExitPlanMode
, the tool Claude calls when it finishes presenting a plan and asks to proceed, so you aren’t prompted every time a plan is ready.
Unlike the exit-code examples above, auto-approval requires your hook to write a JSON decision to stdout. A
PermissionRequest
hook fires when Claude Code is about to show a permission dialog, and returning
"behavior": "allow"
answers it on your behalf.
The matcher scopes the hook to
ExitPlanMode
only, so no other prompts are affected. Add this to
~/.claude/settings.json
:
{
"hooks"
: {
"PermissionRequest"
: [
{
"matcher"
:
"ExitPlanMode"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo '{
\"
hookSpecificOutput
\"
: {
\"
hookEventName
\"
:
\"
PermissionRequest
\"
,
\"
decision
\"
: {
\"
behavior
\"
:
\"
allow
\"
}}}'"
}
]
}
]
}
}
When the hook approves, Claude Code exits plan mode and restores whatever permission mode was active before you entered plan mode. The transcript shows “Allowed by PermissionRequest hook” where the dialog would have appeared. The hook path always keeps the current conversation: it cannot clear context and start a fresh implementation session the way the dialog can.
To set a specific permission mode instead, your hook’s output can include an
updatedPermissions
array with a
setMode
entry. The
mode
value is any permission mode like
default
,
acceptEdits
, or
bypassPermissions
, and
destination: "session"
applies it for the current session only.
bypassPermissions
only applies if the session was launched with bypass mode already available:
--dangerously-skip-permissions
,
--permission-mode bypassPermissions
,
--allow-dangerously-skip-permissions
, or
permissions.defaultMode: "bypassPermissions"
in settings, and not disabled by
permissions.disableBypassPermissionsMode
. It is never persisted as
defaultMode
.
To switch the session to
acceptEdits
, your hook writes this JSON to stdout:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedPermissions"
: [
{
"type"
:
"setMode"
,
"mode"
:
"acceptEdits"
,
"destination"
:
"session"
}
]
}
}
}
Keep the matcher as narrow as possible. Matching on
.*
or leaving the matcher empty would auto-approve every permission prompt, including file writes and shell commands. See the
PermissionRequest reference
for the full set of decision fields.
​
How hooks work
Hook events fire at specific lifecycle points in Claude Code. When an event fires, all matching hooks run in parallel, and identical hook commands are automatically deduplicated. The table below shows each event and when it triggers:
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
Each hook has a
type
that determines how it runs. Most hooks use
"type": "command"
, which runs a shell command. Four other types are available:
"type": "http"
: POST event data to a URL. See
HTTP hooks
.
"type": "mcp_tool"
: call a tool on an already-connected MCP server. See
MCP tool hooks
.
"type": "prompt"
: single-turn LLM evaluation. See
Prompt-based hooks
.
"type": "agent"
: multi-turn verification with tool access. Agent hooks are experimental and may change. See
Agent-based hooks
.
​
Combine results from multiple hooks
When multiple hooks match the same event, every hook’s command runs to completion before Claude Code merges the results. One hook returning
deny
does not stop sibling hooks from executing. Don’t rely on one hook’s
deny
to suppress side effects in another hook.
After all matching hooks finish, Claude Code combines their outputs. For
PreToolUse
permission decisions, the most restrictive answer wins:
deny
overrides
ask
, which overrides
allow
. Text from
additionalContext
is kept from every hook and passed to Claude together.
The example below registers two
PreToolUse
hooks on
Bash
. The first appends every command to a log file and exits 0. The second runs a script that exits 2 to deny when the command contains
rm -rf
:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r .tool_input.command >> ~/.claude/bash.log"
},
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/block-rm-rf.sh"
}
]
}
]
}
}
When Claude tries to run
rm -rf /tmp/build
, both hooks execute in parallel. The logging hook writes the command to
~/.claude/bash.log
and exits 0, which reports no decision. The guardrail hook exits 2, which denies the tool call. The deny wins, so Claude Code blocks the command and shows Claude the guardrail’s stderr. The log entry is still written because the logging hook already ran.
​
Read input and return output
Hooks communicate with Claude Code through stdin, stdout, stderr, and exit codes. When an event fires, Claude Code passes event-specific data as JSON to your script’s stdin. Your script reads that data, does its work, and tells Claude Code what to do next via the exit code.
​
Hook input
Every event includes common fields like
session_id
and
cwd
, but each event type adds different data. For example, when Claude runs a Bash command, a
PreToolUse
hook receives something like this on stdin:
{
"session_id"
:
"abc123"
,
// unique ID for this session
"cwd"
:
"/Users/sarah/myproject"
,
// working directory when the event fired
"hook_event_name"
:
"PreToolUse"
,
// which event triggered this hook
"tool_name"
:
"Bash"
,
// the tool Claude is about to use
"tool_input"
: {
// the arguments Claude passed to the tool
"command"
:
"npm test"
// for Bash, this is the shell command
}
}
Your script can parse that JSON and act on any of those fields.
UserPromptSubmit
hooks get the
prompt
text instead,
SessionStart
hooks get the
source
(startup, resume, clear, compact), and so on. See
Common input fields
in the reference for shared fields, and each event’s section for event-specific schemas.
​
Hook output
Your script tells Claude Code what to do next by writing to stdout or stderr and exiting with a specific code. For example, a
PreToolUse
hook that wants to block a command:
#!/bin/bash
INPUT
=
$(
cat
)
COMMAND
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.command'
)
if
echo
"
$COMMAND
"
|
grep
-q
"drop table"
;
then
echo
"Blocked: dropping tables is not allowed"
>&2
# stderr becomes Claude's feedback
exit
2
# exit 2 = block the action
fi
exit
0
# exit 0 = let it proceed
The exit code determines what happens next:
Exit 0
: the action proceeds. For
UserPromptSubmit
,
UserPromptExpansion
, and
SessionStart
hooks, anything you write to stdout is added to Claude’s context.
Exit 2
: the action is blocked. Write a reason to stderr, and Claude receives it as feedback so it can adjust. Some events cannot be blocked: for
SessionStart
,
Setup
,
Notification
, and others, exit 2 shows stderr to the user and execution continues. See
exit code 2 behavior per event
for the full list.
Any other exit code
: the action proceeds. The transcript shows a
<hook name> hook error
notice followed by the first line of stderr; the full stderr goes to the
debug log
.
​
Structured JSON output
Exit codes give you two options: allow or block. For more control, exit 0 and print a JSON object to stdout instead.
Use exit 2 to block with a stderr message, or exit 0 with JSON for structured control. Don’t mix them: Claude Code ignores JSON when you exit 2.
For example, a
PreToolUse
hook can deny a tool call and tell Claude why, or escalate it to the user for approval:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Use rg instead of grep for better performance"
}
}
With
"deny"
, Claude Code cancels the tool call and feeds
permissionDecisionReason
back to Claude. These
permissionDecision
values are specific to
PreToolUse
:
"allow"
: skip the interactive permission prompt. Deny and ask rules, including enterprise managed deny lists, still apply
"deny"
: cancel the tool call and send the reason to Claude
"ask"
: show the permission prompt to the user as normal
A fourth value,
"defer"
, is available in
non-interactive mode
with the
-p
flag. It exits the process with the tool call preserved so an Agent SDK wrapper can collect input and resume. See
Defer a tool call for later
in the reference.
Returning
"allow"
skips the interactive prompt but does not override
permission rules
. If a deny rule matches the tool call, the call is blocked even when your hook returns
"allow"
. If an ask rule matches, the user is still prompted. This means deny rules from any settings scope, including
managed settings
, always take precedence over hook approvals.
Other events use different decision patterns. For example,
PostToolUse
and
Stop
hooks use a top-level
decision: "block"
field, while
PermissionRequest
uses
hookSpecificOutput.decision.behavior
. See the
summary table
in the reference for a full breakdown by event.
For
UserPromptSubmit
hooks, use
additionalContext
instead to inject text into Claude’s context. Prompt-based hooks (
type: "prompt"
) handle output differently: see
Prompt-based hooks
.
​
Filter hooks with matchers
Without a matcher, a hook fires on every occurrence of its event. Matchers let you narrow that down. For example, if you want to run a formatter only after file edits (not after every tool call), add a matcher to your
PostToolUse
hook:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"prettier --write ..."
}
]
}
]
}
}
The
"Edit|Write"
matcher fires only when Claude uses the
Edit
or
Write
tool, not when it uses
Bash
,
Read
, or any other tool. See
Matcher patterns
for how plain names and regular expressions are evaluated.
Claude can also create or modify files by running shell commands through the
Bash
tool. If your hook must see every file change, such as for compliance scanning or audit logging, add a
Stop
hook that scans the working tree once per turn. For per-call coverage instead, also match
Bash
and have your script list modified and untracked files with
git status --porcelain
.
Each event type matches on a specific field:
Event
What the matcher filters
Example matcher values
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
tool name
Bash
,
Edit|Write
,
mcp__.*
SessionStart
how the session started
startup
,
resume
,
clear
,
compact
Setup
which CLI flag triggered setup
init
,
maintenance
SessionEnd
why the session ended
clear
,
resume
,
logout
,
prompt_input_exit
,
bypass_permissions_disabled
,
other
Notification
notification type
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
SubagentStart
agent type
general-purpose
,
Explore
,
Plan
, or custom agent names
PreCompact
,
PostCompact
what triggered compaction
manual
,
auto
SubagentStop
agent type
same values as
SubagentStart
ConfigChange
configuration source
user_settings
,
project_settings
,
local_settings
,
policy_settings
,
skills
StopFailure
error type
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
,
unknown
InstructionsLoaded
load reason
session_start
,
nested_traversal
,
path_glob_match
,
include
,
compact
Elicitation
MCP server name
your configured MCP server names
ElicitationResult
MCP server name
same values as
Elicitation
FileChanged
literal filenames to watch (see
FileChanged
)
.envrc|.env
UserPromptExpansion
command name
your skill or command names
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
,
CwdChanged
no matcher support
always fires on every occurrence
A few more examples showing matchers on different event types:
Log every Bash command
Match MCP tools
Clean up on session end
Match only
Bash
tool calls and log each command to a file. The
PostToolUse
event fires after the command completes, so
tool_input.command
contains what ran. The hook receives the event data as JSON on stdin, and
jq -r '.tool_input.command'
extracts just the command string, which
>>
appends to the log file:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}
]
}
]
}
}
MCP tools use a different naming convention than built-in tools:
mcp__<server>__<tool>
, where
<server>
is the MCP server name and
<tool>
is the tool it provides. For example,
mcp__github__search_repositories
or
mcp__filesystem__read_file
. Use a regex matcher to target all tools from a specific server, or match across servers with a pattern like
mcp__.*__write.*
. See
Match MCP tools
in the reference for the full list of examples.
The command below extracts the tool name from the hook’s JSON input with
jq
and writes it to stderr. Writing to stderr keeps stdout clean for JSON output and sends the message to the
debug log
:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"mcp__github__.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo
\"
GitHub tool called: $(jq -r '.tool_name')
\"
>&2"
}
]
}
]
}
}
The
SessionEnd
event supports matchers on the reason the session ended. This hook only fires on
clear
(when you run
/clear
), not on normal exits:
{
"hooks"
: {
"SessionEnd"
: [
{
"matcher"
:
"clear"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"rm -f /tmp/claude-scratch-*.txt"
}
]
}
]
}
}
For full matcher syntax, see the
Hooks reference
.
​
Filter by tool name and arguments with the
if
field
The
if
field requires Claude Code v2.1.85 or later. Earlier versions ignore it and run the hook on every matched call.
The
if
field uses
permission rule syntax
to filter hooks by tool name and arguments together, so the hook process only spawns when the tool call matches, or when a Bash command is too complex to parse. This goes beyond
matcher
, which filters at the group level by tool name only.
For example, to run a hook only when Claude uses
git
commands rather than all Bash commands:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"if"
:
"Bash(git *)"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/.claude/hooks/check-git-policy.sh"
}
]
}
]
}
}
The hook process only spawns when a subcommand of the Bash command matches
git *
, or when the command is too complex to parse into subcommands. For compound commands like
npm test && git push
, Claude Code evaluates each subcommand and fires the hook because
git push
matches. The
if
field accepts the same patterns as permission rules:
"Bash(git *)"
,
"Edit(*.ts)"
, and so on. To match multiple tool names, use separate handlers each with its own
if
value, or match at the
matcher
level where pipe alternation is supported.
if
only works on tool events:
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
, and
PermissionDenied
. Adding it to any other event prevents the hook from running.
​
Configure hook location
Where you add a hook determines its scope:
Location
Scope
Shareable
~/.claude/settings.json
All your projects
No, local to your machine
.claude/settings.json
Single project
Yes, can be committed to the repo
.claude/settings.local.json
Single project
No, gitignored
Managed policy settings
Organization-wide
Yes, admin-controlled
Plugin
hooks/hooks.json
When plugin is enabled
Yes, bundled with the plugin
Skill
or
agent
frontmatter
While the skill or agent is active
Yes, defined in the component file
Run
/hooks
in Claude Code to browse all configured hooks grouped by event. To disable hooks, set
"disableAllHooks": true
in your settings file. Hooks configured in managed settings still run unless
disableAllHooks
is also set there.
If you edit settings files directly while Claude Code is running, the file watcher normally picks up hook changes automatically.
​
Prompt-based hooks
For decisions that require judgment rather than deterministic rules, use
type: "prompt"
hooks. Instead of running a shell command, Claude Code sends your prompt and the hook’s input data to a Claude model (Haiku by default) to make the decision. You can specify a different model with the
model
field if you need more capability.
The model’s only job is to return a yes/no decision as JSON:
"ok": true
: the action proceeds
"ok": false
: what happens depends on the event:
Stop
and
SubagentStop
: the
reason
is fed back to Claude so it keeps working
PreToolUse
: the tool call is denied and the
reason
is returned to Claude as the tool error, so it can adjust and continue
PostToolUse
,
PostToolBatch
,
UserPromptSubmit
, and
UserPromptExpansion
: the turn ends and the
reason
appears in the chat as a warning line
This example uses a
Stop
hook to ask the model whether all requested tasks are complete. If the model returns
"ok": false
, Claude keeps working and uses the
reason
as its next instruction:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"Check if all tasks are complete. If not, respond with {
\"
ok
\"
: false,
\"
reason
\"
:
\"
what remains to be done
\"
}."
}
]
}
]
}
}
For full configuration options, see
Prompt-based hooks
in the reference.
​
Agent-based hooks
Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer
command hooks
.
When verification requires inspecting files or running commands, use
type: "agent"
hooks. Unlike prompt hooks which make a single LLM call, agent hooks spawn a subagent that can read files, search code, and use other tools to verify conditions before returning a decision.
Agent hooks use the same
"ok"
/
"reason"
response format as prompt hooks, but with a longer default timeout of 60 seconds and up to 50 tool-use turns.
This example verifies that tests pass before allowing Claude to stop:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"agent"
,
"prompt"
:
"Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS"
,
"timeout"
:
120
}
]
}
]
}
}
Use prompt hooks when the hook input data alone is enough to make a decision. Use agent hooks when you need to verify something against the actual state of the codebase.
For full configuration options, see
Agent-based hooks
in the reference.
​
HTTP hooks
Use
type: "http"
hooks to POST event data to an HTTP endpoint instead of running a shell command. The endpoint receives the same JSON that a command hook would receive on stdin, and returns results through the HTTP response body using the same JSON format.
HTTP hooks are useful when you want a web server, cloud function, or external service to handle hook logic: for example, a shared audit service that logs tool use events across a team.
This example posts every tool use to a local logging service:
{
"hooks"
: {
"PostToolUse"
: [
{
"hooks"
: [
{
"type"
:
"http"
,
"url"
:
"http://localhost:8080/hooks/tool-use"
,
"headers"
: {
"Authorization"
:
"Bearer $MY_TOKEN"
},
"allowedEnvVars"
: [
"MY_TOKEN"
]
}
]
}
]
}
}
The endpoint should return a JSON response body using the same
output format
as command hooks. To block a tool call, return a 2xx response with the appropriate
hookSpecificOutput
fields. HTTP status codes alone cannot block actions.
Header values support environment variable interpolation using
$VAR_NAME
or
${VAR_NAME}
syntax. Only variables listed in the
allowedEnvVars
array are resolved; all other
$VAR
references remain empty.
For full configuration options and response handling, see
HTTP hooks
in the reference.
​
Limitations and troubleshooting
​
Limitations
Command hooks communicate through stdout, stderr, and exit codes only. They cannot trigger
/
commands or tool calls. Text returned via
additionalContext
is injected as a system reminder that Claude reads as plain text. HTTP hooks communicate through the response body instead.
Hook timeouts vary by type. Override per hook with the
timeout
field in seconds.
command
,
http
,
mcp_tool
: 10 minutes.
UserPromptSubmit
lowers these to 30 seconds.
prompt
: 30 seconds.
agent
: 60 seconds.
PostToolUse
hooks cannot undo actions since the tool has already executed.
PermissionRequest
hooks do not fire in
non-interactive mode
(
-p
). Use
PreToolUse
hooks for automated permission decisions.
Stop
hooks fire whenever Claude finishes responding, not only at task completion. They do not fire on user interrupts. API errors fire
StopFailure
instead.
When multiple PreToolUse hooks return
updatedInput
to rewrite a tool’s arguments, the last one to finish wins. Since hooks run in parallel, the order is non-deterministic. Avoid having more than one hook modify the same tool’s input.
​
Hooks and permission modes
PreToolUse hooks fire before any permission-mode check. A hook that returns
permissionDecision: "deny"
blocks the tool even in
bypassPermissions
mode or with
--dangerously-skip-permissions
. This lets you enforce policy that users cannot bypass by changing their permission mode.
The reverse is not true: a hook returning
"allow"
does not bypass deny rules from settings. Hooks can tighten restrictions but not loosen them past what permission rules allow.
​
Hook not firing
The hook is configured but never executes.
Run
/hooks
and confirm the hook appears under the correct event
Check that the matcher pattern matches the tool name exactly (matchers are case-sensitive)
Verify you’re triggering the right event type (e.g.,
PreToolUse
fires before tool execution,
PostToolUse
fires after)
If using
PermissionRequest
hooks in non-interactive mode (
-p
), switch to
PreToolUse
instead
​
Hook error in output
You see a message like “PreToolUse hook error: …” in the transcript.
Your script exited with a non-zero code unexpectedly. Test it manually by piping sample JSON:
echo
'{"tool_name":"Bash","tool_input":{"command":"ls"}}'
|
./my-hook.sh
echo
$?
# Check the exit code
If you see “command not found”, use absolute paths or
${CLAUDE_PROJECT_DIR}
to reference scripts. To avoid shell quoting entirely, add
"args": []
to switch to
exec form
, which spawns the script directly without a shell
If you see “jq: command not found”, install
jq
or use Python/Node.js for JSON parsing
If the script isn’t running at all, make it executable:
chmod +x ./my-hook.sh
​
/hooks
shows no hooks configured
You edited a settings file but the hooks don’t appear in the menu.
File edits are normally picked up automatically. If they haven’t appeared after a few seconds, the file watcher may have missed the change: restart your session to force a reload.
Verify your JSON is valid (trailing commas and comments are not allowed)
Confirm the settings file is in the correct location:
.claude/settings.json
for project hooks,
~/.claude/settings.json
for global hooks
​
Stop hook runs forever
Claude keeps working in an infinite loop instead of stopping.
Your Stop hook script needs to check whether it already triggered a continuation. Parse the
stop_hook_active
field from the JSON input and exit early if it’s
true
:
#!/bin/bash
INPUT
=
$(
cat
)
if
[
"$(
echo
"
$INPUT
"
|
jq
-r
'.stop_hook_active')"
=
"true"
];
then
exit
0
# Allow Claude to stop
fi
# ... rest of your hook logic
​
JSON validation failed
Claude Code shows a JSON parsing error even though your hook script outputs valid JSON.
When Claude Code runs a shell-form command hook (one without
args
), it spawns
sh -c
on macOS and Linux or Git Bash on Windows by default. This shell is non-interactive, but Git Bash and some configurations (such as
BASH_ENV
pointing at
~/.bashrc
) still source your profile. If that profile contains unconditional
echo
statements, the output gets prepended to your hook’s JSON:
Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}
Claude Code tries to parse this as JSON and fails. To fix this, wrap echo statements in your shell profile so they only run in interactive shells:
# In ~/.zshrc or ~/.bashrc
if
[[
$-
==
*
i
*
]];
then
echo
"Shell ready"
fi
The
$-
variable contains shell flags, and
i
means interactive. Hooks run in non-interactive shells, so the echo is skipped.
​
Debug techniques
The transcript view, toggled with
Ctrl+O
, shows a one-line summary for each hook that fired: success is silent, blocking errors show stderr, and non-blocking errors show a
<hook name> hook error
notice followed by the first line of stderr.
For full execution details including which hooks matched, their exit codes, stdout, and stderr, read the debug log. Start Claude Code with
claude --debug-file /tmp/claude.log
to write to a known path, then
tail -f /tmp/claude.log
in another terminal. If you started without that flag, run
/debug
mid-session to enable logging and find the log path.
​
Learn more
Hooks reference
: full event schemas, JSON output format, async hooks, and MCP tool hooks
Security considerations
: review before deploying hooks in shared or production environments
Bash command validator example
: complete reference implementation
Was this page helpful?
Yes
No
Extend Claude with skills
Push external events to Claude
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/hooks-guide" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Manage multiple agents with agent view</title>
  <link>https://code.claude.com/docs/en/agent-view</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-view</guid>
  <pubDate>Tue, 11 Jun 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Manage multiple agents with agent view
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Manage multiple agents with agent view
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Agent view, opened with
claude agents
, is one screen for all your background sessions: what’s running, what needs your input, and what’s done. Dispatch new sessions, watch their state at a glance instead of scrolling through transcripts, and step in only when one needs you. Each background session is a full Claude Code conversation that keeps running without a terminal attached, so you can open it, reply, and leave whenever you want.
Use agent view when you have several independent tasks Claude can work on without you watching every step. Dispatch a bug fix, a pull request review, and a flaky-test investigation as three rows, keep working in another window, and check back when a row shows it needs you or has a result.
When you want to work more directly in any agent’s session, attach to the row to enter the full conversation.
To compare agent view with subagents, agent teams, and worktrees, see
Run agents in parallel
.
Agent view is in research preview and requires Claude Code v2.1.139 or later. Check your version with
claude --version
. The interface and keyboard shortcuts may change as the feature evolves.
This page covers:
Quick start
: give Claude a task to work on in the background, check on it, and step in when needed
Monitor sessions with agent view
, including state icons, peeking and replying, attaching, organizing, and keyboard shortcuts
Dispatch new agents
from agent view, from inside a session, or from your shell
Manage sessions from the shell
How background sessions are hosted
by the supervisor process
​
Quick start
This walkthrough covers the core agent view loop: dispatch a task, watch its row update as Claude works, peek to check on it and reply, and attach for the full conversation. The session you dispatch keeps running after you close agent view, so you can leave and come back to it.
1
Open agent view
From your shell, run:
claude
agents
Agent view opens with an input at the bottom and a table that fills in as sessions start. Press
Esc
at any time to return to your shell. Your sessions keep running while you’re away and reappear the next time you open agent view.
2
Dispatch a session
Type a prompt describing a task and press
Enter
. A new background session starts on that task and appears as a row showing whether it’s working, waiting on you, or done. The new session uses the model shown in the agent view header and the same
permission mode
you’d get running
claude
in that directory.
Every prompt you enter here starts its own new session. Typing another prompt and pressing
Enter
launches a second session alongside the first rather than sending a follow-up to it. You can run several in parallel this way.
Each session uses your subscription quota independently, so see
Limitations
before dispatching many at once.
3
Peek and reply
Select a row with the arrow keys and press
Space
to open the peek panel. It shows the session’s most recent output, or the question it’s waiting on, rather than the full transcript. Type a reply and press
Enter
to send it without leaving agent view.
4
Attach and detach
Press
Enter
or
→
on a row to attach when you want the full conversation. The session takes over the terminal exactly as if you had run
claude
. Press
←
on an empty prompt to detach and return to the table.
5
Bring an existing session in
To move a session you already have open into agent view, run
/bg
inside it, or press
←
on an empty prompt to background it and open agent view in one step. The session keeps running and appears as a row alongside the ones you dispatched.
You can use
claude agents
as your primary entry point instead of
claude
: dispatch every task from agent view, attach when you want the full conversation, and press
←
to return to the table.
​
Monitor sessions with agent view
Run
claude agents
to open agent view. It takes over the full terminal and lists every session grouped by state, with pinned sessions and the ones that need you at the top. Each row shows the session’s name, current activity, and how long ago it last changed.
The list shows every background session you’ve started, across all your projects. A session working in one repository and another in a different worktree both appear here, regardless of which directory you opened agent view from. Interactive sessions you have open in other terminals don’t appear until you
background them
.
Subagents
and
teammates
a session spawns aren’t listed as separate rows.
To scope the view to one project, launch with
claude agents --cwd <path>
. Only sessions started under that directory appear, including any running in a
worktree
dispatched from it.
Pinned
✽ clawd walk cycle          Write assets/sprites/clawd-walk.png           3m
Ready for review
∙ jump physics              github.com/example/game/pull/2048          ●  2h
Needs input
✻ power-up design           needs input: double jump or wall climb?       1m
Working
✽ collision detection       Edit src/physics/CollisionSystem.ts           2m
✢ playtest level 3          run 12 · all checkpoints cleared           in 4m
Completed
✻ title screen              result: menu, options, and credits done       9m
∙ sound effects             result: 14 SFX exported to assets/audio       4h
… 6 more
​
Read session state
Each row starts with an icon whose color and animation show the session’s state:
State
Icon shows as
What it means
Working
Animated
Claude is actively running tools or generating a response
Needs input
Yellow
Claude is waiting on a specific question or permission decision from you
Idle
Dimmed
The session has nothing to do and is ready for your next prompt
Completed
Green
The task finished successfully
Failed
Red
The task ended with an error
Stopped
Grey
The session was stopped with
Ctrl+X
or
claude stop
Separately, the icon’s shape shows whether the underlying process is running:
Shape
What it means
✻
or animated
✽
The session process is alive and replies immediately
∙
The process has exited. You can still peek, reply, or attach, and Claude restarts from where it left off
✢
A
/loop
session sleeping between iterations. The row shows its run count and a countdown
Background sessions don’t need any terminal open to keep working. A separate
supervisor process
runs them, so you can close agent view, close your shell, or start a new interactive session and your dispatched work keeps going.
Session state persists on disk through auto-updates and supervisor restarts. If your machine sleeps or shuts down, running sessions stop; restart them with
claude respawn --all
.
​
Row summaries
The one-line summary in each row is generated by a
Haiku-class model
so the row can tell you what the session is doing, what it needs, or what it produced without opening the transcript. While a session is actively working, the summary refreshes at most once every 15 seconds, plus once when each turn ends.
Each refresh is one short Haiku-class request through your normal provider, billed and handled under the same
data usage terms
as the session itself.
​
Pull request status
When a session opens a pull request, a status dot appears at the right edge of the row, linked to the pull request in terminals that support hyperlinks. When the session has opened more than one pull request, the count appears before the dot and the color reflects whichever one most needs attention.
Dot color
Pull request status
Yellow
Waiting on checks or review, or checks failed
Green
Checks passed and no review is blocking
Purple
Merged
Grey
Draft or closed
For most tasks this row is where you pick up the result: review and merge the pull request when the dot turns green.
​
Peek and reply
Press
Space
on a selected row to open the peek panel. It shows what the session needs from you, its most recent output, and any pull requests it opened. Most of the time this is enough, and you never need to open the full transcript.
Type a reply in the peek panel and press
Enter
to send it to that session. When the session is asking a multiple-choice question, the peek panel shows the options and you can press a number key to pick one. For other blocked sessions, press
Tab
to fill the input with a suggested reply you can edit before sending. Prefix a reply with
!
to send a Bash command instead.
Use
↑
and
↓
to peek at adjacent sessions without closing the panel, or
→
to attach.
​
Attach to a session
Press
Enter
or
→
on a selected row to attach. Agent view is replaced by the full interactive session, exactly as if you had run
claude
in that directory. When you attach, Claude posts a short recap of what happened while you were away.
While attached, the session behaves like any other Claude Code session: every
command
, keyboard shortcut, and feature works.
Press
←
on an empty prompt to detach and return to agent view. If a dialog has focus and isn’t responding to
←
, press
Ctrl+Z
to detach immediately.
Detaching never stops a background session:
←
,
Ctrl+C
,
Ctrl+D
,
Ctrl+Z
, and
/exit
all leave it running. To end a session from inside it, run
/stop
.
After you’ve dispatched or backgrounded a session, pressing
←
on an empty prompt works from any Claude Code session, not only ones you attached to from agent view. It backgrounds the current session and opens agent view with that session pre-selected, so you can switch sessions without leaving the terminal. You can turn this shortcut off in
/config
.
​
Organize the list
Agent view groups sessions so the ones that need input are at the top, with
Ready for review
and
Needs input
above
Working
and
Completed
. These group names don’t map one-to-one to the
states
above: a session moves to
Ready for review
when it has an open pull request, and
Completed
collects finished, failed, and stopped sessions together. Press
Ctrl+S
to group by directory instead. Your choice persists across runs.
Within a group:
Press
Ctrl+T
to pin a session to the top
Press
Shift+↑
or
Shift+↓
to reorder sessions
Press
Ctrl+R
to rename a session
Press
Enter
on a group header to collapse it
To remove a session from the list, press
Ctrl+X
to stop it and
Ctrl+X
again within two seconds to delete it. Pressing
Ctrl+X
on a group header deletes every session in that group after confirmation.
Deleting removes the session from agent view and cleans up its
worktree
, including any uncommitted changes in it, so push or commit work you want to keep before deleting. The conversation transcript stays on disk and remains available through
claude --resume
.
Older completed sessions fold into a
… N more
row to keep the list short. Failures and sessions with an open pull request always stay visible.
​
Filter sessions
Type in the dispatch input to filter instead of dispatching:
Filter
Shows
a:<name>
Sessions running the named agent
s:<state>
Sessions in the given state, such as
s:working
. Also accepts
s:blocked
for everything waiting on you
#<number>
or a PR URL
The session working on that pull request
​
Keyboard shortcuts
Press
?
in agent view to see every shortcut in context. The table below summarizes them.
Shortcut
Action
↑
/
↓
Move between rows
Enter
Attach to the selected session, or dispatch if there’s text in the input
Space
Open or close the peek panel for the selected session
Shift+Enter
Dispatch and attach immediately
→
Attach to the selected session
Alt+1
..
Alt+9
Attach to session 1–9 in the current group
Tab
On an empty input, browse all subagents. Otherwise apply the highlighted suggestion
Ctrl+S
Switch grouping between state and directory
Ctrl+T
Pin or unpin the selected session
Ctrl+R
Rename the selected session
Ctrl+G
Open the dispatch prompt in your
$EDITOR
Ctrl+X
Stop the session; press again within two seconds to delete it
Shift+↑
/
Shift+↓
Reorder the selected session
Esc
Close the peek panel, clear the input, or exit
Ctrl+C
Clear the input; press twice to exit
?
Show all shortcuts
​
Dispatch new agents
You can dispatch new background sessions from agent view, send an existing interactive session to the background, or start one directly from the shell.
​
From agent view
Type a prompt in the input at the bottom of agent view and press
Enter
to start a new background session. The session is named automatically from the prompt; rename it later with
Ctrl+R
.
Paste an image into the prompt to include a screenshot or diagram with the task.
Prefix or mention parts of the prompt to control how the session starts:
Input
Effect
<agent-name> <prompt>
If the first word matches a custom
subagent
name, that subagent runs as the session’s main agent with the configuration from its frontmatter
@<agent-name>
Mention a custom subagent anywhere in the prompt to run it as the main agent
@<repo>
Mention a repository under the directory you opened agent view from to run the session there
/<skill>
Suggest
skills
to dispatch as the prompt
#<number>
or a pull request URL
If a session is already working on that PR, select it instead of dispatching
Shift+Enter
Dispatch and immediately attach to the new session
Packaging a recurring task as a
skill
lets you start the same workflow from agent view repeatedly without retyping the prompt.
When the same
@name
matches both a subagent and a sibling repository, the subagent takes precedence. The bare first-word match also applies, so a prompt that happens to begin with one of your subagent names dispatches that subagent rather than treating the word as plain text. Use the
@
form when you want to be explicit, or start the prompt with a different word to avoid the match.
​
Dispatch to a specific directory
A new session runs in the directory you opened agent view from. To target a different directory:
Open
claude agents
in that directory.
Open
claude agents
in a parent directory that holds several repositories and mention one with
@<repo>
in the prompt to run the session there.
From the shell,
cd
into the directory and run
claude --bg "<prompt>"
.
When agent view is grouped by directory, the highlighted row’s directory becomes the dispatch target, so you can scroll to a group and dispatch into it without retyping the path.
​
From inside a session
Run
/background
or its alias
/bg
to move the current conversation into a background session. Pass a prompt such as
/bg run the test suite and fix any failures
to give one more instruction first.
Backgrounding from an interactive session starts a fresh process that resumes from the saved conversation, so running subagents,
monitors
, and background commands do not transfer to it. Claude asks you to confirm before backgrounding when any are running. Once in the background, the session can start new subagents, monitors, and background commands, and those keep running across later detach and reattach.
​
From your shell
Pass
--bg
to start a session that goes straight to the background:
claude
--bg
"investigate the flaky SettingsChangeDetector test"
To run a specific subagent as the session’s main agent, combine
--bg
with
--agent
:
claude
--agent
code-reviewer
--bg
"address review comments on PR 1234"
Pass
--name
to set the session’s display name in agent view instead of the auto-generated one:
claude
--bg
--name
"flaky-test-fix"
"investigate the flaky SettingsChangeDetector test"
After backgrounding, Claude prints the session’s short ID and the commands for managing it:
backgrounded · 7c5dcf5d
claude agents             list sessions
claude attach 7c5dcf5d    open in this terminal
claude logs 7c5dcf5d      show recent output
claude stop 7c5dcf5d      stop this session
​
How file edits are isolated
Every background session, whether started from agent view,
/bg
, or
claude --bg
, starts in your working directory. Before editing files, Claude moves the session into an isolated
git worktree
under
.claude/worktrees/
, so parallel sessions can read the same checkout but each writes to its own. Claude skips this when the session is already under
.claude/worktrees/
, when the working directory isn’t a git repository, or for writes outside the working directory.
Outside a git repository, sessions write to the working directory directly and aren’t isolated from each other, so avoid dispatching parallel sessions that edit the same files.
The worktree is removed when you delete the session, so merge or push the changes you want to keep before you delete. To find a session’s worktree path, peek the session or attach and check its working directory.
To make a subagent always run in its own worktree regardless of how it was started, set
isolation: worktree
in its frontmatter.
​
Set the model
The model name shown in the agent view header is the dispatch default. New sessions you start from the input use this model, which is the same setting
/model
controls in any session. To override it for the whole agent view session, pass
--model
when opening agent view. See
Permission mode, model, and effort
.
Each background session can run on a different model. To override it for one session:
From the shell, pass
--model
with
claude --bg
.
Attach to a running session and run
/model
there. The change persists if the session is respawned.
Dispatch a
subagent
whose frontmatter sets a
model
field.
​
Permission mode, model, and effort
A background session reads its
settings
from the directory it runs in, the same as if you had started
claude
there.
The
permission mode
depends on how you started the session. Backgrounding an existing session with
/bg
or
←
keeps the current permission mode, so a session you switched to
acceptEdits
or
auto
stays in that mode after detaching. Dispatching from the agent view input or running
claude --bg
from your shell uses the
defaultMode
from that directory’s settings, or the
permissionMode
from the dispatched
subagent’s frontmatter
.
To set defaults for every session you dispatch from agent view, pass any of
--permission-mode
,
--model
, or
--effort
when opening it:
claude
agents
--permission-mode
plan
--model
opus
--effort
high
Passing
--permission-mode
,
--model
, or
--effort
to
claude agents
requires Claude Code v2.1.142 or later. Earlier versions reject these flags with an unknown-option error.
The active defaults appear in the footer below the dispatch input.
Without these flags, the session uses the
defaultMode
from that directory’s settings or the
permissionMode
from the dispatched
subagent’s frontmatter
, and the model shown in the agent view header.
Using
bypassPermissions
or
auto
is refused until you have accepted that mode by running
claude
with it once interactively, since those modes let a session you aren’t watching act without approval. The same applies whether you pass the mode to
claude agents
or to
claude --bg --permission-mode
.
​
Settings, plugins, and MCP servers
Agent view accepts the same configuration flags as
claude
for loading settings, plugins, MCP servers, and additional directories. Each flag applies to agent view itself and is passed through to every session you dispatch from it, so a plugin or MCP server you load this way is available in those sessions too.
Flag
Effect
--settings <file-or-json>
Override settings for agent view and dispatched sessions
--add-dir <path>
Grant file access to an additional directory
--plugin-dir <path>
Load a plugin from a local directory
--mcp-config <file-or-json>
Load MCP servers from a config file or JSON string
--strict-mcp-config
Use only the MCP servers from
--mcp-config
, ignoring other MCP configuration
Repeat
--add-dir
,
--plugin-dir
, or
--mcp-config
once per value. The space-separated form, such as
--add-dir a b c
, is not supported with
claude agents
.
The following example opens agent view with a settings override and one extra directory:
claude
agents
--settings
./ci-settings.json
--add-dir
../shared-lib
​
Manage sessions from the shell
Every background session has a short ID you can use from the shell. The ID is printed when you start a session with
claude --bg
, and each session’s ID is its directory name under
~/.claude/jobs/
. These commands are useful for scripting or when you don’t want to open agent view.
Command
Purpose
claude agents
Open agent view. Pass
--cwd <path>
to list only sessions started under that directory
claude attach <id>
Attach to a session in this terminal
claude logs <id>
Print the session’s recent output
claude stop <id>
Stop a session. Also accepts
claude kill
claude respawn <id>
Restart a stopped session with its conversation intact
claude respawn --all
Restart every stopped session
claude rm <id>
Remove a session from the list. Cleans up its worktree if there are no uncommitted changes
​
How background sessions are hosted
Every session listed in agent view is considered a background session, whether or not you’re currently attached to it. By contrast, a session started by running
claude
directly is tied to that terminal and ends when it closes, unless you
send it to the background
.
​
The supervisor process
Background sessions are hosted by a per-user supervisor process, separate from your terminal and from agent view. The supervisor starts automatically the first time you background a session or open agent view, and you don’t manage it directly.
The supervisor and its sessions authenticate with the same credentials as your interactive sessions and make no additional network connections beyond the model API.
Each background session is its own Claude Code process, managed by the supervisor rather than tied to your terminal. A session that’s actively working, waiting for your input, or has a terminal attached keeps its process running.
Once a session finishes and sits unattached for about an hour, the supervisor stops its process to free resources. The transcript and state stay on disk, and the next time you attach, peek, or reply, the supervisor starts a fresh process from where it left off. When every session has finished and no terminal is connected, the supervisor itself exits and starts again the next time you need it.
The supervisor watches the installed Claude Code binary on disk and restarts into the new version after the regular
auto-updater
replaces it. This is a local file watch, not a network check. Background sessions are detached processes, so they keep running through the restart and the new supervisor reconnects to them.
​
Where state is stored
Session state is stored under your Claude Code config directory. If you set
CLAUDE_CONFIG_DIR
, the supervisor uses that directory instead of
~/.claude
and runs as a separate instance with its own sessions.
Path
Contents
~/.claude/daemon.log
Supervisor log
~/.claude/daemon/roster.json
List of running background sessions, used to reconnect after a restart
~/.claude/jobs/<id>/state.json
Per-session state shown in agent view
​
Turn off agent view
To turn off background agents and agent view entirely, set the
disableAgentView
setting
to
true
or set the
CLAUDE_CODE_DISABLE_AGENT_VIEW
environment variable. Administrators can enforce this through
managed settings
.
​
Troubleshooting
​
claude agents
lists subagents instead of opening agent view
If
claude agents
prints a count followed by your configured subagents and then exits, agent view is unavailable in your environment. Earlier versions didn’t open agent view in every environment, including when connected through Bedrock, Vertex AI, or Foundry. Run
claude update
to install the latest version.
If agent view still does not open after updating, check whether it has been
turned off
by a setting or environment variable.
​
Agent view opens with no sessions
Agent view is empty until you dispatch your first session. Type a prompt in the input at the bottom and press
Enter
.
​
Cannot open agents because background tasks are running
If pressing
←
to background the current session shows
Cannot open agents — N background task(s) running
, the session has in-flight work such as a subagent, a workflow, or a background shell command, and the shortcut won’t silently abandon it. Run
/tasks
to see what’s running, then
/bg
to confirm abandoning them. See
From inside a session
for what does and doesn’t transfer when you background.
​
Prompt rejected as too short
The dispatch input expects a task description, not a conversational opener. A prompt shorter than four characters is rejected with a
Too short
hint so a stray keystroke doesn’t start a session. Describe what you want the session to do, such as
investigate the flaky checkout test
.
​
Sessions show as failed after waking your machine
Background sessions don’t survive sleep or shutdown, so sessions that were running show as failed after you wake. Attach, peek, or reply to any of them and the session restarts from where it left off. To restart all of them at once, run
claude respawn --all
.
​
A session is slow to respond after attaching
Once a session has finished and sat unattached for about an hour, the supervisor stops its process to free resources. Attaching starts a fresh process from where it left off, which takes a moment. Sessions that are working or waiting on you are never stopped this way.
​
.claude/worktrees/
is filling up
Worktrees are removed when you delete the session that created them. If a session ended without cleaning up, list leftover entries with
git worktree list
in the project directory and remove each with
git worktree remove <path>
. See
Clean up worktrees
.
​
Limitations
Agent view is in research preview with the following limitations:
Rate limits apply
: background sessions consume your subscription usage the same as interactive sessions, so running ten agents in parallel uses quota roughly ten times as fast as running one.
Sessions are local
: background sessions run on your machine and stop if it sleeps or shuts down.
Worktrees are deleted with the session
: merge or push changes before deleting a session that edited files in its own worktree.
​
Related resources
For other ways to run Claude in parallel, see:
Run agents in parallel
: compare agent view with subagents, agent teams, and worktrees
Agent teams
: coordinate multiple sessions that message each other
Claude Code on the web
: run sessions in a managed cloud environment instead of locally
Was this page helpful?
Yes
No
Create custom subagents
Run agent teams
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-view" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Manage multiple agents with agent view
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Manage multiple agents with agent view
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Agent view, opened with
claude agents
, is one screen for all your background sessions: what’s running, what needs your input, and what’s done. Dispatch new sessions, watch their state at a glance instead of scrolling through transcripts, and step in only when one needs you. Each background session is a full Claude Code conversation that keeps running without a terminal attached, so you can open it, reply, and leave whenever you want.
Use agent view when you have several independent tasks Claude can work on without you watching every step. Dispatch a bug fix, a pull request review, and a flaky-test investigation as three rows, keep working in another window, and check back when a row shows it needs you or has a result.
When you want to work more directly in any agent’s session, attach to the row to enter the full conversation.
To compare agent view with subagents, agent teams, and worktrees, see
Run agents in parallel
.
Agent view is in research preview and requires Claude Code v2.1.139 or later. Check your version with
claude --version
. The interface and keyboard shortcuts may change as the feature evolves.
This page covers:
Quick start
: give Claude a task to work on in the background, check on it, and step in when needed
Monitor sessions with agent view
, including state icons, peeking and replying, attaching, organizing, and keyboard shortcuts
Dispatch new agents
from agent view, from inside a session, or from your shell
Manage sessions from the shell
How background sessions are hosted
by the supervisor process
​
Quick start
This walkthrough covers the core agent view loop: dispatch a task, watch its row update as Claude works, peek to check on it and reply, and attach for the full conversation. The session you dispatch keeps running after you close agent view, so you can leave and come back to it.
1
Open agent view
From your shell, run:
claude
agents
Agent view opens with an input at the bottom and a table that fills in as sessions start. Press
Esc
at any time to return to your shell. Your sessions keep running while you’re away and reappear the next time you open agent view.
2
Dispatch a session
Type a prompt describing a task and press
Enter
. A new background session starts on that task and appears as a row showing whether it’s working, waiting on you, or done. The new session uses the model shown in the agent view header and the same
permission mode
you’d get running
claude
in that directory.
Every prompt you enter here starts its own new session. Typing another prompt and pressing
Enter
launches a second session alongside the first rather than sending a follow-up to it. You can run several in parallel this way.
Each session uses your subscription quota independently, so see
Limitations
before dispatching many at once.
3
Peek and reply
Select a row with the arrow keys and press
Space
to open the peek panel. It shows the session’s most recent output, or the question it’s waiting on, rather than the full transcript. Type a reply and press
Enter
to send it without leaving agent view.
4
Attach and detach
Press
Enter
or
→
on a row to attach when you want the full conversation. The session takes over the terminal exactly as if you had run
claude
. Press
←
on an empty prompt to detach and return to the table.
5
Bring an existing session in
To move a session you already have open into agent view, run
/bg
inside it, or press
←
on an empty prompt to background it and open agent view in one step. The session keeps running and appears as a row alongside the ones you dispatched.
You can use
claude agents
as your primary entry point instead of
claude
: dispatch every task from agent view, attach when you want the full conversation, and press
←
to return to the table.
​
Monitor sessions with agent view
Run
claude agents
to open agent view. It takes over the full terminal and lists every session grouped by state, with pinned sessions and the ones that need you at the top. Each row shows the session’s name, current activity, and how long ago it last changed.
The list shows every background session you’ve started, across all your projects. A session working in one repository and another in a different worktree both appear here, regardless of which directory you opened agent view from. Interactive sessions you have open in other terminals don’t appear until you
background them
.
Subagents
and
teammates
a session spawns aren’t listed as separate rows.
To scope the view to one project, launch with
claude agents --cwd <path>
. Only sessions started under that directory appear, including any running in a
worktree
dispatched from it.
Pinned
✽ clawd walk cycle          Write assets/sprites/clawd-walk.png           3m
Ready for review
∙ jump physics              github.com/example/game/pull/2048          ●  2h
Needs input
✻ power-up design           needs input: double jump or wall climb?       1m
Working
✽ collision detection       Edit src/physics/CollisionSystem.ts           2m
✢ playtest level 3          run 12 · all checkpoints cleared           in 4m
Completed
✻ title screen              result: menu, options, and credits done       9m
∙ sound effects             result: 14 SFX exported to assets/audio       4h
… 6 more
​
Read session state
Each row starts with an icon whose color and animation show the session’s state:
State
Icon shows as
What it means
Working
Animated
Claude is actively running tools or generating a response
Needs input
Yellow
Claude is waiting on a specific question or permission decision from you
Idle
Dimmed
The session has nothing to do and is ready for your next prompt
Completed
Green
The task finished successfully
Failed
Red
The task ended with an error
Stopped
Grey
The session was stopped with
Ctrl+X
or
claude stop
Separately, the icon’s shape shows whether the underlying process is running:
Shape
What it means
✻
or animated
✽
The session process is alive and replies immediately
∙
The process has exited. You can still peek, reply, or attach, and Claude restarts from where it left off
✢
A
/loop
session sleeping between iterations. The row shows its run count and a countdown
Background sessions don’t need any terminal open to keep working. A separate
supervisor process
runs them, so you can close agent view, close your shell, or start a new interactive session and your dispatched work keeps going.
Session state persists on disk through auto-updates and supervisor restarts. If your machine sleeps or shuts down, running sessions stop; restart them with
claude respawn --all
.
​
Row summaries
The one-line summary in each row is generated by a
Haiku-class model
so the row can tell you what the session is doing, what it needs, or what it produced without opening the transcript. While a session is actively working, the summary refreshes at most once every 15 seconds, plus once when each turn ends.
Each refresh is one short Haiku-class request through your normal provider, billed and handled under the same
data usage terms
as the session itself.
​
Pull request status
When a session opens a pull request, a status dot appears at the right edge of the row, linked to the pull request in terminals that support hyperlinks. When the session has opened more than one pull request, the count appears before the dot and the color reflects whichever one most needs attention.
Dot color
Pull request status
Yellow
Waiting on checks or review, or checks failed
Green
Checks passed and no review is blocking
Purple
Merged
Grey
Draft or closed
For most tasks this row is where you pick up the result: review and merge the pull request when the dot turns green.
​
Peek and reply
Press
Space
on a selected row to open the peek panel. It shows what the session needs from you, its most recent output, and any pull requests it opened. Most of the time this is enough, and you never need to open the full transcript.
Type a reply in the peek panel and press
Enter
to send it to that session. When the session is asking a multiple-choice question, the peek panel shows the options and you can press a number key to pick one. For other blocked sessions, press
Tab
to fill the input with a suggested reply you can edit before sending. Prefix a reply with
!
to send a Bash command instead.
Use
↑
and
↓
to peek at adjacent sessions without closing the panel, or
→
to attach.
​
Attach to a session
Press
Enter
or
→
on a selected row to attach. Agent view is replaced by the full interactive session, exactly as if you had run
claude
in that directory. When you attach, Claude posts a short recap of what happened while you were away.
While attached, the session behaves like any other Claude Code session: every
command
, keyboard shortcut, and feature works.
Press
←
on an empty prompt to detach and return to agent view. If a dialog has focus and isn’t responding to
←
, press
Ctrl+Z
to detach immediately.
Detaching never stops a background session:
←
,
Ctrl+C
,
Ctrl+D
,
Ctrl+Z
, and
/exit
all leave it running. To end a session from inside it, run
/stop
.
After you’ve dispatched or backgrounded a session, pressing
←
on an empty prompt works from any Claude Code session, not only ones you attached to from agent view. It backgrounds the current session and opens agent view with that session pre-selected, so you can switch sessions without leaving the terminal. You can turn this shortcut off in
/config
.
​
Organize the list
Agent view groups sessions so the ones that need input are at the top, with
Ready for review
and
Needs input
above
Working
and
Completed
. These group names don’t map one-to-one to the
states
above: a session moves to
Ready for review
when it has an open pull request, and
Completed
collects finished, failed, and stopped sessions together. Press
Ctrl+S
to group by directory instead. Your choice persists across runs.
Within a group:
Press
Ctrl+T
to pin a session to the top
Press
Shift+↑
or
Shift+↓
to reorder sessions
Press
Ctrl+R
to rename a session
Press
Enter
on a group header to collapse it
To remove a session from the list, press
Ctrl+X
to stop it and
Ctrl+X
again within two seconds to delete it. Pressing
Ctrl+X
on a group header deletes every session in that group after confirmation.
Deleting removes the session from agent view and cleans up its
worktree
, including any uncommitted changes in it, so push or commit work you want to keep before deleting. The conversation transcript stays on disk and remains available through
claude --resume
.
Older completed sessions fold into a
… N more
row to keep the list short. Failures and sessions with an open pull request always stay visible.
​
Filter sessions
Type in the dispatch input to filter instead of dispatching:
Filter
Shows
a:<name>
Sessions running the named agent
s:<state>
Sessions in the given state, such as
s:working
. Also accepts
s:blocked
for everything waiting on you
#<number>
or a PR URL
The session working on that pull request
​
Keyboard shortcuts
Press
?
in agent view to see every shortcut in context. The table below summarizes them.
Shortcut
Action
↑
/
↓
Move between rows
Enter
Attach to the selected session, or dispatch if there’s text in the input
Space
Open or close the peek panel for the selected session
Shift+Enter
Dispatch and attach immediately
→
Attach to the selected session
Alt+1
..
Alt+9
Attach to session 1–9 in the current group
Tab
On an empty input, browse all subagents. Otherwise apply the highlighted suggestion
Ctrl+S
Switch grouping between state and directory
Ctrl+T
Pin or unpin the selected session
Ctrl+R
Rename the selected session
Ctrl+G
Open the dispatch prompt in your
$EDITOR
Ctrl+X
Stop the session; press again within two seconds to delete it
Shift+↑
/
Shift+↓
Reorder the selected session
Esc
Close the peek panel, clear the input, or exit
Ctrl+C
Clear the input; press twice to exit
?
Show all shortcuts
​
Dispatch new agents
You can dispatch new background sessions from agent view, send an existing interactive session to the background, or start one directly from the shell.
​
From agent view
Type a prompt in the input at the bottom of agent view and press
Enter
to start a new background session. The session is named automatically from the prompt; rename it later with
Ctrl+R
.
Paste an image into the prompt to include a screenshot or diagram with the task.
Prefix or mention parts of the prompt to control how the session starts:
Input
Effect
<agent-name> <prompt>
If the first word matches a custom
subagent
name, that subagent runs as the session’s main agent with the configuration from its frontmatter
@<agent-name>
Mention a custom subagent anywhere in the prompt to run it as the main agent
@<repo>
Mention a repository under the directory you opened agent view from to run the session there
/<skill>
Suggest
skills
to dispatch as the prompt
#<number>
or a pull request URL
If a session is already working on that PR, select it instead of dispatching
Shift+Enter
Dispatch and immediately attach to the new session
Packaging a recurring task as a
skill
lets you start the same workflow from agent view repeatedly without retyping the prompt.
When the same
@name
matches both a subagent and a sibling repository, the subagent takes precedence. The bare first-word match also applies, so a prompt that happens to begin with one of your subagent names dispatches that subagent rather than treating the word as plain text. Use the
@
form when you want to be explicit, or start the prompt with a different word to avoid the match.
​
Dispatch to a specific directory
A new session runs in the directory you opened agent view from. To target a different directory:
Open
claude agents
in that directory.
Open
claude agents
in a parent directory that holds several repositories and mention one with
@<repo>
in the prompt to run the session there.
From the shell,
cd
into the directory and run
claude --bg "<prompt>"
.
When agent view is grouped by directory, the highlighted row’s directory becomes the dispatch target, so you can scroll to a group and dispatch into it without retyping the path.
​
From inside a session
Run
/background
or its alias
/bg
to move the current conversation into a background session. Pass a prompt such as
/bg run the test suite and fix any failures
to give one more instruction first.
Backgrounding from an interactive session starts a fresh process that resumes from the saved conversation, so running subagents,
monitors
, and background commands do not transfer to it. Claude asks you to confirm before backgrounding when any are running. Once in the background, the session can start new subagents, monitors, and background commands, and those keep running across later detach and reattach.
​
From your shell
Pass
--bg
to start a session that goes straight to the background:
claude
--bg
"investigate the flaky SettingsChangeDetector test"
To run a specific subagent as the session’s main agent, combine
--bg
with
--agent
:
claude
--agent
code-reviewer
--bg
"address review comments on PR 1234"
Pass
--name
to set the session’s display name in agent view instead of the auto-generated one:
claude
--bg
--name
"flaky-test-fix"
"investigate the flaky SettingsChangeDetector test"
After backgrounding, Claude prints the session’s short ID and the commands for managing it:
backgrounded · 7c5dcf5d
claude agents             list sessions
claude attach 7c5dcf5d    open in this terminal
claude logs 7c5dcf5d      show recent output
claude stop 7c5dcf5d      stop this session
​
How file edits are isolated
Every background session, whether started from agent view,
/bg
, or
claude --bg
, starts in your working directory. Before editing files, Claude moves the session into an isolated
git worktree
under
.claude/worktrees/
, so parallel sessions can read the same checkout but each writes to its own. Claude skips this when the session is already under
.claude/worktrees/
, when the working directory isn’t a git repository, or for writes outside the working directory.
Outside a git repository, sessions write to the working directory directly and aren’t isolated from each other, so avoid dispatching parallel sessions that edit the same files.
The worktree is removed when you delete the session, so merge or push the changes you want to keep before you delete. To find a session’s worktree path, peek the session or attach and check its working directory.
To make a subagent always run in its own worktree regardless of how it was started, set
isolation: worktree
in its frontmatter.
​
Set the model
The model name shown in the agent view header is the dispatch default. New sessions you start from the input use this model, which is the same setting
/model
controls in any session. To override it for the whole agent view session, pass
--model
when opening agent view. See
Permission mode, model, and effort
.
Each background session can run on a different model. To override it for one session:
From the shell, pass
--model
with
claude --bg
.
Attach to a running session and run
/model
there. The change persists if the session is respawned.
Dispatch a
subagent
whose frontmatter sets a
model
field.
​
Permission mode, model, and effort
A background session reads its
settings
from the directory it runs in, the same as if you had started
claude
there.
The
permission mode
depends on how you started the session. Backgrounding an existing session with
/bg
or
←
keeps the current permission mode, so a session you switched to
acceptEdits
or
auto
stays in that mode after detaching. Dispatching from the agent view input or running
claude --bg
from your shell uses the
defaultMode
from that directory’s settings, or the
permissionMode
from the dispatched
subagent’s frontmatter
.
To set defaults for every session you dispatch from agent view, pass any of
--permission-mode
,
--model
, or
--effort
when opening it:
claude
agents
--permission-mode
plan
--model
opus
--effort
high
Passing
--permission-mode
,
--model
, or
--effort
to
claude agents
requires Claude Code v2.1.142 or later. Earlier versions reject these flags with an unknown-option error.
The active defaults appear in the footer below the dispatch input.
Without these flags, the session uses the
defaultMode
from that directory’s settings or the
permissionMode
from the dispatched
subagent’s frontmatter
, and the model shown in the agent view header.
Using
bypassPermissions
or
auto
is refused until you have accepted that mode by running
claude
with it once interactively, since those modes let a session you aren’t watching act without approval. The same applies whether you pass the mode to
claude agents
or to
claude --bg --permission-mode
.
​
Settings, plugins, and MCP servers
Agent view accepts the same configuration flags as
claude
for loading settings, plugins, MCP servers, and additional directories. Each flag applies to agent view itself and is passed through to every session you dispatch from it, so a plugin or MCP server you load this way is available in those sessions too.
Flag
Effect
--settings <file-or-json>
Override settings for agent view and dispatched sessions
--add-dir <path>
Grant file access to an additional directory
--plugin-dir <path>
Load a plugin from a local directory
--mcp-config <file-or-json>
Load MCP servers from a config file or JSON string
--strict-mcp-config
Use only the MCP servers from
--mcp-config
, ignoring other MCP configuration
Repeat
--add-dir
,
--plugin-dir
, or
--mcp-config
once per value. The space-separated form, such as
--add-dir a b c
, is not supported with
claude agents
.
The following example opens agent view with a settings override and one extra directory:
claude
agents
--settings
./ci-settings.json
--add-dir
../shared-lib
​
Manage sessions from the shell
Every background session has a short ID you can use from the shell. The ID is printed when you start a session with
claude --bg
, and each session’s ID is its directory name under
~/.claude/jobs/
. These commands are useful for scripting or when you don’t want to open agent view.
Command
Purpose
claude agents
Open agent view. Pass
--cwd <path>
to list only sessions started under that directory
claude attach <id>
Attach to a session in this terminal
claude logs <id>
Print the session’s recent output
claude stop <id>
Stop a session. Also accepts
claude kill
claude respawn <id>
Restart a stopped session with its conversation intact
claude respawn --all
Restart every stopped session
claude rm <id>
Remove a session from the list. Cleans up its worktree if there are no uncommitted changes
​
How background sessions are hosted
Every session listed in agent view is considered a background session, whether or not you’re currently attached to it. By contrast, a session started by running
claude
directly is tied to that terminal and ends when it closes, unless you
send it to the background
.
​
The supervisor process
Background sessions are hosted by a per-user supervisor process, separate from your terminal and from agent view. The supervisor starts automatically the first time you background a session or open agent view, and you don’t manage it directly.
The supervisor and its sessions authenticate with the same credentials as your interactive sessions and make no additional network connections beyond the model API.
Each background session is its own Claude Code process, managed by the supervisor rather than tied to your terminal. A session that’s actively working, waiting for your input, or has a terminal attached keeps its process running.
Once a session finishes and sits unattached for about an hour, the supervisor stops its process to free resources. The transcript and state stay on disk, and the next time you attach, peek, or reply, the supervisor starts a fresh process from where it left off. When every session has finished and no terminal is connected, the supervisor itself exits and starts again the next time you need it.
The supervisor watches the installed Claude Code binary on disk and restarts into the new version after the regular
auto-updater
replaces it. This is a local file watch, not a network check. Background sessions are detached processes, so they keep running through the restart and the new supervisor reconnects to them.
​
Where state is stored
Session state is stored under your Claude Code config directory. If you set
CLAUDE_CONFIG_DIR
, the supervisor uses that directory instead of
~/.claude
and runs as a separate instance with its own sessions.
Path
Contents
~/.claude/daemon.log
Supervisor log
~/.claude/daemon/roster.json
List of running background sessions, used to reconnect after a restart
~/.claude/jobs/<id>/state.json
Per-session state shown in agent view
​
Turn off agent view
To turn off background agents and agent view entirely, set the
disableAgentView
setting
to
true
or set the
CLAUDE_CODE_DISABLE_AGENT_VIEW
environment variable. Administrators can enforce this through
managed settings
.
​
Troubleshooting
​
claude agents
lists subagents instead of opening agent view
If
claude agents
prints a count followed by your configured subagents and then exits, agent view is unavailable in your environment. Earlier versions didn’t open agent view in every environment, including when connected through Bedrock, Vertex AI, or Foundry. Run
claude update
to install the latest version.
If agent view still does not open after updating, check whether it has been
turned off
by a setting or environment variable.
​
Agent view opens with no sessions
Agent view is empty until you dispatch your first session. Type a prompt in the input at the bottom and press
Enter
.
​
Cannot open agents because background tasks are running
If pressing
←
to background the current session shows
Cannot open agents — N background task(s) running
, the session has in-flight work such as a subagent, a workflow, or a background shell command, and the shortcut won’t silently abandon it. Run
/tasks
to see what’s running, then
/bg
to confirm abandoning them. See
From inside a session
for what does and doesn’t transfer when you background.
​
Prompt rejected as too short
The dispatch input expects a task description, not a conversational opener. A prompt shorter than four characters is rejected with a
Too short
hint so a stray keystroke doesn’t start a session. Describe what you want the session to do, such as
investigate the flaky checkout test
.
​
Sessions show as failed after waking your machine
Background sessions don’t survive sleep or shutdown, so sessions that were running show as failed after you wake. Attach, peek, or reply to any of them and the session restarts from where it left off. To restart all of them at once, run
claude respawn --all
.
​
A session is slow to respond after attaching
Once a session has finished and sat unattached for about an hour, the supervisor stops its process to free resources. Attaching starts a fresh process from where it left off, which takes a moment. Sessions that are working or waiting on you are never stopped this way.
​
.claude/worktrees/
is filling up
Worktrees are removed when you delete the session that created them. If a session ended without cleaning up, list leftover entries with
git worktree list
in the project directory and remove each with
git worktree remove <path>
. See
Clean up worktrees
.
​
Limitations
Agent view is in research preview with the following limitations:
Rate limits apply
: background sessions consume your subscription usage the same as interactive sessions, so running ten agents in parallel uses quota roughly ten times as fast as running one.
Sessions are local
: background sessions run on your machine and stop if it sleeps or shuts down.
Worktrees are deleted with the session
: merge or push changes before deleting a session that edited files in its own worktree.
​
Related resources
For other ways to run Claude in parallel, see:
Run agents in parallel
: compare agent view with subagents, agent teams, and worktrees
Agent teams
: coordinate multiple sessions that message each other
Claude Code on the web
: run sessions in a managed cloud environment instead of locally
Was this page helpful?
Yes
No
Create custom subagents
Run agent teams
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-view" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Tools reference</title>
  <link>https://code.claude.com/docs/en/tools-reference</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/tools-reference</guid>
  <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
  <category>Reference</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Tools reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code has access to a set of built-in tool...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Tools reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code has access to a set of built-in tools that help it understand and modify your codebase. The tool names are the exact strings you use in
permission rules
,
subagent tool lists
, and
hook matchers
. To disable a tool entirely, add its name to the
deny
array in your
permission settings
.
To add custom tools, connect an
MCP server
. To extend Claude with reusable prompt-based workflows, write a
skill
, which runs through the existing
Skill
tool rather than adding a new tool entry.
Tool
Description
Permission Required
Agent
Spawns a
subagent
with its own context window to handle a task. See
Agent tool behavior
No
AskUserQuestion
Asks multiple-choice questions to gather requirements or clarify ambiguity
No
Bash
Executes shell commands in your environment. See
Bash tool behavior
Yes
CronCreate
Schedules a recurring or one-shot prompt within the current session. Tasks are session-scoped and restored on
--resume
or
--continue
if unexpired. See
scheduled tasks
No
CronDelete
Cancels a scheduled task by ID
No
CronList
Lists all scheduled tasks in the session
No
Edit
Makes targeted edits to specific files. See
Edit tool behavior
Yes
EnterPlanMode
Switches to plan mode to design an approach before coding
No
EnterWorktree
Creates an isolated
git worktree
and switches into it. Pass a
path
to switch into an existing worktree of the current repository instead of creating a new one. Not available to subagents
No
ExitPlanMode
Presents a plan for approval and exits plan mode
Yes
ExitWorktree
Exits a worktree session and returns to the original directory. Not available to subagents
No
Glob
Finds files based on pattern matching. See
Glob tool behavior
No
Grep
Searches for patterns in file contents. See
Grep tool behavior
No
ListMcpResourcesTool
Lists resources exposed by connected
MCP servers
No
LSP
Code intelligence via language servers: jump to definitions, find references, report type errors and warnings. See
LSP tool behavior
No
Monitor
Runs a command in the background and feeds each output line back to Claude, so it can react to log entries, file changes, or polled status mid-conversation. See
Monitor tool
Yes
NotebookEdit
Modifies Jupyter notebook cells. See
NotebookEdit tool behavior
Yes
PowerShell
Executes PowerShell commands natively. See
PowerShell tool
for availability
Yes
PushNotification
Sends a desktop notification, and a phone push when
Remote Control
is connected, so a long-running task or
scheduled task
can reach you when you step away. Push delivery runs through Anthropic-hosted infrastructure, which is not accessible from Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
No
Read
Reads the contents of files. See
Read tool behavior
No
ReadMcpResourceTool
Reads a specific MCP resource by URI
No
RemoteTrigger
Creates, updates, runs, and lists
Routines
on claude.ai. Backs the
/schedule
command. Routines live on claude.ai and require a Pro, Max, Team, or Enterprise plan, so this tool is not accessible from Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
No
SendMessage
Sends a message to an
agent team
teammate, or
resumes a subagent
by its agent ID. Stopped subagents auto-resume in the background. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
ShareOnboardingGuide
Uploads
ONBOARDING.md
and returns a share link teammates can open in Claude Code. Called from
/team-onboarding
after the guide is written. Available to claude.ai subscribers on Pro, Max, Team, and Enterprise plans
Yes
Skill
Executes a
skill
within the main conversation
Yes
TaskCreate
Creates a new task in the task list
No
TaskGet
Retrieves full details for a specific task
No
TaskList
Lists all tasks with their current status
No
TaskOutput
(Deprecated) Retrieves output from a background task. Prefer
Read
on the task’s output file path
No
TaskStop
Kills a running background task by ID
No
TaskUpdate
Updates task status, dependencies, details, or deletes tasks
No
TeamCreate
Creates an
agent team
with multiple teammates. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
TeamDelete
Disbands an agent team and cleans up teammate processes. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
TodoWrite
Manages the session task checklist. Deprecated in favor of
TaskCreate
,
TaskGet
,
TaskList
, and
TaskUpdate
. Interactive sessions already use the Task tools by default. When you run
claude -p
or use the
Agent SDK
,
TodoWrite
is still the default. Set
CLAUDE_CODE_ENABLE_TASKS=1
to switch those to the Task tools before
TodoWrite
is removed
No
ToolSearch
Searches for and loads deferred tools when
tool search
is enabled
No
WebFetch
Fetches content from a specified URL. See
WebFetch tool behavior
Yes
WebSearch
Performs web searches. See
WebSearch tool behavior
Yes
Write
Creates or overwrites files. See
Write tool behavior
Yes
​
Configure tools with permission rules and hooks
For the most part, Claude decides when to use these tools and you do not need to name them yourself when interacting with Claude. You reference tool names directly when defining permissions and other configuration:
in
permissions.allow
and
permissions.deny
in settings, and the
/permissions
interface
in the
--allowedTools
and
--disallowedTools
CLI flags
in the Agent SDK’s
allowedTools
and
disallowedTools
options
in a
subagent’s
tools
or
disallowedTools
frontmatter
in a
skill’s
allowed-tools
frontmatter
in a hook’s
if
condition
All of these accept the same rule format,
ToolName(specifier)
. The specifier depends on the tool, and several tools share a format:
Rule format
Applies to
Details
Bash(npm run *)
Bash, Monitor
Command pattern matching
PowerShell(Get-ChildItem *)
PowerShell
Command pattern matching
Read(~/secrets/**)
Read, Grep, Glob, LSP
Path pattern matching
Edit(/src/**)
Edit, Write, NotebookEdit
Path pattern matching
Skill(deploy *)
Skill
Skill name matching
Agent(Explore)
Agent
Subagent type matching
WebFetch(domain:example.com)
WebFetch
Domain matching
WebSearch
WebSearch
No specifier; allow or deny the tool as a whole
Tools not listed here, such as
ExitPlanMode
or
ShareOnboardingGuide
, accept only the bare tool name with no specifier.
An
Edit(...)
allow rule also grants read access to the same path, so you do not need a matching
Read(...)
rule.
Hook
matcher
fields use bare tool names, not the parenthesized rule format. See
matcher patterns
for the matching rules. For the field names each tool passes to
tool_input
in hooks, see the
PreToolUse input reference
.
​
Agent tool behavior
The Agent tool spawns a subagent in a separate context window. The subagent works through its task autonomously, then returns a single text result to the parent conversation. The parent does not see the subagent’s intermediate tool calls or outputs, only that final result. To cap how many turns a subagent runs, set
maxTurns
in the
subagent definition
.
The same Agent tool also launches
forked subagents
when fork mode is enabled. A fork inherits the full parent conversation instead of starting fresh, always runs in the background, and still surfaces permission prompts in your terminal. The rest of this section describes named subagents.
Which tools a named subagent can use depends on the
tools
and
disallowedTools
fields in the
subagent definition
:
Neither field set
: the subagent inherits every tool available to the parent.
tools
only
: the subagent gets only the listed tools.
disallowedTools
only
: the subagent gets every parent tool except the listed ones.
Both set
:
disallowedTools
takes precedence. A tool listed in both is removed.
Launching the subagent does not itself prompt for permission. The subagent’s own tool calls are checked against your permission rules as it runs:
Foreground subagents
show the same permission prompts you would see in the main conversation, at the moment each tool call happens.
Background subagents
do not show prompts. They run with the permissions already granted in the session and auto-deny any tool call that would otherwise prompt. After a denial, the subagent keeps going without that tool.
To limit what a subagent can reach in the first place, narrow its
tools
field, leave Bash off the list, or set deny rules in your settings, as described in
Control subagent capabilities
. For more on choosing between foreground and background, see
Run subagents in foreground or background
.
​
Bash tool behavior
The Bash tool runs each command in a separate process with the following persistence behavior:
When Claude runs
cd
in the main session, the new working directory carries over to later Bash commands as long as it stays inside the project directory or an
additional working directory
you added with
--add-dir
,
/add-dir
, or
additionalDirectories
in settings. Subagent sessions never carry over working directory changes.
If
cd
lands outside those directories, Claude Code resets to the project directory and appends
Shell cwd was reset to <dir>
to the tool result.
To disable this carry-over so every Bash command starts in the project directory, set
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1
.
Environment variables do not persist. An
export
in one command will not be available in the next.
Activate your virtualenv or conda environment before launching Claude Code. To make environment variables persist across Bash commands, set
CLAUDE_ENV_FILE
to a shell script before launching Claude Code, or use a
SessionStart hook
to populate it dynamically.
Two limits bound each command:
Timeout
: two minutes by default. Claude can request up to 10 minutes per command with the
timeout
parameter. Override the default and ceiling with
BASH_DEFAULT_TIMEOUT_MS
and
BASH_MAX_TIMEOUT_MS
.
Output length
: 30,000 characters by default. When a command produces more than that, Claude Code saves the full output to a file in the session directory and gives Claude the file path plus a short preview from the start. Claude reads or searches that file when it needs the rest. Raise the limit with
BASH_MAX_OUTPUT_LENGTH
, up to a hard ceiling of 150,000 characters.
For long-running processes such as dev servers or watch builds, Claude can set
run_in_background: true
to start the command as a background task and continue working while it runs. List and stop background tasks with
/tasks
.
​
Edit tool behavior
The Edit tool performs exact string replacement. It takes an
old_string
and a
new_string
and replaces the first with the second. It does not use regex or fuzzy matching.
Three checks must pass for an edit to apply:
Read-before-edit
: Claude must have read the file in the current conversation, and the file must not have changed on disk since that read. This check runs first, before any string matching.
Match
:
old_string
must appear in the file exactly as written. A single character of whitespace or indentation difference is enough to miss.
Uniqueness
:
old_string
must appear exactly once. When it appears more than once, Claude either supplies a longer string with enough surrounding context to pin down one occurrence, or sets
replace_all: true
to replace them all.
Viewing a file with Bash also satisfies the read-before-edit requirement when the command is
cat path/to/file
or
sed -n 'X,Yp' path/to/file
on a single file with no pipes or redirects. Other Bash commands such as
head
,
tail
, or piped output do not count, and Claude must use Read before editing in those cases.
This affects edit eligibility only, not permissions.
Read and Edit deny rules
also apply to file commands Claude Code recognizes in Bash, such as
cat
,
head
,
tail
, and
sed
, but not to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that covers every process,
enable the sandbox
.
​
Glob tool behavior
The Glob tool finds files by name pattern. It supports standard glob syntax including
**
for recursive directory matching:
**/*.js
matches all
.js
files at any depth
src/**/*.ts
matches all
.ts
files under
src/
*.{json,yaml}
matches
.json
and
.yaml
files in the current directory
Results are sorted by modification time and capped at 100 files. If the cap is hit, Claude sees a truncation flag in the result and can narrow the pattern.
Glob does not respect
.gitignore
by default, so it finds gitignored files alongside tracked ones. This differs from
Grep
, which skips gitignored files. To make Glob respect
.gitignore
, set
CLAUDE_CODE_GLOB_NO_IGNORE=false
before launching Claude Code.
​
Grep tool behavior
The Grep tool searches file contents for patterns. Where
Glob
finds files by name, Grep finds lines inside them.
Grep is built on
ripgrep
and uses ripgrep’s regex syntax, not POSIX grep. Patterns that include regex metacharacters need escaping. For example, finding
interface{}
in Go code takes the pattern
interface\{\}
.
Three output modes control what comes back:
files_with_matches
: file paths only, no line content. This is the default.
content
: matching lines with file and line number.
count
: match count per file.
Claude can scope results by file with the
glob
parameter, such as
**/*.tsx
, or by language with the
type
parameter, such as
py
or
rust
. By default, patterns match within a single line. Claude can set
multiline: true
to match across line boundaries.
Grep respects
.gitignore
, so gitignored files are skipped. To search a gitignored file, Claude passes its path directly.
​
LSP tool behavior
The LSP tool gives Claude code intelligence from a running language server. After each file edit, it automatically reports type errors and warnings so Claude can fix issues without a separate build step. Claude can also call it directly to navigate code:
Jump to a symbol’s definition
Find all references to a symbol
Get type information at a position
List symbols in a file or workspace
Find implementations of an interface
Trace call hierarchies
The tool is inactive until you install a
code intelligence plugin
for your language. The plugin bundles the language server configuration, and you install the server binary separately.
​
Monitor tool
The Monitor tool requires Claude Code v2.1.98 or later.
The Monitor tool lets Claude watch something in the background and react when it changes, without pausing the conversation. Ask Claude to:
Tail a log file and flag errors as they appear
Poll a PR or CI job and report when its status changes
Watch a directory for file changes
Track output from any long-running script you point it at
Claude writes a small script for the watch, runs it in the background, and receives each output line as it arrives. You keep working in the same session and Claude interjects when an event lands. Stop a monitor by asking Claude to cancel it or by ending the session.
Monitor uses the same
permission rules as Bash
, so
allow
and
deny
patterns you have set for Bash apply here too. It is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. It is also not available when
DISABLE_TELEMETRY
or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set.
Plugins can declare monitors that start automatically when the plugin is active, instead of asking Claude to start them. See
plugin monitors
.
​
NotebookEdit tool behavior
NotebookEdit modifies a Jupyter notebook one cell at a time, targeting cells by their
cell_id
. It does not perform string replacement across the notebook the way
Edit
does on plain files.
Three edit modes control what happens to the target cell:
replace
: overwrite the cell’s source. This is the default.
insert
: add a new cell after the target. With no
cell_id
, the new cell goes at the start of the notebook. Requires
cell_type
set to
code
or
markdown
.
delete
: remove the target cell.
Permission rules use the
Edit(...)
path format. A rule like
Edit(notebooks/**)
covers NotebookEdit calls on files in that directory.
​
PowerShell tool
The PowerShell tool lets Claude run PowerShell commands natively. On Windows, this means commands run in PowerShell instead of routing through Git Bash. On Windows without Git Bash, the tool is enabled automatically. On Windows with Git Bash installed, the tool is rolling out progressively. On Linux, macOS, and WSL, the tool is opt-in.
​
Enable the PowerShell tool
Set
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
in your environment or in
settings.json
:
{
"env"
: {
"CLAUDE_CODE_USE_POWERSHELL_TOOL"
:
"1"
}
}
On Windows, set the variable to
0
to opt out of the rollout. On Linux, macOS, and WSL, the tool requires PowerShell 7 or later: install
pwsh
and ensure it is on your
PATH
.
On Windows, Claude Code auto-detects
pwsh.exe
for PowerShell 7+ with a fallback to
powershell.exe
for PowerShell 5.1. When the tool is enabled, Claude treats PowerShell as the primary shell. The Bash tool remains available for POSIX scripts when Git Bash is installed.
​
Shell selection in settings, hooks, and skills
Three additional settings control where PowerShell is used:
"defaultShell": "powershell"
in
settings.json
: routes interactive
!
commands through PowerShell. Requires the PowerShell tool to be enabled.
"shell": "powershell"
on individual
command hooks
: runs that hook in PowerShell. Hooks spawn PowerShell directly, so this works regardless of
CLAUDE_CODE_USE_POWERSHELL_TOOL
.
shell: powershell
in
skill frontmatter
: runs
!`command`
blocks in PowerShell. Requires the PowerShell tool to be enabled.
The same main-session working-directory reset behavior described under the Bash tool section applies to PowerShell commands, including the
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR
environment variable.
​
Preview limitations
The PowerShell tool has the following known limitations during the preview:
PowerShell profiles are not loaded
On Windows, sandboxing is not supported
​
Read tool behavior
The Read tool takes a file path and returns the contents with line numbers. Claude is instructed to always pass absolute paths.
By default, Read returns the file from the start. Files over a size threshold return an error rather than partial content, prompting Claude to retry with
offset
and
limit
to read a specific range.
Read handles several file types beyond plain text:
Images
: PNG, JPG, and other image formats are returned as visual content that Claude can see, not as raw bytes. Claude Code resizes and recompresses large images to fit the model’s image size limits before sending them, so Claude may see a downscaled version of a large screenshot. If Claude misses fine pixel-level detail in a large image, ask it to crop the region of interest first, for example with ImageMagick via Bash.
PDFs
: Claude reads short
.pdf
files whole. For PDFs longer than 10 pages, it reads in ranges with a
pages
parameter, such as
"1-5"
, up to 20 pages at a time.
Jupyter notebooks
:
.ipynb
files return all cells with their outputs, including code, markdown, and visualizations.
Read only reads files, not directories. Claude uses
ls
via the Bash tool to list directory contents.
​
WebFetch tool behavior
WebFetch takes a URL and a prompt describing what to extract. It fetches the page, converts the response to Markdown when the server returns HTML, and runs the prompt against the content using a small, fast model. For most fetches, Claude receives that model’s answer, not the raw page. The conversion step is not configurable.
This makes WebFetch lossy by design. The extraction prompt determines what reaches Claude, so a result that says a page does not mention something may only mean the prompt did not ask about it. Ask Claude to fetch again with a more specific prompt, or use
curl
via Bash for the unprocessed page.
A few behaviors shape the response Claude receives:
HTTP URLs are automatically upgraded to HTTPS.
Large pages are truncated to a fixed character limit before processing.
Responses are cached for 15 minutes, so repeated fetches of the same URL return quickly.
When a URL redirects to a different host, WebFetch returns a text result that names the original URL and the redirect target instead of following it. Claude then fetches the new URL with a second WebFetch call.
In the default and
acceptEdits
permission modes, WebFetch prompts the first time it reaches a new domain. To allow a domain in advance without a prompt, add a permission rule like
WebFetch(domain:example.com)
. The
auto
and
bypassPermissions
permission modes
skip the prompt entirely.
WebFetch sets a
User-Agent
header beginning with
Claude-User
, and an
Accept
header that prefers Markdown over HTML so servers that support content negotiation can return Markdown directly.
Sandbox
network rules are configured separately, so a domain you want a sandboxed process to reach still needs an explicit sandbox permission rule.
​
WebSearch tool behavior
WebSearch runs a query against Anthropic’s
web search
backend and returns result titles and URLs. It does not fetch the result pages. To read a page Claude finds in search results, it follows up with
WebFetch
.
The tool may issue up to eight backend searches per call, refining the search internally before returning results. Claude can scope results with
allowed_domains
to include only certain hosts, or
blocked_domains
to exclude them. The two lists cannot be combined in a single call.
The search backend is not configurable. To search with a different provider, add an
MCP server
that exposes a search tool.
WebSearch permission rules take no specifier. A bare
WebSearch
entry in
allow
or
deny
is the only form.
WebSearch is available on the Claude API and Microsoft Foundry. On Google Cloud Vertex AI it works with Claude 4 models, including Opus, Sonnet, and Haiku. Amazon Bedrock does not expose the server-side web search tool.
​
Write tool behavior
The Write tool creates a new file or overwrites an existing one with the full content provided. It does not append or merge.
If the target path already exists, Claude must have read that file at least once in the current conversation before overwriting it. A Write to an unread existing file fails with an error. This constraint does not apply to new files.
Viewing the file with Bash
cat
or
sed -n
also satisfies this requirement, as described in
Edit tool behavior
.
For partial changes to an existing file, Claude uses Edit instead of Write.
​
Check which tools are available
Your exact tool set depends on your provider, platform, and settings. To check what’s loaded in a running session, ask Claude directly:
What tools do you have access to?
Claude gives a conversational summary. For exact MCP tool names, run
/mcp
.
​
See also
MCP servers
: add custom tools by connecting external servers
Permissions
: permission system, rule syntax, and tool-specific patterns
Subagents
: configure tool access for subagents
Hooks
: run custom commands before or after tool execution
Was this page helpful?
Yes
No
Environment variables
Interactive mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/tools-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Tools reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code has access to a set of built-in tool...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Tools reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code has access to a set of built-in tools that help it understand and modify your codebase. The tool names are the exact strings you use in
permission rules
,
subagent tool lists
, and
hook matchers
. To disable a tool entirely, add its name to the
deny
array in your
permission settings
.
To add custom tools, connect an
MCP server
. To extend Claude with reusable prompt-based workflows, write a
skill
, which runs through the existing
Skill
tool rather than adding a new tool entry.
Tool
Description
Permission Required
Agent
Spawns a
subagent
with its own context window to handle a task. See
Agent tool behavior
No
AskUserQuestion
Asks multiple-choice questions to gather requirements or clarify ambiguity
No
Bash
Executes shell commands in your environment. See
Bash tool behavior
Yes
CronCreate
Schedules a recurring or one-shot prompt within the current session. Tasks are session-scoped and restored on
--resume
or
--continue
if unexpired. See
scheduled tasks
No
CronDelete
Cancels a scheduled task by ID
No
CronList
Lists all scheduled tasks in the session
No
Edit
Makes targeted edits to specific files. See
Edit tool behavior
Yes
EnterPlanMode
Switches to plan mode to design an approach before coding
No
EnterWorktree
Creates an isolated
git worktree
and switches into it. Pass a
path
to switch into an existing worktree of the current repository instead of creating a new one. Not available to subagents
No
ExitPlanMode
Presents a plan for approval and exits plan mode
Yes
ExitWorktree
Exits a worktree session and returns to the original directory. Not available to subagents
No
Glob
Finds files based on pattern matching. See
Glob tool behavior
No
Grep
Searches for patterns in file contents. See
Grep tool behavior
No
ListMcpResourcesTool
Lists resources exposed by connected
MCP servers
No
LSP
Code intelligence via language servers: jump to definitions, find references, report type errors and warnings. See
LSP tool behavior
No
Monitor
Runs a command in the background and feeds each output line back to Claude, so it can react to log entries, file changes, or polled status mid-conversation. See
Monitor tool
Yes
NotebookEdit
Modifies Jupyter notebook cells. See
NotebookEdit tool behavior
Yes
PowerShell
Executes PowerShell commands natively. See
PowerShell tool
for availability
Yes
PushNotification
Sends a desktop notification, and a phone push when
Remote Control
is connected, so a long-running task or
scheduled task
can reach you when you step away. Push delivery runs through Anthropic-hosted infrastructure, which is not accessible from Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
No
Read
Reads the contents of files. See
Read tool behavior
No
ReadMcpResourceTool
Reads a specific MCP resource by URI
No
RemoteTrigger
Creates, updates, runs, and lists
Routines
on claude.ai. Backs the
/schedule
command. Routines live on claude.ai and require a Pro, Max, Team, or Enterprise plan, so this tool is not accessible from Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
No
SendMessage
Sends a message to an
agent team
teammate, or
resumes a subagent
by its agent ID. Stopped subagents auto-resume in the background. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
ShareOnboardingGuide
Uploads
ONBOARDING.md
and returns a share link teammates can open in Claude Code. Called from
/team-onboarding
after the guide is written. Available to claude.ai subscribers on Pro, Max, Team, and Enterprise plans
Yes
Skill
Executes a
skill
within the main conversation
Yes
TaskCreate
Creates a new task in the task list
No
TaskGet
Retrieves full details for a specific task
No
TaskList
Lists all tasks with their current status
No
TaskOutput
(Deprecated) Retrieves output from a background task. Prefer
Read
on the task’s output file path
No
TaskStop
Kills a running background task by ID
No
TaskUpdate
Updates task status, dependencies, details, or deletes tasks
No
TeamCreate
Creates an
agent team
with multiple teammates. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
TeamDelete
Disbands an agent team and cleans up teammate processes. Only available when
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
is set
No
TodoWrite
Manages the session task checklist. Deprecated in favor of
TaskCreate
,
TaskGet
,
TaskList
, and
TaskUpdate
. Interactive sessions already use the Task tools by default. When you run
claude -p
or use the
Agent SDK
,
TodoWrite
is still the default. Set
CLAUDE_CODE_ENABLE_TASKS=1
to switch those to the Task tools before
TodoWrite
is removed
No
ToolSearch
Searches for and loads deferred tools when
tool search
is enabled
No
WebFetch
Fetches content from a specified URL. See
WebFetch tool behavior
Yes
WebSearch
Performs web searches. See
WebSearch tool behavior
Yes
Write
Creates or overwrites files. See
Write tool behavior
Yes
​
Configure tools with permission rules and hooks
For the most part, Claude decides when to use these tools and you do not need to name them yourself when interacting with Claude. You reference tool names directly when defining permissions and other configuration:
in
permissions.allow
and
permissions.deny
in settings, and the
/permissions
interface
in the
--allowedTools
and
--disallowedTools
CLI flags
in the Agent SDK’s
allowedTools
and
disallowedTools
options
in a
subagent’s
tools
or
disallowedTools
frontmatter
in a
skill’s
allowed-tools
frontmatter
in a hook’s
if
condition
All of these accept the same rule format,
ToolName(specifier)
. The specifier depends on the tool, and several tools share a format:
Rule format
Applies to
Details
Bash(npm run *)
Bash, Monitor
Command pattern matching
PowerShell(Get-ChildItem *)
PowerShell
Command pattern matching
Read(~/secrets/**)
Read, Grep, Glob, LSP
Path pattern matching
Edit(/src/**)
Edit, Write, NotebookEdit
Path pattern matching
Skill(deploy *)
Skill
Skill name matching
Agent(Explore)
Agent
Subagent type matching
WebFetch(domain:example.com)
WebFetch
Domain matching
WebSearch
WebSearch
No specifier; allow or deny the tool as a whole
Tools not listed here, such as
ExitPlanMode
or
ShareOnboardingGuide
, accept only the bare tool name with no specifier.
An
Edit(...)
allow rule also grants read access to the same path, so you do not need a matching
Read(...)
rule.
Hook
matcher
fields use bare tool names, not the parenthesized rule format. See
matcher patterns
for the matching rules. For the field names each tool passes to
tool_input
in hooks, see the
PreToolUse input reference
.
​
Agent tool behavior
The Agent tool spawns a subagent in a separate context window. The subagent works through its task autonomously, then returns a single text result to the parent conversation. The parent does not see the subagent’s intermediate tool calls or outputs, only that final result. To cap how many turns a subagent runs, set
maxTurns
in the
subagent definition
.
The same Agent tool also launches
forked subagents
when fork mode is enabled. A fork inherits the full parent conversation instead of starting fresh, always runs in the background, and still surfaces permission prompts in your terminal. The rest of this section describes named subagents.
Which tools a named subagent can use depends on the
tools
and
disallowedTools
fields in the
subagent definition
:
Neither field set
: the subagent inherits every tool available to the parent.
tools
only
: the subagent gets only the listed tools.
disallowedTools
only
: the subagent gets every parent tool except the listed ones.
Both set
:
disallowedTools
takes precedence. A tool listed in both is removed.
Launching the subagent does not itself prompt for permission. The subagent’s own tool calls are checked against your permission rules as it runs:
Foreground subagents
show the same permission prompts you would see in the main conversation, at the moment each tool call happens.
Background subagents
do not show prompts. They run with the permissions already granted in the session and auto-deny any tool call that would otherwise prompt. After a denial, the subagent keeps going without that tool.
To limit what a subagent can reach in the first place, narrow its
tools
field, leave Bash off the list, or set deny rules in your settings, as described in
Control subagent capabilities
. For more on choosing between foreground and background, see
Run subagents in foreground or background
.
​
Bash tool behavior
The Bash tool runs each command in a separate process with the following persistence behavior:
When Claude runs
cd
in the main session, the new working directory carries over to later Bash commands as long as it stays inside the project directory or an
additional working directory
you added with
--add-dir
,
/add-dir
, or
additionalDirectories
in settings. Subagent sessions never carry over working directory changes.
If
cd
lands outside those directories, Claude Code resets to the project directory and appends
Shell cwd was reset to <dir>
to the tool result.
To disable this carry-over so every Bash command starts in the project directory, set
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1
.
Environment variables do not persist. An
export
in one command will not be available in the next.
Activate your virtualenv or conda environment before launching Claude Code. To make environment variables persist across Bash commands, set
CLAUDE_ENV_FILE
to a shell script before launching Claude Code, or use a
SessionStart hook
to populate it dynamically.
Two limits bound each command:
Timeout
: two minutes by default. Claude can request up to 10 minutes per command with the
timeout
parameter. Override the default and ceiling with
BASH_DEFAULT_TIMEOUT_MS
and
BASH_MAX_TIMEOUT_MS
.
Output length
: 30,000 characters by default. When a command produces more than that, Claude Code saves the full output to a file in the session directory and gives Claude the file path plus a short preview from the start. Claude reads or searches that file when it needs the rest. Raise the limit with
BASH_MAX_OUTPUT_LENGTH
, up to a hard ceiling of 150,000 characters.
For long-running processes such as dev servers or watch builds, Claude can set
run_in_background: true
to start the command as a background task and continue working while it runs. List and stop background tasks with
/tasks
.
​
Edit tool behavior
The Edit tool performs exact string replacement. It takes an
old_string
and a
new_string
and replaces the first with the second. It does not use regex or fuzzy matching.
Three checks must pass for an edit to apply:
Read-before-edit
: Claude must have read the file in the current conversation, and the file must not have changed on disk since that read. This check runs first, before any string matching.
Match
:
old_string
must appear in the file exactly as written. A single character of whitespace or indentation difference is enough to miss.
Uniqueness
:
old_string
must appear exactly once. When it appears more than once, Claude either supplies a longer string with enough surrounding context to pin down one occurrence, or sets
replace_all: true
to replace them all.
Viewing a file with Bash also satisfies the read-before-edit requirement when the command is
cat path/to/file
or
sed -n 'X,Yp' path/to/file
on a single file with no pipes or redirects. Other Bash commands such as
head
,
tail
, or piped output do not count, and Claude must use Read before editing in those cases.
This affects edit eligibility only, not permissions.
Read and Edit deny rules
also apply to file commands Claude Code recognizes in Bash, such as
cat
,
head
,
tail
, and
sed
, but not to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that covers every process,
enable the sandbox
.
​
Glob tool behavior
The Glob tool finds files by name pattern. It supports standard glob syntax including
**
for recursive directory matching:
**/*.js
matches all
.js
files at any depth
src/**/*.ts
matches all
.ts
files under
src/
*.{json,yaml}
matches
.json
and
.yaml
files in the current directory
Results are sorted by modification time and capped at 100 files. If the cap is hit, Claude sees a truncation flag in the result and can narrow the pattern.
Glob does not respect
.gitignore
by default, so it finds gitignored files alongside tracked ones. This differs from
Grep
, which skips gitignored files. To make Glob respect
.gitignore
, set
CLAUDE_CODE_GLOB_NO_IGNORE=false
before launching Claude Code.
​
Grep tool behavior
The Grep tool searches file contents for patterns. Where
Glob
finds files by name, Grep finds lines inside them.
Grep is built on
ripgrep
and uses ripgrep’s regex syntax, not POSIX grep. Patterns that include regex metacharacters need escaping. For example, finding
interface{}
in Go code takes the pattern
interface\{\}
.
Three output modes control what comes back:
files_with_matches
: file paths only, no line content. This is the default.
content
: matching lines with file and line number.
count
: match count per file.
Claude can scope results by file with the
glob
parameter, such as
**/*.tsx
, or by language with the
type
parameter, such as
py
or
rust
. By default, patterns match within a single line. Claude can set
multiline: true
to match across line boundaries.
Grep respects
.gitignore
, so gitignored files are skipped. To search a gitignored file, Claude passes its path directly.
​
LSP tool behavior
The LSP tool gives Claude code intelligence from a running language server. After each file edit, it automatically reports type errors and warnings so Claude can fix issues without a separate build step. Claude can also call it directly to navigate code:
Jump to a symbol’s definition
Find all references to a symbol
Get type information at a position
List symbols in a file or workspace
Find implementations of an interface
Trace call hierarchies
The tool is inactive until you install a
code intelligence plugin
for your language. The plugin bundles the language server configuration, and you install the server binary separately.
​
Monitor tool
The Monitor tool requires Claude Code v2.1.98 or later.
The Monitor tool lets Claude watch something in the background and react when it changes, without pausing the conversation. Ask Claude to:
Tail a log file and flag errors as they appear
Poll a PR or CI job and report when its status changes
Watch a directory for file changes
Track output from any long-running script you point it at
Claude writes a small script for the watch, runs it in the background, and receives each output line as it arrives. You keep working in the same session and Claude interjects when an event lands. Stop a monitor by asking Claude to cancel it or by ending the session.
Monitor uses the same
permission rules as Bash
, so
allow
and
deny
patterns you have set for Bash apply here too. It is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. It is also not available when
DISABLE_TELEMETRY
or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
is set.
Plugins can declare monitors that start automatically when the plugin is active, instead of asking Claude to start them. See
plugin monitors
.
​
NotebookEdit tool behavior
NotebookEdit modifies a Jupyter notebook one cell at a time, targeting cells by their
cell_id
. It does not perform string replacement across the notebook the way
Edit
does on plain files.
Three edit modes control what happens to the target cell:
replace
: overwrite the cell’s source. This is the default.
insert
: add a new cell after the target. With no
cell_id
, the new cell goes at the start of the notebook. Requires
cell_type
set to
code
or
markdown
.
delete
: remove the target cell.
Permission rules use the
Edit(...)
path format. A rule like
Edit(notebooks/**)
covers NotebookEdit calls on files in that directory.
​
PowerShell tool
The PowerShell tool lets Claude run PowerShell commands natively. On Windows, this means commands run in PowerShell instead of routing through Git Bash. On Windows without Git Bash, the tool is enabled automatically. On Windows with Git Bash installed, the tool is rolling out progressively. On Linux, macOS, and WSL, the tool is opt-in.
​
Enable the PowerShell tool
Set
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
in your environment or in
settings.json
:
{
"env"
: {
"CLAUDE_CODE_USE_POWERSHELL_TOOL"
:
"1"
}
}
On Windows, set the variable to
0
to opt out of the rollout. On Linux, macOS, and WSL, the tool requires PowerShell 7 or later: install
pwsh
and ensure it is on your
PATH
.
On Windows, Claude Code auto-detects
pwsh.exe
for PowerShell 7+ with a fallback to
powershell.exe
for PowerShell 5.1. When the tool is enabled, Claude treats PowerShell as the primary shell. The Bash tool remains available for POSIX scripts when Git Bash is installed.
​
Shell selection in settings, hooks, and skills
Three additional settings control where PowerShell is used:
"defaultShell": "powershell"
in
settings.json
: routes interactive
!
commands through PowerShell. Requires the PowerShell tool to be enabled.
"shell": "powershell"
on individual
command hooks
: runs that hook in PowerShell. Hooks spawn PowerShell directly, so this works regardless of
CLAUDE_CODE_USE_POWERSHELL_TOOL
.
shell: powershell
in
skill frontmatter
: runs
!`command`
blocks in PowerShell. Requires the PowerShell tool to be enabled.
The same main-session working-directory reset behavior described under the Bash tool section applies to PowerShell commands, including the
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR
environment variable.
​
Preview limitations
The PowerShell tool has the following known limitations during the preview:
PowerShell profiles are not loaded
On Windows, sandboxing is not supported
​
Read tool behavior
The Read tool takes a file path and returns the contents with line numbers. Claude is instructed to always pass absolute paths.
By default, Read returns the file from the start. Files over a size threshold return an error rather than partial content, prompting Claude to retry with
offset
and
limit
to read a specific range.
Read handles several file types beyond plain text:
Images
: PNG, JPG, and other image formats are returned as visual content that Claude can see, not as raw bytes. Claude Code resizes and recompresses large images to fit the model’s image size limits before sending them, so Claude may see a downscaled version of a large screenshot. If Claude misses fine pixel-level detail in a large image, ask it to crop the region of interest first, for example with ImageMagick via Bash.
PDFs
: Claude reads short
.pdf
files whole. For PDFs longer than 10 pages, it reads in ranges with a
pages
parameter, such as
"1-5"
, up to 20 pages at a time.
Jupyter notebooks
:
.ipynb
files return all cells with their outputs, including code, markdown, and visualizations.
Read only reads files, not directories. Claude uses
ls
via the Bash tool to list directory contents.
​
WebFetch tool behavior
WebFetch takes a URL and a prompt describing what to extract. It fetches the page, converts the response to Markdown when the server returns HTML, and runs the prompt against the content using a small, fast model. For most fetches, Claude receives that model’s answer, not the raw page. The conversion step is not configurable.
This makes WebFetch lossy by design. The extraction prompt determines what reaches Claude, so a result that says a page does not mention something may only mean the prompt did not ask about it. Ask Claude to fetch again with a more specific prompt, or use
curl
via Bash for the unprocessed page.
A few behaviors shape the response Claude receives:
HTTP URLs are automatically upgraded to HTTPS.
Large pages are truncated to a fixed character limit before processing.
Responses are cached for 15 minutes, so repeated fetches of the same URL return quickly.
When a URL redirects to a different host, WebFetch returns a text result that names the original URL and the redirect target instead of following it. Claude then fetches the new URL with a second WebFetch call.
In the default and
acceptEdits
permission modes, WebFetch prompts the first time it reaches a new domain. To allow a domain in advance without a prompt, add a permission rule like
WebFetch(domain:example.com)
. The
auto
and
bypassPermissions
permission modes
skip the prompt entirely.
WebFetch sets a
User-Agent
header beginning with
Claude-User
, and an
Accept
header that prefers Markdown over HTML so servers that support content negotiation can return Markdown directly.
Sandbox
network rules are configured separately, so a domain you want a sandboxed process to reach still needs an explicit sandbox permission rule.
​
WebSearch tool behavior
WebSearch runs a query against Anthropic’s
web search
backend and returns result titles and URLs. It does not fetch the result pages. To read a page Claude finds in search results, it follows up with
WebFetch
.
The tool may issue up to eight backend searches per call, refining the search internally before returning results. Claude can scope results with
allowed_domains
to include only certain hosts, or
blocked_domains
to exclude them. The two lists cannot be combined in a single call.
The search backend is not configurable. To search with a different provider, add an
MCP server
that exposes a search tool.
WebSearch permission rules take no specifier. A bare
WebSearch
entry in
allow
or
deny
is the only form.
WebSearch is available on the Claude API and Microsoft Foundry. On Google Cloud Vertex AI it works with Claude 4 models, including Opus, Sonnet, and Haiku. Amazon Bedrock does not expose the server-side web search tool.
​
Write tool behavior
The Write tool creates a new file or overwrites an existing one with the full content provided. It does not append or merge.
If the target path already exists, Claude must have read that file at least once in the current conversation before overwriting it. A Write to an unread existing file fails with an error. This constraint does not apply to new files.
Viewing the file with Bash
cat
or
sed -n
also satisfies this requirement, as described in
Edit tool behavior
.
For partial changes to an existing file, Claude uses Edit instead of Write.
​
Check which tools are available
Your exact tool set depends on your provider, platform, and settings. To check what’s loaded in a running session, ask Claude directly:
What tools do you have access to?
Claude gives a conversational summary. For exact MCP tool names, run
/mcp
.
​
See also
MCP servers
: add custom tools by connecting external servers
Permissions
: permission system, rule syntax, and tool-specific patterns
Subagents
: configure tool access for subagents
Hooks
: run custom commands before or after tool execution
Was this page helpful?
Yes
No
Environment variables
Interactive mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/tools-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Configure auto mode</title>
  <link>https://code.claude.com/docs/en/auto-mode-config</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/auto-mode-config</guid>
  <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
  <category>Configuration</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure auto mode
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure auto mode
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Auto mode
lets Claude Code run without permission prompts by routing each tool call through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Use the
autoMode
settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.
Auto mode is available on Max, Team, Enterprise, and API plans through the Anthropic API. It is not available on Pro or on Bedrock, Vertex, or Foundry. If Claude Code reports auto mode as unavailable for your account, check the
full requirements
, which also cover the supported models and admin enablement on Team and Enterprise plans.
Out of the box, the classifier trusts only the working directory and the current repo’s configured remotes. Actions like pushing to your company’s source-control org or writing to a team cloud bucket are blocked until you add them to
autoMode.environment
.
For how to enable auto mode and what it blocks by default, see
Permission modes
. This page is the configuration reference.
This page covers how to:
Choose where to set rules
across CLAUDE.md, user settings, and managed settings
Define trusted infrastructure
with
autoMode.environment
Override the block and allow rules
when the defaults don’t fit your pipeline
Inspect your effective config
with the
claude auto-mode
subcommands
Review denials
so you know what to add next
​
Where the classifier reads configuration
The classifier reads the same
CLAUDE.md
content Claude itself loads, so an instruction like “never force push” in your project’s CLAUDE.md steers both Claude and the classifier at the same time. Start there for project conventions and behavioral rules.
For rules that apply across projects, such as trusted infrastructure or organization-wide deny rules, use the
autoMode
settings block. The classifier reads
autoMode
from the following scopes:
Scope
File
Use for
One developer
~/.claude/settings.json
Personal trusted infrastructure
One project, one developer
.claude/settings.local.json
Per-project trusted buckets or services, gitignored
Organization-wide
Managed settings
Trusted infrastructure distributed to all developers
--settings
flag or Agent SDK
Inline JSON
Per-invocation overrides for automation
The classifier does not read
autoMode
from shared project settings in
.claude/settings.json
, so a checked-in repo cannot inject its own allow rules.
Entries from each scope are combined. A developer can extend
environment
,
allow
,
soft_deny
, and
hard_deny
with personal entries but cannot remove entries that managed settings provide. Because allow rules act as exceptions to soft block rules inside the classifier, a developer-added
allow
entry can override an organization
soft_deny
entry: the combination is additive, not a hard policy boundary.
The classifier is a second gate that runs after the
permissions system
. For actions that must never run regardless of user intent or classifier configuration, use
permissions.deny
in managed settings, which blocks the action before the classifier is consulted and cannot be overridden.
​
Define trusted infrastructure
For most organizations,
autoMode.environment
is the only field you need to set. It tells the classifier which repos, buckets, and domains are trusted: the classifier uses it to decide what “external” means, so any destination not listed is a potential exfiltration target.
The default environment list trusts the working repo and its configured remotes. To add your own entries alongside that default, include the literal string
"$defaults"
in the array. The default entries are spliced in at that position, so your custom entries can go before or after them.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Source control: github.example.com/acme-corp and all repos under it"
,
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets"
,
"Trusted internal domains: *.corp.example.com, api.internal.example.com"
,
"Key internal services: Jenkins at ci.example.com, Artifactory at artifacts.example.com"
]
}
}
Entries are prose, not regex or tool patterns. The classifier reads them as natural-language rules. Write them the way you would describe your infrastructure to a new engineer. A thorough environment section covers:
Organization
: your company name and what Claude Code is primarily used for, like software development, infrastructure automation, or data engineering
Source control
: every GitHub, GitLab, or Bitbucket org your developers push to
Cloud providers and trusted buckets
: bucket names or prefixes that Claude should be able to read from and write to
Trusted internal domains
: hostnames for APIs, dashboards, and services inside your network, like
*.internal.example.com
Key internal services
: CI, artifact registries, internal package indexes, incident tooling
Additional context
: regulated-industry constraints, multi-tenant infrastructure, or compliance requirements that affect what the classifier should treat as risky
A useful starting template: fill in the bracketed fields and remove any lines that don’t apply.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Organization: {COMPANY_NAME}. Primary use: {PRIMARY_USE_CASE, e.g. software development, infrastructure automation}"
,
"Source control: {SOURCE_CONTROL, e.g. GitHub org github.example.com/acme-corp}"
,
"Cloud provider(s): {CLOUD_PROVIDERS, e.g. AWS, GCP, Azure}"
,
"Trusted cloud buckets: {TRUSTED_BUCKETS, e.g. s3://acme-builds, gs://acme-datasets}"
,
"Trusted internal domains: {TRUSTED_DOMAINS, e.g. *.internal.example.com, api.example.com}"
,
"Key internal services: {SERVICES, e.g. Jenkins at ci.example.com, Artifactory at artifacts.example.com}"
,
"Additional context: {EXTRA, e.g. regulated industry, multi-tenant infrastructure, compliance requirements}"
]
}
}
The more specific context you give, the better the classifier can distinguish routine internal operations from exfiltration attempts.
You don’t need to fill everything in at once. A reasonable rollout: start with the defaults and add your source control org and key internal services, which resolves the most common false positives like pushing to your own repos. Add trusted domains and cloud buckets next. Fill the rest as blocks come up.
​
Override the block and allow rules
Three additional fields let you replace the classifier’s built-in rule lists:
autoMode.hard_deny
for unconditional security boundaries,
autoMode.soft_deny
for destructive actions that user intent can clear, and
autoMode.allow
for exceptions. Each is an array of prose descriptions, read as natural-language rules. For tool-pattern-based hard blocks that run before the classifier, use
permissions.deny
.
Inside the classifier, precedence works in four tiers:
hard_deny
rules block unconditionally. User intent and
allow
exceptions do not apply.
soft_deny
rules block next. User intent and
allow
exceptions can override these.
allow
rules then override matching
soft_deny
rules as exceptions.
Explicit user intent overrides the remaining soft blocks: if the user’s message directly and specifically describes the exact action Claude is about to take, the classifier allows it even when a
soft_deny
rule matches.
General requests don’t count as explicit intent. Asking Claude to “clean up the repo” does not authorize force-pushing, but asking Claude to “force-push this branch” does.
To loosen, add to
allow
when the classifier repeatedly flags a routine pattern the default exceptions don’t cover. To tighten, add to
soft_deny
for destructive risks specific to your environment that the defaults miss, or to
hard_deny
for security boundaries that must never be crossed. To keep the built-in rules while adding your own, include the literal string
"$defaults"
in the array. The default rules are spliced in at that position, so your custom rules can go before or after them, and you continue to inherit updates as the built-in list changes across releases.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Source control: github.example.com/acme-corp and all repos under it"
],
"allow"
: [
"$defaults"
,
"Deploying to the staging namespace is allowed: staging is isolated from production and resets nightly"
,
"Writing to s3://acme-scratch/ is allowed: ephemeral bucket with a 7-day lifecycle policy"
],
"soft_deny"
: [
"$defaults"
,
"Never run database migrations outside the migrations CLI, even against dev databases"
,
"Never modify files under infra/terraform/prod/: production infrastructure changes go through the review workflow"
],
"hard_deny"
: [
"$defaults"
,
"Never send repository contents to third-party code-review APIs"
]
}
}
Setting any of
environment
,
allow
,
soft_deny
, or
hard_deny
without
"$defaults"
replaces the entire default list for that section. A
soft_deny
array without
"$defaults"
discards every built-in soft block rule, including force push,
curl | bash
, and production deploys. A
hard_deny
array without
"$defaults"
discards the built-in data exfiltration and safety-check bypass rules.
Each section is evaluated independently, so setting
environment
alone leaves the default
allow
,
soft_deny
, and
hard_deny
lists intact. Only omit
"$defaults"
when you intend to take full ownership of the list. To do that safely, run
claude auto-mode defaults
to print the built-in rules, copy them into your settings file, then review each rule against your own pipeline and risk tolerance.
​
Inspect the defaults and your effective config
Three CLI subcommands help you inspect and validate your configuration.
Print the built-in
environment
,
allow
,
soft_deny
, and
hard_deny
rules as JSON:
claude
auto-mode
defaults
Print what the classifier actually uses as JSON, with your settings applied where set and defaults otherwise:
claude
auto-mode
config
Get AI feedback on your custom
allow
,
soft_deny
, and
hard_deny
rules:
claude
auto-mode
critique
Run
claude auto-mode config
after saving your settings to confirm the effective rules are what you expect, with
"$defaults"
expanded in place. If you’ve written custom rules,
claude auto-mode critique
reviews them and flags entries that are ambiguous, redundant, or likely to cause false positives. If you need to remove or rewrite a built-in rule rather than add alongside it, save the output of
claude auto-mode defaults
to a file, edit the lists, and paste the result into your settings file in place of
"$defaults"
.
​
Review denials
When auto mode denies a tool call, the denial is recorded in
/permissions
under the Recently denied tab. Press
r
on a denied action to mark it for retry: when you exit the dialog, Claude Code sends a message telling the model it may retry that tool call and resumes the conversation.
Repeated denials for the same destination usually mean the classifier is missing context. Add that destination to
autoMode.environment
, then run
claude auto-mode config
to confirm it took effect.
To react to denials programmatically, use the
PermissionDenied
hook
.
​
See also
Permission modes
: what auto mode is, what it blocks by default, and how to enable it
Managed settings
: deploy
autoMode
configuration across your organization
Permissions
: allow, ask, and deny rules that apply before the classifier runs
Settings
: the full settings reference, including the
autoMode
key
Was this page helpful?
Yes
No
Server-managed settings
Overview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/auto-mode-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure auto mode
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Configure auto mode
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Auto mode
lets Claude Code run without permission prompts by routing each tool call through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Use the
autoMode
settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.
Auto mode is available on Max, Team, Enterprise, and API plans through the Anthropic API. It is not available on Pro or on Bedrock, Vertex, or Foundry. If Claude Code reports auto mode as unavailable for your account, check the
full requirements
, which also cover the supported models and admin enablement on Team and Enterprise plans.
Out of the box, the classifier trusts only the working directory and the current repo’s configured remotes. Actions like pushing to your company’s source-control org or writing to a team cloud bucket are blocked until you add them to
autoMode.environment
.
For how to enable auto mode and what it blocks by default, see
Permission modes
. This page is the configuration reference.
This page covers how to:
Choose where to set rules
across CLAUDE.md, user settings, and managed settings
Define trusted infrastructure
with
autoMode.environment
Override the block and allow rules
when the defaults don’t fit your pipeline
Inspect your effective config
with the
claude auto-mode
subcommands
Review denials
so you know what to add next
​
Where the classifier reads configuration
The classifier reads the same
CLAUDE.md
content Claude itself loads, so an instruction like “never force push” in your project’s CLAUDE.md steers both Claude and the classifier at the same time. Start there for project conventions and behavioral rules.
For rules that apply across projects, such as trusted infrastructure or organization-wide deny rules, use the
autoMode
settings block. The classifier reads
autoMode
from the following scopes:
Scope
File
Use for
One developer
~/.claude/settings.json
Personal trusted infrastructure
One project, one developer
.claude/settings.local.json
Per-project trusted buckets or services, gitignored
Organization-wide
Managed settings
Trusted infrastructure distributed to all developers
--settings
flag or Agent SDK
Inline JSON
Per-invocation overrides for automation
The classifier does not read
autoMode
from shared project settings in
.claude/settings.json
, so a checked-in repo cannot inject its own allow rules.
Entries from each scope are combined. A developer can extend
environment
,
allow
,
soft_deny
, and
hard_deny
with personal entries but cannot remove entries that managed settings provide. Because allow rules act as exceptions to soft block rules inside the classifier, a developer-added
allow
entry can override an organization
soft_deny
entry: the combination is additive, not a hard policy boundary.
The classifier is a second gate that runs after the
permissions system
. For actions that must never run regardless of user intent or classifier configuration, use
permissions.deny
in managed settings, which blocks the action before the classifier is consulted and cannot be overridden.
​
Define trusted infrastructure
For most organizations,
autoMode.environment
is the only field you need to set. It tells the classifier which repos, buckets, and domains are trusted: the classifier uses it to decide what “external” means, so any destination not listed is a potential exfiltration target.
The default environment list trusts the working repo and its configured remotes. To add your own entries alongside that default, include the literal string
"$defaults"
in the array. The default entries are spliced in at that position, so your custom entries can go before or after them.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Source control: github.example.com/acme-corp and all repos under it"
,
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets"
,
"Trusted internal domains: *.corp.example.com, api.internal.example.com"
,
"Key internal services: Jenkins at ci.example.com, Artifactory at artifacts.example.com"
]
}
}
Entries are prose, not regex or tool patterns. The classifier reads them as natural-language rules. Write them the way you would describe your infrastructure to a new engineer. A thorough environment section covers:
Organization
: your company name and what Claude Code is primarily used for, like software development, infrastructure automation, or data engineering
Source control
: every GitHub, GitLab, or Bitbucket org your developers push to
Cloud providers and trusted buckets
: bucket names or prefixes that Claude should be able to read from and write to
Trusted internal domains
: hostnames for APIs, dashboards, and services inside your network, like
*.internal.example.com
Key internal services
: CI, artifact registries, internal package indexes, incident tooling
Additional context
: regulated-industry constraints, multi-tenant infrastructure, or compliance requirements that affect what the classifier should treat as risky
A useful starting template: fill in the bracketed fields and remove any lines that don’t apply.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Organization: {COMPANY_NAME}. Primary use: {PRIMARY_USE_CASE, e.g. software development, infrastructure automation}"
,
"Source control: {SOURCE_CONTROL, e.g. GitHub org github.example.com/acme-corp}"
,
"Cloud provider(s): {CLOUD_PROVIDERS, e.g. AWS, GCP, Azure}"
,
"Trusted cloud buckets: {TRUSTED_BUCKETS, e.g. s3://acme-builds, gs://acme-datasets}"
,
"Trusted internal domains: {TRUSTED_DOMAINS, e.g. *.internal.example.com, api.example.com}"
,
"Key internal services: {SERVICES, e.g. Jenkins at ci.example.com, Artifactory at artifacts.example.com}"
,
"Additional context: {EXTRA, e.g. regulated industry, multi-tenant infrastructure, compliance requirements}"
]
}
}
The more specific context you give, the better the classifier can distinguish routine internal operations from exfiltration attempts.
You don’t need to fill everything in at once. A reasonable rollout: start with the defaults and add your source control org and key internal services, which resolves the most common false positives like pushing to your own repos. Add trusted domains and cloud buckets next. Fill the rest as blocks come up.
​
Override the block and allow rules
Three additional fields let you replace the classifier’s built-in rule lists:
autoMode.hard_deny
for unconditional security boundaries,
autoMode.soft_deny
for destructive actions that user intent can clear, and
autoMode.allow
for exceptions. Each is an array of prose descriptions, read as natural-language rules. For tool-pattern-based hard blocks that run before the classifier, use
permissions.deny
.
Inside the classifier, precedence works in four tiers:
hard_deny
rules block unconditionally. User intent and
allow
exceptions do not apply.
soft_deny
rules block next. User intent and
allow
exceptions can override these.
allow
rules then override matching
soft_deny
rules as exceptions.
Explicit user intent overrides the remaining soft blocks: if the user’s message directly and specifically describes the exact action Claude is about to take, the classifier allows it even when a
soft_deny
rule matches.
General requests don’t count as explicit intent. Asking Claude to “clean up the repo” does not authorize force-pushing, but asking Claude to “force-push this branch” does.
To loosen, add to
allow
when the classifier repeatedly flags a routine pattern the default exceptions don’t cover. To tighten, add to
soft_deny
for destructive risks specific to your environment that the defaults miss, or to
hard_deny
for security boundaries that must never be crossed. To keep the built-in rules while adding your own, include the literal string
"$defaults"
in the array. The default rules are spliced in at that position, so your custom rules can go before or after them, and you continue to inherit updates as the built-in list changes across releases.
{
"autoMode"
: {
"environment"
: [
"$defaults"
,
"Source control: github.example.com/acme-corp and all repos under it"
],
"allow"
: [
"$defaults"
,
"Deploying to the staging namespace is allowed: staging is isolated from production and resets nightly"
,
"Writing to s3://acme-scratch/ is allowed: ephemeral bucket with a 7-day lifecycle policy"
],
"soft_deny"
: [
"$defaults"
,
"Never run database migrations outside the migrations CLI, even against dev databases"
,
"Never modify files under infra/terraform/prod/: production infrastructure changes go through the review workflow"
],
"hard_deny"
: [
"$defaults"
,
"Never send repository contents to third-party code-review APIs"
]
}
}
Setting any of
environment
,
allow
,
soft_deny
, or
hard_deny
without
"$defaults"
replaces the entire default list for that section. A
soft_deny
array without
"$defaults"
discards every built-in soft block rule, including force push,
curl | bash
, and production deploys. A
hard_deny
array without
"$defaults"
discards the built-in data exfiltration and safety-check bypass rules.
Each section is evaluated independently, so setting
environment
alone leaves the default
allow
,
soft_deny
, and
hard_deny
lists intact. Only omit
"$defaults"
when you intend to take full ownership of the list. To do that safely, run
claude auto-mode defaults
to print the built-in rules, copy them into your settings file, then review each rule against your own pipeline and risk tolerance.
​
Inspect the defaults and your effective config
Three CLI subcommands help you inspect and validate your configuration.
Print the built-in
environment
,
allow
,
soft_deny
, and
hard_deny
rules as JSON:
claude
auto-mode
defaults
Print what the classifier actually uses as JSON, with your settings applied where set and defaults otherwise:
claude
auto-mode
config
Get AI feedback on your custom
allow
,
soft_deny
, and
hard_deny
rules:
claude
auto-mode
critique
Run
claude auto-mode config
after saving your settings to confirm the effective rules are what you expect, with
"$defaults"
expanded in place. If you’ve written custom rules,
claude auto-mode critique
reviews them and flags entries that are ambiguous, redundant, or likely to cause false positives. If you need to remove or rewrite a built-in rule rather than add alongside it, save the output of
claude auto-mode defaults
to a file, edit the lists, and paste the result into your settings file in place of
"$defaults"
.
​
Review denials
When auto mode denies a tool call, the denial is recorded in
/permissions
under the Recently denied tab. Press
r
on a denied action to mark it for retry: when you exit the dialog, Claude Code sends a message telling the model it may retry that tool call and resumes the conversation.
Repeated denials for the same destination usually mean the classifier is missing context. Add that destination to
autoMode.environment
, then run
claude auto-mode config
to confirm it took effect.
To react to denials programmatically, use the
PermissionDenied
hook
.
​
See also
Permission modes
: what auto mode is, what it blocks by default, and how to enable it
Managed settings
: deploy
autoMode
configuration across your organization
Permissions
: allow, ask, and deny rules that apply before the classifier runs
Settings
: the full settings reference, including the
autoMode
key
Was this page helpful?
Yes
No
Server-managed settings
Overview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/auto-mode-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code on Microsoft Foundry</title>
  <link>https://code.claude.com/docs/en/microsoft-foundry</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/microsoft-foundry</guid>
  <pubDate>Sun, 02 Jun 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Microsoft Foundry
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marke...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Microsoft Foundry
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Microsoft Foundry, ensure you have:
An Azure subscription with access to Microsoft Foundry
RBAC permissions to create Microsoft Foundry resources and deployments
Azure CLI installed and configured (optional - only needed if you don’t have another mechanism for getting credentials)
If you are deploying Claude Code to multiple users,
pin your model versions
to prevent breakage when Anthropic releases new models.
​
Setup
​
1. Provision Microsoft Foundry resource
First, create a Claude resource in Azure:
Navigate to the
Microsoft Foundry portal
Create a new resource, noting your resource name
Create deployments for the Claude models:
Claude Opus
Claude Sonnet
Claude Haiku
​
2. Configure Azure credentials
Claude Code supports two authentication methods for Microsoft Foundry. Choose the method that best fits your security requirements.
Option A: API key authentication
Navigate to your resource in the Microsoft Foundry portal
Go to the
Endpoints and keys
section
Copy
API Key
Set the environment variable:
export
ANTHROPIC_FOUNDRY_API_KEY
=
your-azure-api-key
Option B: Microsoft Entra ID authentication
When
ANTHROPIC_FOUNDRY_API_KEY
is not set, Claude Code automatically uses the Azure SDK
default credential chain
.
This supports a variety of methods for authenticating local and remote workloads.
On local environments, you commonly may use the Azure CLI:
az
login
When using Microsoft Foundry, the
/login
and
/logout
commands are disabled since authentication is handled through Azure credentials.
​
3. Configure Claude Code
Set the following environment variables to enable Microsoft Foundry:
# Enable Microsoft Foundry integration
export
CLAUDE_CODE_USE_FOUNDRY
=
1
# Azure resource name (replace {resource} with your resource name)
export
ANTHROPIC_FOUNDRY_RESOURCE
=
{
resource}
# Or provide the full base URL:
# export ANTHROPIC_FOUNDRY_BASE_URL=https://{resource}.services.ai.azure.com/anthropic
​
4. Pin model versions
Pin specific model versions for every deployment. If you use model aliases (
sonnet
,
opus
,
haiku
) without pinning, Claude Code may attempt to use a newer model version that isn’t available in your Foundry account, breaking existing users when Anthropic releases updates. When you create Azure deployments, select a specific model version rather than “auto-update to latest.”
Set the model variables to match the deployment names you created in step 1.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Foundry resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5'
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Foundry, Claude Code defaults this to the primary model because not every account has a Haiku deployment. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a Haiku deployment that is available in your account, as shown above.
For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Prompt caching
is enabled automatically. To request a 1-hour cache TTL instead of the 5-minute default, set the following variable; cache writes with a 1-hour TTL are billed at a higher rate:
export
ENABLE_PROMPT_CACHING_1H
=
1
​
5. Run Claude Code
With the environment variables set, start Claude Code from your project directory:
claude
Claude Code reads
CLAUDE_CODE_USE_FOUNDRY
and the other Foundry variables from the environment and connects to your Azure resource on the first prompt. Unlike Bedrock and Vertex AI, Foundry has no interactive setup wizard, so the environment variables in steps 3 and 4 are the only configuration path.
​
Azure RBAC configuration
The
Azure AI User
and
Cognitive Services User
default roles include all required permissions for invoking Claude models.
For more restrictive permissions, create a custom role with the following:
{
"permissions"
: [
{
"dataActions"
: [
"Microsoft.CognitiveServices/accounts/providers/*"
]
}
]
}
For details, see
Microsoft Foundry RBAC documentation
.
​
Troubleshooting
If you receive an error “Failed to get token from azureADTokenProvider: ChainedTokenCredential authentication failed”:
Configure Entra ID on the environment, or set
ANTHROPIC_FOUNDRY_API_KEY
.
​
Additional resources
Microsoft Foundry documentation
Microsoft Foundry models
Microsoft Foundry pricing
Was this page helpful?
Yes
No
Google Vertex AI
Network configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/microsoft-foundry" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Microsoft Foundry
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marke...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Microsoft Foundry
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Microsoft Foundry, ensure you have:
An Azure subscription with access to Microsoft Foundry
RBAC permissions to create Microsoft Foundry resources and deployments
Azure CLI installed and configured (optional - only needed if you don’t have another mechanism for getting credentials)
If you are deploying Claude Code to multiple users,
pin your model versions
to prevent breakage when Anthropic releases new models.
​
Setup
​
1. Provision Microsoft Foundry resource
First, create a Claude resource in Azure:
Navigate to the
Microsoft Foundry portal
Create a new resource, noting your resource name
Create deployments for the Claude models:
Claude Opus
Claude Sonnet
Claude Haiku
​
2. Configure Azure credentials
Claude Code supports two authentication methods for Microsoft Foundry. Choose the method that best fits your security requirements.
Option A: API key authentication
Navigate to your resource in the Microsoft Foundry portal
Go to the
Endpoints and keys
section
Copy
API Key
Set the environment variable:
export
ANTHROPIC_FOUNDRY_API_KEY
=
your-azure-api-key
Option B: Microsoft Entra ID authentication
When
ANTHROPIC_FOUNDRY_API_KEY
is not set, Claude Code automatically uses the Azure SDK
default credential chain
.
This supports a variety of methods for authenticating local and remote workloads.
On local environments, you commonly may use the Azure CLI:
az
login
When using Microsoft Foundry, the
/login
and
/logout
commands are disabled since authentication is handled through Azure credentials.
​
3. Configure Claude Code
Set the following environment variables to enable Microsoft Foundry:
# Enable Microsoft Foundry integration
export
CLAUDE_CODE_USE_FOUNDRY
=
1
# Azure resource name (replace {resource} with your resource name)
export
ANTHROPIC_FOUNDRY_RESOURCE
=
{
resource}
# Or provide the full base URL:
# export ANTHROPIC_FOUNDRY_BASE_URL=https://{resource}.services.ai.azure.com/anthropic
​
4. Pin model versions
Pin specific model versions for every deployment. If you use model aliases (
sonnet
,
opus
,
haiku
) without pinning, Claude Code may attempt to use a newer model version that isn’t available in your Foundry account, breaking existing users when Anthropic releases updates. When you create Azure deployments, select a specific model version rather than “auto-update to latest.”
Set the model variables to match the deployment names you created in step 1.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Foundry resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5'
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Foundry, Claude Code defaults this to the primary model because not every account has a Haiku deployment. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a Haiku deployment that is available in your account, as shown above.
For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Prompt caching
is enabled automatically. To request a 1-hour cache TTL instead of the 5-minute default, set the following variable; cache writes with a 1-hour TTL are billed at a higher rate:
export
ENABLE_PROMPT_CACHING_1H
=
1
​
5. Run Claude Code
With the environment variables set, start Claude Code from your project directory:
claude
Claude Code reads
CLAUDE_CODE_USE_FOUNDRY
and the other Foundry variables from the environment and connects to your Azure resource on the first prompt. Unlike Bedrock and Vertex AI, Foundry has no interactive setup wizard, so the environment variables in steps 3 and 4 are the only configuration path.
​
Azure RBAC configuration
The
Azure AI User
and
Cognitive Services User
default roles include all required permissions for invoking Claude models.
For more restrictive permissions, create a custom role with the following:
{
"permissions"
: [
{
"dataActions"
: [
"Microsoft.CognitiveServices/accounts/providers/*"
]
}
]
}
For details, see
Microsoft Foundry RBAC documentation
.
​
Troubleshooting
If you receive an error “Failed to get token from azureADTokenProvider: ChainedTokenCredential authentication failed”:
Configure Entra ID on the environment, or set
ANTHROPIC_FOUNDRY_API_KEY
.
​
Additional resources
Microsoft Foundry documentation
Microsoft Foundry models
Microsoft Foundry pricing
Was this page helpful?
Yes
No
Google Vertex AI
Network configuration
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/microsoft-foundry" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Securely deploying AI agents</title>
  <link>https://code.claude.com/docs/en/agent-sdk/secure-deployment</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/secure-deployment</guid>
  <pubDate>Thu, 30 May 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Securely deploying AI agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cu...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Securely deploying AI agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code and the Agent SDK are powerful tools that can execute code, access files, and interact with external services on your behalf. Like any tool with these capabilities, deploying them thoughtfully ensures you get the benefits while maintaining appropriate controls.
Unlike traditional software that follows predetermined code paths, these tools generate their actions dynamically based on context and goals. This flexibility is what makes them useful, but it also means their behavior can be influenced by the content they process: files, webpages, or user input. This is sometimes called prompt injection. For example, if a repository’s README contains unusual instructions, Claude Code might incorporate those into its actions in ways the operator didn’t anticipate. This guide covers practical ways to reduce this risk.
The good news is that securing an agent deployment doesn’t require exotic infrastructure. The same principles that apply to running any semi-trusted code apply here: isolation, least privilege, and defense in depth. Claude Code includes several security features that help with common concerns, and this guide walks through these along with additional hardening options for those who need them.
Not every deployment needs maximum security. A developer running Claude Code on their laptop has different requirements than a company processing customer data in a multi-tenant environment. This guide presents options ranging from Claude Code’s built-in security features to hardened production architectures, so you can choose what fits your situation.
​
Threat model
Agents can take unintended actions due to prompt injection (instructions embedded in content they process) or model error. Claude models are designed to resist this; see the
model overview
and the system card for the model you deploy for evaluation details.
Defense in depth is still good practice though. For example, if an agent processes a malicious file that instructs it to send customer data to an external server, network controls can block that request entirely.
​
Built-in security features
Claude Code includes several security features that address common concerns. See the
security documentation
for full details.
Permissions system
: Every tool and bash command can be configured to allow, block, or prompt the user for approval. Use glob patterns to create rules like “allow all npm commands” or “block any command with sudo”. Organizations can set policies that apply across all users. See
permissions
.
Command parsing for permissions
: Before executing bash commands, Claude Code parses them into an AST and matches the result against your permission rules. Commands that cannot be parsed cleanly, or that do not match an allow rule, require explicit approval. A small set of constructs such as
eval
always require approval regardless of allow rules. This is a permission gate, not a sandbox; it does not infer whether a command is dangerous from its target path or effects.
Web search summarization
: Search results are summarized rather than passing raw content directly into the context, reducing the risk of prompt injection from malicious web content.
Sandbox mode
: Bash commands can run in a sandboxed environment that restricts filesystem and network access. See the
sandboxing documentation
for details.
​
Security principles
For deployments that require additional hardening beyond Claude Code’s defaults, these principles guide the available options.
​
Security boundaries
A security boundary separates components with different trust levels. For high-security deployments, you can place sensitive resources (like credentials) outside the boundary containing the agent. If something goes wrong in the agent’s environment, resources outside that boundary remain protected.
For example, rather than giving an agent direct access to an API key, you could run a proxy outside the agent’s environment that injects the key into requests. The agent can make API calls, but it never sees the credential itself. This pattern is useful for multi-tenant deployments or when processing untrusted content.
​
Least privilege
When needed, you can restrict the agent to only the capabilities required for its specific task:
Resource
Restriction options
Filesystem
Mount only needed directories, prefer read-only
Network
Restrict to specific endpoints via proxy
Credentials
Inject via proxy rather than exposing directly
System capabilities
Drop Linux capabilities in containers
​
Defense in depth
For high-security environments, layering multiple controls provides additional protection. Options include:
Container isolation
Network restrictions
Filesystem controls
Request validation at a proxy
The right combination depends on your threat model and operational requirements.
​
Isolation technologies
Different isolation technologies offer different tradeoffs between security strength, performance, and operational complexity.
In all of these configurations, Claude Code (or your Agent SDK application) runs inside the isolation boundary (the sandbox, container, or VM). The security controls described below restrict what the agent can access from within that boundary.
Technology
Isolation strength
Performance overhead
Complexity
Sandbox runtime
Good (secure defaults)
Very low
Low
Containers (Docker)
Setup dependent
Low
Medium
gVisor
Excellent (with correct setup)
Medium/High
Medium
VMs (Firecracker, QEMU)
Excellent (with correct setup)
High
Medium/High
​
Sandbox runtime
For lightweight isolation without containers,
sandbox-runtime
enforces filesystem and network restrictions at the OS level.
The main advantage is simplicity: no Docker configuration, container images, or networking setup required. The proxy and filesystem restrictions are built in. You provide a settings file specifying allowed domains and paths.
How it works:
Filesystem
: Uses OS primitives (
bubblewrap
on Linux,
sandbox-exec
on macOS) to restrict read/write access to configured paths
Network
: Removes network namespace (Linux) or uses Seatbelt profiles (macOS) to route network traffic through a built-in proxy
Configuration
: JSON-based allowlists for domains and filesystem paths
Setup:
npm
install
@anthropic-ai/sandbox-runtime
Then create a configuration file specifying allowed paths and domains.
Security considerations:
Same-host kernel
: Unlike VMs, sandboxed processes share the host kernel. A kernel vulnerability could theoretically enable escape. For some threat models this is acceptable, but if you need kernel-level isolation, use gVisor or a separate VM.
No TLS inspection
: The proxy allowlists domains based on the client-supplied hostname and does not terminate or inspect encrypted traffic. Code running inside the sandbox can potentially use
domain fronting
or similar techniques to reach hosts outside the allowlist. If your threat model requires stronger guarantees, configure a
TLS-terminating proxy
. See the
sandboxing security limitations
for more detail. Separately, if the agent has permissive credentials for an allowed domain, ensure it cannot use that domain to trigger other network requests or to exfiltrate data.
For many single-developer and CI/CD use cases, sandbox-runtime raises the bar significantly with minimal setup. The sections below cover containers and VMs for deployments requiring stronger isolation.
​
Containers
Containers provide isolation through Linux namespaces. Each container has its own view of the filesystem, process tree, and network stack, while sharing the host kernel.
A security-hardened container configuration might look like this:
docker
run
\
--cap-drop
ALL
\
--security-opt
no-new-privileges
\
--security-opt
seccomp=/path/to/seccomp-profile.json
\
--read-only
\
--tmpfs
/tmp:rw,noexec,nosuid,size=100m
\
--tmpfs
/home/agent:rw,noexec,nosuid,size=500m
\
--network
none
\
--memory
2g
\
--cpus
2
\
--pids-limit
100
\
--user
1000:1000
\
-v
/path/to/code:/workspace:ro
\
-v
/var/run/proxy.sock:/var/run/proxy.sock:ro
\
agent-image
Here’s what each option does:
Option
Purpose
--cap-drop ALL
Removes Linux capabilities like
NET_ADMIN
and
SYS_ADMIN
that could enable privilege escalation
--security-opt no-new-privileges
Prevents processes from gaining privileges through setuid binaries
--security-opt seccomp=...
Restricts available syscalls; Docker’s default blocks ~44, custom profiles can block more
--read-only
Makes the container’s root filesystem immutable, preventing the agent from persisting changes
--tmpfs /tmp:...
Provides a writable temporary directory that’s cleared when the container stops
--network none
Removes all network interfaces; the agent communicates through the mounted Unix socket below
--memory 2g
Limits memory usage to prevent resource exhaustion
--pids-limit 100
Limits process count to prevent fork bombs
--user 1000:1000
Runs as a non-root user
-v ...:/workspace:ro
Mounts code read-only so the agent can analyze but not modify it.
Avoid mounting sensitive host directories like
~/.ssh
,
~/.aws
, or
~/.config
-v .../proxy.sock:...
Mounts a Unix socket connected to a proxy running outside the container (see below)
Unix socket architecture:
With
--network none
, the container has no network interfaces at all. The only way for the agent to reach the outside world is through the mounted Unix socket, which connects to a proxy running on the host. This proxy can enforce domain allowlists, inject credentials, and log all traffic.
This is the same architecture used by
sandbox-runtime
. Even if the agent is compromised via prompt injection, it cannot exfiltrate data to arbitrary servers. It can only communicate through the proxy, which controls what domains are reachable. For more details, see the
Claude Code sandboxing blog post
.
Additional hardening options:
Option
Purpose
--userns-remap
Maps container root to unprivileged host user; requires daemon configuration but limits damage from container escape
--ipc private
Isolates inter-process communication to prevent cross-container attacks
​
gVisor
Standard containers share the host kernel: when code inside a container makes a system call, it goes directly to the same kernel that runs the host. This means a kernel vulnerability could allow container escape. gVisor addresses this by intercepting system calls in userspace before they reach the host kernel, implementing its own compatibility layer that handles most syscalls without involving the real kernel.
If an agent runs malicious code (perhaps due to prompt injection), that code runs in the container and could attempt kernel exploits. With gVisor, the attack surface is much smaller: the malicious code would need to exploit gVisor’s userspace implementation first and would have limited access to the real kernel.
To use gVisor with Docker, install the
runsc
runtime and configure the daemon:
// /etc/docker/daemon.json
{
"runtimes"
: {
"runsc"
: {
"path"
:
"/usr/local/bin/runsc"
}
}
}
Then run containers with:
docker
run
--runtime=runsc
agent-image
Performance considerations:
Workload
Overhead
CPU-bound computation
~0% (no syscall interception)
Simple syscalls
~2× slower
File I/O intensive
Up to 10-200× slower for heavy open/close patterns
For multi-tenant environments or when processing untrusted content, the additional isolation is often worth the overhead.
​
Virtual machines
VMs provide hardware-level isolation through CPU virtualization extensions. Each VM runs its own kernel, creating a strong boundary. A vulnerability in the guest kernel doesn’t directly compromise the host. However, VMs aren’t automatically “more secure” than alternatives like gVisor. VM security depends heavily on the hypervisor and device emulation code.
Firecracker is designed for lightweight microVM isolation. It can boot VMs in under 125ms with less than 5 MiB memory overhead, stripping away unnecessary device emulation to reduce attack surface.
With this approach, the agent VM has no external network interface. Instead, it communicates through
vsock
(virtual sockets). All traffic routes through vsock to a proxy on the host, which enforces allowlists and injects credentials before forwarding requests.
​
Cloud deployments
For cloud deployments, you can combine any of the above isolation technologies with cloud-native network controls:
Run agent containers in a private subnet with no internet gateway
Configure cloud firewall rules (AWS Security Groups, GCP VPC firewall) to block all egress except to your proxy
Run a proxy (such as
Envoy
with its
credential_injector
filter) that validates requests, enforces domain allowlists, injects credentials, and forwards to external APIs
Assign minimal IAM permissions to the agent’s service account, routing sensitive access through the proxy where possible
Log all traffic at the proxy for audit purposes
​
Credential management
Agents often need credentials to call APIs, access repositories, or interact with cloud services. The challenge is providing this access without exposing the credentials themselves.
​
The proxy pattern
The recommended approach is to run a proxy outside the agent’s security boundary that injects credentials into outgoing requests. The agent sends requests without credentials, the proxy adds them, and forwards the request to its destination.
This pattern has several benefits:
The agent never sees the actual credentials
The proxy can enforce an allowlist of permitted endpoints
The proxy can log all requests for auditing
Credentials are stored in one secure location rather than distributed to each agent
​
Configuring Claude Code to use a proxy
Claude Code supports two methods for routing sampling requests through a proxy:
Option 1: ANTHROPIC_BASE_URL (simple but only for sampling API requests)
export
ANTHROPIC_BASE_URL
=
"http://localhost:8080"
This tells Claude Code and the Agent SDK to send sampling requests to your proxy instead of the Claude API directly. Your proxy receives plaintext HTTP requests, can inspect and modify them (including injecting credentials), then forwards to the real API.
Option 2: HTTP_PROXY / HTTPS_PROXY (system-wide)
export
HTTP_PROXY
=
"http://localhost:8080"
export
HTTPS_PROXY
=
"http://localhost:8080"
Claude Code and the Agent SDK respect these standard environment variables, routing all HTTP traffic through the proxy. For HTTPS, the proxy creates an encrypted CONNECT tunnel: it cannot see or modify request contents without TLS interception.
​
Implementing a proxy
You can build your own proxy or use an existing one:
Envoy Proxy
: production-grade proxy with
credential_injector
filter for adding auth headers
mitmproxy
: TLS-terminating proxy for inspecting and modifying HTTPS traffic
Squid
: caching proxy with access control lists
LiteLLM
: LLM gateway with credential injection and rate limiting
​
Credentials for other services
Beyond sampling from the Claude API, agents often need authenticated access to other services, such as git repositories, databases, and internal APIs. There are two main approaches:
​
Custom tools
Provide access through an MCP server or custom tool that routes requests to a service running outside the agent’s security boundary. The agent calls the tool, but the actual authenticated request happens outside. The tool calls to a proxy which injects the credentials.
For example, a git MCP server could accept commands from the agent but forward them to a git proxy running on the host, which adds authentication before contacting the remote repository. The agent never sees the credentials.
Advantages:
No TLS interception
: The external service makes authenticated requests directly
Credentials stay outside
: The agent only sees the tool interface, not the underlying credentials
​
Traffic forwarding
For Claude API calls,
ANTHROPIC_BASE_URL
lets you route requests to a proxy that can inspect and modify them in plaintext. But for other HTTPS services (GitHub, npm registries, internal APIs), the traffic is often encrypted end-to-end. Even if you route it through a proxy via
HTTP_PROXY
, the proxy only sees an opaque TLS tunnel and can’t inject credentials.
To modify HTTPS traffic to arbitrary services, without using a custom tool, you need a TLS-terminating proxy that decrypts traffic, inspects or modifies it, then re-encrypts it before forwarding. This requires:
Running the proxy outside the agent’s container
Installing the proxy’s CA certificate in the agent’s trust store (so the agent trusts the proxy’s certificates)
Configuring
HTTP_PROXY
/
HTTPS_PROXY
to route traffic through the proxy
This approach handles any HTTP-based service without writing custom tools, but adds complexity around certificate management.
Note that not all programs respect
HTTP_PROXY
/
HTTPS_PROXY
. Most tools (curl, pip, npm, git) do, but some may bypass these variables and connect directly. For example, Node.js
fetch()
ignores these variables by default; in Node 24+ you can set
NODE_USE_ENV_PROXY=1
to enable support. For comprehensive coverage, you can use
proxychains
to intercept network calls, or configure iptables to redirect outbound traffic to a transparent proxy.
A
transparent proxy
intercepts traffic at the network level, so the client doesn’t need to be configured to use it. Regular proxies require clients to explicitly connect and speak HTTP CONNECT or SOCKS. Transparent proxies (like Squid or mitmproxy in transparent mode) can handle raw redirected TCP connections.
Both approaches still require the TLS-terminating proxy and trusted CA certificate. They just ensure traffic actually reaches the proxy.
​
Filesystem configuration
Filesystem controls determine what files the agent can read and write.
​
Read-only code mounting
When the agent needs to analyze code but not modify it, mount the directory read-only:
docker
run
-v
/path/to/code:/workspace:ro
agent-image
Even read-only access to a code directory can expose credentials. Common files to exclude or sanitize before mounting:
File
Risk
.env
,
.env.local
API keys, database passwords, secrets
~/.git-credentials
Git passwords/tokens in plaintext
~/.aws/credentials
AWS access keys
~/.config/gcloud/application_default_credentials.json
Google Cloud ADC tokens
~/.azure/
Azure CLI credentials
~/.docker/config.json
Docker registry auth tokens
~/.kube/config
Kubernetes cluster credentials
.npmrc
,
.pypirc
Package registry tokens
*-service-account.json
GCP service account keys
*.pem
,
*.key
Private keys
Consider copying only the source files needed, or using
.dockerignore
-style filtering.
​
Writable locations
If the agent needs to write files, you have a few options depending on whether you want changes to persist:
For ephemeral workspaces in containers, use
tmpfs
mounts that exist only in memory and are cleared when the container stops:
docker
run
\
--read-only
\
--tmpfs
/tmp:rw,noexec,nosuid,size=100m
\
--tmpfs
/workspace:rw,noexec,size=500m
\
agent-image
If you want to review changes before persisting them, an overlay filesystem lets the agent write without modifying underlying files. Changes are stored in a separate layer you can inspect, apply, or discard. For fully persistent output, mount a dedicated volume but keep it separate from sensitive directories.
​
Further reading
Claude Code security documentation
Hosting the Agent SDK
Handling permissions
Sandbox runtime
The Lethal Trifecta for AI Agents
OWASP Top 10 for LLM Applications
Docker Security Best Practices
gVisor Documentation
Firecracker Documentation
Was this page helpful?
Yes
No
Hosting the Agent SDK
TypeScript SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/secure-deployment" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Securely deploying AI agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cu...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Securely deploying AI agents
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code and the Agent SDK are powerful tools that can execute code, access files, and interact with external services on your behalf. Like any tool with these capabilities, deploying them thoughtfully ensures you get the benefits while maintaining appropriate controls.
Unlike traditional software that follows predetermined code paths, these tools generate their actions dynamically based on context and goals. This flexibility is what makes them useful, but it also means their behavior can be influenced by the content they process: files, webpages, or user input. This is sometimes called prompt injection. For example, if a repository’s README contains unusual instructions, Claude Code might incorporate those into its actions in ways the operator didn’t anticipate. This guide covers practical ways to reduce this risk.
The good news is that securing an agent deployment doesn’t require exotic infrastructure. The same principles that apply to running any semi-trusted code apply here: isolation, least privilege, and defense in depth. Claude Code includes several security features that help with common concerns, and this guide walks through these along with additional hardening options for those who need them.
Not every deployment needs maximum security. A developer running Claude Code on their laptop has different requirements than a company processing customer data in a multi-tenant environment. This guide presents options ranging from Claude Code’s built-in security features to hardened production architectures, so you can choose what fits your situation.
​
Threat model
Agents can take unintended actions due to prompt injection (instructions embedded in content they process) or model error. Claude models are designed to resist this; see the
model overview
and the system card for the model you deploy for evaluation details.
Defense in depth is still good practice though. For example, if an agent processes a malicious file that instructs it to send customer data to an external server, network controls can block that request entirely.
​
Built-in security features
Claude Code includes several security features that address common concerns. See the
security documentation
for full details.
Permissions system
: Every tool and bash command can be configured to allow, block, or prompt the user for approval. Use glob patterns to create rules like “allow all npm commands” or “block any command with sudo”. Organizations can set policies that apply across all users. See
permissions
.
Command parsing for permissions
: Before executing bash commands, Claude Code parses them into an AST and matches the result against your permission rules. Commands that cannot be parsed cleanly, or that do not match an allow rule, require explicit approval. A small set of constructs such as
eval
always require approval regardless of allow rules. This is a permission gate, not a sandbox; it does not infer whether a command is dangerous from its target path or effects.
Web search summarization
: Search results are summarized rather than passing raw content directly into the context, reducing the risk of prompt injection from malicious web content.
Sandbox mode
: Bash commands can run in a sandboxed environment that restricts filesystem and network access. See the
sandboxing documentation
for details.
​
Security principles
For deployments that require additional hardening beyond Claude Code’s defaults, these principles guide the available options.
​
Security boundaries
A security boundary separates components with different trust levels. For high-security deployments, you can place sensitive resources (like credentials) outside the boundary containing the agent. If something goes wrong in the agent’s environment, resources outside that boundary remain protected.
For example, rather than giving an agent direct access to an API key, you could run a proxy outside the agent’s environment that injects the key into requests. The agent can make API calls, but it never sees the credential itself. This pattern is useful for multi-tenant deployments or when processing untrusted content.
​
Least privilege
When needed, you can restrict the agent to only the capabilities required for its specific task:
Resource
Restriction options
Filesystem
Mount only needed directories, prefer read-only
Network
Restrict to specific endpoints via proxy
Credentials
Inject via proxy rather than exposing directly
System capabilities
Drop Linux capabilities in containers
​
Defense in depth
For high-security environments, layering multiple controls provides additional protection. Options include:
Container isolation
Network restrictions
Filesystem controls
Request validation at a proxy
The right combination depends on your threat model and operational requirements.
​
Isolation technologies
Different isolation technologies offer different tradeoffs between security strength, performance, and operational complexity.
In all of these configurations, Claude Code (or your Agent SDK application) runs inside the isolation boundary (the sandbox, container, or VM). The security controls described below restrict what the agent can access from within that boundary.
Technology
Isolation strength
Performance overhead
Complexity
Sandbox runtime
Good (secure defaults)
Very low
Low
Containers (Docker)
Setup dependent
Low
Medium
gVisor
Excellent (with correct setup)
Medium/High
Medium
VMs (Firecracker, QEMU)
Excellent (with correct setup)
High
Medium/High
​
Sandbox runtime
For lightweight isolation without containers,
sandbox-runtime
enforces filesystem and network restrictions at the OS level.
The main advantage is simplicity: no Docker configuration, container images, or networking setup required. The proxy and filesystem restrictions are built in. You provide a settings file specifying allowed domains and paths.
How it works:
Filesystem
: Uses OS primitives (
bubblewrap
on Linux,
sandbox-exec
on macOS) to restrict read/write access to configured paths
Network
: Removes network namespace (Linux) or uses Seatbelt profiles (macOS) to route network traffic through a built-in proxy
Configuration
: JSON-based allowlists for domains and filesystem paths
Setup:
npm
install
@anthropic-ai/sandbox-runtime
Then create a configuration file specifying allowed paths and domains.
Security considerations:
Same-host kernel
: Unlike VMs, sandboxed processes share the host kernel. A kernel vulnerability could theoretically enable escape. For some threat models this is acceptable, but if you need kernel-level isolation, use gVisor or a separate VM.
No TLS inspection
: The proxy allowlists domains based on the client-supplied hostname and does not terminate or inspect encrypted traffic. Code running inside the sandbox can potentially use
domain fronting
or similar techniques to reach hosts outside the allowlist. If your threat model requires stronger guarantees, configure a
TLS-terminating proxy
. See the
sandboxing security limitations
for more detail. Separately, if the agent has permissive credentials for an allowed domain, ensure it cannot use that domain to trigger other network requests or to exfiltrate data.
For many single-developer and CI/CD use cases, sandbox-runtime raises the bar significantly with minimal setup. The sections below cover containers and VMs for deployments requiring stronger isolation.
​
Containers
Containers provide isolation through Linux namespaces. Each container has its own view of the filesystem, process tree, and network stack, while sharing the host kernel.
A security-hardened container configuration might look like this:
docker
run
\
--cap-drop
ALL
\
--security-opt
no-new-privileges
\
--security-opt
seccomp=/path/to/seccomp-profile.json
\
--read-only
\
--tmpfs
/tmp:rw,noexec,nosuid,size=100m
\
--tmpfs
/home/agent:rw,noexec,nosuid,size=500m
\
--network
none
\
--memory
2g
\
--cpus
2
\
--pids-limit
100
\
--user
1000:1000
\
-v
/path/to/code:/workspace:ro
\
-v
/var/run/proxy.sock:/var/run/proxy.sock:ro
\
agent-image
Here’s what each option does:
Option
Purpose
--cap-drop ALL
Removes Linux capabilities like
NET_ADMIN
and
SYS_ADMIN
that could enable privilege escalation
--security-opt no-new-privileges
Prevents processes from gaining privileges through setuid binaries
--security-opt seccomp=...
Restricts available syscalls; Docker’s default blocks ~44, custom profiles can block more
--read-only
Makes the container’s root filesystem immutable, preventing the agent from persisting changes
--tmpfs /tmp:...
Provides a writable temporary directory that’s cleared when the container stops
--network none
Removes all network interfaces; the agent communicates through the mounted Unix socket below
--memory 2g
Limits memory usage to prevent resource exhaustion
--pids-limit 100
Limits process count to prevent fork bombs
--user 1000:1000
Runs as a non-root user
-v ...:/workspace:ro
Mounts code read-only so the agent can analyze but not modify it.
Avoid mounting sensitive host directories like
~/.ssh
,
~/.aws
, or
~/.config
-v .../proxy.sock:...
Mounts a Unix socket connected to a proxy running outside the container (see below)
Unix socket architecture:
With
--network none
, the container has no network interfaces at all. The only way for the agent to reach the outside world is through the mounted Unix socket, which connects to a proxy running on the host. This proxy can enforce domain allowlists, inject credentials, and log all traffic.
This is the same architecture used by
sandbox-runtime
. Even if the agent is compromised via prompt injection, it cannot exfiltrate data to arbitrary servers. It can only communicate through the proxy, which controls what domains are reachable. For more details, see the
Claude Code sandboxing blog post
.
Additional hardening options:
Option
Purpose
--userns-remap
Maps container root to unprivileged host user; requires daemon configuration but limits damage from container escape
--ipc private
Isolates inter-process communication to prevent cross-container attacks
​
gVisor
Standard containers share the host kernel: when code inside a container makes a system call, it goes directly to the same kernel that runs the host. This means a kernel vulnerability could allow container escape. gVisor addresses this by intercepting system calls in userspace before they reach the host kernel, implementing its own compatibility layer that handles most syscalls without involving the real kernel.
If an agent runs malicious code (perhaps due to prompt injection), that code runs in the container and could attempt kernel exploits. With gVisor, the attack surface is much smaller: the malicious code would need to exploit gVisor’s userspace implementation first and would have limited access to the real kernel.
To use gVisor with Docker, install the
runsc
runtime and configure the daemon:
// /etc/docker/daemon.json
{
"runtimes"
: {
"runsc"
: {
"path"
:
"/usr/local/bin/runsc"
}
}
}
Then run containers with:
docker
run
--runtime=runsc
agent-image
Performance considerations:
Workload
Overhead
CPU-bound computation
~0% (no syscall interception)
Simple syscalls
~2× slower
File I/O intensive
Up to 10-200× slower for heavy open/close patterns
For multi-tenant environments or when processing untrusted content, the additional isolation is often worth the overhead.
​
Virtual machines
VMs provide hardware-level isolation through CPU virtualization extensions. Each VM runs its own kernel, creating a strong boundary. A vulnerability in the guest kernel doesn’t directly compromise the host. However, VMs aren’t automatically “more secure” than alternatives like gVisor. VM security depends heavily on the hypervisor and device emulation code.
Firecracker is designed for lightweight microVM isolation. It can boot VMs in under 125ms with less than 5 MiB memory overhead, stripping away unnecessary device emulation to reduce attack surface.
With this approach, the agent VM has no external network interface. Instead, it communicates through
vsock
(virtual sockets). All traffic routes through vsock to a proxy on the host, which enforces allowlists and injects credentials before forwarding requests.
​
Cloud deployments
For cloud deployments, you can combine any of the above isolation technologies with cloud-native network controls:
Run agent containers in a private subnet with no internet gateway
Configure cloud firewall rules (AWS Security Groups, GCP VPC firewall) to block all egress except to your proxy
Run a proxy (such as
Envoy
with its
credential_injector
filter) that validates requests, enforces domain allowlists, injects credentials, and forwards to external APIs
Assign minimal IAM permissions to the agent’s service account, routing sensitive access through the proxy where possible
Log all traffic at the proxy for audit purposes
​
Credential management
Agents often need credentials to call APIs, access repositories, or interact with cloud services. The challenge is providing this access without exposing the credentials themselves.
​
The proxy pattern
The recommended approach is to run a proxy outside the agent’s security boundary that injects credentials into outgoing requests. The agent sends requests without credentials, the proxy adds them, and forwards the request to its destination.
This pattern has several benefits:
The agent never sees the actual credentials
The proxy can enforce an allowlist of permitted endpoints
The proxy can log all requests for auditing
Credentials are stored in one secure location rather than distributed to each agent
​
Configuring Claude Code to use a proxy
Claude Code supports two methods for routing sampling requests through a proxy:
Option 1: ANTHROPIC_BASE_URL (simple but only for sampling API requests)
export
ANTHROPIC_BASE_URL
=
"http://localhost:8080"
This tells Claude Code and the Agent SDK to send sampling requests to your proxy instead of the Claude API directly. Your proxy receives plaintext HTTP requests, can inspect and modify them (including injecting credentials), then forwards to the real API.
Option 2: HTTP_PROXY / HTTPS_PROXY (system-wide)
export
HTTP_PROXY
=
"http://localhost:8080"
export
HTTPS_PROXY
=
"http://localhost:8080"
Claude Code and the Agent SDK respect these standard environment variables, routing all HTTP traffic through the proxy. For HTTPS, the proxy creates an encrypted CONNECT tunnel: it cannot see or modify request contents without TLS interception.
​
Implementing a proxy
You can build your own proxy or use an existing one:
Envoy Proxy
: production-grade proxy with
credential_injector
filter for adding auth headers
mitmproxy
: TLS-terminating proxy for inspecting and modifying HTTPS traffic
Squid
: caching proxy with access control lists
LiteLLM
: LLM gateway with credential injection and rate limiting
​
Credentials for other services
Beyond sampling from the Claude API, agents often need authenticated access to other services, such as git repositories, databases, and internal APIs. There are two main approaches:
​
Custom tools
Provide access through an MCP server or custom tool that routes requests to a service running outside the agent’s security boundary. The agent calls the tool, but the actual authenticated request happens outside. The tool calls to a proxy which injects the credentials.
For example, a git MCP server could accept commands from the agent but forward them to a git proxy running on the host, which adds authentication before contacting the remote repository. The agent never sees the credentials.
Advantages:
No TLS interception
: The external service makes authenticated requests directly
Credentials stay outside
: The agent only sees the tool interface, not the underlying credentials
​
Traffic forwarding
For Claude API calls,
ANTHROPIC_BASE_URL
lets you route requests to a proxy that can inspect and modify them in plaintext. But for other HTTPS services (GitHub, npm registries, internal APIs), the traffic is often encrypted end-to-end. Even if you route it through a proxy via
HTTP_PROXY
, the proxy only sees an opaque TLS tunnel and can’t inject credentials.
To modify HTTPS traffic to arbitrary services, without using a custom tool, you need a TLS-terminating proxy that decrypts traffic, inspects or modifies it, then re-encrypts it before forwarding. This requires:
Running the proxy outside the agent’s container
Installing the proxy’s CA certificate in the agent’s trust store (so the agent trusts the proxy’s certificates)
Configuring
HTTP_PROXY
/
HTTPS_PROXY
to route traffic through the proxy
This approach handles any HTTP-based service without writing custom tools, but adds complexity around certificate management.
Note that not all programs respect
HTTP_PROXY
/
HTTPS_PROXY
. Most tools (curl, pip, npm, git) do, but some may bypass these variables and connect directly. For example, Node.js
fetch()
ignores these variables by default; in Node 24+ you can set
NODE_USE_ENV_PROXY=1
to enable support. For comprehensive coverage, you can use
proxychains
to intercept network calls, or configure iptables to redirect outbound traffic to a transparent proxy.
A
transparent proxy
intercepts traffic at the network level, so the client doesn’t need to be configured to use it. Regular proxies require clients to explicitly connect and speak HTTP CONNECT or SOCKS. Transparent proxies (like Squid or mitmproxy in transparent mode) can handle raw redirected TCP connections.
Both approaches still require the TLS-terminating proxy and trusted CA certificate. They just ensure traffic actually reaches the proxy.
​
Filesystem configuration
Filesystem controls determine what files the agent can read and write.
​
Read-only code mounting
When the agent needs to analyze code but not modify it, mount the directory read-only:
docker
run
-v
/path/to/code:/workspace:ro
agent-image
Even read-only access to a code directory can expose credentials. Common files to exclude or sanitize before mounting:
File
Risk
.env
,
.env.local
API keys, database passwords, secrets
~/.git-credentials
Git passwords/tokens in plaintext
~/.aws/credentials
AWS access keys
~/.config/gcloud/application_default_credentials.json
Google Cloud ADC tokens
~/.azure/
Azure CLI credentials
~/.docker/config.json
Docker registry auth tokens
~/.kube/config
Kubernetes cluster credentials
.npmrc
,
.pypirc
Package registry tokens
*-service-account.json
GCP service account keys
*.pem
,
*.key
Private keys
Consider copying only the source files needed, or using
.dockerignore
-style filtering.
​
Writable locations
If the agent needs to write files, you have a few options depending on whether you want changes to persist:
For ephemeral workspaces in containers, use
tmpfs
mounts that exist only in memory and are cleared when the container stops:
docker
run
\
--read-only
\
--tmpfs
/tmp:rw,noexec,nosuid,size=100m
\
--tmpfs
/workspace:rw,noexec,size=500m
\
agent-image
If you want to review changes before persisting them, an overlay filesystem lets the agent write without modifying underlying files. Changes are stored in a separate layer you can inspect, apply, or discard. For fully persistent output, mount a dedicated volume but keep it separate from sensitive directories.
​
Further reading
Claude Code security documentation
Hosting the Agent SDK
Handling permissions
Sandbox runtime
The Lethal Trifecta for AI Agents
OWASP Top 10 for LLM Applications
Docker Security Best Practices
gVisor Documentation
Firecracker Documentation
Was this page helpful?
Yes
No
Hosting the Agent SDK
TypeScript SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/secure-deployment" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Hooks reference</title>
  <link>https://code.claude.com/docs/en/hooks</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/hooks</guid>
  <pubDate>Wed, 29 May 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Hooks reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
For a quickstart guide with examples, see
Automa...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Hooks reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
For a quickstart guide with examples, see
Automate workflows with hooks
.
Hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code’s lifecycle. Use this reference to look up event schemas, configuration options, JSON input/output formats, and advanced features like async hooks, HTTP hooks, and MCP tool hooks. If you’re setting up hooks for the first time, start with the
guide
instead.
​
Hook lifecycle
Hooks fire at specific points during a Claude Code session. When an event fires and a matcher matches, Claude Code passes JSON context about the event to your hook handler. For command hooks, input arrives on stdin. For HTTP hooks, it arrives as the POST request body. Your handler can then inspect the input, take action, and optionally return a decision. Events fall into three cadences: once per session (
SessionStart
,
SessionEnd
), once per turn (
UserPromptSubmit
,
Stop
,
StopFailure
), and on every tool call inside the agentic loop (
PreToolUse
,
PostToolUse
):
The table below summarizes when each event fires. The
Hook events
section documents the full input schema and decision control options for each one.
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
​
How a hook resolves
To see how these pieces fit together, consider this
PreToolUse
hook that blocks destructive shell commands. The
matcher
narrows to Bash tool calls and the
if
condition narrows further to Bash subcommands matching
rm *
, so
block-rm.sh
only spawns when both filters match:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"if"
:
"Bash(rm *)"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
,
"args"
: []
}
]
}
]
}
}
The script reads the JSON input from stdin, extracts the command, and returns a
permissionDecision
of
"deny"
if it contains
rm -rf
:
#!/bin/bash
# .claude/hooks/block-rm.sh
COMMAND
=
$(
jq
-r
'.tool_input.command'
)
if
echo
"
$COMMAND
"
|
grep
-q
'rm -rf'
;
then
jq
-n
'{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
else
exit
0
# allow the command
fi
Now suppose Claude Code decides to run
Bash "rm -rf /tmp/build"
. Here’s what happens:
1
Event fires
The
PreToolUse
event fires. Claude Code sends the tool input as JSON on stdin to the hook:
{
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf /tmp/build"
},
...
}
2
Matcher checks
The matcher
"Bash"
matches the tool name, so this hook group activates. If you omit the matcher or use
"*"
, the group activates on every occurrence of the event.
3
If condition checks
The
if
condition
"Bash(rm *)"
matches because
rm -rf /tmp/build
is a subcommand matching
rm *
, so this handler spawns. If the command had been
npm test
, the
if
check would fail and
block-rm.sh
would never run, avoiding the process spawn overhead. The
if
field is optional; without it, every handler in the matched group runs.
4
Hook handler runs
The script inspects the full command and finds
rm -rf
, so it prints a decision to stdout:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Destructive command blocked by hook"
}
}
If the command had been a safer
rm
variant like
rm file.txt
, the script would hit
exit 0
instead, which tells Claude Code to allow the tool call with no further action.
5
Claude Code acts on the result
Claude Code reads the JSON decision, blocks the tool call, and shows Claude the reason.
The
Configuration
section below documents the full schema, and each
hook event
section documents what input your command receives and what output it can return.
​
Configuration
Hooks are defined in JSON settings files. The configuration has three levels of nesting:
Choose a
hook event
to respond to, like
PreToolUse
or
Stop
Add a
matcher group
to filter when it fires, like “only for the Bash tool”
Define one or more
hook handlers
to run when matched
See
How a hook resolves
above for a complete walkthrough with an annotated example.
This page uses specific terms for each level:
hook event
for the lifecycle point,
matcher group
for the filter, and
hook handler
for the shell command, HTTP endpoint, MCP tool, prompt, or agent that runs. “Hook” on its own refers to the general feature.
​
Hook locations
Where you define a hook determines its scope:
Location
Scope
Shareable
~/.claude/settings.json
All your projects
No, local to your machine
.claude/settings.json
Single project
Yes, can be committed to the repo
.claude/settings.local.json
Single project
No, gitignored
Managed policy settings
Organization-wide
Yes, admin-controlled
Plugin
hooks/hooks.json
When plugin is enabled
Yes, bundled with the plugin
Skill
or
agent
frontmatter
While the component is active
Yes, defined in the component file
For details on settings file resolution, see
settings
. Enterprise administrators can use
allowManagedHooksOnly
to block user, project, and plugin hooks. Hooks from plugins force-enabled in managed settings
enabledPlugins
are exempt, so administrators can distribute vetted hooks through an organization marketplace. See
Hook configuration
.
​
Matcher patterns
The
matcher
field filters when hooks fire. How a matcher is evaluated depends on the characters it contains:
Matcher value
Evaluated as
Example
"*"
,
""
, or omitted
Match all
fires on every occurrence of the event
Only letters, digits,
_
, and
|
Exact string, or
|
-separated list of exact strings
Bash
matches only the Bash tool;
Edit|Write
matches either tool exactly
Contains any other character
JavaScript regular expression
^Notebook
matches any tool starting with Notebook;
mcp__memory__.*
matches every tool from the
memory
server
The
FileChanged
event does not follow these rules when building its watch list. See
FileChanged
.
Each event type matches on a different field:
Event
What the matcher filters
Example matcher values
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
tool name
Bash
,
Edit|Write
,
mcp__.*
SessionStart
how the session started
startup
,
resume
,
clear
,
compact
Setup
which CLI flag triggered setup
init
,
maintenance
SessionEnd
why the session ended
clear
,
resume
,
logout
,
prompt_input_exit
,
bypass_permissions_disabled
,
other
Notification
notification type
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
SubagentStart
agent type
general-purpose
,
Explore
,
Plan
, or custom agent names
PreCompact
,
PostCompact
what triggered compaction
manual
,
auto
SubagentStop
agent type
same values as
SubagentStart
ConfigChange
configuration source
user_settings
,
project_settings
,
local_settings
,
policy_settings
,
skills
CwdChanged
no matcher support
always fires on every directory change
FileChanged
literal filenames to watch (see
FileChanged
)
.envrc|.env
StopFailure
error type
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
,
unknown
InstructionsLoaded
load reason
session_start
,
nested_traversal
,
path_glob_match
,
include
,
compact
UserPromptExpansion
command name
your skill or command names
Elicitation
MCP server name
your configured MCP server names
ElicitationResult
MCP server name
same values as
Elicitation
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
no matcher support
always fires on every occurrence
The matcher runs against a field from the
JSON input
that Claude Code sends to your hook on stdin. For tool events, that field is
tool_name
. Each
hook event
section lists the full set of matcher values and the input schema for that event.
This example runs a linting script only when Claude writes or edits a file:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/lint-check.sh"
}
]
}
]
}
}
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
, and
CwdChanged
don’t support matchers and always fire on every occurrence. If you add a
matcher
field to these events, it is silently ignored.
For tool events, you can filter more narrowly by setting the
if
field
on individual hook handlers.
if
uses
permission rule syntax
to match against the tool name and arguments together, so
"Bash(git *)"
runs when any subcommand of the Bash input matches
git *
and
"Edit(*.ts)"
runs only for TypeScript files.
​
Match MCP tools
MCP
server tools appear as regular tools in tool events (
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
), so you can match them the same way you match any other tool name.
MCP tools follow the naming pattern
mcp__<server>__<tool>
, for example:
mcp__memory__create_entities
: Memory server’s create entities tool
mcp__filesystem__read_file
: Filesystem server’s read file tool
mcp__github__search_repositories
: GitHub server’s search tool
To match every tool from a server, append
.*
to the server prefix. The
.*
is required: a matcher like
mcp__memory
contains only letters and underscores, so it is compared as an exact string and matches no tool.
mcp__memory__.*
matches all tools from the
memory
server
mcp__.*__write.*
matches any tool whose name starts with
write
from any server
This example logs all memory server operations and validates write operations from any MCP server:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"mcp__memory__.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo 'Memory operation initiated' >> ~/mcp-operations.log"
}
]
},
{
"matcher"
:
"mcp__.*__write.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/home/user/scripts/validate-mcp-write.py"
}
]
}
]
}
}
​
Hook handler fields
Each object in the inner
hooks
array is a hook handler: the shell command, HTTP endpoint, MCP tool, LLM prompt, or agent that runs when the matcher matches. There are five types:
Command hooks
(
type: "command"
): run a shell command. Your script receives the event’s
JSON input
on stdin and communicates results back through exit codes and stdout.
HTTP hooks
(
type: "http"
): send the event’s JSON input as an HTTP POST request to a URL. The endpoint communicates results back through the response body using the same
JSON output format
as command hooks.
MCP tool hooks
(
type: "mcp_tool"
): call a tool on an already-connected
MCP server
. The tool’s text output is treated like command-hook stdout.
Prompt hooks
(
type: "prompt"
): send a prompt to a Claude model for single-turn evaluation. The model returns a yes/no decision as JSON. See
Prompt-based hooks
.
Agent hooks
(
type: "agent"
): spawn a subagent that can use tools like Read, Grep, and Glob to verify conditions before returning a decision. Agent hooks are experimental and may change. See
Agent-based hooks
.
​
Common fields
These fields apply to all hook types:
Field
Required
Description
type
yes
"command"
,
"http"
,
"mcp_tool"
,
"prompt"
, or
"agent"
if
no
Permission rule syntax to filter when this hook runs, such as
"Bash(git *)"
or
"Edit(*.ts)"
. The hook only spawns if the tool call matches the pattern, or if a Bash command is too complex to parse. Only evaluated on tool events:
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
, and
PermissionDenied
. On other events, a hook with
if
set never runs. Uses the same syntax as
permission rules
timeout
no
Seconds before canceling. Defaults: 600 for
command
,
http
, and
mcp_tool
; 30 for
prompt
; 60 for
agent
.
UserPromptSubmit
lowers the
command
,
http
, and
mcp_tool
default to 30
statusMessage
no
Custom spinner message displayed while the hook runs
once
no
If
true
, runs once per session then is removed. Only honored for hooks declared in
skill frontmatter
; ignored in settings files and agent frontmatter
The
if
field holds exactly one permission rule. There is no
&&
,
||
, or list syntax for combining rules; to apply multiple conditions, define a separate hook handler for each. For Bash, the rule is matched against each subcommand of the tool input after leading
VAR=value
assignments are stripped, so
if: "Bash(git push *)"
matches both
FOO=bar git push
and
npm test && git push
. The hook runs if any subcommand matches, and always runs when the command is too complex to parse.
​
Command hook fields
In addition to the
common fields
, command hooks accept these fields:
Field
Required
Description
command
yes
Shell command to execute. With
args
, the executable to spawn directly. See
Exec form and shell form
args
no
Argument list. When present,
command
is resolved as an executable and spawned directly with
args
as the argument vector, with no shell involved. See
Exec form and shell form
async
no
If
true
, runs in the background without blocking. See
Run hooks in the background
asyncRewake
no
If
true
, runs in the background and wakes Claude on exit code 2. Implies
async
. The hook’s stderr, or stdout if stderr is empty, is shown to Claude as a system reminder so it can react to a long-running background failure
shell
no
Shell to use for this hook. Accepts
"bash"
(default) or
"powershell"
. Setting
"powershell"
runs the command via PowerShell on Windows. Does not require
CLAUDE_CODE_USE_POWERSHELL_TOOL
since hooks spawn PowerShell directly. Ignored when
args
is set
Exec form and shell form
A command hook runs as exec form when
args
is set, and shell form when
args
is omitted. Set
args
whenever the hook references a
path placeholder
, since each element is passed as one argument with no quoting. Omit
args
when you need shell features like pipes or
&&
, or when neither concern applies.
Exec form
runs when
args
is present. Claude Code resolves
command
as an executable on
PATH
and spawns it directly with
args
as the argument vector. There is no shell, so each
args
element is one argument exactly as written, and path placeholders like
${CLAUDE_PLUGIN_ROOT}
are substituted into
command
and into each
args
element as plain strings. Special characters such as apostrophes,
$
, and backticks pass through verbatim because there is no shell to interpret them. No shell tokenization happens on any platform.
Shell form
runs when
args
is absent. The
command
string is passed to a shell:
sh -c
on macOS and Linux, Git Bash on Windows, or PowerShell when Git Bash isn’t installed. Set the
shell
field to choose explicitly. The shell tokenizes the string, expands variables, and interprets pipes,
&&
, redirects, and globs.
On Windows, exec form requires
command
to resolve to a real executable such as a
.exe
. The
.cmd
and
.bat
shims that npm, npx, eslint, and other tools install in
node_modules/.bin
are not executables and cannot be spawned without a shell. To run them in exec form, invoke the underlying script with
node
directly, for example
"command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]
. The
node
plus script-path pattern works on every platform because
node.exe
is a real binary. To run a
.cmd
or
.bat
shim by name, use shell form.
This example runs a Node script bundled with a plugin. Exec form passes the resolved script path as one argument with no quoting:
{
"type"
:
"command"
,
"command"
:
"node"
,
"args"
: [
"${CLAUDE_PLUGIN_ROOT}/scripts/format.js"
,
"--fix"
]
}
The equivalent shell form needs quoting to handle paths with spaces or special characters:
{
"type"
:
"command"
,
"command"
:
"node
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/format.js --fix"
}
Both forms support the same
path placeholders
, and both export them as the environment variables
CLAUDE_PROJECT_DIR
,
CLAUDE_PLUGIN_ROOT
, and
CLAUDE_PLUGIN_DATA
on the spawned process, so a script can read
process.env.CLAUDE_PLUGIN_ROOT
regardless of how it was launched. Plugin hooks additionally substitute
${user_config.*}
values; see
User configuration
.
In exec form,
command
is the executable name or path only. If
command
is a bare name with no path separator and contains whitespace alongside
args
, Claude Code logs a warning because the spawn will fail: there is no executable named
node script.js
. Move the extra tokens into
args
. Absolute paths with spaces, such as
C:\Program Files\nodejs\node.exe
, are a single valid executable and do not trigger the warning.
​
HTTP hook fields
In addition to the
common fields
, HTTP hooks accept these fields:
Field
Required
Description
url
yes
URL to send the POST request to
headers
no
Additional HTTP headers as key-value pairs. Values support environment variable interpolation using
$VAR_NAME
or
${VAR_NAME}
syntax. Only variables listed in
allowedEnvVars
are resolved
allowedEnvVars
no
List of environment variable names that may be interpolated into header values. References to unlisted variables are replaced with empty strings. Required for any env var interpolation to work
Claude Code sends the hook’s
JSON input
as the POST request body with
Content-Type: application/json
. The response body uses the same
JSON output format
as command hooks.
Error handling differs from command hooks: non-2xx responses, connection failures, and timeouts all produce non-blocking errors that allow execution to continue. To block a tool call or deny a permission, return a 2xx response with a JSON body containing
decision: "block"
or a
hookSpecificOutput
with
permissionDecision: "deny"
.
This example sends
PreToolUse
events to a local validation service, authenticating with a token from the
MY_TOKEN
environment variable:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"http"
,
"url"
:
"http://localhost:8080/hooks/pre-tool-use"
,
"timeout"
:
30
,
"headers"
: {
"Authorization"
:
"Bearer $MY_TOKEN"
},
"allowedEnvVars"
: [
"MY_TOKEN"
]
}
]
}
]
}
}
​
MCP tool hook fields
In addition to the
common fields
, MCP tool hooks accept these fields:
Field
Required
Description
server
yes
Name of a configured MCP server. The server must already be connected; the hook never triggers an OAuth or connection flow
tool
yes
Name of the tool to call on that server
input
no
Arguments passed to the tool. String values support
${path}
substitution from the hook’s
JSON input
, such as
"${tool_input.file_path}"
The tool’s text content is treated like command-hook stdout: if it parses as valid
JSON output
it is processed as a decision, otherwise it is shown as plain text. If the named server is not connected, or the tool returns
isError: true
, the hook produces a non-blocking error and execution continues.
MCP tool hooks are available on every hook event once Claude Code has connected to your MCP servers.
SessionStart
and
Setup
typically fire before servers finish connecting, so hooks on those events should expect the “not connected” error on first run.
This example calls the
security_scan
tool on the
my_server
MCP server after each
Write
or
Edit
, passing the edited file’s path:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"mcp_tool"
,
"server"
:
"my_server"
,
"tool"
:
"security_scan"
,
"input"
: {
"file_path"
:
"${tool_input.file_path}"
}
}
]
}
]
}
}
​
Prompt and agent hook fields
In addition to the
common fields
, prompt and agent hooks accept these fields:
Field
Required
Description
prompt
yes
Prompt text to send to the model. Use
$ARGUMENTS
as a placeholder for the hook input JSON
model
no
Model to use for evaluation. Defaults to a fast model
All matching hooks run in parallel, and identical handlers are deduplicated automatically. Command hooks are deduplicated by command string and
args
, and HTTP hooks are deduplicated by URL. Handlers run in the current directory with Claude Code’s environment. The
$CLAUDE_CODE_REMOTE
environment variable is set to
"true"
in remote web environments and not set in the local CLI.
​
Reference scripts by path
Use these placeholders to reference hook scripts relative to the project or plugin root, regardless of the working directory when the hook runs:
${CLAUDE_PROJECT_DIR}
: the project root.
${CLAUDE_PLUGIN_ROOT}
: the plugin’s installation directory, for scripts bundled with a
plugin
. Changes on each plugin update.
${CLAUDE_PLUGIN_DATA}
: the plugin’s
persistent data directory
, for dependencies and state that should survive plugin updates.
Prefer
exec form
for any hook that references a path placeholder. Exec form passes each
args
element as one argument with no shell tokenization, so paths with spaces or special characters need no quoting. In shell form, wrap each placeholder in double quotes.
Project scripts
Plugin scripts
This example uses
${CLAUDE_PROJECT_DIR}
to run a style checker from the project’s
.claude/hooks/
directory after any
Write
or
Edit
tool call:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh"
,
"args"
: []
}
]
}
]
}
}
Define plugin hooks in
hooks/hooks.json
with an optional top-level
description
field. When a plugin is enabled, its hooks merge with your user and project hooks.
This example runs a formatting script bundled with the plugin:
{
"description"
:
"Automatic code formatting"
,
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
,
"args"
: [],
"timeout"
:
30
}
]
}
]
}
}
See the
plugin components reference
for details on creating plugin hooks.
​
Hooks in skills and agents
In addition to settings files and plugins, hooks can be defined directly in
skills
and
subagents
using frontmatter. These hooks are scoped to the component’s lifecycle and only run when that component is active.
All hook events are supported. For subagents,
Stop
hooks are automatically converted to
SubagentStop
since that is the event that fires when a subagent completes.
Hooks use the same configuration format as settings-based hooks but are scoped to the component’s lifetime and cleaned up when it finishes.
This skill defines a
PreToolUse
hook that runs a security validation script before each
Bash
command:
---
name
:
secure-operations
description
:
Perform operations with security checks
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/security-check.sh"
---
Agents use the same format in their YAML frontmatter.
​
The
/hooks
menu
Type
/hooks
in Claude Code to open a read-only browser for your configured hooks. The menu shows every hook event with a count of configured hooks, lets you drill into matchers, and shows the full details of each hook handler. Use it to verify configuration, check which settings file a hook came from, or inspect a hook’s command, prompt, or URL.
The menu displays all five hook types:
command
,
prompt
,
agent
,
http
, and
mcp_tool
. Each hook is labeled with a
[type]
prefix and a source indicating where it was defined:
User
: from
~/.claude/settings.json
Project
: from
.claude/settings.json
Local
: from
.claude/settings.local.json
Plugin
: from a plugin’s
hooks/hooks.json
Session
: registered in memory for the current session
Built-in
: registered internally by Claude Code
Selecting a hook opens a detail view showing its event, matcher, type, source file, and the full command, prompt, or URL. The menu is read-only: to add, modify, or remove hooks, edit the settings JSON directly or ask Claude to make the change.
​
Disable or remove hooks
To remove a hook, delete its entry from the settings JSON file.
To temporarily disable all hooks without removing them, set
"disableAllHooks": true
in your settings file. There is no way to disable an individual hook while keeping it in the configuration.
The
disableAllHooks
setting respects the managed settings hierarchy. If an administrator has configured hooks through managed policy settings,
disableAllHooks
set in user, project, or local settings cannot disable those managed hooks. Only
disableAllHooks
set at the managed settings level can disable managed hooks.
Direct edits to hooks in settings files are normally picked up automatically by the file watcher.
​
Hook input and output
Command hooks receive JSON data via stdin and communicate results through exit codes, stdout, and stderr. HTTP hooks receive the same JSON as the POST request body and communicate results through the HTTP response body. This section covers fields and behavior common to all events. Each event’s section under
Hook events
includes its specific input schema and decision control options.
On macOS and Linux, command hooks run in their own session without a controlling terminal as of v2.1.139. The hook process and any child processes cannot open
/dev/tty
or send escape sequences directly to the Claude Code interface. Windows has no
/dev/tty
. To surface a message to the user on any platform, return
systemMessage
in JSON output. To trigger a desktop notification, set a window title, or ring the bell, return
terminalSequence
instead.
​
Common input fields
Hook events receive these fields as JSON, in addition to event-specific fields documented in each
hook event
section. For command hooks, this JSON arrives via stdin. For HTTP hooks, it arrives as the POST request body.
Field
Description
session_id
Current session identifier
transcript_path
Path to conversation JSON
cwd
Current working directory when the hook is invoked
permission_mode
Current
permission mode
:
"default"
,
"plan"
,
"acceptEdits"
,
"auto"
,
"dontAsk"
, or
"bypassPermissions"
. Not all events receive this field: see each event’s JSON example below to check
effort
Object with a
level
field holding the active
effort level
for the turn:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. If the requested effort exceeds what the current model supports, this is the downgraded level the model actually used, not the level you requested. The object matches the
status line
effort
field. Present for events that fire within a tool-use context, such as
PreToolUse
,
PostToolUse
,
Stop
, and
SubagentStop
, when the current model supports the effort parameter. The level is also available to hook commands and the Bash tool as the
$CLAUDE_EFFORT
environment variable.
hook_event_name
Name of the event that fired
When running with
--agent
or inside a subagent, two additional fields are included:
Field
Description
agent_id
Unique identifier for the subagent. Present only when the hook fires inside a subagent call. Use this to distinguish subagent hook calls from main-thread calls.
agent_type
Agent name (for example,
"Explore"
or
"security-reviewer"
). Present when the session uses
--agent
or the hook fires inside a subagent. For subagents, the subagent’s type takes precedence over the session’s
--agent
value. For
custom subagents
, this is the
name
field from the agent’s frontmatter, not the filename.
Only
SessionStart
hooks receive a
model
field. There is no
$CLAUDE_MODEL
environment variable. A hook process inherits the parent environment, so it can read
$ANTHROPIC_MODEL
if you set it in your shell, but that value does not change when you switch models with
/model
during a session.
For example, a
PreToolUse
hook for a Bash command receives this on stdin:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/home/user/.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/home/user/my-project"
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PreToolUse"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"npm test"
}
}
The
tool_name
and
tool_input
fields are event-specific. Each
hook event
section documents the additional fields for that event.
​
Exit code output
The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored.
Exit 0
means success. Claude Code parses stdout for
JSON output fields
. JSON output is only processed on exit 0. For most events, stdout is written to the debug log but not shown in the transcript. The exceptions are
UserPromptSubmit
,
UserPromptExpansion
, and
SessionStart
, where stdout is added as context that Claude can see and act on.
Exit 2
means a blocking error. Claude Code ignores stdout and any JSON in it. Instead, stderr text is fed back to Claude as an error message. The effect depends on the event:
PreToolUse
blocks the tool call,
UserPromptSubmit
rejects the prompt, and so on. See
exit code 2 behavior
for the full list.
Any other exit code
is a non-blocking error for most hook events. The transcript shows a
<hook name> hook error
notice followed by the first line of stderr, so you can identify the cause without
--debug
. Execution continues and the full stderr is written to the debug log.
For example, a hook command script that blocks dangerous Bash commands:
#!/bin/bash
# Reads JSON input from stdin, checks the command
command
=
$(
jq
-r
'.tool_input.command'
<
/dev/stdin
)
if
[[
"
$command
"
==
rm
*
]];
then
echo
"Blocked: rm commands are not allowed"
>&2
exit
2
# Blocking error: tool call is prevented
fi
exit
0
# Success: tool call proceeds
For most hook events, only exit code 2 blocks the action. Claude Code treats exit code 1 as a non-blocking error and proceeds with the action, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use
exit 2
. The exception is
WorktreeCreate
, where any non-zero exit code aborts worktree creation.
​
Exit code 2 behavior per event
Exit code 2 is the way a hook signals “stop, don’t do this.” The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn’t happened yet) and others represent things that already happened or can’t be prevented.
Hook event
Can block?
What happens on exit 2
PreToolUse
Yes
Blocks the tool call
PermissionRequest
Yes
Denies the permission
UserPromptSubmit
Yes
Blocks prompt processing and erases the prompt
UserPromptExpansion
Yes
Blocks the expansion
Stop
Yes
Prevents Claude from stopping, continues the conversation
SubagentStop
Yes
Prevents the subagent from stopping
TeammateIdle
Yes
Prevents the teammate from going idle (teammate continues working)
TaskCreated
Yes
Rolls back the task creation
TaskCompleted
Yes
Prevents the task from being marked as completed
ConfigChange
Yes
Blocks the configuration change from taking effect (except
policy_settings
)
StopFailure
No
Output and exit code are ignored
PostToolUse
No
Shows stderr to Claude (tool already ran)
PostToolUseFailure
No
Shows stderr to Claude (tool already failed)
PostToolBatch
Yes
Stops the agentic loop before the next model call
PermissionDenied
No
Exit code and stderr are ignored (denial already occurred). Use JSON
hookSpecificOutput.retry: true
to tell the model it may retry
Notification
No
Shows stderr to user only
SubagentStart
No
Shows stderr to user only
SessionStart
No
Shows stderr to user only
Setup
No
Shows stderr to user only
SessionEnd
No
Shows stderr to user only
CwdChanged
No
Shows stderr to user only
FileChanged
No
Shows stderr to user only
PreCompact
Yes
Blocks compaction
PostCompact
No
Shows stderr to user only
Elicitation
Yes
Denies the elicitation
ElicitationResult
Yes
Blocks the response (action becomes decline)
WorktreeCreate
Yes
Any non-zero exit code causes worktree creation to fail
WorktreeRemove
No
Failures are logged in debug mode only
InstructionsLoaded
No
Exit code is ignored
​
HTTP response handling
HTTP hooks use HTTP status codes and response bodies instead of exit codes and stdout:
2xx with an empty body
: success, equivalent to exit code 0 with no output
2xx with a plain text body
: success, the text is added as context
2xx with a JSON body
: success, parsed using the same
JSON output
schema as command hooks
Non-2xx status
: non-blocking error, execution continues
Connection failure or timeout
: non-blocking error, execution continues
Unlike command hooks, HTTP hooks cannot signal a blocking error through status codes alone. To block a tool call or deny a permission, return a 2xx response with a JSON body containing the appropriate decision fields.
​
JSON output
Exit codes let you allow or block, but JSON output gives you finer-grained control. Instead of exiting with code 2 to block, exit 0 and print a JSON object to stdout. Claude Code reads specific fields from that JSON to control behavior, including
decision control
for blocking, allowing, or escalating to the user.
You must choose one approach per hook, not both: either use exit codes alone for signaling, or exit 0 and print JSON for structured control. Claude Code only processes JSON on exit 0. If you exit 2, any JSON is ignored.
Your hook’s stdout must contain only the JSON object. If your shell profile prints text on startup, it can interfere with JSON parsing. See
JSON validation failed
in the troubleshooting guide.
Hook output strings, including
additionalContext
,
systemMessage
, and plain stdout, are capped at 10,000 characters. Output that exceeds this limit is saved to a file and replaced with a preview and file path, the same way large tool results are handled.
The JSON object supports three kinds of fields:
Universal fields
like
continue
work across all events. These are listed in the table below.
Top-level
decision
and
reason
are used by some events to block or provide feedback.
hookSpecificOutput
is a nested object for events that need richer control. It requires a
hookEventName
field set to the event name.
Field
Default
Description
continue
true
If
false
, Claude stops processing entirely after the hook runs. Takes precedence over any event-specific decision fields
stopReason
none
Message shown to the user when
continue
is
false
. Not shown to Claude
suppressOutput
false
If
true
, omits stdout from the debug log
systemMessage
none
Warning message shown to the user
terminalSequence
none
A terminal escape sequence for Claude Code to emit on your behalf, such as a desktop notification, window title, or bell. Restricted to OSC
0
/
1
/
2
/
9
/
99
/
777
and BEL. If the value contains anything outside the allowlist, the field is ignored. Use this instead of writing to
/dev/tty
, which is unavailable to hooks
To stop Claude entirely regardless of event type:
{
"continue"
:
false
,
"stopReason"
:
"Build failed, fix errors before continuing"
}
​
Emit terminal notifications
The
terminalSequence
field requires Claude Code v2.1.141 or later.
Hooks run without a controlling terminal, so writing escape sequences directly to
/dev/tty
fails. Instead, return the escape sequence in the
terminalSequence
field and Claude Code emits it for you through its own terminal write path. This is race-free, works inside tmux and GNU screen, and works on Windows where there is no
/dev/tty
.
The field accepts a string of one or more allowlisted escape sequences:
OSC
0
,
1
,
2
: window and icon titles
OSC
9
: iTerm2, ConEmu, Windows Terminal, and WezTerm notifications, including
9;4
taskbar progress
OSC
99
: Kitty notifications
OSC
777
: urxvt, Ghostty, and Warp notifications
Bare BEL
Sequences may be terminated with BEL or with ST. Anything outside the allowlist, including CSI cursor and color sequences, OSC palette sequences, OSC 8 hyperlinks, OSC 52 clipboard writes, and OSC 1337, is rejected and the field is ignored.
The example below fires a desktop notification from a
Notification
hook. The escape sequence is built with
printf
octal escapes so the control bytes never appear on the shell command line, and
jq -n --arg
builds the JSON output so quotes, backslashes, and newlines in the notification message are escaped correctly:
#!/bin/bash
# Notification hook: ping the desktop when Claude Code needs attention.
input
=
$(
cat
)
title
=
"Claude Code"
body
=
$(
jq
-r
'.message // "Needs your attention"'
<<<
"
$input
"
)
seq
=
$(
printf
'\033]777;notify;%s;%s\007'
"
$title
"
"
$body
"
)
jq
-nc
--arg
seq
"
$seq
"
'{terminalSequence: $seq}'
The
{ "terminalSequence": "..." }
shape is the same from any shell or language. On Windows, build the escape string in PowerShell or a script and emit the same JSON object.
terminalSequence
is the supported replacement for hooks that previously wrote escape sequences directly to
/dev/tty
. The allowlist is restricted to sequences that cannot move the cursor or alter colors, so a hook can never corrupt an on-screen prompt.
​
Add context for Claude
The
additionalContext
field passes a string from your hook into Claude’s context window. Claude Code wraps the string in a system reminder and inserts it into the conversation at the point where the hook fired. Claude reads the reminder on the next model request, but it does not appear as a chat message in the interface.
Return
additionalContext
inside
hookSpecificOutput
alongside the event name:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUse"
,
"additionalContext"
:
"This file is generated. Edit src/schema.ts and run `bun generate` instead."
}
}
Where the reminder appears depends on the event:
SessionStart
,
Setup
, and
SubagentStart
: at the start of the conversation, before the first prompt
UserPromptSubmit
and
UserPromptExpansion
: alongside the submitted prompt
PreToolUse
,
PostToolUse
,
PostToolUseFailure
, and
PostToolBatch
: next to the tool result
When several hooks return
additionalContext
for the same event, Claude receives all of the values. If a value exceeds 10,000 characters, Claude Code writes the full text to a file in the session directory and passes Claude the file path with a short preview instead.
Use
additionalContext
for information Claude should know about the current state of your environment or the operation that just ran:
Environment state
: the current branch, deployment target, or active feature flags
Conditional project rules
: which test command applies to the file just edited, which directories are read-only in this worktree
External data
: open issues assigned to you, recent CI results, content fetched from an internal service
For instructions that never change, prefer
CLAUDE.md
. It loads without running a script and is the standard place for static project conventions.
Write the text as factual statements rather than imperative system instructions. Phrasing such as “The deployment target is production” or “This repo uses
bun test
” reads as project information. Text framed as out-of-band system commands can trigger Claude’s prompt-injection defenses, which causes Claude to surface the text to you instead of treating it as context.
Once injected, the text is saved in the session transcript. For mid-session events like
PostToolUse
or
UserPromptSubmit
, resuming with
--continue
or
--resume
replays the saved text rather than re-running the hook for past turns, so values like timestamps or commit SHAs become stale on resume.
SessionStart
hooks run again on resume with
source
set to
"resume"
, so they can refresh their context.
​
Decision control
Not every event supports blocking or controlling behavior through JSON. The events that do each use a different set of fields to express that decision. Use this table as a quick reference before writing a hook:
Events
Decision pattern
Key fields
UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact
Top-level
decision
decision: "block"
,
reason
TeammateIdle, TaskCreated, TaskCompleted
Exit code or
continue: false
Exit code 2 blocks the action with stderr feedback. JSON
{"continue": false, "stopReason": "..."}
also stops the teammate entirely, matching
Stop
hook behavior
PreToolUse
hookSpecificOutput
permissionDecision
(allow/deny/ask/defer),
permissionDecisionReason
PermissionRequest
hookSpecificOutput
decision.behavior
(allow/deny)
PermissionDenied
hookSpecificOutput
retry: true
tells the model it may retry the denied tool call
WorktreeCreate
path return
Command hook prints path on stdout; HTTP hook returns
hookSpecificOutput.worktreePath
. Hook failure or missing path fails creation
Elicitation
hookSpecificOutput
action
(accept/decline/cancel),
content
(form field values for accept)
ElicitationResult
hookSpecificOutput
action
(accept/decline/cancel),
content
(form field values override)
WorktreeRemove, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, FileChanged
None
No decision control. Used for side effects like logging or cleanup
Here are examples of each pattern in action:
Top-level decision
PreToolUse
PermissionRequest
Used by
UserPromptSubmit
,
UserPromptExpansion
,
PostToolUse
,
PostToolUseFailure
,
PostToolBatch
,
Stop
,
SubagentStop
,
ConfigChange
, and
PreCompact
. The only value is
"block"
. To allow the action to proceed, omit
decision
from your JSON, or exit 0 without any JSON at all:
{
"decision"
:
"block"
,
"reason"
:
"Test suite must pass before proceeding"
}
Uses
hookSpecificOutput
for richer control: allow, deny, or escalate to the user. You can also modify tool input before it runs or inject additional context for Claude. See
PreToolUse decision control
for the full set of options.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Database writes are not allowed"
}
}
Uses
hookSpecificOutput
to allow or deny a permission request on behalf of the user. When allowing, you can also modify the tool’s input or apply permission rules so the user isn’t prompted again. See
PermissionRequest decision control
for the full set of options.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedInput"
: {
"command"
:
"npm run lint"
}
}
}
}
For extended examples including Bash command validation, prompt filtering, and auto-approval scripts, see
What you can automate
in the guide and the
Bash command validator reference implementation
.
​
Hook events
Each event corresponds to a point in Claude Code’s lifecycle where hooks can run. The sections below are ordered to match the lifecycle: from session setup through the agentic loop to session end. Each section describes when the event fires, what matchers it supports, the JSON input it receives, and how to control behavior through output.
​
SessionStart
Runs when Claude Code starts a new session or resumes an existing session. Useful for loading development context like existing issues or recent changes to your codebase, or setting up environment variables. For static context that does not require a script, use
CLAUDE.md
instead.
SessionStart runs on every session, so keep these hooks fast. Only
type: "command"
and
type: "mcp_tool"
hooks are supported.
The matcher value corresponds to how the session was initiated:
Matcher
When it fires
startup
New session
resume
--resume
,
--continue
, or
/resume
clear
/clear
compact
Auto or manual compaction
​
SessionStart input
In addition to the
common input fields
, SessionStart hooks receive
source
,
model
, and optionally
agent_type
. The
source
field indicates how the session started:
"startup"
for new sessions,
"resume"
for resumed sessions,
"clear"
after
/clear
, or
"compact"
after compaction. The
model
field contains the model identifier. If you start Claude Code with
claude --agent <name>
, an
agent_type
field contains the agent name.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SessionStart"
,
"source"
:
"startup"
,
"model"
:
"claude-sonnet-4-6"
}
​
SessionStart decision control
Any text your hook script prints to stdout is added as context for Claude. In addition to the
JSON output fields
available to all hooks, you can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context at the start of the conversation, before the first prompt. See
Add context for Claude
for how the text is delivered and what to put in it
{
"hookSpecificOutput"
: {
"hookEventName"
:
"SessionStart"
,
"additionalContext"
:
"Current branch: feat/auth-refactor
\n
Uncommitted changes: src/auth.ts, src/login.tsx
\n
Active issue: #4211 Migrate to OAuth2"
}
}
Since plain stdout already reaches Claude for this event, a hook that only loads context can print to stdout directly without building JSON. Use the JSON form when you need to combine context with other fields such as
suppressOutput
.
​
Persist environment variables
SessionStart hooks have access to the
CLAUDE_ENV_FILE
environment variable, which provides a file path where you can persist environment variables for subsequent Bash commands.
To set individual environment variables, write
export
statements to
CLAUDE_ENV_FILE
. Use append (
>>
) to preserve variables set by other hooks:
#!/bin/bash
if
[
-n
"
$CLAUDE_ENV_FILE
"
];
then
echo
'export NODE_ENV=production'
>>
"
$CLAUDE_ENV_FILE
"
echo
'export DEBUG_LOG=true'
>>
"
$CLAUDE_ENV_FILE
"
echo
'export PATH="$PATH:./node_modules/.bin"'
>>
"
$CLAUDE_ENV_FILE
"
fi
exit
0
To capture all environment changes from setup commands, compare the exported variables before and after:
#!/bin/bash
ENV_BEFORE
=
$(e
xport
-p
|
sort
)
# Run your setup commands that modify the environment
source
~/.nvm/nvm.sh
nvm
use
20
if
[
-n
"
$CLAUDE_ENV_FILE
"
];
then
ENV_AFTER
=
$(e
xport
-p
|
sort
)
comm
-13
<(
echo
"
$ENV_BEFORE
")
<(
echo
"
$ENV_AFTER
")
>>
"
$CLAUDE_ENV_FILE
"
fi
exit
0
Any variables written to this file will be available in all subsequent Bash commands that Claude Code executes during the session.
CLAUDE_ENV_FILE
is available for SessionStart,
Setup
,
CwdChanged
, and
FileChanged
hooks. Other hook types do not have access to this variable.
​
Setup
Fires only when you launch Claude Code with
--init-only
, or with
--init
or
--maintenance
in print mode (
-p
). It does not fire on normal startup. Use it for one-time dependency installation or scheduled cleanup that you trigger explicitly from CI or scripts, separate from normal session startup. For per-session initialization, use
SessionStart
instead.
The matcher value corresponds to the CLI flag that triggered the hook:
Matcher
When it fires
init
claude --init-only
or
claude -p --init
maintenance
claude -p --maintenance
--init-only
runs Setup hooks and
SessionStart
hooks with the
startup
matcher, then exits without starting a conversation.
--init
and
--maintenance
fire Setup hooks only when combined with
-p
(print mode); in an interactive session those two flags do not currently fire Setup hooks.
Because Setup does not fire on every launch, a plugin that needs a dependency installed cannot rely on Setup alone. The practical pattern is to check for the dependency on first use and install on miss, for example a hook or skill that tests for
${CLAUDE_PLUGIN_DATA}/node_modules
and runs
npm install
if absent. See the
persistent data directory
for where to store installed dependencies.
​
Setup input
In addition to the
common input fields
, Setup hooks receive a
trigger
field set to either
"init"
or
"maintenance"
:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"Setup"
,
"trigger"
:
"init"
}
​
Setup decision control
Setup hooks cannot block. On exit code 2, stderr is shown to the user; on any other non-zero exit code, stderr appears only when you launch with
--verbose
. In both cases execution continues. To pass information into Claude’s context, return
additionalContext
in JSON output; plain stdout is written to the debug log only. In addition to the
JSON output fields
available to all hooks, you can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context. Multiple hooks’ values are concatenated
{
"hookSpecificOutput"
: {
"hookEventName"
:
"Setup"
,
"additionalContext"
:
"Dependencies installed: node_modules, .venv"
}
}
Setup hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
. Only
type: "command"
and
type: "mcp_tool"
hooks are supported.
​
InstructionsLoaded
Fires when a
CLAUDE.md
or
.claude/rules/*.md
file is loaded into context. This event fires at session start for eagerly-loaded files and again later when files are lazily loaded, for example when Claude accesses a subdirectory that contains a nested
CLAUDE.md
or when conditional rules with
paths:
frontmatter match. The hook does not support blocking or decision control. It runs asynchronously for observability purposes.
The matcher runs against
load_reason
. For example, use
"matcher": "session_start"
to fire only for files loaded at session start, or
"matcher": "path_glob_match|nested_traversal"
to fire only for lazy loads.
​
InstructionsLoaded input
In addition to the
common input fields
, InstructionsLoaded hooks receive these fields:
Field
Description
file_path
Absolute path to the instruction file that was loaded
memory_type
Scope of the file:
"User"
,
"Project"
,
"Local"
, or
"Managed"
load_reason
Why the file was loaded:
"session_start"
,
"nested_traversal"
,
"path_glob_match"
,
"include"
, or
"compact"
. The
"compact"
value fires when instruction files are re-loaded after a compaction event
globs
Path glob patterns from the file’s
paths:
frontmatter, if any. Present only for
path_glob_match
loads
trigger_file_path
Path to the file whose access triggered this load, for lazy loads
parent_file_path
Path to the parent instruction file that included this one, for
include
loads
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project"
,
"hook_event_name"
:
"InstructionsLoaded"
,
"file_path"
:
"/Users/my-project/CLAUDE.md"
,
"memory_type"
:
"Project"
,
"load_reason"
:
"session_start"
}
​
InstructionsLoaded decision control
InstructionsLoaded hooks have no decision control. They cannot block or modify instruction loading. Use this event for audit logging, compliance tracking, or observability.
​
UserPromptSubmit
Runs when the user submits a prompt, before Claude processes it. This allows you
to add additional context based on the prompt/conversation, validate prompts, or
block certain types of prompts.
UserPromptSubmit
hooks have a default timeout of 30 seconds for
command
,
http
, and
mcp_tool
types, shorter than the 600-second default for those types on other events. Because this hook runs before every prompt and blocks model processing until it completes, a stuck hook stalls the session. If your hook needs more time, set the
timeout
field in the hook entry.
​
UserPromptSubmit input
In addition to the
common input fields
, UserPromptSubmit hooks receive the
prompt
field containing the text the user submitted.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"UserPromptSubmit"
,
"prompt"
:
"Write a function to calculate the factorial of a number"
}
​
UserPromptSubmit decision control
UserPromptSubmit
hooks can control whether a user prompt is processed and add context. All
JSON output fields
are available.
There are two ways to add context to the conversation on exit code 0:
Plain text stdout
: any non-JSON text written to stdout is added as context
JSON with
additionalContext
: use the JSON format below for more control. The
additionalContext
field is added as context
Plain stdout is shown as hook output in the transcript. The
additionalContext
field is added more discretely.
To block a prompt, return a JSON object with
decision
set to
"block"
:
Field
Description
decision
"block"
prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed
reason
Shown to the user when
decision
is
"block"
. Not added to context
additionalContext
String added to Claude’s context alongside the submitted prompt. See
Add context for Claude
sessionTitle
Sets the session title. Use to name sessions automatically based on the prompt content
{
"decision"
:
"block"
,
"reason"
:
"Explanation for decision"
,
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptSubmit"
,
"additionalContext"
:
"My additional context here"
,
"sessionTitle"
:
"My session title"
}
}
The JSON format isn’t required for simple use cases. To add context, you can print plain text to stdout with exit code 0. Use JSON when you need to
block prompts or want more structured control.
​
UserPromptExpansion
Runs when a user-typed slash command expands into a prompt before reaching Claude. Use this to block specific commands from direct invocation, inject context for a particular skill, or log which commands users invoke. For example, a hook matching
deploy
can block
/deploy
unless an approval file is present, or a hook matching a review skill can append the team’s review checklist as
additionalContext
.
This event covers the path
PreToolUse
does not: a
PreToolUse
hook matching the
Skill
tool fires only when Claude calls the tool, but typing
/skillname
directly bypasses
PreToolUse
.
UserPromptExpansion
fires on that direct path.
Matches on
command_name
. Leave the matcher empty to fire on every prompt-type slash command.
​
UserPromptExpansion input
In addition to the
common input fields
, UserPromptExpansion hooks receive
expansion_type
,
command_name
,
command_args
,
command_source
, and the original
prompt
string. The
expansion_type
field is
slash_command
for skill and custom commands, or
mcp_prompt
for MCP server prompts.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../00893aaf.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"UserPromptExpansion"
,
"expansion_type"
:
"slash_command"
,
"command_name"
:
"example-skill"
,
"command_args"
:
"arg1 arg2"
,
"command_source"
:
"plugin"
,
"prompt"
:
"/example-skill arg1 arg2"
}
​
UserPromptExpansion decision control
UserPromptExpansion
hooks can block the expansion or add context. All
JSON output fields
are available.
Field
Description
decision
"block"
prevents the slash command from expanding. Omit to allow it to proceed
reason
Shown to the user when
decision
is
"block"
additionalContext
String added to Claude’s context alongside the expanded prompt. See
Add context for Claude
{
"decision"
:
"block"
,
"reason"
:
"This slash command is not available"
,
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptExpansion"
,
"additionalContext"
:
"Additional context for this expansion"
}
}
​
PreToolUse
Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name:
Bash
,
Edit
,
Write
,
Read
,
Glob
,
Grep
,
Agent
,
WebFetch
,
WebSearch
,
AskUserQuestion
,
ExitPlanMode
, and any
MCP tool names
.
Use
PreToolUse decision control
to allow, deny, ask, or defer the tool call.
​
PreToolUse input
In addition to the
common input fields
, PreToolUse hooks receive
tool_name
,
tool_input
, and
tool_use_id
. The
tool_input
fields depend on the tool:
Bash
Executes shell commands.
Field
Type
Example
Description
command
string
"npm test"
The shell command to execute
description
string
"Run test suite"
Optional description of what the command does
timeout
number
120000
Optional timeout in milliseconds
run_in_background
boolean
false
Whether to run the command in background
Write
Creates or overwrites a file.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to write
content
string
"file content"
Content to write to the file
Edit
Replaces a string in an existing file.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to edit
old_string
string
"original text"
Text to find and replace
new_string
string
"replacement text"
Replacement text
replace_all
boolean
false
Whether to replace all occurrences
Read
Reads file contents.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to read
offset
number
10
Optional line number to start reading from
limit
number
50
Optional number of lines to read
Glob
Finds files matching a glob pattern.
Field
Type
Example
Description
pattern
string
"**/*.ts"
Glob pattern to match files against
path
string
"/path/to/dir"
Optional directory to search in. Defaults to current working directory
Grep
Searches file contents with regular expressions.
Field
Type
Example
Description
pattern
string
"TODO.*fix"
Regular expression pattern to search for
path
string
"/path/to/dir"
Optional file or directory to search in
glob
string
"*.ts"
Optional glob pattern to filter files
output_mode
string
"content"
"content"
,
"files_with_matches"
, or
"count"
. Defaults to
"files_with_matches"
-i
boolean
true
Case insensitive search
multiline
boolean
false
Enable multiline matching
WebFetch
Fetches and processes web content.
Field
Type
Example
Description
url
string
"https://example.com/api"
URL to fetch content from
prompt
string
"Extract the API endpoints"
Prompt to run on the fetched content
WebSearch
Searches the web.
Field
Type
Example
Description
query
string
"react hooks best practices"
Search query
allowed_domains
array
["docs.example.com"]
Optional: only include results from these domains
blocked_domains
array
["spam.example.com"]
Optional: exclude results from these domains
Agent
Spawns a
subagent
.
Field
Type
Example
Description
prompt
string
"Find all API endpoints"
The task for the agent to perform
description
string
"Find API endpoints"
Short description of the task
subagent_type
string
"Explore"
Type of specialized agent to use
model
string
"sonnet"
Optional model alias to override the default
In
PostToolUse
,
tool_response
for a completed Agent call carries the subagent’s final text along with usage telemetry. Read these fields to record per-subagent cost from a hook:
Field
Type
Example
Description
status
string
"completed"
"completed"
for synchronous calls,
"async_launched"
for
run_in_background: true
agentId
string
"a4d2c8f1e0b3a297"
Identifier for the subagent run
content
array
[{"type": "text", "text": "Found 12 endpoints..."}]
The subagent’s final text blocks
totalTokens
number
12450
Total tokens billed across the subagent’s turns
totalDurationMs
number
48211
Wall-clock duration of the subagent run
totalToolUseCount
number
7
Count of tool calls the subagent made
usage
object
{"input_tokens": 8320, ...}
Per-type token breakdown:
input_tokens
,
output_tokens
,
cache_creation_input_tokens
,
cache_read_input_tokens
For
run_in_background: true
calls, the tool returns immediately after launching the subagent, so
tool_response
carries no usage fields. It has
status: "async_launched"
,
agentId
,
description
,
prompt
, and
outputFile
instead.
AskUserQuestion
Asks the user one to four multiple-choice questions.
Field
Type
Example
Description
questions
array
[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]
Questions to present, each with a
question
string, short
header
,
options
array, and optional
multiSelect
flag
answers
object
{"Which framework?": "React"}
Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude does not set this field; supply it via
updatedInput
to answer programmatically
ExitPlanMode
Presents a plan and asks the user to approve it before Claude leaves
plan mode
. Claude writes the plan to a file on disk before calling the tool, so the literal
tool_input
from the model only carries
allowedPrompts
. Claude Code injects the plan content and file path before passing the input to hooks.
Field
Type
Example
Description
plan
string
"## Refactor auth\n1. Extract..."
Plan content in Markdown. Injected from the plan file on disk
planFilePath
string
"/Users/.../plans/refactor-auth.md"
Path to the plan file. Injected
allowedPrompts
array
[{"tool": "Bash", "prompt": "run tests"}]
Optional. Prompt-based permissions Claude is requesting to implement the plan, each with a
tool
name and a
prompt
describing the category of action
In
PostToolUse
,
tool_response
is an object with
plan
and
filePath
fields holding the approved plan, plus internal status flags. Read
tool_response.plan
for the plan content rather than re-reading the file from disk.
​
PreToolUse decision control
PreToolUse
hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level
decision
field, PreToolUse returns its decision inside a
hookSpecificOutput
object. This gives it richer control: four outcomes (allow, deny, ask, or defer) plus the ability to modify tool input before execution.
Field
Description
permissionDecision
"allow"
skips the permission prompt.
"deny"
prevents the tool call.
"ask"
prompts the user to confirm.
"defer"
exits gracefully so the tool can be resumed later.
Deny and ask rules
are still evaluated regardless of what the hook returns
permissionDecisionReason
For
"allow"
and
"ask"
, shown to the user but not Claude. For
"deny"
, shown to Claude. For
"defer"
, ignored
updatedInput
Modifies the tool’s input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Combine with
"allow"
to auto-approve, or
"ask"
to show the modified input to the user. For
"defer"
, ignored
additionalContext
String added to Claude’s context alongside the tool result. Ignored when
permissionDecision
is
"defer"
. See
Add context for Claude
When multiple PreToolUse hooks return different decisions, precedence is
deny
>
defer
>
ask
>
allow
.
When a hook returns
"ask"
, the permission prompt displayed to the user includes a label identifying where the hook came from: for example,
[User]
,
[Project]
,
[Plugin]
, or
[Local]
. This helps users understand which configuration source is requesting confirmation.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"allow"
,
"permissionDecisionReason"
:
"My reason here"
,
"updatedInput"
: {
"field_to_modify"
:
"new value"
},
"additionalContext"
:
"Current environment: production. Proceed with caution."
}
}
AskUserQuestion
and
ExitPlanMode
require user interaction and normally block in
non-interactive mode
with the
-p
flag. Returning
permissionDecision: "allow"
together with
updatedInput
satisfies that requirement: the hook reads the tool’s input from stdin, collects the answer through your own UI, and returns it in
updatedInput
so the tool runs without prompting. Returning
"allow"
alone is not sufficient for these tools. For
AskUserQuestion
, echo back the original
questions
array and add an
answers
object mapping each question’s text to the chosen answer.
PreToolUse previously used top-level
decision
and
reason
fields, but these are deprecated for this event. Use
hookSpecificOutput.permissionDecision
and
hookSpecificOutput.permissionDecisionReason
instead. The deprecated values
"approve"
and
"block"
map to
"allow"
and
"deny"
respectively. Other events like PostToolUse and Stop continue to use top-level
decision
and
reason
as their current format.
​
Defer a tool call for later
"defer"
is for integrations that run
claude -p
as a subprocess and read its JSON output, such as an Agent SDK app or a custom UI built on top of Claude Code. It lets that calling process pause Claude at a tool call, collect input through its own interface, and resume where it left off. Claude Code honors this value only in
non-interactive mode
with the
-p
flag. In interactive sessions it logs a warning and ignores the hook result.
The
defer
value requires Claude Code v2.1.89 or later. Earlier versions do not recognize it and the tool proceeds through the normal permission flow.
The
AskUserQuestion
tool is the typical case: Claude wants to ask the user something, but there is no terminal to answer in. The round trip works like this:
Claude calls
AskUserQuestion
. The
PreToolUse
hook fires.
The hook returns
permissionDecision: "defer"
. The tool does not execute. The process exits with
stop_reason: "tool_deferred"
and the pending tool call preserved in the transcript.
The calling process reads
deferred_tool_use
from the SDK result, surfaces the question in its own UI, and waits for an answer.
The calling process runs
claude -p --resume <session-id>
. The same tool call fires
PreToolUse
again.
The hook returns
permissionDecision: "allow"
with the answer in
updatedInput
. The tool executes and Claude continues.
The
deferred_tool_use
field carries the tool’s
id
,
name
, and
input
. The
input
is the parameters Claude generated for the tool call, captured before execution:
{
"type"
:
"result"
,
"subtype"
:
"success"
,
"stop_reason"
:
"tool_deferred"
,
"session_id"
:
"abc123"
,
"deferred_tool_use"
: {
"id"
:
"toolu_01abc"
,
"name"
:
"AskUserQuestion"
,
"input"
: {
"questions"
: [{
"question"
:
"Which framework?"
,
"header"
:
"Framework"
,
"options"
: [{
"label"
:
"React"
}, {
"label"
:
"Vue"
}],
"multiSelect"
:
false
}] }
}
}
There is no timeout or retry limit. The session remains on disk until you resume it, subject to the
cleanupPeriodDays
retention sweep that deletes session files after 30 days by default. If the answer is not ready when you resume, the hook can return
"defer"
again and the process exits the same way. The calling process controls when to break the loop by eventually returning
"allow"
or
"deny"
from the hook.
"defer"
only works when Claude makes a single tool call in the turn. If Claude makes several tool calls at once,
"defer"
is ignored with a warning and the tool proceeds through the normal permission flow. The constraint exists because resume can only re-run one tool: there is no way to defer one call from a batch without leaving the others unresolved.
If the deferred tool is no longer available when you resume, the process exits with
stop_reason: "tool_deferred_unavailable"
and
is_error: true
before the hook fires. This happens when an MCP server that provided the tool is not connected for the resumed session. The
deferred_tool_use
payload is still included so you can identify which tool went missing.
--resume
restores the permission mode that was active when the tool was deferred, so you do not need to pass
--permission-mode
again. The exceptions are
plan
and
bypassPermissions
, which are never carried over. Passing
--permission-mode
explicitly on resume overrides the restored value.
​
PermissionRequest
Runs when the user is shown a permission dialog.
Use
PermissionRequest decision control
to allow or deny on behalf of the user.
Matches on tool name, same values as PreToolUse.
​
PermissionRequest input
PermissionRequest hooks receive
tool_name
and
tool_input
fields like PreToolUse hooks, but without
tool_use_id
. An optional
permission_suggestions
array contains the “always allow” options the user would normally see in the permission dialog. The difference is when the hook fires: PermissionRequest hooks run when a permission dialog is about to be shown to the user, while PreToolUse hooks run before tool execution regardless of permission status.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PermissionRequest"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf node_modules"
,
"description"
:
"Remove node_modules directory"
},
"permission_suggestions"
: [
{
"type"
:
"addRules"
,
"rules"
: [{
"toolName"
:
"Bash"
,
"ruleContent"
:
"rm -rf node_modules"
}],
"behavior"
:
"allow"
,
"destination"
:
"localSettings"
}
]
}
​
PermissionRequest decision control
PermissionRequest
hooks can allow or deny permission requests. In addition to the
JSON output fields
available to all hooks, your hook script can return a
decision
object with these event-specific fields:
Field
Description
behavior
"allow"
grants the permission,
"deny"
denies it.
Deny and ask rules
are still evaluated, so a hook returning
"allow"
does not override a matching deny rule
updatedInput
For
"allow"
only: modifies the tool’s input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. The modified input is re-evaluated against deny and ask rules
updatedPermissions
For
"allow"
only: array of
permission update entries
to apply, such as adding an allow rule or changing the session permission mode
message
For
"deny"
only: tells Claude why the permission was denied
interrupt
For
"deny"
only: if
true
, stops Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedInput"
: {
"command"
:
"npm run lint"
}
}
}
}
​
Permission update entries
The
updatedPermissions
output field and the
permission_suggestions
input field
both use the same array of entry objects. Each entry has a
type
that determines its other fields, and a
destination
that controls where the change is written.
type
Fields
Effect
addRules
rules
,
behavior
,
destination
Adds permission rules.
rules
is an array of
{toolName, ruleContent?}
objects. Omit
ruleContent
to match the whole tool.
behavior
is
"allow"
,
"deny"
, or
"ask"
replaceRules
rules
,
behavior
,
destination
Replaces all rules of the given
behavior
at the
destination
with the provided
rules
removeRules
rules
,
behavior
,
destination
Removes matching rules of the given
behavior
setMode
mode
,
destination
Changes the permission mode. Valid modes are
default
,
acceptEdits
,
dontAsk
,
bypassPermissions
, and
plan
addDirectories
directories
,
destination
Adds working directories.
directories
is an array of path strings
removeDirectories
directories
,
destination
Removes working directories
setMode
with
bypassPermissions
only takes effect if the session was launched with bypass mode already available:
--dangerously-skip-permissions
,
--permission-mode bypassPermissions
,
--allow-dangerously-skip-permissions
, or
permissions.defaultMode: "bypassPermissions"
in settings, and the mode is not disabled by
permissions.disableBypassPermissionsMode
. Otherwise the update is a no-op.
bypassPermissions
is never persisted as
defaultMode
regardless of
destination
.
The
destination
field on every entry determines whether the change stays in memory or persists to a settings file.
destination
Writes to
session
in-memory only, discarded when the session ends
localSettings
.claude/settings.local.json
projectSettings
.claude/settings.json
userSettings
~/.claude/settings.json
A hook can echo one of the
permission_suggestions
it received as its own
updatedPermissions
output, which is equivalent to the user selecting that “always allow” option in the dialog.
​
PostToolUse
Runs immediately after a tool completes successfully.
Matches on tool name, same values as PreToolUse.
​
PostToolUse input
PostToolUse
hooks fire after a tool has already executed successfully. The input includes both
tool_input
, the arguments sent to the tool, and
tool_response
, the result it returned. The exact schema for both depends on the tool.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolUse"
,
"tool_name"
:
"Write"
,
"tool_input"
: {
"file_path"
:
"/path/to/file.txt"
,
"content"
:
"file content"
},
"tool_response"
: {
"filePath"
:
"/path/to/file.txt"
,
"success"
:
true
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"duration_ms"
:
12
}
Field
Description
duration_ms
Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks
​
PostToolUse decision control
PostToolUse
hooks can provide feedback to Claude after tool execution. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
decision
"block"
adds the
reason
next to the tool result. Claude still sees the original output; to replace it, use
updatedToolOutput
reason
Explanation shown to Claude when
decision
is
"block"
additionalContext
String added to Claude’s context alongside the tool result. See
Add context for Claude
updatedToolOutput
Replaces the tool’s output with the provided value before it is sent to Claude. The value must match the tool’s output shape
updatedMCPToolOutput
Replaces the output for
MCP tools
only. Prefer
updatedToolOutput
, which works for all tools
The example below replaces the output of a
Bash
call. The replacement value matches the
Bash
tool’s output shape:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUse"
,
"additionalContext"
:
"Additional information for Claude"
,
"updatedToolOutput"
: {
"stdout"
:
"[redacted]"
,
"stderr"
:
""
,
"interrupted"
:
false
,
"isImage"
:
false
}
}
}
updatedToolOutput
only changes what Claude sees. The tool has already run by the time the hook fires, so any files written, commands executed, or network requests sent have already taken effect. Telemetry such as OpenTelemetry tool spans and analytics events also captures the original output before the hook runs. To prevent or modify a tool call before it runs, use a
PreToolUse
hook instead.
The replacement value must match the tool’s output shape. Built-in tools return structured objects rather than plain strings. For example,
Bash
returns an object with
stdout
,
stderr
,
interrupted
, and
isImage
fields. For built-in tools, a value that does not match the tool’s output schema is ignored and the original output is used. MCP tool output is passed through without schema validation. Stripping error details that Claude needs can cause it to proceed on a false assumption.
​
PostToolUseFailure
Runs when a tool execution fails. This event fires for tool calls that throw errors or return failure results. Use this to log failures, send alerts, or provide corrective feedback to Claude.
Matches on tool name, same values as PreToolUse.
​
PostToolUseFailure input
PostToolUseFailure hooks receive the same
tool_name
and
tool_input
fields as PostToolUse, along with error information as top-level fields:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolUseFailure"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"npm test"
,
"description"
:
"Run test suite"
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"error"
:
"Command exited with non-zero status code 1"
,
"is_interrupt"
:
false
,
"duration_ms"
:
4187
}
Field
Description
error
String describing what went wrong
is_interrupt
Optional boolean indicating whether the failure was caused by user interruption
duration_ms
Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks
​
PostToolUseFailure decision control
PostToolUseFailure
hooks can provide context to Claude after a tool failure. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context alongside the error. See
Add context for Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUseFailure"
,
"additionalContext"
:
"Additional information about the failure for Claude"
}
}
​
PostToolBatch
Runs once after every tool call in a batch has resolved, before Claude Code sends the next request to the model.
PostToolUse
fires once per tool, which means it fires concurrently when Claude makes parallel tool calls.
PostToolBatch
fires exactly once with the full batch, so it is the right place to inject context that depends on the set of tools that ran rather than on any single tool. There is no matcher for this event.
​
PostToolBatch input
In addition to the
common input fields
, PostToolBatch hooks receive
tool_calls
, an array describing every tool call in the batch:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolBatch"
,
"tool_calls"
: [
{
"tool_name"
:
"Read"
,
"tool_input"
: {
"file_path"
:
"/.../ledger/accounts.py"
},
"tool_use_id"
:
"toolu_01..."
,
"tool_response"
:
"     1
\t
from __future__ import annotations
\n
2
\t
..."
},
{
"tool_name"
:
"Read"
,
"tool_input"
: {
"file_path"
:
"/.../ledger/transactions.py"
},
"tool_use_id"
:
"toolu_02..."
,
"tool_response"
:
"     1
\t
from __future__ import annotations
\n
2
\t
..."
}
]
}
tool_response
contains the same content the model receives in the corresponding
tool_result
block. The value is a serialized string or content-block array, exactly as the tool emitted it. For
Read
, that means line-number-prefixed text rather than raw file contents. Responses can be large, so parse only the fields you need.
The
tool_response
shape differs from
PostToolUse
’s.
PostToolUse
passes the tool’s structured
Output
object, such as
{filePath: "...", success: true}
for
Write
;
PostToolBatch
passes the serialized
tool_result
content the model sees.
​
PostToolBatch decision control
PostToolBatch
hooks can inject context for Claude. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
additionalContext
Context string injected once before the next model call. See
Add context for Claude
for delivery details, what to put in it, and how resumed sessions handle past values
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolBatch"
,
"additionalContext"
:
"These files are part of the ledger module. Run pytest before marking the task complete."
}
}
Returning
decision: "block"
or
continue: false
stops the agentic loop before the next model call.
​
PermissionDenied
Runs when the
auto mode
classifier denies a tool call. This hook only fires in auto mode: it does not run when you manually deny a permission dialog, when a
PreToolUse
hook blocks a call, or when a
deny
rule matches. Use it to log classifier denials, adjust configuration, or tell the model it may retry the tool call.
Matches on tool name, same values as PreToolUse.
​
PermissionDenied input
In addition to the
common input fields
, PermissionDenied hooks receive
tool_name
,
tool_input
,
tool_use_id
, and
reason
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"auto"
,
"hook_event_name"
:
"PermissionDenied"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf /tmp/build"
,
"description"
:
"Clean build directory"
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"reason"
:
"Auto mode denied: command targets a path outside the project"
}
Field
Description
reason
The classifier’s explanation for why the tool call was denied
​
PermissionDenied decision control
PermissionDenied hooks can tell the model it may retry the denied tool call. Return a JSON object with
hookSpecificOutput.retry
set to
true
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionDenied"
,
"retry"
:
true
}
}
When
retry
is
true
, Claude Code adds a message to the conversation telling the model it may retry the tool call. The denial itself is not reversed. If your hook does not return JSON, or returns
retry: false
, the denial stands and the model receives the original rejection message.
​
Notification
Runs when Claude Code sends notifications. Matches on notification type:
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
. Omit the matcher to run hooks for all notification types.
Use separate matchers to run different handlers depending on the notification type. This configuration triggers a permission-specific alert script when Claude needs permission approval and a different notification when Claude has been idle:
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
"permission_prompt"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/permission-alert.sh"
}
]
},
{
"matcher"
:
"idle_prompt"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/idle-notification.sh"
}
]
}
]
}
}
​
Notification input
In addition to the
common input fields
, Notification hooks receive
message
with the notification text, an optional
title
, and
notification_type
indicating which type fired.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"Notification"
,
"message"
:
"Claude needs your permission to use Bash"
,
"title"
:
"Permission needed"
,
"notification_type"
:
"permission_prompt"
}
Notification hooks cannot block or modify notifications. They are intended for side effects such as forwarding the notification to an external service. The
common JSON output fields
such as
systemMessage
apply.
​
SubagentStart
Runs when a Claude Code subagent is spawned via the Agent tool. Supports matchers to filter by agent type name. For built-in agents, this is the agent name like
general-purpose
,
Explore
, or
Plan
. For
custom subagents
, this is the
name
field from the agent’s frontmatter, not the filename.
​
SubagentStart input
In addition to the
common input fields
, SubagentStart hooks receive
agent_id
with the unique identifier for the subagent and
agent_type
with the agent name (built-in agents like
"general-purpose"
,
"Explore"
,
"Plan"
, or custom agent names).
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SubagentStart"
,
"agent_id"
:
"agent-abc123"
,
"agent_type"
:
"Explore"
}
SubagentStart hooks cannot block subagent creation, but they can inject context into the subagent. In addition to the
JSON output fields
available to all hooks, you can return:
Field
Description
additionalContext
String added to the subagent’s context at the start of its conversation, before its first prompt. See
Add context for Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"SubagentStart"
,
"additionalContext"
:
"Follow security guidelines for this task"
}
}
​
SubagentStop
Runs when a Claude Code subagent has finished responding. Matches on agent type, same values as SubagentStart.
​
SubagentStop input
In addition to the
common input fields
, SubagentStop hooks receive
stop_hook_active
,
agent_id
,
agent_type
,
agent_transcript_path
, and
last_assistant_message
. The
agent_type
field is the value used for matcher filtering. The
transcript_path
is the main session’s transcript, while
agent_transcript_path
is the subagent’s own transcript stored in a nested
subagents/
folder. The
last_assistant_message
field contains the text content of the subagent’s final response, so hooks can access it without parsing the transcript file.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"~/.claude/projects/.../abc123.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"SubagentStop"
,
"stop_hook_active"
:
false
,
"agent_id"
:
"def456"
,
"agent_type"
:
"Explore"
,
"agent_transcript_path"
:
"~/.claude/projects/.../abc123/subagents/agent-def456.jsonl"
,
"last_assistant_message"
:
"Analysis complete. Found 3 potential issues..."
}
SubagentStop hooks use the same decision control format as
Stop hooks
. They do not support
additionalContext
. Returning
decision: "block"
with a
reason
keeps the subagent running and delivers
reason
to the subagent as its next instruction. To inject context into the parent session after a subagent returns, use a
PostToolUse
hook on the
Agent
tool instead.
​
TaskCreated
Runs when a task is being created via the
TaskCreate
tool. Use this to enforce naming conventions, require task descriptions, or prevent certain tasks from being created.
When a
TaskCreated
hook exits with code 2, the task is not created and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TaskCreated hooks do not support matchers and fire on every occurrence.
​
TaskCreated input
In addition to the
common input fields
, TaskCreated hooks receive
task_id
,
task_subject
, and optionally
task_description
,
teammate_name
, and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TaskCreated"
,
"task_id"
:
"task-001"
,
"task_subject"
:
"Implement user authentication"
,
"task_description"
:
"Add login and signup endpoints"
,
"teammate_name"
:
"implementer"
,
"team_name"
:
"my-project"
}
Field
Description
task_id
Identifier of the task being created
task_subject
Title of the task
task_description
Detailed description of the task. May be absent
teammate_name
Name of the teammate creating the task. May be absent
team_name
Name of the team. May be absent
​
TaskCreated decision control
TaskCreated hooks support two ways to control task creation:
Exit code 2
: the task is not created and the stderr message is fed back to the model as feedback.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example blocks tasks whose subjects don’t follow the required format:
#!/bin/bash
INPUT
=
$(
cat
)
TASK_SUBJECT
=
$(
echo
"
$INPUT
"
|
jq
-r
'.task_subject'
)
if
[[
!
"
$TASK_SUBJECT
"
=~
^
\[
TICKET-[0-9]+
\]
]];
then
echo
"Task subject must start with a ticket number, e.g. '[TICKET-123] Add feature'"
>&2
exit
2
fi
exit
0
​
TaskCompleted
Runs when a task is being marked as completed. This fires in two situations: when any agent explicitly marks a task as completed through the TaskUpdate tool, or when an
agent team
teammate finishes its turn with in-progress tasks. Use this to enforce completion criteria like passing tests or lint checks before a task can close.
When a
TaskCompleted
hook exits with code 2, the task is not marked as completed and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TaskCompleted hooks do not support matchers and fire on every occurrence.
​
TaskCompleted input
In addition to the
common input fields
, TaskCompleted hooks receive
task_id
,
task_subject
, and optionally
task_description
,
teammate_name
, and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TaskCompleted"
,
"task_id"
:
"task-001"
,
"task_subject"
:
"Implement user authentication"
,
"task_description"
:
"Add login and signup endpoints"
,
"teammate_name"
:
"implementer"
,
"team_name"
:
"my-project"
}
Field
Description
task_id
Identifier of the task being completed
task_subject
Title of the task
task_description
Detailed description of the task. May be absent
teammate_name
Name of the teammate completing the task. May be absent
team_name
Name of the team. May be absent
​
TaskCompleted decision control
TaskCompleted hooks support two ways to control task completion:
Exit code 2
: the task is not marked as completed and the stderr message is fed back to the model as feedback.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example runs tests and blocks task completion if they fail:
#!/bin/bash
INPUT
=
$(
cat
)
TASK_SUBJECT
=
$(
echo
"
$INPUT
"
|
jq
-r
'.task_subject'
)
# Run the test suite
if
!
npm
test
2>&1
;
then
echo
"Tests not passing. Fix failing tests before completing:
$TASK_SUBJECT
"
>&2
exit
2
fi
exit
0
​
Stop
Runs when the main Claude Code agent has finished responding. Does not run if
the stoppage occurred due to a user interrupt. API errors fire
StopFailure
instead.
The
/goal
command is a built-in shortcut for a session-scoped prompt-based Stop hook. Use it when you want Claude to keep working until a condition holds without writing hook configuration.
​
Stop input
In addition to the
common input fields
, Stop hooks receive
stop_hook_active
and
last_assistant_message
. The
stop_hook_active
field is
true
when Claude Code is already continuing as a result of a stop hook. Check this value or process the transcript to prevent Claude Code from running indefinitely. The
last_assistant_message
field contains the text content of Claude’s final response, so hooks can access it without parsing the transcript file.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Stop"
,
"stop_hook_active"
:
true
,
"last_assistant_message"
:
"I've completed the refactoring. Here's a summary..."
}
​
Stop decision control
Stop
and
SubagentStop
hooks can control whether Claude continues. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
decision
"block"
prevents Claude from stopping. Omit to allow Claude to stop
reason
Required when
decision
is
"block"
. Tells Claude why it should continue
{
"decision"
:
"block"
,
"reason"
:
"Must be provided when Claude is blocked from stopping"
}
​
StopFailure
Runs instead of
Stop
when the turn ends due to an API error. Output and exit code are ignored. Use this to log failures, send alerts, or take recovery actions when Claude cannot complete a response due to rate limits, authentication problems, or other API errors.
​
StopFailure input
In addition to the
common input fields
, StopFailure hooks receive
error
, optional
error_details
, and optional
last_assistant_message
. The
error
field identifies the error type and is used for matcher filtering.
Field
Description
error
Error type:
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
, or
unknown
error_details
Additional details about the error, when available
last_assistant_message
The rendered error text shown in the conversation. Unlike
Stop
and
SubagentStop
, where this field holds Claude’s conversational output, for
StopFailure
it contains the API error string itself, such as
"API Error: Rate limit reached"
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"StopFailure"
,
"error"
:
"rate_limit"
,
"error_details"
:
"429 Too Many Requests"
,
"last_assistant_message"
:
"API Error: Rate limit reached"
}
StopFailure hooks have no decision control. They run for notification and logging purposes only.
​
TeammateIdle
Runs when an
agent team
teammate is about to go idle after finishing its turn. Use this to enforce quality gates before a teammate stops working, such as requiring passing lint checks or verifying that output files exist.
When a
TeammateIdle
hook exits with code 2, the teammate receives the stderr message as feedback and continues working instead of going idle. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TeammateIdle hooks do not support matchers and fire on every occurrence.
​
TeammateIdle input
In addition to the
common input fields
, TeammateIdle hooks receive
teammate_name
and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TeammateIdle"
,
"teammate_name"
:
"researcher"
,
"team_name"
:
"my-project"
}
Field
Description
teammate_name
Name of the teammate that is about to go idle
team_name
Name of the team
​
TeammateIdle decision control
TeammateIdle hooks support two ways to control teammate behavior:
Exit code 2
: the teammate receives the stderr message as feedback and continues working instead of going idle.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example checks that a build artifact exists before allowing a teammate to go idle:
#!/bin/bash
if
[
!
-f
"./dist/output.js"
];
then
echo
"Build artifact missing. Run the build before stopping."
>&2
exit
2
fi
exit
0
​
ConfigChange
Runs when a configuration file changes during a session. Use this to audit settings changes, enforce security policies, or block unauthorized modifications to configuration files.
ConfigChange hooks fire for changes to settings files, managed policy settings, and skill files. The
source
field in the input tells you which type of configuration changed, and the optional
file_path
field provides the path to the changed file.
The matcher filters on the configuration source:
Matcher
When it fires
user_settings
~/.claude/settings.json
changes
project_settings
.claude/settings.json
changes
local_settings
.claude/settings.local.json
changes
policy_settings
Managed policy settings change
skills
A skill file in
.claude/skills/
changes
This example logs all configuration changes for security auditing:
{
"hooks"
: {
"ConfigChange"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-config-change.sh"
,
"args"
: []
}
]
}
]
}
}
​
ConfigChange input
In addition to the
common input fields
, ConfigChange hooks receive
source
and optionally
file_path
. The
source
field indicates which configuration type changed, and
file_path
provides the path to the specific file that was modified.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"ConfigChange"
,
"source"
:
"project_settings"
,
"file_path"
:
"/Users/.../my-project/.claude/settings.json"
}
​
ConfigChange decision control
ConfigChange hooks can block configuration changes from taking effect. Use exit code 2 or a JSON
decision
to prevent the change. When blocked, the new settings are not applied to the running session.
Field
Description
decision
"block"
prevents the configuration change from being applied. Omit to allow the change
reason
Explanation shown to the user when
decision
is
"block"
{
"decision"
:
"block"
,
"reason"
:
"Configuration changes to project settings require admin approval"
}
policy_settings
changes cannot be blocked. Hooks still fire for
policy_settings
sources, so you can use them for audit logging, but any blocking decision is ignored. This ensures enterprise-managed settings always take effect.
​
CwdChanged
Runs when the working directory changes during a session, for example when Claude executes a
cd
command. Use this to react to directory changes: reload environment variables, activate project-specific toolchains, or run setup scripts automatically. Pairs with
FileChanged
for tools like
direnv
that manage per-directory environment.
CwdChanged hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
.
CwdChanged does not support matchers and fires on every directory change.
​
CwdChanged input
In addition to the
common input fields
, CwdChanged hooks receive
old_cwd
and
new_cwd
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project/src"
,
"hook_event_name"
:
"CwdChanged"
,
"old_cwd"
:
"/Users/my-project"
,
"new_cwd"
:
"/Users/my-project/src"
}
​
CwdChanged output
In addition to the
JSON output fields
available to all hooks, CwdChanged hooks can return
watchPaths
to dynamically set which file paths
FileChanged
watches:
Field
Description
watchPaths
Array of absolute paths. Replaces the current dynamic watch list (paths from your
matcher
configuration are always watched). Returning an empty array clears the dynamic list, which is typical when entering a new directory
CwdChanged hooks have no decision control. They cannot block the directory change.
​
FileChanged
Runs when a watched file changes on disk. Useful for reloading environment variables when project configuration files are modified.
The
matcher
for this event serves two roles:
Build the watch list
: the value is split on
|
and each segment is registered as a literal filename in the working directory, so
".envrc|.env"
watches exactly those two files. Regex patterns are not useful here: a value like
^\.env
would watch a file literally named
^\.env
.
Filter which hooks run
: when a watched file changes, the same value filters which hook groups run using the standard
matcher rules
against the changed file’s basename.
FileChanged hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
.
​
FileChanged input
In addition to the
common input fields
, FileChanged hooks receive
file_path
and
event
.
Field
Description
file_path
Absolute path to the file that changed
event
What happened:
"change"
(file modified),
"add"
(file created), or
"unlink"
(file deleted)
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project"
,
"hook_event_name"
:
"FileChanged"
,
"file_path"
:
"/Users/my-project/.envrc"
,
"event"
:
"change"
}
​
FileChanged output
In addition to the
JSON output fields
available to all hooks, FileChanged hooks can return
watchPaths
to dynamically update which file paths are watched:
Field
Description
watchPaths
Array of absolute paths. Replaces the current dynamic watch list (paths from your
matcher
configuration are always watched). Use this when your hook script discovers additional files to watch based on the changed file
FileChanged hooks have no decision control. They cannot block the file change from occurring.
​
WorktreeCreate
When you run
claude --worktree
or a
subagent uses
isolation: "worktree"
, Claude Code creates an isolated working copy using
git worktree
. If you configure a WorktreeCreate hook, it replaces the default git behavior, letting you use a different version control system like SVN, Perforce, or Mercurial.
Because the hook replaces the default behavior entirely,
.worktreeinclude
is not processed. If you need to copy local configuration files like
.env
into the new worktree, do it inside your hook script.
The hook must return the absolute path to the created worktree directory. Claude Code uses this path as the working directory for the isolated session. Command hooks print it on stdout; HTTP hooks return it via
hookSpecificOutput.worktreePath
.
This example creates an SVN working copy and prints the path for Claude Code to use. Replace the repository URL with your own:
{
"hooks"
: {
"WorktreeCreate"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'NAME=$(jq -r .name); DIR=
\"
$HOME/.claude/worktrees/$NAME
\"
; svn checkout https://svn.example.com/repo/trunk
\"
$DIR
\"
>&2 && echo
\"
$DIR
\"
'"
}
]
}
]
}
}
The hook reads the worktree
name
from the JSON input on stdin, checks out a fresh copy into a new directory, and prints the directory path. The
echo
on the last line is what Claude Code reads as the worktree path. Redirect any other output to stderr so it doesn’t interfere with the path.
​
WorktreeCreate input
In addition to the
common input fields
, WorktreeCreate hooks receive the
name
field. This is a slug identifier for the new worktree, either specified by the user or auto-generated (for example,
bold-oak-a3f2
).
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"WorktreeCreate"
,
"name"
:
"feature-auth"
}
​
WorktreeCreate output
WorktreeCreate hooks do not use the standard allow/block decision model. Instead, the hook’s success or failure determines the outcome. The hook must return the absolute path to the created worktree directory:
Command hooks
(
type: "command"
): print the path on stdout.
HTTP hooks
(
type: "http"
): return
{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }
in the response body.
If the hook fails or produces no path, worktree creation fails with an error.
​
WorktreeRemove
The cleanup counterpart to
WorktreeCreate
. This hook fires when a worktree is being removed, either when you exit a
--worktree
session and choose to remove it, or when a subagent with
isolation: "worktree"
finishes. For git-based worktrees, Claude handles cleanup automatically with
git worktree remove
. If you configured a WorktreeCreate hook for a non-git version control system, pair it with a WorktreeRemove hook to handle cleanup. Without one, the worktree directory is left on disk.
Claude Code passes the path returned by WorktreeCreate as
worktree_path
in the hook input. This example reads that path and removes the directory:
{
"hooks"
: {
"WorktreeRemove"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'jq -r .worktree_path | xargs rm -rf'"
}
]
}
]
}
}
​
WorktreeRemove input
In addition to the
common input fields
, WorktreeRemove hooks receive the
worktree_path
field, which is the absolute path to the worktree being removed.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"WorktreeRemove"
,
"worktree_path"
:
"/Users/.../my-project/.claude/worktrees/feature-auth"
}
WorktreeRemove hooks have no decision control. They cannot block worktree removal but can perform cleanup tasks like removing version control state or archiving changes. Hook failures are logged in debug mode only.
​
PreCompact
Runs before Claude Code is about to run a compact operation.
The matcher value indicates whether compaction was triggered manually or automatically:
Matcher
When it fires
manual
/compact
auto
Auto-compact when the context window is full
Exit with code 2 to block compaction. For a manual
/compact
, the stderr message is shown to the user. You can also block by returning JSON with
"decision": "block"
.
Blocking automatic compaction has different effects depending on when it fires. If compaction was triggered proactively before the context limit, Claude Code skips it and the conversation continues uncompacted. If compaction was triggered to recover from a context-limit error already returned by the API, the underlying error surfaces and the current request fails.
​
PreCompact input
In addition to the
common input fields
, PreCompact hooks receive
trigger
and
custom_instructions
. For
manual
,
custom_instructions
contains what the user passes into
/compact
. For
auto
,
custom_instructions
is empty.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"PreCompact"
,
"trigger"
:
"manual"
,
"custom_instructions"
:
""
}
​
PostCompact
Runs after Claude Code completes a compact operation. Use this event to react to the new compacted state, for example to log the generated summary or update external state.
The same matcher values apply as for
PreCompact
:
Matcher
When it fires
manual
After
/compact
auto
After auto-compact when the context window is full
​
PostCompact input
In addition to the
common input fields
, PostCompact hooks receive
trigger
and
compact_summary
. The
compact_summary
field contains the conversation summary generated by the compact operation.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"PostCompact"
,
"trigger"
:
"manual"
,
"compact_summary"
:
"Summary of the compacted conversation..."
}
PostCompact hooks have no decision control. They cannot affect the compaction result but can perform follow-up tasks.
​
SessionEnd
Runs when a Claude Code session ends. Useful for cleanup tasks, logging session
statistics, or saving session state. Supports matchers to filter by exit reason.
The
reason
field in the hook input indicates why the session ended:
Reason
Description
clear
Session cleared with
/clear
command
resume
Session switched via interactive
/resume
logout
User logged out
prompt_input_exit
User exited while prompt input was visible
bypass_permissions_disabled
Bypass permissions mode was disabled
other
Other exit reasons
​
SessionEnd input
In addition to the
common input fields
, SessionEnd hooks receive a
reason
field indicating why the session ended. See the
reason table
above for all values.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SessionEnd"
,
"reason"
:
"other"
}
SessionEnd hooks have no decision control. They cannot block session termination but can perform cleanup tasks.
SessionEnd hooks have a default timeout of 1.5 seconds. This applies to session exit,
/clear
, and switching sessions via interactive
/resume
. If a hook needs more time, set a per-hook
timeout
in the hook configuration. The overall budget is automatically raised to the highest per-hook timeout configured in settings files, up to 60 seconds. Timeouts set on plugin-provided hooks do not raise the budget. To override the budget explicitly, set the
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
environment variable in milliseconds.
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
=
5000
claude
​
Elicitation
Runs when an MCP server requests user input mid-task. By default, Claude Code shows an interactive dialog for the user to respond. Hooks can intercept this request and respond programmatically, skipping the dialog entirely.
The matcher field matches against the MCP server name.
​
Elicitation input
In addition to the
common input fields
, Elicitation hooks receive
mcp_server_name
,
message
, and optional
mode
,
url
,
elicitation_id
, and
requested_schema
fields.
For form-mode elicitation (the most common case):
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Elicitation"
,
"mcp_server_name"
:
"my-mcp-server"
,
"message"
:
"Please provide your credentials"
,
"mode"
:
"form"
,
"requested_schema"
: {
"type"
:
"object"
,
"properties"
: {
"username"
: {
"type"
:
"string"
,
"title"
:
"Username"
}
}
}
}
For URL-mode elicitation (browser-based authentication):
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Elicitation"
,
"mcp_server_name"
:
"my-mcp-server"
,
"message"
:
"Please authenticate"
,
"mode"
:
"url"
,
"url"
:
"https://auth.example.com/login"
}
​
Elicitation output
To respond programmatically without showing the dialog, return a JSON object with
hookSpecificOutput
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"Elicitation"
,
"action"
:
"accept"
,
"content"
: {
"username"
:
"alice"
}
}
}
Field
Values
Description
action
accept
,
decline
,
cancel
Whether to accept, decline, or cancel the request
content
object
Form field values to submit. Only used when
action
is
accept
Exit code 2 denies the elicitation and shows stderr to the user.
​
ElicitationResult
Runs after a user responds to an MCP elicitation. Hooks can observe, modify, or block the response before it is sent back to the MCP server.
The matcher field matches against the MCP server name.
​
ElicitationResult input
In addition to the
common input fields
, ElicitationResult hooks receive
mcp_server_name
,
action
, and optional
mode
,
elicitation_id
, and
content
fields.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"ElicitationResult"
,
"mcp_server_name"
:
"my-mcp-server"
,
"action"
:
"accept"
,
"content"
: {
"username"
:
"alice"
},
"mode"
:
"form"
,
"elicitation_id"
:
"elicit-123"
}
​
ElicitationResult output
To override the user’s response, return a JSON object with
hookSpecificOutput
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"ElicitationResult"
,
"action"
:
"decline"
,
"content"
: {}
}
}
Field
Values
Description
action
accept
,
decline
,
cancel
Overrides the user’s action
content
object
Overrides form field values. Only meaningful when
action
is
accept
Exit code 2 blocks the response, changing the effective action to
decline
.
​
Prompt-based hooks
In addition to command, HTTP, and MCP tool hooks, Claude Code supports prompt-based hooks (
type: "prompt"
) that use an LLM to evaluate whether to allow or block an action, and agent hooks (
type: "agent"
) that spawn an agentic verifier with tool access. Not all events support every hook type.
Events that support all five hook types (
command
,
http
,
mcp_tool
,
prompt
, and
agent
):
PermissionRequest
PostToolBatch
PostToolUse
PostToolUseFailure
PreToolUse
Stop
SubagentStop
TaskCompleted
TaskCreated
UserPromptExpansion
UserPromptSubmit
Events that support
command
,
http
, and
mcp_tool
hooks but not
prompt
or
agent
:
ConfigChange
CwdChanged
Elicitation
ElicitationResult
FileChanged
InstructionsLoaded
Notification
PermissionDenied
PostCompact
PreCompact
SessionEnd
StopFailure
SubagentStart
TeammateIdle
WorktreeCreate
WorktreeRemove
SessionStart
and
Setup
support
command
and
mcp_tool
hooks. They do not support
http
,
prompt
, or
agent
hooks.
​
How prompt-based hooks work
Instead of executing a Bash command, prompt-based hooks:
Send the hook input and your prompt to a Claude model, Haiku by default
The LLM responds with structured JSON containing a decision
Claude Code processes the decision automatically
​
Prompt hook configuration
Set
type
to
"prompt"
and provide a
prompt
string instead of a
command
. Use the
$ARGUMENTS
placeholder to inject the hook’s JSON input data into your prompt text. Claude Code sends the combined prompt and input to a fast Claude model, which returns a JSON decision.
This
Stop
hook asks the LLM to evaluate whether all tasks are complete before allowing Claude to finish:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
}
]
}
]
}
}
Field
Required
Description
type
yes
Must be
"prompt"
prompt
yes
The prompt text to send to the LLM. Use
$ARGUMENTS
as a placeholder for the hook input JSON. If
$ARGUMENTS
is not present, input JSON is appended to the prompt
model
no
Model to use for evaluation. Defaults to a fast model
timeout
no
Timeout in seconds. Default: 30
continueOnBlock
no
When the prompt returns
ok: false
, feed the reason back to Claude and continue the turn instead of stopping. Default:
false
. Implemented as
continue: true
on the resulting
decision: "block"
. See
Response schema
for per-event behavior
​
Response schema
The LLM must respond with JSON containing:
{
"ok"
:
true
|
false
,
"reason"
:
"Explanation for the decision"
}
Field
Description
ok
true
to allow.
false
produces a
decision: "block"
. See the per-event behavior below
reason
Required when
ok
is
false
. Used as the block reason
What happens on
ok: false
depends on the event:
Stop
and
SubagentStop
: the reason is fed back to Claude as its next instruction and the turn continues
PreToolUse
: the tool call is denied and the reason is returned to Claude as the tool error, equivalent to a command hook’s
permissionDecision: "deny"
PostToolUse
: by default the turn ends and the reason appears in the chat as a warning line. Set
continueOnBlock: true
to feed the reason back to Claude and continue the turn instead
PostToolBatch
,
UserPromptSubmit
, and
UserPromptExpansion
: the turn ends and the reason appears as a warning line. These events end the turn on
decision: "block"
regardless of
continue
PostToolUseFailure
,
TaskCreated
, and
TaskCompleted
: the reason is returned to Claude as a tool error, similar to
PreToolUse
PermissionRequest
:
ok: false
has no effect. To deny an approval from a hook, use a
command hook
returning
hookSpecificOutput.decision.behavior: "deny"
If you need finer control on any event, use a
command hook
with the per-event fields described in
Decision control
.
​
Example: Multi-criteria Stop hook
This
Stop
hook uses a detailed prompt to check three conditions before allowing Claude to stop. If
"ok"
is
false
, Claude continues working with the provided reason as its next instruction.
SubagentStop
hooks use the same format to evaluate whether a
subagent
should stop:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"You are evaluating whether Claude should stop working. Context: $ARGUMENTS
\n\n
Analyze the conversation and determine if:
\n
1. All user-requested tasks are complete
\n
2. Any errors need to be addressed
\n
3. Follow-up work is needed
\n\n
Respond with JSON: {
\"
ok
\"
: true} to allow stopping, or {
\"
ok
\"
: false,
\"
reason
\"
:
\"
your explanation
\"
} to continue working."
,
"timeout"
:
30
}
]
}
]
}
}
​
Agent-based hooks
Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer
command hooks
.
Agent-based hooks (
type: "agent"
) are like prompt-based hooks but with multi-turn tool access. Instead of a single LLM call, an agent hook spawns a subagent that can read files, search code, and inspect the codebase to verify conditions. Agent hooks support the same events as prompt-based hooks.
​
How agent hooks work
When an agent hook fires:
Claude Code spawns a subagent with your prompt and the hook’s JSON input
The subagent can use tools like Read, Grep, and Glob to investigate
After up to 50 turns, the subagent returns a structured
{ "ok": true/false }
decision
Claude Code processes the decision the same way as a prompt hook
Agent hooks are useful when verification requires inspecting actual files or test output, not just evaluating the hook input data alone.
​
Agent hook configuration
Set
type
to
"agent"
and provide a
prompt
string. The configuration fields are the same as
prompt hooks
, with a longer default timeout:
Field
Required
Description
type
yes
Must be
"agent"
prompt
yes
Prompt describing what to verify. Use
$ARGUMENTS
as a placeholder for the hook input JSON
model
no
Model to use. Defaults to a fast model
timeout
no
Timeout in seconds. Default: 60
The response schema is the same as prompt hooks:
{ "ok": true }
to allow or
{ "ok": false, "reason": "..." }
to block.
This
Stop
hook verifies that all unit tests pass before allowing Claude to finish:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"agent"
,
"prompt"
:
"Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS"
,
"timeout"
:
120
}
]
}
]
}
}
​
Run hooks in the background
By default, hooks block Claude’s execution until they complete. For long-running tasks like deployments, test suites, or external API calls, set
"async": true
to run the hook in the background while Claude continues working. Async hooks cannot block or control Claude’s behavior: response fields like
decision
,
permissionDecision
, and
continue
have no effect, because the action they would have controlled has already completed.
​
Configure an async hook
Add
"async": true
to a command hook’s configuration to run it in the background without blocking Claude. This field is only available on
type: "command"
hooks.
This hook runs a test script after every
Write
tool call. Claude continues working immediately while
run-tests.sh
executes for up to 120 seconds. When the script finishes, its output is delivered on the next conversation turn:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/run-tests.sh"
,
"async"
:
true
,
"timeout"
:
120
}
]
}
]
}
}
The
timeout
field sets the maximum time in seconds for the background process. If not specified, async hooks use the same 10-minute default as sync hooks.
​
How async hooks execute
When an async hook fires, Claude Code starts the hook process and immediately continues without waiting for it to finish. The hook receives the same JSON input via stdin as a synchronous hook.
After the background process exits, if the hook produced a JSON response with an
additionalContext
field, that content is delivered to Claude as context on the next conversation turn. A
systemMessage
field is shown to you, not to Claude.
Async hook completion notifications are suppressed by default. To see them, enable verbose mode with
Ctrl+O
or start Claude Code with
--verbose
.
​
Example: run tests after file changes
This hook starts a test suite in the background whenever Claude writes a file, then reports the results back to Claude when the tests finish. Save this script to
.claude/hooks/run-tests-async.sh
in your project and make it executable with
chmod +x
:
#!/bin/bash
# run-tests-async.sh
# Read hook input from stdin
INPUT
=
$(
cat
)
FILE_PATH
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.file_path // empty'
)
# Only run tests for source files
if
[[
"
$FILE_PATH
"
!=
*
.ts
&&
"
$FILE_PATH
"
!=
*
.js ]];
then
exit
0
fi
# Run tests and report results to Claude via additionalContext
RESULT
=
$(
npm
test
2>&1
)
EXIT_CODE
=
$?
if
[
$EXIT_CODE
-eq
0
];
then
MSG
=
"Tests passed after editing
$FILE_PATH
"
else
MSG
=
"Tests failed after editing
$FILE_PATH
:
$RESULT
"
fi
jq
-nc
--arg
msg
"
$MSG
"
'{hookSpecificOutput: {hookEventName: "PostToolUse", additionalContext: $msg}}'
Then add this configuration to
.claude/settings.json
in your project root. The
async: true
flag lets Claude keep working while tests run:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh"
,
"args"
: [],
"async"
:
true
,
"timeout"
:
300
}
]
}
]
}
}
​
Limitations
Async hooks have several constraints compared to synchronous hooks:
Only
type: "command"
hooks support
async
. Prompt-based hooks cannot run asynchronously.
Async hooks cannot block tool calls or return decisions. By the time the hook completes, the triggering action has already proceeded.
Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction. Exception: an
asyncRewake
hook that exits with code 2 wakes Claude immediately even when the session is idle.
Each execution creates a separate background process. There is no deduplication across multiple firings of the same async hook.
​
Security considerations
​
Disclaimer
Command hooks run with your system user’s full permissions.
Command hooks execute shell commands with your full user permissions. They can modify, delete, or access any files your user account can access. Review and test all hook commands before adding them to your configuration.
​
Security best practices
Keep these practices in mind when writing hooks:
Validate and sanitize inputs
: never trust input data blindly
Always quote shell variables
: use
"$VAR"
not
$VAR
Block path traversal
: check for
..
in file paths
Use absolute paths
: specify full paths for scripts. In exec form, use
${CLAUDE_PROJECT_DIR}
and the path needs no quoting. In shell form, wrap it in double quotes
Skip sensitive files
: avoid
.env
,
.git/
, keys, etc.
​
Windows PowerShell tool
On Windows, you can run individual hooks in PowerShell by setting
"shell": "powershell"
on a command hook. Hooks spawn PowerShell directly, so this works regardless of whether
CLAUDE_CODE_USE_POWERSHELL_TOOL
is set. Claude Code auto-detects
pwsh.exe
(PowerShell 7+) with a fallback to
powershell.exe
(5.1).
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"shell"
:
"powershell"
,
"command"
:
"Write-Host 'File written'"
}
]
}
]
}
}
​
Debug hooks
Hook execution details, including which hooks matched, their exit codes, and full stdout and stderr, are written to the debug log file. Start Claude Code with
claude --debug-file <path>
to write the log to a known location, or run
claude --debug
and read the log at
~/.claude/debug/<session-id>.txt
. The
--debug
flag does not print to the terminal.
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 600000ms
[DEBUG] Hook command completed with status 0: <Your stdout>
For more granular hook matching details, set
CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose
to see additional log lines such as hook matcher counts and query matching.
For troubleshooting common issues like hooks not firing, infinite Stop hook loops, or configuration errors, see
Limitations and troubleshooting
in the guide. For a broader diagnostic walkthrough covering
/context
,
/doctor
, and settings precedence, see
Debug your config
.
Was this page helpful?
Yes
No
Checkpointing
Plugins reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/hooks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Hooks reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
For a quickstart guide with examples, see
Automa...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Hooks reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
For a quickstart guide with examples, see
Automate workflows with hooks
.
Hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code’s lifecycle. Use this reference to look up event schemas, configuration options, JSON input/output formats, and advanced features like async hooks, HTTP hooks, and MCP tool hooks. If you’re setting up hooks for the first time, start with the
guide
instead.
​
Hook lifecycle
Hooks fire at specific points during a Claude Code session. When an event fires and a matcher matches, Claude Code passes JSON context about the event to your hook handler. For command hooks, input arrives on stdin. For HTTP hooks, it arrives as the POST request body. Your handler can then inspect the input, take action, and optionally return a decision. Events fall into three cadences: once per session (
SessionStart
,
SessionEnd
), once per turn (
UserPromptSubmit
,
Stop
,
StopFailure
), and on every tool call inside the agentic loop (
PreToolUse
,
PostToolUse
):
The table below summarizes when each event fires. The
Hook events
section documents the full input schema and decision control options for each one.
Event
When it fires
SessionStart
When a session begins or resumes
Setup
When you start Claude Code with
--init-only
, or with
--init
or
--maintenance
in
-p
mode. For one-time preparation in CI or scripts
UserPromptSubmit
When you submit a prompt, before Claude processes it
UserPromptExpansion
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUse
Before a tool call executes. Can block it
PermissionRequest
When a permission dialog appears
PermissionDenied
When a tool call is denied by the auto mode classifier. Return
{retry: true}
to tell the model it may retry the denied tool call
PostToolUse
After a tool call succeeds
PostToolUseFailure
After a tool call fails
PostToolBatch
After a full batch of parallel tool calls resolves, before the next model call
Notification
When Claude Code sends a notification
SubagentStart
When a subagent is spawned
SubagentStop
When a subagent finishes
TaskCreated
When a task is being created via
TaskCreate
TaskCompleted
When a task is being marked as completed
Stop
When Claude finishes responding
StopFailure
When the turn ends due to an API error. Output and exit code are ignored
TeammateIdle
When an
agent team
teammate is about to go idle
InstructionsLoaded
When a CLAUDE.md or
.claude/rules/*.md
file is loaded into context. Fires at session start and when files are lazily loaded during a session
ConfigChange
When a configuration file changes during a session
CwdChanged
When the working directory changes, for example when Claude executes a
cd
command. Useful for reactive environment management with tools like direnv
FileChanged
When a watched file changes on disk. The
matcher
field specifies which filenames to watch
WorktreeCreate
When a worktree is being created via
--worktree
or
isolation: "worktree"
. Replaces default git behavior
WorktreeRemove
When a worktree is being removed, either at session exit or when a subagent finishes
PreCompact
Before context compaction
PostCompact
After context compaction completes
Elicitation
When an MCP server requests user input during a tool call
ElicitationResult
After a user responds to an MCP elicitation, before the response is sent back to the server
SessionEnd
When a session terminates
​
How a hook resolves
To see how these pieces fit together, consider this
PreToolUse
hook that blocks destructive shell commands. The
matcher
narrows to Bash tool calls and the
if
condition narrows further to Bash subcommands matching
rm *
, so
block-rm.sh
only spawns when both filters match:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"command"
,
"if"
:
"Bash(rm *)"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
,
"args"
: []
}
]
}
]
}
}
The script reads the JSON input from stdin, extracts the command, and returns a
permissionDecision
of
"deny"
if it contains
rm -rf
:
#!/bin/bash
# .claude/hooks/block-rm.sh
COMMAND
=
$(
jq
-r
'.tool_input.command'
)
if
echo
"
$COMMAND
"
|
grep
-q
'rm -rf'
;
then
jq
-n
'{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
else
exit
0
# allow the command
fi
Now suppose Claude Code decides to run
Bash "rm -rf /tmp/build"
. Here’s what happens:
1
Event fires
The
PreToolUse
event fires. Claude Code sends the tool input as JSON on stdin to the hook:
{
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf /tmp/build"
},
...
}
2
Matcher checks
The matcher
"Bash"
matches the tool name, so this hook group activates. If you omit the matcher or use
"*"
, the group activates on every occurrence of the event.
3
If condition checks
The
if
condition
"Bash(rm *)"
matches because
rm -rf /tmp/build
is a subcommand matching
rm *
, so this handler spawns. If the command had been
npm test
, the
if
check would fail and
block-rm.sh
would never run, avoiding the process spawn overhead. The
if
field is optional; without it, every handler in the matched group runs.
4
Hook handler runs
The script inspects the full command and finds
rm -rf
, so it prints a decision to stdout:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Destructive command blocked by hook"
}
}
If the command had been a safer
rm
variant like
rm file.txt
, the script would hit
exit 0
instead, which tells Claude Code to allow the tool call with no further action.
5
Claude Code acts on the result
Claude Code reads the JSON decision, blocks the tool call, and shows Claude the reason.
The
Configuration
section below documents the full schema, and each
hook event
section documents what input your command receives and what output it can return.
​
Configuration
Hooks are defined in JSON settings files. The configuration has three levels of nesting:
Choose a
hook event
to respond to, like
PreToolUse
or
Stop
Add a
matcher group
to filter when it fires, like “only for the Bash tool”
Define one or more
hook handlers
to run when matched
See
How a hook resolves
above for a complete walkthrough with an annotated example.
This page uses specific terms for each level:
hook event
for the lifecycle point,
matcher group
for the filter, and
hook handler
for the shell command, HTTP endpoint, MCP tool, prompt, or agent that runs. “Hook” on its own refers to the general feature.
​
Hook locations
Where you define a hook determines its scope:
Location
Scope
Shareable
~/.claude/settings.json
All your projects
No, local to your machine
.claude/settings.json
Single project
Yes, can be committed to the repo
.claude/settings.local.json
Single project
No, gitignored
Managed policy settings
Organization-wide
Yes, admin-controlled
Plugin
hooks/hooks.json
When plugin is enabled
Yes, bundled with the plugin
Skill
or
agent
frontmatter
While the component is active
Yes, defined in the component file
For details on settings file resolution, see
settings
. Enterprise administrators can use
allowManagedHooksOnly
to block user, project, and plugin hooks. Hooks from plugins force-enabled in managed settings
enabledPlugins
are exempt, so administrators can distribute vetted hooks through an organization marketplace. See
Hook configuration
.
​
Matcher patterns
The
matcher
field filters when hooks fire. How a matcher is evaluated depends on the characters it contains:
Matcher value
Evaluated as
Example
"*"
,
""
, or omitted
Match all
fires on every occurrence of the event
Only letters, digits,
_
, and
|
Exact string, or
|
-separated list of exact strings
Bash
matches only the Bash tool;
Edit|Write
matches either tool exactly
Contains any other character
JavaScript regular expression
^Notebook
matches any tool starting with Notebook;
mcp__memory__.*
matches every tool from the
memory
server
The
FileChanged
event does not follow these rules when building its watch list. See
FileChanged
.
Each event type matches on a different field:
Event
What the matcher filters
Example matcher values
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
tool name
Bash
,
Edit|Write
,
mcp__.*
SessionStart
how the session started
startup
,
resume
,
clear
,
compact
Setup
which CLI flag triggered setup
init
,
maintenance
SessionEnd
why the session ended
clear
,
resume
,
logout
,
prompt_input_exit
,
bypass_permissions_disabled
,
other
Notification
notification type
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
SubagentStart
agent type
general-purpose
,
Explore
,
Plan
, or custom agent names
PreCompact
,
PostCompact
what triggered compaction
manual
,
auto
SubagentStop
agent type
same values as
SubagentStart
ConfigChange
configuration source
user_settings
,
project_settings
,
local_settings
,
policy_settings
,
skills
CwdChanged
no matcher support
always fires on every directory change
FileChanged
literal filenames to watch (see
FileChanged
)
.envrc|.env
StopFailure
error type
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
,
unknown
InstructionsLoaded
load reason
session_start
,
nested_traversal
,
path_glob_match
,
include
,
compact
UserPromptExpansion
command name
your skill or command names
Elicitation
MCP server name
your configured MCP server names
ElicitationResult
MCP server name
same values as
Elicitation
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
no matcher support
always fires on every occurrence
The matcher runs against a field from the
JSON input
that Claude Code sends to your hook on stdin. For tool events, that field is
tool_name
. Each
hook event
section lists the full set of matcher values and the input schema for that event.
This example runs a linting script only when Claude writes or edits a file:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Edit|Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/lint-check.sh"
}
]
}
]
}
}
UserPromptSubmit
,
PostToolBatch
,
Stop
,
TeammateIdle
,
TaskCreated
,
TaskCompleted
,
WorktreeCreate
,
WorktreeRemove
, and
CwdChanged
don’t support matchers and always fire on every occurrence. If you add a
matcher
field to these events, it is silently ignored.
For tool events, you can filter more narrowly by setting the
if
field
on individual hook handlers.
if
uses
permission rule syntax
to match against the tool name and arguments together, so
"Bash(git *)"
runs when any subcommand of the Bash input matches
git *
and
"Edit(*.ts)"
runs only for TypeScript files.
​
Match MCP tools
MCP
server tools appear as regular tools in tool events (
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
,
PermissionDenied
), so you can match them the same way you match any other tool name.
MCP tools follow the naming pattern
mcp__<server>__<tool>
, for example:
mcp__memory__create_entities
: Memory server’s create entities tool
mcp__filesystem__read_file
: Filesystem server’s read file tool
mcp__github__search_repositories
: GitHub server’s search tool
To match every tool from a server, append
.*
to the server prefix. The
.*
is required: a matcher like
mcp__memory
contains only letters and underscores, so it is compared as an exact string and matches no tool.
mcp__memory__.*
matches all tools from the
memory
server
mcp__.*__write.*
matches any tool whose name starts with
write
from any server
This example logs all memory server operations and validates write operations from any MCP server:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"mcp__memory__.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"echo 'Memory operation initiated' >> ~/mcp-operations.log"
}
]
},
{
"matcher"
:
"mcp__.*__write.*"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/home/user/scripts/validate-mcp-write.py"
}
]
}
]
}
}
​
Hook handler fields
Each object in the inner
hooks
array is a hook handler: the shell command, HTTP endpoint, MCP tool, LLM prompt, or agent that runs when the matcher matches. There are five types:
Command hooks
(
type: "command"
): run a shell command. Your script receives the event’s
JSON input
on stdin and communicates results back through exit codes and stdout.
HTTP hooks
(
type: "http"
): send the event’s JSON input as an HTTP POST request to a URL. The endpoint communicates results back through the response body using the same
JSON output format
as command hooks.
MCP tool hooks
(
type: "mcp_tool"
): call a tool on an already-connected
MCP server
. The tool’s text output is treated like command-hook stdout.
Prompt hooks
(
type: "prompt"
): send a prompt to a Claude model for single-turn evaluation. The model returns a yes/no decision as JSON. See
Prompt-based hooks
.
Agent hooks
(
type: "agent"
): spawn a subagent that can use tools like Read, Grep, and Glob to verify conditions before returning a decision. Agent hooks are experimental and may change. See
Agent-based hooks
.
​
Common fields
These fields apply to all hook types:
Field
Required
Description
type
yes
"command"
,
"http"
,
"mcp_tool"
,
"prompt"
, or
"agent"
if
no
Permission rule syntax to filter when this hook runs, such as
"Bash(git *)"
or
"Edit(*.ts)"
. The hook only spawns if the tool call matches the pattern, or if a Bash command is too complex to parse. Only evaluated on tool events:
PreToolUse
,
PostToolUse
,
PostToolUseFailure
,
PermissionRequest
, and
PermissionDenied
. On other events, a hook with
if
set never runs. Uses the same syntax as
permission rules
timeout
no
Seconds before canceling. Defaults: 600 for
command
,
http
, and
mcp_tool
; 30 for
prompt
; 60 for
agent
.
UserPromptSubmit
lowers the
command
,
http
, and
mcp_tool
default to 30
statusMessage
no
Custom spinner message displayed while the hook runs
once
no
If
true
, runs once per session then is removed. Only honored for hooks declared in
skill frontmatter
; ignored in settings files and agent frontmatter
The
if
field holds exactly one permission rule. There is no
&&
,
||
, or list syntax for combining rules; to apply multiple conditions, define a separate hook handler for each. For Bash, the rule is matched against each subcommand of the tool input after leading
VAR=value
assignments are stripped, so
if: "Bash(git push *)"
matches both
FOO=bar git push
and
npm test && git push
. The hook runs if any subcommand matches, and always runs when the command is too complex to parse.
​
Command hook fields
In addition to the
common fields
, command hooks accept these fields:
Field
Required
Description
command
yes
Shell command to execute. With
args
, the executable to spawn directly. See
Exec form and shell form
args
no
Argument list. When present,
command
is resolved as an executable and spawned directly with
args
as the argument vector, with no shell involved. See
Exec form and shell form
async
no
If
true
, runs in the background without blocking. See
Run hooks in the background
asyncRewake
no
If
true
, runs in the background and wakes Claude on exit code 2. Implies
async
. The hook’s stderr, or stdout if stderr is empty, is shown to Claude as a system reminder so it can react to a long-running background failure
shell
no
Shell to use for this hook. Accepts
"bash"
(default) or
"powershell"
. Setting
"powershell"
runs the command via PowerShell on Windows. Does not require
CLAUDE_CODE_USE_POWERSHELL_TOOL
since hooks spawn PowerShell directly. Ignored when
args
is set
Exec form and shell form
A command hook runs as exec form when
args
is set, and shell form when
args
is omitted. Set
args
whenever the hook references a
path placeholder
, since each element is passed as one argument with no quoting. Omit
args
when you need shell features like pipes or
&&
, or when neither concern applies.
Exec form
runs when
args
is present. Claude Code resolves
command
as an executable on
PATH
and spawns it directly with
args
as the argument vector. There is no shell, so each
args
element is one argument exactly as written, and path placeholders like
${CLAUDE_PLUGIN_ROOT}
are substituted into
command
and into each
args
element as plain strings. Special characters such as apostrophes,
$
, and backticks pass through verbatim because there is no shell to interpret them. No shell tokenization happens on any platform.
Shell form
runs when
args
is absent. The
command
string is passed to a shell:
sh -c
on macOS and Linux, Git Bash on Windows, or PowerShell when Git Bash isn’t installed. Set the
shell
field to choose explicitly. The shell tokenizes the string, expands variables, and interprets pipes,
&&
, redirects, and globs.
On Windows, exec form requires
command
to resolve to a real executable such as a
.exe
. The
.cmd
and
.bat
shims that npm, npx, eslint, and other tools install in
node_modules/.bin
are not executables and cannot be spawned without a shell. To run them in exec form, invoke the underlying script with
node
directly, for example
"command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]
. The
node
plus script-path pattern works on every platform because
node.exe
is a real binary. To run a
.cmd
or
.bat
shim by name, use shell form.
This example runs a Node script bundled with a plugin. Exec form passes the resolved script path as one argument with no quoting:
{
"type"
:
"command"
,
"command"
:
"node"
,
"args"
: [
"${CLAUDE_PLUGIN_ROOT}/scripts/format.js"
,
"--fix"
]
}
The equivalent shell form needs quoting to handle paths with spaces or special characters:
{
"type"
:
"command"
,
"command"
:
"node
\"
${CLAUDE_PLUGIN_ROOT}
\"
/scripts/format.js --fix"
}
Both forms support the same
path placeholders
, and both export them as the environment variables
CLAUDE_PROJECT_DIR
,
CLAUDE_PLUGIN_ROOT
, and
CLAUDE_PLUGIN_DATA
on the spawned process, so a script can read
process.env.CLAUDE_PLUGIN_ROOT
regardless of how it was launched. Plugin hooks additionally substitute
${user_config.*}
values; see
User configuration
.
In exec form,
command
is the executable name or path only. If
command
is a bare name with no path separator and contains whitespace alongside
args
, Claude Code logs a warning because the spawn will fail: there is no executable named
node script.js
. Move the extra tokens into
args
. Absolute paths with spaces, such as
C:\Program Files\nodejs\node.exe
, are a single valid executable and do not trigger the warning.
​
HTTP hook fields
In addition to the
common fields
, HTTP hooks accept these fields:
Field
Required
Description
url
yes
URL to send the POST request to
headers
no
Additional HTTP headers as key-value pairs. Values support environment variable interpolation using
$VAR_NAME
or
${VAR_NAME}
syntax. Only variables listed in
allowedEnvVars
are resolved
allowedEnvVars
no
List of environment variable names that may be interpolated into header values. References to unlisted variables are replaced with empty strings. Required for any env var interpolation to work
Claude Code sends the hook’s
JSON input
as the POST request body with
Content-Type: application/json
. The response body uses the same
JSON output format
as command hooks.
Error handling differs from command hooks: non-2xx responses, connection failures, and timeouts all produce non-blocking errors that allow execution to continue. To block a tool call or deny a permission, return a 2xx response with a JSON body containing
decision: "block"
or a
hookSpecificOutput
with
permissionDecision: "deny"
.
This example sends
PreToolUse
events to a local validation service, authenticating with a token from the
MY_TOKEN
environment variable:
{
"hooks"
: {
"PreToolUse"
: [
{
"matcher"
:
"Bash"
,
"hooks"
: [
{
"type"
:
"http"
,
"url"
:
"http://localhost:8080/hooks/pre-tool-use"
,
"timeout"
:
30
,
"headers"
: {
"Authorization"
:
"Bearer $MY_TOKEN"
},
"allowedEnvVars"
: [
"MY_TOKEN"
]
}
]
}
]
}
}
​
MCP tool hook fields
In addition to the
common fields
, MCP tool hooks accept these fields:
Field
Required
Description
server
yes
Name of a configured MCP server. The server must already be connected; the hook never triggers an OAuth or connection flow
tool
yes
Name of the tool to call on that server
input
no
Arguments passed to the tool. String values support
${path}
substitution from the hook’s
JSON input
, such as
"${tool_input.file_path}"
The tool’s text content is treated like command-hook stdout: if it parses as valid
JSON output
it is processed as a decision, otherwise it is shown as plain text. If the named server is not connected, or the tool returns
isError: true
, the hook produces a non-blocking error and execution continues.
MCP tool hooks are available on every hook event once Claude Code has connected to your MCP servers.
SessionStart
and
Setup
typically fire before servers finish connecting, so hooks on those events should expect the “not connected” error on first run.
This example calls the
security_scan
tool on the
my_server
MCP server after each
Write
or
Edit
, passing the edited file’s path:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"mcp_tool"
,
"server"
:
"my_server"
,
"tool"
:
"security_scan"
,
"input"
: {
"file_path"
:
"${tool_input.file_path}"
}
}
]
}
]
}
}
​
Prompt and agent hook fields
In addition to the
common fields
, prompt and agent hooks accept these fields:
Field
Required
Description
prompt
yes
Prompt text to send to the model. Use
$ARGUMENTS
as a placeholder for the hook input JSON
model
no
Model to use for evaluation. Defaults to a fast model
All matching hooks run in parallel, and identical handlers are deduplicated automatically. Command hooks are deduplicated by command string and
args
, and HTTP hooks are deduplicated by URL. Handlers run in the current directory with Claude Code’s environment. The
$CLAUDE_CODE_REMOTE
environment variable is set to
"true"
in remote web environments and not set in the local CLI.
​
Reference scripts by path
Use these placeholders to reference hook scripts relative to the project or plugin root, regardless of the working directory when the hook runs:
${CLAUDE_PROJECT_DIR}
: the project root.
${CLAUDE_PLUGIN_ROOT}
: the plugin’s installation directory, for scripts bundled with a
plugin
. Changes on each plugin update.
${CLAUDE_PLUGIN_DATA}
: the plugin’s
persistent data directory
, for dependencies and state that should survive plugin updates.
Prefer
exec form
for any hook that references a path placeholder. Exec form passes each
args
element as one argument with no shell tokenization, so paths with spaces or special characters need no quoting. In shell form, wrap each placeholder in double quotes.
Project scripts
Plugin scripts
This example uses
${CLAUDE_PROJECT_DIR}
to run a style checker from the project’s
.claude/hooks/
directory after any
Write
or
Edit
tool call:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh"
,
"args"
: []
}
]
}
]
}
}
Define plugin hooks in
hooks/hooks.json
with an optional top-level
description
field. When a plugin is enabled, its hooks merge with your user and project hooks.
This example runs a formatting script bundled with the plugin:
{
"description"
:
"Automatic code formatting"
,
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
,
"args"
: [],
"timeout"
:
30
}
]
}
]
}
}
See the
plugin components reference
for details on creating plugin hooks.
​
Hooks in skills and agents
In addition to settings files and plugins, hooks can be defined directly in
skills
and
subagents
using frontmatter. These hooks are scoped to the component’s lifecycle and only run when that component is active.
All hook events are supported. For subagents,
Stop
hooks are automatically converted to
SubagentStop
since that is the event that fires when a subagent completes.
Hooks use the same configuration format as settings-based hooks but are scoped to the component’s lifetime and cleaned up when it finishes.
This skill defines a
PreToolUse
hook that runs a security validation script before each
Bash
command:
---
name
:
secure-operations
description
:
Perform operations with security checks
hooks
:
PreToolUse
:
-
matcher
:
"Bash"
hooks
:
-
type
:
command
command
:
"./scripts/security-check.sh"
---
Agents use the same format in their YAML frontmatter.
​
The
/hooks
menu
Type
/hooks
in Claude Code to open a read-only browser for your configured hooks. The menu shows every hook event with a count of configured hooks, lets you drill into matchers, and shows the full details of each hook handler. Use it to verify configuration, check which settings file a hook came from, or inspect a hook’s command, prompt, or URL.
The menu displays all five hook types:
command
,
prompt
,
agent
,
http
, and
mcp_tool
. Each hook is labeled with a
[type]
prefix and a source indicating where it was defined:
User
: from
~/.claude/settings.json
Project
: from
.claude/settings.json
Local
: from
.claude/settings.local.json
Plugin
: from a plugin’s
hooks/hooks.json
Session
: registered in memory for the current session
Built-in
: registered internally by Claude Code
Selecting a hook opens a detail view showing its event, matcher, type, source file, and the full command, prompt, or URL. The menu is read-only: to add, modify, or remove hooks, edit the settings JSON directly or ask Claude to make the change.
​
Disable or remove hooks
To remove a hook, delete its entry from the settings JSON file.
To temporarily disable all hooks without removing them, set
"disableAllHooks": true
in your settings file. There is no way to disable an individual hook while keeping it in the configuration.
The
disableAllHooks
setting respects the managed settings hierarchy. If an administrator has configured hooks through managed policy settings,
disableAllHooks
set in user, project, or local settings cannot disable those managed hooks. Only
disableAllHooks
set at the managed settings level can disable managed hooks.
Direct edits to hooks in settings files are normally picked up automatically by the file watcher.
​
Hook input and output
Command hooks receive JSON data via stdin and communicate results through exit codes, stdout, and stderr. HTTP hooks receive the same JSON as the POST request body and communicate results through the HTTP response body. This section covers fields and behavior common to all events. Each event’s section under
Hook events
includes its specific input schema and decision control options.
On macOS and Linux, command hooks run in their own session without a controlling terminal as of v2.1.139. The hook process and any child processes cannot open
/dev/tty
or send escape sequences directly to the Claude Code interface. Windows has no
/dev/tty
. To surface a message to the user on any platform, return
systemMessage
in JSON output. To trigger a desktop notification, set a window title, or ring the bell, return
terminalSequence
instead.
​
Common input fields
Hook events receive these fields as JSON, in addition to event-specific fields documented in each
hook event
section. For command hooks, this JSON arrives via stdin. For HTTP hooks, it arrives as the POST request body.
Field
Description
session_id
Current session identifier
transcript_path
Path to conversation JSON
cwd
Current working directory when the hook is invoked
permission_mode
Current
permission mode
:
"default"
,
"plan"
,
"acceptEdits"
,
"auto"
,
"dontAsk"
, or
"bypassPermissions"
. Not all events receive this field: see each event’s JSON example below to check
effort
Object with a
level
field holding the active
effort level
for the turn:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. If the requested effort exceeds what the current model supports, this is the downgraded level the model actually used, not the level you requested. The object matches the
status line
effort
field. Present for events that fire within a tool-use context, such as
PreToolUse
,
PostToolUse
,
Stop
, and
SubagentStop
, when the current model supports the effort parameter. The level is also available to hook commands and the Bash tool as the
$CLAUDE_EFFORT
environment variable.
hook_event_name
Name of the event that fired
When running with
--agent
or inside a subagent, two additional fields are included:
Field
Description
agent_id
Unique identifier for the subagent. Present only when the hook fires inside a subagent call. Use this to distinguish subagent hook calls from main-thread calls.
agent_type
Agent name (for example,
"Explore"
or
"security-reviewer"
). Present when the session uses
--agent
or the hook fires inside a subagent. For subagents, the subagent’s type takes precedence over the session’s
--agent
value. For
custom subagents
, this is the
name
field from the agent’s frontmatter, not the filename.
Only
SessionStart
hooks receive a
model
field. There is no
$CLAUDE_MODEL
environment variable. A hook process inherits the parent environment, so it can read
$ANTHROPIC_MODEL
if you set it in your shell, but that value does not change when you switch models with
/model
during a session.
For example, a
PreToolUse
hook for a Bash command receives this on stdin:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/home/user/.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/home/user/my-project"
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PreToolUse"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"npm test"
}
}
The
tool_name
and
tool_input
fields are event-specific. Each
hook event
section documents the additional fields for that event.
​
Exit code output
The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored.
Exit 0
means success. Claude Code parses stdout for
JSON output fields
. JSON output is only processed on exit 0. For most events, stdout is written to the debug log but not shown in the transcript. The exceptions are
UserPromptSubmit
,
UserPromptExpansion
, and
SessionStart
, where stdout is added as context that Claude can see and act on.
Exit 2
means a blocking error. Claude Code ignores stdout and any JSON in it. Instead, stderr text is fed back to Claude as an error message. The effect depends on the event:
PreToolUse
blocks the tool call,
UserPromptSubmit
rejects the prompt, and so on. See
exit code 2 behavior
for the full list.
Any other exit code
is a non-blocking error for most hook events. The transcript shows a
<hook name> hook error
notice followed by the first line of stderr, so you can identify the cause without
--debug
. Execution continues and the full stderr is written to the debug log.
For example, a hook command script that blocks dangerous Bash commands:
#!/bin/bash
# Reads JSON input from stdin, checks the command
command
=
$(
jq
-r
'.tool_input.command'
<
/dev/stdin
)
if
[[
"
$command
"
==
rm
*
]];
then
echo
"Blocked: rm commands are not allowed"
>&2
exit
2
# Blocking error: tool call is prevented
fi
exit
0
# Success: tool call proceeds
For most hook events, only exit code 2 blocks the action. Claude Code treats exit code 1 as a non-blocking error and proceeds with the action, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use
exit 2
. The exception is
WorktreeCreate
, where any non-zero exit code aborts worktree creation.
​
Exit code 2 behavior per event
Exit code 2 is the way a hook signals “stop, don’t do this.” The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn’t happened yet) and others represent things that already happened or can’t be prevented.
Hook event
Can block?
What happens on exit 2
PreToolUse
Yes
Blocks the tool call
PermissionRequest
Yes
Denies the permission
UserPromptSubmit
Yes
Blocks prompt processing and erases the prompt
UserPromptExpansion
Yes
Blocks the expansion
Stop
Yes
Prevents Claude from stopping, continues the conversation
SubagentStop
Yes
Prevents the subagent from stopping
TeammateIdle
Yes
Prevents the teammate from going idle (teammate continues working)
TaskCreated
Yes
Rolls back the task creation
TaskCompleted
Yes
Prevents the task from being marked as completed
ConfigChange
Yes
Blocks the configuration change from taking effect (except
policy_settings
)
StopFailure
No
Output and exit code are ignored
PostToolUse
No
Shows stderr to Claude (tool already ran)
PostToolUseFailure
No
Shows stderr to Claude (tool already failed)
PostToolBatch
Yes
Stops the agentic loop before the next model call
PermissionDenied
No
Exit code and stderr are ignored (denial already occurred). Use JSON
hookSpecificOutput.retry: true
to tell the model it may retry
Notification
No
Shows stderr to user only
SubagentStart
No
Shows stderr to user only
SessionStart
No
Shows stderr to user only
Setup
No
Shows stderr to user only
SessionEnd
No
Shows stderr to user only
CwdChanged
No
Shows stderr to user only
FileChanged
No
Shows stderr to user only
PreCompact
Yes
Blocks compaction
PostCompact
No
Shows stderr to user only
Elicitation
Yes
Denies the elicitation
ElicitationResult
Yes
Blocks the response (action becomes decline)
WorktreeCreate
Yes
Any non-zero exit code causes worktree creation to fail
WorktreeRemove
No
Failures are logged in debug mode only
InstructionsLoaded
No
Exit code is ignored
​
HTTP response handling
HTTP hooks use HTTP status codes and response bodies instead of exit codes and stdout:
2xx with an empty body
: success, equivalent to exit code 0 with no output
2xx with a plain text body
: success, the text is added as context
2xx with a JSON body
: success, parsed using the same
JSON output
schema as command hooks
Non-2xx status
: non-blocking error, execution continues
Connection failure or timeout
: non-blocking error, execution continues
Unlike command hooks, HTTP hooks cannot signal a blocking error through status codes alone. To block a tool call or deny a permission, return a 2xx response with a JSON body containing the appropriate decision fields.
​
JSON output
Exit codes let you allow or block, but JSON output gives you finer-grained control. Instead of exiting with code 2 to block, exit 0 and print a JSON object to stdout. Claude Code reads specific fields from that JSON to control behavior, including
decision control
for blocking, allowing, or escalating to the user.
You must choose one approach per hook, not both: either use exit codes alone for signaling, or exit 0 and print JSON for structured control. Claude Code only processes JSON on exit 0. If you exit 2, any JSON is ignored.
Your hook’s stdout must contain only the JSON object. If your shell profile prints text on startup, it can interfere with JSON parsing. See
JSON validation failed
in the troubleshooting guide.
Hook output strings, including
additionalContext
,
systemMessage
, and plain stdout, are capped at 10,000 characters. Output that exceeds this limit is saved to a file and replaced with a preview and file path, the same way large tool results are handled.
The JSON object supports three kinds of fields:
Universal fields
like
continue
work across all events. These are listed in the table below.
Top-level
decision
and
reason
are used by some events to block or provide feedback.
hookSpecificOutput
is a nested object for events that need richer control. It requires a
hookEventName
field set to the event name.
Field
Default
Description
continue
true
If
false
, Claude stops processing entirely after the hook runs. Takes precedence over any event-specific decision fields
stopReason
none
Message shown to the user when
continue
is
false
. Not shown to Claude
suppressOutput
false
If
true
, omits stdout from the debug log
systemMessage
none
Warning message shown to the user
terminalSequence
none
A terminal escape sequence for Claude Code to emit on your behalf, such as a desktop notification, window title, or bell. Restricted to OSC
0
/
1
/
2
/
9
/
99
/
777
and BEL. If the value contains anything outside the allowlist, the field is ignored. Use this instead of writing to
/dev/tty
, which is unavailable to hooks
To stop Claude entirely regardless of event type:
{
"continue"
:
false
,
"stopReason"
:
"Build failed, fix errors before continuing"
}
​
Emit terminal notifications
The
terminalSequence
field requires Claude Code v2.1.141 or later.
Hooks run without a controlling terminal, so writing escape sequences directly to
/dev/tty
fails. Instead, return the escape sequence in the
terminalSequence
field and Claude Code emits it for you through its own terminal write path. This is race-free, works inside tmux and GNU screen, and works on Windows where there is no
/dev/tty
.
The field accepts a string of one or more allowlisted escape sequences:
OSC
0
,
1
,
2
: window and icon titles
OSC
9
: iTerm2, ConEmu, Windows Terminal, and WezTerm notifications, including
9;4
taskbar progress
OSC
99
: Kitty notifications
OSC
777
: urxvt, Ghostty, and Warp notifications
Bare BEL
Sequences may be terminated with BEL or with ST. Anything outside the allowlist, including CSI cursor and color sequences, OSC palette sequences, OSC 8 hyperlinks, OSC 52 clipboard writes, and OSC 1337, is rejected and the field is ignored.
The example below fires a desktop notification from a
Notification
hook. The escape sequence is built with
printf
octal escapes so the control bytes never appear on the shell command line, and
jq -n --arg
builds the JSON output so quotes, backslashes, and newlines in the notification message are escaped correctly:
#!/bin/bash
# Notification hook: ping the desktop when Claude Code needs attention.
input
=
$(
cat
)
title
=
"Claude Code"
body
=
$(
jq
-r
'.message // "Needs your attention"'
<<<
"
$input
"
)
seq
=
$(
printf
'\033]777;notify;%s;%s\007'
"
$title
"
"
$body
"
)
jq
-nc
--arg
seq
"
$seq
"
'{terminalSequence: $seq}'
The
{ "terminalSequence": "..." }
shape is the same from any shell or language. On Windows, build the escape string in PowerShell or a script and emit the same JSON object.
terminalSequence
is the supported replacement for hooks that previously wrote escape sequences directly to
/dev/tty
. The allowlist is restricted to sequences that cannot move the cursor or alter colors, so a hook can never corrupt an on-screen prompt.
​
Add context for Claude
The
additionalContext
field passes a string from your hook into Claude’s context window. Claude Code wraps the string in a system reminder and inserts it into the conversation at the point where the hook fired. Claude reads the reminder on the next model request, but it does not appear as a chat message in the interface.
Return
additionalContext
inside
hookSpecificOutput
alongside the event name:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUse"
,
"additionalContext"
:
"This file is generated. Edit src/schema.ts and run `bun generate` instead."
}
}
Where the reminder appears depends on the event:
SessionStart
,
Setup
, and
SubagentStart
: at the start of the conversation, before the first prompt
UserPromptSubmit
and
UserPromptExpansion
: alongside the submitted prompt
PreToolUse
,
PostToolUse
,
PostToolUseFailure
, and
PostToolBatch
: next to the tool result
When several hooks return
additionalContext
for the same event, Claude receives all of the values. If a value exceeds 10,000 characters, Claude Code writes the full text to a file in the session directory and passes Claude the file path with a short preview instead.
Use
additionalContext
for information Claude should know about the current state of your environment or the operation that just ran:
Environment state
: the current branch, deployment target, or active feature flags
Conditional project rules
: which test command applies to the file just edited, which directories are read-only in this worktree
External data
: open issues assigned to you, recent CI results, content fetched from an internal service
For instructions that never change, prefer
CLAUDE.md
. It loads without running a script and is the standard place for static project conventions.
Write the text as factual statements rather than imperative system instructions. Phrasing such as “The deployment target is production” or “This repo uses
bun test
” reads as project information. Text framed as out-of-band system commands can trigger Claude’s prompt-injection defenses, which causes Claude to surface the text to you instead of treating it as context.
Once injected, the text is saved in the session transcript. For mid-session events like
PostToolUse
or
UserPromptSubmit
, resuming with
--continue
or
--resume
replays the saved text rather than re-running the hook for past turns, so values like timestamps or commit SHAs become stale on resume.
SessionStart
hooks run again on resume with
source
set to
"resume"
, so they can refresh their context.
​
Decision control
Not every event supports blocking or controlling behavior through JSON. The events that do each use a different set of fields to express that decision. Use this table as a quick reference before writing a hook:
Events
Decision pattern
Key fields
UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact
Top-level
decision
decision: "block"
,
reason
TeammateIdle, TaskCreated, TaskCompleted
Exit code or
continue: false
Exit code 2 blocks the action with stderr feedback. JSON
{"continue": false, "stopReason": "..."}
also stops the teammate entirely, matching
Stop
hook behavior
PreToolUse
hookSpecificOutput
permissionDecision
(allow/deny/ask/defer),
permissionDecisionReason
PermissionRequest
hookSpecificOutput
decision.behavior
(allow/deny)
PermissionDenied
hookSpecificOutput
retry: true
tells the model it may retry the denied tool call
WorktreeCreate
path return
Command hook prints path on stdout; HTTP hook returns
hookSpecificOutput.worktreePath
. Hook failure or missing path fails creation
Elicitation
hookSpecificOutput
action
(accept/decline/cancel),
content
(form field values for accept)
ElicitationResult
hookSpecificOutput
action
(accept/decline/cancel),
content
(form field values override)
WorktreeRemove, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, FileChanged
None
No decision control. Used for side effects like logging or cleanup
Here are examples of each pattern in action:
Top-level decision
PreToolUse
PermissionRequest
Used by
UserPromptSubmit
,
UserPromptExpansion
,
PostToolUse
,
PostToolUseFailure
,
PostToolBatch
,
Stop
,
SubagentStop
,
ConfigChange
, and
PreCompact
. The only value is
"block"
. To allow the action to proceed, omit
decision
from your JSON, or exit 0 without any JSON at all:
{
"decision"
:
"block"
,
"reason"
:
"Test suite must pass before proceeding"
}
Uses
hookSpecificOutput
for richer control: allow, deny, or escalate to the user. You can also modify tool input before it runs or inject additional context for Claude. See
PreToolUse decision control
for the full set of options.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"deny"
,
"permissionDecisionReason"
:
"Database writes are not allowed"
}
}
Uses
hookSpecificOutput
to allow or deny a permission request on behalf of the user. When allowing, you can also modify the tool’s input or apply permission rules so the user isn’t prompted again. See
PermissionRequest decision control
for the full set of options.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedInput"
: {
"command"
:
"npm run lint"
}
}
}
}
For extended examples including Bash command validation, prompt filtering, and auto-approval scripts, see
What you can automate
in the guide and the
Bash command validator reference implementation
.
​
Hook events
Each event corresponds to a point in Claude Code’s lifecycle where hooks can run. The sections below are ordered to match the lifecycle: from session setup through the agentic loop to session end. Each section describes when the event fires, what matchers it supports, the JSON input it receives, and how to control behavior through output.
​
SessionStart
Runs when Claude Code starts a new session or resumes an existing session. Useful for loading development context like existing issues or recent changes to your codebase, or setting up environment variables. For static context that does not require a script, use
CLAUDE.md
instead.
SessionStart runs on every session, so keep these hooks fast. Only
type: "command"
and
type: "mcp_tool"
hooks are supported.
The matcher value corresponds to how the session was initiated:
Matcher
When it fires
startup
New session
resume
--resume
,
--continue
, or
/resume
clear
/clear
compact
Auto or manual compaction
​
SessionStart input
In addition to the
common input fields
, SessionStart hooks receive
source
,
model
, and optionally
agent_type
. The
source
field indicates how the session started:
"startup"
for new sessions,
"resume"
for resumed sessions,
"clear"
after
/clear
, or
"compact"
after compaction. The
model
field contains the model identifier. If you start Claude Code with
claude --agent <name>
, an
agent_type
field contains the agent name.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SessionStart"
,
"source"
:
"startup"
,
"model"
:
"claude-sonnet-4-6"
}
​
SessionStart decision control
Any text your hook script prints to stdout is added as context for Claude. In addition to the
JSON output fields
available to all hooks, you can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context at the start of the conversation, before the first prompt. See
Add context for Claude
for how the text is delivered and what to put in it
{
"hookSpecificOutput"
: {
"hookEventName"
:
"SessionStart"
,
"additionalContext"
:
"Current branch: feat/auth-refactor
\n
Uncommitted changes: src/auth.ts, src/login.tsx
\n
Active issue: #4211 Migrate to OAuth2"
}
}
Since plain stdout already reaches Claude for this event, a hook that only loads context can print to stdout directly without building JSON. Use the JSON form when you need to combine context with other fields such as
suppressOutput
.
​
Persist environment variables
SessionStart hooks have access to the
CLAUDE_ENV_FILE
environment variable, which provides a file path where you can persist environment variables for subsequent Bash commands.
To set individual environment variables, write
export
statements to
CLAUDE_ENV_FILE
. Use append (
>>
) to preserve variables set by other hooks:
#!/bin/bash
if
[
-n
"
$CLAUDE_ENV_FILE
"
];
then
echo
'export NODE_ENV=production'
>>
"
$CLAUDE_ENV_FILE
"
echo
'export DEBUG_LOG=true'
>>
"
$CLAUDE_ENV_FILE
"
echo
'export PATH="$PATH:./node_modules/.bin"'
>>
"
$CLAUDE_ENV_FILE
"
fi
exit
0
To capture all environment changes from setup commands, compare the exported variables before and after:
#!/bin/bash
ENV_BEFORE
=
$(e
xport
-p
|
sort
)
# Run your setup commands that modify the environment
source
~/.nvm/nvm.sh
nvm
use
20
if
[
-n
"
$CLAUDE_ENV_FILE
"
];
then
ENV_AFTER
=
$(e
xport
-p
|
sort
)
comm
-13
<(
echo
"
$ENV_BEFORE
")
<(
echo
"
$ENV_AFTER
")
>>
"
$CLAUDE_ENV_FILE
"
fi
exit
0
Any variables written to this file will be available in all subsequent Bash commands that Claude Code executes during the session.
CLAUDE_ENV_FILE
is available for SessionStart,
Setup
,
CwdChanged
, and
FileChanged
hooks. Other hook types do not have access to this variable.
​
Setup
Fires only when you launch Claude Code with
--init-only
, or with
--init
or
--maintenance
in print mode (
-p
). It does not fire on normal startup. Use it for one-time dependency installation or scheduled cleanup that you trigger explicitly from CI or scripts, separate from normal session startup. For per-session initialization, use
SessionStart
instead.
The matcher value corresponds to the CLI flag that triggered the hook:
Matcher
When it fires
init
claude --init-only
or
claude -p --init
maintenance
claude -p --maintenance
--init-only
runs Setup hooks and
SessionStart
hooks with the
startup
matcher, then exits without starting a conversation.
--init
and
--maintenance
fire Setup hooks only when combined with
-p
(print mode); in an interactive session those two flags do not currently fire Setup hooks.
Because Setup does not fire on every launch, a plugin that needs a dependency installed cannot rely on Setup alone. The practical pattern is to check for the dependency on first use and install on miss, for example a hook or skill that tests for
${CLAUDE_PLUGIN_DATA}/node_modules
and runs
npm install
if absent. See the
persistent data directory
for where to store installed dependencies.
​
Setup input
In addition to the
common input fields
, Setup hooks receive a
trigger
field set to either
"init"
or
"maintenance"
:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"Setup"
,
"trigger"
:
"init"
}
​
Setup decision control
Setup hooks cannot block. On exit code 2, stderr is shown to the user; on any other non-zero exit code, stderr appears only when you launch with
--verbose
. In both cases execution continues. To pass information into Claude’s context, return
additionalContext
in JSON output; plain stdout is written to the debug log only. In addition to the
JSON output fields
available to all hooks, you can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context. Multiple hooks’ values are concatenated
{
"hookSpecificOutput"
: {
"hookEventName"
:
"Setup"
,
"additionalContext"
:
"Dependencies installed: node_modules, .venv"
}
}
Setup hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
. Only
type: "command"
and
type: "mcp_tool"
hooks are supported.
​
InstructionsLoaded
Fires when a
CLAUDE.md
or
.claude/rules/*.md
file is loaded into context. This event fires at session start for eagerly-loaded files and again later when files are lazily loaded, for example when Claude accesses a subdirectory that contains a nested
CLAUDE.md
or when conditional rules with
paths:
frontmatter match. The hook does not support blocking or decision control. It runs asynchronously for observability purposes.
The matcher runs against
load_reason
. For example, use
"matcher": "session_start"
to fire only for files loaded at session start, or
"matcher": "path_glob_match|nested_traversal"
to fire only for lazy loads.
​
InstructionsLoaded input
In addition to the
common input fields
, InstructionsLoaded hooks receive these fields:
Field
Description
file_path
Absolute path to the instruction file that was loaded
memory_type
Scope of the file:
"User"
,
"Project"
,
"Local"
, or
"Managed"
load_reason
Why the file was loaded:
"session_start"
,
"nested_traversal"
,
"path_glob_match"
,
"include"
, or
"compact"
. The
"compact"
value fires when instruction files are re-loaded after a compaction event
globs
Path glob patterns from the file’s
paths:
frontmatter, if any. Present only for
path_glob_match
loads
trigger_file_path
Path to the file whose access triggered this load, for lazy loads
parent_file_path
Path to the parent instruction file that included this one, for
include
loads
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project"
,
"hook_event_name"
:
"InstructionsLoaded"
,
"file_path"
:
"/Users/my-project/CLAUDE.md"
,
"memory_type"
:
"Project"
,
"load_reason"
:
"session_start"
}
​
InstructionsLoaded decision control
InstructionsLoaded hooks have no decision control. They cannot block or modify instruction loading. Use this event for audit logging, compliance tracking, or observability.
​
UserPromptSubmit
Runs when the user submits a prompt, before Claude processes it. This allows you
to add additional context based on the prompt/conversation, validate prompts, or
block certain types of prompts.
UserPromptSubmit
hooks have a default timeout of 30 seconds for
command
,
http
, and
mcp_tool
types, shorter than the 600-second default for those types on other events. Because this hook runs before every prompt and blocks model processing until it completes, a stuck hook stalls the session. If your hook needs more time, set the
timeout
field in the hook entry.
​
UserPromptSubmit input
In addition to the
common input fields
, UserPromptSubmit hooks receive the
prompt
field containing the text the user submitted.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"UserPromptSubmit"
,
"prompt"
:
"Write a function to calculate the factorial of a number"
}
​
UserPromptSubmit decision control
UserPromptSubmit
hooks can control whether a user prompt is processed and add context. All
JSON output fields
are available.
There are two ways to add context to the conversation on exit code 0:
Plain text stdout
: any non-JSON text written to stdout is added as context
JSON with
additionalContext
: use the JSON format below for more control. The
additionalContext
field is added as context
Plain stdout is shown as hook output in the transcript. The
additionalContext
field is added more discretely.
To block a prompt, return a JSON object with
decision
set to
"block"
:
Field
Description
decision
"block"
prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed
reason
Shown to the user when
decision
is
"block"
. Not added to context
additionalContext
String added to Claude’s context alongside the submitted prompt. See
Add context for Claude
sessionTitle
Sets the session title. Use to name sessions automatically based on the prompt content
{
"decision"
:
"block"
,
"reason"
:
"Explanation for decision"
,
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptSubmit"
,
"additionalContext"
:
"My additional context here"
,
"sessionTitle"
:
"My session title"
}
}
The JSON format isn’t required for simple use cases. To add context, you can print plain text to stdout with exit code 0. Use JSON when you need to
block prompts or want more structured control.
​
UserPromptExpansion
Runs when a user-typed slash command expands into a prompt before reaching Claude. Use this to block specific commands from direct invocation, inject context for a particular skill, or log which commands users invoke. For example, a hook matching
deploy
can block
/deploy
unless an approval file is present, or a hook matching a review skill can append the team’s review checklist as
additionalContext
.
This event covers the path
PreToolUse
does not: a
PreToolUse
hook matching the
Skill
tool fires only when Claude calls the tool, but typing
/skillname
directly bypasses
PreToolUse
.
UserPromptExpansion
fires on that direct path.
Matches on
command_name
. Leave the matcher empty to fire on every prompt-type slash command.
​
UserPromptExpansion input
In addition to the
common input fields
, UserPromptExpansion hooks receive
expansion_type
,
command_name
,
command_args
,
command_source
, and the original
prompt
string. The
expansion_type
field is
slash_command
for skill and custom commands, or
mcp_prompt
for MCP server prompts.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../00893aaf.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"UserPromptExpansion"
,
"expansion_type"
:
"slash_command"
,
"command_name"
:
"example-skill"
,
"command_args"
:
"arg1 arg2"
,
"command_source"
:
"plugin"
,
"prompt"
:
"/example-skill arg1 arg2"
}
​
UserPromptExpansion decision control
UserPromptExpansion
hooks can block the expansion or add context. All
JSON output fields
are available.
Field
Description
decision
"block"
prevents the slash command from expanding. Omit to allow it to proceed
reason
Shown to the user when
decision
is
"block"
additionalContext
String added to Claude’s context alongside the expanded prompt. See
Add context for Claude
{
"decision"
:
"block"
,
"reason"
:
"This slash command is not available"
,
"hookSpecificOutput"
: {
"hookEventName"
:
"UserPromptExpansion"
,
"additionalContext"
:
"Additional context for this expansion"
}
}
​
PreToolUse
Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name:
Bash
,
Edit
,
Write
,
Read
,
Glob
,
Grep
,
Agent
,
WebFetch
,
WebSearch
,
AskUserQuestion
,
ExitPlanMode
, and any
MCP tool names
.
Use
PreToolUse decision control
to allow, deny, ask, or defer the tool call.
​
PreToolUse input
In addition to the
common input fields
, PreToolUse hooks receive
tool_name
,
tool_input
, and
tool_use_id
. The
tool_input
fields depend on the tool:
Bash
Executes shell commands.
Field
Type
Example
Description
command
string
"npm test"
The shell command to execute
description
string
"Run test suite"
Optional description of what the command does
timeout
number
120000
Optional timeout in milliseconds
run_in_background
boolean
false
Whether to run the command in background
Write
Creates or overwrites a file.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to write
content
string
"file content"
Content to write to the file
Edit
Replaces a string in an existing file.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to edit
old_string
string
"original text"
Text to find and replace
new_string
string
"replacement text"
Replacement text
replace_all
boolean
false
Whether to replace all occurrences
Read
Reads file contents.
Field
Type
Example
Description
file_path
string
"/path/to/file.txt"
Absolute path to the file to read
offset
number
10
Optional line number to start reading from
limit
number
50
Optional number of lines to read
Glob
Finds files matching a glob pattern.
Field
Type
Example
Description
pattern
string
"**/*.ts"
Glob pattern to match files against
path
string
"/path/to/dir"
Optional directory to search in. Defaults to current working directory
Grep
Searches file contents with regular expressions.
Field
Type
Example
Description
pattern
string
"TODO.*fix"
Regular expression pattern to search for
path
string
"/path/to/dir"
Optional file or directory to search in
glob
string
"*.ts"
Optional glob pattern to filter files
output_mode
string
"content"
"content"
,
"files_with_matches"
, or
"count"
. Defaults to
"files_with_matches"
-i
boolean
true
Case insensitive search
multiline
boolean
false
Enable multiline matching
WebFetch
Fetches and processes web content.
Field
Type
Example
Description
url
string
"https://example.com/api"
URL to fetch content from
prompt
string
"Extract the API endpoints"
Prompt to run on the fetched content
WebSearch
Searches the web.
Field
Type
Example
Description
query
string
"react hooks best practices"
Search query
allowed_domains
array
["docs.example.com"]
Optional: only include results from these domains
blocked_domains
array
["spam.example.com"]
Optional: exclude results from these domains
Agent
Spawns a
subagent
.
Field
Type
Example
Description
prompt
string
"Find all API endpoints"
The task for the agent to perform
description
string
"Find API endpoints"
Short description of the task
subagent_type
string
"Explore"
Type of specialized agent to use
model
string
"sonnet"
Optional model alias to override the default
In
PostToolUse
,
tool_response
for a completed Agent call carries the subagent’s final text along with usage telemetry. Read these fields to record per-subagent cost from a hook:
Field
Type
Example
Description
status
string
"completed"
"completed"
for synchronous calls,
"async_launched"
for
run_in_background: true
agentId
string
"a4d2c8f1e0b3a297"
Identifier for the subagent run
content
array
[{"type": "text", "text": "Found 12 endpoints..."}]
The subagent’s final text blocks
totalTokens
number
12450
Total tokens billed across the subagent’s turns
totalDurationMs
number
48211
Wall-clock duration of the subagent run
totalToolUseCount
number
7
Count of tool calls the subagent made
usage
object
{"input_tokens": 8320, ...}
Per-type token breakdown:
input_tokens
,
output_tokens
,
cache_creation_input_tokens
,
cache_read_input_tokens
For
run_in_background: true
calls, the tool returns immediately after launching the subagent, so
tool_response
carries no usage fields. It has
status: "async_launched"
,
agentId
,
description
,
prompt
, and
outputFile
instead.
AskUserQuestion
Asks the user one to four multiple-choice questions.
Field
Type
Example
Description
questions
array
[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]
Questions to present, each with a
question
string, short
header
,
options
array, and optional
multiSelect
flag
answers
object
{"Which framework?": "React"}
Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude does not set this field; supply it via
updatedInput
to answer programmatically
ExitPlanMode
Presents a plan and asks the user to approve it before Claude leaves
plan mode
. Claude writes the plan to a file on disk before calling the tool, so the literal
tool_input
from the model only carries
allowedPrompts
. Claude Code injects the plan content and file path before passing the input to hooks.
Field
Type
Example
Description
plan
string
"## Refactor auth\n1. Extract..."
Plan content in Markdown. Injected from the plan file on disk
planFilePath
string
"/Users/.../plans/refactor-auth.md"
Path to the plan file. Injected
allowedPrompts
array
[{"tool": "Bash", "prompt": "run tests"}]
Optional. Prompt-based permissions Claude is requesting to implement the plan, each with a
tool
name and a
prompt
describing the category of action
In
PostToolUse
,
tool_response
is an object with
plan
and
filePath
fields holding the approved plan, plus internal status flags. Read
tool_response.plan
for the plan content rather than re-reading the file from disk.
​
PreToolUse decision control
PreToolUse
hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level
decision
field, PreToolUse returns its decision inside a
hookSpecificOutput
object. This gives it richer control: four outcomes (allow, deny, ask, or defer) plus the ability to modify tool input before execution.
Field
Description
permissionDecision
"allow"
skips the permission prompt.
"deny"
prevents the tool call.
"ask"
prompts the user to confirm.
"defer"
exits gracefully so the tool can be resumed later.
Deny and ask rules
are still evaluated regardless of what the hook returns
permissionDecisionReason
For
"allow"
and
"ask"
, shown to the user but not Claude. For
"deny"
, shown to Claude. For
"defer"
, ignored
updatedInput
Modifies the tool’s input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Combine with
"allow"
to auto-approve, or
"ask"
to show the modified input to the user. For
"defer"
, ignored
additionalContext
String added to Claude’s context alongside the tool result. Ignored when
permissionDecision
is
"defer"
. See
Add context for Claude
When multiple PreToolUse hooks return different decisions, precedence is
deny
>
defer
>
ask
>
allow
.
When a hook returns
"ask"
, the permission prompt displayed to the user includes a label identifying where the hook came from: for example,
[User]
,
[Project]
,
[Plugin]
, or
[Local]
. This helps users understand which configuration source is requesting confirmation.
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PreToolUse"
,
"permissionDecision"
:
"allow"
,
"permissionDecisionReason"
:
"My reason here"
,
"updatedInput"
: {
"field_to_modify"
:
"new value"
},
"additionalContext"
:
"Current environment: production. Proceed with caution."
}
}
AskUserQuestion
and
ExitPlanMode
require user interaction and normally block in
non-interactive mode
with the
-p
flag. Returning
permissionDecision: "allow"
together with
updatedInput
satisfies that requirement: the hook reads the tool’s input from stdin, collects the answer through your own UI, and returns it in
updatedInput
so the tool runs without prompting. Returning
"allow"
alone is not sufficient for these tools. For
AskUserQuestion
, echo back the original
questions
array and add an
answers
object mapping each question’s text to the chosen answer.
PreToolUse previously used top-level
decision
and
reason
fields, but these are deprecated for this event. Use
hookSpecificOutput.permissionDecision
and
hookSpecificOutput.permissionDecisionReason
instead. The deprecated values
"approve"
and
"block"
map to
"allow"
and
"deny"
respectively. Other events like PostToolUse and Stop continue to use top-level
decision
and
reason
as their current format.
​
Defer a tool call for later
"defer"
is for integrations that run
claude -p
as a subprocess and read its JSON output, such as an Agent SDK app or a custom UI built on top of Claude Code. It lets that calling process pause Claude at a tool call, collect input through its own interface, and resume where it left off. Claude Code honors this value only in
non-interactive mode
with the
-p
flag. In interactive sessions it logs a warning and ignores the hook result.
The
defer
value requires Claude Code v2.1.89 or later. Earlier versions do not recognize it and the tool proceeds through the normal permission flow.
The
AskUserQuestion
tool is the typical case: Claude wants to ask the user something, but there is no terminal to answer in. The round trip works like this:
Claude calls
AskUserQuestion
. The
PreToolUse
hook fires.
The hook returns
permissionDecision: "defer"
. The tool does not execute. The process exits with
stop_reason: "tool_deferred"
and the pending tool call preserved in the transcript.
The calling process reads
deferred_tool_use
from the SDK result, surfaces the question in its own UI, and waits for an answer.
The calling process runs
claude -p --resume <session-id>
. The same tool call fires
PreToolUse
again.
The hook returns
permissionDecision: "allow"
with the answer in
updatedInput
. The tool executes and Claude continues.
The
deferred_tool_use
field carries the tool’s
id
,
name
, and
input
. The
input
is the parameters Claude generated for the tool call, captured before execution:
{
"type"
:
"result"
,
"subtype"
:
"success"
,
"stop_reason"
:
"tool_deferred"
,
"session_id"
:
"abc123"
,
"deferred_tool_use"
: {
"id"
:
"toolu_01abc"
,
"name"
:
"AskUserQuestion"
,
"input"
: {
"questions"
: [{
"question"
:
"Which framework?"
,
"header"
:
"Framework"
,
"options"
: [{
"label"
:
"React"
}, {
"label"
:
"Vue"
}],
"multiSelect"
:
false
}] }
}
}
There is no timeout or retry limit. The session remains on disk until you resume it, subject to the
cleanupPeriodDays
retention sweep that deletes session files after 30 days by default. If the answer is not ready when you resume, the hook can return
"defer"
again and the process exits the same way. The calling process controls when to break the loop by eventually returning
"allow"
or
"deny"
from the hook.
"defer"
only works when Claude makes a single tool call in the turn. If Claude makes several tool calls at once,
"defer"
is ignored with a warning and the tool proceeds through the normal permission flow. The constraint exists because resume can only re-run one tool: there is no way to defer one call from a batch without leaving the others unresolved.
If the deferred tool is no longer available when you resume, the process exits with
stop_reason: "tool_deferred_unavailable"
and
is_error: true
before the hook fires. This happens when an MCP server that provided the tool is not connected for the resumed session. The
deferred_tool_use
payload is still included so you can identify which tool went missing.
--resume
restores the permission mode that was active when the tool was deferred, so you do not need to pass
--permission-mode
again. The exceptions are
plan
and
bypassPermissions
, which are never carried over. Passing
--permission-mode
explicitly on resume overrides the restored value.
​
PermissionRequest
Runs when the user is shown a permission dialog.
Use
PermissionRequest decision control
to allow or deny on behalf of the user.
Matches on tool name, same values as PreToolUse.
​
PermissionRequest input
PermissionRequest hooks receive
tool_name
and
tool_input
fields like PreToolUse hooks, but without
tool_use_id
. An optional
permission_suggestions
array contains the “always allow” options the user would normally see in the permission dialog. The difference is when the hook fires: PermissionRequest hooks run when a permission dialog is about to be shown to the user, while PreToolUse hooks run before tool execution regardless of permission status.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PermissionRequest"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf node_modules"
,
"description"
:
"Remove node_modules directory"
},
"permission_suggestions"
: [
{
"type"
:
"addRules"
,
"rules"
: [{
"toolName"
:
"Bash"
,
"ruleContent"
:
"rm -rf node_modules"
}],
"behavior"
:
"allow"
,
"destination"
:
"localSettings"
}
]
}
​
PermissionRequest decision control
PermissionRequest
hooks can allow or deny permission requests. In addition to the
JSON output fields
available to all hooks, your hook script can return a
decision
object with these event-specific fields:
Field
Description
behavior
"allow"
grants the permission,
"deny"
denies it.
Deny and ask rules
are still evaluated, so a hook returning
"allow"
does not override a matching deny rule
updatedInput
For
"allow"
only: modifies the tool’s input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. The modified input is re-evaluated against deny and ask rules
updatedPermissions
For
"allow"
only: array of
permission update entries
to apply, such as adding an allow rule or changing the session permission mode
message
For
"deny"
only: tells Claude why the permission was denied
interrupt
For
"deny"
only: if
true
, stops Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionRequest"
,
"decision"
: {
"behavior"
:
"allow"
,
"updatedInput"
: {
"command"
:
"npm run lint"
}
}
}
}
​
Permission update entries
The
updatedPermissions
output field and the
permission_suggestions
input field
both use the same array of entry objects. Each entry has a
type
that determines its other fields, and a
destination
that controls where the change is written.
type
Fields
Effect
addRules
rules
,
behavior
,
destination
Adds permission rules.
rules
is an array of
{toolName, ruleContent?}
objects. Omit
ruleContent
to match the whole tool.
behavior
is
"allow"
,
"deny"
, or
"ask"
replaceRules
rules
,
behavior
,
destination
Replaces all rules of the given
behavior
at the
destination
with the provided
rules
removeRules
rules
,
behavior
,
destination
Removes matching rules of the given
behavior
setMode
mode
,
destination
Changes the permission mode. Valid modes are
default
,
acceptEdits
,
dontAsk
,
bypassPermissions
, and
plan
addDirectories
directories
,
destination
Adds working directories.
directories
is an array of path strings
removeDirectories
directories
,
destination
Removes working directories
setMode
with
bypassPermissions
only takes effect if the session was launched with bypass mode already available:
--dangerously-skip-permissions
,
--permission-mode bypassPermissions
,
--allow-dangerously-skip-permissions
, or
permissions.defaultMode: "bypassPermissions"
in settings, and the mode is not disabled by
permissions.disableBypassPermissionsMode
. Otherwise the update is a no-op.
bypassPermissions
is never persisted as
defaultMode
regardless of
destination
.
The
destination
field on every entry determines whether the change stays in memory or persists to a settings file.
destination
Writes to
session
in-memory only, discarded when the session ends
localSettings
.claude/settings.local.json
projectSettings
.claude/settings.json
userSettings
~/.claude/settings.json
A hook can echo one of the
permission_suggestions
it received as its own
updatedPermissions
output, which is equivalent to the user selecting that “always allow” option in the dialog.
​
PostToolUse
Runs immediately after a tool completes successfully.
Matches on tool name, same values as PreToolUse.
​
PostToolUse input
PostToolUse
hooks fire after a tool has already executed successfully. The input includes both
tool_input
, the arguments sent to the tool, and
tool_response
, the result it returned. The exact schema for both depends on the tool.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolUse"
,
"tool_name"
:
"Write"
,
"tool_input"
: {
"file_path"
:
"/path/to/file.txt"
,
"content"
:
"file content"
},
"tool_response"
: {
"filePath"
:
"/path/to/file.txt"
,
"success"
:
true
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"duration_ms"
:
12
}
Field
Description
duration_ms
Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks
​
PostToolUse decision control
PostToolUse
hooks can provide feedback to Claude after tool execution. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
decision
"block"
adds the
reason
next to the tool result. Claude still sees the original output; to replace it, use
updatedToolOutput
reason
Explanation shown to Claude when
decision
is
"block"
additionalContext
String added to Claude’s context alongside the tool result. See
Add context for Claude
updatedToolOutput
Replaces the tool’s output with the provided value before it is sent to Claude. The value must match the tool’s output shape
updatedMCPToolOutput
Replaces the output for
MCP tools
only. Prefer
updatedToolOutput
, which works for all tools
The example below replaces the output of a
Bash
call. The replacement value matches the
Bash
tool’s output shape:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUse"
,
"additionalContext"
:
"Additional information for Claude"
,
"updatedToolOutput"
: {
"stdout"
:
"[redacted]"
,
"stderr"
:
""
,
"interrupted"
:
false
,
"isImage"
:
false
}
}
}
updatedToolOutput
only changes what Claude sees. The tool has already run by the time the hook fires, so any files written, commands executed, or network requests sent have already taken effect. Telemetry such as OpenTelemetry tool spans and analytics events also captures the original output before the hook runs. To prevent or modify a tool call before it runs, use a
PreToolUse
hook instead.
The replacement value must match the tool’s output shape. Built-in tools return structured objects rather than plain strings. For example,
Bash
returns an object with
stdout
,
stderr
,
interrupted
, and
isImage
fields. For built-in tools, a value that does not match the tool’s output schema is ignored and the original output is used. MCP tool output is passed through without schema validation. Stripping error details that Claude needs can cause it to proceed on a false assumption.
​
PostToolUseFailure
Runs when a tool execution fails. This event fires for tool calls that throw errors or return failure results. Use this to log failures, send alerts, or provide corrective feedback to Claude.
Matches on tool name, same values as PreToolUse.
​
PostToolUseFailure input
PostToolUseFailure hooks receive the same
tool_name
and
tool_input
fields as PostToolUse, along with error information as top-level fields:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolUseFailure"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"npm test"
,
"description"
:
"Run test suite"
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"error"
:
"Command exited with non-zero status code 1"
,
"is_interrupt"
:
false
,
"duration_ms"
:
4187
}
Field
Description
error
String describing what went wrong
is_interrupt
Optional boolean indicating whether the failure was caused by user interruption
duration_ms
Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks
​
PostToolUseFailure decision control
PostToolUseFailure
hooks can provide context to Claude after a tool failure. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
additionalContext
String added to Claude’s context alongside the error. See
Add context for Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolUseFailure"
,
"additionalContext"
:
"Additional information about the failure for Claude"
}
}
​
PostToolBatch
Runs once after every tool call in a batch has resolved, before Claude Code sends the next request to the model.
PostToolUse
fires once per tool, which means it fires concurrently when Claude makes parallel tool calls.
PostToolBatch
fires exactly once with the full batch, so it is the right place to inject context that depends on the set of tools that ran rather than on any single tool. There is no matcher for this event.
​
PostToolBatch input
In addition to the
common input fields
, PostToolBatch hooks receive
tool_calls
, an array describing every tool call in the batch:
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"PostToolBatch"
,
"tool_calls"
: [
{
"tool_name"
:
"Read"
,
"tool_input"
: {
"file_path"
:
"/.../ledger/accounts.py"
},
"tool_use_id"
:
"toolu_01..."
,
"tool_response"
:
"     1
\t
from __future__ import annotations
\n
2
\t
..."
},
{
"tool_name"
:
"Read"
,
"tool_input"
: {
"file_path"
:
"/.../ledger/transactions.py"
},
"tool_use_id"
:
"toolu_02..."
,
"tool_response"
:
"     1
\t
from __future__ import annotations
\n
2
\t
..."
}
]
}
tool_response
contains the same content the model receives in the corresponding
tool_result
block. The value is a serialized string or content-block array, exactly as the tool emitted it. For
Read
, that means line-number-prefixed text rather than raw file contents. Responses can be large, so parse only the fields you need.
The
tool_response
shape differs from
PostToolUse
’s.
PostToolUse
passes the tool’s structured
Output
object, such as
{filePath: "...", success: true}
for
Write
;
PostToolBatch
passes the serialized
tool_result
content the model sees.
​
PostToolBatch decision control
PostToolBatch
hooks can inject context for Claude. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
additionalContext
Context string injected once before the next model call. See
Add context for Claude
for delivery details, what to put in it, and how resumed sessions handle past values
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PostToolBatch"
,
"additionalContext"
:
"These files are part of the ledger module. Run pytest before marking the task complete."
}
}
Returning
decision: "block"
or
continue: false
stops the agentic loop before the next model call.
​
PermissionDenied
Runs when the
auto mode
classifier denies a tool call. This hook only fires in auto mode: it does not run when you manually deny a permission dialog, when a
PreToolUse
hook blocks a call, or when a
deny
rule matches. Use it to log classifier denials, adjust configuration, or tell the model it may retry the tool call.
Matches on tool name, same values as PreToolUse.
​
PermissionDenied input
In addition to the
common input fields
, PermissionDenied hooks receive
tool_name
,
tool_input
,
tool_use_id
, and
reason
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"auto"
,
"hook_event_name"
:
"PermissionDenied"
,
"tool_name"
:
"Bash"
,
"tool_input"
: {
"command"
:
"rm -rf /tmp/build"
,
"description"
:
"Clean build directory"
},
"tool_use_id"
:
"toolu_01ABC123..."
,
"reason"
:
"Auto mode denied: command targets a path outside the project"
}
Field
Description
reason
The classifier’s explanation for why the tool call was denied
​
PermissionDenied decision control
PermissionDenied hooks can tell the model it may retry the denied tool call. Return a JSON object with
hookSpecificOutput.retry
set to
true
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"PermissionDenied"
,
"retry"
:
true
}
}
When
retry
is
true
, Claude Code adds a message to the conversation telling the model it may retry the tool call. The denial itself is not reversed. If your hook does not return JSON, or returns
retry: false
, the denial stands and the model receives the original rejection message.
​
Notification
Runs when Claude Code sends notifications. Matches on notification type:
permission_prompt
,
idle_prompt
,
auth_success
,
elicitation_dialog
,
elicitation_complete
,
elicitation_response
. Omit the matcher to run hooks for all notification types.
Use separate matchers to run different handlers depending on the notification type. This configuration triggers a permission-specific alert script when Claude needs permission approval and a different notification when Claude has been idle:
{
"hooks"
: {
"Notification"
: [
{
"matcher"
:
"permission_prompt"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/permission-alert.sh"
}
]
},
{
"matcher"
:
"idle_prompt"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/idle-notification.sh"
}
]
}
]
}
}
​
Notification input
In addition to the
common input fields
, Notification hooks receive
message
with the notification text, an optional
title
, and
notification_type
indicating which type fired.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"Notification"
,
"message"
:
"Claude needs your permission to use Bash"
,
"title"
:
"Permission needed"
,
"notification_type"
:
"permission_prompt"
}
Notification hooks cannot block or modify notifications. They are intended for side effects such as forwarding the notification to an external service. The
common JSON output fields
such as
systemMessage
apply.
​
SubagentStart
Runs when a Claude Code subagent is spawned via the Agent tool. Supports matchers to filter by agent type name. For built-in agents, this is the agent name like
general-purpose
,
Explore
, or
Plan
. For
custom subagents
, this is the
name
field from the agent’s frontmatter, not the filename.
​
SubagentStart input
In addition to the
common input fields
, SubagentStart hooks receive
agent_id
with the unique identifier for the subagent and
agent_type
with the agent name (built-in agents like
"general-purpose"
,
"Explore"
,
"Plan"
, or custom agent names).
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SubagentStart"
,
"agent_id"
:
"agent-abc123"
,
"agent_type"
:
"Explore"
}
SubagentStart hooks cannot block subagent creation, but they can inject context into the subagent. In addition to the
JSON output fields
available to all hooks, you can return:
Field
Description
additionalContext
String added to the subagent’s context at the start of its conversation, before its first prompt. See
Add context for Claude
{
"hookSpecificOutput"
: {
"hookEventName"
:
"SubagentStart"
,
"additionalContext"
:
"Follow security guidelines for this task"
}
}
​
SubagentStop
Runs when a Claude Code subagent has finished responding. Matches on agent type, same values as SubagentStart.
​
SubagentStop input
In addition to the
common input fields
, SubagentStop hooks receive
stop_hook_active
,
agent_id
,
agent_type
,
agent_transcript_path
, and
last_assistant_message
. The
agent_type
field is the value used for matcher filtering. The
transcript_path
is the main session’s transcript, while
agent_transcript_path
is the subagent’s own transcript stored in a nested
subagents/
folder. The
last_assistant_message
field contains the text content of the subagent’s final response, so hooks can access it without parsing the transcript file.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"~/.claude/projects/.../abc123.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"SubagentStop"
,
"stop_hook_active"
:
false
,
"agent_id"
:
"def456"
,
"agent_type"
:
"Explore"
,
"agent_transcript_path"
:
"~/.claude/projects/.../abc123/subagents/agent-def456.jsonl"
,
"last_assistant_message"
:
"Analysis complete. Found 3 potential issues..."
}
SubagentStop hooks use the same decision control format as
Stop hooks
. They do not support
additionalContext
. Returning
decision: "block"
with a
reason
keeps the subagent running and delivers
reason
to the subagent as its next instruction. To inject context into the parent session after a subagent returns, use a
PostToolUse
hook on the
Agent
tool instead.
​
TaskCreated
Runs when a task is being created via the
TaskCreate
tool. Use this to enforce naming conventions, require task descriptions, or prevent certain tasks from being created.
When a
TaskCreated
hook exits with code 2, the task is not created and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TaskCreated hooks do not support matchers and fire on every occurrence.
​
TaskCreated input
In addition to the
common input fields
, TaskCreated hooks receive
task_id
,
task_subject
, and optionally
task_description
,
teammate_name
, and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TaskCreated"
,
"task_id"
:
"task-001"
,
"task_subject"
:
"Implement user authentication"
,
"task_description"
:
"Add login and signup endpoints"
,
"teammate_name"
:
"implementer"
,
"team_name"
:
"my-project"
}
Field
Description
task_id
Identifier of the task being created
task_subject
Title of the task
task_description
Detailed description of the task. May be absent
teammate_name
Name of the teammate creating the task. May be absent
team_name
Name of the team. May be absent
​
TaskCreated decision control
TaskCreated hooks support two ways to control task creation:
Exit code 2
: the task is not created and the stderr message is fed back to the model as feedback.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example blocks tasks whose subjects don’t follow the required format:
#!/bin/bash
INPUT
=
$(
cat
)
TASK_SUBJECT
=
$(
echo
"
$INPUT
"
|
jq
-r
'.task_subject'
)
if
[[
!
"
$TASK_SUBJECT
"
=~
^
\[
TICKET-[0-9]+
\]
]];
then
echo
"Task subject must start with a ticket number, e.g. '[TICKET-123] Add feature'"
>&2
exit
2
fi
exit
0
​
TaskCompleted
Runs when a task is being marked as completed. This fires in two situations: when any agent explicitly marks a task as completed through the TaskUpdate tool, or when an
agent team
teammate finishes its turn with in-progress tasks. Use this to enforce completion criteria like passing tests or lint checks before a task can close.
When a
TaskCompleted
hook exits with code 2, the task is not marked as completed and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TaskCompleted hooks do not support matchers and fire on every occurrence.
​
TaskCompleted input
In addition to the
common input fields
, TaskCompleted hooks receive
task_id
,
task_subject
, and optionally
task_description
,
teammate_name
, and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TaskCompleted"
,
"task_id"
:
"task-001"
,
"task_subject"
:
"Implement user authentication"
,
"task_description"
:
"Add login and signup endpoints"
,
"teammate_name"
:
"implementer"
,
"team_name"
:
"my-project"
}
Field
Description
task_id
Identifier of the task being completed
task_subject
Title of the task
task_description
Detailed description of the task. May be absent
teammate_name
Name of the teammate completing the task. May be absent
team_name
Name of the team. May be absent
​
TaskCompleted decision control
TaskCompleted hooks support two ways to control task completion:
Exit code 2
: the task is not marked as completed and the stderr message is fed back to the model as feedback.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example runs tests and blocks task completion if they fail:
#!/bin/bash
INPUT
=
$(
cat
)
TASK_SUBJECT
=
$(
echo
"
$INPUT
"
|
jq
-r
'.task_subject'
)
# Run the test suite
if
!
npm
test
2>&1
;
then
echo
"Tests not passing. Fix failing tests before completing:
$TASK_SUBJECT
"
>&2
exit
2
fi
exit
0
​
Stop
Runs when the main Claude Code agent has finished responding. Does not run if
the stoppage occurred due to a user interrupt. API errors fire
StopFailure
instead.
The
/goal
command is a built-in shortcut for a session-scoped prompt-based Stop hook. Use it when you want Claude to keep working until a condition holds without writing hook configuration.
​
Stop input
In addition to the
common input fields
, Stop hooks receive
stop_hook_active
and
last_assistant_message
. The
stop_hook_active
field is
true
when Claude Code is already continuing as a result of a stop hook. Check this value or process the transcript to prevent Claude Code from running indefinitely. The
last_assistant_message
field contains the text content of Claude’s final response, so hooks can access it without parsing the transcript file.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Stop"
,
"stop_hook_active"
:
true
,
"last_assistant_message"
:
"I've completed the refactoring. Here's a summary..."
}
​
Stop decision control
Stop
and
SubagentStop
hooks can control whether Claude continues. In addition to the
JSON output fields
available to all hooks, your hook script can return these event-specific fields:
Field
Description
decision
"block"
prevents Claude from stopping. Omit to allow Claude to stop
reason
Required when
decision
is
"block"
. Tells Claude why it should continue
{
"decision"
:
"block"
,
"reason"
:
"Must be provided when Claude is blocked from stopping"
}
​
StopFailure
Runs instead of
Stop
when the turn ends due to an API error. Output and exit code are ignored. Use this to log failures, send alerts, or take recovery actions when Claude cannot complete a response due to rate limits, authentication problems, or other API errors.
​
StopFailure input
In addition to the
common input fields
, StopFailure hooks receive
error
, optional
error_details
, and optional
last_assistant_message
. The
error
field identifies the error type and is used for matcher filtering.
Field
Description
error
Error type:
rate_limit
,
authentication_failed
,
oauth_org_not_allowed
,
billing_error
,
invalid_request
,
server_error
,
max_output_tokens
, or
unknown
error_details
Additional details about the error, when available
last_assistant_message
The rendered error text shown in the conversation. Unlike
Stop
and
SubagentStop
, where this field holds Claude’s conversational output, for
StopFailure
it contains the API error string itself, such as
"API Error: Rate limit reached"
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"StopFailure"
,
"error"
:
"rate_limit"
,
"error_details"
:
"429 Too Many Requests"
,
"last_assistant_message"
:
"API Error: Rate limit reached"
}
StopFailure hooks have no decision control. They run for notification and logging purposes only.
​
TeammateIdle
Runs when an
agent team
teammate is about to go idle after finishing its turn. Use this to enforce quality gates before a teammate stops working, such as requiring passing lint checks or verifying that output files exist.
When a
TeammateIdle
hook exits with code 2, the teammate receives the stderr message as feedback and continues working instead of going idle. To stop the teammate entirely instead of re-running it, return JSON with
{"continue": false, "stopReason": "..."}
. TeammateIdle hooks do not support matchers and fire on every occurrence.
​
TeammateIdle input
In addition to the
common input fields
, TeammateIdle hooks receive
teammate_name
and
team_name
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"TeammateIdle"
,
"teammate_name"
:
"researcher"
,
"team_name"
:
"my-project"
}
Field
Description
teammate_name
Name of the teammate that is about to go idle
team_name
Name of the team
​
TeammateIdle decision control
TeammateIdle hooks support two ways to control teammate behavior:
Exit code 2
: the teammate receives the stderr message as feedback and continues working instead of going idle.
JSON
{"continue": false, "stopReason": "..."}
: stops the teammate entirely, matching
Stop
hook behavior. The
stopReason
is shown to the user.
This example checks that a build artifact exists before allowing a teammate to go idle:
#!/bin/bash
if
[
!
-f
"./dist/output.js"
];
then
echo
"Build artifact missing. Run the build before stopping."
>&2
exit
2
fi
exit
0
​
ConfigChange
Runs when a configuration file changes during a session. Use this to audit settings changes, enforce security policies, or block unauthorized modifications to configuration files.
ConfigChange hooks fire for changes to settings files, managed policy settings, and skill files. The
source
field in the input tells you which type of configuration changed, and the optional
file_path
field provides the path to the changed file.
The matcher filters on the configuration source:
Matcher
When it fires
user_settings
~/.claude/settings.json
changes
project_settings
.claude/settings.json
changes
local_settings
.claude/settings.local.json
changes
policy_settings
Managed policy settings change
skills
A skill file in
.claude/skills/
changes
This example logs all configuration changes for security auditing:
{
"hooks"
: {
"ConfigChange"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-config-change.sh"
,
"args"
: []
}
]
}
]
}
}
​
ConfigChange input
In addition to the
common input fields
, ConfigChange hooks receive
source
and optionally
file_path
. The
source
field indicates which configuration type changed, and
file_path
provides the path to the specific file that was modified.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"ConfigChange"
,
"source"
:
"project_settings"
,
"file_path"
:
"/Users/.../my-project/.claude/settings.json"
}
​
ConfigChange decision control
ConfigChange hooks can block configuration changes from taking effect. Use exit code 2 or a JSON
decision
to prevent the change. When blocked, the new settings are not applied to the running session.
Field
Description
decision
"block"
prevents the configuration change from being applied. Omit to allow the change
reason
Explanation shown to the user when
decision
is
"block"
{
"decision"
:
"block"
,
"reason"
:
"Configuration changes to project settings require admin approval"
}
policy_settings
changes cannot be blocked. Hooks still fire for
policy_settings
sources, so you can use them for audit logging, but any blocking decision is ignored. This ensures enterprise-managed settings always take effect.
​
CwdChanged
Runs when the working directory changes during a session, for example when Claude executes a
cd
command. Use this to react to directory changes: reload environment variables, activate project-specific toolchains, or run setup scripts automatically. Pairs with
FileChanged
for tools like
direnv
that manage per-directory environment.
CwdChanged hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
.
CwdChanged does not support matchers and fires on every directory change.
​
CwdChanged input
In addition to the
common input fields
, CwdChanged hooks receive
old_cwd
and
new_cwd
.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project/src"
,
"hook_event_name"
:
"CwdChanged"
,
"old_cwd"
:
"/Users/my-project"
,
"new_cwd"
:
"/Users/my-project/src"
}
​
CwdChanged output
In addition to the
JSON output fields
available to all hooks, CwdChanged hooks can return
watchPaths
to dynamically set which file paths
FileChanged
watches:
Field
Description
watchPaths
Array of absolute paths. Replaces the current dynamic watch list (paths from your
matcher
configuration are always watched). Returning an empty array clears the dynamic list, which is typical when entering a new directory
CwdChanged hooks have no decision control. They cannot block the directory change.
​
FileChanged
Runs when a watched file changes on disk. Useful for reloading environment variables when project configuration files are modified.
The
matcher
for this event serves two roles:
Build the watch list
: the value is split on
|
and each segment is registered as a literal filename in the working directory, so
".envrc|.env"
watches exactly those two files. Regex patterns are not useful here: a value like
^\.env
would watch a file literally named
^\.env
.
Filter which hooks run
: when a watched file changes, the same value filters which hook groups run using the standard
matcher rules
against the changed file’s basename.
FileChanged hooks have access to
CLAUDE_ENV_FILE
. Variables written to that file persist into subsequent Bash commands for the session, just as in
SessionStart hooks
.
​
FileChanged input
In addition to the
common input fields
, FileChanged hooks receive
file_path
and
event
.
Field
Description
file_path
Absolute path to the file that changed
event
What happened:
"change"
(file modified),
"add"
(file created), or
"unlink"
(file deleted)
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../transcript.jsonl"
,
"cwd"
:
"/Users/my-project"
,
"hook_event_name"
:
"FileChanged"
,
"file_path"
:
"/Users/my-project/.envrc"
,
"event"
:
"change"
}
​
FileChanged output
In addition to the
JSON output fields
available to all hooks, FileChanged hooks can return
watchPaths
to dynamically update which file paths are watched:
Field
Description
watchPaths
Array of absolute paths. Replaces the current dynamic watch list (paths from your
matcher
configuration are always watched). Use this when your hook script discovers additional files to watch based on the changed file
FileChanged hooks have no decision control. They cannot block the file change from occurring.
​
WorktreeCreate
When you run
claude --worktree
or a
subagent uses
isolation: "worktree"
, Claude Code creates an isolated working copy using
git worktree
. If you configure a WorktreeCreate hook, it replaces the default git behavior, letting you use a different version control system like SVN, Perforce, or Mercurial.
Because the hook replaces the default behavior entirely,
.worktreeinclude
is not processed. If you need to copy local configuration files like
.env
into the new worktree, do it inside your hook script.
The hook must return the absolute path to the created worktree directory. Claude Code uses this path as the working directory for the isolated session. Command hooks print it on stdout; HTTP hooks return it via
hookSpecificOutput.worktreePath
.
This example creates an SVN working copy and prints the path for Claude Code to use. Replace the repository URL with your own:
{
"hooks"
: {
"WorktreeCreate"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'NAME=$(jq -r .name); DIR=
\"
$HOME/.claude/worktrees/$NAME
\"
; svn checkout https://svn.example.com/repo/trunk
\"
$DIR
\"
>&2 && echo
\"
$DIR
\"
'"
}
]
}
]
}
}
The hook reads the worktree
name
from the JSON input on stdin, checks out a fresh copy into a new directory, and prints the directory path. The
echo
on the last line is what Claude Code reads as the worktree path. Redirect any other output to stderr so it doesn’t interfere with the path.
​
WorktreeCreate input
In addition to the
common input fields
, WorktreeCreate hooks receive the
name
field. This is a slug identifier for the new worktree, either specified by the user or auto-generated (for example,
bold-oak-a3f2
).
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"WorktreeCreate"
,
"name"
:
"feature-auth"
}
​
WorktreeCreate output
WorktreeCreate hooks do not use the standard allow/block decision model. Instead, the hook’s success or failure determines the outcome. The hook must return the absolute path to the created worktree directory:
Command hooks
(
type: "command"
): print the path on stdout.
HTTP hooks
(
type: "http"
): return
{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }
in the response body.
If the hook fails or produces no path, worktree creation fails with an error.
​
WorktreeRemove
The cleanup counterpart to
WorktreeCreate
. This hook fires when a worktree is being removed, either when you exit a
--worktree
session and choose to remove it, or when a subagent with
isolation: "worktree"
finishes. For git-based worktrees, Claude handles cleanup automatically with
git worktree remove
. If you configured a WorktreeCreate hook for a non-git version control system, pair it with a WorktreeRemove hook to handle cleanup. Without one, the worktree directory is left on disk.
Claude Code passes the path returned by WorktreeCreate as
worktree_path
in the hook input. This example reads that path and removes the directory:
{
"hooks"
: {
"WorktreeRemove"
: [
{
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"bash -c 'jq -r .worktree_path | xargs rm -rf'"
}
]
}
]
}
}
​
WorktreeRemove input
In addition to the
common input fields
, WorktreeRemove hooks receive the
worktree_path
field, which is the absolute path to the worktree being removed.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"WorktreeRemove"
,
"worktree_path"
:
"/Users/.../my-project/.claude/worktrees/feature-auth"
}
WorktreeRemove hooks have no decision control. They cannot block worktree removal but can perform cleanup tasks like removing version control state or archiving changes. Hook failures are logged in debug mode only.
​
PreCompact
Runs before Claude Code is about to run a compact operation.
The matcher value indicates whether compaction was triggered manually or automatically:
Matcher
When it fires
manual
/compact
auto
Auto-compact when the context window is full
Exit with code 2 to block compaction. For a manual
/compact
, the stderr message is shown to the user. You can also block by returning JSON with
"decision": "block"
.
Blocking automatic compaction has different effects depending on when it fires. If compaction was triggered proactively before the context limit, Claude Code skips it and the conversation continues uncompacted. If compaction was triggered to recover from a context-limit error already returned by the API, the underlying error surfaces and the current request fails.
​
PreCompact input
In addition to the
common input fields
, PreCompact hooks receive
trigger
and
custom_instructions
. For
manual
,
custom_instructions
contains what the user passes into
/compact
. For
auto
,
custom_instructions
is empty.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"PreCompact"
,
"trigger"
:
"manual"
,
"custom_instructions"
:
""
}
​
PostCompact
Runs after Claude Code completes a compact operation. Use this event to react to the new compacted state, for example to log the generated summary or update external state.
The same matcher values apply as for
PreCompact
:
Matcher
When it fires
manual
After
/compact
auto
After auto-compact when the context window is full
​
PostCompact input
In addition to the
common input fields
, PostCompact hooks receive
trigger
and
compact_summary
. The
compact_summary
field contains the conversation summary generated by the compact operation.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"PostCompact"
,
"trigger"
:
"manual"
,
"compact_summary"
:
"Summary of the compacted conversation..."
}
PostCompact hooks have no decision control. They cannot affect the compaction result but can perform follow-up tasks.
​
SessionEnd
Runs when a Claude Code session ends. Useful for cleanup tasks, logging session
statistics, or saving session state. Supports matchers to filter by exit reason.
The
reason
field in the hook input indicates why the session ended:
Reason
Description
clear
Session cleared with
/clear
command
resume
Session switched via interactive
/resume
logout
User logged out
prompt_input_exit
User exited while prompt input was visible
bypass_permissions_disabled
Bypass permissions mode was disabled
other
Other exit reasons
​
SessionEnd input
In addition to the
common input fields
, SessionEnd hooks receive a
reason
field indicating why the session ended. See the
reason table
above for all values.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"hook_event_name"
:
"SessionEnd"
,
"reason"
:
"other"
}
SessionEnd hooks have no decision control. They cannot block session termination but can perform cleanup tasks.
SessionEnd hooks have a default timeout of 1.5 seconds. This applies to session exit,
/clear
, and switching sessions via interactive
/resume
. If a hook needs more time, set a per-hook
timeout
in the hook configuration. The overall budget is automatically raised to the highest per-hook timeout configured in settings files, up to 60 seconds. Timeouts set on plugin-provided hooks do not raise the budget. To override the budget explicitly, set the
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
environment variable in milliseconds.
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
=
5000
claude
​
Elicitation
Runs when an MCP server requests user input mid-task. By default, Claude Code shows an interactive dialog for the user to respond. Hooks can intercept this request and respond programmatically, skipping the dialog entirely.
The matcher field matches against the MCP server name.
​
Elicitation input
In addition to the
common input fields
, Elicitation hooks receive
mcp_server_name
,
message
, and optional
mode
,
url
,
elicitation_id
, and
requested_schema
fields.
For form-mode elicitation (the most common case):
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Elicitation"
,
"mcp_server_name"
:
"my-mcp-server"
,
"message"
:
"Please provide your credentials"
,
"mode"
:
"form"
,
"requested_schema"
: {
"type"
:
"object"
,
"properties"
: {
"username"
: {
"type"
:
"string"
,
"title"
:
"Username"
}
}
}
}
For URL-mode elicitation (browser-based authentication):
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"Elicitation"
,
"mcp_server_name"
:
"my-mcp-server"
,
"message"
:
"Please authenticate"
,
"mode"
:
"url"
,
"url"
:
"https://auth.example.com/login"
}
​
Elicitation output
To respond programmatically without showing the dialog, return a JSON object with
hookSpecificOutput
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"Elicitation"
,
"action"
:
"accept"
,
"content"
: {
"username"
:
"alice"
}
}
}
Field
Values
Description
action
accept
,
decline
,
cancel
Whether to accept, decline, or cancel the request
content
object
Form field values to submit. Only used when
action
is
accept
Exit code 2 denies the elicitation and shows stderr to the user.
​
ElicitationResult
Runs after a user responds to an MCP elicitation. Hooks can observe, modify, or block the response before it is sent back to the MCP server.
The matcher field matches against the MCP server name.
​
ElicitationResult input
In addition to the
common input fields
, ElicitationResult hooks receive
mcp_server_name
,
action
, and optional
mode
,
elicitation_id
, and
content
fields.
{
"session_id"
:
"abc123"
,
"transcript_path"
:
"/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl"
,
"cwd"
:
"/Users/..."
,
"permission_mode"
:
"default"
,
"hook_event_name"
:
"ElicitationResult"
,
"mcp_server_name"
:
"my-mcp-server"
,
"action"
:
"accept"
,
"content"
: {
"username"
:
"alice"
},
"mode"
:
"form"
,
"elicitation_id"
:
"elicit-123"
}
​
ElicitationResult output
To override the user’s response, return a JSON object with
hookSpecificOutput
:
{
"hookSpecificOutput"
: {
"hookEventName"
:
"ElicitationResult"
,
"action"
:
"decline"
,
"content"
: {}
}
}
Field
Values
Description
action
accept
,
decline
,
cancel
Overrides the user’s action
content
object
Overrides form field values. Only meaningful when
action
is
accept
Exit code 2 blocks the response, changing the effective action to
decline
.
​
Prompt-based hooks
In addition to command, HTTP, and MCP tool hooks, Claude Code supports prompt-based hooks (
type: "prompt"
) that use an LLM to evaluate whether to allow or block an action, and agent hooks (
type: "agent"
) that spawn an agentic verifier with tool access. Not all events support every hook type.
Events that support all five hook types (
command
,
http
,
mcp_tool
,
prompt
, and
agent
):
PermissionRequest
PostToolBatch
PostToolUse
PostToolUseFailure
PreToolUse
Stop
SubagentStop
TaskCompleted
TaskCreated
UserPromptExpansion
UserPromptSubmit
Events that support
command
,
http
, and
mcp_tool
hooks but not
prompt
or
agent
:
ConfigChange
CwdChanged
Elicitation
ElicitationResult
FileChanged
InstructionsLoaded
Notification
PermissionDenied
PostCompact
PreCompact
SessionEnd
StopFailure
SubagentStart
TeammateIdle
WorktreeCreate
WorktreeRemove
SessionStart
and
Setup
support
command
and
mcp_tool
hooks. They do not support
http
,
prompt
, or
agent
hooks.
​
How prompt-based hooks work
Instead of executing a Bash command, prompt-based hooks:
Send the hook input and your prompt to a Claude model, Haiku by default
The LLM responds with structured JSON containing a decision
Claude Code processes the decision automatically
​
Prompt hook configuration
Set
type
to
"prompt"
and provide a
prompt
string instead of a
command
. Use the
$ARGUMENTS
placeholder to inject the hook’s JSON input data into your prompt text. Claude Code sends the combined prompt and input to a fast Claude model, which returns a JSON decision.
This
Stop
hook asks the LLM to evaluate whether all tasks are complete before allowing Claude to finish:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
}
]
}
]
}
}
Field
Required
Description
type
yes
Must be
"prompt"
prompt
yes
The prompt text to send to the LLM. Use
$ARGUMENTS
as a placeholder for the hook input JSON. If
$ARGUMENTS
is not present, input JSON is appended to the prompt
model
no
Model to use for evaluation. Defaults to a fast model
timeout
no
Timeout in seconds. Default: 30
continueOnBlock
no
When the prompt returns
ok: false
, feed the reason back to Claude and continue the turn instead of stopping. Default:
false
. Implemented as
continue: true
on the resulting
decision: "block"
. See
Response schema
for per-event behavior
​
Response schema
The LLM must respond with JSON containing:
{
"ok"
:
true
|
false
,
"reason"
:
"Explanation for the decision"
}
Field
Description
ok
true
to allow.
false
produces a
decision: "block"
. See the per-event behavior below
reason
Required when
ok
is
false
. Used as the block reason
What happens on
ok: false
depends on the event:
Stop
and
SubagentStop
: the reason is fed back to Claude as its next instruction and the turn continues
PreToolUse
: the tool call is denied and the reason is returned to Claude as the tool error, equivalent to a command hook’s
permissionDecision: "deny"
PostToolUse
: by default the turn ends and the reason appears in the chat as a warning line. Set
continueOnBlock: true
to feed the reason back to Claude and continue the turn instead
PostToolBatch
,
UserPromptSubmit
, and
UserPromptExpansion
: the turn ends and the reason appears as a warning line. These events end the turn on
decision: "block"
regardless of
continue
PostToolUseFailure
,
TaskCreated
, and
TaskCompleted
: the reason is returned to Claude as a tool error, similar to
PreToolUse
PermissionRequest
:
ok: false
has no effect. To deny an approval from a hook, use a
command hook
returning
hookSpecificOutput.decision.behavior: "deny"
If you need finer control on any event, use a
command hook
with the per-event fields described in
Decision control
.
​
Example: Multi-criteria Stop hook
This
Stop
hook uses a detailed prompt to check three conditions before allowing Claude to stop. If
"ok"
is
false
, Claude continues working with the provided reason as its next instruction.
SubagentStop
hooks use the same format to evaluate whether a
subagent
should stop:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"prompt"
,
"prompt"
:
"You are evaluating whether Claude should stop working. Context: $ARGUMENTS
\n\n
Analyze the conversation and determine if:
\n
1. All user-requested tasks are complete
\n
2. Any errors need to be addressed
\n
3. Follow-up work is needed
\n\n
Respond with JSON: {
\"
ok
\"
: true} to allow stopping, or {
\"
ok
\"
: false,
\"
reason
\"
:
\"
your explanation
\"
} to continue working."
,
"timeout"
:
30
}
]
}
]
}
}
​
Agent-based hooks
Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer
command hooks
.
Agent-based hooks (
type: "agent"
) are like prompt-based hooks but with multi-turn tool access. Instead of a single LLM call, an agent hook spawns a subagent that can read files, search code, and inspect the codebase to verify conditions. Agent hooks support the same events as prompt-based hooks.
​
How agent hooks work
When an agent hook fires:
Claude Code spawns a subagent with your prompt and the hook’s JSON input
The subagent can use tools like Read, Grep, and Glob to investigate
After up to 50 turns, the subagent returns a structured
{ "ok": true/false }
decision
Claude Code processes the decision the same way as a prompt hook
Agent hooks are useful when verification requires inspecting actual files or test output, not just evaluating the hook input data alone.
​
Agent hook configuration
Set
type
to
"agent"
and provide a
prompt
string. The configuration fields are the same as
prompt hooks
, with a longer default timeout:
Field
Required
Description
type
yes
Must be
"agent"
prompt
yes
Prompt describing what to verify. Use
$ARGUMENTS
as a placeholder for the hook input JSON
model
no
Model to use. Defaults to a fast model
timeout
no
Timeout in seconds. Default: 60
The response schema is the same as prompt hooks:
{ "ok": true }
to allow or
{ "ok": false, "reason": "..." }
to block.
This
Stop
hook verifies that all unit tests pass before allowing Claude to finish:
{
"hooks"
: {
"Stop"
: [
{
"hooks"
: [
{
"type"
:
"agent"
,
"prompt"
:
"Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS"
,
"timeout"
:
120
}
]
}
]
}
}
​
Run hooks in the background
By default, hooks block Claude’s execution until they complete. For long-running tasks like deployments, test suites, or external API calls, set
"async": true
to run the hook in the background while Claude continues working. Async hooks cannot block or control Claude’s behavior: response fields like
decision
,
permissionDecision
, and
continue
have no effect, because the action they would have controlled has already completed.
​
Configure an async hook
Add
"async": true
to a command hook’s configuration to run it in the background without blocking Claude. This field is only available on
type: "command"
hooks.
This hook runs a test script after every
Write
tool call. Claude continues working immediately while
run-tests.sh
executes for up to 120 seconds. When the script finishes, its output is delivered on the next conversation turn:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"/path/to/run-tests.sh"
,
"async"
:
true
,
"timeout"
:
120
}
]
}
]
}
}
The
timeout
field sets the maximum time in seconds for the background process. If not specified, async hooks use the same 10-minute default as sync hooks.
​
How async hooks execute
When an async hook fires, Claude Code starts the hook process and immediately continues without waiting for it to finish. The hook receives the same JSON input via stdin as a synchronous hook.
After the background process exits, if the hook produced a JSON response with an
additionalContext
field, that content is delivered to Claude as context on the next conversation turn. A
systemMessage
field is shown to you, not to Claude.
Async hook completion notifications are suppressed by default. To see them, enable verbose mode with
Ctrl+O
or start Claude Code with
--verbose
.
​
Example: run tests after file changes
This hook starts a test suite in the background whenever Claude writes a file, then reports the results back to Claude when the tests finish. Save this script to
.claude/hooks/run-tests-async.sh
in your project and make it executable with
chmod +x
:
#!/bin/bash
# run-tests-async.sh
# Read hook input from stdin
INPUT
=
$(
cat
)
FILE_PATH
=
$(
echo
"
$INPUT
"
|
jq
-r
'.tool_input.file_path // empty'
)
# Only run tests for source files
if
[[
"
$FILE_PATH
"
!=
*
.ts
&&
"
$FILE_PATH
"
!=
*
.js ]];
then
exit
0
fi
# Run tests and report results to Claude via additionalContext
RESULT
=
$(
npm
test
2>&1
)
EXIT_CODE
=
$?
if
[
$EXIT_CODE
-eq
0
];
then
MSG
=
"Tests passed after editing
$FILE_PATH
"
else
MSG
=
"Tests failed after editing
$FILE_PATH
:
$RESULT
"
fi
jq
-nc
--arg
msg
"
$MSG
"
'{hookSpecificOutput: {hookEventName: "PostToolUse", additionalContext: $msg}}'
Then add this configuration to
.claude/settings.json
in your project root. The
async: true
flag lets Claude keep working while tests run:
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh"
,
"args"
: [],
"async"
:
true
,
"timeout"
:
300
}
]
}
]
}
}
​
Limitations
Async hooks have several constraints compared to synchronous hooks:
Only
type: "command"
hooks support
async
. Prompt-based hooks cannot run asynchronously.
Async hooks cannot block tool calls or return decisions. By the time the hook completes, the triggering action has already proceeded.
Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction. Exception: an
asyncRewake
hook that exits with code 2 wakes Claude immediately even when the session is idle.
Each execution creates a separate background process. There is no deduplication across multiple firings of the same async hook.
​
Security considerations
​
Disclaimer
Command hooks run with your system user’s full permissions.
Command hooks execute shell commands with your full user permissions. They can modify, delete, or access any files your user account can access. Review and test all hook commands before adding them to your configuration.
​
Security best practices
Keep these practices in mind when writing hooks:
Validate and sanitize inputs
: never trust input data blindly
Always quote shell variables
: use
"$VAR"
not
$VAR
Block path traversal
: check for
..
in file paths
Use absolute paths
: specify full paths for scripts. In exec form, use
${CLAUDE_PROJECT_DIR}
and the path needs no quoting. In shell form, wrap it in double quotes
Skip sensitive files
: avoid
.env
,
.git/
, keys, etc.
​
Windows PowerShell tool
On Windows, you can run individual hooks in PowerShell by setting
"shell": "powershell"
on a command hook. Hooks spawn PowerShell directly, so this works regardless of whether
CLAUDE_CODE_USE_POWERSHELL_TOOL
is set. Claude Code auto-detects
pwsh.exe
(PowerShell 7+) with a fallback to
powershell.exe
(5.1).
{
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write"
,
"hooks"
: [
{
"type"
:
"command"
,
"shell"
:
"powershell"
,
"command"
:
"Write-Host 'File written'"
}
]
}
]
}
}
​
Debug hooks
Hook execution details, including which hooks matched, their exit codes, and full stdout and stderr, are written to the debug log file. Start Claude Code with
claude --debug-file <path>
to write the log to a known location, or run
claude --debug
and read the log at
~/.claude/debug/<session-id>.txt
. The
--debug
flag does not print to the terminal.
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 600000ms
[DEBUG] Hook command completed with status 0: <Your stdout>
For more granular hook matching details, set
CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose
to see additional log lines such as hook matcher counts and query matching.
For troubleshooting common issues like hooks not firing, infinite Stop hook loops, or configuration errors, see
Limitations and troubleshooting
in the guide. For a broader diagnostic walkthrough covering
/context
,
/doctor
, and settings precedence, see
Debug your config
.
Was this page helpful?
Yes
No
Checkpointing
Plugins reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/hooks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Set up Claude Code for your organization</title>
  <link>https://code.claude.com/docs/en/admin-setup</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/admin-setup</guid>
  <pubDate>Tue, 21 May 2024 00:00:00 +0000</pubDate>
  <category>Setup</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Set up Claude Code for your organization
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Set up Claude Code for your organization
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code enforces organization policy through managed settings that take precedence over local developer configuration. You deliver those settings from the Claude admin console, your mobile device management (MDM) system, or a file on disk. The settings control which tools, commands, servers, and network destinations Claude can reach.
This page walks through the deployment decisions in order. Each row links to the section below and to the reference page for that area.
SSO, SCIM provisioning, and seat assignment are configured at the Claude account level. See the
Claude Enterprise Administrator Guide
and
seat assignment
for those steps.
Decision
What you’re choosing
Reference
Choose your API provider
Where Claude Code authenticates and how it’s billed
Authentication
,
Bedrock
,
Vertex AI
,
Foundry
Decide how settings reach devices
How managed policy reaches developer machines
Server-managed settings
,
Settings files
Decide what to enforce
Which tools, commands, and integrations are allowed
Permissions
,
Sandboxing
Set up usage visibility
How you track spend and adoption
Analytics
,
Monitoring
,
Costs
Review data handling
Data retention and compliance posture
Data usage
,
Security
​
Choose your API provider
Claude Code connects to Claude through one of several API providers. Your choice affects billing, authentication, which compliance posture you inherit, and which Claude Code features your developers can use.
Provider
Choose this when
Claude for Teams / Enterprise
You want Claude Code and claude.ai under one per-seat subscription with no infrastructure to run. This is the default recommendation.
Claude Console
You’re API-first or want pay-as-you-go billing
Amazon Bedrock
You want to inherit existing AWS compliance controls and billing
Google Vertex AI
You want to inherit existing GCP compliance controls and billing
Microsoft Foundry
You want to inherit existing Azure compliance controls and billing
Some Claude Code features require a Claude.ai account.
Claude Code on the web
,
Routines
,
Code Review
,
Remote Control
, and the
Chrome extension
are not available through Console API keys or cloud-provider credentials alone. If you deploy through Bedrock, Vertex, or Foundry, plan whether developers also need Claude for Teams or Enterprise seats. Each feature page lists its plan requirements.
For the full provider comparison covering authentication, regions, and feature parity, see the
enterprise deployment overview
. Each provider’s auth setup is in
Authentication
.
Proxy and firewall requirements in
Network configuration
apply regardless of provider. If you want a single endpoint in front of multiple providers or centralized request logging, see
LLM gateway
.
​
Decide how settings reach devices
Managed settings define policy that takes precedence over local developer configuration. Claude Code looks for them in four places and uses the first one it finds on a given device.
Mechanism
Delivery
Priority
Platforms
Server-managed
Claude.ai admin console
Highest
All
plist / registry policy
macOS:
com.anthropic.claudecode
plist
Windows:
HKLM\SOFTWARE\Policies\ClaudeCode
High
macOS, Windows
File-based managed
macOS:
/Library/Application Support/ClaudeCode/managed-settings.json
Linux and WSL:
/etc/claude-code/managed-settings.json
Windows:
C:\Program Files\ClaudeCode\managed-settings.json
Medium
All
Windows user registry
HKCU\SOFTWARE\Policies\ClaudeCode
Lowest
Windows only
Server-managed settings reach devices at authentication time and refresh hourly during active sessions, with no endpoint infrastructure. They require a Claude for Teams or Enterprise plan, so deployments on other providers need one of the file-based or OS-level mechanisms instead.
If your organization mixes providers, configure
server-managed settings
for Claude.ai users plus a
file-based or plist/registry fallback
so other users still receive managed policy.
The plist and HKLM registry locations work with any provider and resist tampering because they require admin privileges to write. The Windows user registry at HKCU is writable without elevation, so treat it as a convenience default rather than an enforcement channel.
By default WSL reads only the Linux file path at
/etc/claude-code
. To extend your Windows registry and
C:\Program Files\ClaudeCode
policy to WSL on the same machine, set
wslInheritsWindowsSettings: true
in either of those admin-only Windows sources.
Whichever mechanism you choose, managed values take precedence over user and project settings. Array settings such as
permissions.allow
and
permissions.deny
merge entries from all sources, so developers can extend managed lists but not remove from them.
See
Server-managed settings
and
Settings files and precedence
.
​
Decide what to enforce
Managed settings can lock down tools, sandbox execution, restrict MCP servers and plugin sources, and control which hooks run. Each row is a control surface with the setting keys that drive it.
Control
What it does
Key settings
Permission rules
Allow, ask, or deny specific tools and commands
permissions.allow
,
permissions.deny
Permission lockdown
Only managed permission rules apply; disable
--dangerously-skip-permissions
allowManagedPermissionRulesOnly
,
permissions.disableBypassPermissionsMode
Sandboxing
OS-level filesystem and network isolation with domain allowlists
sandbox.enabled
,
sandbox.network.allowedDomains
Managed policy CLAUDE.md
Org-wide instructions loaded in every session, cannot be excluded
File at the managed policy path
MCP server control
Restrict which MCP servers users can add or connect to
allowedMcpServers
,
deniedMcpServers
,
allowManagedMcpServersOnly
Plugin marketplace control
Restrict which marketplace sources users can add and install from
strictKnownMarketplaces
,
blockedMarketplaces
Hook restrictions
Only managed hooks load; restrict HTTP hook URLs
allowManagedHooksOnly
,
allowedHttpHookUrls
Disable agent view
Turn off
claude agents
,
--bg
,
/background
, and the on-demand supervisor
disableAgentView
Version floor
Prevent auto-update from installing below an org-wide minimum
minimumVersion
Permission rules and sandboxing cover different layers. Denying WebFetch blocks Claude’s fetch tool, but if Bash is allowed,
curl
and
wget
can still reach any URL. Sandboxing closes that gap with a network domain allowlist enforced at the OS level.
For the threat model these controls defend against, see
Security
.
​
Set up usage visibility
Choose monitoring based on what you need to report on.
Capability
What you get
Availability
Where to start
Usage monitoring
OpenTelemetry export of sessions, tools, and tokens
All providers
Monitoring usage
Analytics dashboard
Per-user metrics, contribution tracking, leaderboard
Anthropic only
Analytics
Cost tracking
Spend limits, rate limits, and usage attribution
Anthropic only
Costs
Cloud providers expose spend through AWS Cost Explorer, GCP Billing, or Azure Cost Management. Claude for Teams and Enterprise plans include a usage dashboard at
claude.ai/analytics/claude-code
.
​
Review data handling
On Team, Enterprise, Claude API, and cloud provider plans, Anthropic does not train models on your code or prompts. Your API provider determines retention and compliance posture.
Topic
What to know
Where to start
Data usage policy
What Anthropic collects, how long it’s retained, what’s never used for training
Data usage
Zero Data Retention (ZDR)
Nothing stored after the request completes. Available on Claude for Enterprise
Zero data retention
Security architecture
Network model, encryption, authentication, audit trail
Security
If you need request-level audit logging or to route traffic by data sensitivity, place an
LLM gateway
between developers and your provider. For regulatory requirements and certifications, see
Legal and compliance
.
​
Verify and onboard
After configuring managed settings, have a developer run
/status
inside Claude Code. The output includes a line beginning with
Enterprise managed settings
followed by the source in parentheses, one of
(remote)
,
(plist)
,
(HKLM)
,
(HKCU)
, or
(file)
. See
Verify active settings
.
Share these resources to help developers get started:
Quickstart
: first-session walkthrough from install to working with a project
Common workflows
: patterns for everyday tasks like code review, refactoring, and debugging
Claude 101
and
Claude Code in Action
: self-paced Anthropic Academy courses
For login issues, point developers to
authentication troubleshooting
. The most common fixes are:
Run
/logout
then
/login
to switch accounts
Run
claude update
if the enterprise auth option is missing
Restart the terminal after updating
If a developer sees “You haven’t been added to your organization yet,” their seat doesn’t include Claude Code access and needs to be updated in the admin console.
​
Next steps
With provider and delivery mechanism chosen, move on to detailed configuration:
Server-managed settings
: deliver managed policy from the Claude admin console
Settings reference
: every setting key, file location, and precedence rule
Amazon Bedrock
,
Google Vertex AI
,
Microsoft Foundry
: provider-specific deployment
Claude Enterprise Administrator Guide
: SSO, SCIM, seat management, and rollout playbook
Was this page helpful?
Yes
No
Advanced setup
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/admin-setup" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Set up Claude Code for your organization
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Set up Claude Code for your organization
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code enforces organization policy through managed settings that take precedence over local developer configuration. You deliver those settings from the Claude admin console, your mobile device management (MDM) system, or a file on disk. The settings control which tools, commands, servers, and network destinations Claude can reach.
This page walks through the deployment decisions in order. Each row links to the section below and to the reference page for that area.
SSO, SCIM provisioning, and seat assignment are configured at the Claude account level. See the
Claude Enterprise Administrator Guide
and
seat assignment
for those steps.
Decision
What you’re choosing
Reference
Choose your API provider
Where Claude Code authenticates and how it’s billed
Authentication
,
Bedrock
,
Vertex AI
,
Foundry
Decide how settings reach devices
How managed policy reaches developer machines
Server-managed settings
,
Settings files
Decide what to enforce
Which tools, commands, and integrations are allowed
Permissions
,
Sandboxing
Set up usage visibility
How you track spend and adoption
Analytics
,
Monitoring
,
Costs
Review data handling
Data retention and compliance posture
Data usage
,
Security
​
Choose your API provider
Claude Code connects to Claude through one of several API providers. Your choice affects billing, authentication, which compliance posture you inherit, and which Claude Code features your developers can use.
Provider
Choose this when
Claude for Teams / Enterprise
You want Claude Code and claude.ai under one per-seat subscription with no infrastructure to run. This is the default recommendation.
Claude Console
You’re API-first or want pay-as-you-go billing
Amazon Bedrock
You want to inherit existing AWS compliance controls and billing
Google Vertex AI
You want to inherit existing GCP compliance controls and billing
Microsoft Foundry
You want to inherit existing Azure compliance controls and billing
Some Claude Code features require a Claude.ai account.
Claude Code on the web
,
Routines
,
Code Review
,
Remote Control
, and the
Chrome extension
are not available through Console API keys or cloud-provider credentials alone. If you deploy through Bedrock, Vertex, or Foundry, plan whether developers also need Claude for Teams or Enterprise seats. Each feature page lists its plan requirements.
For the full provider comparison covering authentication, regions, and feature parity, see the
enterprise deployment overview
. Each provider’s auth setup is in
Authentication
.
Proxy and firewall requirements in
Network configuration
apply regardless of provider. If you want a single endpoint in front of multiple providers or centralized request logging, see
LLM gateway
.
​
Decide how settings reach devices
Managed settings define policy that takes precedence over local developer configuration. Claude Code looks for them in four places and uses the first one it finds on a given device.
Mechanism
Delivery
Priority
Platforms
Server-managed
Claude.ai admin console
Highest
All
plist / registry policy
macOS:
com.anthropic.claudecode
plist
Windows:
HKLM\SOFTWARE\Policies\ClaudeCode
High
macOS, Windows
File-based managed
macOS:
/Library/Application Support/ClaudeCode/managed-settings.json
Linux and WSL:
/etc/claude-code/managed-settings.json
Windows:
C:\Program Files\ClaudeCode\managed-settings.json
Medium
All
Windows user registry
HKCU\SOFTWARE\Policies\ClaudeCode
Lowest
Windows only
Server-managed settings reach devices at authentication time and refresh hourly during active sessions, with no endpoint infrastructure. They require a Claude for Teams or Enterprise plan, so deployments on other providers need one of the file-based or OS-level mechanisms instead.
If your organization mixes providers, configure
server-managed settings
for Claude.ai users plus a
file-based or plist/registry fallback
so other users still receive managed policy.
The plist and HKLM registry locations work with any provider and resist tampering because they require admin privileges to write. The Windows user registry at HKCU is writable without elevation, so treat it as a convenience default rather than an enforcement channel.
By default WSL reads only the Linux file path at
/etc/claude-code
. To extend your Windows registry and
C:\Program Files\ClaudeCode
policy to WSL on the same machine, set
wslInheritsWindowsSettings: true
in either of those admin-only Windows sources.
Whichever mechanism you choose, managed values take precedence over user and project settings. Array settings such as
permissions.allow
and
permissions.deny
merge entries from all sources, so developers can extend managed lists but not remove from them.
See
Server-managed settings
and
Settings files and precedence
.
​
Decide what to enforce
Managed settings can lock down tools, sandbox execution, restrict MCP servers and plugin sources, and control which hooks run. Each row is a control surface with the setting keys that drive it.
Control
What it does
Key settings
Permission rules
Allow, ask, or deny specific tools and commands
permissions.allow
,
permissions.deny
Permission lockdown
Only managed permission rules apply; disable
--dangerously-skip-permissions
allowManagedPermissionRulesOnly
,
permissions.disableBypassPermissionsMode
Sandboxing
OS-level filesystem and network isolation with domain allowlists
sandbox.enabled
,
sandbox.network.allowedDomains
Managed policy CLAUDE.md
Org-wide instructions loaded in every session, cannot be excluded
File at the managed policy path
MCP server control
Restrict which MCP servers users can add or connect to
allowedMcpServers
,
deniedMcpServers
,
allowManagedMcpServersOnly
Plugin marketplace control
Restrict which marketplace sources users can add and install from
strictKnownMarketplaces
,
blockedMarketplaces
Hook restrictions
Only managed hooks load; restrict HTTP hook URLs
allowManagedHooksOnly
,
allowedHttpHookUrls
Disable agent view
Turn off
claude agents
,
--bg
,
/background
, and the on-demand supervisor
disableAgentView
Version floor
Prevent auto-update from installing below an org-wide minimum
minimumVersion
Permission rules and sandboxing cover different layers. Denying WebFetch blocks Claude’s fetch tool, but if Bash is allowed,
curl
and
wget
can still reach any URL. Sandboxing closes that gap with a network domain allowlist enforced at the OS level.
For the threat model these controls defend against, see
Security
.
​
Set up usage visibility
Choose monitoring based on what you need to report on.
Capability
What you get
Availability
Where to start
Usage monitoring
OpenTelemetry export of sessions, tools, and tokens
All providers
Monitoring usage
Analytics dashboard
Per-user metrics, contribution tracking, leaderboard
Anthropic only
Analytics
Cost tracking
Spend limits, rate limits, and usage attribution
Anthropic only
Costs
Cloud providers expose spend through AWS Cost Explorer, GCP Billing, or Azure Cost Management. Claude for Teams and Enterprise plans include a usage dashboard at
claude.ai/analytics/claude-code
.
​
Review data handling
On Team, Enterprise, Claude API, and cloud provider plans, Anthropic does not train models on your code or prompts. Your API provider determines retention and compliance posture.
Topic
What to know
Where to start
Data usage policy
What Anthropic collects, how long it’s retained, what’s never used for training
Data usage
Zero Data Retention (ZDR)
Nothing stored after the request completes. Available on Claude for Enterprise
Zero data retention
Security architecture
Network model, encryption, authentication, audit trail
Security
If you need request-level audit logging or to route traffic by data sensitivity, place an
LLM gateway
between developers and your provider. For regulatory requirements and certifications, see
Legal and compliance
.
​
Verify and onboard
After configuring managed settings, have a developer run
/status
inside Claude Code. The output includes a line beginning with
Enterprise managed settings
followed by the source in parentheses, one of
(remote)
,
(plist)
,
(HKLM)
,
(HKCU)
, or
(file)
. See
Verify active settings
.
Share these resources to help developers get started:
Quickstart
: first-session walkthrough from install to working with a project
Common workflows
: patterns for everyday tasks like code review, refactoring, and debugging
Claude 101
and
Claude Code in Action
: self-paced Anthropic Academy courses
For login issues, point developers to
authentication troubleshooting
. The most common fixes are:
Run
/logout
then
/login
to switch accounts
Run
claude update
if the enterprise auth option is missing
Restart the terminal after updating
If a developer sees “You haven’t been added to your organization yet,” their seat doesn’t include Claude Code access and needs to be updated in the admin console.
​
Next steps
With provider and delivery mechanism chosen, move on to detailed configuration:
Server-managed settings
: deliver managed policy from the Claude admin console
Settings reference
: every setting key, file location, and precedence rule
Amazon Bedrock
,
Google Vertex AI
,
Microsoft Foundry
: provider-specific deployment
Claude Enterprise Administrator Guide
: SSO, SCIM, seat management, and rollout playbook
Was this page helpful?
Yes
No
Advanced setup
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/admin-setup" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Agent SDK overview</title>
  <link>https://code.claude.com/docs/en/agent-sdk/overview</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/overview</guid>
  <pubDate>Mon, 20 May 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Agent SDK overview
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize beh...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Agent SDK overview
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
Build AI agents that autonomously read files, run commands, search the web, edit code, and more. The Agent SDK gives you the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Find and fix the bug in auth.py"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
]),
):
print
(message)
# Claude reads the file, finds the bug, edits it
asyncio.run(main())
The Agent SDK includes built-in tools for reading files, running commands, and editing code, so your agent can start working immediately without you implementing tool execution. Dive into the quickstart or explore real agents built with the SDK:
Quickstart
Build a bug-fixing agent in minutes
Example agents
Email assistant, research agent, and more
​
Get started
1
Install the SDK
TypeScript
Python
npm
install
@anthropic-ai/claude-agent-sdk
pip
install
claude-agent-sdk
The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
2
Set your API key
Get an API key from the
Console
, then set it as an environment variable:
export
ANTHROPIC_API_KEY
=
your-api-key
The SDK also supports authentication via third-party API providers:
Amazon Bedrock
: set
CLAUDE_CODE_USE_BEDROCK=1
environment variable and configure AWS credentials
Claude Platform on AWS
: set
CLAUDE_CODE_USE_ANTHROPIC_AWS=1
and
ANTHROPIC_AWS_WORKSPACE_ID
, then configure AWS credentials
Google Vertex AI
: set
CLAUDE_CODE_USE_VERTEX=1
environment variable and configure Google Cloud credentials
Microsoft Azure
: set
CLAUDE_CODE_USE_FOUNDRY=1
environment variable and configure Azure credentials
See the setup guides for
Bedrock
,
Claude Platform on AWS
,
Vertex AI
, or
Azure AI Foundry
for details.
Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.
3
Run your first agent
This example creates an agent that lists files in your current directory using built-in tools.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"What files are in this directory?"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Bash"
,
"Glob"
]),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Ready to build?
Follow the
Quickstart
to create an agent that finds and fixes bugs in minutes.
​
Capabilities
Everything that makes Claude Code powerful is available in the SDK:
Built-in tools
Hooks
Subagents
MCP
Permissions
Sessions
Your agent can read files, run commands, and search codebases out of the box. Key tools include:
Tool
What it does
Read
Read any file in the working directory
Write
Create new files
Edit
Make precise edits to existing files
Bash
Run terminal commands, scripts, git operations
Monitor
Watch a background script and react to each output line as an event
Glob
Find files by pattern (
**/*.ts
,
src/**/*.py
)
Grep
Search file contents with regex
WebSearch
Search the web for current information
WebFetch
Fetch and parse web page content
AskUserQuestion
Ask the user clarifying questions with multiple choice options
This example creates an agent that searches your codebase for TODO comments:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Find all TODO comments and create a summary"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
]),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Run custom code at key points in the agent lifecycle. SDK hooks use callback functions to validate, log, block, or transform agent behavior.
Available hooks:
PreToolUse
,
PostToolUse
,
Stop
,
SessionStart
,
SessionEnd
,
UserPromptSubmit
, and more.
This example logs all file changes to an audit file:
Python
TypeScript
import
asyncio
from
datetime
import
datetime
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher
async
def
log_file_change
(
input_data
,
tool_use_id
,
context
):
file_path
=
input_data.get(
"tool_input"
, {}).get(
"file_path"
,
"unknown"
)
with
open
(
"./audit.log"
,
"a"
)
as
f:
f.write(
f
"
{
datetime.now()
}
: modified
{
file_path
}
\n
"
)
return
{}
async
def
main
():
async
for
message
in
query(
prompt
=
"Refactor utils.py to improve readability"
,
options
=
ClaudeAgentOptions(
permission_mode
=
"acceptEdits"
,
hooks
=
{
"PostToolUse"
: [
HookMatcher(
matcher
=
"Edit|Write"
,
hooks
=
[log_file_change])
]
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about hooks →
Spawn specialized agents to handle focused subtasks. Your main agent delegates work, and subagents report back with results.
Define custom agents with specialized instructions. Include
Agent
in
allowedTools
since subagents are invoked via the Agent tool:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Use the code-reviewer agent to review this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
description
=
"Expert code reviewer for quality and security reviews."
,
prompt
=
"Analyze code quality and suggest improvements."
,
tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Messages from within a subagent’s context include a
parent_tool_use_id
field, letting you track which messages belong to which subagent execution.
Learn more about subagents →
Connect to external systems via the Model Context Protocol: databases, browsers, APIs, and
hundreds more
.
This example connects the
Playwright MCP server
to give your agent browser automation capabilities:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Open example.com and describe what you see"
,
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"playwright"
: {
"command"
:
"npx"
,
"args"
: [
"@playwright/mcp@latest"
]}
}
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about MCP →
Control exactly which tools your agent can use. Allow safe operations, block dangerous ones, or require approval for sensitive actions.
For interactive approval prompts and the
AskUserQuestion
tool, see
Handle approvals and user input
.
This example creates a read-only agent that can analyze but not modify code.
allowed_tools
pre-approves
Read
,
Glob
, and
Grep
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Review this code for best practices"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about permissions →
Maintain context across multiple exchanges. Claude remembers files read, analysis done, and conversation history. Resume sessions later, or fork them to explore different approaches.
This example captures the session ID from the first query, then resumes to continue with full context:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, SystemMessage, ResultMessage
async
def
main
():
session_id
=
None
# First query: capture the session ID
async
for
message
in
query(
prompt
=
"Read the authentication module"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
]),
):
if
isinstance
(message, SystemMessage)
and
message.subtype
==
"init"
:
session_id
=
message.data[
"session_id"
]
# Resume with full context from the first query
async
for
message
in
query(
prompt
=
"Now find all places that call it"
,
# "it" = auth module
options
=
ClaudeAgentOptions(
resume
=
session_id),
):
if
isinstance
(message, ResultMessage):
print
(message.result)
asyncio.run(main())
Learn more about sessions →
​
Claude Code features
The SDK also supports Claude Code’s filesystem-based configuration. With default options the SDK loads these from
.claude/
in your working directory and
~/.claude/
. To restrict which sources load, set
setting_sources
(Python) or
settingSources
(TypeScript) in your options.
Feature
Description
Location
Skills
Specialized capabilities defined in Markdown
.claude/skills/*/SKILL.md
Slash commands
Custom commands for common tasks
.claude/commands/*.md
Memory
Project context and instructions
CLAUDE.md
or
.claude/CLAUDE.md
Plugins
Extend with custom commands, agents, and MCP servers
Programmatic via
plugins
option
​
Compare the Agent SDK to other Claude tools
The Claude Platform offers multiple ways to build with Claude. Here’s how the Agent SDK fits in:
Agent SDK vs Client SDK
Agent SDK vs Claude Code CLI
Agent SDK vs Managed Agents
The
Anthropic Client SDK
gives you direct API access: you send prompts and implement tool execution yourself. The
Agent SDK
gives you Claude with built-in tool execution.
With the Client SDK, you implement a tool loop. With the Agent SDK, Claude handles it:
Python
TypeScript
# Client SDK: You implement the tool loop
response
=
client.messages.create(
...
)
while
response.stop_reason
==
"tool_use"
:
result
=
your_tool_executor(response.tool_use)
response
=
client.messages.create(
tool_result
=
result,
**
params)
# Agent SDK: Claude handles tools autonomously
async
for
message
in
query(
prompt
=
"Fix the bug in auth.py"
):
print
(message)
Same capabilities, different interface:
Use case
Best choice
Interactive development
CLI
CI/CD pipelines
SDK
Custom applications
SDK
One-off tasks
CLI
Production automation
SDK
Many teams use both: CLI for daily development, SDK for production. Workflows translate directly between them.
Managed Agents
is a hosted REST API: Anthropic runs the agent and the sandbox, and your application sends events and streams back results. The
Agent SDK
is a library that runs the agent loop inside your own process.
Agent SDK
Managed Agents
Runs in
Your process, your infrastructure
Anthropic-managed infrastructure
Interface
Python or TypeScript library
REST API
Agent works on
Files on your infrastructure
A managed sandbox per session
Session state
JSONL on your filesystem
Anthropic-hosted event log
Custom tools
In-process Python or TypeScript functions
Claude triggers the tool; you execute and return results
Best for
Local prototyping, agents that work directly on your filesystem and services
Production agents without operating sandbox or session infrastructure, long-running and asynchronous sessions
A common path is to prototype with the Agent SDK locally, then move to Managed Agents for production.
​
Changelog
View the full changelog for SDK updates, bug fixes, and new features:
TypeScript SDK
:
view CHANGELOG.md
Python SDK
:
view CHANGELOG.md
​
Reporting bugs
If you encounter bugs or issues with the Agent SDK:
TypeScript SDK
:
report issues on GitHub
Python SDK
:
report issues on GitHub
​
Branding guidelines
For partners integrating the Claude Agent SDK, use of Claude branding is optional. When referencing Claude in your product:
Allowed:
“Claude Agent” (preferred for dropdown menus)
“Claude” (when within a menu already labeled “Agents”)
” Powered by Claude” (if you have an existing agent name)
Not permitted:
“Claude Code” or “Claude Code Agent”
Claude Code-branded ASCII art or visual elements that mimic Claude Code
Your product should maintain its own branding and not appear to be Claude Code or any Anthropic product. For questions about branding compliance, contact the Anthropic
sales team
.
​
License and terms
Use of the Claude Agent SDK is governed by
Anthropic’s Commercial Terms of Service
, including when you use it to power products and services that you make available to your own customers and end users, except to the extent a specific component or dependency is covered by a different license as indicated in that component’s LICENSE file.
​
Next steps
Quickstart
Build an agent that finds and fixes bugs in minutes
Example agents
Email assistant, research agent, and more
TypeScript SDK
Full TypeScript API reference and examples
Python SDK
Full Python API reference and examples
Was this page helpful?
Yes
No
Quickstart
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Agent SDK overview
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize beh...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agent SDK
Agent SDK overview
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Starting June 15, 2026, Agent SDK and
claude -p
usage on subscription plans will draw from a new monthly Agent SDK credit, separate from your interactive usage limits. See
Use the Claude Agent SDK with your Claude plan
for details.
Build AI agents that autonomously read files, run commands, search the web, edit code, and more. The Agent SDK gives you the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Find and fix the bug in auth.py"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
]),
):
print
(message)
# Claude reads the file, finds the bug, edits it
asyncio.run(main())
The Agent SDK includes built-in tools for reading files, running commands, and editing code, so your agent can start working immediately without you implementing tool execution. Dive into the quickstart or explore real agents built with the SDK:
Quickstart
Build a bug-fixing agent in minutes
Example agents
Email assistant, research agent, and more
​
Get started
1
Install the SDK
TypeScript
Python
npm
install
@anthropic-ai/claude-agent-sdk
pip
install
claude-agent-sdk
The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don’t need to install Claude Code separately.
2
Set your API key
Get an API key from the
Console
, then set it as an environment variable:
export
ANTHROPIC_API_KEY
=
your-api-key
The SDK also supports authentication via third-party API providers:
Amazon Bedrock
: set
CLAUDE_CODE_USE_BEDROCK=1
environment variable and configure AWS credentials
Claude Platform on AWS
: set
CLAUDE_CODE_USE_ANTHROPIC_AWS=1
and
ANTHROPIC_AWS_WORKSPACE_ID
, then configure AWS credentials
Google Vertex AI
: set
CLAUDE_CODE_USE_VERTEX=1
environment variable and configure Google Cloud credentials
Microsoft Azure
: set
CLAUDE_CODE_USE_FOUNDRY=1
environment variable and configure Azure credentials
See the setup guides for
Bedrock
,
Claude Platform on AWS
,
Vertex AI
, or
Azure AI Foundry
for details.
Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.
3
Run your first agent
This example creates an agent that lists files in your current directory using built-in tools.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"What files are in this directory?"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Bash"
,
"Glob"
]),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Ready to build?
Follow the
Quickstart
to create an agent that finds and fixes bugs in minutes.
​
Capabilities
Everything that makes Claude Code powerful is available in the SDK:
Built-in tools
Hooks
Subagents
MCP
Permissions
Sessions
Your agent can read files, run commands, and search codebases out of the box. Key tools include:
Tool
What it does
Read
Read any file in the working directory
Write
Create new files
Edit
Make precise edits to existing files
Bash
Run terminal commands, scripts, git operations
Monitor
Watch a background script and react to each output line as an event
Glob
Find files by pattern (
**/*.ts
,
src/**/*.py
)
Grep
Search file contents with regex
WebSearch
Search the web for current information
WebFetch
Fetch and parse web page content
AskUserQuestion
Ask the user clarifying questions with multiple choice options
This example creates an agent that searches your codebase for TODO comments:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Find all TODO comments and create a summary"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
]),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Run custom code at key points in the agent lifecycle. SDK hooks use callback functions to validate, log, block, or transform agent behavior.
Available hooks:
PreToolUse
,
PostToolUse
,
Stop
,
SessionStart
,
SessionEnd
,
UserPromptSubmit
, and more.
This example logs all file changes to an audit file:
Python
TypeScript
import
asyncio
from
datetime
import
datetime
from
claude_agent_sdk
import
query, ClaudeAgentOptions, HookMatcher
async
def
log_file_change
(
input_data
,
tool_use_id
,
context
):
file_path
=
input_data.get(
"tool_input"
, {}).get(
"file_path"
,
"unknown"
)
with
open
(
"./audit.log"
,
"a"
)
as
f:
f.write(
f
"
{
datetime.now()
}
: modified
{
file_path
}
\n
"
)
return
{}
async
def
main
():
async
for
message
in
query(
prompt
=
"Refactor utils.py to improve readability"
,
options
=
ClaudeAgentOptions(
permission_mode
=
"acceptEdits"
,
hooks
=
{
"PostToolUse"
: [
HookMatcher(
matcher
=
"Edit|Write"
,
hooks
=
[log_file_change])
]
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about hooks →
Spawn specialized agents to handle focused subtasks. Your main agent delegates work, and subagents report back with results.
Define custom agents with specialized instructions. Include
Agent
in
allowedTools
since subagents are invoked via the Agent tool:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Use the code-reviewer agent to review this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
description
=
"Expert code reviewer for quality and security reviews."
,
prompt
=
"Analyze code quality and suggest improvements."
,
tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Messages from within a subagent’s context include a
parent_tool_use_id
field, letting you track which messages belong to which subagent execution.
Learn more about subagents →
Connect to external systems via the Model Context Protocol: databases, browsers, APIs, and
hundreds more
.
This example connects the
Playwright MCP server
to give your agent browser automation capabilities:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Open example.com and describe what you see"
,
options
=
ClaudeAgentOptions(
mcp_servers
=
{
"playwright"
: {
"command"
:
"npx"
,
"args"
: [
"@playwright/mcp@latest"
]}
}
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about MCP →
Control exactly which tools your agent can use. Allow safe operations, block dangerous ones, or require approval for sensitive actions.
For interactive approval prompts and the
AskUserQuestion
tool, see
Handle approvals and user input
.
This example creates a read-only agent that can analyze but not modify code.
allowed_tools
pre-approves
Read
,
Glob
, and
Grep
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Review this code for best practices"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Learn more about permissions →
Maintain context across multiple exchanges. Claude remembers files read, analysis done, and conversation history. Resume sessions later, or fork them to explore different approaches.
This example captures the session ID from the first query, then resumes to continue with full context:
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, SystemMessage, ResultMessage
async
def
main
():
session_id
=
None
# First query: capture the session ID
async
for
message
in
query(
prompt
=
"Read the authentication module"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
]),
):
if
isinstance
(message, SystemMessage)
and
message.subtype
==
"init"
:
session_id
=
message.data[
"session_id"
]
# Resume with full context from the first query
async
for
message
in
query(
prompt
=
"Now find all places that call it"
,
# "it" = auth module
options
=
ClaudeAgentOptions(
resume
=
session_id),
):
if
isinstance
(message, ResultMessage):
print
(message.result)
asyncio.run(main())
Learn more about sessions →
​
Claude Code features
The SDK also supports Claude Code’s filesystem-based configuration. With default options the SDK loads these from
.claude/
in your working directory and
~/.claude/
. To restrict which sources load, set
setting_sources
(Python) or
settingSources
(TypeScript) in your options.
Feature
Description
Location
Skills
Specialized capabilities defined in Markdown
.claude/skills/*/SKILL.md
Slash commands
Custom commands for common tasks
.claude/commands/*.md
Memory
Project context and instructions
CLAUDE.md
or
.claude/CLAUDE.md
Plugins
Extend with custom commands, agents, and MCP servers
Programmatic via
plugins
option
​
Compare the Agent SDK to other Claude tools
The Claude Platform offers multiple ways to build with Claude. Here’s how the Agent SDK fits in:
Agent SDK vs Client SDK
Agent SDK vs Claude Code CLI
Agent SDK vs Managed Agents
The
Anthropic Client SDK
gives you direct API access: you send prompts and implement tool execution yourself. The
Agent SDK
gives you Claude with built-in tool execution.
With the Client SDK, you implement a tool loop. With the Agent SDK, Claude handles it:
Python
TypeScript
# Client SDK: You implement the tool loop
response
=
client.messages.create(
...
)
while
response.stop_reason
==
"tool_use"
:
result
=
your_tool_executor(response.tool_use)
response
=
client.messages.create(
tool_result
=
result,
**
params)
# Agent SDK: Claude handles tools autonomously
async
for
message
in
query(
prompt
=
"Fix the bug in auth.py"
):
print
(message)
Same capabilities, different interface:
Use case
Best choice
Interactive development
CLI
CI/CD pipelines
SDK
Custom applications
SDK
One-off tasks
CLI
Production automation
SDK
Many teams use both: CLI for daily development, SDK for production. Workflows translate directly between them.
Managed Agents
is a hosted REST API: Anthropic runs the agent and the sandbox, and your application sends events and streams back results. The
Agent SDK
is a library that runs the agent loop inside your own process.
Agent SDK
Managed Agents
Runs in
Your process, your infrastructure
Anthropic-managed infrastructure
Interface
Python or TypeScript library
REST API
Agent works on
Files on your infrastructure
A managed sandbox per session
Session state
JSONL on your filesystem
Anthropic-hosted event log
Custom tools
In-process Python or TypeScript functions
Claude triggers the tool; you execute and return results
Best for
Local prototyping, agents that work directly on your filesystem and services
Production agents without operating sandbox or session infrastructure, long-running and asynchronous sessions
A common path is to prototype with the Agent SDK locally, then move to Managed Agents for production.
​
Changelog
View the full changelog for SDK updates, bug fixes, and new features:
TypeScript SDK
:
view CHANGELOG.md
Python SDK
:
view CHANGELOG.md
​
Reporting bugs
If you encounter bugs or issues with the Agent SDK:
TypeScript SDK
:
report issues on GitHub
Python SDK
:
report issues on GitHub
​
Branding guidelines
For partners integrating the Claude Agent SDK, use of Claude branding is optional. When referencing Claude in your product:
Allowed:
“Claude Agent” (preferred for dropdown menus)
“Claude” (when within a menu already labeled “Agents”)
” Powered by Claude” (if you have an existing agent name)
Not permitted:
“Claude Code” or “Claude Code Agent”
Claude Code-branded ASCII art or visual elements that mimic Claude Code
Your product should maintain its own branding and not appear to be Claude Code or any Anthropic product. For questions about branding compliance, contact the Anthropic
sales team
.
​
License and terms
Use of the Claude Agent SDK is governed by
Anthropic’s Commercial Terms of Service
, including when you use it to power products and services that you make available to your own customers and end users, except to the extent a specific component or dependency is covered by a different license as indicated in that component’s LICENSE file.
​
Next steps
Quickstart
Build an agent that finds and fixes bugs in minutes
Example agents
Email assistant, research agent, and more
TypeScript SDK
Full TypeScript API reference and examples
Python SDK
Full Python API reference and examples
Was this page helpful?
Yes
No
Quickstart
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/overview" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>CLI reference</title>
  <link>https://code.claude.com/docs/en/cli-reference</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/cli-reference</guid>
  <pubDate>Mon, 20 May 2024 00:00:00 +0000</pubDate>
  <category>Reference</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
CLI reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
CLI commands
You can start sessions, pipe conten...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
CLI reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
CLI commands
You can start sessions, pipe content, resume conversations, and manage updates with these commands:
Command
Description
Example
claude
Start interactive session
claude
claude "query"
Start interactive session with initial prompt
claude "explain this project"
claude -p "query"
Query via SDK, then exit
claude -p "explain this function"
cat file | claude -p "query"
Process piped content
cat logs.txt | claude -p "explain"
claude -c
Continue most recent conversation in current directory
claude -c
claude -c -p "query"
Continue via SDK
claude -c -p "Check for type errors"
claude -r "<session>" "query"
Resume session by ID or name
claude -r "auth-refactor" "Finish this PR"
claude update
Update to latest version
claude update
claude install [version]
Install or reinstall the native binary. Accepts a version like
2.1.118
, or
stable
or
latest
. See
Install a specific version
claude install stable
claude auth login
Sign in to your Anthropic account. Use
--email
to pre-fill your email address,
--sso
to force SSO authentication, and
--console
to sign in with Anthropic Console for API usage billing instead of a Claude subscription
claude auth login --console
claude auth logout
Log out from your Anthropic account
claude auth logout
claude auth status
Show authentication status as JSON. Use
--text
for human-readable output. Exits with code 0 if logged in, 1 if not
claude auth status
claude agents
Open
agent view
to monitor and dispatch parallel background sessions. Use
--cwd <path>
to show only sessions started under that directory
claude agents
claude attach <id>
Attach to a
background session
in this terminal
claude attach 7c5dcf5d
claude auto-mode defaults
Print the built-in
auto mode
classifier rules as JSON. Use
claude auto-mode config
to see your effective config with settings applied
claude auto-mode defaults > rules.json
claude logs <id>
Print recent output from a
background session
claude logs 7c5dcf5d
claude mcp
Configure Model Context Protocol (MCP) servers
See the
Claude Code MCP documentation
.
claude plugin
Manage Claude Code
plugins
. Alias:
claude plugins
. See
plugin reference
for subcommands
claude plugin install code-review@claude-plugins-official
claude project purge [path]
Delete all local Claude Code state for a project: transcripts, task lists, debug logs, file-edit history, prompt history lines, and the project’s entry in
~/.claude.json
. Omit
[path]
to pick from an interactive list. Flags:
--dry-run
to preview,
-y
/
--yes
to skip confirmation,
-i
/
--interactive
to confirm each item,
--all
for every project. See
Clear local data
claude project purge ~/work/repo --dry-run
claude remote-control
Start a
Remote Control
server to control Claude Code from Claude.ai or the Claude app. Runs in server mode (no local interactive session). See
Server mode flags
claude remote-control --name "My Project"
claude respawn <id>
Restart a stopped
background session
with its conversation intact. Use
--all
to restart every stopped session
claude respawn 7c5dcf5d
claude rm <id>
Remove a
background session
from the list
claude rm 7c5dcf5d
claude setup-token
Generate a long-lived OAuth token for CI and scripts. Prints the token to the terminal without saving it. Requires a Claude subscription. See
Generate a long-lived token
claude setup-token
claude stop <id>
Stop a
background session
. Also accepts
claude kill
claude stop 7c5dcf5d
claude ultrareview [target]
Run
ultrareview
non-interactively. Prints findings to stdout and exits 0 on success or 1 on failure. Use
--json
for the raw payload and
--timeout <minutes>
to override the 30-minute default
claude ultrareview 1234 --json
If you mistype a subcommand, Claude Code suggests the closest match and exits without starting a session. For example,
claude udpate
prints
Did you mean claude update?
.
​
CLI flags
Customize Claude Code’s behavior with these command-line flags.
claude --help
does not list every flag, so a flag’s absence from
--help
does not mean it is unavailable.
Flag
Description
Example
--add-dir
Add additional working directories for Claude to read and edit files. Grants file access; most
.claude/
configuration is
not discovered
from these directories. Validates each path exists as a directory. To persist these directories across sessions, set
permissions.additionalDirectories
in settings
claude --add-dir ../apps ../lib
--agent
Specify an agent for the current session (overrides the
agent
setting)
claude --agent my-custom-agent
--agents
Define custom subagents dynamically via JSON. Uses the same field names as subagent
frontmatter
, plus a
prompt
field for the agent’s instructions
claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a code reviewer"}}'
--allow-dangerously-skip-permissions
Add
bypassPermissions
to the
Shift+Tab
mode cycle without starting in it. Lets you begin in a different mode like
plan
and switch to
bypassPermissions
later. See
permission modes
claude --permission-mode plan --allow-dangerously-skip-permissions
--allowedTools
Tools that execute without prompting for permission. See
permission rule syntax
for pattern matching. To restrict which tools are available, use
--tools
instead
"Bash(git log *)" "Bash(git diff *)" "Read"
--append-system-prompt
Append custom text to the end of the default system prompt
claude --append-system-prompt "Always use TypeScript"
--append-system-prompt-file
Load additional system prompt text from a file and append to the default prompt
claude --append-system-prompt-file ./extra-rules.txt
--bare
Minimal mode: skip auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md so scripted calls start faster. Claude has access to Bash, file read, and file edit tools. Sets
CLAUDE_CODE_SIMPLE
. See
bare mode
claude --bare -p "query"
--betas
Beta headers to include in API requests (API key users only)
claude --betas interleaved-thinking
--bg
Start the session as a
background agent
and return immediately. Prints the session ID and management commands. Combine with
--agent
to run a specific subagent
claude --bg "investigate the flaky test"
--channels
(Research preview) MCP servers whose
channel
notifications Claude should listen for in this session. Space-separated list of
plugin:<name>@<marketplace>
entries. Requires Claude.ai authentication
claude --channels plugin:my-notifier@my-marketplace
--chrome
Enable
Chrome browser integration
for web automation and testing
claude --chrome
--continue
,
-c
Load the most recent conversation in the current directory. Includes sessions that added this directory with
/add-dir
claude --continue
--dangerously-load-development-channels
Enable
channels
that are not on the approved allowlist, for local development. Accepts
plugin:<name>@<marketplace>
and
server:<name>
entries. Prompts for confirmation
claude --dangerously-load-development-channels server:webhook
--dangerously-skip-permissions
Skip permission prompts. Equivalent to
--permission-mode bypassPermissions
. See
permission modes
for what this does and does not skip
claude --dangerously-skip-permissions
--debug
Enable debug mode with optional category filtering (for example,
"api,hooks"
or
"!statsig,!file"
)
claude --debug "api,mcp"
--debug-file <path>
Write debug logs to a specific file path. Implicitly enables debug mode. Takes precedence over
CLAUDE_CODE_DEBUG_LOGS_DIR
claude --debug-file /tmp/claude-debug.log
--disable-slash-commands
Disable all skills and commands for this session
claude --disable-slash-commands
--disallowedTools
Tools that are removed from the model’s context and cannot be used
"Bash(git log *)" "Bash(git diff *)" "Edit"
--effort
Set the
effort level
for the current session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model. Overrides the
effortLevel
setting for this session and does not persist
claude --effort high
--enable-auto-mode
Removed in v2.1.111. Auto mode is now in the
Shift+Tab
cycle by default; use
--permission-mode auto
to start in it
claude --permission-mode auto
--exclude-dynamic-system-prompt-sections
Move per-machine sections from the system prompt (working directory, environment info, memory paths, git-repo flag) into the first user message. Improves prompt-cache reuse across different users and machines running the same task. Only applies with the default system prompt; ignored when
--system-prompt
or
--system-prompt-file
is set. Use with
-p
for scripted, multi-user workloads
claude -p --exclude-dynamic-system-prompt-sections "query"
--fallback-model
Enable automatic fallback to specified model when default model is overloaded (print mode only)
claude -p --fallback-model sonnet "query"
--fork-session
When resuming, create a new session ID instead of reusing the original (use with
--resume
or
--continue
)
claude --resume abc123 --fork-session
--from-pr
Resume sessions linked to a specific pull request. Accepts a PR number, a GitHub or GitHub Enterprise PR URL, a GitLab merge request URL, or a Bitbucket pull request URL. Sessions are linked automatically when Claude creates the pull request
claude --from-pr 123
--ide
Automatically connect to IDE on startup if exactly one valid IDE is available
claude --ide
--init
Run
Setup hooks
with the
init
matcher before the session (print mode only)
claude -p --init "query"
--init-only
Run
Setup
and
SessionStart
hooks, then exit without starting a conversation
claude --init-only
--include-hook-events
Include all hook lifecycle events in the output stream. Requires
--output-format stream-json
claude -p --output-format stream-json --include-hook-events "query"
--include-partial-messages
Include partial streaming events in output. Requires
--print
and
--output-format stream-json
claude -p --output-format stream-json --include-partial-messages "query"
--input-format
Specify input format for print mode (options:
text
,
stream-json
)
claude -p --output-format json --input-format stream-json
--json-schema
Get validated JSON output matching a JSON Schema after agent completes its workflow (print mode only, see
structured outputs
)
claude -p --json-schema '{"type":"object","properties":{...}}' "query"
--maintenance
Run
Setup hooks
with the
maintenance
matcher before the session (print mode only)
claude -p --maintenance "query"
--max-budget-usd
Maximum dollar amount to spend on API calls before stopping (print mode only)
claude -p --max-budget-usd 5.00 "query"
--max-turns
Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default
claude -p --max-turns 3 "query"
--mcp-config
Load MCP servers from JSON files or strings (space-separated)
claude --mcp-config ./mcp.json
--model
Sets the model for the current session with an alias for the latest model (
sonnet
or
opus
) or a model’s full name. Overrides the
model
setting and
ANTHROPIC_MODEL
claude --model claude-sonnet-4-6
--name
,
-n
Set a display name for the session, shown in
/resume
and the terminal title. You can resume a named session with
claude --resume <name>
.
/rename
changes the name mid-session and also shows it on the prompt bar
claude -n "my-feature-work"
--no-chrome
Disable
Chrome browser integration
for this session
claude --no-chrome
--no-session-persistence
Disable session persistence so sessions are not saved to disk and cannot be resumed. Print mode only. The
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable does the same in any mode
claude -p --no-session-persistence "query"
--output-format
Specify output format for print mode (options:
text
,
json
,
stream-json
)
claude -p "query" --output-format json
--permission-mode
Begin in a specified
permission mode
. Accepts
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
, or
bypassPermissions
. Overrides
defaultMode
from settings files
claude --permission-mode plan
--permission-prompt-tool
Specify an MCP tool to handle permission prompts in non-interactive mode
claude -p --permission-prompt-tool mcp_auth_tool "query"
--plugin-dir
Load a plugin from a directory or
.zip
archive for this session only. Each flag takes one path. Repeat the flag for multiple plugins:
--plugin-dir A --plugin-dir B.zip
claude --plugin-dir ./my-plugin
--plugin-url
Fetch a plugin
.zip
archive from a URL for this session only. Repeat the flag for multiple plugins, or pass space-separated URLs in a single quoted value
claude --plugin-url https://example.com/plugin.zip
--print
,
-p
Print response without interactive mode (see
Agent SDK documentation
for programmatic usage details)
claude -p "query"
--remote
Create a new
web session
on claude.ai with the provided task description
claude --remote "Fix the login bug"
--remote-control
,
--rc
Start an interactive session with
Remote Control
enabled so you can also control it from claude.ai or the Claude app. Optionally pass a name for the session
claude --remote-control "My Project"
--remote-control-session-name-prefix <prefix>
Prefix for auto-generated
Remote Control
session names when no explicit name is set. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. Set
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
for the same effect
claude remote-control --remote-control-session-name-prefix dev-box
--replay-user-messages
Re-emit user messages from stdin back on stdout for acknowledgment. Requires
--input-format stream-json
and
--output-format stream-json
claude -p --input-format stream-json --output-format stream-json --replay-user-messages
--resume
,
-r
Resume a specific session by ID or name, or show an interactive picker to choose a session. Includes sessions that added this directory with
/add-dir
claude --resume auth-refactor
--session-id
Use a specific session ID for the conversation (must be a valid UUID)
claude --session-id "550e8400-e29b-41d4-a716-446655440000"
--setting-sources
Comma-separated list of setting sources to load (
user
,
project
,
local
)
claude --setting-sources user,project
--settings
Path to a settings JSON file or an inline JSON string. Values you set here override the same keys in your
settings.json
files for this session. Keys you omit keep their file-based values. See
settings precedence
claude --settings ./settings.json
--strict-mcp-config
Only use MCP servers from
--mcp-config
, ignoring all other MCP configurations
claude --strict-mcp-config --mcp-config ./mcp.json
--system-prompt
Replace the entire system prompt with custom text
claude --system-prompt "You are a Python expert"
--system-prompt-file
Load system prompt from a file, replacing the default prompt
claude --system-prompt-file ./custom-prompt.txt
--teleport
Resume a
web session
in your local terminal
claude --teleport
--teammate-mode
Set how
agent team
teammates display:
auto
(default),
in-process
, or
tmux
. Overrides the
teammateMode
setting for this session. See
Choose a display mode
claude --teammate-mode in-process
--tmux
Create a tmux session for the worktree. Requires
--worktree
. Uses iTerm2 native panes when available; pass
--tmux=classic
for traditional tmux
claude -w feature-auth --tmux
--tools
Restrict which built-in tools Claude can use. Use
""
to disable all,
"default"
for all, or tool names like
"Bash,Edit,Read"
claude --tools "Bash,Edit,Read"
--verbose
Enable verbose logging, shows full turn-by-turn output. Overrides the
viewMode
setting for this session
claude --verbose
--version
,
-v
Output the version number
claude -v
--worktree
,
-w
Start Claude in an isolated
git worktree
at
<repo>/.claude/worktrees/<name>
. If no name is given, one is auto-generated. Pass
#<number>
or a GitHub pull request URL to fetch that PR from
origin
and branch the worktree from it
claude -w feature-auth
​
System prompt flags
Claude Code provides four flags for customizing the system prompt. All four work in both interactive and non-interactive modes.
Flag
Behavior
Example
--system-prompt
Replaces the entire default prompt
claude --system-prompt "You are a Python expert"
--system-prompt-file
Replaces with file contents
claude --system-prompt-file ./prompts/review.txt
--append-system-prompt
Appends to the default prompt
claude --append-system-prompt "Always use TypeScript"
--append-system-prompt-file
Appends file contents to the default prompt
claude --append-system-prompt-file ./style-rules.txt
--system-prompt
and
--system-prompt-file
are mutually exclusive. The append flags can be combined with either replacement flag.
Choose based on whether Claude Code’s default identity still fits your task. Use an append flag when Claude should remain a coding assistant that also follows your extra rules: per-invocation instructions, output formatting, or domain context for a
-p
script. Appending preserves the default tool guidance, safety instructions, and coding conventions, so you only supply what differs. Use a replacement flag when the surface, identity, or permission model differs from Claude Code’s, like a non-coding agent in a pipeline that no human watches. Replacing drops all of the default prompt, including tool guidance and safety instructions, so you take responsibility for whatever your task still needs.
These flags apply only to the current invocation. For persistent personas you can switch between and share across a project, use
output styles
. For project conventions Claude should always follow, use
CLAUDE.md
. The
Agent SDK guide on system prompts
covers the same decision in more depth.
​
See also
Chrome extension
- Browser automation and web testing
Interactive mode
- Shortcuts, input modes, and interactive features
Quickstart guide
- Getting started with Claude Code
Common workflows
- Advanced workflows and patterns
Settings
- Configuration options
Agent SDK documentation
- Programmatic usage and integrations
Was this page helpful?
Yes
No
Commands
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/cli-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
CLI reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
CLI commands
You can start sessions, pipe conten...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
CLI reference
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
CLI commands
You can start sessions, pipe content, resume conversations, and manage updates with these commands:
Command
Description
Example
claude
Start interactive session
claude
claude "query"
Start interactive session with initial prompt
claude "explain this project"
claude -p "query"
Query via SDK, then exit
claude -p "explain this function"
cat file | claude -p "query"
Process piped content
cat logs.txt | claude -p "explain"
claude -c
Continue most recent conversation in current directory
claude -c
claude -c -p "query"
Continue via SDK
claude -c -p "Check for type errors"
claude -r "<session>" "query"
Resume session by ID or name
claude -r "auth-refactor" "Finish this PR"
claude update
Update to latest version
claude update
claude install [version]
Install or reinstall the native binary. Accepts a version like
2.1.118
, or
stable
or
latest
. See
Install a specific version
claude install stable
claude auth login
Sign in to your Anthropic account. Use
--email
to pre-fill your email address,
--sso
to force SSO authentication, and
--console
to sign in with Anthropic Console for API usage billing instead of a Claude subscription
claude auth login --console
claude auth logout
Log out from your Anthropic account
claude auth logout
claude auth status
Show authentication status as JSON. Use
--text
for human-readable output. Exits with code 0 if logged in, 1 if not
claude auth status
claude agents
Open
agent view
to monitor and dispatch parallel background sessions. Use
--cwd <path>
to show only sessions started under that directory
claude agents
claude attach <id>
Attach to a
background session
in this terminal
claude attach 7c5dcf5d
claude auto-mode defaults
Print the built-in
auto mode
classifier rules as JSON. Use
claude auto-mode config
to see your effective config with settings applied
claude auto-mode defaults > rules.json
claude logs <id>
Print recent output from a
background session
claude logs 7c5dcf5d
claude mcp
Configure Model Context Protocol (MCP) servers
See the
Claude Code MCP documentation
.
claude plugin
Manage Claude Code
plugins
. Alias:
claude plugins
. See
plugin reference
for subcommands
claude plugin install code-review@claude-plugins-official
claude project purge [path]
Delete all local Claude Code state for a project: transcripts, task lists, debug logs, file-edit history, prompt history lines, and the project’s entry in
~/.claude.json
. Omit
[path]
to pick from an interactive list. Flags:
--dry-run
to preview,
-y
/
--yes
to skip confirmation,
-i
/
--interactive
to confirm each item,
--all
for every project. See
Clear local data
claude project purge ~/work/repo --dry-run
claude remote-control
Start a
Remote Control
server to control Claude Code from Claude.ai or the Claude app. Runs in server mode (no local interactive session). See
Server mode flags
claude remote-control --name "My Project"
claude respawn <id>
Restart a stopped
background session
with its conversation intact. Use
--all
to restart every stopped session
claude respawn 7c5dcf5d
claude rm <id>
Remove a
background session
from the list
claude rm 7c5dcf5d
claude setup-token
Generate a long-lived OAuth token for CI and scripts. Prints the token to the terminal without saving it. Requires a Claude subscription. See
Generate a long-lived token
claude setup-token
claude stop <id>
Stop a
background session
. Also accepts
claude kill
claude stop 7c5dcf5d
claude ultrareview [target]
Run
ultrareview
non-interactively. Prints findings to stdout and exits 0 on success or 1 on failure. Use
--json
for the raw payload and
--timeout <minutes>
to override the 30-minute default
claude ultrareview 1234 --json
If you mistype a subcommand, Claude Code suggests the closest match and exits without starting a session. For example,
claude udpate
prints
Did you mean claude update?
.
​
CLI flags
Customize Claude Code’s behavior with these command-line flags.
claude --help
does not list every flag, so a flag’s absence from
--help
does not mean it is unavailable.
Flag
Description
Example
--add-dir
Add additional working directories for Claude to read and edit files. Grants file access; most
.claude/
configuration is
not discovered
from these directories. Validates each path exists as a directory. To persist these directories across sessions, set
permissions.additionalDirectories
in settings
claude --add-dir ../apps ../lib
--agent
Specify an agent for the current session (overrides the
agent
setting)
claude --agent my-custom-agent
--agents
Define custom subagents dynamically via JSON. Uses the same field names as subagent
frontmatter
, plus a
prompt
field for the agent’s instructions
claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a code reviewer"}}'
--allow-dangerously-skip-permissions
Add
bypassPermissions
to the
Shift+Tab
mode cycle without starting in it. Lets you begin in a different mode like
plan
and switch to
bypassPermissions
later. See
permission modes
claude --permission-mode plan --allow-dangerously-skip-permissions
--allowedTools
Tools that execute without prompting for permission. See
permission rule syntax
for pattern matching. To restrict which tools are available, use
--tools
instead
"Bash(git log *)" "Bash(git diff *)" "Read"
--append-system-prompt
Append custom text to the end of the default system prompt
claude --append-system-prompt "Always use TypeScript"
--append-system-prompt-file
Load additional system prompt text from a file and append to the default prompt
claude --append-system-prompt-file ./extra-rules.txt
--bare
Minimal mode: skip auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md so scripted calls start faster. Claude has access to Bash, file read, and file edit tools. Sets
CLAUDE_CODE_SIMPLE
. See
bare mode
claude --bare -p "query"
--betas
Beta headers to include in API requests (API key users only)
claude --betas interleaved-thinking
--bg
Start the session as a
background agent
and return immediately. Prints the session ID and management commands. Combine with
--agent
to run a specific subagent
claude --bg "investigate the flaky test"
--channels
(Research preview) MCP servers whose
channel
notifications Claude should listen for in this session. Space-separated list of
plugin:<name>@<marketplace>
entries. Requires Claude.ai authentication
claude --channels plugin:my-notifier@my-marketplace
--chrome
Enable
Chrome browser integration
for web automation and testing
claude --chrome
--continue
,
-c
Load the most recent conversation in the current directory. Includes sessions that added this directory with
/add-dir
claude --continue
--dangerously-load-development-channels
Enable
channels
that are not on the approved allowlist, for local development. Accepts
plugin:<name>@<marketplace>
and
server:<name>
entries. Prompts for confirmation
claude --dangerously-load-development-channels server:webhook
--dangerously-skip-permissions
Skip permission prompts. Equivalent to
--permission-mode bypassPermissions
. See
permission modes
for what this does and does not skip
claude --dangerously-skip-permissions
--debug
Enable debug mode with optional category filtering (for example,
"api,hooks"
or
"!statsig,!file"
)
claude --debug "api,mcp"
--debug-file <path>
Write debug logs to a specific file path. Implicitly enables debug mode. Takes precedence over
CLAUDE_CODE_DEBUG_LOGS_DIR
claude --debug-file /tmp/claude-debug.log
--disable-slash-commands
Disable all skills and commands for this session
claude --disable-slash-commands
--disallowedTools
Tools that are removed from the model’s context and cannot be used
"Bash(git log *)" "Bash(git diff *)" "Edit"
--effort
Set the
effort level
for the current session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model. Overrides the
effortLevel
setting for this session and does not persist
claude --effort high
--enable-auto-mode
Removed in v2.1.111. Auto mode is now in the
Shift+Tab
cycle by default; use
--permission-mode auto
to start in it
claude --permission-mode auto
--exclude-dynamic-system-prompt-sections
Move per-machine sections from the system prompt (working directory, environment info, memory paths, git-repo flag) into the first user message. Improves prompt-cache reuse across different users and machines running the same task. Only applies with the default system prompt; ignored when
--system-prompt
or
--system-prompt-file
is set. Use with
-p
for scripted, multi-user workloads
claude -p --exclude-dynamic-system-prompt-sections "query"
--fallback-model
Enable automatic fallback to specified model when default model is overloaded (print mode only)
claude -p --fallback-model sonnet "query"
--fork-session
When resuming, create a new session ID instead of reusing the original (use with
--resume
or
--continue
)
claude --resume abc123 --fork-session
--from-pr
Resume sessions linked to a specific pull request. Accepts a PR number, a GitHub or GitHub Enterprise PR URL, a GitLab merge request URL, or a Bitbucket pull request URL. Sessions are linked automatically when Claude creates the pull request
claude --from-pr 123
--ide
Automatically connect to IDE on startup if exactly one valid IDE is available
claude --ide
--init
Run
Setup hooks
with the
init
matcher before the session (print mode only)
claude -p --init "query"
--init-only
Run
Setup
and
SessionStart
hooks, then exit without starting a conversation
claude --init-only
--include-hook-events
Include all hook lifecycle events in the output stream. Requires
--output-format stream-json
claude -p --output-format stream-json --include-hook-events "query"
--include-partial-messages
Include partial streaming events in output. Requires
--print
and
--output-format stream-json
claude -p --output-format stream-json --include-partial-messages "query"
--input-format
Specify input format for print mode (options:
text
,
stream-json
)
claude -p --output-format json --input-format stream-json
--json-schema
Get validated JSON output matching a JSON Schema after agent completes its workflow (print mode only, see
structured outputs
)
claude -p --json-schema '{"type":"object","properties":{...}}' "query"
--maintenance
Run
Setup hooks
with the
maintenance
matcher before the session (print mode only)
claude -p --maintenance "query"
--max-budget-usd
Maximum dollar amount to spend on API calls before stopping (print mode only)
claude -p --max-budget-usd 5.00 "query"
--max-turns
Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default
claude -p --max-turns 3 "query"
--mcp-config
Load MCP servers from JSON files or strings (space-separated)
claude --mcp-config ./mcp.json
--model
Sets the model for the current session with an alias for the latest model (
sonnet
or
opus
) or a model’s full name. Overrides the
model
setting and
ANTHROPIC_MODEL
claude --model claude-sonnet-4-6
--name
,
-n
Set a display name for the session, shown in
/resume
and the terminal title. You can resume a named session with
claude --resume <name>
.
/rename
changes the name mid-session and also shows it on the prompt bar
claude -n "my-feature-work"
--no-chrome
Disable
Chrome browser integration
for this session
claude --no-chrome
--no-session-persistence
Disable session persistence so sessions are not saved to disk and cannot be resumed. Print mode only. The
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable does the same in any mode
claude -p --no-session-persistence "query"
--output-format
Specify output format for print mode (options:
text
,
json
,
stream-json
)
claude -p "query" --output-format json
--permission-mode
Begin in a specified
permission mode
. Accepts
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
, or
bypassPermissions
. Overrides
defaultMode
from settings files
claude --permission-mode plan
--permission-prompt-tool
Specify an MCP tool to handle permission prompts in non-interactive mode
claude -p --permission-prompt-tool mcp_auth_tool "query"
--plugin-dir
Load a plugin from a directory or
.zip
archive for this session only. Each flag takes one path. Repeat the flag for multiple plugins:
--plugin-dir A --plugin-dir B.zip
claude --plugin-dir ./my-plugin
--plugin-url
Fetch a plugin
.zip
archive from a URL for this session only. Repeat the flag for multiple plugins, or pass space-separated URLs in a single quoted value
claude --plugin-url https://example.com/plugin.zip
--print
,
-p
Print response without interactive mode (see
Agent SDK documentation
for programmatic usage details)
claude -p "query"
--remote
Create a new
web session
on claude.ai with the provided task description
claude --remote "Fix the login bug"
--remote-control
,
--rc
Start an interactive session with
Remote Control
enabled so you can also control it from claude.ai or the Claude app. Optionally pass a name for the session
claude --remote-control "My Project"
--remote-control-session-name-prefix <prefix>
Prefix for auto-generated
Remote Control
session names when no explicit name is set. Defaults to your machine’s hostname, producing names like
myhost-graceful-unicorn
. Set
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX
for the same effect
claude remote-control --remote-control-session-name-prefix dev-box
--replay-user-messages
Re-emit user messages from stdin back on stdout for acknowledgment. Requires
--input-format stream-json
and
--output-format stream-json
claude -p --input-format stream-json --output-format stream-json --replay-user-messages
--resume
,
-r
Resume a specific session by ID or name, or show an interactive picker to choose a session. Includes sessions that added this directory with
/add-dir
claude --resume auth-refactor
--session-id
Use a specific session ID for the conversation (must be a valid UUID)
claude --session-id "550e8400-e29b-41d4-a716-446655440000"
--setting-sources
Comma-separated list of setting sources to load (
user
,
project
,
local
)
claude --setting-sources user,project
--settings
Path to a settings JSON file or an inline JSON string. Values you set here override the same keys in your
settings.json
files for this session. Keys you omit keep their file-based values. See
settings precedence
claude --settings ./settings.json
--strict-mcp-config
Only use MCP servers from
--mcp-config
, ignoring all other MCP configurations
claude --strict-mcp-config --mcp-config ./mcp.json
--system-prompt
Replace the entire system prompt with custom text
claude --system-prompt "You are a Python expert"
--system-prompt-file
Load system prompt from a file, replacing the default prompt
claude --system-prompt-file ./custom-prompt.txt
--teleport
Resume a
web session
in your local terminal
claude --teleport
--teammate-mode
Set how
agent team
teammates display:
auto
(default),
in-process
, or
tmux
. Overrides the
teammateMode
setting for this session. See
Choose a display mode
claude --teammate-mode in-process
--tmux
Create a tmux session for the worktree. Requires
--worktree
. Uses iTerm2 native panes when available; pass
--tmux=classic
for traditional tmux
claude -w feature-auth --tmux
--tools
Restrict which built-in tools Claude can use. Use
""
to disable all,
"default"
for all, or tool names like
"Bash,Edit,Read"
claude --tools "Bash,Edit,Read"
--verbose
Enable verbose logging, shows full turn-by-turn output. Overrides the
viewMode
setting for this session
claude --verbose
--version
,
-v
Output the version number
claude -v
--worktree
,
-w
Start Claude in an isolated
git worktree
at
<repo>/.claude/worktrees/<name>
. If no name is given, one is auto-generated. Pass
#<number>
or a GitHub pull request URL to fetch that PR from
origin
and branch the worktree from it
claude -w feature-auth
​
System prompt flags
Claude Code provides four flags for customizing the system prompt. All four work in both interactive and non-interactive modes.
Flag
Behavior
Example
--system-prompt
Replaces the entire default prompt
claude --system-prompt "You are a Python expert"
--system-prompt-file
Replaces with file contents
claude --system-prompt-file ./prompts/review.txt
--append-system-prompt
Appends to the default prompt
claude --append-system-prompt "Always use TypeScript"
--append-system-prompt-file
Appends file contents to the default prompt
claude --append-system-prompt-file ./style-rules.txt
--system-prompt
and
--system-prompt-file
are mutually exclusive. The append flags can be combined with either replacement flag.
Choose based on whether Claude Code’s default identity still fits your task. Use an append flag when Claude should remain a coding assistant that also follows your extra rules: per-invocation instructions, output formatting, or domain context for a
-p
script. Appending preserves the default tool guidance, safety instructions, and coding conventions, so you only supply what differs. Use a replacement flag when the surface, identity, or permission model differs from Claude Code’s, like a non-coding agent in a pipeline that no human watches. Replacing drops all of the default prompt, including tool guidance and safety instructions, so you take responsibility for whatever your task still needs.
These flags apply only to the current invocation. For persistent personas you can switch between and share across a project, use
output styles
. For project conventions Claude should always follow, use
CLAUDE.md
. The
Agent SDK guide on system prompts
covers the same decision in more depth.
​
See also
Chrome extension
- Browser automation and web testing
Interactive mode
- Shortcuts, input modes, and interactive features
Quickstart guide
- Getting started with Claude Code
Common workflows
- Advanced workflows and patterns
Settings
- Configuration options
Agent SDK documentation
- Programmatic usage and integrations
Was this page helpful?
Yes
No
Commands
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/cli-reference" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Configure your terminal for Claude Code</title>
  <link>https://code.claude.com/docs/en/terminal-config</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/terminal-config</guid>
  <pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
  <category>Configuration</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Configure your terminal for Claude Code
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Configure your terminal for Claude Code
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code works in any terminal without configuration. This page is for when something specific is not behaving the way you expect. Find your symptom below. If everything already feels right, you do not need this page.
Shift+Enter submits instead of inserting a newline
Option-key shortcuts do nothing on macOS
No sound or alert when Claude finishes
You run Claude Code inside tmux
Display flickers or scrollback jumps
You want Vim keys in the prompt
This page is about getting your terminal to send the right signals to Claude Code. To change which keys Claude Code itself responds to, see
keybindings
instead.
​
Enter multiline prompts
Pressing Enter submits your message. To add a line break without submitting, press Ctrl+J, or type
\
and then press Enter. Both work in every terminal with no setup.
In most terminals you can also press Shift+Enter, but support varies by terminal emulator:
Terminal
Shift+Enter for newline
Ghostty, Kitty, iTerm2, WezTerm, Warp, Apple Terminal, Windows Terminal
Works without setup
VS Code, Cursor, Windsurf, Alacritty, Zed
Run
/terminal-setup
once
gnome-terminal, JetBrains IDEs such as PyCharm and Android Studio
Not available; use Ctrl+J or
\
then Enter
For VS Code, Cursor, Windsurf, Alacritty, and Zed,
/terminal-setup
writes Shift+Enter and other keybindings into the terminal’s configuration file. In VS Code, Cursor, and Windsurf it also sets
terminal.integrated.mouseWheelScrollSensitivity
in the editor settings for smoother scrolling in
fullscreen mode
. Existing bindings and settings are left in place; if you see a message such as
VSCode terminal Shift+Enter key binding already configured
, no change was made. Run
/terminal-setup
directly in the host terminal rather than inside tmux or screen, since it needs to write to the host terminal’s configuration.
If you are running inside tmux, Shift+Enter also requires the
tmux configuration below
even when the outer terminal supports it.
To bind newline to a different key, or to swap behavior so Enter inserts a newline and Shift+Enter submits, map the
chat:newline
and
chat:submit
actions in your
keybindings file
.
​
Enable Option key shortcuts on macOS
Some Claude Code shortcuts use the Option key, such as Option+Enter for a newline or Option+P to switch models. On macOS, most terminals do not send Option as a modifier by default, so these shortcuts do nothing until you enable it. The terminal setting for this is usually labeled “Use Option as Meta Key”; Meta is the historical Unix name for the key now labeled Option or Alt.
Apple Terminal
iTerm2
VS Code
Open Settings → Profiles → Keyboard and check “Use Option as Meta Key”.
If you accepted Claude Code’s first-run prompt that offered “Option+Enter for newlines and visual bell”, this is already done. That prompt runs
/terminal-setup
for you, which enables Option as Meta and switches the audio bell to a visual screen flash in your Apple Terminal profile.
Open Settings → Profiles → Keys → General and set Left Option key and Right Option key to “Esc+”.
Running
/terminal-setup
in iTerm2 enables “Applications in terminal may access clipboard” under Settings → General → Selection so the
/copy
command can write to your system clipboard. The command detects iTerm2 even when run from inside tmux. Restart iTerm2 for the change to take effect.
Add
"terminal.integrated.macOptionIsMeta": true
to your VS Code settings.
For Ghostty, Kitty, and other terminals, look for an Option-as-Alt or Option-as-Meta setting in the terminal’s configuration file.
​
Get a terminal bell or notification
When Claude finishes a task or pauses for a permission prompt, it fires a notification event. Surfacing this as a terminal bell or desktop notification lets you switch to other work while a long task runs.
By default Claude Code sends a desktop notification only in Ghostty, Kitty, and iTerm2. In other terminals, set
preferredNotifChannel
to
"terminal_bell"
to ring the terminal bell instead, or configure a
Notification hook
for a custom sound or command.
The desktop notification reaches your local machine over SSH, so a remote session can still alert you. Ghostty and Kitty forward it to your OS notification center without further setup. iTerm2 requires you to enable forwarding:
1
Open iTerm2 notification settings
Go to Settings → Profiles → Terminal.
2
Enable alerts
Check “Notification Center Alerts”, then click “Filter Alerts” and enable “Send escape sequence-generated alerts”.
If notifications still do not appear, confirm that your terminal application has notification permission in your OS settings, and if you are running inside tmux,
enable passthrough
.
​
Play a sound with a Notification hook
In any terminal you can configure a
Notification hook
to play a sound or run a custom command when Claude needs your attention. Hooks run alongside the built-in notification rather than replacing it, so terminals that do not receive a desktop notification, such as Warp or the VS Code integrated terminal, can use a hook or set
preferredNotifChannel
to
"terminal_bell"
instead.
The example below plays a system sound on macOS. The linked guide has desktop notification commands for macOS, Linux, and Windows.
~/.claude/settings.json
{
"hooks"
: {
"Notification"
: [
{
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"afplay /System/Library/Sounds/Glass.aiff"
}]
}
]
}
}
​
Configure tmux
When Claude Code runs inside tmux, two things break by default: Shift+Enter submits instead of inserting a newline, and desktop notifications and the
progress bar
never reach the outer terminal. Add these lines to
~/.tmux.conf
, then run
tmux source-file ~/.tmux.conf
to apply them to the running server:
~/.tmux.conf
set
-g
allow-passthrough
on
set
-s
extended-keys
on
set
-as
terminal-features
'xterm*:extkeys'
The
allow-passthrough
line lets notifications and progress updates reach the outer terminal instead of being swallowed by tmux. The
extended-keys
lines let tmux distinguish Shift+Enter from plain Enter so the newline shortcut works.
​
Match the color theme
Use the
/theme
command, or the theme picker in
/config
, to choose a Claude Code theme that matches your terminal. Selecting the auto option detects your terminal’s light or dark background, so the theme follows OS appearance changes whenever your terminal does. Claude Code does not control the terminal’s own color scheme, which is set by the terminal application.
To customize what appears at the bottom of the interface, configure a
custom status line
that shows the current model, working directory, git branch, or other context.
​
Create a custom theme
Custom themes require Claude Code v2.1.118 or later.
In addition to the built-in presets,
/theme
lists any custom themes you have defined and any themes contributed by installed
plugins
. Select
New custom theme…
at the end of the list to create one interactively: you name the theme, then pick individual color tokens to override. Press
Ctrl+E
while a custom theme is highlighted to edit it.
Each custom theme is a JSON file in
~/.claude/themes/
. The filename without the
.json
extension is the theme’s slug, and selecting the theme stores
custom:<slug>
as your theme preference. The file has three optional fields:
Field
Type
Description
name
string
Display label shown in
/theme
. Defaults to the filename slug
base
string
Built-in preset the theme starts from:
dark
,
light
,
dark-daltonized
,
light-daltonized
,
dark-ansi
, or
light-ansi
. Defaults to
dark
overrides
object
Map of color token names to color values. Tokens not listed here fall through to the base preset
Color values accept
#rrggbb
,
#rgb
,
rgb(r,g,b)
,
ansi256(n)
, or
ansi:<name>
where
<name>
is one of the 16 standard ANSI color names such as
red
or
cyanBright
. Unknown tokens and invalid color values are ignored, so a typo cannot break rendering.
The following example defines a theme that keeps the dark preset but recolors the prompt accent, error text, and success text:
~/.claude/themes/dracula.json
{
"name"
:
"Dracula"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#bd93f9"
,
"error"
:
"#ff5555"
,
"success"
:
"#50fa7b"
}
}
Claude Code watches
~/.claude/themes/
and reloads when a file changes, so edits made in your editor apply to a running session without a restart.
The reference below covers the tokens you can set in
overrides
. The interactive editor in
/theme
shows the same tokens with a live preview, plus a few single-purpose accents such as onboarding screen colors that are omitted here.
Color token reference
The following example combines tokens from several of the groups below: the brand accent, the plan mode border, the diff backgrounds, and the fullscreen message background.
~/.claude/themes/midnight.json
{
"name"
:
"Midnight"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#a78bfa"
,
"planMode"
:
"#38bdf8"
,
"diffAdded"
:
"#14532d"
,
"diffRemoved"
:
"#7f1d1d"
,
"userMessageBackground"
:
"#1e1b4b"
}
}
​
Text and accent colors
Control the primary brand accent and the foreground text shades used throughout the interface.
Token
Controls
claude
Primary brand accent, used for the spinner and assistant label
text
Default foreground text
inverseText
Text drawn on top of a colored background, such as status badges
inactive
Secondary text such as hints, timestamps, and disabled items
subtle
Faint borders and de-emphasized secondary text
suggestion
Autocomplete suggestions and selection highlight in pickers
permission
Dialog borders, including permission prompts and pickers
remember
Memory and
CLAUDE.md
indicators
​
Status colors
Signal success, failure, and warning states across messages and indicators.
Token
Controls
success
Success messages and passing checks
error
Error messages and failures
warning
Warnings, caution messages, and the auto mode border
merged
Merged pull request status
​
Input box and mode indicators
Set the input box border color and the accent shown while a permission mode or indicator is active.
Token
Controls
promptBorder
Input box border in the default permission mode
planMode
Plan mode accent and border
autoAccept
Accept-edits mode accent and border
bashBorder
Input box border when entering a
!
shell command
ide
IDE connection indicator
fastMode
Fast mode indicator
​
Diff rendering
Color added and removed code in file edits and reviews.
Token
Controls
diffAdded
Background of added lines
diffRemoved
Background of removed lines
diffAddedDimmed
Background of unchanged context near added lines
diffRemovedDimmed
Background of unchanged context near removed lines
diffAddedWord
Word-level highlight within an added line
diffRemovedWord
Word-level highlight within a removed line
​
Fullscreen mode
Apply only in
fullscreen rendering mode
, where messages have a background fill.
Token
Controls
userMessageBackground
Background behind your messages in the transcript
userMessageBackgroundHover
Background behind a message while hovered or expanded
messageActionsBackground
Background behind the selected message when the action bar is open
bashMessageBackgroundColor
Background behind
!
shell command entries in the transcript
memoryBackgroundColor
Background behind
#
memory entries in the transcript
selectionBg
Background of text selected with the mouse
​
Usage meter and speaker labels
Adjust the bar shown in the
/usage
view and the labels that distinguish your messages from Claude’s.
Token
Controls
rate_limit_fill
Filled portion of the usage meter
rate_limit_empty
Unfilled portion of the usage meter
briefLabelYou
Color of the
You
label on your messages
briefLabelClaude
Color of the
Claude
label on assistant messages
​
Shimmer variants and subagent colors
Several tokens have a paired shimmer variant that supplies the lighter color used in the spinner’s animated gradient. Override the shimmer alongside its base token if the animation looks mismatched.
claude
and
claudeShimmer
warning
and
warningShimmer
permission
and
permissionShimmer
promptBorder
and
promptBorderShimmer
inactive
and
inactiveShimmer
fastMode
and
fastModeShimmer
Each
subagent
and parallel task is shown in one of eight named colors so you can tell them apart in the transcript. The token names follow the pattern
<color>_FOR_SUBAGENTS_ONLY
, where
<color>
is
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
, or
cyan
. Override these to change what each named color looks like. For example, a subagent with
color: blue
in its definition is drawn using the
blue_FOR_SUBAGENTS_ONLY
value.
The
ultrathink
and
ultraplan
keywords in the prompt input are rendered with a seven-color rainbow gradient. The token names follow the pattern
rainbow_<color>
and
rainbow_<color>_shimmer
, where
<color>
is
red
,
orange
,
yellow
,
green
,
blue
,
indigo
, or
violet
.
​
Switch to fullscreen rendering
If the display flickers or the scroll position jumps while Claude is working, switch to
fullscreen rendering mode
. It draws to a separate screen the terminal reserves for full-screen apps instead of appending to your normal scrollback, which keeps memory usage flat and adds mouse support for scrolling and selection. In this mode you scroll with the mouse or PageUp inside Claude Code rather than with your terminal’s native scrollback; see the
fullscreen page
for how to search and copy.
Run
/tui fullscreen
to switch in the current session with your conversation intact. To make it the default, set the
CLAUDE_CODE_NO_FLICKER
environment variable before starting Claude Code:
Bash and Zsh
PowerShell
~/.claude/settings.json
CLAUDE_CODE_NO_FLICKER
=
1
claude
​
Paste large content
When you paste more than 10,000 characters into the prompt, Claude Code collapses the input to a
[Pasted text]
placeholder so the input box stays usable. The full content is still sent to Claude when you submit.
The VS Code integrated terminal can drop characters from very large pastes before they reach Claude Code, so prefer file-based workflows there. For very large inputs such as entire files or long logs, write the content to a file and ask Claude to read it instead of pasting. This keeps the conversation transcript readable and lets Claude reference the file by path in later turns.
​
Edit prompts with Vim keybindings
Claude Code includes a Vim-style editing mode for the prompt input. Enable it through
/config
→ Editor mode, or by setting
editorMode
to
"vim"
in
~/.claude/settings.json
. Set Editor mode back to
normal
to turn it off.
Vim mode supports a subset of NORMAL- and VISUAL-mode motions and operators, such as
hjkl
navigation,
v
/
V
selection, and
d
/
c
/
y
with text objects. See the
Vim editor mode reference
for the full key table. Vim motions are not remappable through the keybindings file.
Pressing Enter still submits your prompt in INSERT mode, unlike standard Vim. Use
o
or
O
in NORMAL mode, or Ctrl+J, to insert a newline instead.
​
Related resources
Interactive mode
: full keyboard shortcut reference and the Vim key table
Keybindings
: remap any Claude Code shortcut, including Enter and Shift+Enter
Fullscreen rendering
: details on scrolling, search, and copy in fullscreen mode
Hooks guide
: more Notification hook examples for Linux and Windows
Troubleshooting
: fixes for issues outside terminal configuration
Was this page helpful?
Yes
No
Output styles
Fullscreen rendering
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/terminal-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Configure your terminal for Claude Code
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Configure your terminal for Claude Code
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code works in any terminal without configuration. This page is for when something specific is not behaving the way you expect. Find your symptom below. If everything already feels right, you do not need this page.
Shift+Enter submits instead of inserting a newline
Option-key shortcuts do nothing on macOS
No sound or alert when Claude finishes
You run Claude Code inside tmux
Display flickers or scrollback jumps
You want Vim keys in the prompt
This page is about getting your terminal to send the right signals to Claude Code. To change which keys Claude Code itself responds to, see
keybindings
instead.
​
Enter multiline prompts
Pressing Enter submits your message. To add a line break without submitting, press Ctrl+J, or type
\
and then press Enter. Both work in every terminal with no setup.
In most terminals you can also press Shift+Enter, but support varies by terminal emulator:
Terminal
Shift+Enter for newline
Ghostty, Kitty, iTerm2, WezTerm, Warp, Apple Terminal, Windows Terminal
Works without setup
VS Code, Cursor, Windsurf, Alacritty, Zed
Run
/terminal-setup
once
gnome-terminal, JetBrains IDEs such as PyCharm and Android Studio
Not available; use Ctrl+J or
\
then Enter
For VS Code, Cursor, Windsurf, Alacritty, and Zed,
/terminal-setup
writes Shift+Enter and other keybindings into the terminal’s configuration file. In VS Code, Cursor, and Windsurf it also sets
terminal.integrated.mouseWheelScrollSensitivity
in the editor settings for smoother scrolling in
fullscreen mode
. Existing bindings and settings are left in place; if you see a message such as
VSCode terminal Shift+Enter key binding already configured
, no change was made. Run
/terminal-setup
directly in the host terminal rather than inside tmux or screen, since it needs to write to the host terminal’s configuration.
If you are running inside tmux, Shift+Enter also requires the
tmux configuration below
even when the outer terminal supports it.
To bind newline to a different key, or to swap behavior so Enter inserts a newline and Shift+Enter submits, map the
chat:newline
and
chat:submit
actions in your
keybindings file
.
​
Enable Option key shortcuts on macOS
Some Claude Code shortcuts use the Option key, such as Option+Enter for a newline or Option+P to switch models. On macOS, most terminals do not send Option as a modifier by default, so these shortcuts do nothing until you enable it. The terminal setting for this is usually labeled “Use Option as Meta Key”; Meta is the historical Unix name for the key now labeled Option or Alt.
Apple Terminal
iTerm2
VS Code
Open Settings → Profiles → Keyboard and check “Use Option as Meta Key”.
If you accepted Claude Code’s first-run prompt that offered “Option+Enter for newlines and visual bell”, this is already done. That prompt runs
/terminal-setup
for you, which enables Option as Meta and switches the audio bell to a visual screen flash in your Apple Terminal profile.
Open Settings → Profiles → Keys → General and set Left Option key and Right Option key to “Esc+”.
Running
/terminal-setup
in iTerm2 enables “Applications in terminal may access clipboard” under Settings → General → Selection so the
/copy
command can write to your system clipboard. The command detects iTerm2 even when run from inside tmux. Restart iTerm2 for the change to take effect.
Add
"terminal.integrated.macOptionIsMeta": true
to your VS Code settings.
For Ghostty, Kitty, and other terminals, look for an Option-as-Alt or Option-as-Meta setting in the terminal’s configuration file.
​
Get a terminal bell or notification
When Claude finishes a task or pauses for a permission prompt, it fires a notification event. Surfacing this as a terminal bell or desktop notification lets you switch to other work while a long task runs.
By default Claude Code sends a desktop notification only in Ghostty, Kitty, and iTerm2. In other terminals, set
preferredNotifChannel
to
"terminal_bell"
to ring the terminal bell instead, or configure a
Notification hook
for a custom sound or command.
The desktop notification reaches your local machine over SSH, so a remote session can still alert you. Ghostty and Kitty forward it to your OS notification center without further setup. iTerm2 requires you to enable forwarding:
1
Open iTerm2 notification settings
Go to Settings → Profiles → Terminal.
2
Enable alerts
Check “Notification Center Alerts”, then click “Filter Alerts” and enable “Send escape sequence-generated alerts”.
If notifications still do not appear, confirm that your terminal application has notification permission in your OS settings, and if you are running inside tmux,
enable passthrough
.
​
Play a sound with a Notification hook
In any terminal you can configure a
Notification hook
to play a sound or run a custom command when Claude needs your attention. Hooks run alongside the built-in notification rather than replacing it, so terminals that do not receive a desktop notification, such as Warp or the VS Code integrated terminal, can use a hook or set
preferredNotifChannel
to
"terminal_bell"
instead.
The example below plays a system sound on macOS. The linked guide has desktop notification commands for macOS, Linux, and Windows.
~/.claude/settings.json
{
"hooks"
: {
"Notification"
: [
{
"hooks"
: [{
"type"
:
"command"
,
"command"
:
"afplay /System/Library/Sounds/Glass.aiff"
}]
}
]
}
}
​
Configure tmux
When Claude Code runs inside tmux, two things break by default: Shift+Enter submits instead of inserting a newline, and desktop notifications and the
progress bar
never reach the outer terminal. Add these lines to
~/.tmux.conf
, then run
tmux source-file ~/.tmux.conf
to apply them to the running server:
~/.tmux.conf
set
-g
allow-passthrough
on
set
-s
extended-keys
on
set
-as
terminal-features
'xterm*:extkeys'
The
allow-passthrough
line lets notifications and progress updates reach the outer terminal instead of being swallowed by tmux. The
extended-keys
lines let tmux distinguish Shift+Enter from plain Enter so the newline shortcut works.
​
Match the color theme
Use the
/theme
command, or the theme picker in
/config
, to choose a Claude Code theme that matches your terminal. Selecting the auto option detects your terminal’s light or dark background, so the theme follows OS appearance changes whenever your terminal does. Claude Code does not control the terminal’s own color scheme, which is set by the terminal application.
To customize what appears at the bottom of the interface, configure a
custom status line
that shows the current model, working directory, git branch, or other context.
​
Create a custom theme
Custom themes require Claude Code v2.1.118 or later.
In addition to the built-in presets,
/theme
lists any custom themes you have defined and any themes contributed by installed
plugins
. Select
New custom theme…
at the end of the list to create one interactively: you name the theme, then pick individual color tokens to override. Press
Ctrl+E
while a custom theme is highlighted to edit it.
Each custom theme is a JSON file in
~/.claude/themes/
. The filename without the
.json
extension is the theme’s slug, and selecting the theme stores
custom:<slug>
as your theme preference. The file has three optional fields:
Field
Type
Description
name
string
Display label shown in
/theme
. Defaults to the filename slug
base
string
Built-in preset the theme starts from:
dark
,
light
,
dark-daltonized
,
light-daltonized
,
dark-ansi
, or
light-ansi
. Defaults to
dark
overrides
object
Map of color token names to color values. Tokens not listed here fall through to the base preset
Color values accept
#rrggbb
,
#rgb
,
rgb(r,g,b)
,
ansi256(n)
, or
ansi:<name>
where
<name>
is one of the 16 standard ANSI color names such as
red
or
cyanBright
. Unknown tokens and invalid color values are ignored, so a typo cannot break rendering.
The following example defines a theme that keeps the dark preset but recolors the prompt accent, error text, and success text:
~/.claude/themes/dracula.json
{
"name"
:
"Dracula"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#bd93f9"
,
"error"
:
"#ff5555"
,
"success"
:
"#50fa7b"
}
}
Claude Code watches
~/.claude/themes/
and reloads when a file changes, so edits made in your editor apply to a running session without a restart.
The reference below covers the tokens you can set in
overrides
. The interactive editor in
/theme
shows the same tokens with a live preview, plus a few single-purpose accents such as onboarding screen colors that are omitted here.
Color token reference
The following example combines tokens from several of the groups below: the brand accent, the plan mode border, the diff backgrounds, and the fullscreen message background.
~/.claude/themes/midnight.json
{
"name"
:
"Midnight"
,
"base"
:
"dark"
,
"overrides"
: {
"claude"
:
"#a78bfa"
,
"planMode"
:
"#38bdf8"
,
"diffAdded"
:
"#14532d"
,
"diffRemoved"
:
"#7f1d1d"
,
"userMessageBackground"
:
"#1e1b4b"
}
}
​
Text and accent colors
Control the primary brand accent and the foreground text shades used throughout the interface.
Token
Controls
claude
Primary brand accent, used for the spinner and assistant label
text
Default foreground text
inverseText
Text drawn on top of a colored background, such as status badges
inactive
Secondary text such as hints, timestamps, and disabled items
subtle
Faint borders and de-emphasized secondary text
suggestion
Autocomplete suggestions and selection highlight in pickers
permission
Dialog borders, including permission prompts and pickers
remember
Memory and
CLAUDE.md
indicators
​
Status colors
Signal success, failure, and warning states across messages and indicators.
Token
Controls
success
Success messages and passing checks
error
Error messages and failures
warning
Warnings, caution messages, and the auto mode border
merged
Merged pull request status
​
Input box and mode indicators
Set the input box border color and the accent shown while a permission mode or indicator is active.
Token
Controls
promptBorder
Input box border in the default permission mode
planMode
Plan mode accent and border
autoAccept
Accept-edits mode accent and border
bashBorder
Input box border when entering a
!
shell command
ide
IDE connection indicator
fastMode
Fast mode indicator
​
Diff rendering
Color added and removed code in file edits and reviews.
Token
Controls
diffAdded
Background of added lines
diffRemoved
Background of removed lines
diffAddedDimmed
Background of unchanged context near added lines
diffRemovedDimmed
Background of unchanged context near removed lines
diffAddedWord
Word-level highlight within an added line
diffRemovedWord
Word-level highlight within a removed line
​
Fullscreen mode
Apply only in
fullscreen rendering mode
, where messages have a background fill.
Token
Controls
userMessageBackground
Background behind your messages in the transcript
userMessageBackgroundHover
Background behind a message while hovered or expanded
messageActionsBackground
Background behind the selected message when the action bar is open
bashMessageBackgroundColor
Background behind
!
shell command entries in the transcript
memoryBackgroundColor
Background behind
#
memory entries in the transcript
selectionBg
Background of text selected with the mouse
​
Usage meter and speaker labels
Adjust the bar shown in the
/usage
view and the labels that distinguish your messages from Claude’s.
Token
Controls
rate_limit_fill
Filled portion of the usage meter
rate_limit_empty
Unfilled portion of the usage meter
briefLabelYou
Color of the
You
label on your messages
briefLabelClaude
Color of the
Claude
label on assistant messages
​
Shimmer variants and subagent colors
Several tokens have a paired shimmer variant that supplies the lighter color used in the spinner’s animated gradient. Override the shimmer alongside its base token if the animation looks mismatched.
claude
and
claudeShimmer
warning
and
warningShimmer
permission
and
permissionShimmer
promptBorder
and
promptBorderShimmer
inactive
and
inactiveShimmer
fastMode
and
fastModeShimmer
Each
subagent
and parallel task is shown in one of eight named colors so you can tell them apart in the transcript. The token names follow the pattern
<color>_FOR_SUBAGENTS_ONLY
, where
<color>
is
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
, or
cyan
. Override these to change what each named color looks like. For example, a subagent with
color: blue
in its definition is drawn using the
blue_FOR_SUBAGENTS_ONLY
value.
The
ultrathink
and
ultraplan
keywords in the prompt input are rendered with a seven-color rainbow gradient. The token names follow the pattern
rainbow_<color>
and
rainbow_<color>_shimmer
, where
<color>
is
red
,
orange
,
yellow
,
green
,
blue
,
indigo
, or
violet
.
​
Switch to fullscreen rendering
If the display flickers or the scroll position jumps while Claude is working, switch to
fullscreen rendering mode
. It draws to a separate screen the terminal reserves for full-screen apps instead of appending to your normal scrollback, which keeps memory usage flat and adds mouse support for scrolling and selection. In this mode you scroll with the mouse or PageUp inside Claude Code rather than with your terminal’s native scrollback; see the
fullscreen page
for how to search and copy.
Run
/tui fullscreen
to switch in the current session with your conversation intact. To make it the default, set the
CLAUDE_CODE_NO_FLICKER
environment variable before starting Claude Code:
Bash and Zsh
PowerShell
~/.claude/settings.json
CLAUDE_CODE_NO_FLICKER
=
1
claude
​
Paste large content
When you paste more than 10,000 characters into the prompt, Claude Code collapses the input to a
[Pasted text]
placeholder so the input box stays usable. The full content is still sent to Claude when you submit.
The VS Code integrated terminal can drop characters from very large pastes before they reach Claude Code, so prefer file-based workflows there. For very large inputs such as entire files or long logs, write the content to a file and ask Claude to read it instead of pasting. This keeps the conversation transcript readable and lets Claude reference the file by path in later turns.
​
Edit prompts with Vim keybindings
Claude Code includes a Vim-style editing mode for the prompt input. Enable it through
/config
→ Editor mode, or by setting
editorMode
to
"vim"
in
~/.claude/settings.json
. Set Editor mode back to
normal
to turn it off.
Vim mode supports a subset of NORMAL- and VISUAL-mode motions and operators, such as
hjkl
navigation,
v
/
V
selection, and
d
/
c
/
y
with text objects. See the
Vim editor mode reference
for the full key table. Vim motions are not remappable through the keybindings file.
Pressing Enter still submits your prompt in INSERT mode, unlike standard Vim. Use
o
or
O
in NORMAL mode, or Ctrl+J, to insert a newline instead.
​
Related resources
Interactive mode
: full keyboard shortcut reference and the Vim key table
Keybindings
: remap any Claude Code shortcut, including Enter and Shift+Enter
Fullscreen rendering
: details on scrolling, search, and copy in fullscreen mode
Hooks guide
: more Notification hook examples for Linux and Windows
Troubleshooting
: fixes for issues outside terminal configuration
Was this page helpful?
Yes
No
Output styles
Fullscreen rendering
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/terminal-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Model configuration</title>
  <link>https://code.claude.com/docs/en/model-config</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/model-config</guid>
  <pubDate>Sat, 11 May 2024 00:00:00 +0000</pubDate>
  <category>Models</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Model configuration
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Model configuration
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Available models
For the
model
setting in Claude Code, you can configure either:
A
model alias
A
model name
Anthropic API: A full
model name
Bedrock: an inference profile ARN
Foundry: a deployment name
Vertex: a version name
ANTHROPIC_BASE_URL
changes where requests are sent, not which model answers them. To route Claude through an LLM gateway, see
LLM gateway configuration
.
​
Model aliases
Model aliases provide a convenient way to select model settings without
remembering exact version numbers:
Model alias
Behavior
default
Special value that clears any model override and reverts to the recommended model for your account type. Not itself a model alias
best
Uses the most capable available model, currently equivalent to
opus
sonnet
Uses the latest Sonnet model for daily coding tasks
opus
Uses the latest Opus model for complex reasoning tasks
haiku
Uses the fast and efficient Haiku model for simple tasks
sonnet[1m]
Uses Sonnet with a
1 million token context window
for long sessions
opus[1m]
Uses Opus with a
1 million token context window
for long sessions
opusplan
Special mode that uses
opus
during plan mode, then switches to
sonnet
for execution
On the Anthropic API and
Claude Platform on AWS
,
opus
resolves to Opus 4.7 and
sonnet
resolves to Sonnet 4.6. On Bedrock, Vertex, and Foundry,
opus
resolves to Opus 4.6 and
sonnet
resolves to Sonnet 4.5; newer models are available on those providers by selecting the full model name explicitly or setting
ANTHROPIC_DEFAULT_OPUS_MODEL
or
ANTHROPIC_DEFAULT_SONNET_MODEL
.
Aliases point to the recommended version for your provider and update over time. To pin to a specific version, use the full model name (for example,
claude-opus-4-7
) or set the corresponding environment variable like
ANTHROPIC_DEFAULT_OPUS_MODEL
.
Opus 4.7 requires Claude Code v2.1.111 or later. Run
claude update
to upgrade.
​
Setting your model
You can configure your model in several ways, listed in order of priority:
During session
- Use
/model <alias|name>
to switch immediately, or run
/model
with no argument to open the picker. The picker asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context
At startup
- Launch with
claude --model <alias|name>
Environment variable
- Set
ANTHROPIC_MODEL=<alias|name>
Settings
- Configure permanently in your settings file using the
model
field.
Your
/model
selection is saved to user settings and persists across restarts. As of v2.1.117, if the project’s
.claude/settings.json
pins a different model, Claude Code also writes your choice to
.claude/settings.local.json
so it continues to apply in that project after a restart. Managed settings take precedence and reapply on the next launch.
The
--model
flag and
ANTHROPIC_MODEL
environment variable apply only to the session you launch with them and are not saved. To run different models in different terminals at the same time, launch each one with its own
--model
flag rather than switching with
/model
.
When the active model at startup comes from project or managed settings rather than your own selection, the startup header shows which settings file set it. Run
/model
to override for the current session.
Example usage:
# Start with Opus
claude
--model
opus
# Switch to Sonnet during session
/model
sonnet
Example settings file:
{
"permissions"
: {
...
},
"model"
:
"opus"
}
​
Restrict model selection
Enterprise administrators can use
availableModels
in
managed or policy settings
to restrict which models users can select.
When
availableModels
is set, users cannot switch to models not in the list via
/model
,
--model
flag, or
ANTHROPIC_MODEL
environment variable.
{
"availableModels"
: [
"sonnet"
,
"haiku"
]
}
​
Default model behavior
The Default option in the model picker is not affected by
availableModels
. It always remains available and represents the system’s runtime default
based on the user’s subscription tier
.
Even with
availableModels: []
, users can still use Claude Code with the Default model for their tier.
​
Control the model users run on
The
model
setting is an initial selection, not enforcement. It sets which model is active when a session starts, but users can still open
/model
and pick Default, which resolves to the system default for their tier regardless of what
model
is set to.
To fully control the model experience, combine three settings:
availableModels
: restricts which named models users can switch to
model
: sets the initial model selection when a session starts
ANTHROPIC_DEFAULT_SONNET_MODEL
/
ANTHROPIC_DEFAULT_OPUS_MODEL
/
ANTHROPIC_DEFAULT_HAIKU_MODEL
: control what the Default option and the
sonnet
,
opus
, and
haiku
aliases resolve to
This example starts users on Sonnet 4.5, limits the picker to Sonnet and Haiku, and pins Default to resolve to Sonnet 4.5 rather than the latest release:
{
"model"
:
"claude-sonnet-4-5"
,
"availableModels"
: [
"claude-sonnet-4-5"
,
"haiku"
],
"env"
: {
"ANTHROPIC_DEFAULT_SONNET_MODEL"
:
"claude-sonnet-4-5"
}
}
Without the
env
block, a user who selects Default in the picker would get the latest Sonnet release, bypassing the version pin in
model
and
availableModels
.
​
Merge behavior
When
availableModels
is set at multiple levels, such as user settings and project settings, arrays are merged and deduplicated. To enforce a strict allowlist, set
availableModels
in managed or policy settings which take highest priority.
​
Mantle model IDs
When the
Bedrock Mantle endpoint
is enabled, entries in
availableModels
that start with
anthropic.
are added to the
/model
picker as custom options and routed to the Mantle endpoint. This is an exception to the alias-only matching described in
Pin models for third-party deployments
. The setting still restricts the picker to listed entries, so include the standard aliases alongside any Mantle IDs.
​
Special model behavior
​
default
model setting
The behavior of
default
depends on your account type:
Max and Team Premium
: defaults to Opus 4.7
Pro, Team Standard, Enterprise, and Anthropic API
: defaults to Sonnet 4.6
Bedrock, Vertex, and Foundry
: defaults to Sonnet 4.5
Claude Code may automatically fall back to Sonnet if you hit a usage threshold with Opus.
On April 23, 2026, the default model for Enterprise pay-as-you-go and Anthropic API users will change to Opus 4.7. To keep a different default, set
ANTHROPIC_MODEL
or the
model
field in
server-managed settings
.
​
opusplan
model setting
The
opusplan
model alias provides an automated hybrid approach:
In plan mode
- Uses
opus
for complex reasoning and architecture
decisions
In execution mode
- Automatically switches to
sonnet
for code generation
and implementation
This gives you the best of both worlds: Opus’s superior reasoning for planning,
and Sonnet’s efficiency for execution.
The plan-mode Opus phase runs with the standard 200K context window. The automatic 1M upgrade described in
Extended context
applies to the
opus
model setting and does not extend to
opusplan
.
​
Adjust effort level
Effort levels
control adaptive reasoning, which lets the model decide whether and how much to think on each step based on task complexity. Lower effort is faster and cheaper for straightforward tasks, while higher effort provides deeper reasoning for complex problems.
Effort is supported on Opus 4.7, Opus 4.6, and Sonnet 4.6. The available levels depend on the model:
Model
Levels
Opus 4.7
low
,
medium
,
high
,
xhigh
,
max
Opus 4.6 and Sonnet 4.6
low
,
medium
,
high
,
max
If you set a level the active model does not support, Claude Code falls back to the highest supported level at or below the one you set. For example,
xhigh
runs as
high
on Opus 4.6.
As of v2.1.117, the default effort is
xhigh
on Opus 4.7 and
high
on Opus 4.6 and Sonnet 4.6.
When you first run Opus 4.7, Claude Code applies
xhigh
even if you previously set a different effort level for Opus 4.6 or Sonnet 4.6. Run
/effort
again to choose a different level after switching.
low
,
medium
,
high
, and
xhigh
persist across sessions.
max
provides the deepest reasoning with no constraint on token spending and applies to the current session only, except when set through the
CLAUDE_CODE_EFFORT_LEVEL
environment variable.
​
Choose an effort level
Each level trades token spend against capability. The default suits most coding tasks; adjust when you want a different balance.
Level
When to use it
low
Reserve for short, scoped, latency-sensitive tasks that are not intelligence-sensitive
medium
Reduces token usage for cost-sensitive work that can trade off some intelligence
high
Balances token usage and intelligence. Use as a minimum for intelligence-sensitive work, or to reduce token spend relative to
xhigh
xhigh
Best results for most coding and agentic tasks. Recommended default on Opus 4.7
max
Can improve performance on demanding tasks but may show diminishing returns and is prone to overthinking. Test before adopting broadly
The effort scale is calibrated per model, so the same level name does not represent the same underlying value across models.
​
Use ultrathink for one-off deep reasoning
Include
ultrathink
anywhere in your prompt to request deeper reasoning on that turn without changing your session effort setting. Claude Code recognizes the keyword and adds an in-context instruction. The effort level sent to the API is unchanged. Other phrases such as “think”, “think hard”, and “think more” are passed through as ordinary prompt text and are not recognized as keywords.
​
Set the effort level
You can change effort through any of the following:
/effort
: run
/effort
with no arguments to open an interactive slider,
/effort
followed by a level name to set it directly, or
/effort auto
to reset to the model default
In
/model
: use left/right arrow keys to adjust the effort slider when selecting a model
--effort
flag
: pass a level name to set it for a single session when launching Claude Code
Environment variable
: set
CLAUDE_CODE_EFFORT_LEVEL
to a level name or
auto
Settings
: set
effortLevel
to
low
,
medium
,
high
, or
xhigh
in your settings file.
max
is
session-only
and is not accepted here
Skill and subagent frontmatter
: set
effort
in a
skill
or
subagent
markdown file to override the effort level when that skill or subagent runs
The environment variable takes precedence over all other methods, then your configured level, then the model default. Frontmatter effort applies when that skill or subagent is active, overriding the session level but not the environment variable.
The effort slider appears in
/model
when a supported model is selected. The current effort level is also displayed next to the logo and spinner, for example “with low effort”, so you can confirm which setting is active without opening
/model
.
​
Adaptive reasoning and fixed thinking budgets
Adaptive reasoning makes thinking optional on each step, so Claude can respond faster to routine prompts and reserve deeper thinking for steps that benefit from it. If you want Claude to think more or less often than the current level produces, you can say so directly in your prompt or in
CLAUDE.md
; the model responds to that guidance within its effort setting.
Opus 4.7 always uses adaptive reasoning. The fixed thinking budget mode and
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
do not apply to it.
On Opus 4.6 and Sonnet 4.6, you can set
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1
to revert to the previous fixed thinking budget controlled by
MAX_THINKING_TOKENS
. See
environment variables
.
​
Extended thinking
Extended thinking is the reasoning Claude emits before responding. On models that support
adaptive reasoning
, the effort level is the primary control for how much thinking happens; the settings below turn thinking on or off and control how it displays.
Control
How to set it
Toggle for the current session
Press
Option+T
on macOS or
Alt+T
on Windows and Linux
Set the global default
Run
/config
and toggle thinking mode. Saved as
alwaysThinkingEnabled
in
~/.claude/settings.json
Disable regardless of effort
Set
MAX_THINKING_TOKENS=0
. Other values apply only with a
fixed thinking budget
Thinking output is collapsed by default. Press
Ctrl+O
to toggle verbose mode and see the reasoning as gray italic text. Interactive sessions on the Anthropic API receive redacted thinking blocks by default, so set
showThinkingSummaries: true
in
settings
if you want the full summaries available when you expand. You are charged for all thinking tokens generated, even when collapsed or redacted.
​
Extended context
Opus 4.7, Opus 4.6, and Sonnet 4.6 support a
1 million token context window
for long sessions with large codebases.
Availability varies by model and plan. On Max, Team, and Enterprise plans, Opus is automatically upgraded to 1M context with no additional configuration. This applies to both Team Standard and Team Premium seats. Sonnet with 1M context is not part of the automatic upgrade and requires
extra usage
on every subscription plan, including Max.
Plan
Opus with 1M context
Sonnet with 1M context
Max, Team, and Enterprise
Included with subscription
Requires
extra usage
Pro
Requires
extra usage
Requires
extra usage
API and pay-as-you-go
Full access
Full access
To disable 1M context entirely, set
CLAUDE_CODE_DISABLE_1M_CONTEXT=1
. This removes 1M model variants from the model picker. See
environment variables
.
The 1M context window uses standard model pricing with no premium for tokens beyond 200K. For plans where extended context is included with your subscription, usage remains covered by your subscription. For plans that access extended context through extra usage, tokens are billed to extra usage.
If your account supports 1M context, the option appears in the model picker (
/model
) in the latest versions of Claude Code. If you don’t see it, try restarting your session.
You can also use the
[1m]
suffix with model aliases or full model names:
# Use the opus[1m] or sonnet[1m] alias
/model
opus[1m]
/model
sonnet[1m]
# Or append [1m] to a full model name
/model
claude-opus-4-7[1m]
​
Checking your current model
You can see which model you’re currently using in several ways:
In
status line
(if configured)
In
/status
, which also displays your account information.
​
Add a custom model option
Use
ANTHROPIC_CUSTOM_MODEL_OPTION
to add a single custom entry to the
/model
picker without replacing the built-in aliases. This is useful for testing model IDs that Claude Code does not list by default. For LLM gateway deployments, Claude Code can populate the picker from the gateway’s
/v1/models
endpoint when
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
is set, so this variable is needed only when discovery is disabled or does not return the model you want. See
LLM gateway model selection
.
This example sets all three variables to make a gateway-routed Opus deployment selectable:
export
ANTHROPIC_CUSTOM_MODEL_OPTION
=
"my-gateway/claude-opus-4-7"
export
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
=
"Opus via Gateway"
export
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
=
"Custom deployment routed through the internal LLM gateway"
The custom entry appears at the bottom of the
/model
picker.
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
and
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
are optional. If omitted, the model ID is used as the name and the description defaults to
Custom model (<model-id>)
.
Claude Code skips validation for the model ID set in
ANTHROPIC_CUSTOM_MODEL_OPTION
, so you can use any string your API endpoint accepts.
​
Environment variables
You can use the following environment variables, which must be full
model
names
(or equivalent for your API provider), to control the model names that the aliases map to.
Environment variable
Description
ANTHROPIC_DEFAULT_OPUS_MODEL
The model to use for
opus
, or for
opusplan
when Plan Mode is active.
ANTHROPIC_DEFAULT_SONNET_MODEL
The model to use for
sonnet
, or for
opusplan
when Plan Mode is not active.
ANTHROPIC_DEFAULT_HAIKU_MODEL
The model to use for
haiku
, or
background functionality
CLAUDE_CODE_SUBAGENT_MODEL
The model to use for
subagents
Note:
ANTHROPIC_SMALL_FAST_MODEL
is deprecated in favor of
ANTHROPIC_DEFAULT_HAIKU_MODEL
.
​
Pin models for third-party deployments
When deploying Claude Code through
Bedrock
,
Vertex AI
,
Foundry
, or
Claude Platform on AWS
, pin model versions before rolling out to users.
Without pinning, Claude Code uses model aliases (
sonnet
,
opus
,
haiku
) that resolve to the latest version. When Anthropic releases a new model that isn’t yet enabled in a user’s account, Bedrock and Vertex AI users see a notice and fall back to the previous version for that session, while Foundry users see errors because Foundry has no equivalent startup check.
Set all three model environment variables to specific version IDs as part of your initial setup. Pinning lets you control when your users move to a new model.
Use the following environment variables with version-specific model IDs for your provider:
Provider
Example
Bedrock
export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-7'
Vertex AI
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'
Foundry
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'
Apply the same pattern for
ANTHROPIC_DEFAULT_SONNET_MODEL
and
ANTHROPIC_DEFAULT_HAIKU_MODEL
. For current and legacy model IDs across all providers, see
Models overview
. To upgrade users to a new model version, update these environment variables and redeploy.
To enable
extended context
for a pinned model, append
[1m]
to the model ID in
ANTHROPIC_DEFAULT_OPUS_MODEL
or
ANTHROPIC_DEFAULT_SONNET_MODEL
:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7[1m]'
The
[1m]
suffix applies the 1M context window to all usage of that alias, including
opusplan
. Claude Code strips the suffix before sending the model ID to your provider. Only append
[1m]
when the underlying model supports 1M context, such as Opus 4.7 or Sonnet 4.6.
The
settings.availableModels
allowlist still applies when using third-party providers. Filtering matches on the model alias (
opus
,
sonnet
,
haiku
), not the provider-specific model ID.
​
Customize pinned model display and capabilities
When you pin a model on a third-party provider, the provider-specific ID appears as-is in the
/model
picker and Claude Code may not recognize which features the model supports. You can override the display name and declare capabilities with companion environment variables for each pinned model.
These variables take effect on third-party providers such as Bedrock, Vertex AI, and Foundry. The
_NAME
and
_DESCRIPTION
variables also take effect when
ANTHROPIC_BASE_URL
points to an
LLM gateway
. They have no effect when connecting directly to
api.anthropic.com
.
Environment variable
Description
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
Display name for the pinned Opus model in the
/model
picker. Defaults to the model ID when not set
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
Display description for the pinned Opus model in the
/model
picker. Defaults to
Custom Opus model
when not set
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
Comma-separated list of capabilities the pinned Opus model supports
The same
_NAME
,
_DESCRIPTION
, and
_SUPPORTED_CAPABILITIES
suffixes are available for
ANTHROPIC_DEFAULT_SONNET_MODEL
,
ANTHROPIC_DEFAULT_HAIKU_MODEL
, and
ANTHROPIC_CUSTOM_MODEL_OPTION
.
Claude Code enables features like
effort levels
and
extended thinking
by matching the model ID against known patterns. Provider-specific IDs such as Bedrock ARNs or custom deployment names often don’t match these patterns, leaving supported features disabled. Set
_SUPPORTED_CAPABILITIES
to tell Claude Code which features the model actually supports:
Capability value
Enables
effort
Effort levels
and the
/effort
command
xhigh_effort
The
xhigh
effort level
max_effort
The
max
effort level
thinking
Extended thinking
adaptive_thinking
Adaptive reasoning that dynamically allocates thinking based on task complexity
interleaved_thinking
Thinking between tool calls
When
_SUPPORTED_CAPABILITIES
is set, listed capabilities are enabled and unlisted capabilities are disabled for the matching pinned model. When the variable is unset, Claude Code falls back to built-in detection based on the model ID.
This example pins Opus to a Bedrock custom model ARN, sets a friendly name, and declares its capabilities:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'arn:aws:bedrock:us-east-1:123456789012:custom-model/abc'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
=
'Opus via Bedrock'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
=
'Opus 4.7 routed through a Bedrock custom endpoint'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
=
'effort,xhigh_effort,max_effort,thinking,adaptive_thinking,interleaved_thinking'
​
Override model IDs per version
The family-level environment variables above configure one model ID per family alias. If you need to map several versions within the same family to distinct provider IDs, use the
modelOverrides
setting instead.
modelOverrides
maps individual Anthropic model IDs to the provider-specific strings that Claude Code sends to your provider’s API. When a user selects a mapped model in the
/model
picker, Claude Code uses your configured value instead of the built-in default.
This lets enterprise administrators route each model version to a specific Bedrock inference profile ARN, Vertex AI version name, or Foundry deployment name for governance, cost allocation, or regional routing.
Set
modelOverrides
in your
settings file
:
{
"modelOverrides"
: {
"claude-opus-4-7"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-prod"
,
"claude-opus-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod"
,
"claude-sonnet-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-prod"
}
}
Keys must be Anthropic model IDs as listed in the
Models overview
. For dated model IDs, include the date suffix exactly as it appears there. Unknown keys are ignored.
Overrides replace the built-in model IDs that back each entry in the
/model
picker. On Bedrock, overrides take precedence over any inference profiles that Claude Code discovers automatically at startup. Values you supply directly through
ANTHROPIC_MODEL
,
--model
, or the
ANTHROPIC_DEFAULT_*_MODEL
environment variables are passed to the provider as-is and are not transformed by
modelOverrides
.
modelOverrides
works alongside
availableModels
. The allowlist is evaluated against the Anthropic model ID, not the override value, so an entry like
"opus"
in
availableModels
continues to match even when Opus versions are mapped to ARNs.
​
Prompt caching configuration
Claude Code automatically uses
prompt caching
to optimize performance and reduce costs. You can disable prompt caching globally or for specific model tiers:
Environment variable
Description
DISABLE_PROMPT_CACHING
Set to
1
to disable prompt caching for all models (takes precedence over per-model settings)
DISABLE_PROMPT_CACHING_HAIKU
Set to
1
to disable prompt caching for Haiku models only
DISABLE_PROMPT_CACHING_SONNET
Set to
1
to disable prompt caching for Sonnet models only
DISABLE_PROMPT_CACHING_OPUS
Set to
1
to disable prompt caching for Opus models only
These environment variables give you fine-grained control over prompt caching behavior. The global
DISABLE_PROMPT_CACHING
setting takes precedence over the model-specific settings, allowing you to quickly disable all caching when needed. The per-model settings are useful for selective control, such as when debugging specific models or working with cloud providers that may have different caching implementations.
Was this page helpful?
Yes
No
Sandboxing
Speed up responses with fast mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/model-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Model configuration
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Model and responses
Model configuration
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Available models
For the
model
setting in Claude Code, you can configure either:
A
model alias
A
model name
Anthropic API: A full
model name
Bedrock: an inference profile ARN
Foundry: a deployment name
Vertex: a version name
ANTHROPIC_BASE_URL
changes where requests are sent, not which model answers them. To route Claude through an LLM gateway, see
LLM gateway configuration
.
​
Model aliases
Model aliases provide a convenient way to select model settings without
remembering exact version numbers:
Model alias
Behavior
default
Special value that clears any model override and reverts to the recommended model for your account type. Not itself a model alias
best
Uses the most capable available model, currently equivalent to
opus
sonnet
Uses the latest Sonnet model for daily coding tasks
opus
Uses the latest Opus model for complex reasoning tasks
haiku
Uses the fast and efficient Haiku model for simple tasks
sonnet[1m]
Uses Sonnet with a
1 million token context window
for long sessions
opus[1m]
Uses Opus with a
1 million token context window
for long sessions
opusplan
Special mode that uses
opus
during plan mode, then switches to
sonnet
for execution
On the Anthropic API and
Claude Platform on AWS
,
opus
resolves to Opus 4.7 and
sonnet
resolves to Sonnet 4.6. On Bedrock, Vertex, and Foundry,
opus
resolves to Opus 4.6 and
sonnet
resolves to Sonnet 4.5; newer models are available on those providers by selecting the full model name explicitly or setting
ANTHROPIC_DEFAULT_OPUS_MODEL
or
ANTHROPIC_DEFAULT_SONNET_MODEL
.
Aliases point to the recommended version for your provider and update over time. To pin to a specific version, use the full model name (for example,
claude-opus-4-7
) or set the corresponding environment variable like
ANTHROPIC_DEFAULT_OPUS_MODEL
.
Opus 4.7 requires Claude Code v2.1.111 or later. Run
claude update
to upgrade.
​
Setting your model
You can configure your model in several ways, listed in order of priority:
During session
- Use
/model <alias|name>
to switch immediately, or run
/model
with no argument to open the picker. The picker asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context
At startup
- Launch with
claude --model <alias|name>
Environment variable
- Set
ANTHROPIC_MODEL=<alias|name>
Settings
- Configure permanently in your settings file using the
model
field.
Your
/model
selection is saved to user settings and persists across restarts. As of v2.1.117, if the project’s
.claude/settings.json
pins a different model, Claude Code also writes your choice to
.claude/settings.local.json
so it continues to apply in that project after a restart. Managed settings take precedence and reapply on the next launch.
The
--model
flag and
ANTHROPIC_MODEL
environment variable apply only to the session you launch with them and are not saved. To run different models in different terminals at the same time, launch each one with its own
--model
flag rather than switching with
/model
.
When the active model at startup comes from project or managed settings rather than your own selection, the startup header shows which settings file set it. Run
/model
to override for the current session.
Example usage:
# Start with Opus
claude
--model
opus
# Switch to Sonnet during session
/model
sonnet
Example settings file:
{
"permissions"
: {
...
},
"model"
:
"opus"
}
​
Restrict model selection
Enterprise administrators can use
availableModels
in
managed or policy settings
to restrict which models users can select.
When
availableModels
is set, users cannot switch to models not in the list via
/model
,
--model
flag, or
ANTHROPIC_MODEL
environment variable.
{
"availableModels"
: [
"sonnet"
,
"haiku"
]
}
​
Default model behavior
The Default option in the model picker is not affected by
availableModels
. It always remains available and represents the system’s runtime default
based on the user’s subscription tier
.
Even with
availableModels: []
, users can still use Claude Code with the Default model for their tier.
​
Control the model users run on
The
model
setting is an initial selection, not enforcement. It sets which model is active when a session starts, but users can still open
/model
and pick Default, which resolves to the system default for their tier regardless of what
model
is set to.
To fully control the model experience, combine three settings:
availableModels
: restricts which named models users can switch to
model
: sets the initial model selection when a session starts
ANTHROPIC_DEFAULT_SONNET_MODEL
/
ANTHROPIC_DEFAULT_OPUS_MODEL
/
ANTHROPIC_DEFAULT_HAIKU_MODEL
: control what the Default option and the
sonnet
,
opus
, and
haiku
aliases resolve to
This example starts users on Sonnet 4.5, limits the picker to Sonnet and Haiku, and pins Default to resolve to Sonnet 4.5 rather than the latest release:
{
"model"
:
"claude-sonnet-4-5"
,
"availableModels"
: [
"claude-sonnet-4-5"
,
"haiku"
],
"env"
: {
"ANTHROPIC_DEFAULT_SONNET_MODEL"
:
"claude-sonnet-4-5"
}
}
Without the
env
block, a user who selects Default in the picker would get the latest Sonnet release, bypassing the version pin in
model
and
availableModels
.
​
Merge behavior
When
availableModels
is set at multiple levels, such as user settings and project settings, arrays are merged and deduplicated. To enforce a strict allowlist, set
availableModels
in managed or policy settings which take highest priority.
​
Mantle model IDs
When the
Bedrock Mantle endpoint
is enabled, entries in
availableModels
that start with
anthropic.
are added to the
/model
picker as custom options and routed to the Mantle endpoint. This is an exception to the alias-only matching described in
Pin models for third-party deployments
. The setting still restricts the picker to listed entries, so include the standard aliases alongside any Mantle IDs.
​
Special model behavior
​
default
model setting
The behavior of
default
depends on your account type:
Max and Team Premium
: defaults to Opus 4.7
Pro, Team Standard, Enterprise, and Anthropic API
: defaults to Sonnet 4.6
Bedrock, Vertex, and Foundry
: defaults to Sonnet 4.5
Claude Code may automatically fall back to Sonnet if you hit a usage threshold with Opus.
On April 23, 2026, the default model for Enterprise pay-as-you-go and Anthropic API users will change to Opus 4.7. To keep a different default, set
ANTHROPIC_MODEL
or the
model
field in
server-managed settings
.
​
opusplan
model setting
The
opusplan
model alias provides an automated hybrid approach:
In plan mode
- Uses
opus
for complex reasoning and architecture
decisions
In execution mode
- Automatically switches to
sonnet
for code generation
and implementation
This gives you the best of both worlds: Opus’s superior reasoning for planning,
and Sonnet’s efficiency for execution.
The plan-mode Opus phase runs with the standard 200K context window. The automatic 1M upgrade described in
Extended context
applies to the
opus
model setting and does not extend to
opusplan
.
​
Adjust effort level
Effort levels
control adaptive reasoning, which lets the model decide whether and how much to think on each step based on task complexity. Lower effort is faster and cheaper for straightforward tasks, while higher effort provides deeper reasoning for complex problems.
Effort is supported on Opus 4.7, Opus 4.6, and Sonnet 4.6. The available levels depend on the model:
Model
Levels
Opus 4.7
low
,
medium
,
high
,
xhigh
,
max
Opus 4.6 and Sonnet 4.6
low
,
medium
,
high
,
max
If you set a level the active model does not support, Claude Code falls back to the highest supported level at or below the one you set. For example,
xhigh
runs as
high
on Opus 4.6.
As of v2.1.117, the default effort is
xhigh
on Opus 4.7 and
high
on Opus 4.6 and Sonnet 4.6.
When you first run Opus 4.7, Claude Code applies
xhigh
even if you previously set a different effort level for Opus 4.6 or Sonnet 4.6. Run
/effort
again to choose a different level after switching.
low
,
medium
,
high
, and
xhigh
persist across sessions.
max
provides the deepest reasoning with no constraint on token spending and applies to the current session only, except when set through the
CLAUDE_CODE_EFFORT_LEVEL
environment variable.
​
Choose an effort level
Each level trades token spend against capability. The default suits most coding tasks; adjust when you want a different balance.
Level
When to use it
low
Reserve for short, scoped, latency-sensitive tasks that are not intelligence-sensitive
medium
Reduces token usage for cost-sensitive work that can trade off some intelligence
high
Balances token usage and intelligence. Use as a minimum for intelligence-sensitive work, or to reduce token spend relative to
xhigh
xhigh
Best results for most coding and agentic tasks. Recommended default on Opus 4.7
max
Can improve performance on demanding tasks but may show diminishing returns and is prone to overthinking. Test before adopting broadly
The effort scale is calibrated per model, so the same level name does not represent the same underlying value across models.
​
Use ultrathink for one-off deep reasoning
Include
ultrathink
anywhere in your prompt to request deeper reasoning on that turn without changing your session effort setting. Claude Code recognizes the keyword and adds an in-context instruction. The effort level sent to the API is unchanged. Other phrases such as “think”, “think hard”, and “think more” are passed through as ordinary prompt text and are not recognized as keywords.
​
Set the effort level
You can change effort through any of the following:
/effort
: run
/effort
with no arguments to open an interactive slider,
/effort
followed by a level name to set it directly, or
/effort auto
to reset to the model default
In
/model
: use left/right arrow keys to adjust the effort slider when selecting a model
--effort
flag
: pass a level name to set it for a single session when launching Claude Code
Environment variable
: set
CLAUDE_CODE_EFFORT_LEVEL
to a level name or
auto
Settings
: set
effortLevel
to
low
,
medium
,
high
, or
xhigh
in your settings file.
max
is
session-only
and is not accepted here
Skill and subagent frontmatter
: set
effort
in a
skill
or
subagent
markdown file to override the effort level when that skill or subagent runs
The environment variable takes precedence over all other methods, then your configured level, then the model default. Frontmatter effort applies when that skill or subagent is active, overriding the session level but not the environment variable.
The effort slider appears in
/model
when a supported model is selected. The current effort level is also displayed next to the logo and spinner, for example “with low effort”, so you can confirm which setting is active without opening
/model
.
​
Adaptive reasoning and fixed thinking budgets
Adaptive reasoning makes thinking optional on each step, so Claude can respond faster to routine prompts and reserve deeper thinking for steps that benefit from it. If you want Claude to think more or less often than the current level produces, you can say so directly in your prompt or in
CLAUDE.md
; the model responds to that guidance within its effort setting.
Opus 4.7 always uses adaptive reasoning. The fixed thinking budget mode and
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
do not apply to it.
On Opus 4.6 and Sonnet 4.6, you can set
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1
to revert to the previous fixed thinking budget controlled by
MAX_THINKING_TOKENS
. See
environment variables
.
​
Extended thinking
Extended thinking is the reasoning Claude emits before responding. On models that support
adaptive reasoning
, the effort level is the primary control for how much thinking happens; the settings below turn thinking on or off and control how it displays.
Control
How to set it
Toggle for the current session
Press
Option+T
on macOS or
Alt+T
on Windows and Linux
Set the global default
Run
/config
and toggle thinking mode. Saved as
alwaysThinkingEnabled
in
~/.claude/settings.json
Disable regardless of effort
Set
MAX_THINKING_TOKENS=0
. Other values apply only with a
fixed thinking budget
Thinking output is collapsed by default. Press
Ctrl+O
to toggle verbose mode and see the reasoning as gray italic text. Interactive sessions on the Anthropic API receive redacted thinking blocks by default, so set
showThinkingSummaries: true
in
settings
if you want the full summaries available when you expand. You are charged for all thinking tokens generated, even when collapsed or redacted.
​
Extended context
Opus 4.7, Opus 4.6, and Sonnet 4.6 support a
1 million token context window
for long sessions with large codebases.
Availability varies by model and plan. On Max, Team, and Enterprise plans, Opus is automatically upgraded to 1M context with no additional configuration. This applies to both Team Standard and Team Premium seats. Sonnet with 1M context is not part of the automatic upgrade and requires
extra usage
on every subscription plan, including Max.
Plan
Opus with 1M context
Sonnet with 1M context
Max, Team, and Enterprise
Included with subscription
Requires
extra usage
Pro
Requires
extra usage
Requires
extra usage
API and pay-as-you-go
Full access
Full access
To disable 1M context entirely, set
CLAUDE_CODE_DISABLE_1M_CONTEXT=1
. This removes 1M model variants from the model picker. See
environment variables
.
The 1M context window uses standard model pricing with no premium for tokens beyond 200K. For plans where extended context is included with your subscription, usage remains covered by your subscription. For plans that access extended context through extra usage, tokens are billed to extra usage.
If your account supports 1M context, the option appears in the model picker (
/model
) in the latest versions of Claude Code. If you don’t see it, try restarting your session.
You can also use the
[1m]
suffix with model aliases or full model names:
# Use the opus[1m] or sonnet[1m] alias
/model
opus[1m]
/model
sonnet[1m]
# Or append [1m] to a full model name
/model
claude-opus-4-7[1m]
​
Checking your current model
You can see which model you’re currently using in several ways:
In
status line
(if configured)
In
/status
, which also displays your account information.
​
Add a custom model option
Use
ANTHROPIC_CUSTOM_MODEL_OPTION
to add a single custom entry to the
/model
picker without replacing the built-in aliases. This is useful for testing model IDs that Claude Code does not list by default. For LLM gateway deployments, Claude Code can populate the picker from the gateway’s
/v1/models
endpoint when
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
is set, so this variable is needed only when discovery is disabled or does not return the model you want. See
LLM gateway model selection
.
This example sets all three variables to make a gateway-routed Opus deployment selectable:
export
ANTHROPIC_CUSTOM_MODEL_OPTION
=
"my-gateway/claude-opus-4-7"
export
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
=
"Opus via Gateway"
export
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
=
"Custom deployment routed through the internal LLM gateway"
The custom entry appears at the bottom of the
/model
picker.
ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
and
ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
are optional. If omitted, the model ID is used as the name and the description defaults to
Custom model (<model-id>)
.
Claude Code skips validation for the model ID set in
ANTHROPIC_CUSTOM_MODEL_OPTION
, so you can use any string your API endpoint accepts.
​
Environment variables
You can use the following environment variables, which must be full
model
names
(or equivalent for your API provider), to control the model names that the aliases map to.
Environment variable
Description
ANTHROPIC_DEFAULT_OPUS_MODEL
The model to use for
opus
, or for
opusplan
when Plan Mode is active.
ANTHROPIC_DEFAULT_SONNET_MODEL
The model to use for
sonnet
, or for
opusplan
when Plan Mode is not active.
ANTHROPIC_DEFAULT_HAIKU_MODEL
The model to use for
haiku
, or
background functionality
CLAUDE_CODE_SUBAGENT_MODEL
The model to use for
subagents
Note:
ANTHROPIC_SMALL_FAST_MODEL
is deprecated in favor of
ANTHROPIC_DEFAULT_HAIKU_MODEL
.
​
Pin models for third-party deployments
When deploying Claude Code through
Bedrock
,
Vertex AI
,
Foundry
, or
Claude Platform on AWS
, pin model versions before rolling out to users.
Without pinning, Claude Code uses model aliases (
sonnet
,
opus
,
haiku
) that resolve to the latest version. When Anthropic releases a new model that isn’t yet enabled in a user’s account, Bedrock and Vertex AI users see a notice and fall back to the previous version for that session, while Foundry users see errors because Foundry has no equivalent startup check.
Set all three model environment variables to specific version IDs as part of your initial setup. Pinning lets you control when your users move to a new model.
Use the following environment variables with version-specific model IDs for your provider:
Provider
Example
Bedrock
export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-7'
Vertex AI
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'
Foundry
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'
Apply the same pattern for
ANTHROPIC_DEFAULT_SONNET_MODEL
and
ANTHROPIC_DEFAULT_HAIKU_MODEL
. For current and legacy model IDs across all providers, see
Models overview
. To upgrade users to a new model version, update these environment variables and redeploy.
To enable
extended context
for a pinned model, append
[1m]
to the model ID in
ANTHROPIC_DEFAULT_OPUS_MODEL
or
ANTHROPIC_DEFAULT_SONNET_MODEL
:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7[1m]'
The
[1m]
suffix applies the 1M context window to all usage of that alias, including
opusplan
. Claude Code strips the suffix before sending the model ID to your provider. Only append
[1m]
when the underlying model supports 1M context, such as Opus 4.7 or Sonnet 4.6.
The
settings.availableModels
allowlist still applies when using third-party providers. Filtering matches on the model alias (
opus
,
sonnet
,
haiku
), not the provider-specific model ID.
​
Customize pinned model display and capabilities
When you pin a model on a third-party provider, the provider-specific ID appears as-is in the
/model
picker and Claude Code may not recognize which features the model supports. You can override the display name and declare capabilities with companion environment variables for each pinned model.
These variables take effect on third-party providers such as Bedrock, Vertex AI, and Foundry. The
_NAME
and
_DESCRIPTION
variables also take effect when
ANTHROPIC_BASE_URL
points to an
LLM gateway
. They have no effect when connecting directly to
api.anthropic.com
.
Environment variable
Description
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
Display name for the pinned Opus model in the
/model
picker. Defaults to the model ID when not set
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
Display description for the pinned Opus model in the
/model
picker. Defaults to
Custom Opus model
when not set
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
Comma-separated list of capabilities the pinned Opus model supports
The same
_NAME
,
_DESCRIPTION
, and
_SUPPORTED_CAPABILITIES
suffixes are available for
ANTHROPIC_DEFAULT_SONNET_MODEL
,
ANTHROPIC_DEFAULT_HAIKU_MODEL
, and
ANTHROPIC_CUSTOM_MODEL_OPTION
.
Claude Code enables features like
effort levels
and
extended thinking
by matching the model ID against known patterns. Provider-specific IDs such as Bedrock ARNs or custom deployment names often don’t match these patterns, leaving supported features disabled. Set
_SUPPORTED_CAPABILITIES
to tell Claude Code which features the model actually supports:
Capability value
Enables
effort
Effort levels
and the
/effort
command
xhigh_effort
The
xhigh
effort level
max_effort
The
max
effort level
thinking
Extended thinking
adaptive_thinking
Adaptive reasoning that dynamically allocates thinking based on task complexity
interleaved_thinking
Thinking between tool calls
When
_SUPPORTED_CAPABILITIES
is set, listed capabilities are enabled and unlisted capabilities are disabled for the matching pinned model. When the variable is unset, Claude Code falls back to built-in detection based on the model ID.
This example pins Opus to a Bedrock custom model ARN, sets a friendly name, and declares its capabilities:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'arn:aws:bedrock:us-east-1:123456789012:custom-model/abc'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME
=
'Opus via Bedrock'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION
=
'Opus 4.7 routed through a Bedrock custom endpoint'
export
ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES
=
'effort,xhigh_effort,max_effort,thinking,adaptive_thinking,interleaved_thinking'
​
Override model IDs per version
The family-level environment variables above configure one model ID per family alias. If you need to map several versions within the same family to distinct provider IDs, use the
modelOverrides
setting instead.
modelOverrides
maps individual Anthropic model IDs to the provider-specific strings that Claude Code sends to your provider’s API. When a user selects a mapped model in the
/model
picker, Claude Code uses your configured value instead of the built-in default.
This lets enterprise administrators route each model version to a specific Bedrock inference profile ARN, Vertex AI version name, or Foundry deployment name for governance, cost allocation, or regional routing.
Set
modelOverrides
in your
settings file
:
{
"modelOverrides"
: {
"claude-opus-4-7"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-prod"
,
"claude-opus-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod"
,
"claude-sonnet-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-prod"
}
}
Keys must be Anthropic model IDs as listed in the
Models overview
. For dated model IDs, include the date suffix exactly as it appears there. Unknown keys are ignored.
Overrides replace the built-in model IDs that back each entry in the
/model
picker. On Bedrock, overrides take precedence over any inference profiles that Claude Code discovers automatically at startup. Values you supply directly through
ANTHROPIC_MODEL
,
--model
, or the
ANTHROPIC_DEFAULT_*_MODEL
environment variables are passed to the provider as-is and are not transformed by
modelOverrides
.
modelOverrides
works alongside
availableModels
. The allowlist is evaluated against the Anthropic model ID, not the override value, so an entry like
"opus"
in
availableModels
continues to match even when Opus versions are mapped to ARNs.
​
Prompt caching configuration
Claude Code automatically uses
prompt caching
to optimize performance and reduce costs. You can disable prompt caching globally or for specific model tiers:
Environment variable
Description
DISABLE_PROMPT_CACHING
Set to
1
to disable prompt caching for all models (takes precedence over per-model settings)
DISABLE_PROMPT_CACHING_HAIKU
Set to
1
to disable prompt caching for Haiku models only
DISABLE_PROMPT_CACHING_SONNET
Set to
1
to disable prompt caching for Sonnet models only
DISABLE_PROMPT_CACHING_OPUS
Set to
1
to disable prompt caching for Opus models only
These environment variables give you fine-grained control over prompt caching behavior. The global
DISABLE_PROMPT_CACHING
setting takes precedence over the model-specific settings, allowing you to quickly disable all caching when needed. The per-model settings are useful for selective control, such as when debugging specific models or working with cloud providers that may have different caching implementations.
Was this page helpful?
Yes
No
Sandboxing
Speed up responses with fast mode
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/model-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Use Claude Code Desktop</title>
  <link>https://code.claude.com/docs/en/desktop</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/desktop</guid>
  <pubDate>Fri, 10 May 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Use Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Use Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Desktop app has three tabs:
Chat
for conversations,
Cowork
for
Dispatch and longer agentic work
, and
Code
for software development. This page is the reference for the Code tab.
Download for macOS
Universal build for Intel and Apple Silicon
Download for Windows
For x64 processors
For Windows ARM64, download the
ARM64 installer
. The desktop app is not available on Linux; use the
CLI
instead.
After installing, launch Claude, sign in, and click the
Code
tab. The first time you open it on Windows, you need
Git for Windows
installed; restart the app after installing it. For a walkthrough of your first session, see the
Get started guide
.
In the Code tab, each conversation is a
session
: it has its own chat history, project folder, and code changes, independent of any other session. The sidebar lists your sessions and lets you run several in parallel. Within a session you can:
Review and comment on diffs
, then
watch the resulting PR through CI
Preview your running app
in an embedded browser while Claude verifies its own changes
Arrange panes
for the chat, diff, preview, terminal, and file editor side by side
Ask a
side question
that uses the session’s context without derailing it
Connect external tools
like GitHub, Slack, and Linear
Let Claude
open apps and control your screen
Run on your machine, in the
cloud
, or over
SSH
For
scheduled recurring work
,
keyboard shortcuts
, or
sending tasks from your phone
, see the linked pages and sections. If you already use the terminal-based CLI, see the
CLI comparison
for what carries over.
​
Start a session
Before you send your first message, configure four things in the prompt area:
Environment
: choose where Claude runs. Select
Local
for your machine,
Remote
for Anthropic-hosted cloud sessions, or an
SSH connection
for a remote machine you manage. See
environment configuration
.
Project folder
: select the folder or repository Claude works in. For remote sessions, you can add
multiple repositories
.
Model
: pick a
model
from the dropdown next to the send button. You can change this during the session.
Permission mode
: choose how much autonomy Claude has from the
mode selector
. You can change this during the session.
Type your task and press
Enter
to start. Each session tracks its own context and changes independently.
​
Work with code
Give Claude the right context, control how much it does on its own, and review what it changed.
​
Use the prompt box
Type what you want Claude to do and press
Enter
to send. Claude reads your project files, makes changes, and runs commands based on your
permission mode
. You can interrupt Claude at any point: click the stop button or type your correction and press
Enter
. Claude stops what it’s doing and adjusts based on your input.
The
+
button next to the prompt box gives you access to file attachments,
skills
,
connectors
, and
plugins
.
​
Add files and context to prompts
The prompt box supports two ways to bring in external context:
@mention files
: type
@
followed by a filename to add a file to the conversation context. Claude can then read and reference that file. @mention is not available in remote sessions.
Attach files
: attach images, PDFs, and other files to your prompt using the attachment button, or drag and drop files directly into the prompt. This is useful for sharing screenshots of bugs, design mockups, or reference documents.
​
Choose a permission mode
Permission modes control how much autonomy Claude has during a session: whether it asks before editing files, running commands, or both. You can switch modes at any time using the mode selector next to the send button. Start with Ask permissions to see exactly what Claude does, then move to Auto accept edits or Plan mode as you get comfortable.
Mode
Settings key
Behavior
Ask permissions
default
Claude asks before editing files or running commands. You see a diff and can accept or reject each change. Recommended for new users.
Auto accept edits
acceptEdits
Claude auto-accepts file edits and common filesystem commands like
mkdir
,
touch
, and
mv
, but still asks before running other terminal commands. Use this when you trust file changes and want faster iteration.
Plan mode
plan
Claude reads files and runs commands to explore, then proposes a plan without editing your source code. Good for complex tasks where you want to review the approach first.
Auto
auto
Claude executes all actions with background safety checks that verify alignment with your request. Reduces permission prompts while maintaining oversight. Enable in your Settings → Claude Code. See
availability requirements
below.
Bypass permissions
bypassPermissions
Claude runs without any permission prompts, equivalent to
--dangerously-skip-permissions
in the CLI. Enable in your Settings → Claude Code under “Allow bypass permissions mode”. Only use this in sandboxed containers or VMs. Enterprise admins can disable this option.
The
dontAsk
permission mode is available only in the
CLI
.
Auto mode is a research preview available on Max, Team, Enterprise, and API plans. It is not available on Pro plans or third-party providers. On Team, Enterprise, and API plans it requires Claude Sonnet 4.6, Opus 4.6, or Opus 4.7. On Max plans it requires Claude Opus 4.7.
Start complex tasks in Plan mode so Claude maps out an approach before making changes. Once you approve the plan, switch to Auto accept edits or Ask permissions to execute it. See
explore first, then plan, then code
for more on this workflow.
Remote sessions support Auto accept edits and Plan mode. Ask permissions is not available because remote sessions auto-accept file edits by default, and Bypass permissions is not available because the remote environment is already sandboxed.
Enterprise admins can restrict which permission modes are available. See
enterprise configuration
for details.
​
Preview your app
Claude can start a dev server and open an embedded browser to verify its changes. This works for frontend web apps as well as backend servers: Claude can test API endpoints, view server logs, and iterate on issues it finds. In most cases, Claude starts the server automatically after editing project files. You can also ask Claude to preview at any time. By default, Claude
auto-verifies
changes after every edit.
The preview pane can also open static HTML files, PDFs, images, and videos from your project. Click an HTML, PDF, image, or video path in the chat to open it in preview.
From the preview pane, you can:
Interact with your running app directly in the embedded browser
Watch Claude verify its own changes automatically: it takes screenshots, inspects the DOM, clicks elements, fills forms, and fixes issues it finds
Start or stop servers from the
Preview
dropdown in the session toolbar
Persist cookies and local storage across server restarts by selecting
Persist sessions
in the dropdown, so you don’t have to re-login during development
Edit the server configuration or stop all servers at once
Claude creates the initial server configuration based on your project. If your app uses a custom dev command, edit
.claude/launch.json
to match your setup. See
Configure preview servers
for the full reference.
To clear saved session data, toggle
Persist preview sessions
off in Settings → Claude Code. To disable preview entirely, toggle off
Preview
in Settings → Claude Code.
​
Review changes with diff view
After Claude makes changes to your code, the diff view lets you review modifications file by file before creating a pull request.
When Claude changes files, a diff stats indicator appears showing the number of lines added and removed, such as
+12 -1
. Click this indicator to open the diff viewer, which displays a file list on the left and the changes for each file on the right.
To comment on specific lines, click any line in the diff to open a comment box. Type your feedback and press
Enter
to add the comment. After adding comments to multiple lines, submit all comments at once:
macOS
: press
Cmd+Enter
Windows
: press
Ctrl+Enter
Claude reads your comments and makes the requested changes, which appear as a new diff you can review.
​
Review your code
In the diff view, click
Review code
in the top-right toolbar to ask Claude to evaluate the changes before you commit. Claude examines the current diffs and leaves comments directly in the diff view. You can respond to any comment or ask Claude to revise.
The review focuses on high-signal issues: compile errors, definite logic errors, security vulnerabilities, and obvious bugs. It does not flag style, formatting, pre-existing issues, or anything a linter would catch.
​
Monitor pull request status
After you open a pull request, a CI status bar appears in the session. Claude Code uses the GitHub CLI to poll check results and surface failures.
Auto-fix
: when enabled, Claude automatically attempts to fix failing CI checks by reading the failure output and iterating.
Auto-merge
: when enabled, Claude merges the PR once all checks pass. The merge method is squash. Auto-merge must be
enabled in your GitHub repository settings
for this to work.
Use the
Auto-fix
and
Auto-merge
toggles in the CI status bar to enable either option. Claude Code also sends a desktop notification when CI finishes. To archive the session automatically once the PR merges or closes, turn on
auto-archive
in Settings → Claude Code.
PR monitoring requires the
GitHub CLI (
gh
)
to be installed and authenticated on your machine. If
gh
is not installed, Desktop prompts you to install it the first time you try to create a PR.
​
Arrange your workspace
The Code tab is built around panes you can arrange in any layout: chat, diff, preview, terminal, file, plan, tasks, and subagent. Drag a pane by its header to reposition it, or drag a pane edge to resize it. Press
Cmd+\
on macOS or
Ctrl+\
on Windows to close the focused pane. Open additional panes from the
Views
menu in the session toolbar.
The pane layout, terminal, file editor, and view modes in this section require Claude Desktop v1.2581.0 or later. Open
Claude → Check for Updates
on macOS or
Help → Check for Updates
on Windows to update.
​
Run commands in the terminal
The integrated terminal lets you run commands alongside your session without switching to another app. Open it from the
Views
menu or press
Ctrl+`
on macOS or Windows. The terminal opens in your session’s working directory and shares the same environment as Claude, so commands like
npm test
or
git status
see the same files Claude is editing. To open a second terminal tab, click
+
in the terminal pane header or right-click a folder in the chat to choose
Open in terminal
. The terminal is available in local sessions only.
​
Open and edit files
Click a file path in the chat or diff viewer to open it in the file pane. HTML, PDF, image, and video paths open in the
preview pane
instead. Make spot edits and click
Save
to write them back. If the file changed on disk since you opened it, the pane warns you and lets you override or discard. Click
Discard
to revert your edits, or click the path in the pane header to copy the absolute path.
The file pane is available in local and SSH sessions. For remote sessions, ask Claude to make the change.
​
Open files in other apps
Right-click any file path in the chat, diff viewer, or file pane to open a context menu:
Attach as context
: add the file to your next prompt
Open in
: open the file in an installed editor such as VS Code, Cursor, or Zed
Show in Finder
on macOS,
Show in Explorer
on Windows: open the containing folder
Copy path
: copy the absolute path to your clipboard
​
Switch view modes
View modes control how much detail appears in the chat transcript. Switch modes from the
Transcript view
dropdown next to the send button, or press
Ctrl+O
on macOS or Windows to cycle through them.
Mode
What it shows
Normal
Tool calls collapsed into summaries, with full text responses
Verbose
Every tool call, file read, and intermediate step Claude takes
Summary
Only Claude’s final responses and the changes it made
Use Verbose when debugging why Claude took a particular action. Use Summary when you’re running multiple sessions and want to scan results quickly.
​
Keyboard shortcuts
Press
Cmd+/
on macOS or
Ctrl+/
on Windows to see all shortcuts available in the Code tab. On Windows, use
Ctrl
in place of
Cmd
for the shortcuts below. Session cycling, the terminal toggle, and the view-mode toggle use
Ctrl
on every platform.
Shortcut
Action
Cmd
/
Show keyboard shortcuts
Cmd
N
New session
Cmd
W
Close session
Ctrl
Tab
/
Ctrl
Shift
Tab
Next or previous session
Cmd
Shift
]
/
Cmd
Shift
[
Next or previous session
Esc
Stop Claude’s response
Cmd
Shift
D
Toggle diff pane
Cmd
Shift
P
Toggle preview pane
Cmd
Shift
S
Select an element in preview
Ctrl
`
Toggle terminal pane
Cmd
\
Close focused pane
Cmd
;
Open side chat
Ctrl
O
Cycle view modes
Cmd
Shift
M
Open permission mode menu
Cmd
Shift
I
Open model menu
Cmd
Shift
E
Open effort menu
1
–
9
Select item in an open menu
These shortcuts apply only to the Code tab. The terminal-based
interactive mode shortcuts
, such as
Shift+Tab
to cycle modes, do not apply in Desktop.
​
Check usage
Click the usage ring next to the model picker to see your current context window usage and your plan usage for the period. Context usage is per session; plan usage is shared across all your Claude Code surfaces.
​
Let Claude use your computer
Computer use lets Claude open your apps, control your screen, and work directly on your machine the way you would. Ask Claude to test a native app in a mobile simulator, interact with a desktop tool that has no CLI, or automate something that only works through a GUI.
Computer use is a research preview on macOS and Windows that requires a Pro or Max plan. It is not available on Team or Enterprise plans. The Claude Desktop app must be running.
Computer use is off by default.
Enable it in Settings
before Claude can control your screen. On macOS, you also need to grant Accessibility and Screen Recording permissions.
Unlike the
sandboxed Bash tool
, computer use runs on your actual desktop with access to whatever you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the
computer use safety guide
for best practices.
​
When computer use applies
Claude has several ways to interact with an app or service, and computer use is the broadest and slowest. It tries the most precise tool first:
If you have a
connector
for a service, Claude uses the connector.
If the task is a shell command, Claude uses Bash.
If the task is browser work and you have
Claude in Chrome
set up, Claude uses that.
If none of those apply, Claude uses computer use.
The
per-app access tiers
reinforce this: browsers are capped at view-only, and terminals and IDEs at click-only, steering Claude toward the dedicated tool even when computer use is active. Screen control is reserved for things nothing else can reach, like native apps, hardware control panels, mobile simulators, or proprietary tools without an API.
​
Enable computer use
Computer use is off by default. If you ask Claude to do something that needs it while it’s off, Claude tells you it could do the task if you enable computer use in Settings.
1
Update the desktop app
Make sure you have the latest version of Claude Desktop. Download or update at
claude.com/download
, then restart the app.
2
Turn on the toggle
In the desktop app, go to
Settings > General
(under
Desktop app
). Find the
Computer use
toggle and turn it on. On Windows, the toggle takes effect immediately and setup is complete. On macOS, continue to the next step.
If you don’t see the toggle, confirm you’re on macOS or Windows with a Pro or Max plan, then update and restart the app.
3
Grant macOS permissions
On macOS, grant two system permissions before the toggle takes effect:
Accessibility
: lets Claude click, type, and scroll
Screen Recording
: lets Claude see what’s on your screen
The Settings page shows the current status of each permission. If either is denied, click the badge to open the relevant System Settings pane.
​
App permissions
The first time Claude needs to use an app, a prompt appears in your session. Click
Allow for this session
or
Deny
. Approvals last for the current session, or 30 minutes in
Dispatch-spawned sessions
.
The prompt also shows what level of control Claude gets for that app. These tiers are fixed by app category and can’t be changed:
Tier
What Claude can do
Applies to
View only
See the app in screenshots
Browsers, trading platforms
Click only
Click and scroll, but not type or use keyboard shortcuts
Terminals, IDEs
Full control
Click, type, drag, and use keyboard shortcuts
Everything else
Apps with broad reach, like terminals, Finder or File Explorer, and System Settings or Settings, show an extra warning in the prompt so you know what approving them grants.
You can configure two settings in
Settings > General
(under
Desktop app
):
Denied apps
: add apps here to reject them without prompting. Claude may still affect a denied app indirectly through actions in an allowed app, but it can’t interact with the denied app directly.
Unhide apps when Claude finishes
: while Claude is working, your other windows are hidden so it interacts with only the approved app. When Claude finishes, hidden windows are restored unless you turn this setting off.
​
Manage sessions
Each session is an independent conversation with its own context and changes. You can run multiple sessions in parallel, branch off side chats, send work to the cloud, or let Dispatch start sessions for you from your phone.
​
Work in parallel with sessions
Click
+ New session
in the sidebar, or press
Cmd+N
on macOS or
Ctrl+N
on Windows, to work on multiple tasks in parallel. Press
Ctrl+Tab
and
Ctrl+Shift+Tab
to cycle through sessions in the sidebar. For Git repositories, each session gets its own isolated copy of your project using
Git worktrees
, so changes in one session don’t affect other sessions until you commit them.
To view two sessions at once, hold
Cmd
on macOS or
Ctrl
on Windows and click a session in the sidebar. The session opens in a second pane alongside the one you already have open. While the split is active, clicking another sidebar session replaces whichever pane has focus. Press
Cmd+\
on macOS or
Ctrl+\
on Windows to close the focused pane and return to a single session.
Worktrees are stored in
<project-root>/.claude/worktrees/
by default. You can change this to a custom directory in Settings → Claude Code under “Worktree location”. You can also set a branch prefix that gets prepended to every worktree branch name, which is useful for keeping Claude-created branches organized. To remove a worktree when you’re done, hover over the session in the sidebar and click the archive icon. To have sessions archive themselves when their pull request merges or closes, turn on
Auto-archive after PR merge or close
in Settings → Claude Code. Auto-archive only applies to local sessions that have finished running.
To include gitignored files like
.env
in new worktrees, create a
.worktreeinclude
file
in your project root.
Session isolation requires
Git
. Most Macs include Git by default. Run
git --version
in Terminal to check. On Windows, Git is required for the Code tab to work:
download Git for Windows
, install it, and restart the app. If you run into Git errors, ask Claude in the
Cowork tab
to help troubleshoot your setup.
Use the controls at the top of the sidebar to filter sessions by status, project, or environment, and to group sessions by project. To rename a session, click the session title in the toolbar at the top of the active session. To check context usage, see
Check usage
. When context fills up, Claude automatically summarizes the conversation and continues working. You can also type
/compact
to trigger summarization earlier and free up context space. See
the context window
for details on how compaction works.
The desktop app sends an OS notification when a Code session finishes a task and you aren’t currently viewing that session.
​
Ask a side question without derailing the session
A side chat lets you ask Claude a question that uses your session’s context but doesn’t add anything back to the main conversation. Use it when you want to understand a piece of code, check an assumption, or explore an idea without steering the session off course.
Press
Cmd+;
on macOS or
Ctrl+;
on Windows to open a side chat, or type
/btw
in the prompt box. The side chat can read everything in the main thread up to that point. When you’re done, close the side chat and continue the main session where you left off. Side chats are available in local and SSH sessions.
​
Watch background tasks
The tasks pane shows the background work running inside the current session: subagents, background shell commands, and workflows. Open it from the
Views
menu or drag it into your layout.
Click any entry to see its output in the subagent pane or stop it. To see what other sessions are doing, use the
sidebar
.
​
Run long-running tasks remotely
For large refactors, test suites, migrations, or other long-running tasks, select
Remote
instead of
Local
when starting a session. Remote sessions run on Anthropic’s cloud infrastructure and continue even if you close the app or shut down your computer. Check back anytime to see progress or steer Claude in a different direction. You can also monitor remote sessions from
claude.ai/code
or the Claude iOS app.
Remote sessions also support multiple repositories. After selecting a cloud environment, click the
+
button next to the repo pill to add additional repositories to the session. Each repo gets its own branch selector. This is useful for tasks that span multiple codebases, such as updating a shared library and its consumers.
See
Claude Code on the web
for more on how remote sessions work.
​
Continue in another surface
The
Continue in
menu, accessible from the VS Code icon in the bottom right of the session toolbar, lets you move your session to another surface:
Claude Code on the Web
: sends your local session to continue running remotely. Desktop pushes your branch, generates a summary of the conversation, and creates a new remote session with the full context. You can then choose to archive the local session or keep it. This requires a clean working tree, and is not available for SSH sessions.
Your IDE
: opens your project in a supported IDE at the current working directory.
​
Sessions from Dispatch
Dispatch
is a persistent conversation with Claude that lives in the
Cowork
tab. You message Dispatch a task, and it decides how to handle it.
A task can end up as a Code session in two ways: you ask for one directly, such as “open a Claude Code session and fix the login bug”, or Dispatch decides the task is development work and spawns one on its own. Tasks that typically route to Code include fixing bugs, updating dependencies, running tests, or opening pull requests. Research, document editing, and spreadsheet work stay in Cowork.
Either way, the Code session appears in the Code tab’s sidebar with a
Dispatch
badge. You get a push notification on your phone when it finishes or needs your approval.
If you have
computer use
enabled, Dispatch-spawned Code sessions can use it too. App approvals in those sessions expire after 30 minutes and re-prompt, rather than lasting the full session like regular Code sessions.
For setup, pairing, and Dispatch settings, see the
Dispatch help article
. Dispatch requires a Pro or Max plan and is not available on Team or Enterprise plans.
Dispatch is one of several ways to work with Claude when you’re away from your terminal. See
Platforms and integrations
to compare it with Remote Control, Channels, Slack, and scheduled tasks.
​
Extend Claude Code
Connect external services, add reusable workflows, customize Claude’s behavior, and configure preview servers. To manage connectors, skills, and plugins in one place, click
Customize
in the sidebar.
​
Connect external tools
For local and
SSH
sessions, click the
+
button next to the prompt box and select
Connectors
to add integrations like Google Calendar, Slack, GitHub, Linear, Notion, and more. You can add connectors before or during a session. The
+
button is not available in remote sessions, but
routines
configure connectors at routine creation time.
To manage or disconnect connectors, go to Settings → Connectors in the desktop app, or select
Manage connectors
from the Connectors menu in the prompt box.
Once connected, Claude can read your calendar, send messages, create issues, and interact with your tools directly. You can ask Claude what connectors are configured in your session.
Connectors are
MCP servers
with a graphical setup flow. Use them for quick integration with supported services. For integrations not listed in Connectors, add MCP servers manually via
settings files
. You can also
create custom connectors
.
​
Use skills
Skills
extend what Claude can do. Claude loads them automatically when relevant, or you can invoke one directly: type
/
in the prompt box or click the
+
button and select
Slash commands
to browse what’s available. This includes
built-in commands
, your
custom skills
, project skills from your codebase, and skills from any
installed plugins
. Select one and it appears highlighted in the input field. Type your task after it and send as usual.
​
Install plugins
Plugins
are reusable packages that add skills, agents, hooks, MCP servers, and LSP configurations to Claude Code. You can install plugins from the desktop app without using the terminal.
For local and
SSH
sessions, click the
+
button next to the prompt box and select
Plugins
to see your installed plugins and their skills. To add a plugin, select
Add plugin
from the submenu to open the plugin browser, which shows available plugins from your configured
marketplaces
including the official Anthropic marketplace. Select
Manage plugins
to enable, disable, or uninstall plugins.
Plugins can be scoped to your user account, a specific project, or local-only. If your organization manages plugins centrally, those plugins are available in desktop sessions the same way they are in the CLI. Plugins are not available for remote sessions. For the full plugin reference including creating your own plugins, see
plugins
.
​
Configure preview servers
Claude automatically detects your dev server setup and stores the configuration in
.claude/launch.json
at the root of the folder you selected when starting the session. Preview uses this folder as its working directory, so if you selected a parent folder, subfolders with their own dev servers won’t be detected automatically. To work with a subfolder’s server, either start a session in that folder directly or add a configuration manually.
To customize how your server starts, for example to use
yarn dev
instead of
npm run dev
or to change the port, edit the file manually or click
Edit configuration
in the Preview dropdown to open it in your code editor. The file supports JSON with comments.
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"my-app"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"dev"
],
"port"
:
3000
}
]
}
You can define multiple configurations to run different servers from the same project, such as a frontend and an API. See the
examples
below.
​
Auto-verify changes
When
autoVerify
is enabled, Claude automatically verifies code changes after editing files. It takes screenshots, checks for errors, and confirms changes work before completing its response.
Auto-verify is on by default. Disable it per-project by adding
"autoVerify": false
to
.claude/launch.json
, or toggle it from the
Preview
dropdown menu.
{
"version"
:
"0.0.1"
,
"autoVerify"
:
false
,
"configurations"
: [
...
]
}
When disabled, preview tools are still available and you can ask Claude to verify at any time. Auto-verify makes it automatic after every edit.
​
Configuration fields
Each entry in the
configurations
array accepts the following fields:
Field
Type
Description
name
string
A unique identifier for this server
runtimeExecutable
string
The command to run, such as
npm
,
yarn
, or
node
runtimeArgs
string[]
Arguments passed to
runtimeExecutable
, such as
["run", "dev"]
port
number
The port your server listens on. Defaults to 3000
cwd
string
Working directory relative to your project root. Defaults to the project root. Use
${workspaceFolder}
to reference the project root explicitly
env
object
Additional environment variables as key-value pairs, such as
{ "NODE_ENV": "development" }
. Don’t put secrets here since this file is committed to your repo. To pass secrets to your dev server, set them in the
local environment editor
instead.
autoPort
boolean
How to handle port conflicts. See below
program
string
A script to run with
node
. See
when to use
program
vs
runtimeExecutable
args
string[]
Arguments passed to
program
. Only used when
program
is set
When to use
program
vs
runtimeExecutable
Use
runtimeExecutable
with
runtimeArgs
to start a dev server through a package manager. For example,
"runtimeExecutable": "npm"
with
"runtimeArgs": ["run", "dev"]
runs
npm run dev
.
Use
program
when you have a standalone script you want to run with
node
directly. For example,
"program": "server.js"
runs
node server.js
. Pass additional flags with
args
.
​
Port conflicts
The
autoPort
field controls what happens when your preferred port is already in use:
true
: Claude finds and uses a free port automatically. Suitable for most dev servers.
false
: Claude fails with an error. Use this when your server must use a specific port, such as for OAuth callbacks or CORS allowlists.
Not set (default)
: Claude asks whether the server needs that exact port, then saves your answer.
When Claude picks a different port, it passes the assigned port to your server via the
PORT
environment variable.
​
Examples
These configurations show common setups for different project types:
Next.js
Multiple servers
Node.js script
This configuration runs a Next.js app using Yarn on port 3000:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"web"
,
"runtimeExecutable"
:
"yarn"
,
"runtimeArgs"
: [
"dev"
],
"port"
:
3000
}
]
}
For a monorepo with a frontend and an API server, define multiple configurations. The frontend uses
autoPort: true
so it picks a free port if 3000 is taken, while the API server requires port 8080 exactly:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"frontend"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"dev"
],
"cwd"
:
"apps/web"
,
"port"
:
3000
,
"autoPort"
:
true
},
{
"name"
:
"api"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"start"
],
"cwd"
:
"server"
,
"port"
:
8080
,
"env"
: {
"NODE_ENV"
:
"development"
},
"autoPort"
:
false
}
]
}
To run a Node.js script directly instead of using a package manager command, use the
program
field:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"server"
,
"program"
:
"server.js"
,
"args"
: [
"--verbose"
],
"port"
:
4000
}
]
}
​
Environment configuration
The environment you pick when
starting a session
determines where Claude executes and how you connect:
Local
: runs on your machine with direct access to your files
Remote
: runs on Anthropic’s cloud infrastructure. Sessions continue even if you close the app.
SSH
: runs on a remote machine you connect to over SSH, such as your own servers, cloud VMs, or dev containers
​
Local sessions
The desktop app does not always inherit your full shell environment. On macOS, when you launch the app from the Dock or Finder, it reads your shell profile, such as
~/.zshrc
or
~/.bashrc
, to extract
PATH
and a fixed set of Claude Code variables, but other variables you export there are not picked up. On Windows, the app inherits user and system environment variables but does not read PowerShell profiles.
To set environment variables for local sessions and dev servers on any platform, open the environment dropdown in the prompt box, hover over
Local
, and click the gear icon to open the local environment editor. Variables you save here are stored encrypted on your machine and apply to every local session and preview server you start. You can also add variables to the
env
key in your
~/.claude/settings.json
file, though these reach Claude sessions only and not dev servers. See
environment variables
for the full list of supported variables.
Extended thinking
is enabled by default, which improves performance on complex reasoning tasks but uses additional tokens. To disable thinking entirely, set
MAX_THINKING_TOKENS
to
0
in the local environment editor. On models with
adaptive reasoning
, any other
MAX_THINKING_TOKENS
value is ignored because adaptive reasoning controls thinking depth instead. On Opus 4.6 and Sonnet 4.6, set
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
to
1
to use a fixed thinking budget; Opus 4.7 always uses adaptive reasoning and has no fixed-budget mode.
​
Remote sessions
Remote sessions continue in the background even if you close the app. Usage counts toward your
subscription plan limits
with no separate compute charges.
You can create custom cloud environments with different network access levels and environment variables. Select the environment dropdown when starting a remote session and choose
Add environment
. See
the cloud environment
for details on configuring network access and environment variables.
​
SSH sessions
SSH sessions let you run Claude Code on a remote machine while using the desktop app as your interface. This is useful for working with codebases that live on cloud VMs, dev containers, or servers with specific hardware or dependencies.
To add an SSH connection, click the environment dropdown before starting a session and select
+ Add SSH connection
. The dialog asks for:
Name
: a friendly label for this connection
SSH Host
:
user@hostname
or a host defined in
~/.ssh/config
SSH Port
: defaults to 22 if left empty, or uses the port from your SSH config
Identity File
: path to your private key, such as
~/.ssh/id_rsa
. Leave empty to use the default key or your SSH config.
Once added, the connection appears in the environment dropdown. Select it to start a session on that machine. Claude runs on the remote machine with access to its files and tools.
The remote machine must run Linux or macOS. Desktop installs Claude Code on the remote machine automatically the first time you connect. Once connected, SSH sessions support permission modes, connectors, plugins, and MCP servers.
​
Pre-configure SSH connections for your team
Administrators can distribute SSH connections to team members by adding
sshConfigs
to a
managed settings
file. Connections defined this way appear in each user’s environment dropdown automatically and are shown as managed, so users can select them but cannot edit or delete them in the app.
The following example pre-configures a single connection that opens in
~/projects
on the remote host:
{
"sshConfigs"
: [
{
"id"
:
"shared-dev-vm"
,
"name"
:
"Shared Dev VM"
,
"sshHost"
:
"user@dev.example.com"
,
"sshPort"
:
22
,
"sshIdentityFile"
:
"~/.ssh/id_ed25519"
,
"startDirectory"
:
"~/projects"
}
]
}
Each entry requires
id
,
name
, and
sshHost
. The
sshPort
,
sshIdentityFile
, and
startDirectory
fields are optional. Users can also add
sshConfigs
to their own
~/.claude/settings.json
, which is where connections added through the dialog are stored.
​
Restrict which SSH hosts users can connect to
Administrators can limit Desktop’s SSH sessions to an approved set of hosts by adding
sshHostAllowlist
to a
managed settings
file. When set, users can only connect to hosts whose resolved hostname matches one of the patterns. Set it to an empty array to disable SSH sessions entirely.
The following example allows connections to any host under
devboxes.example.com
and to a single named bastion host:
{
"sshHostAllowlist"
: [
"*.devboxes.example.com"
,
"bastion.example.com"
]
}
Patterns are case-insensitive.
*
matches any host, and
*.example.com
matches
example.com
and any subdomain. Anything else is an exact match. The check runs against the hostname after
~/.ssh/config
resolution via
ssh -G
, so
Host
aliases and
ProxyCommand
/
ProxyJump
entries are permitted as long as the resolved
HostName
matches.
sshHostAllowlist
is read from managed settings only; values in user or project settings are ignored. Only the Claude Desktop app honors this setting; the Claude Code CLI and IDE extensions do not read it, and it does not restrict
ssh
commands run through the Bash tool. It governs which hosts the Desktop app connects to, not network egress, so pair it with your organization’s network or zero-trust controls if you need a hard boundary.
​
Enterprise configuration
Organizations on Team or Enterprise plans can manage desktop app behavior through admin console controls, managed settings files, and device management policies.
​
Admin console controls
These settings are configured through the
admin settings console
:
Code in the desktop
: control whether users in your organization can access Claude Code in the desktop app
Code in the web
: enable or disable
web sessions
for your organization
Remote Control
: enable or disable
Remote Control
for your organization
Disable Bypass permissions mode
: prevent users in your organization from enabling bypass permissions mode
​
Managed settings
Managed settings override project and user settings and apply when Desktop spawns CLI sessions. You can set these keys in your organization’s
managed settings
file or push them remotely through the admin console.
Key
Description
permissions.disableBypassPermissionsMode
set to
"disable"
to prevent users from enabling Bypass permissions mode.
disableAutoMode
set to
"disable"
to prevent users from enabling
Auto
mode. Removes Auto from the mode selector. Also accepted under
permissions
.
autoMode
customize what the auto mode classifier trusts and blocks across your organization. See
Configure auto mode
.
sshConfigs
pre-configure
SSH connections
that appear in the environment dropdown. Users cannot edit or delete managed connections.
sshHostAllowlist
restrict
SSH sessions
to hosts whose resolved hostname matches one of these patterns. An empty array disables SSH sessions. Read from managed settings only.
managedMcpServers
push MCP server configurations to all users in a third-party deployment. Each entry specifies a transport of
"http"
,
"sse"
, or
"stdio"
, connection details, and optionally a
toolPolicy
map that restricts which tools in that server users can invoke. Available in third-party (3P) Desktop deployments only.
A managed settings file deployed to disk on each machine applies to Desktop sessions. Managed settings pushed remotely through the admin console currently reach CLI and IDE sessions only, so for Desktop deployments either distribute the file via MDM or use the
admin console controls
above.
permissions.disableBypassPermissionsMode
and
disableAutoMode
also work in user and project settings, but placing them in managed settings prevents users from overriding them.
autoMode
is read from user settings,
.claude/settings.local.json
, and managed settings, but not from the checked-in
.claude/settings.json
: a cloned repo cannot inject its own classifier rules. For the complete list of managed-only settings including
allowManagedPermissionRulesOnly
and
allowManagedHooksOnly
, see
managed-only settings
.
​
Device management policies
IT teams can manage the desktop app through MDM on macOS or group policy on Windows. Available policies include enabling or disabling the Claude Code feature, controlling auto-updates, and setting a custom deployment URL.
macOS
: configure via
com.anthropic.Claude
preference domain using tools like Jamf or Kandji
Windows
: configure via registry at
SOFTWARE\Policies\Claude
​
Authentication and SSO
Enterprise organizations can require SSO for all users. See
authentication
for plan-level details and
Setting up SSO
for SAML and OIDC configuration.
​
Data handling
Claude Code processes your code locally in local sessions or on Anthropic’s cloud infrastructure in remote sessions. Conversations and code context are sent to Anthropic’s API for processing. See
data handling
for details on data retention, privacy, and compliance.
​
Deployment
Desktop can be distributed through enterprise deployment tools:
macOS
: distribute via MDM such as Jamf or Kandji using the
.dmg
installer
Windows
: deploy via MSIX package or
.exe
installer. See
Deploy Claude Desktop for Windows
for enterprise deployment options including silent installation
For network configuration such as proxy settings, firewall allowlisting, and LLM gateways, see
network configuration
.
For the full enterprise configuration reference, see the
enterprise configuration guide
.
​
Coming from the CLI?
If you already use the Claude Code CLI, Desktop runs the same underlying engine with a graphical interface. You can run both simultaneously on the same machine, even on the same project. Each maintains separate session history, but they share configuration and project memory via CLAUDE.md files.
To move a CLI session into Desktop, run
/desktop
in the terminal. Claude saves your session and opens it in the desktop app, then exits the CLI. This command is available on macOS and Windows only.
When to use Desktop vs CLI: use Desktop when you want to manage parallel sessions in one window, arrange panes side by side, or review changes visually. Use the CLI when you need scripting, automation, or prefer a terminal workflow.
​
CLI flag equivalents
This table shows the desktop app equivalent for common CLI flags. Flags not listed have no desktop equivalent because they are designed for scripting or automation.
CLI
Desktop equivalent
--model sonnet
Model dropdown next to the send button
--resume
,
--continue
Click a session in the sidebar
--permission-mode
Mode selector next to the send button
--dangerously-skip-permissions
Bypass permissions mode. Enable in Settings → Claude Code → “Allow bypass permissions mode”. Enterprise admins can disable this setting.
--add-dir
Add multiple repos with the
+
button in remote sessions
--allowedTools
,
--disallowedTools
No per-session equivalent. Permission rules in
settings files
still apply.
--verbose
Verbose view mode
in the Transcript view dropdown
--print
,
--output-format
Not available. Desktop is interactive only.
ANTHROPIC_MODEL
env var
Model dropdown next to the send button
MAX_THINKING_TOKENS
env var
Set in the local environment editor. See
environment configuration
.
​
Shared configuration
Desktop and CLI read the same configuration files, so your setup carries over:
CLAUDE.md
and
CLAUDE.local.md
files in your project are used by both
MCP servers
configured in
~/.claude.json
or
.mcp.json
work in both
Hooks
and
skills
defined in settings apply to both
Settings
in
~/.claude.json
and
~/.claude/settings.json
are shared. Permission rules, allowed tools, and other settings in
settings.json
apply to Desktop sessions.
Models
: Sonnet, Opus, and Haiku are available in both. In Desktop, select the model from the dropdown next to the send button. You can change the model mid-session from the same dropdown.
MCP servers: desktop chat app vs Claude Code
: MCP servers configured for the Claude Desktop chat app in
claude_desktop_config.json
are separate from Claude Code and will not appear in the Code tab. To use MCP servers in Claude Code, configure them in
~/.claude.json
or your project’s
.mcp.json
file. See
MCP configuration
for details.
​
Feature comparison
This table compares core capabilities between the CLI and Desktop. For a full list of CLI flags, see the
CLI reference
.
Feature
CLI
Desktop
Permission modes
All modes including
dontAsk
Ask permissions, Auto accept edits, Plan mode, Auto, and Bypass permissions via Settings
--dangerously-skip-permissions
CLI flag
Bypass permissions mode. Enable in Settings → Claude Code → “Allow bypass permissions mode”
Third-party providers
Bedrock, Vertex, Foundry
Anthropic’s API by default. Enterprise deployments can configure Vertex AI and gateway providers. See the
enterprise configuration guide
.
MCP servers
Configure in settings files
Connectors UI for local and SSH sessions, or settings files
Plugins
/plugin
command
Plugin manager UI
@mention files
Text-based
With autocomplete; local and SSH sessions only
File attachments
Not available
Images, PDFs
Session isolation
--worktree
flag
Automatic worktrees
Multiple sessions
Separate terminals
Sidebar tabs
Recurring tasks
Cron jobs, CI pipelines
Scheduled tasks
Computer use
Enable via
/mcp
on macOS
App and screen control
on macOS and Windows
Dispatch integration
Not available
Dispatch sessions
in the sidebar
Scripting and automation
--print
,
Agent SDK
Not available
​
What’s not available in Desktop
The following features are only available in the CLI or VS Code extension:
Third-party providers
: Desktop connects to Anthropic’s API by default. Enterprise deployments can configure Vertex AI and gateway providers via
managed settings
. For Bedrock or Foundry, use the
CLI
.
Linux
: the desktop app is available on macOS and Windows only. On Linux, use the
CLI
.
Inline code suggestions
: Desktop does not provide autocomplete-style suggestions. It works through conversational prompts and explicit code changes.
Agent teams
: multi-agent orchestration is available via the
CLI
and
Agent SDK
, not in Desktop.
​
Troubleshooting
The sections below cover issues specific to the desktop app. For runtime API errors that appear in the chat such as
API Error: 500
,
529 Overloaded
,
429
, or
Prompt is too long
, see the
Error reference
. Those errors and their fixes are the same across the CLI, desktop, and web.
​
Check your version
To see which version of the desktop app you’re running:
macOS
: click
Claude
in the menu bar, then
About Claude
Windows
: click
Help
, then
About
Click the version number to copy it to your clipboard.
​
403 or authentication errors in the Code tab
If you see
Error 403: Forbidden
or other authentication failures when using the Code tab:
Sign out and back in from the app menu. This is the most common fix.
Verify you have an active paid subscription: Pro, Max, Team, or Enterprise.
If the CLI works but Desktop does not, quit the desktop app completely, not just close the window, then reopen and sign in again.
Check your internet connection and proxy settings.
​
Blank or stuck screen on launch
If the app opens but shows a blank or unresponsive screen:
Restart the app.
Check for pending updates. The app auto-updates on launch.
On Windows, check Event Viewer for crash logs under
Windows Logs → Application
.
​
”Failed to load session”
If you see
Failed to load session
, the selected folder may no longer exist, a Git repository may require Git LFS that isn’t installed, or file permissions may prevent access. Try selecting a different folder or restarting the app.
​
Session not finding installed tools
If Claude can’t find tools like
npm
,
node
, or other CLI commands, verify the tools work in your regular terminal, check that your shell profile properly sets up PATH, and restart the desktop app to reload environment variables.
​
Git and Git LFS errors
On Windows, Git is required for the Code tab to start local sessions. If you see “Git is required,” install
Git for Windows
and restart the app.
If you see “Git LFS is required by this repository but is not installed,” install Git LFS from
git-lfs.com
, run
git lfs install
, and restart the app.
​
MCP servers not working on Windows
If MCP server toggles don’t respond or servers fail to connect on Windows, check that the server is properly configured in your settings, restart the app, verify the server process is running in Task Manager, and review server logs for connection errors.
​
App won’t quit
macOS
: press Cmd+Q. If the app doesn’t respond, use Force Quit with Cmd+Option+Esc, select Claude, and click Force Quit.
Windows
: use Task Manager with Ctrl+Shift+Esc to end the Claude process.
​
Windows-specific issues
PATH not updated after install
: open a new terminal window. PATH updates only apply to new terminal sessions.
Concurrent installation error
: if you see an error about another installation in progress but there isn’t one, try running the installer as Administrator.
​
”Branch doesn’t exist yet” when opening in CLI
Remote sessions can create branches that don’t exist on your local machine. Click the branch name in the session toolbar to copy it, then fetch it locally:
git
fetch
origin
<
branch-nam
e
>
git
checkout
<
branch-nam
e
>
​
Still stuck?
Search or file a bug on
GitHub Issues
Visit the
Claude support center
When filing a bug, include your desktop app version, your operating system, the exact error message, and relevant logs. On macOS, check Console.app. On Windows, check Event Viewer → Windows Logs → Application.
Was this page helpful?
Yes
No
Get started
Scheduled tasks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Use Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Use Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Desktop app has three tabs:
Chat
for conversations,
Cowork
for
Dispatch and longer agentic work
, and
Code
for software development. This page is the reference for the Code tab.
Download for macOS
Universal build for Intel and Apple Silicon
Download for Windows
For x64 processors
For Windows ARM64, download the
ARM64 installer
. The desktop app is not available on Linux; use the
CLI
instead.
After installing, launch Claude, sign in, and click the
Code
tab. The first time you open it on Windows, you need
Git for Windows
installed; restart the app after installing it. For a walkthrough of your first session, see the
Get started guide
.
In the Code tab, each conversation is a
session
: it has its own chat history, project folder, and code changes, independent of any other session. The sidebar lists your sessions and lets you run several in parallel. Within a session you can:
Review and comment on diffs
, then
watch the resulting PR through CI
Preview your running app
in an embedded browser while Claude verifies its own changes
Arrange panes
for the chat, diff, preview, terminal, and file editor side by side
Ask a
side question
that uses the session’s context without derailing it
Connect external tools
like GitHub, Slack, and Linear
Let Claude
open apps and control your screen
Run on your machine, in the
cloud
, or over
SSH
For
scheduled recurring work
,
keyboard shortcuts
, or
sending tasks from your phone
, see the linked pages and sections. If you already use the terminal-based CLI, see the
CLI comparison
for what carries over.
​
Start a session
Before you send your first message, configure four things in the prompt area:
Environment
: choose where Claude runs. Select
Local
for your machine,
Remote
for Anthropic-hosted cloud sessions, or an
SSH connection
for a remote machine you manage. See
environment configuration
.
Project folder
: select the folder or repository Claude works in. For remote sessions, you can add
multiple repositories
.
Model
: pick a
model
from the dropdown next to the send button. You can change this during the session.
Permission mode
: choose how much autonomy Claude has from the
mode selector
. You can change this during the session.
Type your task and press
Enter
to start. Each session tracks its own context and changes independently.
​
Work with code
Give Claude the right context, control how much it does on its own, and review what it changed.
​
Use the prompt box
Type what you want Claude to do and press
Enter
to send. Claude reads your project files, makes changes, and runs commands based on your
permission mode
. You can interrupt Claude at any point: click the stop button or type your correction and press
Enter
. Claude stops what it’s doing and adjusts based on your input.
The
+
button next to the prompt box gives you access to file attachments,
skills
,
connectors
, and
plugins
.
​
Add files and context to prompts
The prompt box supports two ways to bring in external context:
@mention files
: type
@
followed by a filename to add a file to the conversation context. Claude can then read and reference that file. @mention is not available in remote sessions.
Attach files
: attach images, PDFs, and other files to your prompt using the attachment button, or drag and drop files directly into the prompt. This is useful for sharing screenshots of bugs, design mockups, or reference documents.
​
Choose a permission mode
Permission modes control how much autonomy Claude has during a session: whether it asks before editing files, running commands, or both. You can switch modes at any time using the mode selector next to the send button. Start with Ask permissions to see exactly what Claude does, then move to Auto accept edits or Plan mode as you get comfortable.
Mode
Settings key
Behavior
Ask permissions
default
Claude asks before editing files or running commands. You see a diff and can accept or reject each change. Recommended for new users.
Auto accept edits
acceptEdits
Claude auto-accepts file edits and common filesystem commands like
mkdir
,
touch
, and
mv
, but still asks before running other terminal commands. Use this when you trust file changes and want faster iteration.
Plan mode
plan
Claude reads files and runs commands to explore, then proposes a plan without editing your source code. Good for complex tasks where you want to review the approach first.
Auto
auto
Claude executes all actions with background safety checks that verify alignment with your request. Reduces permission prompts while maintaining oversight. Enable in your Settings → Claude Code. See
availability requirements
below.
Bypass permissions
bypassPermissions
Claude runs without any permission prompts, equivalent to
--dangerously-skip-permissions
in the CLI. Enable in your Settings → Claude Code under “Allow bypass permissions mode”. Only use this in sandboxed containers or VMs. Enterprise admins can disable this option.
The
dontAsk
permission mode is available only in the
CLI
.
Auto mode is a research preview available on Max, Team, Enterprise, and API plans. It is not available on Pro plans or third-party providers. On Team, Enterprise, and API plans it requires Claude Sonnet 4.6, Opus 4.6, or Opus 4.7. On Max plans it requires Claude Opus 4.7.
Start complex tasks in Plan mode so Claude maps out an approach before making changes. Once you approve the plan, switch to Auto accept edits or Ask permissions to execute it. See
explore first, then plan, then code
for more on this workflow.
Remote sessions support Auto accept edits and Plan mode. Ask permissions is not available because remote sessions auto-accept file edits by default, and Bypass permissions is not available because the remote environment is already sandboxed.
Enterprise admins can restrict which permission modes are available. See
enterprise configuration
for details.
​
Preview your app
Claude can start a dev server and open an embedded browser to verify its changes. This works for frontend web apps as well as backend servers: Claude can test API endpoints, view server logs, and iterate on issues it finds. In most cases, Claude starts the server automatically after editing project files. You can also ask Claude to preview at any time. By default, Claude
auto-verifies
changes after every edit.
The preview pane can also open static HTML files, PDFs, images, and videos from your project. Click an HTML, PDF, image, or video path in the chat to open it in preview.
From the preview pane, you can:
Interact with your running app directly in the embedded browser
Watch Claude verify its own changes automatically: it takes screenshots, inspects the DOM, clicks elements, fills forms, and fixes issues it finds
Start or stop servers from the
Preview
dropdown in the session toolbar
Persist cookies and local storage across server restarts by selecting
Persist sessions
in the dropdown, so you don’t have to re-login during development
Edit the server configuration or stop all servers at once
Claude creates the initial server configuration based on your project. If your app uses a custom dev command, edit
.claude/launch.json
to match your setup. See
Configure preview servers
for the full reference.
To clear saved session data, toggle
Persist preview sessions
off in Settings → Claude Code. To disable preview entirely, toggle off
Preview
in Settings → Claude Code.
​
Review changes with diff view
After Claude makes changes to your code, the diff view lets you review modifications file by file before creating a pull request.
When Claude changes files, a diff stats indicator appears showing the number of lines added and removed, such as
+12 -1
. Click this indicator to open the diff viewer, which displays a file list on the left and the changes for each file on the right.
To comment on specific lines, click any line in the diff to open a comment box. Type your feedback and press
Enter
to add the comment. After adding comments to multiple lines, submit all comments at once:
macOS
: press
Cmd+Enter
Windows
: press
Ctrl+Enter
Claude reads your comments and makes the requested changes, which appear as a new diff you can review.
​
Review your code
In the diff view, click
Review code
in the top-right toolbar to ask Claude to evaluate the changes before you commit. Claude examines the current diffs and leaves comments directly in the diff view. You can respond to any comment or ask Claude to revise.
The review focuses on high-signal issues: compile errors, definite logic errors, security vulnerabilities, and obvious bugs. It does not flag style, formatting, pre-existing issues, or anything a linter would catch.
​
Monitor pull request status
After you open a pull request, a CI status bar appears in the session. Claude Code uses the GitHub CLI to poll check results and surface failures.
Auto-fix
: when enabled, Claude automatically attempts to fix failing CI checks by reading the failure output and iterating.
Auto-merge
: when enabled, Claude merges the PR once all checks pass. The merge method is squash. Auto-merge must be
enabled in your GitHub repository settings
for this to work.
Use the
Auto-fix
and
Auto-merge
toggles in the CI status bar to enable either option. Claude Code also sends a desktop notification when CI finishes. To archive the session automatically once the PR merges or closes, turn on
auto-archive
in Settings → Claude Code.
PR monitoring requires the
GitHub CLI (
gh
)
to be installed and authenticated on your machine. If
gh
is not installed, Desktop prompts you to install it the first time you try to create a PR.
​
Arrange your workspace
The Code tab is built around panes you can arrange in any layout: chat, diff, preview, terminal, file, plan, tasks, and subagent. Drag a pane by its header to reposition it, or drag a pane edge to resize it. Press
Cmd+\
on macOS or
Ctrl+\
on Windows to close the focused pane. Open additional panes from the
Views
menu in the session toolbar.
The pane layout, terminal, file editor, and view modes in this section require Claude Desktop v1.2581.0 or later. Open
Claude → Check for Updates
on macOS or
Help → Check for Updates
on Windows to update.
​
Run commands in the terminal
The integrated terminal lets you run commands alongside your session without switching to another app. Open it from the
Views
menu or press
Ctrl+`
on macOS or Windows. The terminal opens in your session’s working directory and shares the same environment as Claude, so commands like
npm test
or
git status
see the same files Claude is editing. To open a second terminal tab, click
+
in the terminal pane header or right-click a folder in the chat to choose
Open in terminal
. The terminal is available in local sessions only.
​
Open and edit files
Click a file path in the chat or diff viewer to open it in the file pane. HTML, PDF, image, and video paths open in the
preview pane
instead. Make spot edits and click
Save
to write them back. If the file changed on disk since you opened it, the pane warns you and lets you override or discard. Click
Discard
to revert your edits, or click the path in the pane header to copy the absolute path.
The file pane is available in local and SSH sessions. For remote sessions, ask Claude to make the change.
​
Open files in other apps
Right-click any file path in the chat, diff viewer, or file pane to open a context menu:
Attach as context
: add the file to your next prompt
Open in
: open the file in an installed editor such as VS Code, Cursor, or Zed
Show in Finder
on macOS,
Show in Explorer
on Windows: open the containing folder
Copy path
: copy the absolute path to your clipboard
​
Switch view modes
View modes control how much detail appears in the chat transcript. Switch modes from the
Transcript view
dropdown next to the send button, or press
Ctrl+O
on macOS or Windows to cycle through them.
Mode
What it shows
Normal
Tool calls collapsed into summaries, with full text responses
Verbose
Every tool call, file read, and intermediate step Claude takes
Summary
Only Claude’s final responses and the changes it made
Use Verbose when debugging why Claude took a particular action. Use Summary when you’re running multiple sessions and want to scan results quickly.
​
Keyboard shortcuts
Press
Cmd+/
on macOS or
Ctrl+/
on Windows to see all shortcuts available in the Code tab. On Windows, use
Ctrl
in place of
Cmd
for the shortcuts below. Session cycling, the terminal toggle, and the view-mode toggle use
Ctrl
on every platform.
Shortcut
Action
Cmd
/
Show keyboard shortcuts
Cmd
N
New session
Cmd
W
Close session
Ctrl
Tab
/
Ctrl
Shift
Tab
Next or previous session
Cmd
Shift
]
/
Cmd
Shift
[
Next or previous session
Esc
Stop Claude’s response
Cmd
Shift
D
Toggle diff pane
Cmd
Shift
P
Toggle preview pane
Cmd
Shift
S
Select an element in preview
Ctrl
`
Toggle terminal pane
Cmd
\
Close focused pane
Cmd
;
Open side chat
Ctrl
O
Cycle view modes
Cmd
Shift
M
Open permission mode menu
Cmd
Shift
I
Open model menu
Cmd
Shift
E
Open effort menu
1
–
9
Select item in an open menu
These shortcuts apply only to the Code tab. The terminal-based
interactive mode shortcuts
, such as
Shift+Tab
to cycle modes, do not apply in Desktop.
​
Check usage
Click the usage ring next to the model picker to see your current context window usage and your plan usage for the period. Context usage is per session; plan usage is shared across all your Claude Code surfaces.
​
Let Claude use your computer
Computer use lets Claude open your apps, control your screen, and work directly on your machine the way you would. Ask Claude to test a native app in a mobile simulator, interact with a desktop tool that has no CLI, or automate something that only works through a GUI.
Computer use is a research preview on macOS and Windows that requires a Pro or Max plan. It is not available on Team or Enterprise plans. The Claude Desktop app must be running.
Computer use is off by default.
Enable it in Settings
before Claude can control your screen. On macOS, you also need to grant Accessibility and Screen Recording permissions.
Unlike the
sandboxed Bash tool
, computer use runs on your actual desktop with access to whatever you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the
computer use safety guide
for best practices.
​
When computer use applies
Claude has several ways to interact with an app or service, and computer use is the broadest and slowest. It tries the most precise tool first:
If you have a
connector
for a service, Claude uses the connector.
If the task is a shell command, Claude uses Bash.
If the task is browser work and you have
Claude in Chrome
set up, Claude uses that.
If none of those apply, Claude uses computer use.
The
per-app access tiers
reinforce this: browsers are capped at view-only, and terminals and IDEs at click-only, steering Claude toward the dedicated tool even when computer use is active. Screen control is reserved for things nothing else can reach, like native apps, hardware control panels, mobile simulators, or proprietary tools without an API.
​
Enable computer use
Computer use is off by default. If you ask Claude to do something that needs it while it’s off, Claude tells you it could do the task if you enable computer use in Settings.
1
Update the desktop app
Make sure you have the latest version of Claude Desktop. Download or update at
claude.com/download
, then restart the app.
2
Turn on the toggle
In the desktop app, go to
Settings > General
(under
Desktop app
). Find the
Computer use
toggle and turn it on. On Windows, the toggle takes effect immediately and setup is complete. On macOS, continue to the next step.
If you don’t see the toggle, confirm you’re on macOS or Windows with a Pro or Max plan, then update and restart the app.
3
Grant macOS permissions
On macOS, grant two system permissions before the toggle takes effect:
Accessibility
: lets Claude click, type, and scroll
Screen Recording
: lets Claude see what’s on your screen
The Settings page shows the current status of each permission. If either is denied, click the badge to open the relevant System Settings pane.
​
App permissions
The first time Claude needs to use an app, a prompt appears in your session. Click
Allow for this session
or
Deny
. Approvals last for the current session, or 30 minutes in
Dispatch-spawned sessions
.
The prompt also shows what level of control Claude gets for that app. These tiers are fixed by app category and can’t be changed:
Tier
What Claude can do
Applies to
View only
See the app in screenshots
Browsers, trading platforms
Click only
Click and scroll, but not type or use keyboard shortcuts
Terminals, IDEs
Full control
Click, type, drag, and use keyboard shortcuts
Everything else
Apps with broad reach, like terminals, Finder or File Explorer, and System Settings or Settings, show an extra warning in the prompt so you know what approving them grants.
You can configure two settings in
Settings > General
(under
Desktop app
):
Denied apps
: add apps here to reject them without prompting. Claude may still affect a denied app indirectly through actions in an allowed app, but it can’t interact with the denied app directly.
Unhide apps when Claude finishes
: while Claude is working, your other windows are hidden so it interacts with only the approved app. When Claude finishes, hidden windows are restored unless you turn this setting off.
​
Manage sessions
Each session is an independent conversation with its own context and changes. You can run multiple sessions in parallel, branch off side chats, send work to the cloud, or let Dispatch start sessions for you from your phone.
​
Work in parallel with sessions
Click
+ New session
in the sidebar, or press
Cmd+N
on macOS or
Ctrl+N
on Windows, to work on multiple tasks in parallel. Press
Ctrl+Tab
and
Ctrl+Shift+Tab
to cycle through sessions in the sidebar. For Git repositories, each session gets its own isolated copy of your project using
Git worktrees
, so changes in one session don’t affect other sessions until you commit them.
To view two sessions at once, hold
Cmd
on macOS or
Ctrl
on Windows and click a session in the sidebar. The session opens in a second pane alongside the one you already have open. While the split is active, clicking another sidebar session replaces whichever pane has focus. Press
Cmd+\
on macOS or
Ctrl+\
on Windows to close the focused pane and return to a single session.
Worktrees are stored in
<project-root>/.claude/worktrees/
by default. You can change this to a custom directory in Settings → Claude Code under “Worktree location”. You can also set a branch prefix that gets prepended to every worktree branch name, which is useful for keeping Claude-created branches organized. To remove a worktree when you’re done, hover over the session in the sidebar and click the archive icon. To have sessions archive themselves when their pull request merges or closes, turn on
Auto-archive after PR merge or close
in Settings → Claude Code. Auto-archive only applies to local sessions that have finished running.
To include gitignored files like
.env
in new worktrees, create a
.worktreeinclude
file
in your project root.
Session isolation requires
Git
. Most Macs include Git by default. Run
git --version
in Terminal to check. On Windows, Git is required for the Code tab to work:
download Git for Windows
, install it, and restart the app. If you run into Git errors, ask Claude in the
Cowork tab
to help troubleshoot your setup.
Use the controls at the top of the sidebar to filter sessions by status, project, or environment, and to group sessions by project. To rename a session, click the session title in the toolbar at the top of the active session. To check context usage, see
Check usage
. When context fills up, Claude automatically summarizes the conversation and continues working. You can also type
/compact
to trigger summarization earlier and free up context space. See
the context window
for details on how compaction works.
The desktop app sends an OS notification when a Code session finishes a task and you aren’t currently viewing that session.
​
Ask a side question without derailing the session
A side chat lets you ask Claude a question that uses your session’s context but doesn’t add anything back to the main conversation. Use it when you want to understand a piece of code, check an assumption, or explore an idea without steering the session off course.
Press
Cmd+;
on macOS or
Ctrl+;
on Windows to open a side chat, or type
/btw
in the prompt box. The side chat can read everything in the main thread up to that point. When you’re done, close the side chat and continue the main session where you left off. Side chats are available in local and SSH sessions.
​
Watch background tasks
The tasks pane shows the background work running inside the current session: subagents, background shell commands, and workflows. Open it from the
Views
menu or drag it into your layout.
Click any entry to see its output in the subagent pane or stop it. To see what other sessions are doing, use the
sidebar
.
​
Run long-running tasks remotely
For large refactors, test suites, migrations, or other long-running tasks, select
Remote
instead of
Local
when starting a session. Remote sessions run on Anthropic’s cloud infrastructure and continue even if you close the app or shut down your computer. Check back anytime to see progress or steer Claude in a different direction. You can also monitor remote sessions from
claude.ai/code
or the Claude iOS app.
Remote sessions also support multiple repositories. After selecting a cloud environment, click the
+
button next to the repo pill to add additional repositories to the session. Each repo gets its own branch selector. This is useful for tasks that span multiple codebases, such as updating a shared library and its consumers.
See
Claude Code on the web
for more on how remote sessions work.
​
Continue in another surface
The
Continue in
menu, accessible from the VS Code icon in the bottom right of the session toolbar, lets you move your session to another surface:
Claude Code on the Web
: sends your local session to continue running remotely. Desktop pushes your branch, generates a summary of the conversation, and creates a new remote session with the full context. You can then choose to archive the local session or keep it. This requires a clean working tree, and is not available for SSH sessions.
Your IDE
: opens your project in a supported IDE at the current working directory.
​
Sessions from Dispatch
Dispatch
is a persistent conversation with Claude that lives in the
Cowork
tab. You message Dispatch a task, and it decides how to handle it.
A task can end up as a Code session in two ways: you ask for one directly, such as “open a Claude Code session and fix the login bug”, or Dispatch decides the task is development work and spawns one on its own. Tasks that typically route to Code include fixing bugs, updating dependencies, running tests, or opening pull requests. Research, document editing, and spreadsheet work stay in Cowork.
Either way, the Code session appears in the Code tab’s sidebar with a
Dispatch
badge. You get a push notification on your phone when it finishes or needs your approval.
If you have
computer use
enabled, Dispatch-spawned Code sessions can use it too. App approvals in those sessions expire after 30 minutes and re-prompt, rather than lasting the full session like regular Code sessions.
For setup, pairing, and Dispatch settings, see the
Dispatch help article
. Dispatch requires a Pro or Max plan and is not available on Team or Enterprise plans.
Dispatch is one of several ways to work with Claude when you’re away from your terminal. See
Platforms and integrations
to compare it with Remote Control, Channels, Slack, and scheduled tasks.
​
Extend Claude Code
Connect external services, add reusable workflows, customize Claude’s behavior, and configure preview servers. To manage connectors, skills, and plugins in one place, click
Customize
in the sidebar.
​
Connect external tools
For local and
SSH
sessions, click the
+
button next to the prompt box and select
Connectors
to add integrations like Google Calendar, Slack, GitHub, Linear, Notion, and more. You can add connectors before or during a session. The
+
button is not available in remote sessions, but
routines
configure connectors at routine creation time.
To manage or disconnect connectors, go to Settings → Connectors in the desktop app, or select
Manage connectors
from the Connectors menu in the prompt box.
Once connected, Claude can read your calendar, send messages, create issues, and interact with your tools directly. You can ask Claude what connectors are configured in your session.
Connectors are
MCP servers
with a graphical setup flow. Use them for quick integration with supported services. For integrations not listed in Connectors, add MCP servers manually via
settings files
. You can also
create custom connectors
.
​
Use skills
Skills
extend what Claude can do. Claude loads them automatically when relevant, or you can invoke one directly: type
/
in the prompt box or click the
+
button and select
Slash commands
to browse what’s available. This includes
built-in commands
, your
custom skills
, project skills from your codebase, and skills from any
installed plugins
. Select one and it appears highlighted in the input field. Type your task after it and send as usual.
​
Install plugins
Plugins
are reusable packages that add skills, agents, hooks, MCP servers, and LSP configurations to Claude Code. You can install plugins from the desktop app without using the terminal.
For local and
SSH
sessions, click the
+
button next to the prompt box and select
Plugins
to see your installed plugins and their skills. To add a plugin, select
Add plugin
from the submenu to open the plugin browser, which shows available plugins from your configured
marketplaces
including the official Anthropic marketplace. Select
Manage plugins
to enable, disable, or uninstall plugins.
Plugins can be scoped to your user account, a specific project, or local-only. If your organization manages plugins centrally, those plugins are available in desktop sessions the same way they are in the CLI. Plugins are not available for remote sessions. For the full plugin reference including creating your own plugins, see
plugins
.
​
Configure preview servers
Claude automatically detects your dev server setup and stores the configuration in
.claude/launch.json
at the root of the folder you selected when starting the session. Preview uses this folder as its working directory, so if you selected a parent folder, subfolders with their own dev servers won’t be detected automatically. To work with a subfolder’s server, either start a session in that folder directly or add a configuration manually.
To customize how your server starts, for example to use
yarn dev
instead of
npm run dev
or to change the port, edit the file manually or click
Edit configuration
in the Preview dropdown to open it in your code editor. The file supports JSON with comments.
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"my-app"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"dev"
],
"port"
:
3000
}
]
}
You can define multiple configurations to run different servers from the same project, such as a frontend and an API. See the
examples
below.
​
Auto-verify changes
When
autoVerify
is enabled, Claude automatically verifies code changes after editing files. It takes screenshots, checks for errors, and confirms changes work before completing its response.
Auto-verify is on by default. Disable it per-project by adding
"autoVerify": false
to
.claude/launch.json
, or toggle it from the
Preview
dropdown menu.
{
"version"
:
"0.0.1"
,
"autoVerify"
:
false
,
"configurations"
: [
...
]
}
When disabled, preview tools are still available and you can ask Claude to verify at any time. Auto-verify makes it automatic after every edit.
​
Configuration fields
Each entry in the
configurations
array accepts the following fields:
Field
Type
Description
name
string
A unique identifier for this server
runtimeExecutable
string
The command to run, such as
npm
,
yarn
, or
node
runtimeArgs
string[]
Arguments passed to
runtimeExecutable
, such as
["run", "dev"]
port
number
The port your server listens on. Defaults to 3000
cwd
string
Working directory relative to your project root. Defaults to the project root. Use
${workspaceFolder}
to reference the project root explicitly
env
object
Additional environment variables as key-value pairs, such as
{ "NODE_ENV": "development" }
. Don’t put secrets here since this file is committed to your repo. To pass secrets to your dev server, set them in the
local environment editor
instead.
autoPort
boolean
How to handle port conflicts. See below
program
string
A script to run with
node
. See
when to use
program
vs
runtimeExecutable
args
string[]
Arguments passed to
program
. Only used when
program
is set
When to use
program
vs
runtimeExecutable
Use
runtimeExecutable
with
runtimeArgs
to start a dev server through a package manager. For example,
"runtimeExecutable": "npm"
with
"runtimeArgs": ["run", "dev"]
runs
npm run dev
.
Use
program
when you have a standalone script you want to run with
node
directly. For example,
"program": "server.js"
runs
node server.js
. Pass additional flags with
args
.
​
Port conflicts
The
autoPort
field controls what happens when your preferred port is already in use:
true
: Claude finds and uses a free port automatically. Suitable for most dev servers.
false
: Claude fails with an error. Use this when your server must use a specific port, such as for OAuth callbacks or CORS allowlists.
Not set (default)
: Claude asks whether the server needs that exact port, then saves your answer.
When Claude picks a different port, it passes the assigned port to your server via the
PORT
environment variable.
​
Examples
These configurations show common setups for different project types:
Next.js
Multiple servers
Node.js script
This configuration runs a Next.js app using Yarn on port 3000:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"web"
,
"runtimeExecutable"
:
"yarn"
,
"runtimeArgs"
: [
"dev"
],
"port"
:
3000
}
]
}
For a monorepo with a frontend and an API server, define multiple configurations. The frontend uses
autoPort: true
so it picks a free port if 3000 is taken, while the API server requires port 8080 exactly:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"frontend"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"dev"
],
"cwd"
:
"apps/web"
,
"port"
:
3000
,
"autoPort"
:
true
},
{
"name"
:
"api"
,
"runtimeExecutable"
:
"npm"
,
"runtimeArgs"
: [
"run"
,
"start"
],
"cwd"
:
"server"
,
"port"
:
8080
,
"env"
: {
"NODE_ENV"
:
"development"
},
"autoPort"
:
false
}
]
}
To run a Node.js script directly instead of using a package manager command, use the
program
field:
{
"version"
:
"0.0.1"
,
"configurations"
: [
{
"name"
:
"server"
,
"program"
:
"server.js"
,
"args"
: [
"--verbose"
],
"port"
:
4000
}
]
}
​
Environment configuration
The environment you pick when
starting a session
determines where Claude executes and how you connect:
Local
: runs on your machine with direct access to your files
Remote
: runs on Anthropic’s cloud infrastructure. Sessions continue even if you close the app.
SSH
: runs on a remote machine you connect to over SSH, such as your own servers, cloud VMs, or dev containers
​
Local sessions
The desktop app does not always inherit your full shell environment. On macOS, when you launch the app from the Dock or Finder, it reads your shell profile, such as
~/.zshrc
or
~/.bashrc
, to extract
PATH
and a fixed set of Claude Code variables, but other variables you export there are not picked up. On Windows, the app inherits user and system environment variables but does not read PowerShell profiles.
To set environment variables for local sessions and dev servers on any platform, open the environment dropdown in the prompt box, hover over
Local
, and click the gear icon to open the local environment editor. Variables you save here are stored encrypted on your machine and apply to every local session and preview server you start. You can also add variables to the
env
key in your
~/.claude/settings.json
file, though these reach Claude sessions only and not dev servers. See
environment variables
for the full list of supported variables.
Extended thinking
is enabled by default, which improves performance on complex reasoning tasks but uses additional tokens. To disable thinking entirely, set
MAX_THINKING_TOKENS
to
0
in the local environment editor. On models with
adaptive reasoning
, any other
MAX_THINKING_TOKENS
value is ignored because adaptive reasoning controls thinking depth instead. On Opus 4.6 and Sonnet 4.6, set
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING
to
1
to use a fixed thinking budget; Opus 4.7 always uses adaptive reasoning and has no fixed-budget mode.
​
Remote sessions
Remote sessions continue in the background even if you close the app. Usage counts toward your
subscription plan limits
with no separate compute charges.
You can create custom cloud environments with different network access levels and environment variables. Select the environment dropdown when starting a remote session and choose
Add environment
. See
the cloud environment
for details on configuring network access and environment variables.
​
SSH sessions
SSH sessions let you run Claude Code on a remote machine while using the desktop app as your interface. This is useful for working with codebases that live on cloud VMs, dev containers, or servers with specific hardware or dependencies.
To add an SSH connection, click the environment dropdown before starting a session and select
+ Add SSH connection
. The dialog asks for:
Name
: a friendly label for this connection
SSH Host
:
user@hostname
or a host defined in
~/.ssh/config
SSH Port
: defaults to 22 if left empty, or uses the port from your SSH config
Identity File
: path to your private key, such as
~/.ssh/id_rsa
. Leave empty to use the default key or your SSH config.
Once added, the connection appears in the environment dropdown. Select it to start a session on that machine. Claude runs on the remote machine with access to its files and tools.
The remote machine must run Linux or macOS. Desktop installs Claude Code on the remote machine automatically the first time you connect. Once connected, SSH sessions support permission modes, connectors, plugins, and MCP servers.
​
Pre-configure SSH connections for your team
Administrators can distribute SSH connections to team members by adding
sshConfigs
to a
managed settings
file. Connections defined this way appear in each user’s environment dropdown automatically and are shown as managed, so users can select them but cannot edit or delete them in the app.
The following example pre-configures a single connection that opens in
~/projects
on the remote host:
{
"sshConfigs"
: [
{
"id"
:
"shared-dev-vm"
,
"name"
:
"Shared Dev VM"
,
"sshHost"
:
"user@dev.example.com"
,
"sshPort"
:
22
,
"sshIdentityFile"
:
"~/.ssh/id_ed25519"
,
"startDirectory"
:
"~/projects"
}
]
}
Each entry requires
id
,
name
, and
sshHost
. The
sshPort
,
sshIdentityFile
, and
startDirectory
fields are optional. Users can also add
sshConfigs
to their own
~/.claude/settings.json
, which is where connections added through the dialog are stored.
​
Restrict which SSH hosts users can connect to
Administrators can limit Desktop’s SSH sessions to an approved set of hosts by adding
sshHostAllowlist
to a
managed settings
file. When set, users can only connect to hosts whose resolved hostname matches one of the patterns. Set it to an empty array to disable SSH sessions entirely.
The following example allows connections to any host under
devboxes.example.com
and to a single named bastion host:
{
"sshHostAllowlist"
: [
"*.devboxes.example.com"
,
"bastion.example.com"
]
}
Patterns are case-insensitive.
*
matches any host, and
*.example.com
matches
example.com
and any subdomain. Anything else is an exact match. The check runs against the hostname after
~/.ssh/config
resolution via
ssh -G
, so
Host
aliases and
ProxyCommand
/
ProxyJump
entries are permitted as long as the resolved
HostName
matches.
sshHostAllowlist
is read from managed settings only; values in user or project settings are ignored. Only the Claude Desktop app honors this setting; the Claude Code CLI and IDE extensions do not read it, and it does not restrict
ssh
commands run through the Bash tool. It governs which hosts the Desktop app connects to, not network egress, so pair it with your organization’s network or zero-trust controls if you need a hard boundary.
​
Enterprise configuration
Organizations on Team or Enterprise plans can manage desktop app behavior through admin console controls, managed settings files, and device management policies.
​
Admin console controls
These settings are configured through the
admin settings console
:
Code in the desktop
: control whether users in your organization can access Claude Code in the desktop app
Code in the web
: enable or disable
web sessions
for your organization
Remote Control
: enable or disable
Remote Control
for your organization
Disable Bypass permissions mode
: prevent users in your organization from enabling bypass permissions mode
​
Managed settings
Managed settings override project and user settings and apply when Desktop spawns CLI sessions. You can set these keys in your organization’s
managed settings
file or push them remotely through the admin console.
Key
Description
permissions.disableBypassPermissionsMode
set to
"disable"
to prevent users from enabling Bypass permissions mode.
disableAutoMode
set to
"disable"
to prevent users from enabling
Auto
mode. Removes Auto from the mode selector. Also accepted under
permissions
.
autoMode
customize what the auto mode classifier trusts and blocks across your organization. See
Configure auto mode
.
sshConfigs
pre-configure
SSH connections
that appear in the environment dropdown. Users cannot edit or delete managed connections.
sshHostAllowlist
restrict
SSH sessions
to hosts whose resolved hostname matches one of these patterns. An empty array disables SSH sessions. Read from managed settings only.
managedMcpServers
push MCP server configurations to all users in a third-party deployment. Each entry specifies a transport of
"http"
,
"sse"
, or
"stdio"
, connection details, and optionally a
toolPolicy
map that restricts which tools in that server users can invoke. Available in third-party (3P) Desktop deployments only.
A managed settings file deployed to disk on each machine applies to Desktop sessions. Managed settings pushed remotely through the admin console currently reach CLI and IDE sessions only, so for Desktop deployments either distribute the file via MDM or use the
admin console controls
above.
permissions.disableBypassPermissionsMode
and
disableAutoMode
also work in user and project settings, but placing them in managed settings prevents users from overriding them.
autoMode
is read from user settings,
.claude/settings.local.json
, and managed settings, but not from the checked-in
.claude/settings.json
: a cloned repo cannot inject its own classifier rules. For the complete list of managed-only settings including
allowManagedPermissionRulesOnly
and
allowManagedHooksOnly
, see
managed-only settings
.
​
Device management policies
IT teams can manage the desktop app through MDM on macOS or group policy on Windows. Available policies include enabling or disabling the Claude Code feature, controlling auto-updates, and setting a custom deployment URL.
macOS
: configure via
com.anthropic.Claude
preference domain using tools like Jamf or Kandji
Windows
: configure via registry at
SOFTWARE\Policies\Claude
​
Authentication and SSO
Enterprise organizations can require SSO for all users. See
authentication
for plan-level details and
Setting up SSO
for SAML and OIDC configuration.
​
Data handling
Claude Code processes your code locally in local sessions or on Anthropic’s cloud infrastructure in remote sessions. Conversations and code context are sent to Anthropic’s API for processing. See
data handling
for details on data retention, privacy, and compliance.
​
Deployment
Desktop can be distributed through enterprise deployment tools:
macOS
: distribute via MDM such as Jamf or Kandji using the
.dmg
installer
Windows
: deploy via MSIX package or
.exe
installer. See
Deploy Claude Desktop for Windows
for enterprise deployment options including silent installation
For network configuration such as proxy settings, firewall allowlisting, and LLM gateways, see
network configuration
.
For the full enterprise configuration reference, see the
enterprise configuration guide
.
​
Coming from the CLI?
If you already use the Claude Code CLI, Desktop runs the same underlying engine with a graphical interface. You can run both simultaneously on the same machine, even on the same project. Each maintains separate session history, but they share configuration and project memory via CLAUDE.md files.
To move a CLI session into Desktop, run
/desktop
in the terminal. Claude saves your session and opens it in the desktop app, then exits the CLI. This command is available on macOS and Windows only.
When to use Desktop vs CLI: use Desktop when you want to manage parallel sessions in one window, arrange panes side by side, or review changes visually. Use the CLI when you need scripting, automation, or prefer a terminal workflow.
​
CLI flag equivalents
This table shows the desktop app equivalent for common CLI flags. Flags not listed have no desktop equivalent because they are designed for scripting or automation.
CLI
Desktop equivalent
--model sonnet
Model dropdown next to the send button
--resume
,
--continue
Click a session in the sidebar
--permission-mode
Mode selector next to the send button
--dangerously-skip-permissions
Bypass permissions mode. Enable in Settings → Claude Code → “Allow bypass permissions mode”. Enterprise admins can disable this setting.
--add-dir
Add multiple repos with the
+
button in remote sessions
--allowedTools
,
--disallowedTools
No per-session equivalent. Permission rules in
settings files
still apply.
--verbose
Verbose view mode
in the Transcript view dropdown
--print
,
--output-format
Not available. Desktop is interactive only.
ANTHROPIC_MODEL
env var
Model dropdown next to the send button
MAX_THINKING_TOKENS
env var
Set in the local environment editor. See
environment configuration
.
​
Shared configuration
Desktop and CLI read the same configuration files, so your setup carries over:
CLAUDE.md
and
CLAUDE.local.md
files in your project are used by both
MCP servers
configured in
~/.claude.json
or
.mcp.json
work in both
Hooks
and
skills
defined in settings apply to both
Settings
in
~/.claude.json
and
~/.claude/settings.json
are shared. Permission rules, allowed tools, and other settings in
settings.json
apply to Desktop sessions.
Models
: Sonnet, Opus, and Haiku are available in both. In Desktop, select the model from the dropdown next to the send button. You can change the model mid-session from the same dropdown.
MCP servers: desktop chat app vs Claude Code
: MCP servers configured for the Claude Desktop chat app in
claude_desktop_config.json
are separate from Claude Code and will not appear in the Code tab. To use MCP servers in Claude Code, configure them in
~/.claude.json
or your project’s
.mcp.json
file. See
MCP configuration
for details.
​
Feature comparison
This table compares core capabilities between the CLI and Desktop. For a full list of CLI flags, see the
CLI reference
.
Feature
CLI
Desktop
Permission modes
All modes including
dontAsk
Ask permissions, Auto accept edits, Plan mode, Auto, and Bypass permissions via Settings
--dangerously-skip-permissions
CLI flag
Bypass permissions mode. Enable in Settings → Claude Code → “Allow bypass permissions mode”
Third-party providers
Bedrock, Vertex, Foundry
Anthropic’s API by default. Enterprise deployments can configure Vertex AI and gateway providers. See the
enterprise configuration guide
.
MCP servers
Configure in settings files
Connectors UI for local and SSH sessions, or settings files
Plugins
/plugin
command
Plugin manager UI
@mention files
Text-based
With autocomplete; local and SSH sessions only
File attachments
Not available
Images, PDFs
Session isolation
--worktree
flag
Automatic worktrees
Multiple sessions
Separate terminals
Sidebar tabs
Recurring tasks
Cron jobs, CI pipelines
Scheduled tasks
Computer use
Enable via
/mcp
on macOS
App and screen control
on macOS and Windows
Dispatch integration
Not available
Dispatch sessions
in the sidebar
Scripting and automation
--print
,
Agent SDK
Not available
​
What’s not available in Desktop
The following features are only available in the CLI or VS Code extension:
Third-party providers
: Desktop connects to Anthropic’s API by default. Enterprise deployments can configure Vertex AI and gateway providers via
managed settings
. For Bedrock or Foundry, use the
CLI
.
Linux
: the desktop app is available on macOS and Windows only. On Linux, use the
CLI
.
Inline code suggestions
: Desktop does not provide autocomplete-style suggestions. It works through conversational prompts and explicit code changes.
Agent teams
: multi-agent orchestration is available via the
CLI
and
Agent SDK
, not in Desktop.
​
Troubleshooting
The sections below cover issues specific to the desktop app. For runtime API errors that appear in the chat such as
API Error: 500
,
529 Overloaded
,
429
, or
Prompt is too long
, see the
Error reference
. Those errors and their fixes are the same across the CLI, desktop, and web.
​
Check your version
To see which version of the desktop app you’re running:
macOS
: click
Claude
in the menu bar, then
About Claude
Windows
: click
Help
, then
About
Click the version number to copy it to your clipboard.
​
403 or authentication errors in the Code tab
If you see
Error 403: Forbidden
or other authentication failures when using the Code tab:
Sign out and back in from the app menu. This is the most common fix.
Verify you have an active paid subscription: Pro, Max, Team, or Enterprise.
If the CLI works but Desktop does not, quit the desktop app completely, not just close the window, then reopen and sign in again.
Check your internet connection and proxy settings.
​
Blank or stuck screen on launch
If the app opens but shows a blank or unresponsive screen:
Restart the app.
Check for pending updates. The app auto-updates on launch.
On Windows, check Event Viewer for crash logs under
Windows Logs → Application
.
​
”Failed to load session”
If you see
Failed to load session
, the selected folder may no longer exist, a Git repository may require Git LFS that isn’t installed, or file permissions may prevent access. Try selecting a different folder or restarting the app.
​
Session not finding installed tools
If Claude can’t find tools like
npm
,
node
, or other CLI commands, verify the tools work in your regular terminal, check that your shell profile properly sets up PATH, and restart the desktop app to reload environment variables.
​
Git and Git LFS errors
On Windows, Git is required for the Code tab to start local sessions. If you see “Git is required,” install
Git for Windows
and restart the app.
If you see “Git LFS is required by this repository but is not installed,” install Git LFS from
git-lfs.com
, run
git lfs install
, and restart the app.
​
MCP servers not working on Windows
If MCP server toggles don’t respond or servers fail to connect on Windows, check that the server is properly configured in your settings, restart the app, verify the server process is running in Task Manager, and review server logs for connection errors.
​
App won’t quit
macOS
: press Cmd+Q. If the app doesn’t respond, use Force Quit with Cmd+Option+Esc, select Claude, and click Force Quit.
Windows
: use Task Manager with Ctrl+Shift+Esc to end the Claude process.
​
Windows-specific issues
PATH not updated after install
: open a new terminal window. PATH updates only apply to new terminal sessions.
Concurrent installation error
: if you see an error about another installation in progress but there isn’t one, try running the installer as Administrator.
​
”Branch doesn’t exist yet” when opening in CLI
Remote sessions can create branches that don’t exist on your local machine. Click the branch name in the session toolbar to copy it, then fetch it locally:
git
fetch
origin
<
branch-nam
e
>
git
checkout
<
branch-nam
e
>
​
Still stuck?
Search or file a bug on
GitHub Issues
Visit the
Claude support center
When filing a bug, include your desktop app version, your operating system, the exact error message, and relevant logs. On macOS, check Console.app. On Windows, check Event Viewer → Windows Logs → Application.
Was this page helpful?
Yes
No
Get started
Scheduled tasks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Get started with Claude Code on the web</title>
  <link>https://code.claude.com/docs/en/web-quickstart</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/web-quickstart</guid>
  <pubDate>Thu, 09 May 2024 00:00:00 +0000</pubDate>
  <category>Getting Started</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Get started with Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routin...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Get started with Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.
Claude Code on the web runs on Anthropic-managed cloud infrastructure instead of your machine. Submit tasks from
claude.ai/code
in your browser or the Claude mobile app.
You’ll need a GitHub repository to
get started
. Claude clones it into an isolated virtual machine, makes changes, and pushes a branch for you to review. Sessions persist across devices, so a task you start on your laptop is ready to review from your phone later.
Claude Code on the web works well for:
Parallel tasks
: run several independent tasks at once, each in its own session and branch, without managing multiple worktrees
Repos you don’t have locally
: Claude clones the repo fresh every session, so you don’t need it checked out
Tasks that don’t need frequent steering
: submit a well-defined task, do something else, and review the result when Claude is done
Code questions and exploration
: understand a codebase or trace how a feature is implemented without a local checkout
For work that needs your local config, tools, or environment, running Claude Code locally or using
Remote Control
is a better fit.
​
How sessions run
When you submit a task:
Clone and prepare
: your repository is cloned to an Anthropic-managed VM, and your
setup script
runs if configured.
Configure network
: internet access is set based on your environment’s
access level
.
Work
: Claude analyzes code, makes changes, runs tests, and checks its work. You can watch and steer throughout, or step away and come back when it’s done.
Push the branch
: when Claude reaches a stopping point, it pushes its branch to GitHub. You review the diff, leave inline comments, create a PR, or send another message to keep going.
The session doesn’t close when the branch is pushed. PR creation and further edits all happen within the same conversation.
​
Compare ways to run Claude Code
Claude Code behaves the same everywhere. What changes is where code executes and whether your local config is available. The Desktop app offers both local and cloud sessions, so its answers below depend on which you choose:
On the web
Remote Control
Terminal CLI
Desktop app
Code runs on
Anthropic cloud VM
Your machine
Your machine
Your machine or cloud VM
You chat from
claude.ai or mobile app
claude.ai or mobile app
Your terminal
The Desktop UI
Uses your local config
No, repo only
Yes
Yes
Yes for local, no for cloud
Requires GitHub
Yes, or
bundle a local repo
via
--remote
No
No
Only for cloud sessions
Keeps running if you disconnect
Yes
While terminal stays open
No
Depends on session type
Permission modes
Auto accept edits, Plan
Ask, Auto accept edits, Plan
All modes
Depends on session type
Network access
Configurable per environment
Your machine’s network
Your machine’s network
Depends on session type
See the
terminal quickstart
,
Desktop app
, or
Remote Control
docs to set those up.
​
Connect GitHub and create an environment
Setup is a one-time process. If you already use the GitHub CLI, you can
do this from your terminal
instead of the browser.
1
Visit claude.ai/code
Go to
claude.ai/code
and sign in with your Anthropic account.
2
Install the Claude GitHub App
After signing in, claude.ai/code prompts you to connect GitHub. Follow the prompt to install the Claude GitHub App and grant it access to your repositories. Cloud sessions work with existing GitHub repositories, so to start a new project,
create an empty repository on GitHub
first.
3
Create your environment
After connecting GitHub, you’ll be prompted to create a cloud environment. The environment controls what network access Claude has during sessions and what runs when a new session is created. See
Installed tools
for what’s available without any configuration.
The form has these fields:
Name
: a display label. Useful when you have multiple environments for different projects or access levels.
Network access
: controls what the session can reach on the internet. The default,
Trusted
, allows connections to
common package registries
like npm, PyPI, and RubyGems while blocking general internet access.
Environment variables
: optional variables available in every session, in
.env
format. Don’t wrap values in quotes, since quotes are stored as part of the value. These are visible to anyone who can edit this environment.
Setup script
: an optional Bash script that runs before Claude Code launches. Use it to install system tools the cloud VM doesn’t include, like
apt install -y gh
. The result is
cached
, so the script doesn’t re-run on every session. See
Setup scripts
for examples and debugging tips.
For a first project, leave the defaults and click
Create environment
. You can
edit it later or create additional environments
for different projects.
​
Connect from your terminal
If you already use the GitHub CLI (
gh
), you can set up Claude Code on the web without opening a browser. This requires the
Claude Code CLI
.
/web-setup
reads your local
gh
token, links it to your Claude account, and creates a default cloud environment if you don’t have one.
Organizations with
Zero Data Retention
enabled cannot use
/web-setup
or other cloud session features. If the GitHub CLI isn’t installed or authenticated,
/web-setup
opens the browser onboarding flow instead.
1
Authenticate with the GitHub CLI
In your shell, authenticate the GitHub CLI if you haven’t already:
gh
auth
login
2
Sign in to Claude
In the Claude Code CLI, run
/login
to sign in with your claude.ai account. Skip this step if you’re already signed in.
3
Run /web-setup
In the Claude Code CLI, run:
/web-setup
This syncs your
gh
token to your Claude account. If you don’t have a cloud environment yet,
/web-setup
creates one with Trusted network access and no setup script. You can
edit the environment or add variables
afterward. Once
/web-setup
completes, you can start cloud sessions from your terminal with
--remote
or set up recurring tasks with
/schedule
.
​
Start a task
With GitHub connected and an environment created, you’re ready to submit tasks.
1
Select a repository and branch
From
claude.ai/code
or the Code tab in the Claude mobile app, click the repository selector below the input box and choose a repository for Claude to work in. Each repository shows a branch selector. Change it to start Claude from a feature branch instead of the default. You can add multiple repositories to work across them in one session.
2
Choose a permission mode
The mode dropdown next to the input defaults to
Auto accept edits
, where Claude makes changes and pushes a branch without stopping for approval. Switch to
Plan mode
if you want Claude to propose an approach and wait for your go-ahead before editing files. Cloud sessions don’t offer Ask permissions, Auto mode, or Bypass permissions. See
Permission modes
for the full list.
3
Describe the task and submit
Type a description of what you want and press Enter. Be specific:
Name the file or function: “Add a README with setup instructions” or “Fix the failing auth test in
tests/test_auth.py
” is better than “fix tests”
Paste error output if you have it
Describe the expected behavior, not just the symptom
Claude clones the repositories, runs your setup script if configured, and starts working. Each task gets its own session and its own branch, so you don’t need to wait for one to finish before starting another.
​
Pre-fill sessions
You can prefill the prompt, repositories, and environment for a new session by adding query parameters to the
claude.ai/code
URL. Use this to build integrations such as a button in your issue tracker that opens Claude Code with the issue description as the prompt.
Parameter
Description
prompt
Prompt text to prefill in the input box. The alias
q
is also accepted.
prompt_url
URL to fetch the prompt text from, for prompts too long to embed in a query string. The URL must allow cross-origin requests. Ignored when
prompt
is also set.
repositories
Comma-separated list of
owner/repo
slugs to preselect. The alias
repo
is also accepted.
environment
Name or ID of the
environment
to preselect.
URL-encode each value. The example below opens the form with a prompt and a repository already selected:
https://claude.ai/code?prompt=Fix%20the%20login%20bug&repositories=acme/webapp
​
Review and iterate
When Claude finishes, review the changes, leave feedback on specific lines, and keep going until the diff looks right.
1
Open the diff view
A diff indicator shows lines added and removed across the session, for example
+42 -18
. Select it to open the diff view, with a file list on the left and changes on the right.
2
Leave inline comments
Select any line in the diff, type your feedback, and press Enter. Comments queue up until you send your next message, then they’re bundled with it. Claude sees “at
src/auth.ts:47
, don’t catch the error here” alongside your main instruction, so you don’t have to describe where the problem is.
3
Create a pull request
When the diff looks right, select
Create PR
at the top of the diff view. You can open it as a full PR, a draft, or jump to GitHub’s compose page with a generated title and description.
4
Keep iterating after the PR
The session stays live after the PR is created. Paste CI failure output or reviewer comments into the chat and ask Claude to address them. To have Claude monitor the PR automatically, see
Auto-fix pull requests
.
​
Troubleshoot setup
​
No repositories appear after connecting GitHub
A cloud session can use any repository the connected GitHub account can see, regardless of which repositories the Claude GitHub App is installed on. If a repository is missing, verify the connected GitHub account has access to it on GitHub. If you also want
Auto-fix
for a repository, install the App on it: on github.com, open
Settings → Applications → Claude → Configure
and verify the repository is listed under
Repository access
. Private repositories need the same authorization as public ones.
​
The page only shows a GitHub login button
Cloud sessions require a connected GitHub account. Connect via the browser flow above, or run
/web-setup
from your terminal if you use the GitHub CLI. If you’d rather not connect GitHub at all, see
Remote Control
to run Claude Code on your own machine and monitor it from the web.
​
”Not available for the selected organization”
Enterprise organizations may need an admin to enable Claude Code on the web. Contact your Anthropic account team.
​
/web-setup
returns “Unknown command”
/web-setup
runs inside the Claude Code CLI, not your shell. Launch
claude
first, then type
/web-setup
at the prompt.
If you typed it inside Claude Code and still see the error, your CLI is older than v2.1.80 or you’re authenticated with an API key or third-party provider instead of a claude.ai subscription. Run
claude update
, then
/login
to sign in with your claude.ai account.
​
”Could not create a cloud environment” or “No cloud environment available” when using
--remote
or ultraplan
Remote-session features create a default cloud environment automatically if you don’t have one. If you see “Could not create a cloud environment”, automatic creation failed. If you see “No cloud environment available”, your CLI predates automatic creation. In either case, run
/web-setup
in the Claude Code CLI to create one manually, or visit
claude.ai/code
and follow the
Create your environment
step above.
​
Setup script failed
The setup script exited with a non-zero status, which blocks the session from starting. Common causes:
A package install failed because the registry isn’t in your
network access level
.
Trusted
covers most package managers;
None
blocks them all.
The script references a file or path that doesn’t exist in a fresh clone.
A command that works locally needs a different invocation on Ubuntu.
To debug, add
set -x
at the top of the script to see which command failed. For non-critical commands, append
|| true
so they don’t block session start.
​
New sessions hang or time out during setup
If new sessions stall on the setup script step or fail with a generic container error before the script finishes, the script is likely exceeding the roughly five-minute time budget for building the
environment cache
. Heavy steps such as pulling large Docker images, syncing full dependency trees, or downloading model weights often push the total over the limit, especially when they run one after another.
To fix this, trim the script so it reliably finishes in under five minutes:
Run independent installs in parallel with
&
and a final
wait
instead of running them serially.
Move the largest downloads out of the setup script and into a
SessionStart hook
that launches them in the background, so the session becomes usable while they finish.
Remove long retry sleeps from the setup script, since a stalled retry loop counts against the budget.
​
Session keeps running after closing the tab
This is by design. Closing the tab or navigating away doesn’t stop the session. It continues running in the background until Claude finishes the current task, then idles. From the sidebar, you can
archive a session
to hide it from your list, or
delete it
to remove it permanently.
​
Next steps
Now that you can submit and review tasks, these pages cover what comes next: starting cloud sessions from your terminal, scheduling recurring work, and giving Claude standing instructions.
Use Claude Code on the web
: the full reference, including teleporting sessions to your terminal, setup scripts, environment variables, and network config
Routines
: automate work on a schedule, via API call, or in response to GitHub events
CLAUDE.md
: give Claude persistent instructions and context that load at the start of every session
Install the Claude mobile app for
iOS
or
Android
to monitor sessions from your phone. From the Claude Code CLI,
/mobile
shows a QR code.
Was this page helpful?
Yes
No
Remote Control
Reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/web-quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Get started with Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routin...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Get started with Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.
Claude Code on the web runs on Anthropic-managed cloud infrastructure instead of your machine. Submit tasks from
claude.ai/code
in your browser or the Claude mobile app.
You’ll need a GitHub repository to
get started
. Claude clones it into an isolated virtual machine, makes changes, and pushes a branch for you to review. Sessions persist across devices, so a task you start on your laptop is ready to review from your phone later.
Claude Code on the web works well for:
Parallel tasks
: run several independent tasks at once, each in its own session and branch, without managing multiple worktrees
Repos you don’t have locally
: Claude clones the repo fresh every session, so you don’t need it checked out
Tasks that don’t need frequent steering
: submit a well-defined task, do something else, and review the result when Claude is done
Code questions and exploration
: understand a codebase or trace how a feature is implemented without a local checkout
For work that needs your local config, tools, or environment, running Claude Code locally or using
Remote Control
is a better fit.
​
How sessions run
When you submit a task:
Clone and prepare
: your repository is cloned to an Anthropic-managed VM, and your
setup script
runs if configured.
Configure network
: internet access is set based on your environment’s
access level
.
Work
: Claude analyzes code, makes changes, runs tests, and checks its work. You can watch and steer throughout, or step away and come back when it’s done.
Push the branch
: when Claude reaches a stopping point, it pushes its branch to GitHub. You review the diff, leave inline comments, create a PR, or send another message to keep going.
The session doesn’t close when the branch is pushed. PR creation and further edits all happen within the same conversation.
​
Compare ways to run Claude Code
Claude Code behaves the same everywhere. What changes is where code executes and whether your local config is available. The Desktop app offers both local and cloud sessions, so its answers below depend on which you choose:
On the web
Remote Control
Terminal CLI
Desktop app
Code runs on
Anthropic cloud VM
Your machine
Your machine
Your machine or cloud VM
You chat from
claude.ai or mobile app
claude.ai or mobile app
Your terminal
The Desktop UI
Uses your local config
No, repo only
Yes
Yes
Yes for local, no for cloud
Requires GitHub
Yes, or
bundle a local repo
via
--remote
No
No
Only for cloud sessions
Keeps running if you disconnect
Yes
While terminal stays open
No
Depends on session type
Permission modes
Auto accept edits, Plan
Ask, Auto accept edits, Plan
All modes
Depends on session type
Network access
Configurable per environment
Your machine’s network
Your machine’s network
Depends on session type
See the
terminal quickstart
,
Desktop app
, or
Remote Control
docs to set those up.
​
Connect GitHub and create an environment
Setup is a one-time process. If you already use the GitHub CLI, you can
do this from your terminal
instead of the browser.
1
Visit claude.ai/code
Go to
claude.ai/code
and sign in with your Anthropic account.
2
Install the Claude GitHub App
After signing in, claude.ai/code prompts you to connect GitHub. Follow the prompt to install the Claude GitHub App and grant it access to your repositories. Cloud sessions work with existing GitHub repositories, so to start a new project,
create an empty repository on GitHub
first.
3
Create your environment
After connecting GitHub, you’ll be prompted to create a cloud environment. The environment controls what network access Claude has during sessions and what runs when a new session is created. See
Installed tools
for what’s available without any configuration.
The form has these fields:
Name
: a display label. Useful when you have multiple environments for different projects or access levels.
Network access
: controls what the session can reach on the internet. The default,
Trusted
, allows connections to
common package registries
like npm, PyPI, and RubyGems while blocking general internet access.
Environment variables
: optional variables available in every session, in
.env
format. Don’t wrap values in quotes, since quotes are stored as part of the value. These are visible to anyone who can edit this environment.
Setup script
: an optional Bash script that runs before Claude Code launches. Use it to install system tools the cloud VM doesn’t include, like
apt install -y gh
. The result is
cached
, so the script doesn’t re-run on every session. See
Setup scripts
for examples and debugging tips.
For a first project, leave the defaults and click
Create environment
. You can
edit it later or create additional environments
for different projects.
​
Connect from your terminal
If you already use the GitHub CLI (
gh
), you can set up Claude Code on the web without opening a browser. This requires the
Claude Code CLI
.
/web-setup
reads your local
gh
token, links it to your Claude account, and creates a default cloud environment if you don’t have one.
Organizations with
Zero Data Retention
enabled cannot use
/web-setup
or other cloud session features. If the GitHub CLI isn’t installed or authenticated,
/web-setup
opens the browser onboarding flow instead.
1
Authenticate with the GitHub CLI
In your shell, authenticate the GitHub CLI if you haven’t already:
gh
auth
login
2
Sign in to Claude
In the Claude Code CLI, run
/login
to sign in with your claude.ai account. Skip this step if you’re already signed in.
3
Run /web-setup
In the Claude Code CLI, run:
/web-setup
This syncs your
gh
token to your Claude account. If you don’t have a cloud environment yet,
/web-setup
creates one with Trusted network access and no setup script. You can
edit the environment or add variables
afterward. Once
/web-setup
completes, you can start cloud sessions from your terminal with
--remote
or set up recurring tasks with
/schedule
.
​
Start a task
With GitHub connected and an environment created, you’re ready to submit tasks.
1
Select a repository and branch
From
claude.ai/code
or the Code tab in the Claude mobile app, click the repository selector below the input box and choose a repository for Claude to work in. Each repository shows a branch selector. Change it to start Claude from a feature branch instead of the default. You can add multiple repositories to work across them in one session.
2
Choose a permission mode
The mode dropdown next to the input defaults to
Auto accept edits
, where Claude makes changes and pushes a branch without stopping for approval. Switch to
Plan mode
if you want Claude to propose an approach and wait for your go-ahead before editing files. Cloud sessions don’t offer Ask permissions, Auto mode, or Bypass permissions. See
Permission modes
for the full list.
3
Describe the task and submit
Type a description of what you want and press Enter. Be specific:
Name the file or function: “Add a README with setup instructions” or “Fix the failing auth test in
tests/test_auth.py
” is better than “fix tests”
Paste error output if you have it
Describe the expected behavior, not just the symptom
Claude clones the repositories, runs your setup script if configured, and starts working. Each task gets its own session and its own branch, so you don’t need to wait for one to finish before starting another.
​
Pre-fill sessions
You can prefill the prompt, repositories, and environment for a new session by adding query parameters to the
claude.ai/code
URL. Use this to build integrations such as a button in your issue tracker that opens Claude Code with the issue description as the prompt.
Parameter
Description
prompt
Prompt text to prefill in the input box. The alias
q
is also accepted.
prompt_url
URL to fetch the prompt text from, for prompts too long to embed in a query string. The URL must allow cross-origin requests. Ignored when
prompt
is also set.
repositories
Comma-separated list of
owner/repo
slugs to preselect. The alias
repo
is also accepted.
environment
Name or ID of the
environment
to preselect.
URL-encode each value. The example below opens the form with a prompt and a repository already selected:
https://claude.ai/code?prompt=Fix%20the%20login%20bug&repositories=acme/webapp
​
Review and iterate
When Claude finishes, review the changes, leave feedback on specific lines, and keep going until the diff looks right.
1
Open the diff view
A diff indicator shows lines added and removed across the session, for example
+42 -18
. Select it to open the diff view, with a file list on the left and changes on the right.
2
Leave inline comments
Select any line in the diff, type your feedback, and press Enter. Comments queue up until you send your next message, then they’re bundled with it. Claude sees “at
src/auth.ts:47
, don’t catch the error here” alongside your main instruction, so you don’t have to describe where the problem is.
3
Create a pull request
When the diff looks right, select
Create PR
at the top of the diff view. You can open it as a full PR, a draft, or jump to GitHub’s compose page with a generated title and description.
4
Keep iterating after the PR
The session stays live after the PR is created. Paste CI failure output or reviewer comments into the chat and ask Claude to address them. To have Claude monitor the PR automatically, see
Auto-fix pull requests
.
​
Troubleshoot setup
​
No repositories appear after connecting GitHub
A cloud session can use any repository the connected GitHub account can see, regardless of which repositories the Claude GitHub App is installed on. If a repository is missing, verify the connected GitHub account has access to it on GitHub. If you also want
Auto-fix
for a repository, install the App on it: on github.com, open
Settings → Applications → Claude → Configure
and verify the repository is listed under
Repository access
. Private repositories need the same authorization as public ones.
​
The page only shows a GitHub login button
Cloud sessions require a connected GitHub account. Connect via the browser flow above, or run
/web-setup
from your terminal if you use the GitHub CLI. If you’d rather not connect GitHub at all, see
Remote Control
to run Claude Code on your own machine and monitor it from the web.
​
”Not available for the selected organization”
Enterprise organizations may need an admin to enable Claude Code on the web. Contact your Anthropic account team.
​
/web-setup
returns “Unknown command”
/web-setup
runs inside the Claude Code CLI, not your shell. Launch
claude
first, then type
/web-setup
at the prompt.
If you typed it inside Claude Code and still see the error, your CLI is older than v2.1.80 or you’re authenticated with an API key or third-party provider instead of a claude.ai subscription. Run
claude update
, then
/login
to sign in with your claude.ai account.
​
”Could not create a cloud environment” or “No cloud environment available” when using
--remote
or ultraplan
Remote-session features create a default cloud environment automatically if you don’t have one. If you see “Could not create a cloud environment”, automatic creation failed. If you see “No cloud environment available”, your CLI predates automatic creation. In either case, run
/web-setup
in the Claude Code CLI to create one manually, or visit
claude.ai/code
and follow the
Create your environment
step above.
​
Setup script failed
The setup script exited with a non-zero status, which blocks the session from starting. Common causes:
A package install failed because the registry isn’t in your
network access level
.
Trusted
covers most package managers;
None
blocks them all.
The script references a file or path that doesn’t exist in a fresh clone.
A command that works locally needs a different invocation on Ubuntu.
To debug, add
set -x
at the top of the script to see which command failed. For non-critical commands, append
|| true
so they don’t block session start.
​
New sessions hang or time out during setup
If new sessions stall on the setup script step or fail with a generic container error before the script finishes, the script is likely exceeding the roughly five-minute time budget for building the
environment cache
. Heavy steps such as pulling large Docker images, syncing full dependency trees, or downloading model weights often push the total over the limit, especially when they run one after another.
To fix this, trim the script so it reliably finishes in under five minutes:
Run independent installs in parallel with
&
and a final
wait
instead of running them serially.
Move the largest downloads out of the setup script and into a
SessionStart hook
that launches them in the background, so the session becomes usable while they finish.
Remove long retry sleeps from the setup script, since a stalled retry loop counts against the budget.
​
Session keeps running after closing the tab
This is by design. Closing the tab or navigating away doesn’t stop the session. It continues running in the background until Claude finishes the current task, then idles. From the sidebar, you can
archive a session
to hide it from your list, or
delete it
to remove it permanently.
​
Next steps
Now that you can submit and review tasks, these pages cover what comes next: starting cloud sessions from your terminal, scheduling recurring work, and giving Claude standing instructions.
Use Claude Code on the web
: the full reference, including teleporting sessions to your terminal, setup scripts, environment variables, and network config
Routines
: automate work on a schedule, via API call, or in response to GitHub events
CLAUDE.md
: give Claude persistent instructions and context that load at the start of every session
Install the Claude mobile app for
iOS
or
Android
to monitor sessions from your phone. From the Claude Code CLI,
/mobile
shows a QR code.
Was this page helpful?
Yes
No
Remote Control
Reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/web-quickstart" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 16 · April 13–17, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w16</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w16</guid>
  <pubDate>Mon, 06 May 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 16 · April 13–17, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.105 → v2.1.113
5 features...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 16 · April 13–17, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.105 → v2.1.113
5 features · April 13–17
Claude Opus 4.7
new model
Anthropic’s strongest coding model yet is now the default on Max and Team Premium, and available everywhere else from
/model
. It adds a new
xhigh
effort level that sits between
high
and
max
: best results for most coding and agentic tasks, applied as the default the first time you switch to 4.7.
/effort
now opens an interactive arrow-key slider when you call it without arguments, so you can dial intelligence against speed without remembering the level names.
Switch model and effort in one go:
Claude Code
> /model opus
> /effort xhigh
Model config: effort levels
Routines
web
Templated cloud agents that fire on a schedule, a GitHub event, or an API call. Define a routine once on Claude Code on the web with a prompt, the repos it can touch, and the connectors it needs, then let PR-opened, release-published, or your own webhook trigger it without your machine running. The trigger picker now covers GitHub events with optional filters and gives every routine a tokened
/fire
endpoint for external systems.
Create one from the web UI, or scaffold from your terminal:
Claude Code
> /schedule daily PR review at 9am
Routines guide
/usage breakdown
CLI
More visibility into where your Claude Code usage goes.
/usage
now shows what’s driving your limits: parallel sessions, subagents, cache misses, and long context, each with a percentage of your last 24 hours and a tip to optimize it. Press
d
or
w
to switch between day and week views.
Run it any time:
Claude Code
> /usage
Commands reference
Mobile push notifications
mobile
With
Remote Control
connected, Claude can send a push notification to your phone when a long task finishes or it needs a decision to keep going. Turn it on with “Push when Claude decides” in
/config
, or ask for one in your prompt. Useful when you kick off a long agent run and want to step away from the terminal.
Ask Claude to ping you when it’s done:
Claude Code
> notify me when the tests pass
Remote Control: mobile push notifications
Native binaries
v2.1.113
The
claude
CLI now spawns a native per-platform binary instead of bundled JavaScript, so the installed
claude
command no longer invokes Node. The npm package pulls the right binary in through an optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
, so your install command doesn’t change. The standalone installer already shipped this binary; npm now matches it.
Upgrade and check what you’re running:
claude
update
claude
--version
Setup guide
Other wins
New
/ultrareview
: comprehensive code review in the cloud using parallel multi-agent analysis and an adversarial critique pass. Run it bare to review your current branch, or
/ultrareview <PR#>
for a specific PR
Auto mode
is now available for Max subscribers on Opus 4.7, and the
—enable-auto-mode
flag is no longer required
Session recap
shows a one-line summary of what happened while you were away; run
/recap
on demand or turn it off from
/config
New
/tui
command and
tui
setting switch between classic and flicker-free rendering mid-conversation; focus view moved from
Ctrl+O
to its own
/focus
command
Plugins can ship background watchers via a top-level
monitors
manifest key that auto-arms at session start or on skill invoke
”Auto (match terminal)” option in
/theme
follows your terminal’s dark/light mode
/fewer-permission-prompts
scans your transcripts for common read-only Bash and MCP calls and proposes an allowlist for
.claude/settings.json
Claude can now discover and run built-in commands like
/init
,
/review
, and
/security-review
via the Skill tool
PreCompact
hooks can block compaction by exiting with code 2 or returning
{“decision”:“block”}
ENABLE_PROMPT_CACHING_1H
opts API key, Bedrock, Vertex, and Foundry users into 1-hour prompt cache TTL
sandbox.network.deniedDomains
setting carves specific domains out of a broader
allowedDomains
wildcard
/undo
is now an alias for
/rewind
, and
/proactive
is an alias for
/loop
Hardened Bash permissions: deny rules now match through
env
/
sudo
/
watch
wrappers, and
Bash(find:*)
allow rules no longer auto-approve
-exec
or
-delete
Full changelog for v2.1.105–v2.1.113 →
Was this page helpful?
Yes
No
Week 17 · Apr 20–24
Week 15 · Apr 6–10
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w16" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 16 · April 13–17, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.105 → v2.1.113
5 features...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 16 · April 13–17, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.105 → v2.1.113
5 features · April 13–17
Claude Opus 4.7
new model
Anthropic’s strongest coding model yet is now the default on Max and Team Premium, and available everywhere else from
/model
. It adds a new
xhigh
effort level that sits between
high
and
max
: best results for most coding and agentic tasks, applied as the default the first time you switch to 4.7.
/effort
now opens an interactive arrow-key slider when you call it without arguments, so you can dial intelligence against speed without remembering the level names.
Switch model and effort in one go:
Claude Code
> /model opus
> /effort xhigh
Model config: effort levels
Routines
web
Templated cloud agents that fire on a schedule, a GitHub event, or an API call. Define a routine once on Claude Code on the web with a prompt, the repos it can touch, and the connectors it needs, then let PR-opened, release-published, or your own webhook trigger it without your machine running. The trigger picker now covers GitHub events with optional filters and gives every routine a tokened
/fire
endpoint for external systems.
Create one from the web UI, or scaffold from your terminal:
Claude Code
> /schedule daily PR review at 9am
Routines guide
/usage breakdown
CLI
More visibility into where your Claude Code usage goes.
/usage
now shows what’s driving your limits: parallel sessions, subagents, cache misses, and long context, each with a percentage of your last 24 hours and a tip to optimize it. Press
d
or
w
to switch between day and week views.
Run it any time:
Claude Code
> /usage
Commands reference
Mobile push notifications
mobile
With
Remote Control
connected, Claude can send a push notification to your phone when a long task finishes or it needs a decision to keep going. Turn it on with “Push when Claude decides” in
/config
, or ask for one in your prompt. Useful when you kick off a long agent run and want to step away from the terminal.
Ask Claude to ping you when it’s done:
Claude Code
> notify me when the tests pass
Remote Control: mobile push notifications
Native binaries
v2.1.113
The
claude
CLI now spawns a native per-platform binary instead of bundled JavaScript, so the installed
claude
command no longer invokes Node. The npm package pulls the right binary in through an optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
, so your install command doesn’t change. The standalone installer already shipped this binary; npm now matches it.
Upgrade and check what you’re running:
claude
update
claude
--version
Setup guide
Other wins
New
/ultrareview
: comprehensive code review in the cloud using parallel multi-agent analysis and an adversarial critique pass. Run it bare to review your current branch, or
/ultrareview <PR#>
for a specific PR
Auto mode
is now available for Max subscribers on Opus 4.7, and the
—enable-auto-mode
flag is no longer required
Session recap
shows a one-line summary of what happened while you were away; run
/recap
on demand or turn it off from
/config
New
/tui
command and
tui
setting switch between classic and flicker-free rendering mid-conversation; focus view moved from
Ctrl+O
to its own
/focus
command
Plugins can ship background watchers via a top-level
monitors
manifest key that auto-arms at session start or on skill invoke
”Auto (match terminal)” option in
/theme
follows your terminal’s dark/light mode
/fewer-permission-prompts
scans your transcripts for common read-only Bash and MCP calls and proposes an allowlist for
.claude/settings.json
Claude can now discover and run built-in commands like
/init
,
/review
, and
/security-review
via the Skill tool
PreCompact
hooks can block compaction by exiting with code 2 or returning
{“decision”:“block”}
ENABLE_PROMPT_CACHING_1H
opts API key, Bedrock, Vertex, and Foundry users into 1-hour prompt cache TTL
sandbox.network.deniedDomains
setting carves specific domains out of a broader
allowedDomains
wildcard
/undo
is now an alias for
/rewind
, and
/proactive
is an alias for
/loop
Hardened Bash permissions: deny rules now match through
env
/
sudo
/
watch
wrappers, and
Bash(find:*)
allow rules no longer auto-approve
-exec
or
-delete
Full changelog for v2.1.105–v2.1.113 →
Was this page helpful?
Yes
No
Week 17 · Apr 20–24
Week 15 · Apr 6–10
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w16" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Configure permissions</title>
  <link>https://code.claude.com/docs/en/agent-sdk/permissions</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/permissions</guid>
  <pubDate>Sun, 05 May 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Configure permissions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Configure permissions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK provides permission controls to manage how Claude uses tools. Use permission modes and rules to define what’s allowed automatically, and the
canUseTool
callback
to handle everything else at runtime.
This page covers permission modes and rules. To build interactive approval flows where users approve or deny tool requests at runtime, see
Handle approvals and user input
.
​
How permissions are evaluated
When Claude requests a tool, the SDK checks permissions in this order:
1
Hooks
Run
hooks
first. A hook can deny the call outright or pass it on. A hook that returns
allow
does not skip the deny and ask rules below; those are evaluated regardless of the hook result.
2
Deny rules
Check
deny
rules (from
disallowed_tools
and
settings.json
). If a deny rule matches, the tool is blocked, even in
bypassPermissions
mode.
3
Permission mode
Apply the active
permission mode
.
bypassPermissions
approves everything that reaches this step.
acceptEdits
approves file operations. Other modes fall through.
4
Allow rules
Check
allow
rules (from
allowed_tools
and settings.json). If a rule matches, the tool is approved.
5
canUseTool callback
If not resolved by any of the above, call your
canUseTool
callback
for a decision. In
dontAsk
mode, this step is skipped and the tool is denied.
This page focuses on
allow and deny rules
and
permission modes
. For the other steps:
Hooks:
run custom code to allow, deny, or modify tool requests. See
Control execution with hooks
.
canUseTool callback:
prompt users for approval at runtime. See
Handle approvals and user input
.
​
Allow and deny rules
allowed_tools
and
disallowed_tools
(TypeScript:
allowedTools
/
disallowedTools
) add entries to the allow and deny rule lists in the evaluation flow above. They control whether a tool call is approved, not whether the tool is available to Claude.
Option
Effect
allowed_tools=["Read", "Grep"]
Read
and
Grep
are auto-approved. Tools not listed here still exist and fall through to the permission mode and
canUseTool
.
disallowed_tools=["Bash"]
Bash
is always denied. Deny rules are checked first and hold in every permission mode, including
bypassPermissions
.
For a locked-down agent, pair
allowedTools
with
permissionMode: "dontAsk"
. Listed tools are approved; anything else is denied outright instead of prompting:
const
options
=
{
allowedTools:
[
"Read"
,
"Glob"
,
"Grep"
],
permissionMode:
"dontAsk"
};
allowed_tools
does not constrain
bypassPermissions
.
allowed_tools
only pre-approves the tools you list. Unlisted tools are not matched by any allow rule and fall through to the permission mode, where
bypassPermissions
approves them. Setting
allowed_tools=["Read"]
alongside
permission_mode="bypassPermissions"
still approves every tool, including
Bash
,
Write
, and
Edit
. If you need
bypassPermissions
but want specific tools blocked, use
disallowed_tools
.
You can also configure allow, deny, and ask rules declaratively in
.claude/settings.json
. These rules are read when the
project
setting source is enabled, which it is for default
query()
options. If you set
setting_sources
(TypeScript:
settingSources
) explicitly, include
"project"
for them to apply. See
Permission settings
for the rule syntax.
​
Permission modes
Permission modes provide global control over how Claude uses tools. You can set the permission mode when calling
query()
or change it dynamically during streaming sessions.
​
Available modes
The SDK supports these permission modes:
Mode
Description
Tool behavior
default
Standard permission behavior
No auto-approvals; unmatched tools trigger your
canUseTool
callback
dontAsk
Deny instead of prompting
Anything not pre-approved by
allowed_tools
or rules is denied;
canUseTool
is never called
acceptEdits
Auto-accept file edits
File edits and
filesystem operations
(
mkdir
,
rm
,
mv
, etc.) are automatically approved
bypassPermissions
Bypass all permission checks
All tools run without permission prompts (use with caution)
plan
Planning mode
Read-only tools run; Claude analyzes and plans without editing your source files
auto
(TypeScript only)
Model-classified approvals
A model classifier approves or denies each tool call. See
Auto mode
for availability
Subagent inheritance:
When the parent uses
bypassPermissions
,
acceptEdits
, or
auto
, all subagents inherit that mode and it cannot be overridden per subagent. Subagents may have different system prompts and less constrained behavior than your main agent, so inheriting
bypassPermissions
grants them full, autonomous system access without any approval prompts.
​
Set permission mode
You can set the permission mode once when starting a query, or change it dynamically while the session is active.
At query time
During streaming
Pass
permission_mode
(Python) or
permissionMode
(TypeScript) when creating a query. This mode applies for the entire session unless changed dynamically.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Help me refactor this code"
,
options
=
ClaudeAgentOptions(
permission_mode
=
"default"
,
# Set the mode here
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Call
set_permission_mode()
(Python) or
setPermissionMode()
(TypeScript) to change the mode mid-session. The new mode takes effect immediately for all subsequent tool requests. This lets you start restrictive and loosen permissions as trust builds, for example switching to
acceptEdits
after reviewing Claude’s initial approach.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions
async
def
main
():
async
with
ClaudeSDKClient(
options
=
ClaudeAgentOptions(
permission_mode
=
"default"
,
# Start in default mode
)
)
as
client:
await
client.query(
"Help me refactor this code"
)
# Change mode dynamically mid-session
await
client.set_permission_mode(
"acceptEdits"
)
# Process messages with the new permission mode
async
for
message
in
client.receive_response():
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Mode details
​
Accept edits mode (
acceptEdits
)
Auto-approves file operations so Claude can edit code without prompting. Other tools (like Bash commands that aren’t filesystem operations) still require normal permissions.
Auto-approved operations:
File edits (Edit, Write tools)
Filesystem commands:
mkdir
,
touch
,
rm
,
rmdir
,
mv
,
cp
,
sed
Both apply only to paths inside the working directory or
additionalDirectories
. Paths outside that scope and writes to protected paths still prompt.
Use when:
you trust Claude’s edits and want faster iteration, such as during prototyping or when working in an isolated directory.
​
Don’t ask mode (
dontAsk
)
Converts any permission prompt into a denial. Tools pre-approved by
allowed_tools
,
settings.json
allow rules, or a hook run as normal. Everything else is denied without calling
canUseTool
.
Use when:
you want a fixed, explicit tool surface for a headless agent and prefer a hard deny over silent reliance on
canUseTool
being absent.
​
Bypass permissions mode (
bypassPermissions
)
Auto-approves all tool uses without prompts. Hooks still execute and can block operations if needed.
Use with extreme caution. Claude has full system access in this mode. Only use in controlled environments where you trust all possible operations.
allowed_tools
does not constrain this mode. Every tool is approved, not just the ones you listed. Deny rules (
disallowed_tools
), explicit
ask
rules, and hooks are evaluated before the mode check and can still block a tool.
​
Plan mode (
plan
)
Restricts Claude to read-only tools. Claude can read files and run read-only shell commands to explore the codebase but does not edit your source files. Claude may use
AskUserQuestion
to clarify requirements before finalizing the plan. See
Handle approvals and user input
for handling these prompts.
Use when:
you want Claude to propose changes without executing them, such as during code review or when you need to approve changes before they’re made.
​
Related resources
For the other steps in the permission evaluation flow:
Handle approvals and user input
: interactive approval prompts and clarifying questions
Hooks guide
: run custom code at key points in the agent lifecycle
Permission rules
: declarative allow/deny rules in
settings.json
Was this page helpful?
Yes
No
Plugins in the SDK
Intercept and control agent behavior with hooks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/permissions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Configure permissions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Control and observability
Configure permissions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Claude Agent SDK provides permission controls to manage how Claude uses tools. Use permission modes and rules to define what’s allowed automatically, and the
canUseTool
callback
to handle everything else at runtime.
This page covers permission modes and rules. To build interactive approval flows where users approve or deny tool requests at runtime, see
Handle approvals and user input
.
​
How permissions are evaluated
When Claude requests a tool, the SDK checks permissions in this order:
1
Hooks
Run
hooks
first. A hook can deny the call outright or pass it on. A hook that returns
allow
does not skip the deny and ask rules below; those are evaluated regardless of the hook result.
2
Deny rules
Check
deny
rules (from
disallowed_tools
and
settings.json
). If a deny rule matches, the tool is blocked, even in
bypassPermissions
mode.
3
Permission mode
Apply the active
permission mode
.
bypassPermissions
approves everything that reaches this step.
acceptEdits
approves file operations. Other modes fall through.
4
Allow rules
Check
allow
rules (from
allowed_tools
and settings.json). If a rule matches, the tool is approved.
5
canUseTool callback
If not resolved by any of the above, call your
canUseTool
callback
for a decision. In
dontAsk
mode, this step is skipped and the tool is denied.
This page focuses on
allow and deny rules
and
permission modes
. For the other steps:
Hooks:
run custom code to allow, deny, or modify tool requests. See
Control execution with hooks
.
canUseTool callback:
prompt users for approval at runtime. See
Handle approvals and user input
.
​
Allow and deny rules
allowed_tools
and
disallowed_tools
(TypeScript:
allowedTools
/
disallowedTools
) add entries to the allow and deny rule lists in the evaluation flow above. They control whether a tool call is approved, not whether the tool is available to Claude.
Option
Effect
allowed_tools=["Read", "Grep"]
Read
and
Grep
are auto-approved. Tools not listed here still exist and fall through to the permission mode and
canUseTool
.
disallowed_tools=["Bash"]
Bash
is always denied. Deny rules are checked first and hold in every permission mode, including
bypassPermissions
.
For a locked-down agent, pair
allowedTools
with
permissionMode: "dontAsk"
. Listed tools are approved; anything else is denied outright instead of prompting:
const
options
=
{
allowedTools:
[
"Read"
,
"Glob"
,
"Grep"
],
permissionMode:
"dontAsk"
};
allowed_tools
does not constrain
bypassPermissions
.
allowed_tools
only pre-approves the tools you list. Unlisted tools are not matched by any allow rule and fall through to the permission mode, where
bypassPermissions
approves them. Setting
allowed_tools=["Read"]
alongside
permission_mode="bypassPermissions"
still approves every tool, including
Bash
,
Write
, and
Edit
. If you need
bypassPermissions
but want specific tools blocked, use
disallowed_tools
.
You can also configure allow, deny, and ask rules declaratively in
.claude/settings.json
. These rules are read when the
project
setting source is enabled, which it is for default
query()
options. If you set
setting_sources
(TypeScript:
settingSources
) explicitly, include
"project"
for them to apply. See
Permission settings
for the rule syntax.
​
Permission modes
Permission modes provide global control over how Claude uses tools. You can set the permission mode when calling
query()
or change it dynamically during streaming sessions.
​
Available modes
The SDK supports these permission modes:
Mode
Description
Tool behavior
default
Standard permission behavior
No auto-approvals; unmatched tools trigger your
canUseTool
callback
dontAsk
Deny instead of prompting
Anything not pre-approved by
allowed_tools
or rules is denied;
canUseTool
is never called
acceptEdits
Auto-accept file edits
File edits and
filesystem operations
(
mkdir
,
rm
,
mv
, etc.) are automatically approved
bypassPermissions
Bypass all permission checks
All tools run without permission prompts (use with caution)
plan
Planning mode
Read-only tools run; Claude analyzes and plans without editing your source files
auto
(TypeScript only)
Model-classified approvals
A model classifier approves or denies each tool call. See
Auto mode
for availability
Subagent inheritance:
When the parent uses
bypassPermissions
,
acceptEdits
, or
auto
, all subagents inherit that mode and it cannot be overridden per subagent. Subagents may have different system prompts and less constrained behavior than your main agent, so inheriting
bypassPermissions
grants them full, autonomous system access without any approval prompts.
​
Set permission mode
You can set the permission mode once when starting a query, or change it dynamically while the session is active.
At query time
During streaming
Pass
permission_mode
(Python) or
permissionMode
(TypeScript) when creating a query. This mode applies for the entire session unless changed dynamically.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions
async
def
main
():
async
for
message
in
query(
prompt
=
"Help me refactor this code"
,
options
=
ClaudeAgentOptions(
permission_mode
=
"default"
,
# Set the mode here
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
Call
set_permission_mode()
(Python) or
setPermissionMode()
(TypeScript) to change the mode mid-session. The new mode takes effect immediately for all subsequent tool requests. This lets you start restrictive and loosen permissions as trust builds, for example switching to
acceptEdits
after reviewing Claude’s initial approach.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
ClaudeSDKClient, ClaudeAgentOptions
async
def
main
():
async
with
ClaudeSDKClient(
options
=
ClaudeAgentOptions(
permission_mode
=
"default"
,
# Start in default mode
)
)
as
client:
await
client.query(
"Help me refactor this code"
)
# Change mode dynamically mid-session
await
client.set_permission_mode(
"acceptEdits"
)
# Process messages with the new permission mode
async
for
message
in
client.receive_response():
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Mode details
​
Accept edits mode (
acceptEdits
)
Auto-approves file operations so Claude can edit code without prompting. Other tools (like Bash commands that aren’t filesystem operations) still require normal permissions.
Auto-approved operations:
File edits (Edit, Write tools)
Filesystem commands:
mkdir
,
touch
,
rm
,
rmdir
,
mv
,
cp
,
sed
Both apply only to paths inside the working directory or
additionalDirectories
. Paths outside that scope and writes to protected paths still prompt.
Use when:
you trust Claude’s edits and want faster iteration, such as during prototyping or when working in an isolated directory.
​
Don’t ask mode (
dontAsk
)
Converts any permission prompt into a denial. Tools pre-approved by
allowed_tools
,
settings.json
allow rules, or a hook run as normal. Everything else is denied without calling
canUseTool
.
Use when:
you want a fixed, explicit tool surface for a headless agent and prefer a hard deny over silent reliance on
canUseTool
being absent.
​
Bypass permissions mode (
bypassPermissions
)
Auto-approves all tool uses without prompts. Hooks still execute and can block operations if needed.
Use with extreme caution. Claude has full system access in this mode. Only use in controlled environments where you trust all possible operations.
allowed_tools
does not constrain this mode. Every tool is approved, not just the ones you listed. Deny rules (
disallowed_tools
), explicit
ask
rules, and hooks are evaluated before the mode check and can still block a tool.
​
Plan mode (
plan
)
Restricts Claude to read-only tools. Claude can read files and run read-only shell commands to explore the codebase but does not edit your source files. Claude may use
AskUserQuestion
to clarify requirements before finalizing the plan. See
Handle approvals and user input
for handling these prompts.
Use when:
you want Claude to propose changes without executing them, such as during code review or when you need to approve changes before they’re made.
​
Related resources
For the other steps in the permission evaluation flow:
Handle approvals and user input
: interactive approval prompts and clarifying questions
Hooks guide
: run custom code at key points in the agent lifecycle
Permission rules
: declarative allow/deny rules in
settings.json
Was this page helpful?
Yes
No
Plugins in the SDK
Intercept and control agent behavior with hooks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/permissions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Work with sessions</title>
  <link>https://code.claude.com/docs/en/agent-sdk/sessions</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/sessions</guid>
  <pubDate>Sat, 04 May 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Work with sessions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Work with sessions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A session is the conversation history the SDK accumulates while your agent works. It contains your prompt, every tool call the agent made, every tool result, and every response. The SDK writes it to disk automatically so you can return to it later.
Returning to a session means the agent has full context from before: files it already read, analysis it already performed, decisions it already made. You can ask a follow-up question, recover from an interruption, or branch off to try a different approach.
Sessions persist the
conversation
, not the filesystem. To snapshot and revert file changes the agent made, use
file checkpointing
.
This guide covers how to pick the right approach for your app, the SDK interfaces that track sessions automatically, how to capture session IDs and use
resume
and
fork
manually, and what to know about resuming sessions across hosts.
​
Choose an approach
How much session handling you need depends on your application’s shape. Session management comes into play when you send multiple prompts that should share context. Within a single
query()
call, the agent already takes as many turns as it needs, and permission prompts and
AskUserQuestion
are
handled in-loop
(they don’t end the call).
What you’re building
What to use
One-shot task: single prompt, no follow-up
Nothing extra. One
query()
call handles it.
Multi-turn chat in one process
ClaudeSDKClient
(Python) or
continue: true
(TypeScript)
. The SDK tracks the session for you with no ID handling.
Pick up where you left off after a process restart
continue_conversation=True
(Python) /
continue: true
(TypeScript). Resumes the most recent session in the directory, no ID needed.
Resume a specific past session (not the most recent)
Capture the session ID and pass it to
resume
.
Try an alternative approach without losing the original
Fork the session.
Stateless task, don’t want anything written to disk (TypeScript only)
Set
persistSession: false
. The session exists only in memory for the duration of the call. Python always persists to disk.
​
Continue, resume, and fork
Continue, resume, and fork are option fields you set on
query()
(
ClaudeAgentOptions
in Python,
Options
in TypeScript).
Continue
and
resume
both pick up an existing session and add to it. The difference is how they find that session:
Continue
finds the most recent session in the current directory. You don’t track anything. Works well when your app runs one conversation at a time.
Resume
takes a specific session ID. You track the ID. Required when you have multiple sessions (for example, one per user in a multi-user app) or want to return to one that isn’t the most recent.
Fork
is different: it creates a new session that starts with a copy of the original’s history. The original stays unchanged. Use fork to try a different direction while keeping the option to go back.
​
Automatic session management
Both SDKs offer an interface that tracks session state for you across calls, so you don’t pass IDs around manually. Use these for multi-turn conversations within a single process.
​
Python:
ClaudeSDKClient
ClaudeSDKClient
handles session IDs internally. Each call to
client.query()
automatically continues the same session. Call
client.receive_response()
to iterate over the messages for the current query. The client must be used as an async context manager.
This example runs two queries against the same
client
. The first asks the agent to analyze a module; the second asks it to refactor that module. Because both calls go through the same client instance, the second query has full context from the first without any explicit
resume
or session ID:
Python
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ResultMessage,
TextBlock,
)
def
print_response
(
message
):
"""Print only the human-readable parts of a message."""
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(block.text)
elif
isinstance
(message, ResultMessage):
cost
=
(
f
"$
{
message.total_cost_usd
:.4f}
"
if
message.total_cost_usd
is
not
None
else
"N/A"
)
print
(
f
"[done:
{
message.subtype
}
, cost:
{
cost
}
]"
)
async
def
main
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"Grep"
],
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
# First query: client captures the session ID internally
await
client.query(
"Analyze the auth module"
)
async
for
message
in
client.receive_response():
print_response(message)
# Second query: automatically continues the same session
await
client.query(
"Now refactor it to use JWT"
)
async
for
message
in
client.receive_response():
print_response(message)
asyncio.run(main())
See the
Python SDK reference
for details on when to use
ClaudeSDKClient
vs the standalone
query()
function.
​
TypeScript:
continue: true
The stable TypeScript SDK (the
query()
function used throughout these docs, sometimes called V1) doesn’t have a session-holding client object like Python’s
ClaudeSDKClient
. Instead, pass
continue: true
on each subsequent
query()
call and the SDK picks up the most recent session in the current directory. No ID tracking required.
This example makes two separate
query()
calls. The first creates a fresh session; the second sets
continue: true
, which tells the SDK to find and resume the most recent session on disk. The agent has full context from the first call:
TypeScript
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// First query: creates a new session
for
await
(
const
message
of
query
({
prompt:
"Analyze the auth module"
,
options:
{
allowedTools:
[
"Read"
,
"Glob"
,
"Grep"
] }
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
// Second query: continue: true resumes the most recent session
for
await
(
const
message
of
query
({
prompt:
"Now refactor it to use JWT"
,
options:
{
continue:
true
,
allowedTools:
[
"Read"
,
"Edit"
,
"Write"
,
"Glob"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
The experimental
V2 session API
, which provided
createSession()
with a
send
/
stream
pattern, is deprecated. Use the V1
query()
function and the session options described on this page instead.
​
Use session options with
query()
​
Capture the session ID
Resume and fork require a session ID. Read it from the
session_id
field on the result message (
ResultMessage
in Python,
SDKResultMessage
in TypeScript), which is present on every result regardless of success or error. In TypeScript the ID is also available earlier as a direct field on the init
SystemMessage
; in Python it’s nested inside
SystemMessage.data
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
main
():
session_id
=
None
async
for
message
in
query(
prompt
=
"Analyze the auth module and suggest improvements"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
),
):
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
if
message.subtype
==
"success"
:
print
(message.result)
print
(
f
"Session ID:
{
session_id
}
"
)
return
session_id
session_id
=
asyncio.run(main())
​
Resume by ID
Pass a session ID to
resume
to return to that specific session. The agent picks up with full context from wherever the session left off. Common reasons to resume:
Follow up on a completed task.
The agent already analyzed something; now you want it to act on that analysis without re-reading files.
Recover from a limit.
The first run ended with
error_max_turns
or
error_max_budget_usd
(see
Handle the result
); resume with a higher limit.
Restart your process.
You captured the ID before shutdown and want to restore the conversation.
This example resumes the session from
Capture the session ID
with a follow-up prompt. Because you’re resuming, the agent already has the prior analysis in context:
Python
TypeScript
# Earlier session analyzed the code; now build on that analysis
async
for
message
in
query(
prompt
=
"Now implement the refactoring you suggested"
,
options
=
ClaudeAgentOptions(
resume
=
session_id,
allowed_tools
=
[
"Read"
,
"Edit"
,
"Write"
,
"Glob"
,
"Grep"
],
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
If a
resume
call returns a fresh session instead of the expected history, the most common cause is a mismatched
cwd
. Sessions are stored under
~/.claude/projects/<encoded-cwd>/*.jsonl
, where
<encoded-cwd>
is the absolute working directory with every non-alphanumeric character replaced by
-
(so
/Users/me/proj
becomes
-Users-me-proj
). If your resume call runs from a different directory, the SDK looks in the wrong place. The session file also needs to exist on the current machine.
To resume sessions across machines or in serverless environments, mirror transcripts to shared storage with a
SessionStore
adapter
.
​
Fork to explore alternatives
Forking creates a new session that starts with a copy of the original’s history but diverges from that point. The fork gets its own session ID; the original’s ID and history stay unchanged. You end up with two independent sessions you can resume separately.
Forking branches the conversation history, not the filesystem. If a forked agent edits files, those changes are real and visible to any session working in the same directory. To branch and revert file changes, use
file checkpointing
.
This example builds on
Capture the session ID
: you’ve already analyzed an auth module in
session_id
and want to explore OAuth2 without losing the JWT-focused thread. The first block forks the session and captures the fork’s ID (
forked_id
); the second block resumes the original
session_id
to continue down the JWT path. You now have two session IDs pointing at two separate histories:
Python
TypeScript
# Fork: branch from session_id into a new session
forked_id
=
None
async
for
message
in
query(
prompt
=
"Instead of JWT, implement OAuth2 for the auth module"
,
options
=
ClaudeAgentOptions(
resume
=
session_id,
fork_session
=
True
,
),
):
if
isinstance
(message, ResultMessage):
forked_id
=
message.session_id
# The fork's ID, distinct from session_id
if
message.subtype
==
"success"
:
print
(message.result)
print
(
f
"Forked session:
{
forked_id
}
"
)
# Original session is untouched; resuming it continues the JWT thread
async
for
message
in
query(
prompt
=
"Continue with the JWT approach"
,
options
=
ClaudeAgentOptions(
resume
=
session_id),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
​
Resume across hosts
Session files are local to the machine that created them. To resume a session on a different host (CI workers, ephemeral containers, serverless), you have two options:
Move the session file.
Persist
~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
from the first run and restore it to the same path on the new host before calling
resume
. The
cwd
must match.
Don’t rely on session resume.
Capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session’s prompt. This is often more robust than shipping transcript files around.
Both SDKs expose functions for enumerating sessions on disk and reading their messages:
listSessions()
and
getSessionMessages()
in TypeScript,
list_sessions()
and
get_session_messages()
in Python. Use them to build custom session pickers, cleanup logic, or transcript viewers.
Both SDKs also expose functions for looking up and mutating individual sessions:
get_session_info()
,
rename_session()
, and
tag_session()
in Python, and
getSessionInfo()
,
renameSession()
, and
tagSession()
in TypeScript. Use them to organize sessions by tag or give them human-readable titles.
​
Related resources
How the agent loop works
: Understand turns, messages, and context accumulation within a session
File checkpointing
: Track and revert file changes across sessions
Python
ClaudeAgentOptions
: Full session option reference for Python
TypeScript
Options
: Full session option reference for TypeScript
Was this page helpful?
Yes
No
Use Claude Code features
Streaming Input
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/sessions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Work with sessions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Work with sessions
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A session is the conversation history the SDK accumulates while your agent works. It contains your prompt, every tool call the agent made, every tool result, and every response. The SDK writes it to disk automatically so you can return to it later.
Returning to a session means the agent has full context from before: files it already read, analysis it already performed, decisions it already made. You can ask a follow-up question, recover from an interruption, or branch off to try a different approach.
Sessions persist the
conversation
, not the filesystem. To snapshot and revert file changes the agent made, use
file checkpointing
.
This guide covers how to pick the right approach for your app, the SDK interfaces that track sessions automatically, how to capture session IDs and use
resume
and
fork
manually, and what to know about resuming sessions across hosts.
​
Choose an approach
How much session handling you need depends on your application’s shape. Session management comes into play when you send multiple prompts that should share context. Within a single
query()
call, the agent already takes as many turns as it needs, and permission prompts and
AskUserQuestion
are
handled in-loop
(they don’t end the call).
What you’re building
What to use
One-shot task: single prompt, no follow-up
Nothing extra. One
query()
call handles it.
Multi-turn chat in one process
ClaudeSDKClient
(Python) or
continue: true
(TypeScript)
. The SDK tracks the session for you with no ID handling.
Pick up where you left off after a process restart
continue_conversation=True
(Python) /
continue: true
(TypeScript). Resumes the most recent session in the directory, no ID needed.
Resume a specific past session (not the most recent)
Capture the session ID and pass it to
resume
.
Try an alternative approach without losing the original
Fork the session.
Stateless task, don’t want anything written to disk (TypeScript only)
Set
persistSession: false
. The session exists only in memory for the duration of the call. Python always persists to disk.
​
Continue, resume, and fork
Continue, resume, and fork are option fields you set on
query()
(
ClaudeAgentOptions
in Python,
Options
in TypeScript).
Continue
and
resume
both pick up an existing session and add to it. The difference is how they find that session:
Continue
finds the most recent session in the current directory. You don’t track anything. Works well when your app runs one conversation at a time.
Resume
takes a specific session ID. You track the ID. Required when you have multiple sessions (for example, one per user in a multi-user app) or want to return to one that isn’t the most recent.
Fork
is different: it creates a new session that starts with a copy of the original’s history. The original stays unchanged. Use fork to try a different direction while keeping the option to go back.
​
Automatic session management
Both SDKs offer an interface that tracks session state for you across calls, so you don’t pass IDs around manually. Use these for multi-turn conversations within a single process.
​
Python:
ClaudeSDKClient
ClaudeSDKClient
handles session IDs internally. Each call to
client.query()
automatically continues the same session. Call
client.receive_response()
to iterate over the messages for the current query. The client must be used as an async context manager.
This example runs two queries against the same
client
. The first asks the agent to analyze a module; the second asks it to refactor that module. Because both calls go through the same client instance, the second query has full context from the first without any explicit
resume
or session ID:
Python
import
asyncio
from
claude_agent_sdk
import
(
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ResultMessage,
TextBlock,
)
def
print_response
(
message
):
"""Print only the human-readable parts of a message."""
if
isinstance
(message, AssistantMessage):
for
block
in
message.content:
if
isinstance
(block, TextBlock):
print
(block.text)
elif
isinstance
(message, ResultMessage):
cost
=
(
f
"$
{
message.total_cost_usd
:.4f}
"
if
message.total_cost_usd
is
not
None
else
"N/A"
)
print
(
f
"[done:
{
message.subtype
}
, cost:
{
cost
}
]"
)
async
def
main
():
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Glob"
,
"Grep"
],
)
async
with
ClaudeSDKClient(
options
=
options)
as
client:
# First query: client captures the session ID internally
await
client.query(
"Analyze the auth module"
)
async
for
message
in
client.receive_response():
print_response(message)
# Second query: automatically continues the same session
await
client.query(
"Now refactor it to use JWT"
)
async
for
message
in
client.receive_response():
print_response(message)
asyncio.run(main())
See the
Python SDK reference
for details on when to use
ClaudeSDKClient
vs the standalone
query()
function.
​
TypeScript:
continue: true
The stable TypeScript SDK (the
query()
function used throughout these docs, sometimes called V1) doesn’t have a session-holding client object like Python’s
ClaudeSDKClient
. Instead, pass
continue: true
on each subsequent
query()
call and the SDK picks up the most recent session in the current directory. No ID tracking required.
This example makes two separate
query()
calls. The first creates a fresh session; the second sets
continue: true
, which tells the SDK to find and resume the most recent session on disk. The agent has full context from the first call:
TypeScript
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// First query: creates a new session
for
await
(
const
message
of
query
({
prompt:
"Analyze the auth module"
,
options:
{
allowedTools:
[
"Read"
,
"Glob"
,
"Grep"
] }
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
// Second query: continue: true resumes the most recent session
for
await
(
const
message
of
query
({
prompt:
"Now refactor it to use JWT"
,
options:
{
continue:
true
,
allowedTools:
[
"Read"
,
"Edit"
,
"Write"
,
"Glob"
,
"Grep"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
The experimental
V2 session API
, which provided
createSession()
with a
send
/
stream
pattern, is deprecated. Use the V1
query()
function and the session options described on this page instead.
​
Use session options with
query()
​
Capture the session ID
Resume and fork require a session ID. Read it from the
session_id
field on the result message (
ResultMessage
in Python,
SDKResultMessage
in TypeScript), which is present on every result regardless of success or error. In TypeScript the ID is also available earlier as a direct field on the init
SystemMessage
; in Python it’s nested inside
SystemMessage.data
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
main
():
session_id
=
None
async
for
message
in
query(
prompt
=
"Analyze the auth module and suggest improvements"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
),
):
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
if
message.subtype
==
"success"
:
print
(message.result)
print
(
f
"Session ID:
{
session_id
}
"
)
return
session_id
session_id
=
asyncio.run(main())
​
Resume by ID
Pass a session ID to
resume
to return to that specific session. The agent picks up with full context from wherever the session left off. Common reasons to resume:
Follow up on a completed task.
The agent already analyzed something; now you want it to act on that analysis without re-reading files.
Recover from a limit.
The first run ended with
error_max_turns
or
error_max_budget_usd
(see
Handle the result
); resume with a higher limit.
Restart your process.
You captured the ID before shutdown and want to restore the conversation.
This example resumes the session from
Capture the session ID
with a follow-up prompt. Because you’re resuming, the agent already has the prior analysis in context:
Python
TypeScript
# Earlier session analyzed the code; now build on that analysis
async
for
message
in
query(
prompt
=
"Now implement the refactoring you suggested"
,
options
=
ClaudeAgentOptions(
resume
=
session_id,
allowed_tools
=
[
"Read"
,
"Edit"
,
"Write"
,
"Glob"
,
"Grep"
],
),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
If a
resume
call returns a fresh session instead of the expected history, the most common cause is a mismatched
cwd
. Sessions are stored under
~/.claude/projects/<encoded-cwd>/*.jsonl
, where
<encoded-cwd>
is the absolute working directory with every non-alphanumeric character replaced by
-
(so
/Users/me/proj
becomes
-Users-me-proj
). If your resume call runs from a different directory, the SDK looks in the wrong place. The session file also needs to exist on the current machine.
To resume sessions across machines or in serverless environments, mirror transcripts to shared storage with a
SessionStore
adapter
.
​
Fork to explore alternatives
Forking creates a new session that starts with a copy of the original’s history but diverges from that point. The fork gets its own session ID; the original’s ID and history stay unchanged. You end up with two independent sessions you can resume separately.
Forking branches the conversation history, not the filesystem. If a forked agent edits files, those changes are real and visible to any session working in the same directory. To branch and revert file changes, use
file checkpointing
.
This example builds on
Capture the session ID
: you’ve already analyzed an auth module in
session_id
and want to explore OAuth2 without losing the JWT-focused thread. The first block forks the session and captures the fork’s ID (
forked_id
); the second block resumes the original
session_id
to continue down the JWT path. You now have two session IDs pointing at two separate histories:
Python
TypeScript
# Fork: branch from session_id into a new session
forked_id
=
None
async
for
message
in
query(
prompt
=
"Instead of JWT, implement OAuth2 for the auth module"
,
options
=
ClaudeAgentOptions(
resume
=
session_id,
fork_session
=
True
,
),
):
if
isinstance
(message, ResultMessage):
forked_id
=
message.session_id
# The fork's ID, distinct from session_id
if
message.subtype
==
"success"
:
print
(message.result)
print
(
f
"Forked session:
{
forked_id
}
"
)
# Original session is untouched; resuming it continues the JWT thread
async
for
message
in
query(
prompt
=
"Continue with the JWT approach"
,
options
=
ClaudeAgentOptions(
resume
=
session_id),
):
if
isinstance
(message, ResultMessage)
and
message.subtype
==
"success"
:
print
(message.result)
​
Resume across hosts
Session files are local to the machine that created them. To resume a session on a different host (CI workers, ephemeral containers, serverless), you have two options:
Move the session file.
Persist
~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
from the first run and restore it to the same path on the new host before calling
resume
. The
cwd
must match.
Don’t rely on session resume.
Capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session’s prompt. This is often more robust than shipping transcript files around.
Both SDKs expose functions for enumerating sessions on disk and reading their messages:
listSessions()
and
getSessionMessages()
in TypeScript,
list_sessions()
and
get_session_messages()
in Python. Use them to build custom session pickers, cleanup logic, or transcript viewers.
Both SDKs also expose functions for looking up and mutating individual sessions:
get_session_info()
,
rename_session()
, and
tag_session()
in Python, and
getSessionInfo()
,
renameSession()
, and
tagSession()
in TypeScript. Use them to organize sessions by tag or give them human-readable titles.
​
Related resources
How the agent loop works
: Understand turns, messages, and context accumulation within a session
File checkpointing
: Track and revert file changes across sessions
Python
ClaudeAgentOptions
: Full session option reference for Python
TypeScript
Options
: Full session option reference for TypeScript
Was this page helpful?
Yes
No
Use Claude Code features
Streaming Input
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/sessions" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code on Google Vertex AI</title>
  <link>https://code.claude.com/docs/en/google-vertex-ai</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/google-vertex-ai</guid>
  <pubDate>Sat, 04 May 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Google Vertex AI
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin market...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Google Vertex AI
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Vertex AI, ensure you have:
A Google Cloud Platform (GCP) account with billing enabled
A GCP project with Vertex AI API enabled
Access to desired Claude models (for example, Claude Sonnet 4.6)
Google Cloud SDK (
gcloud
) installed and configured
Quota allocated in desired GCP region
To sign in with your own Vertex AI credentials, follow
Sign in with Vertex AI
below. To deploy Claude Code across a team, use the
manual setup
steps and
pin your model versions
before rolling out.
​
Sign in with Vertex AI
If you have Google Cloud credentials and want to start using Claude Code through Vertex AI, the login wizard walks you through it. You complete the GCP-side prerequisites once per project; the wizard handles the Claude Code side.
The Vertex AI setup wizard requires Claude Code v2.1.98 or later. Run
claude --version
to check.
1
Enable Claude models in your GCP project
Enable the Vertex AI API
for your project, then request access to the Claude models you want in the
Vertex AI Model Garden
. See
IAM configuration
for the permissions your account needs.
2
Start Claude Code and choose Vertex AI
Run
claude
. At the login prompt, select
3rd-party platform
, then
Google Vertex AI
.
3
Follow the wizard prompts
Choose how you authenticate to Google Cloud: Application Default Credentials from
gcloud
, a service account key file, or credentials already in your environment. The wizard detects your project and region, verifies which Claude models your project can invoke, and lets you pin them. It saves the result to the
env
block of your
user settings file
, so you don’t need to export environment variables yourself.
After you’ve signed in, run
/setup-vertex
any time to reopen the wizard and change your credentials, project, region, or model pins.
​
Region configuration
Claude Code supports Vertex AI
global
, multi-region, and regional endpoints. Set
CLOUD_ML_REGION
to
global
, a multi-region location such as
eu
or
us
, or a specific region such as
us-east5
. Claude Code selects the correct Vertex AI hostname for each form, including the
aiplatform.eu.rep.googleapis.com
and
aiplatform.us.rep.googleapis.com
hosts for multi-region locations.
Vertex AI may not support the Claude Code default models on every endpoint type. Model availability varies across
specific regions
, multi-region locations, and
global endpoints
. You may need to switch to a supported location or specify a supported model.
​
Set up manually
To configure Vertex AI through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.
​
1. Enable Vertex AI API
Enable the Vertex AI API in your GCP project:
# Set your project ID
gcloud
config
set
project
YOUR-PROJECT-ID
# Enable Vertex AI API
gcloud
services
enable
aiplatform.googleapis.com
​
2. Request model access
Request access to Claude models in Vertex AI:
Navigate to the
Vertex AI Model Garden
Search for “Claude” models
Request access to desired Claude models (for example, Claude Sonnet 4.6)
Wait for approval (may take 24-48 hours)
​
3. Configure GCP credentials
Claude Code uses standard Google Cloud authentication.
For more information, see
Google Cloud authentication documentation
.
Claude Code v2.1.121 or later supports
X.509 certificate-based Workload Identity Federation
through the same Application Default Credentials chain. Set
GOOGLE_APPLICATION_CREDENTIALS
to the path of your credential configuration file.
Claude Code uses
ANTHROPIC_VERTEX_PROJECT_ID
as the project ID for Vertex AI requests. The
GCLOUD_PROJECT
and
GOOGLE_CLOUD_PROJECT
environment variables and the credential file referenced by
GOOGLE_APPLICATION_CREDENTIALS
take precedence over it. If none of these are set, the project ID is resolved from your
gcloud
configuration or the attached service account.
​
Advanced credential configuration
Claude Code supports automatic credential refresh for GCP through the
gcpAuthRefresh
setting. When Claude Code detects that your GCP credentials are expired or cannot be loaded, it runs the configured command to obtain new credentials before retrying the request.
{
"gcpAuthRefresh"
:
"gcloud auth application-default login"
,
"env"
: {
"ANTHROPIC_VERTEX_PROJECT_ID"
:
"your-project-id"
}
}
The command’s output is displayed to the user, but interactive input isn’t supported. This works well for browser-based authentication flows where the CLI shows a URL and you complete authentication in the browser. The refresh command times out after three minutes if authentication does not complete. If you set
gcpAuthRefresh
in project settings such as
.claude/settings.json
, the command runs only after you accept the workspace trust prompt.
​
4. Configure Claude Code
Set the following environment variables:
# Enable Vertex AI integration
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
global
export
ANTHROPIC_VERTEX_PROJECT_ID
=
YOUR-PROJECT-ID
# Optional: Override the Vertex endpoint URL for custom endpoints or gateways
# export ANTHROPIC_VERTEX_BASE_URL=https://aiplatform.googleapis.com
# Optional: Disable prompt caching if needed
export
DISABLE_PROMPT_CACHING
=
1
# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default
export
ENABLE_PROMPT_CACHING_1H
=
1
# When CLOUD_ML_REGION=global, override region for models that don't support global endpoints
export
VERTEX_REGION_CLAUDE_HAIKU_4_5
=
us-east5
export
VERTEX_REGION_CLAUDE_4_6_SONNET
=
europe-west1
Most model versions have a corresponding
VERTEX_REGION_CLAUDE_*
variable. See the
Environment variables reference
for the full list. Check
Vertex Model Garden
to determine which models support global endpoints versus regional only.
Prompt caching
is enabled automatically. To disable it, set
DISABLE_PROMPT_CACHING=1
. To request a 1-hour cache TTL instead of the 5-minute default, set
ENABLE_PROMPT_CACHING_1H=1
; cache writes with a 1-hour TTL are billed at a higher rate. For heightened rate limits, contact Google Cloud support. When using Vertex AI, the
/login
and
/logout
commands are disabled since authentication is handled through Google Cloud credentials.
Claude Code disables
MCP tool search
by default on Vertex AI, so MCP tool definitions load upfront. Vertex AI supports tool search for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later. Set
ENABLE_TOOL_SEARCH=true
to enable it on those models. Earlier models on Vertex AI do not accept the required beta header, and requests fail if you enable tool search with them.
​
5. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as
sonnet
and
opus
resolve to the latest version, which may not yet be enabled in your Vertex AI project when Anthropic releases an update. Claude Code
falls back
to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Vertex AI model IDs.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Vertex resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5@20251001'
For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Claude Code uses these default models when no pinning variables are set:
Model type
Default value
Primary model
claude-sonnet-4-5@20250929
Small/fast model
Same as primary model
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Vertex AI, Claude Code defaults this to the primary model because Haiku may not be enabled in every project or region. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a model ID that is available in your project.
To customize models further:
export
ANTHROPIC_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5@20251001'
​
Startup model checks
When Claude Code starts with Vertex AI configured, it verifies that the models it intends to use are accessible in your project. This check requires Claude Code v2.1.98 or later.
If you have pinned a model version that is older than the current Claude Code default, and your project can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your
user settings file
and restarts Claude Code. Declining is remembered until the next default version change.
If you have not pinned a model and the current default is unavailable in your project, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in
Model Garden
or
pin a version
to make the choice permanent.
​
IAM configuration
Assign the required IAM permissions:
The
roles/aiplatform.user
role includes the required permissions:
aiplatform.endpoints.predict
- Required for model invocation and token counting
For more restrictive permissions, create a custom role with only the permissions above.
For details, see
Vertex IAM documentation
.
Create a dedicated GCP project for Claude Code to simplify cost tracking and access control.
​
1M token context window
Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the
1M token context window
on Vertex AI. Claude Code automatically enables the extended context window when you select a 1M model variant.
The
setup wizard
offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append
[1m]
to the model ID. See
Pin models for third-party deployments
for details.
​
Troubleshooting
If you encounter “Could not load the default credentials” errors:
Run
gcloud auth application-default login
to set up Application Default Credentials
Set
GOOGLE_APPLICATION_CREDENTIALS
to a service account key file path
See
Configure GCP credentials
for all options
If you encounter quota issues:
Check current quotas or request quota increase through
Cloud Console
If you encounter “model not found” 404 errors:
Confirm model is Enabled in
Model Garden
Verify the model is available in the location you specified. Some models are offered only on
global
or multi-region locations such as
eu
and
us
, not in specific regions
If using
CLOUD_ML_REGION=global
, check that your models support global endpoints in
Model Garden
under “Supported features”. For models that don’t support global endpoints, either:
Specify a supported model via
ANTHROPIC_MODEL
or
ANTHROPIC_DEFAULT_HAIKU_MODEL
, or
Set a region or multi-region location using
VERTEX_REGION_<MODEL_NAME>
environment variables
If you encounter 429 errors:
For regional endpoints, ensure the primary model and small/fast model are supported in your selected region
Consider switching to
CLOUD_ML_REGION=global
for better availability
​
Additional resources
Vertex AI documentation
Vertex AI pricing
Vertex AI quotas and limits
Was this page helpful?
Yes
No
Claude Platform on AWS
Microsoft Foundry
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/google-vertex-ai" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Google Vertex AI
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin market...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Google Vertex AI
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Vertex AI, ensure you have:
A Google Cloud Platform (GCP) account with billing enabled
A GCP project with Vertex AI API enabled
Access to desired Claude models (for example, Claude Sonnet 4.6)
Google Cloud SDK (
gcloud
) installed and configured
Quota allocated in desired GCP region
To sign in with your own Vertex AI credentials, follow
Sign in with Vertex AI
below. To deploy Claude Code across a team, use the
manual setup
steps and
pin your model versions
before rolling out.
​
Sign in with Vertex AI
If you have Google Cloud credentials and want to start using Claude Code through Vertex AI, the login wizard walks you through it. You complete the GCP-side prerequisites once per project; the wizard handles the Claude Code side.
The Vertex AI setup wizard requires Claude Code v2.1.98 or later. Run
claude --version
to check.
1
Enable Claude models in your GCP project
Enable the Vertex AI API
for your project, then request access to the Claude models you want in the
Vertex AI Model Garden
. See
IAM configuration
for the permissions your account needs.
2
Start Claude Code and choose Vertex AI
Run
claude
. At the login prompt, select
3rd-party platform
, then
Google Vertex AI
.
3
Follow the wizard prompts
Choose how you authenticate to Google Cloud: Application Default Credentials from
gcloud
, a service account key file, or credentials already in your environment. The wizard detects your project and region, verifies which Claude models your project can invoke, and lets you pin them. It saves the result to the
env
block of your
user settings file
, so you don’t need to export environment variables yourself.
After you’ve signed in, run
/setup-vertex
any time to reopen the wizard and change your credentials, project, region, or model pins.
​
Region configuration
Claude Code supports Vertex AI
global
, multi-region, and regional endpoints. Set
CLOUD_ML_REGION
to
global
, a multi-region location such as
eu
or
us
, or a specific region such as
us-east5
. Claude Code selects the correct Vertex AI hostname for each form, including the
aiplatform.eu.rep.googleapis.com
and
aiplatform.us.rep.googleapis.com
hosts for multi-region locations.
Vertex AI may not support the Claude Code default models on every endpoint type. Model availability varies across
specific regions
, multi-region locations, and
global endpoints
. You may need to switch to a supported location or specify a supported model.
​
Set up manually
To configure Vertex AI through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.
​
1. Enable Vertex AI API
Enable the Vertex AI API in your GCP project:
# Set your project ID
gcloud
config
set
project
YOUR-PROJECT-ID
# Enable Vertex AI API
gcloud
services
enable
aiplatform.googleapis.com
​
2. Request model access
Request access to Claude models in Vertex AI:
Navigate to the
Vertex AI Model Garden
Search for “Claude” models
Request access to desired Claude models (for example, Claude Sonnet 4.6)
Wait for approval (may take 24-48 hours)
​
3. Configure GCP credentials
Claude Code uses standard Google Cloud authentication.
For more information, see
Google Cloud authentication documentation
.
Claude Code v2.1.121 or later supports
X.509 certificate-based Workload Identity Federation
through the same Application Default Credentials chain. Set
GOOGLE_APPLICATION_CREDENTIALS
to the path of your credential configuration file.
Claude Code uses
ANTHROPIC_VERTEX_PROJECT_ID
as the project ID for Vertex AI requests. The
GCLOUD_PROJECT
and
GOOGLE_CLOUD_PROJECT
environment variables and the credential file referenced by
GOOGLE_APPLICATION_CREDENTIALS
take precedence over it. If none of these are set, the project ID is resolved from your
gcloud
configuration or the attached service account.
​
Advanced credential configuration
Claude Code supports automatic credential refresh for GCP through the
gcpAuthRefresh
setting. When Claude Code detects that your GCP credentials are expired or cannot be loaded, it runs the configured command to obtain new credentials before retrying the request.
{
"gcpAuthRefresh"
:
"gcloud auth application-default login"
,
"env"
: {
"ANTHROPIC_VERTEX_PROJECT_ID"
:
"your-project-id"
}
}
The command’s output is displayed to the user, but interactive input isn’t supported. This works well for browser-based authentication flows where the CLI shows a URL and you complete authentication in the browser. The refresh command times out after three minutes if authentication does not complete. If you set
gcpAuthRefresh
in project settings such as
.claude/settings.json
, the command runs only after you accept the workspace trust prompt.
​
4. Configure Claude Code
Set the following environment variables:
# Enable Vertex AI integration
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
global
export
ANTHROPIC_VERTEX_PROJECT_ID
=
YOUR-PROJECT-ID
# Optional: Override the Vertex endpoint URL for custom endpoints or gateways
# export ANTHROPIC_VERTEX_BASE_URL=https://aiplatform.googleapis.com
# Optional: Disable prompt caching if needed
export
DISABLE_PROMPT_CACHING
=
1
# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default
export
ENABLE_PROMPT_CACHING_1H
=
1
# When CLOUD_ML_REGION=global, override region for models that don't support global endpoints
export
VERTEX_REGION_CLAUDE_HAIKU_4_5
=
us-east5
export
VERTEX_REGION_CLAUDE_4_6_SONNET
=
europe-west1
Most model versions have a corresponding
VERTEX_REGION_CLAUDE_*
variable. See the
Environment variables reference
for the full list. Check
Vertex Model Garden
to determine which models support global endpoints versus regional only.
Prompt caching
is enabled automatically. To disable it, set
DISABLE_PROMPT_CACHING=1
. To request a 1-hour cache TTL instead of the 5-minute default, set
ENABLE_PROMPT_CACHING_1H=1
; cache writes with a 1-hour TTL are billed at a higher rate. For heightened rate limits, contact Google Cloud support. When using Vertex AI, the
/login
and
/logout
commands are disabled since authentication is handled through Google Cloud credentials.
Claude Code disables
MCP tool search
by default on Vertex AI, so MCP tool definitions load upfront. Vertex AI supports tool search for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later. Set
ENABLE_TOOL_SEARCH=true
to enable it on those models. Earlier models on Vertex AI do not accept the required beta header, and requests fail if you enable tool search with them.
​
5. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as
sonnet
and
opus
resolve to the latest version, which may not yet be enabled in your Vertex AI project when Anthropic releases an update. Claude Code
falls back
to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Vertex AI model IDs.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Vertex resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5@20251001'
For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Claude Code uses these default models when no pinning variables are set:
Model type
Default value
Primary model
claude-sonnet-4-5@20250929
Small/fast model
Same as primary model
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Vertex AI, Claude Code defaults this to the primary model because Haiku may not be enabled in every project or region. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a model ID that is available in your project.
To customize models further:
export
ANTHROPIC_MODEL
=
'claude-opus-4-7'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'claude-haiku-4-5@20251001'
​
Startup model checks
When Claude Code starts with Vertex AI configured, it verifies that the models it intends to use are accessible in your project. This check requires Claude Code v2.1.98 or later.
If you have pinned a model version that is older than the current Claude Code default, and your project can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your
user settings file
and restarts Claude Code. Declining is remembered until the next default version change.
If you have not pinned a model and the current default is unavailable in your project, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in
Model Garden
or
pin a version
to make the choice permanent.
​
IAM configuration
Assign the required IAM permissions:
The
roles/aiplatform.user
role includes the required permissions:
aiplatform.endpoints.predict
- Required for model invocation and token counting
For more restrictive permissions, create a custom role with only the permissions above.
For details, see
Vertex IAM documentation
.
Create a dedicated GCP project for Claude Code to simplify cost tracking and access control.
​
1M token context window
Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the
1M token context window
on Vertex AI. Claude Code automatically enables the extended context window when you select a 1M model variant.
The
setup wizard
offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append
[1m]
to the model ID. See
Pin models for third-party deployments
for details.
​
Troubleshooting
If you encounter “Could not load the default credentials” errors:
Run
gcloud auth application-default login
to set up Application Default Credentials
Set
GOOGLE_APPLICATION_CREDENTIALS
to a service account key file path
See
Configure GCP credentials
for all options
If you encounter quota issues:
Check current quotas or request quota increase through
Cloud Console
If you encounter “model not found” 404 errors:
Confirm model is Enabled in
Model Garden
Verify the model is available in the location you specified. Some models are offered only on
global
or multi-region locations such as
eu
and
us
, not in specific regions
If using
CLOUD_ML_REGION=global
, check that your models support global endpoints in
Model Garden
under “Supported features”. For models that don’t support global endpoints, either:
Specify a supported model via
ANTHROPIC_MODEL
or
ANTHROPIC_DEFAULT_HAIKU_MODEL
, or
Set a region or multi-region location using
VERTEX_REGION_<MODEL_NAME>
environment variables
If you encounter 429 errors:
For regional endpoints, ensure the primary model and small/fast model are supported in your selected region
Consider switching to
CLOUD_ML_REGION=global
for better availability
​
Additional resources
Vertex AI documentation
Vertex AI pricing
Vertex AI quotas and limits
Was this page helpful?
Yes
No
Claude Platform on AWS
Microsoft Foundry
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/google-vertex-ai" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Debug your configuration</title>
  <link>https://code.claude.com/docs/en/debug-your-config</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/debug-your-config</guid>
  <pubDate>Thu, 25 Apr 2024 00:00:00 +0000</pubDate>
  <category>Configuration</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Debug your configuration
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from li...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Debug your configuration
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When Claude ignores an instruction or a feature you configured doesn’t appear, the cause is usually that the file didn’t load, it loaded from a different location than you expected, or another file overrode it. This guide shows how to inspect what Claude Code actually loaded so you can narrow down which applies.
For installation, authentication, and connectivity problems, see
Troubleshoot installation and login
instead.
​
See what loaded into context
The
/context
command shows everything occupying the context window for the current session, broken down by category: system prompt, memory files, skills, MCP tools, and conversation messages. Run it first to confirm whether your
CLAUDE.md
, rules, or skill descriptions are present at all.
For detail on a specific category, follow up with the dedicated command:
Command
Shows
/memory
Which
CLAUDE.md
and rules files loaded, plus auto-memory entries
/skills
Available skills from project, user, and plugin sources
/agents
Configured subagents and their settings
/hooks
Active hook configurations
/mcp
Connected MCP servers and their status
/permissions
Resolved allow and deny rules currently in effect
/doctor
Configuration diagnostics: invalid keys, schema errors, installation health
/debug [issue]
Enables debug logging for the session and prompts Claude to diagnose using the log output and settings paths
/status
Active settings sources, including whether managed settings are in effect
If a memory file is missing from
/memory
, check its location against
how CLAUDE.md files load
. Subdirectory
CLAUDE.md
files load on demand when Claude reads a file in that directory with the Read tool, not at session start.
If
/memory
confirms the file loaded but Claude still isn’t following a particular instruction, the issue is likely how the instruction is written rather than whether it loaded. CLAUDE.md works well for the kinds of guidance you’d give a new teammate, such as project conventions, build commands, and where files belong.
Adherence drops when an instruction is vague enough to interpret multiple ways, when two files give conflicting direction, or when the file has grown long enough that individual rules get less attention.
Write effective instructions
covers the specificity, size, and structure patterns that keep adherence high.
CLAUDE.md and permissions solve different problems. CLAUDE.md tells Claude how your project works so it makes good decisions.
Permissions
and
hooks
enforce limits regardless of what Claude decides. Use CLAUDE.md for “we do it this way here.” Use permissions or hooks for security boundaries and anything that must never happen, where you need a guarantee instead of guidance.
​
Check resolved settings
Settings merge across managed, user, project, and local scopes. Managed settings always win when present. Among the rest, the closer scope overrides the broader one in the order local, then project, then user. Some settings can also be set by command-line flags or
environment variables
, which act as another override layer. When a setting doesn’t seem to apply, the value you set is usually being overridden by another scope or an environment variable.
Run
/doctor
to validate your configuration files and surface invalid keys or schema errors. When
/doctor
reports issues, press
f
to send the diagnostic report to Claude and have it walk through fixes with you.
Run
/status
to see which settings sources are active, including whether managed settings are in effect. To understand which scope wins for a given key, see
How scopes interact
.
​
Check MCP servers
Run
/mcp
to see every configured server, its connection status, and whether you have approved it for the current project. A server can be defined correctly but still not provide tools for a few common reasons:
Project-scoped servers in
.mcp.json
require a one-time approval. If the prompt was dismissed, the server stays disabled until you approve it from
/mcp
.
A server that fails to start shows as failed in
/mcp
. Relative file paths in
command
or
args
are a frequent cause, since they resolve against the directory you launched Claude Code from rather than the location of
.mcp.json
.
A server that shows as connected but lists zero tools has started successfully but isn’t returning a tool list. Select
Reconnect
from
/mcp
. If the count stays at zero, run
claude --debug mcp
to see the server’s stderr output.
For configuration locations and scope rules, see
MCP
.
​
Check hooks
Run
/hooks
to list every hook registered for the current session, grouped by event. If a hook you defined doesn’t appear, it isn’t being read: hooks go under the
"hooks"
key in a settings file, not in a standalone file.
If the hook appears but doesn’t fire, the matcher is the usual cause. The
matcher
field is a single string that uses
|
to match multiple tool names, for example
"Edit|Write"
. A misspelled tool name fails silently because the matcher never matches. An array value is a schema error: Claude Code shows a settings error notice,
/doctor
reports the validation failure, and the hook entry is dropped so it won’t appear in
/hooks
.
Edits to
settings.json
take effect in the running session after a brief file-stability delay. You don’t need to restart. If
/hooks
still shows the old definition a few seconds after saving, run
/hooks
again to refresh the view.
If
/hooks
shows the hook but it still does not fire, the next step is to watch hook evaluation live. Start a session with
claude --debug hooks
and trigger the tool call. The debug log records each event, which matchers were checked, and the hook’s exit code and output. See
Debug hooks
for the log format and
hooks troubleshooting
for common failure patterns.
​
Test against a clean configuration
If targeted checks don’t isolate the cause, or your configuration is in an unknown state, compare against a session that loads nothing from your usual setup. Point
CLAUDE_CONFIG_DIR
at an empty directory to bypass everything under
~/.claude
, and launch from a directory that has no
.claude
folder,
.mcp.json
, or
CLAUDE.md
so project configuration is also skipped.
cd
/tmp
&&
CLAUDE_CONFIG_DIR
=
/tmp/claude-clean
claude
The clean session has no user or project settings, hooks, MCP servers, plugins, or memory.
Managed settings still apply if your organization deploys them, since they live at a system path outside
~/.claude
On Linux and Windows, you’ll be prompted to log in again because credentials are stored under the configuration directory
On macOS, credentials are in the Keychain and carry over to the clean session
If the problem disappears here, the cause is somewhere in your real
~/.claude
or project
.claude
files. Reintroduce them one at a time, by copying files into the temporary directory or by launching from your project, to find which one. If it persists in the clean session, the cause is outside your user and project configuration. Run
/status
to check whether managed settings are in effect, look for
environment variables
that affect Claude Code, then see
Troubleshooting
.
​
Check common causes
Most configuration surprises trace back to a small set of location and syntax rules. Check these before assuming a bug:
Symptom
Cause
Fix
Hook never fires
matcher
is a JSON array instead of a string
Use a single string with
|
to match multiple tools, for example
"Edit|Write"
. See
matcher patterns
.
Hook never fires
matcher
value is lowercase, for example
"bash"
Matching is case-sensitive. Tool names are capitalized:
Bash
,
Edit
,
Write
,
Read
.
Hook never fires
Hooks are defined in a standalone file instead of
settings.json
There is no standalone hooks file for project or user config. Define hooks under the
"hooks"
key in
settings.json
. Only
plugins
load a separate
hooks/hooks.json
. See
hook configuration
.
Permissions, hooks, or env set globally are ignored
Configuration was added to
~/.claude.json
~/.claude.json
holds app state and UI toggles.
permissions
,
hooks
, and
env
belong in
~/.claude/settings.json
. These are two different files.
A
settings.json
value seems ignored
The same key is set in
settings.local.json
settings.local.json
overrides
settings.json
, and both override
~/.claude/settings.json
. See
settings precedence
.
Skill doesn’t appear in
/skills
Skill file is at
.claude/skills/name.md
instead of in a folder
Use a folder with
SKILL.md
inside:
.claude/skills/name/SKILL.md
.
Skill appears in
/skills
but Claude never invokes it
Skill has
disable-model-invocation: true
in its frontmatter, or its description doesn’t match how you phrase the request
Check the badge in
/skills
: a “user-only” label means Claude won’t trigger it on its own. See
skill invocation
.
Subdirectory
CLAUDE.md
instructions seem ignored
Subdirectory files load on demand, not at session start
They load when Claude reads a file in that directory with the Read tool, not at launch and not when writing or creating files there. See
how CLAUDE.md files load
.
Subagent ignores
CLAUDE.md
instructions
Subagents don’t always inherit project memory
Put critical rules in the agent file body, which becomes the subagent’s system prompt. See
subagent configuration
.
Cleanup logic never runs at session end
No
SessionEnd
hook configured
Add a
SessionEnd
hook in
settings.json
. See the
hook events list
.
MCP servers in
.mcp.json
never load
File is under
.claude/
or uses Claude Desktop’s config format
Project MCP config goes at the repository root as
.mcp.json
, not inside
.claude/
. See
MCP configuration
.
MCP servers added under
mcpServers
in
settings.json
never appear
settings.json
does not read an
mcpServers
key
Define project servers in
.mcp.json
at the repository root, or run
claude mcp add --scope user
for user-scoped servers. See
MCP configuration
.
Project MCP server added but doesn’t appear
The one-time approval prompt was dismissed
Project-scoped servers require approval. Run
/mcp
to see status and approve.
MCP server fails to start from some directories
command
or
args
uses a relative file path
Use absolute paths for local scripts. Executables on your
PATH
like
npx
or
uvx
work as-is.
MCP server starts without expected environment variables
Variables are in
settings.json
env
, which doesn’t propagate to MCP child processes
Set per-server
env
inside
.mcp.json
instead.
Bash(rm *)
deny rule doesn’t block
/bin/rm
or
find -delete
Prefix rules match the literal command string, not the underlying executable
Add explicit patterns for each variant, or use a
PreToolUse hook
or the
sandbox
for a hard guarantee.
​
Related resources
For full reference on each configuration surface, see the dedicated page:
.claude
directory reference
: every config file location and what reads it
Settings
: precedence order and the full key list
Hooks reference
: event names, payloads, and
--debug hooks
output format
MCP
: server configuration, approval, and
/mcp
output
Troubleshoot installation and login
:
command not found
, PATH, and authentication problems
Troubleshooting
: performance, hangs, and search issues
Was this page helpful?
Yes
No
Troubleshoot performance and stability
Error reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/debug-your-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Debug your configuration
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from li...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Debug your configuration
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
When Claude ignores an instruction or a feature you configured doesn’t appear, the cause is usually that the file didn’t load, it loaded from a different location than you expected, or another file overrode it. This guide shows how to inspect what Claude Code actually loaded so you can narrow down which applies.
For installation, authentication, and connectivity problems, see
Troubleshoot installation and login
instead.
​
See what loaded into context
The
/context
command shows everything occupying the context window for the current session, broken down by category: system prompt, memory files, skills, MCP tools, and conversation messages. Run it first to confirm whether your
CLAUDE.md
, rules, or skill descriptions are present at all.
For detail on a specific category, follow up with the dedicated command:
Command
Shows
/memory
Which
CLAUDE.md
and rules files loaded, plus auto-memory entries
/skills
Available skills from project, user, and plugin sources
/agents
Configured subagents and their settings
/hooks
Active hook configurations
/mcp
Connected MCP servers and their status
/permissions
Resolved allow and deny rules currently in effect
/doctor
Configuration diagnostics: invalid keys, schema errors, installation health
/debug [issue]
Enables debug logging for the session and prompts Claude to diagnose using the log output and settings paths
/status
Active settings sources, including whether managed settings are in effect
If a memory file is missing from
/memory
, check its location against
how CLAUDE.md files load
. Subdirectory
CLAUDE.md
files load on demand when Claude reads a file in that directory with the Read tool, not at session start.
If
/memory
confirms the file loaded but Claude still isn’t following a particular instruction, the issue is likely how the instruction is written rather than whether it loaded. CLAUDE.md works well for the kinds of guidance you’d give a new teammate, such as project conventions, build commands, and where files belong.
Adherence drops when an instruction is vague enough to interpret multiple ways, when two files give conflicting direction, or when the file has grown long enough that individual rules get less attention.
Write effective instructions
covers the specificity, size, and structure patterns that keep adherence high.
CLAUDE.md and permissions solve different problems. CLAUDE.md tells Claude how your project works so it makes good decisions.
Permissions
and
hooks
enforce limits regardless of what Claude decides. Use CLAUDE.md for “we do it this way here.” Use permissions or hooks for security boundaries and anything that must never happen, where you need a guarantee instead of guidance.
​
Check resolved settings
Settings merge across managed, user, project, and local scopes. Managed settings always win when present. Among the rest, the closer scope overrides the broader one in the order local, then project, then user. Some settings can also be set by command-line flags or
environment variables
, which act as another override layer. When a setting doesn’t seem to apply, the value you set is usually being overridden by another scope or an environment variable.
Run
/doctor
to validate your configuration files and surface invalid keys or schema errors. When
/doctor
reports issues, press
f
to send the diagnostic report to Claude and have it walk through fixes with you.
Run
/status
to see which settings sources are active, including whether managed settings are in effect. To understand which scope wins for a given key, see
How scopes interact
.
​
Check MCP servers
Run
/mcp
to see every configured server, its connection status, and whether you have approved it for the current project. A server can be defined correctly but still not provide tools for a few common reasons:
Project-scoped servers in
.mcp.json
require a one-time approval. If the prompt was dismissed, the server stays disabled until you approve it from
/mcp
.
A server that fails to start shows as failed in
/mcp
. Relative file paths in
command
or
args
are a frequent cause, since they resolve against the directory you launched Claude Code from rather than the location of
.mcp.json
.
A server that shows as connected but lists zero tools has started successfully but isn’t returning a tool list. Select
Reconnect
from
/mcp
. If the count stays at zero, run
claude --debug mcp
to see the server’s stderr output.
For configuration locations and scope rules, see
MCP
.
​
Check hooks
Run
/hooks
to list every hook registered for the current session, grouped by event. If a hook you defined doesn’t appear, it isn’t being read: hooks go under the
"hooks"
key in a settings file, not in a standalone file.
If the hook appears but doesn’t fire, the matcher is the usual cause. The
matcher
field is a single string that uses
|
to match multiple tool names, for example
"Edit|Write"
. A misspelled tool name fails silently because the matcher never matches. An array value is a schema error: Claude Code shows a settings error notice,
/doctor
reports the validation failure, and the hook entry is dropped so it won’t appear in
/hooks
.
Edits to
settings.json
take effect in the running session after a brief file-stability delay. You don’t need to restart. If
/hooks
still shows the old definition a few seconds after saving, run
/hooks
again to refresh the view.
If
/hooks
shows the hook but it still does not fire, the next step is to watch hook evaluation live. Start a session with
claude --debug hooks
and trigger the tool call. The debug log records each event, which matchers were checked, and the hook’s exit code and output. See
Debug hooks
for the log format and
hooks troubleshooting
for common failure patterns.
​
Test against a clean configuration
If targeted checks don’t isolate the cause, or your configuration is in an unknown state, compare against a session that loads nothing from your usual setup. Point
CLAUDE_CONFIG_DIR
at an empty directory to bypass everything under
~/.claude
, and launch from a directory that has no
.claude
folder,
.mcp.json
, or
CLAUDE.md
so project configuration is also skipped.
cd
/tmp
&&
CLAUDE_CONFIG_DIR
=
/tmp/claude-clean
claude
The clean session has no user or project settings, hooks, MCP servers, plugins, or memory.
Managed settings still apply if your organization deploys them, since they live at a system path outside
~/.claude
On Linux and Windows, you’ll be prompted to log in again because credentials are stored under the configuration directory
On macOS, credentials are in the Keychain and carry over to the clean session
If the problem disappears here, the cause is somewhere in your real
~/.claude
or project
.claude
files. Reintroduce them one at a time, by copying files into the temporary directory or by launching from your project, to find which one. If it persists in the clean session, the cause is outside your user and project configuration. Run
/status
to check whether managed settings are in effect, look for
environment variables
that affect Claude Code, then see
Troubleshooting
.
​
Check common causes
Most configuration surprises trace back to a small set of location and syntax rules. Check these before assuming a bug:
Symptom
Cause
Fix
Hook never fires
matcher
is a JSON array instead of a string
Use a single string with
|
to match multiple tools, for example
"Edit|Write"
. See
matcher patterns
.
Hook never fires
matcher
value is lowercase, for example
"bash"
Matching is case-sensitive. Tool names are capitalized:
Bash
,
Edit
,
Write
,
Read
.
Hook never fires
Hooks are defined in a standalone file instead of
settings.json
There is no standalone hooks file for project or user config. Define hooks under the
"hooks"
key in
settings.json
. Only
plugins
load a separate
hooks/hooks.json
. See
hook configuration
.
Permissions, hooks, or env set globally are ignored
Configuration was added to
~/.claude.json
~/.claude.json
holds app state and UI toggles.
permissions
,
hooks
, and
env
belong in
~/.claude/settings.json
. These are two different files.
A
settings.json
value seems ignored
The same key is set in
settings.local.json
settings.local.json
overrides
settings.json
, and both override
~/.claude/settings.json
. See
settings precedence
.
Skill doesn’t appear in
/skills
Skill file is at
.claude/skills/name.md
instead of in a folder
Use a folder with
SKILL.md
inside:
.claude/skills/name/SKILL.md
.
Skill appears in
/skills
but Claude never invokes it
Skill has
disable-model-invocation: true
in its frontmatter, or its description doesn’t match how you phrase the request
Check the badge in
/skills
: a “user-only” label means Claude won’t trigger it on its own. See
skill invocation
.
Subdirectory
CLAUDE.md
instructions seem ignored
Subdirectory files load on demand, not at session start
They load when Claude reads a file in that directory with the Read tool, not at launch and not when writing or creating files there. See
how CLAUDE.md files load
.
Subagent ignores
CLAUDE.md
instructions
Subagents don’t always inherit project memory
Put critical rules in the agent file body, which becomes the subagent’s system prompt. See
subagent configuration
.
Cleanup logic never runs at session end
No
SessionEnd
hook configured
Add a
SessionEnd
hook in
settings.json
. See the
hook events list
.
MCP servers in
.mcp.json
never load
File is under
.claude/
or uses Claude Desktop’s config format
Project MCP config goes at the repository root as
.mcp.json
, not inside
.claude/
. See
MCP configuration
.
MCP servers added under
mcpServers
in
settings.json
never appear
settings.json
does not read an
mcpServers
key
Define project servers in
.mcp.json
at the repository root, or run
claude mcp add --scope user
for user-scoped servers. See
MCP configuration
.
Project MCP server added but doesn’t appear
The one-time approval prompt was dismissed
Project-scoped servers require approval. Run
/mcp
to see status and approve.
MCP server fails to start from some directories
command
or
args
uses a relative file path
Use absolute paths for local scripts. Executables on your
PATH
like
npx
or
uvx
work as-is.
MCP server starts without expected environment variables
Variables are in
settings.json
env
, which doesn’t propagate to MCP child processes
Set per-server
env
inside
.mcp.json
instead.
Bash(rm *)
deny rule doesn’t block
/bin/rm
or
find -delete
Prefix rules match the literal command string, not the underlying executable
Add explicit patterns for each variant, or use a
PreToolUse hook
or the
sandbox
for a hard guarantee.
​
Related resources
For full reference on each configuration surface, see the dedicated page:
.claude
directory reference
: every config file location and what reads it
Settings
: precedence order and the full key list
Hooks reference
: event names, payloads, and
--debug hooks
output format
MCP
: server configuration, approval, and
/mcp
output
Troubleshoot installation and login
:
command not found
, PATH, and authentication problems
Troubleshooting
: performance, hangs, and search issues
Was this page helpful?
Yes
No
Troubleshoot performance and stability
Error reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/debug-your-config" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Migrate to Claude Agent SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/migration-guide</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/migration-guide</guid>
  <pubDate>Tue, 23 Apr 2024 00:00:00 +0000</pubDate>
  <category>Guides</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Migrate to Claude Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Migrate to Claude Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
The Claude Code SDK has been renamed to the
Claude Agent SDK
and its documentation has been reorganized. This change reflects the SDK’s broader capabilities for building AI agents beyond just coding tasks.
​
What’s Changed
Aspect
Old
New
Package Name (TS/JS)
@anthropic-ai/claude-code
@anthropic-ai/claude-agent-sdk
Python Package
claude-code-sdk
claude-agent-sdk
Documentation Location
Claude Code docs
API Guide → Agent SDK section
Documentation Changes:
The Agent SDK documentation has moved from the Claude Code docs to the API Guide under a dedicated
Agent SDK
section. The Claude Code docs now focus on the CLI tool and automation features.
​
Migration Steps
​
For TypeScript/JavaScript Projects
1. Uninstall the old package:
npm
uninstall
@anthropic-ai/claude-code
2. Install the new package:
npm
install
@anthropic-ai/claude-agent-sdk
3. Update your imports:
Change all imports from
@anthropic-ai/claude-code
to
@anthropic-ai/claude-agent-sdk
:
// Before
import
{
query
,
tool
,
createSdkMcpServer
}
from
"@anthropic-ai/claude-code"
;
// After
import
{
query
,
tool
,
createSdkMcpServer
}
from
"@anthropic-ai/claude-agent-sdk"
;
4. Update package.json dependencies:
If you have the package listed in your
package.json
, update it:
Before:
{
"dependencies"
: {
"@anthropic-ai/claude-code"
:
"^0.0.42"
}
}
After:
{
"dependencies"
: {
"@anthropic-ai/claude-agent-sdk"
:
"^0.2.0"
}
}
That’s it! No other code changes are required.
​
For Python Projects
1. Uninstall the old package:
pip
uninstall
claude-code-sdk
2. Install the new package:
pip
install
claude-agent-sdk
3. Update your imports:
Change all imports from
claude_code_sdk
to
claude_agent_sdk
:
# Before
from
claude_code_sdk
import
query, ClaudeCodeOptions
# After
from
claude_agent_sdk
import
query, ClaudeAgentOptions
4. Update type names:
Change
ClaudeCodeOptions
to
ClaudeAgentOptions
:
# Before
from
claude_code_sdk
import
query, ClaudeCodeOptions
options
=
ClaudeCodeOptions(
model
=
"claude-opus-4-7"
)
# After
from
claude_agent_sdk
import
query, ClaudeAgentOptions
options
=
ClaudeAgentOptions(
model
=
"claude-opus-4-7"
)
5. Review
breaking changes
Make any code changes needed to complete the migration.
​
Breaking changes
To improve isolation and explicit configuration, Claude Agent SDK v0.1.0 introduces breaking changes for users migrating from Claude Code SDK. Review this section carefully before migrating.
​
Python: ClaudeCodeOptions renamed to ClaudeAgentOptions
What changed:
The Python SDK type
ClaudeCodeOptions
has been renamed to
ClaudeAgentOptions
.
Migration:
# BEFORE (claude-code-sdk)
from
claude_code_sdk
import
query, ClaudeCodeOptions
options
=
ClaudeCodeOptions(
model
=
"claude-opus-4-7"
,
permission_mode
=
"acceptEdits"
)
# AFTER (claude-agent-sdk)
from
claude_agent_sdk
import
query, ClaudeAgentOptions
options
=
ClaudeAgentOptions(
model
=
"claude-opus-4-7"
,
permission_mode
=
"acceptEdits"
)
Why this changed:
The type name now matches the “Claude Agent SDK” branding and provides consistency across the SDK’s naming conventions.
​
System prompt no longer default
What changed:
The SDK no longer uses Claude Code’s system prompt by default.
Migration:
TypeScript
Python
// BEFORE (v0.0.x) - Used Claude Code's system prompt by default
const
result
=
query
({
prompt:
"Hello"
});
// AFTER (v0.1.0) - Uses minimal system prompt by default
// To get the old behavior, explicitly request Claude Code's preset:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
}
}
});
// Or use a custom system prompt:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
systemPrompt:
"You are a helpful coding assistant"
}
});
Why this changed:
Provides better control and isolation for SDK applications. You can now build agents with custom behavior without inheriting Claude Code’s CLI-focused instructions.
​
Settings sources default
This default was briefly changed in v0.1.0 and then reverted, so no migration action is needed.
Current behavior:
Omitting
settingSources
on
query()
loads user, project, and local filesystem settings, matching the CLI. This includes
~/.claude/settings.json
,
.claude/settings.json
,
.claude/settings.local.json
, CLAUDE.md files, and custom commands.
To run isolated from filesystem settings, pass an empty array:
TypeScript
Python
const
result
=
query
({
prompt:
"Hello"
,
options:
{
settingSources:
[]
// No filesystem settings loaded
}
});
// Or load only specific sources:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
settingSources:
[
"project"
]
// Only project settings
}
});
Isolation is especially important for CI/CD pipelines, deployed applications, test environments, and multi-tenant systems where local customizations should not leak in.
SDK v0.1.0 briefly defaulted to no settings loaded; this was reverted in subsequent releases. Python SDK 0.1.59 and earlier treated an empty list the same as omitting the option, so upgrade before relying on
setting_sources=[]
. See
What settingSources does not control
for inputs that are read even when
settingSources
is
[]
.
​
Why the Rename?
The Claude Code SDK was originally designed for coding tasks, but it has evolved into a powerful framework for building all types of AI agents. The new name “Claude Agent SDK” better reflects its capabilities:
Building business agents (legal assistants, finance advisors, customer support)
Creating specialized coding agents (SRE bots, security reviewers, code review agents)
Developing custom agents for any domain with tool use, MCP integration, and more
​
Getting Help
If you encounter any issues during migration:
For TypeScript/JavaScript:
Check that all imports are updated to use
@anthropic-ai/claude-agent-sdk
Verify your package.json has the new package name
Run
npm install
to ensure dependencies are updated
For Python:
Check that all imports are updated to use
claude_agent_sdk
Verify your requirements.txt or pyproject.toml has the new package name
Run
pip install claude-agent-sdk
to ensure the package is installed
​
Next Steps
Explore the
Agent SDK Overview
to learn about available features
Check out the
TypeScript SDK Reference
for detailed API documentation
Review the
Python SDK Reference
for Python-specific documentation
Learn about
Custom Tools
and
MCP Integration
Was this page helpful?
Yes
No
Python SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/migration-guide" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Migrate to Claude Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Migrate to Claude Agent SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Overview
The Claude Code SDK has been renamed to the
Claude Agent SDK
and its documentation has been reorganized. This change reflects the SDK’s broader capabilities for building AI agents beyond just coding tasks.
​
What’s Changed
Aspect
Old
New
Package Name (TS/JS)
@anthropic-ai/claude-code
@anthropic-ai/claude-agent-sdk
Python Package
claude-code-sdk
claude-agent-sdk
Documentation Location
Claude Code docs
API Guide → Agent SDK section
Documentation Changes:
The Agent SDK documentation has moved from the Claude Code docs to the API Guide under a dedicated
Agent SDK
section. The Claude Code docs now focus on the CLI tool and automation features.
​
Migration Steps
​
For TypeScript/JavaScript Projects
1. Uninstall the old package:
npm
uninstall
@anthropic-ai/claude-code
2. Install the new package:
npm
install
@anthropic-ai/claude-agent-sdk
3. Update your imports:
Change all imports from
@anthropic-ai/claude-code
to
@anthropic-ai/claude-agent-sdk
:
// Before
import
{
query
,
tool
,
createSdkMcpServer
}
from
"@anthropic-ai/claude-code"
;
// After
import
{
query
,
tool
,
createSdkMcpServer
}
from
"@anthropic-ai/claude-agent-sdk"
;
4. Update package.json dependencies:
If you have the package listed in your
package.json
, update it:
Before:
{
"dependencies"
: {
"@anthropic-ai/claude-code"
:
"^0.0.42"
}
}
After:
{
"dependencies"
: {
"@anthropic-ai/claude-agent-sdk"
:
"^0.2.0"
}
}
That’s it! No other code changes are required.
​
For Python Projects
1. Uninstall the old package:
pip
uninstall
claude-code-sdk
2. Install the new package:
pip
install
claude-agent-sdk
3. Update your imports:
Change all imports from
claude_code_sdk
to
claude_agent_sdk
:
# Before
from
claude_code_sdk
import
query, ClaudeCodeOptions
# After
from
claude_agent_sdk
import
query, ClaudeAgentOptions
4. Update type names:
Change
ClaudeCodeOptions
to
ClaudeAgentOptions
:
# Before
from
claude_code_sdk
import
query, ClaudeCodeOptions
options
=
ClaudeCodeOptions(
model
=
"claude-opus-4-7"
)
# After
from
claude_agent_sdk
import
query, ClaudeAgentOptions
options
=
ClaudeAgentOptions(
model
=
"claude-opus-4-7"
)
5. Review
breaking changes
Make any code changes needed to complete the migration.
​
Breaking changes
To improve isolation and explicit configuration, Claude Agent SDK v0.1.0 introduces breaking changes for users migrating from Claude Code SDK. Review this section carefully before migrating.
​
Python: ClaudeCodeOptions renamed to ClaudeAgentOptions
What changed:
The Python SDK type
ClaudeCodeOptions
has been renamed to
ClaudeAgentOptions
.
Migration:
# BEFORE (claude-code-sdk)
from
claude_code_sdk
import
query, ClaudeCodeOptions
options
=
ClaudeCodeOptions(
model
=
"claude-opus-4-7"
,
permission_mode
=
"acceptEdits"
)
# AFTER (claude-agent-sdk)
from
claude_agent_sdk
import
query, ClaudeAgentOptions
options
=
ClaudeAgentOptions(
model
=
"claude-opus-4-7"
,
permission_mode
=
"acceptEdits"
)
Why this changed:
The type name now matches the “Claude Agent SDK” branding and provides consistency across the SDK’s naming conventions.
​
System prompt no longer default
What changed:
The SDK no longer uses Claude Code’s system prompt by default.
Migration:
TypeScript
Python
// BEFORE (v0.0.x) - Used Claude Code's system prompt by default
const
result
=
query
({
prompt:
"Hello"
});
// AFTER (v0.1.0) - Uses minimal system prompt by default
// To get the old behavior, explicitly request Claude Code's preset:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
}
}
});
// Or use a custom system prompt:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
systemPrompt:
"You are a helpful coding assistant"
}
});
Why this changed:
Provides better control and isolation for SDK applications. You can now build agents with custom behavior without inheriting Claude Code’s CLI-focused instructions.
​
Settings sources default
This default was briefly changed in v0.1.0 and then reverted, so no migration action is needed.
Current behavior:
Omitting
settingSources
on
query()
loads user, project, and local filesystem settings, matching the CLI. This includes
~/.claude/settings.json
,
.claude/settings.json
,
.claude/settings.local.json
, CLAUDE.md files, and custom commands.
To run isolated from filesystem settings, pass an empty array:
TypeScript
Python
const
result
=
query
({
prompt:
"Hello"
,
options:
{
settingSources:
[]
// No filesystem settings loaded
}
});
// Or load only specific sources:
const
result
=
query
({
prompt:
"Hello"
,
options:
{
settingSources:
[
"project"
]
// Only project settings
}
});
Isolation is especially important for CI/CD pipelines, deployed applications, test environments, and multi-tenant systems where local customizations should not leak in.
SDK v0.1.0 briefly defaulted to no settings loaded; this was reverted in subsequent releases. Python SDK 0.1.59 and earlier treated an empty list the same as omitting the option, so upgrade before relying on
setting_sources=[]
. See
What settingSources does not control
for inputs that are read even when
settingSources
is
[]
.
​
Why the Rename?
The Claude Code SDK was originally designed for coding tasks, but it has evolved into a powerful framework for building all types of AI agents. The new name “Claude Agent SDK” better reflects its capabilities:
Building business agents (legal assistants, finance advisors, customer support)
Creating specialized coding agents (SRE bots, security reviewers, code review agents)
Developing custom agents for any domain with tool use, MCP integration, and more
​
Getting Help
If you encounter any issues during migration:
For TypeScript/JavaScript:
Check that all imports are updated to use
@anthropic-ai/claude-agent-sdk
Verify your package.json has the new package name
Run
npm install
to ensure dependencies are updated
For Python:
Check that all imports are updated to use
claude_agent_sdk
Verify your requirements.txt or pyproject.toml has the new package name
Run
pip install claude-agent-sdk
to ensure the package is installed
​
Next Steps
Explore the
Agent SDK Overview
to learn about available features
Check out the
TypeScript SDK Reference
for detailed API documentation
Review the
Python SDK Reference
for Python-specific documentation
Learn about
Custom Tools
and
MCP Integration
Was this page helpful?
Yes
No
Python SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/migration-guide" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Plan in the cloud with ultraplan</title>
  <link>https://code.claude.com/docs/en/ultraplan</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/ultraplan</guid>
  <pubDate>Sun, 21 Apr 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Plan in the cloud with ultraplan
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Plan in the cloud with ultraplan
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Ultraplan is in research preview and requires Claude Code v2.1.91 or later. Behavior and capabilities may change based on feedback.
Ultraplan hands a planning task from your local CLI to a
Claude Code on the web
session running in
plan mode
. Claude drafts the plan in the cloud while you keep working in your terminal. When the plan is ready, you open it in your browser to comment on specific sections, ask for revisions, and choose where to execute it.
This is useful when you want a richer review surface than the terminal offers:
Targeted feedback
: comment on individual sections of the plan instead of replying to the whole thing
Hands-off drafting
: the plan is generated remotely, so your terminal stays free for other work
Flexible execution
: approve the plan to run on the web and open a pull request, or send it back to your terminal
Ultraplan requires a
Claude Code on the web
account and a GitHub repository. Because it runs on Anthropic’s cloud infrastructure, it is not available when using Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. The cloud session runs in your account’s default
cloud environment
. If you don’t have a cloud environment yet, ultraplan creates one automatically when it first launches.
​
Launch ultraplan from the CLI
From your local CLI session, you can launch ultraplan in three ways:
Command
: run
/ultraplan
followed by your prompt
Keyword
: include the word
ultraplan
anywhere in a normal prompt
From a local plan
: when Claude finishes a local plan and shows the approval dialog, choose
No, refine with Ultraplan on Claude Code on the web
to send the draft to the cloud for further iteration
For example, to plan a service migration with the command:
/ultraplan migrate the auth service from sessions to JWTs
The command and keyword paths open a confirmation dialog before launching. The local plan path skips this dialog because that selection already serves as confirmation. If
Remote Control
is active, it disconnects when ultraplan starts because both features occupy the claude.ai/code interface and only one can be connected at a time.
After the cloud session launches, your CLI’s prompt input shows a status indicator while the remote session works:
Status
Meaning
◇ ultraplan
Claude is researching your codebase and drafting the plan
◇ ultraplan needs your input
Claude has a clarifying question; open the session link to respond
◆ ultraplan ready
The plan is ready to review in your browser
Run
/tasks
and select the ultraplan entry to open a detail view with the session link, agent activity, and a
Stop ultraplan
action. Stopping archives the cloud session and clears the indicator; nothing is saved to your terminal.
​
Review and revise the plan in your browser
When the status changes to
◆ ultraplan ready
, open the session link to view the plan on claude.ai. The plan appears in a dedicated review view:
Inline comments
: highlight any passage and leave a comment for Claude to address
Emoji reactions
: react to a section to signal approval or concern without writing a full comment
Outline sidebar
: jump between sections of the plan
When you ask Claude to address your comments, it revises the plan and presents an updated draft. You can iterate as many times as needed before choosing where to execute.
​
Choose where to execute
When the plan looks right, you choose from the browser whether Claude implements it in the same cloud session or sends it back to your waiting terminal.
​
Execute on the web
Select
Approve Claude’s plan and start coding
in your browser to have Claude implement it in the same Claude Code on the web session. Your terminal shows a confirmation, the status indicator clears, and the work continues in the cloud. When the implementation finishes,
review the diff
and create a pull request from the web interface.
​
Send the plan back to your terminal
Select
Approve plan and teleport back to terminal
in your browser to implement the plan locally with full access to your environment. This option appears when the session was launched from your CLI and the terminal is still polling. The web session is archived so it doesn’t continue working in parallel.
Your terminal shows the plan in a dialog titled
Ultraplan approved
with three options:
Implement here
: inject the plan into your current conversation and continue from where you left off
Start new session
: clear the current conversation and begin fresh with only the plan as context
Cancel
: save the plan to a file without executing it; Claude prints the file path so you can return to it later
If you start a new session, Claude prints a
claude --resume
command at the top so you can return to your previous conversation later.
​
Related resources
Claude Code on the web
: the cloud infrastructure ultraplan runs on
Plan mode
: how planning works in a local session
Find bugs with ultrareview
: the code review counterpart to ultraplan for catching issues before merge
Remote Control
: use the claude.ai/code interface with a session running on your own machine
Was this page helpful?
Yes
No
Routines
Ultrareview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/ultraplan" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Plan in the cloud with ultraplan
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Plan in the cloud with ultraplan
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Ultraplan is in research preview and requires Claude Code v2.1.91 or later. Behavior and capabilities may change based on feedback.
Ultraplan hands a planning task from your local CLI to a
Claude Code on the web
session running in
plan mode
. Claude drafts the plan in the cloud while you keep working in your terminal. When the plan is ready, you open it in your browser to comment on specific sections, ask for revisions, and choose where to execute it.
This is useful when you want a richer review surface than the terminal offers:
Targeted feedback
: comment on individual sections of the plan instead of replying to the whole thing
Hands-off drafting
: the plan is generated remotely, so your terminal stays free for other work
Flexible execution
: approve the plan to run on the web and open a pull request, or send it back to your terminal
Ultraplan requires a
Claude Code on the web
account and a GitHub repository. Because it runs on Anthropic’s cloud infrastructure, it is not available when using Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. The cloud session runs in your account’s default
cloud environment
. If you don’t have a cloud environment yet, ultraplan creates one automatically when it first launches.
​
Launch ultraplan from the CLI
From your local CLI session, you can launch ultraplan in three ways:
Command
: run
/ultraplan
followed by your prompt
Keyword
: include the word
ultraplan
anywhere in a normal prompt
From a local plan
: when Claude finishes a local plan and shows the approval dialog, choose
No, refine with Ultraplan on Claude Code on the web
to send the draft to the cloud for further iteration
For example, to plan a service migration with the command:
/ultraplan migrate the auth service from sessions to JWTs
The command and keyword paths open a confirmation dialog before launching. The local plan path skips this dialog because that selection already serves as confirmation. If
Remote Control
is active, it disconnects when ultraplan starts because both features occupy the claude.ai/code interface and only one can be connected at a time.
After the cloud session launches, your CLI’s prompt input shows a status indicator while the remote session works:
Status
Meaning
◇ ultraplan
Claude is researching your codebase and drafting the plan
◇ ultraplan needs your input
Claude has a clarifying question; open the session link to respond
◆ ultraplan ready
The plan is ready to review in your browser
Run
/tasks
and select the ultraplan entry to open a detail view with the session link, agent activity, and a
Stop ultraplan
action. Stopping archives the cloud session and clears the indicator; nothing is saved to your terminal.
​
Review and revise the plan in your browser
When the status changes to
◆ ultraplan ready
, open the session link to view the plan on claude.ai. The plan appears in a dedicated review view:
Inline comments
: highlight any passage and leave a comment for Claude to address
Emoji reactions
: react to a section to signal approval or concern without writing a full comment
Outline sidebar
: jump between sections of the plan
When you ask Claude to address your comments, it revises the plan and presents an updated draft. You can iterate as many times as needed before choosing where to execute.
​
Choose where to execute
When the plan looks right, you choose from the browser whether Claude implements it in the same cloud session or sends it back to your waiting terminal.
​
Execute on the web
Select
Approve Claude’s plan and start coding
in your browser to have Claude implement it in the same Claude Code on the web session. Your terminal shows a confirmation, the status indicator clears, and the work continues in the cloud. When the implementation finishes,
review the diff
and create a pull request from the web interface.
​
Send the plan back to your terminal
Select
Approve plan and teleport back to terminal
in your browser to implement the plan locally with full access to your environment. This option appears when the session was launched from your CLI and the terminal is still polling. The web session is archived so it doesn’t continue working in parallel.
Your terminal shows the plan in a dialog titled
Ultraplan approved
with three options:
Implement here
: inject the plan into your current conversation and continue from where you left off
Start new session
: clear the current conversation and begin fresh with only the plan as context
Cancel
: save the plan to a file without executing it; Claude prints the file path so you can return to it later
If you start a new session, Claude prints a
claude --resume
command at the top so you can return to your previous conversation later.
​
Related resources
Claude Code on the web
: the cloud infrastructure ultraplan runs on
Plan mode
: how planning works in a local session
Find bugs with ultrareview
: the code review counterpart to ultraplan for catching issues before merge
Remote Control
: use the claude.ai/code interface with a session running on your own machine
Was this page helpful?
Yes
No
Routines
Ultrareview
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/ultraplan" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Constrain plugin dependency versions</title>
  <link>https://code.claude.com/docs/en/plugin-dependencies</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/plugin-dependencies</guid>
  <pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
  <category>Plugins</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Constrain plugin dependency versions
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Constrain plugin dependency versions
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A plugin can depend on other plugins by listing them in
plugin.json
or in its marketplace entry. By default, a dependency tracks the latest available version, so an upstream release can change the dependency under your plugin without warning. Version constraints let you hold a dependency at a tested version range until you choose to move.
When you install a plugin that declares dependencies, Claude Code resolves and installs them automatically and lists which dependencies were added at the end of the install output. If a dependency later goes missing,
/reload-plugins
and the background plugin auto-update reinstall it, provided its marketplace is already in your configured marketplaces. Re-running
claude plugin install
on the dependent plugin, or adding a marketplace with
claude plugin marketplace add
, also resolves any outstanding missing dependencies. Dependencies from a marketplace you have not added are left unresolved.
This guide is for plugin authors who declare dependencies in
plugin.json
and for marketplace maintainers who tag releases. To install plugins that have dependencies, see
Discover and install plugins
. For the full manifest schema, see the
Plugins reference
.
Dependency version constraints require Claude Code v2.1.110 or later.
​
Why constrain dependency versions
Consider an internal marketplace where two teams publish plugins. The platform team maintains
secrets-vault
, an MCP server that wraps a secrets backend. The deploy team maintains
deploy-kit
, which calls
secrets-vault
to fetch credentials during deploys.
deploy-kit
is tested against
secrets-vault
v2.1.0. Without a version constraint, the next time the platform team tags a release that renames an MCP tool, auto-update moves every engineer’s
secrets-vault
to the new version and
deploy-kit
breaks.
With a version constraint,
deploy-kit
declares that it needs
secrets-vault
in the
~2.1.0
range. Engineers with
deploy-kit
installed stay on the highest matching
2.1.x
patch. The deploy team upgrades on their own schedule by publishing a new
deploy-kit
version with a wider constraint.
​
Declare a dependency with a version constraint
List dependencies in the
dependencies
array of your plugin’s
.claude-plugin/plugin.json
. Each entry is either a plugin name or an object with a version constraint.
The following manifest declares one unversioned dependency and one constrained dependency:
.claude-plugin/plugin.json
{
"name"
:
"deploy-kit"
,
"version"
:
"3.1.0"
,
"dependencies"
: [
"audit-logger"
,
{
"name"
:
"secrets-vault"
,
"version"
:
"~2.1.0"
}
]
}
An entry can be a bare string with only the plugin name, like
"audit-logger"
in the example above, which depends on whatever version that plugin’s marketplace provides. For more control, use an object with these fields:
Field
Type
Description
name
string
Plugin name. Resolves within the same marketplace as the declaring plugin. Required.
version
string
A
semver range
such as
~2.1.0
,
^2.0
,
>=1.4
, or
=2.1.0
. The dependency is fetched at the highest tagged version that satisfies this range.
marketplace
string
A different marketplace to resolve
name
in. Cross-marketplace dependencies are blocked unless the target marketplace is listed in
allowCrossMarketplaceDependenciesOn
in the root marketplace’s
marketplace.json
.
The
version
field accepts any expression supported by Node’s
semver
package, including caret, tilde, hyphen, and comparator ranges. Pre-release versions such as
2.0.0-beta.1
are excluded unless your range opts in with a pre-release suffix like
^2.0.0-0
.
​
Depend on a plugin from another marketplace
By default, Claude Code refuses to auto-install a dependency that lives in a different marketplace than the plugin declaring it. This prevents one marketplace from silently pulling in plugins from a source you have not reviewed.
To allow it, the maintainer of the root marketplace adds the target marketplace name to
allowCrossMarketplaceDependenciesOn
in
marketplace.json
. The root marketplace is the one that hosts the plugin the user is installing; only its allowlist is consulted, so trust does not chain through intermediate marketplaces.
The following
marketplace.json
allows
deploy-kit
to depend on a plugin from
acme-shared
:
.claude-plugin/marketplace.json
{
"name"
:
"acme-tools"
,
"owner"
: {
"name"
:
"Acme"
},
"allowCrossMarketplaceDependenciesOn"
: [
"acme-shared"
],
"plugins"
: [
{
"name"
:
"deploy-kit"
,
"source"
:
"./deploy-kit"
,
"dependencies"
: [
{
"name"
:
"audit-logger"
,
"marketplace"
:
"acme-shared"
}
]
}
]
}
If the field is missing or does not include the target marketplace, install fails with a
cross-marketplace
error naming the field to set. Users can still install the dependency manually first, which satisfies the constraint without changing the allowlist.
​
Tag plugin releases for version resolution
Version constraints resolve against git tags on the marketplace repository. For Claude Code to find a dependency’s available versions, the upstream plugin’s releases must be tagged using a specific naming convention.
Tag each release as
{plugin-name}--v{version}
, where
{version}
matches the
version
field in that commit’s
plugin.json
. From the plugin directory, run:
claude
plugin
tag
--push
The
claude plugin tag
command derives the tag name from the plugin’s manifest and the enclosing marketplace entry. Before creating the tag, it validates the plugin contents, checks that
plugin.json
and the marketplace entry agree on the version, requires a clean working tree under the plugin directory, and refuses if the tag already exists. Add
--dry-run
to see what would be tagged without creating it. Running
git tag secrets-vault--v2.1.0
directly is equivalent if you keep
plugin.json
and the marketplace entry in sync yourself.
The plugin name prefix lets one marketplace repository host multiple plugins with independent version lines. The
--v
separator is parsed as a prefix match on the full plugin name, so plugin names that contain hyphens are handled correctly.
When you install a plugin that declares
{ "name": "secrets-vault", "version": "~2.1.0" }
, Claude Code lists the marketplace’s tags, filters to those starting with
secrets-vault--v
, and fetches the highest version satisfying
~2.1.0
. If no matching tag exists, the dependent plugin is disabled with an error listing the available versions.
The resolved tag’s semver is recorded separately from
plugin.json
’s
version
, so constraint checks use the tag that was actually fetched even if
plugin.json
at that commit has a stale value. The cache directory name for a tag-resolved install includes a 12-character commit-SHA suffix, so if a maintainer force-moves a tag to a different commit, the next install gets a fresh cache directory instead of reusing stale content.
For
npm
marketplace sources, the constraint does not control which version is fetched, since tag-based resolution applies only to git-backed sources. The constraint is still checked at load time, and the dependent plugin is disabled with
dependency-version-unsatisfied
if the installed version does not satisfy it.
​
How constraints interact
When several installed plugins constrain the same dependency, Claude Code intersects their ranges and resolves the dependency to the highest version that satisfies all of them. The table below shows how common combinations resolve.
Plugin A requires
Plugin B requires
Result
^2.0
>=2.1
One install at the highest
2.x
tag at or above
2.1.0
. Both plugins load.
~2.1
~3.0
Install of plugin B fails with
range-conflict
. Plugin A and the dependency stay as they were.
=2.1.0
none
The dependency stays at
2.1.0
. Auto-update skips newer versions while plugin A is installed.
Auto-update fetches a constrained dependency at the highest git tag that satisfies every installed plugin’s range, rather than at the marketplace’s latest version, so the dependency continues to receive updates within its allowed range. If no tag satisfies all ranges, the update is skipped and the skip appears in
/doctor
and the
/plugin
Errors tab, naming the constraining plugin.
When you uninstall the last plugin that constrains a dependency, the dependency is no longer held and resumes tracking its marketplace entry on the next update.
​
Remove orphaned auto-installed dependencies
Auto-installed dependencies stay on disk after the plugins that installed them are uninstalled, in case you reinstall a dependent plugin or want to keep using the dependency directly. To clean them up, run
claude plugin prune
to list the auto-installed dependencies that no longer have any installed plugin requiring them and remove them after a confirmation prompt. This requires Claude Code v2.1.121 or later.
claude
plugin
prune
By default, prune operates at user scope. Use
--scope project
or
--scope local
to target a different scope. Pass
--dry-run
to list what would be removed without changing anything. Pass
-y
to skip the confirmation prompt. When stdin or stdout is not a terminal, prune lists the orphans and exits without removing them unless
-y
is passed.
To prune as part of an uninstall, pass
--prune
to
claude plugin uninstall
. After removing the named plugin, Claude Code scans for and removes any auto-installed dependencies that are now orphaned. Plugins you installed yourself are never pruned, only those installed automatically through another plugin’s
dependencies
array.
For example, to uninstall
deploy-kit
and clean up the dependencies it leaves behind:
claude
plugin
uninstall
deploy-kit
--prune
​
Resolve dependency errors
Dependency problems surface in
claude plugin list
, in the
/plugin
interface, and in
/doctor
. The affected plugin is disabled until you resolve the error. The most common errors and their fixes are listed below.
Error
Meaning
How to resolve
dependency-unsatisfied
A declared dependency is not installed, or it is installed but disabled.
Run the
claude plugin install
command shown in the error message. If the dependency’s marketplace is not yet configured, add it with
claude plugin marketplace add
and Claude Code resolves the dependency automatically. If the dependency is disabled, enable it.
range-conflict
The version requirements for a dependency cannot be combined. The error message names the cause: no version satisfies all of the ranges, a range is not valid semver syntax, or the combined ranges are too complex to intersect.
Uninstall or update one of the conflicting plugins, fix any invalid
version
string, simplify long
||
chains, or ask the upstream author to widen its constraint.
dependency-version-unsatisfied
The installed dependency’s version is outside this plugin’s declared range.
Run
claude plugin install <dependency>@<marketplace>
to re-resolve the dependency against all current constraints.
no-matching-tag
The dependency’s repository has no
{name}--v*
tag satisfying the range.
Check that the upstream has tagged releases using the convention above, or relax your range.
To check for these errors programmatically, run
claude plugin list --json
and read the
errors
field on each plugin.
​
See also
Create plugins
: build plugins with skills, agents, and hooks
Create and distribute a plugin marketplace
: host plugins for your team
Plugins reference
: the full
plugin.json
schema
Version management
: how a plugin’s own version is resolved and used as the cache key
Was this page helpful?
Yes
No
Create and distribute a plugin marketplace
Security
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugin-dependencies" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Constrain plugin dependency versions
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Constrain plugin dependency versions
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A plugin can depend on other plugins by listing them in
plugin.json
or in its marketplace entry. By default, a dependency tracks the latest available version, so an upstream release can change the dependency under your plugin without warning. Version constraints let you hold a dependency at a tested version range until you choose to move.
When you install a plugin that declares dependencies, Claude Code resolves and installs them automatically and lists which dependencies were added at the end of the install output. If a dependency later goes missing,
/reload-plugins
and the background plugin auto-update reinstall it, provided its marketplace is already in your configured marketplaces. Re-running
claude plugin install
on the dependent plugin, or adding a marketplace with
claude plugin marketplace add
, also resolves any outstanding missing dependencies. Dependencies from a marketplace you have not added are left unresolved.
This guide is for plugin authors who declare dependencies in
plugin.json
and for marketplace maintainers who tag releases. To install plugins that have dependencies, see
Discover and install plugins
. For the full manifest schema, see the
Plugins reference
.
Dependency version constraints require Claude Code v2.1.110 or later.
​
Why constrain dependency versions
Consider an internal marketplace where two teams publish plugins. The platform team maintains
secrets-vault
, an MCP server that wraps a secrets backend. The deploy team maintains
deploy-kit
, which calls
secrets-vault
to fetch credentials during deploys.
deploy-kit
is tested against
secrets-vault
v2.1.0. Without a version constraint, the next time the platform team tags a release that renames an MCP tool, auto-update moves every engineer’s
secrets-vault
to the new version and
deploy-kit
breaks.
With a version constraint,
deploy-kit
declares that it needs
secrets-vault
in the
~2.1.0
range. Engineers with
deploy-kit
installed stay on the highest matching
2.1.x
patch. The deploy team upgrades on their own schedule by publishing a new
deploy-kit
version with a wider constraint.
​
Declare a dependency with a version constraint
List dependencies in the
dependencies
array of your plugin’s
.claude-plugin/plugin.json
. Each entry is either a plugin name or an object with a version constraint.
The following manifest declares one unversioned dependency and one constrained dependency:
.claude-plugin/plugin.json
{
"name"
:
"deploy-kit"
,
"version"
:
"3.1.0"
,
"dependencies"
: [
"audit-logger"
,
{
"name"
:
"secrets-vault"
,
"version"
:
"~2.1.0"
}
]
}
An entry can be a bare string with only the plugin name, like
"audit-logger"
in the example above, which depends on whatever version that plugin’s marketplace provides. For more control, use an object with these fields:
Field
Type
Description
name
string
Plugin name. Resolves within the same marketplace as the declaring plugin. Required.
version
string
A
semver range
such as
~2.1.0
,
^2.0
,
>=1.4
, or
=2.1.0
. The dependency is fetched at the highest tagged version that satisfies this range.
marketplace
string
A different marketplace to resolve
name
in. Cross-marketplace dependencies are blocked unless the target marketplace is listed in
allowCrossMarketplaceDependenciesOn
in the root marketplace’s
marketplace.json
.
The
version
field accepts any expression supported by Node’s
semver
package, including caret, tilde, hyphen, and comparator ranges. Pre-release versions such as
2.0.0-beta.1
are excluded unless your range opts in with a pre-release suffix like
^2.0.0-0
.
​
Depend on a plugin from another marketplace
By default, Claude Code refuses to auto-install a dependency that lives in a different marketplace than the plugin declaring it. This prevents one marketplace from silently pulling in plugins from a source you have not reviewed.
To allow it, the maintainer of the root marketplace adds the target marketplace name to
allowCrossMarketplaceDependenciesOn
in
marketplace.json
. The root marketplace is the one that hosts the plugin the user is installing; only its allowlist is consulted, so trust does not chain through intermediate marketplaces.
The following
marketplace.json
allows
deploy-kit
to depend on a plugin from
acme-shared
:
.claude-plugin/marketplace.json
{
"name"
:
"acme-tools"
,
"owner"
: {
"name"
:
"Acme"
},
"allowCrossMarketplaceDependenciesOn"
: [
"acme-shared"
],
"plugins"
: [
{
"name"
:
"deploy-kit"
,
"source"
:
"./deploy-kit"
,
"dependencies"
: [
{
"name"
:
"audit-logger"
,
"marketplace"
:
"acme-shared"
}
]
}
]
}
If the field is missing or does not include the target marketplace, install fails with a
cross-marketplace
error naming the field to set. Users can still install the dependency manually first, which satisfies the constraint without changing the allowlist.
​
Tag plugin releases for version resolution
Version constraints resolve against git tags on the marketplace repository. For Claude Code to find a dependency’s available versions, the upstream plugin’s releases must be tagged using a specific naming convention.
Tag each release as
{plugin-name}--v{version}
, where
{version}
matches the
version
field in that commit’s
plugin.json
. From the plugin directory, run:
claude
plugin
tag
--push
The
claude plugin tag
command derives the tag name from the plugin’s manifest and the enclosing marketplace entry. Before creating the tag, it validates the plugin contents, checks that
plugin.json
and the marketplace entry agree on the version, requires a clean working tree under the plugin directory, and refuses if the tag already exists. Add
--dry-run
to see what would be tagged without creating it. Running
git tag secrets-vault--v2.1.0
directly is equivalent if you keep
plugin.json
and the marketplace entry in sync yourself.
The plugin name prefix lets one marketplace repository host multiple plugins with independent version lines. The
--v
separator is parsed as a prefix match on the full plugin name, so plugin names that contain hyphens are handled correctly.
When you install a plugin that declares
{ "name": "secrets-vault", "version": "~2.1.0" }
, Claude Code lists the marketplace’s tags, filters to those starting with
secrets-vault--v
, and fetches the highest version satisfying
~2.1.0
. If no matching tag exists, the dependent plugin is disabled with an error listing the available versions.
The resolved tag’s semver is recorded separately from
plugin.json
’s
version
, so constraint checks use the tag that was actually fetched even if
plugin.json
at that commit has a stale value. The cache directory name for a tag-resolved install includes a 12-character commit-SHA suffix, so if a maintainer force-moves a tag to a different commit, the next install gets a fresh cache directory instead of reusing stale content.
For
npm
marketplace sources, the constraint does not control which version is fetched, since tag-based resolution applies only to git-backed sources. The constraint is still checked at load time, and the dependent plugin is disabled with
dependency-version-unsatisfied
if the installed version does not satisfy it.
​
How constraints interact
When several installed plugins constrain the same dependency, Claude Code intersects their ranges and resolves the dependency to the highest version that satisfies all of them. The table below shows how common combinations resolve.
Plugin A requires
Plugin B requires
Result
^2.0
>=2.1
One install at the highest
2.x
tag at or above
2.1.0
. Both plugins load.
~2.1
~3.0
Install of plugin B fails with
range-conflict
. Plugin A and the dependency stay as they were.
=2.1.0
none
The dependency stays at
2.1.0
. Auto-update skips newer versions while plugin A is installed.
Auto-update fetches a constrained dependency at the highest git tag that satisfies every installed plugin’s range, rather than at the marketplace’s latest version, so the dependency continues to receive updates within its allowed range. If no tag satisfies all ranges, the update is skipped and the skip appears in
/doctor
and the
/plugin
Errors tab, naming the constraining plugin.
When you uninstall the last plugin that constrains a dependency, the dependency is no longer held and resumes tracking its marketplace entry on the next update.
​
Remove orphaned auto-installed dependencies
Auto-installed dependencies stay on disk after the plugins that installed them are uninstalled, in case you reinstall a dependent plugin or want to keep using the dependency directly. To clean them up, run
claude plugin prune
to list the auto-installed dependencies that no longer have any installed plugin requiring them and remove them after a confirmation prompt. This requires Claude Code v2.1.121 or later.
claude
plugin
prune
By default, prune operates at user scope. Use
--scope project
or
--scope local
to target a different scope. Pass
--dry-run
to list what would be removed without changing anything. Pass
-y
to skip the confirmation prompt. When stdin or stdout is not a terminal, prune lists the orphans and exits without removing them unless
-y
is passed.
To prune as part of an uninstall, pass
--prune
to
claude plugin uninstall
. After removing the named plugin, Claude Code scans for and removes any auto-installed dependencies that are now orphaned. Plugins you installed yourself are never pruned, only those installed automatically through another plugin’s
dependencies
array.
For example, to uninstall
deploy-kit
and clean up the dependencies it leaves behind:
claude
plugin
uninstall
deploy-kit
--prune
​
Resolve dependency errors
Dependency problems surface in
claude plugin list
, in the
/plugin
interface, and in
/doctor
. The affected plugin is disabled until you resolve the error. The most common errors and their fixes are listed below.
Error
Meaning
How to resolve
dependency-unsatisfied
A declared dependency is not installed, or it is installed but disabled.
Run the
claude plugin install
command shown in the error message. If the dependency’s marketplace is not yet configured, add it with
claude plugin marketplace add
and Claude Code resolves the dependency automatically. If the dependency is disabled, enable it.
range-conflict
The version requirements for a dependency cannot be combined. The error message names the cause: no version satisfies all of the ranges, a range is not valid semver syntax, or the combined ranges are too complex to intersect.
Uninstall or update one of the conflicting plugins, fix any invalid
version
string, simplify long
||
chains, or ask the upstream author to widen its constraint.
dependency-version-unsatisfied
The installed dependency’s version is outside this plugin’s declared range.
Run
claude plugin install <dependency>@<marketplace>
to re-resolve the dependency against all current constraints.
no-matching-tag
The dependency’s repository has no
{name}--v*
tag satisfying the range.
Check that the upstream has tagged releases using the convention above, or relax your range.
To check for these errors programmatically, run
claude plugin list --json
and read the
errors
field on each plugin.
​
See also
Create plugins
: build plugins with skills, agents, and hooks
Create and distribute a plugin marketplace
: host plugins for your team
Plugins reference
: the full
plugin.json
schema
Version management
: how a plugin’s own version is resolved and used as the cache key
Was this page helpful?
Yes
No
Create and distribute a plugin marketplace
Security
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugin-dependencies" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Run prompts on a schedule</title>
  <link>https://code.claude.com/docs/en/scheduled-tasks</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/scheduled-tasks</guid>
  <pubDate>Sun, 14 Apr 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run prompts on a schedule
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run prompts on a schedule
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Scheduled tasks require Claude Code v2.1.72 or later. Check your version with
claude --version
.
Scheduled tasks let Claude re-run a prompt automatically on an interval. Use them to poll a deployment, babysit a PR, check back on a long-running build, or remind yourself to do something later in the session. To react to events as they happen instead of polling, see
Channels
: your CI can push the failure into the session directly. To keep the session working turn after turn until a condition is met rather than on an interval, see
/goal
.
Tasks are session-scoped: they live in the current conversation and stop when you start a new one. Resuming with
--resume
or
--continue
brings back any task that hasn’t
expired
: a recurring task created within the last 7 days, or a one-shot whose scheduled time hasn’t passed yet. For scheduling that survives independently of any session, use
Routines
,
Desktop scheduled tasks
, or
GitHub Actions
.
​
Compare scheduling options
Claude Code offers three ways to schedule recurring or one-off work:
Cloud
Desktop
/loop
Runs on
Anthropic cloud
Your machine
Your machine
Requires machine on
No
Yes
Yes
Requires open session
No
No
Yes
Persistent across restarts
Yes
Yes
Restored on
--resume
if unexpired
Access to local files
No (fresh clone)
Yes
Yes
MCP servers
Connectors configured per task
Config files
and connectors
Inherits from session
Permission prompts
No (runs autonomously)
Configurable per task
Inherits from session
Customizable schedule
Via
/schedule
in the CLI
Yes
Yes
Minimum interval
1 hour
1 minute
1 minute
Use
cloud tasks
for work that should run reliably without your machine. Use
Desktop tasks
when you need access to local files and tools. Use
/loop
for quick polling during a session.
​
Run a prompt repeatedly with /loop
The
/loop
bundled skill
is the quickest way to run a prompt on repeat while the session stays open. Both the interval and the prompt are optional, and what you provide determines how the loop behaves.
What you provide
Example
What happens
Interval and prompt
/loop 5m check the deploy
Your prompt runs on a
fixed schedule
Prompt only
/loop check the deploy
Your prompt runs at an
interval Claude chooses
each iteration
Interval only, or nothing
/loop
The
built-in maintenance prompt
runs, or your
loop.md
if one exists
You can also pass another command as the prompt, for example
/loop 20m /review-pr 1234
, to re-run a packaged workflow each iteration.
​
Run on a fixed interval
When you supply an interval, Claude converts it to a cron expression, schedules the job, and confirms the cadence and job ID.
/loop 5m check if the deployment finished and tell me what happened
The interval can lead the prompt as a bare token like
30m
, or trail it as a clause like
every 2 hours
. Supported units are
s
for seconds,
m
for minutes,
h
for hours, and
d
for days.
Seconds are rounded up to the nearest minute since cron has one-minute granularity. Intervals that don’t map to a clean cron step, such as
7m
or
90m
, are rounded to the nearest interval that does and Claude tells you what it picked.
​
Let Claude choose the interval
When you omit the interval, Claude chooses one dynamically instead of running on a fixed cron schedule. After each iteration it picks a delay between one minute and one hour based on what it observed: short waits while a build is finishing or a PR is active, longer waits when nothing is pending. The chosen delay and the reason for it are printed at the end of each iteration.
The example below checks CI and review comments, with Claude waiting longer between iterations once the PR goes quiet:
/loop check whether CI passed and address any review comments
When you ask for a dynamic
/loop
schedule, Claude may use the
Monitor tool
directly. Monitor runs a background script and streams each output line back, which avoids polling altogether and is often more token-efficient and responsive than re-running a prompt on an interval.
A dynamically scheduled loop appears in your
scheduled task list
like any other task, so you can list or cancel it the same way. The
jitter rules
don’t apply to it, but the
seven-day expiry
does: the loop ends automatically seven days after you start it.
On Bedrock, Vertex AI, and Microsoft Foundry, a prompt with no interval runs on a fixed 10-minute schedule instead.
​
Run the built-in maintenance prompt
When you omit the prompt, Claude uses a built-in maintenance prompt instead of one you supply. On each iteration it works through the following, in order:
continue any unfinished work from the conversation
tend to the current branch’s pull request: review comments, failed CI runs, merge conflicts
run cleanup passes such as bug hunts or simplification when nothing else is pending
Claude does not start new initiatives outside that scope, and irreversible actions such as pushing or deleting only proceed when they continue something the transcript already authorized.
/loop
A bare
/loop
runs this prompt at a
dynamically chosen interval
. Add an interval, for example
/loop 15m
, to run it on a fixed schedule instead. To replace the built-in prompt with your own default, see
Customize the default prompt with loop.md
.
On Bedrock, Vertex AI, and Microsoft Foundry,
/loop
with no prompt prints the usage message instead of starting the maintenance loop.
​
Customize the default prompt with loop.md
A
loop.md
file replaces the built-in maintenance prompt with your own instructions. It defines a single default prompt for bare
/loop
, not a list of separate scheduled tasks, and is ignored whenever you supply a prompt on the command line. To schedule additional prompts alongside it, use
/loop <prompt>
or
ask Claude directly
.
Claude looks for the file in two locations and uses the first one it finds.
Path
Scope
.claude/loop.md
Project-level. Takes precedence when both files exist.
~/.claude/loop.md
User-level. Applies in any project that does not define its own.
The file is plain Markdown with no required structure. Write it as if you were typing the
/loop
prompt directly. The following example keeps a release branch healthy:
.claude/loop.md
Check the
`release/next`
PR. If CI is red, pull the failing job log,
diagnose, and push a minimal fix. If new review comments have arrived,
address each one and resolve the thread. If everything is green and
quiet, say so in one line.
Edits to
loop.md
take effect on the next iteration, so you can refine the instructions while a loop is running. When no
loop.md
exists in either location, the loop falls back to the built-in maintenance prompt. Keep the file concise: content beyond 25,000 bytes is truncated.
​
Stop a loop
To stop a
/loop
while it is waiting for the next iteration, press
Esc
. This clears the pending wakeup so the loop does not fire again. Tasks you scheduled by
asking Claude directly
are not affected by
Esc
and stay in place until you delete them.
In
self-paced mode
, Claude can also end the loop on its own by not scheduling the next wakeup once the task is provably complete. Loops on a fixed interval keep running until you stop them or
seven days elapse
.
​
Set a one-time reminder
For one-shot reminders, describe what you want in natural language instead of using
/loop
. Claude schedules a single-fire task that deletes itself after running.
remind me at 3pm to push the release branch
in 45 minutes, check whether the integration tests passed
Claude pins the fire time to a specific minute and hour using a cron expression and confirms when it will fire.
​
Manage scheduled tasks
Ask Claude in natural language to list or cancel tasks, or reference the underlying tools directly.
what scheduled tasks do I have?
cancel the deploy check job
Under the hood, Claude uses these tools:
Tool
Purpose
CronCreate
Schedule a new task. Accepts a 5-field cron expression, the prompt to run, and whether it recurs or fires once.
CronList
List all scheduled tasks with their IDs, schedules, and prompts.
CronDelete
Cancel a task by ID.
Each scheduled task has an 8-character ID you can pass to
CronDelete
. A session can hold up to 50 scheduled tasks at once.
​
How scheduled tasks run
The scheduler checks every second for due tasks and enqueues them at low priority. A scheduled prompt fires between your turns, not while Claude is mid-response. If Claude is busy when a task comes due, the prompt waits until the current turn ends.
All times are interpreted in your local timezone. A cron expression like
0 9 * * *
means 9am wherever you’re running Claude Code, not UTC.
​
Jitter
To avoid every session hitting the API at the same wall-clock moment, the scheduler adds a deterministic offset to fire times:
Recurring tasks fire up to 30 minutes after the scheduled time (or up to half the interval, for tasks that run more often than hourly). An hourly job scheduled for
:00
may fire anywhere up to
:30
.
One-shot tasks scheduled for the top or bottom of the hour fire up to 90 seconds early.
The offset is derived from the task ID, so the same task always gets the same offset. If exact timing matters, pick a minute that is not
:00
or
:30
, for example
3 9 * * *
instead of
0 9 * * *
, and the one-shot jitter will not apply.
​
Seven-day expiry
Recurring tasks automatically expire 7 days after creation. The task fires one final time, then deletes itself. This bounds how long a forgotten loop can run. If you need a recurring task to last longer, cancel and recreate it before it expires, or use
Routines
or
Desktop scheduled tasks
for durable scheduling.
​
Cron expression reference
CronCreate
accepts standard 5-field cron expressions:
minute hour day-of-month month day-of-week
. All fields support wildcards (
*
), single values (
5
), steps (
*/15
), ranges (
1-5
), and comma-separated lists (
1,15,30
).
Example
Meaning
*/5 * * * *
Every 5 minutes
0 * * * *
Every hour on the hour
7 * * * *
Every hour at 7 minutes past
0 9 * * *
Every day at 9am local
0 9 * * 1-5
Weekdays at 9am local
30 14 15 3 *
March 15 at 2:30pm local
Day-of-week uses
0
or
7
for Sunday through
6
for Saturday. Extended syntax like
L
,
W
,
?
, and name aliases such as
MON
or
JAN
is not supported.
When both day-of-month and day-of-week are constrained, a date matches if either field matches. This follows standard vixie-cron semantics.
​
Disable scheduled tasks
Set
CLAUDE_CODE_DISABLE_CRON=1
in your environment to disable the scheduler entirely. The cron tools and
/loop
become unavailable, and any already-scheduled tasks stop firing. See
Environment variables
for the full list of disable flags.
​
Limitations
Session-scoped scheduling has inherent constraints:
Tasks only fire while Claude Code is running and idle. Closing the terminal or letting the session exit stops them firing.
No catch-up for missed fires. If a task’s scheduled time passes while Claude is busy on a long-running request, it fires once when Claude becomes idle, not once per missed interval.
Starting a fresh conversation clears all session-scoped tasks. Resuming with
claude --resume
or
claude --continue
restores tasks that have not expired: recurring tasks within seven days of creation, and one-shot tasks whose scheduled time has not yet passed. Background Bash and monitor tasks are never restored on resume.
For cron-driven automation that needs to run unattended:
Routines
: run on Anthropic-managed infrastructure on a schedule, via API call, or on GitHub events
GitHub Actions
: use a
schedule
trigger in CI
Desktop scheduled tasks
: run locally on your machine
Was this page helpful?
Yes
No
Push external events to Claude
Goals
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/scheduled-tasks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run prompts on a schedule
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Automation
Run prompts on a schedule
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Scheduled tasks require Claude Code v2.1.72 or later. Check your version with
claude --version
.
Scheduled tasks let Claude re-run a prompt automatically on an interval. Use them to poll a deployment, babysit a PR, check back on a long-running build, or remind yourself to do something later in the session. To react to events as they happen instead of polling, see
Channels
: your CI can push the failure into the session directly. To keep the session working turn after turn until a condition is met rather than on an interval, see
/goal
.
Tasks are session-scoped: they live in the current conversation and stop when you start a new one. Resuming with
--resume
or
--continue
brings back any task that hasn’t
expired
: a recurring task created within the last 7 days, or a one-shot whose scheduled time hasn’t passed yet. For scheduling that survives independently of any session, use
Routines
,
Desktop scheduled tasks
, or
GitHub Actions
.
​
Compare scheduling options
Claude Code offers three ways to schedule recurring or one-off work:
Cloud
Desktop
/loop
Runs on
Anthropic cloud
Your machine
Your machine
Requires machine on
No
Yes
Yes
Requires open session
No
No
Yes
Persistent across restarts
Yes
Yes
Restored on
--resume
if unexpired
Access to local files
No (fresh clone)
Yes
Yes
MCP servers
Connectors configured per task
Config files
and connectors
Inherits from session
Permission prompts
No (runs autonomously)
Configurable per task
Inherits from session
Customizable schedule
Via
/schedule
in the CLI
Yes
Yes
Minimum interval
1 hour
1 minute
1 minute
Use
cloud tasks
for work that should run reliably without your machine. Use
Desktop tasks
when you need access to local files and tools. Use
/loop
for quick polling during a session.
​
Run a prompt repeatedly with /loop
The
/loop
bundled skill
is the quickest way to run a prompt on repeat while the session stays open. Both the interval and the prompt are optional, and what you provide determines how the loop behaves.
What you provide
Example
What happens
Interval and prompt
/loop 5m check the deploy
Your prompt runs on a
fixed schedule
Prompt only
/loop check the deploy
Your prompt runs at an
interval Claude chooses
each iteration
Interval only, or nothing
/loop
The
built-in maintenance prompt
runs, or your
loop.md
if one exists
You can also pass another command as the prompt, for example
/loop 20m /review-pr 1234
, to re-run a packaged workflow each iteration.
​
Run on a fixed interval
When you supply an interval, Claude converts it to a cron expression, schedules the job, and confirms the cadence and job ID.
/loop 5m check if the deployment finished and tell me what happened
The interval can lead the prompt as a bare token like
30m
, or trail it as a clause like
every 2 hours
. Supported units are
s
for seconds,
m
for minutes,
h
for hours, and
d
for days.
Seconds are rounded up to the nearest minute since cron has one-minute granularity. Intervals that don’t map to a clean cron step, such as
7m
or
90m
, are rounded to the nearest interval that does and Claude tells you what it picked.
​
Let Claude choose the interval
When you omit the interval, Claude chooses one dynamically instead of running on a fixed cron schedule. After each iteration it picks a delay between one minute and one hour based on what it observed: short waits while a build is finishing or a PR is active, longer waits when nothing is pending. The chosen delay and the reason for it are printed at the end of each iteration.
The example below checks CI and review comments, with Claude waiting longer between iterations once the PR goes quiet:
/loop check whether CI passed and address any review comments
When you ask for a dynamic
/loop
schedule, Claude may use the
Monitor tool
directly. Monitor runs a background script and streams each output line back, which avoids polling altogether and is often more token-efficient and responsive than re-running a prompt on an interval.
A dynamically scheduled loop appears in your
scheduled task list
like any other task, so you can list or cancel it the same way. The
jitter rules
don’t apply to it, but the
seven-day expiry
does: the loop ends automatically seven days after you start it.
On Bedrock, Vertex AI, and Microsoft Foundry, a prompt with no interval runs on a fixed 10-minute schedule instead.
​
Run the built-in maintenance prompt
When you omit the prompt, Claude uses a built-in maintenance prompt instead of one you supply. On each iteration it works through the following, in order:
continue any unfinished work from the conversation
tend to the current branch’s pull request: review comments, failed CI runs, merge conflicts
run cleanup passes such as bug hunts or simplification when nothing else is pending
Claude does not start new initiatives outside that scope, and irreversible actions such as pushing or deleting only proceed when they continue something the transcript already authorized.
/loop
A bare
/loop
runs this prompt at a
dynamically chosen interval
. Add an interval, for example
/loop 15m
, to run it on a fixed schedule instead. To replace the built-in prompt with your own default, see
Customize the default prompt with loop.md
.
On Bedrock, Vertex AI, and Microsoft Foundry,
/loop
with no prompt prints the usage message instead of starting the maintenance loop.
​
Customize the default prompt with loop.md
A
loop.md
file replaces the built-in maintenance prompt with your own instructions. It defines a single default prompt for bare
/loop
, not a list of separate scheduled tasks, and is ignored whenever you supply a prompt on the command line. To schedule additional prompts alongside it, use
/loop <prompt>
or
ask Claude directly
.
Claude looks for the file in two locations and uses the first one it finds.
Path
Scope
.claude/loop.md
Project-level. Takes precedence when both files exist.
~/.claude/loop.md
User-level. Applies in any project that does not define its own.
The file is plain Markdown with no required structure. Write it as if you were typing the
/loop
prompt directly. The following example keeps a release branch healthy:
.claude/loop.md
Check the
`release/next`
PR. If CI is red, pull the failing job log,
diagnose, and push a minimal fix. If new review comments have arrived,
address each one and resolve the thread. If everything is green and
quiet, say so in one line.
Edits to
loop.md
take effect on the next iteration, so you can refine the instructions while a loop is running. When no
loop.md
exists in either location, the loop falls back to the built-in maintenance prompt. Keep the file concise: content beyond 25,000 bytes is truncated.
​
Stop a loop
To stop a
/loop
while it is waiting for the next iteration, press
Esc
. This clears the pending wakeup so the loop does not fire again. Tasks you scheduled by
asking Claude directly
are not affected by
Esc
and stay in place until you delete them.
In
self-paced mode
, Claude can also end the loop on its own by not scheduling the next wakeup once the task is provably complete. Loops on a fixed interval keep running until you stop them or
seven days elapse
.
​
Set a one-time reminder
For one-shot reminders, describe what you want in natural language instead of using
/loop
. Claude schedules a single-fire task that deletes itself after running.
remind me at 3pm to push the release branch
in 45 minutes, check whether the integration tests passed
Claude pins the fire time to a specific minute and hour using a cron expression and confirms when it will fire.
​
Manage scheduled tasks
Ask Claude in natural language to list or cancel tasks, or reference the underlying tools directly.
what scheduled tasks do I have?
cancel the deploy check job
Under the hood, Claude uses these tools:
Tool
Purpose
CronCreate
Schedule a new task. Accepts a 5-field cron expression, the prompt to run, and whether it recurs or fires once.
CronList
List all scheduled tasks with their IDs, schedules, and prompts.
CronDelete
Cancel a task by ID.
Each scheduled task has an 8-character ID you can pass to
CronDelete
. A session can hold up to 50 scheduled tasks at once.
​
How scheduled tasks run
The scheduler checks every second for due tasks and enqueues them at low priority. A scheduled prompt fires between your turns, not while Claude is mid-response. If Claude is busy when a task comes due, the prompt waits until the current turn ends.
All times are interpreted in your local timezone. A cron expression like
0 9 * * *
means 9am wherever you’re running Claude Code, not UTC.
​
Jitter
To avoid every session hitting the API at the same wall-clock moment, the scheduler adds a deterministic offset to fire times:
Recurring tasks fire up to 30 minutes after the scheduled time (or up to half the interval, for tasks that run more often than hourly). An hourly job scheduled for
:00
may fire anywhere up to
:30
.
One-shot tasks scheduled for the top or bottom of the hour fire up to 90 seconds early.
The offset is derived from the task ID, so the same task always gets the same offset. If exact timing matters, pick a minute that is not
:00
or
:30
, for example
3 9 * * *
instead of
0 9 * * *
, and the one-shot jitter will not apply.
​
Seven-day expiry
Recurring tasks automatically expire 7 days after creation. The task fires one final time, then deletes itself. This bounds how long a forgotten loop can run. If you need a recurring task to last longer, cancel and recreate it before it expires, or use
Routines
or
Desktop scheduled tasks
for durable scheduling.
​
Cron expression reference
CronCreate
accepts standard 5-field cron expressions:
minute hour day-of-month month day-of-week
. All fields support wildcards (
*
), single values (
5
), steps (
*/15
), ranges (
1-5
), and comma-separated lists (
1,15,30
).
Example
Meaning
*/5 * * * *
Every 5 minutes
0 * * * *
Every hour on the hour
7 * * * *
Every hour at 7 minutes past
0 9 * * *
Every day at 9am local
0 9 * * 1-5
Weekdays at 9am local
30 14 15 3 *
March 15 at 2:30pm local
Day-of-week uses
0
or
7
for Sunday through
6
for Saturday. Extended syntax like
L
,
W
,
?
, and name aliases such as
MON
or
JAN
is not supported.
When both day-of-month and day-of-week are constrained, a date matches if either field matches. This follows standard vixie-cron semantics.
​
Disable scheduled tasks
Set
CLAUDE_CODE_DISABLE_CRON=1
in your environment to disable the scheduler entirely. The cron tools and
/loop
become unavailable, and any already-scheduled tasks stop firing. See
Environment variables
for the full list of disable flags.
​
Limitations
Session-scoped scheduling has inherent constraints:
Tasks only fire while Claude Code is running and idle. Closing the terminal or letting the session exit stops them firing.
No catch-up for missed fires. If a task’s scheduled time passes while Claude is busy on a long-running request, it fires once when Claude becomes idle, not once per missed interval.
Starting a fresh conversation clears all session-scoped tasks. Resuming with
claude --resume
or
claude --continue
restores tasks that have not expired: recurring tasks within seven days of creation, and one-shot tasks whose scheduled time has not yet passed. Background Bash and monitor tasks are never restored on resume.
For cron-driven automation that needs to run unattended:
Routines
: run on Anthropic-managed infrastructure on a schedule, via API call, or on GitHub events
GitHub Actions
: use a
schedule
trigger in CI
Desktop scheduled tasks
: run locally on your machine
Was this page helpful?
Yes
No
Push external events to Claude
Goals
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/scheduled-tasks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Glossary</title>
  <link>https://code.claude.com/docs/en/glossary</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/glossary</guid>
  <pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Glossary
Glossary
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This glossary defines Claude Code terminology. Each entr...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Glossary
Glossary
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This glossary defines Claude Code terminology. Each entry links to the page where the concept is covered in depth. For model-level concepts like tokens, temperature, and RAG, see the
platform glossary
.
​
A
​
Agent teams
Multiple independent Claude Code sessions coordinated by a team lead, with a shared task list and peer-to-peer messaging. Unlike
subagents
, which run within a single session and report only to the parent, teammates each have their own context window and you can interact with any of them directly. Agent teams are experimental and must be enabled by setting
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
.
Learn more:
Run agent teams
​
Agentic coding
A workflow where the AI can read files, run commands, and make changes autonomously while you watch, redirect, or step away, as opposed to chat-based assistants that only respond with text you must apply yourself. Claude Code is agentic because it has
tools
that let it act, not just advise.
Learn more:
How Claude Code works
​
Agentic harness
The tools, context management, and execution environment that turn a language model into a capable coding agent. Claude Code is the harness; Claude is the model inside it. The harness supplies file access, shell execution, permission gating, memory loading, and the loop that chains actions together.
Learn more:
How Claude Code works
​
Agentic loop
The cycle Claude works through for every task: gather context, take action, verify results, and repeat until done. Each tool use returns information that informs the next step. You can interrupt the loop at any point to redirect. Most extension points, including
hooks
,
skills
, and
MCP
, plug into specific phases of this loop.
Learn more:
How Claude Code works
​
Auto memory
Notes Claude writes for itself based on your corrections and preferences, stored per git repository under
~/.claude/projects/
. All worktrees of the same repository share one auto memory directory. The first 200 lines or 25 KB of the
MEMORY.md
index loads at the start of every session. Auto memory is the Claude-written counterpart to
CLAUDE.md
, which you write.
Learn more:
Auto memory
​
Auto mode
A
permission mode
where a separate classifier model reviews each action in the background instead of showing you approval prompts. The classifier blocks scope escalation, untrusted infrastructure, and
prompt injection
. It never sees tool results, so injected instructions cannot influence its decisions. Auto mode is a research preview available on Max, Team, Enterprise, and API plans.
Learn more:
Eliminate prompts with auto mode
​
B
​
Bare mode
A startup flag,
--bare
, that skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Only flags you pass explicitly take effect. Recommended for CI and scripted calls where you need identical behavior across machines regardless of local configuration.
Learn more:
Start faster with bare mode
​
Bundled skills
Prompt-based playbooks included with Claude Code, such as
/batch
,
/simplify
,
/debug
, and
/loop
. Unlike built-in commands, which execute fixed logic, bundled skills give Claude a detailed prompt and let it orchestrate the work, so they can spawn agents, read files, and adapt to your codebase.
Learn more:
Bundled skills
​
C
​
Channel
An
MCP server
that pushes events into your running session so Claude can react to things that happen while you’re away from the terminal. Channels can be two-way: Claude reads an inbound event and replies back through the same channel. Telegram, Discord, and iMessage are included in the research preview.
Learn more:
Channels
​
Checkpoint
A restore point created at each prompt you send. Claude Code snapshots files before every edit so a checkpoint can revert them. Press
Esc
twice or run
/rewind
to restore code, conversation, or both to an earlier point, or to summarize part of the conversation from a selected message. Checkpoints are local to the session, separate from git, and don’t track changes made through the Bash tool.
Learn more:
Checkpointing
​
.claude
directory
The directory where Claude Code reads project-scoped configuration: settings, hooks, skills, subagents, rules, and auto memory. A project has
.claude/
at its root; your user-level defaults are at
~/.claude/
.
Learn more:
The
.claude
directory
​
CLAUDE.md
A markdown file of persistent instructions you write for Claude, loaded at the start of every session as a user message after the system prompt. Put project conventions, architecture notes, and “always do X” rules here. CLAUDE.md survives
compaction
and is re-read fresh from disk afterward.
You can place CLAUDE.md at project scope in
./CLAUDE.md
or
./.claude/CLAUDE.md
, at user scope in
~/.claude/CLAUDE.md
, or as
managed policy
for your organization. More specific locations take precedence.
Learn more:
CLAUDE.md files
​
Command
A reusable instruction you invoke by typing
/name
in the prompt. Built-in commands such as
/clear
,
/model
, and
/compact
control the session. You can define your own commands as files in
.claude/commands/
, or install them from a
plugin
.
Skills
are the recommended way to package multi-step commands.
Learn more:
Commands
·
Skills
​
Compaction
Automatic summarization of your conversation when the
context window
approaches its limit. Older tool outputs are cleared first, then the conversation is summarized. Project-root CLAUDE.md and auto memory survive compaction and reload from disk; instructions given only in conversation may be lost. Run
/compact
to trigger manually, optionally with a focus like
/compact focus on the API changes
.
Learn more:
What survives compaction
·
When context fills up
​
Context window
The working memory for a session, holding conversation history, file contents, command outputs, CLAUDE.md, auto memory, loaded skills, and system instructions. As you work, context fills up until
compaction
summarizes it. Run
/context
to see what’s using space. For the underlying model concept, see the
platform glossary
.
Learn more:
Explore the context window
​
D
​
Dispatch
A phone-initiated task router that spawns a Claude Code session in the Desktop app when you send a coding task from the Claude mobile app. Your prompt routes to the right tool automatically. Available on Pro and Max plans.
Learn more:
Sessions from Dispatch
​
E
​
Effort level
A setting that controls how much of the adaptive-reasoning thinking budget Claude uses on each turn. Higher effort means more thinking tokens and deeper reasoning; lower effort is faster and cheaper. Effort is supported on Opus 4.7, Opus 4.6, and Sonnet 4.6.
Learn more:
Adjust effort level
​
Extended thinking
Visible step-by-step reasoning the model performs before responding. You can cap thinking tokens with
MAX_THINKING_TOKENS
or adjust the
effort level
. Thinking appears in gray italic text in the terminal.
Learn more:
Use extended thinking
​
H
​
Hook
A user-defined handler that executes automatically at a specific point in Claude Code’s lifecycle, such as before a tool runs, after a file edit, or at session start. Handlers can be a shell command, HTTP endpoint, MCP tool, LLM prompt, or subagent. Hooks are deterministic: they fire at fixed lifecycle points rather than at the model’s discretion.
A hook configuration has three levels:
Hook event
: the lifecycle point
Matcher
: filters which events fire it
Hook handler
: what runs
Learn more:
Get started with hooks
·
Hooks reference
​
M
​
Managed settings
A settings file enforced org-wide by IT or DevOps, placed at an OS-level path outside
~/.claude
. Users cannot override or exclude managed settings. Use this for security policies, compliance requirements, or standardized tooling across a fleet.
Learn more:
Server-managed settings
​
MCP (Model Context Protocol)
An open standard for connecting AI tools to external data sources and services. MCP servers give Claude new tools for Slack, Jira, databases, browsers, and hundreds of other integrations. You connect servers via
/mcp
or by adding them to
.mcp.json
. For the protocol itself, see the
platform glossary
.
Learn more:
Model Context Protocol
​
MCP Tool Search
A context-saving mechanism that defers MCP tool schemas until needed. Only tool names load at startup; Claude fetches the full schema on demand when it decides to use a specific tool. This keeps idle MCP servers from consuming much context.
Learn more:
Scale with MCP Tool Search
​
N
​
Non-interactive mode
A mode that executes a single prompt and exits without a conversational session, invoked with
-p
or
--print
. Used for CI, scripts, and piping. The
Agent SDK
is the Python and TypeScript equivalent. Formerly called headless mode.
Learn more:
Run Claude Code programmatically
​
O
​
Output style
A configuration that modifies Claude’s system prompt to change response behavior, tone, or format. Output styles turn off the software-engineering-specific parts of the default system prompt, unlike
CLAUDE.md
which is delivered as a user message following the system prompt. Built-in styles include Default, Proactive, Explanatory, and Learning.
Learn more:
Output styles
​
P
​
Permission mode
The baseline approval behavior for the session. Cycle with
Shift+Tab
in the CLI or use the mode selector in VS Code, Desktop, and claude.ai. Available modes are
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
, and
bypassPermissions
.
Learn more:
Choose a permission mode
​
Permission rule
A settings entry that allows, asks about, or denies a tool invocation based on the tool name and argument pattern. Rules are evaluated deny→ask→allow, first match wins. Permission rules are fine-grained controls layered on top of the broader
permission mode
.
Learn more:
Configure permissions
​
Plan mode
A
permission mode
where Claude researches and proposes changes without editing your source files. It can read, search, and run exploration commands, then presents a plan for approval before touching anything. Enter plan mode with
/plan
or by pressing
Shift+Tab
.
Learn more:
Analyze before you edit with plan mode
​
Plugin
A bundle of skills, hooks, subagents, and MCP servers packaged as a single installable unit. Plugin skills are namespaced as
plugin-name:skill-name
so multiple plugins coexist. Distribute plugins across teams via a
marketplace
.
Learn more:
Plugins
​
Project trust
A one-time dialog accepting a directory before Claude Code loads its configuration. Trust gates auto-installation of marketplace plugins and execution of project-defined hooks. Trusting a directory means its
.claude/settings.json
,
.mcp.json
, and other config files take effect.
Learn more:
The
.claude
directory
​
Prompt injection
Hostile instructions embedded in a file, web page, or tool result that attempt to redirect Claude toward actions you never asked for. Claude Code’s defenses include the permission system, command blocklists, and trust verification.
Auto mode
adds a server-side probe that scans tool results for suspicious content and a classifier that never sees tool results, so injected text cannot influence its approval decisions.
Learn more:
Protect against prompt injection
​
R
​
Remote Control
A way to continue a local Claude Code session from your phone or browser via claude.ai. Your code stays on your machine; only the UI is remote. Different from Claude Code on the web, which runs in a cloud sandbox.
Learn more:
Remote Control
​
Rules
Modular instruction files in
.claude/rules/
that load alongside CLAUDE.md. A rule can be path-scoped with YAML
paths:
frontmatter so it only loads when Claude reads a matching file, keeping context lean until it’s relevant.
Learn more:
Organize rules with
.claude/rules/
​
S
​
Sandboxing
OS-level filesystem and network isolation for the Bash tool. Commands run inside a boundary you define upfront, so Claude can work freely within it without per-command approval prompts. Sandboxing is a separate layer from
permission rules
.
Learn more:
Sandboxing
​
Session
A conversation tied to your current directory, with its own independent
context window
. Sessions can be resumed with
claude -c
, forked with
--fork-session
to preserve history under a new session ID, or run in parallel across terminals. Running
/clear
starts a new session; the previous one stays stored and is available via
/resume
. Each session’s transcript is stored under
~/.claude/projects/
.
Learn more:
Work with sessions
​
Settings layers
The hierarchy Claude Code reads configuration from, in precedence order from highest to lowest:
managed policy
, command-line arguments, local settings at
.claude/settings.local.json
, project settings at
.claude/settings.json
, then user settings at
~/.claude/settings.json
. Arrays merge across layers; scalars at a higher layer override lower ones.
Learn more:
Settings files
​
Skill
A
SKILL.md
file containing instructions, knowledge, or a workflow that Claude adds to its toolkit. Claude loads a skill automatically when relevant, or you invoke it directly with
/skill-name
. Skills follow the Agent Skills open standard; Claude Code extends it with invocation control and subagent execution.
Skills are the recommended successor to custom commands. A file at
.claude/commands/deploy.md
and one at
.claude/skills/deploy/SKILL.md
both create
/deploy
and work the same way; existing command files continue to work.
Learn more:
Extend Claude with skills
​
Subagent
A specialized AI assistant that runs in its own context window with a custom system prompt, specific tool access, and independent permissions. It works on a delegated task and returns a summary to the main conversation. Use subagents to keep large explorations out of your primary context or to run parallel research. Different from
agent teams
, where each agent is a full independent session you can talk to directly.
Built-in subagents include Explore, Plan, and general-purpose.
Learn more:
Create custom subagents
​
Surface
Any place you access Claude Code: the CLI, VS Code, JetBrains, Desktop, or claude.ai. All surfaces share the same engine, so your CLAUDE.md, settings, and skills work the same way across them. Slack and the Chrome extension are integrations that connect to a surface rather than surfaces themselves.
Learn more:
Platforms and integrations
​
T
​
Teleport
A command,
/teleport
, that pulls a cloud Claude Code session into your local terminal. Claude fetches the branch, loads the conversation history, and resumes from the web session’s last state. The reverse direction is
--remote
, which sends a local task to run on the web.
Learn more:
From web to terminal
​
Tool
An action Claude can take: read a file, edit code, run a shell command, search the web, spawn a subagent. Tools are what make Claude Code agentic. Without them, Claude can only respond with text. Each tool use returns a result that informs Claude’s next decision in the
agentic loop
.
Learn more:
Tools available to Claude
​
Turn
One complete response from Claude within a
session
. A turn begins when you send a message and ends when Claude finishes responding, with any number of
tool
calls in between.
Stop hooks
fire at the end of each turn. A session consists of many turns, and the
agentic loop
describes what happens inside one.
Learn more:
How Claude Code works
​
W
​
Worktree isolation
An isolation mode that runs Claude in a separate git worktree under
.claude/worktrees/
, enabled with the
-w
flag or
isolation: worktree
in subagent config. Changes stay on a separate branch in a separate directory, so parallel agents don’t overwrite each other’s files.
Learn more:
Run parallel sessions with git worktrees
​
Deprecated and renamed terms
These terms appear in older docs, blog posts, and community content. Use the current name when searching this site.
Old term
Now called
Notes
Headless mode
Non-interactive mode
Same
-p
flag, same behavior
Custom commands
Skills
.claude/commands/
files still work
Slash commands
Commands
”Slash” dropped from product copy
Was this page helpful?
Yes
No
Channels reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/glossary" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Glossary
Glossary
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This glossary defines Claude Code terminology. Each entr...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Glossary
Glossary
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This glossary defines Claude Code terminology. Each entry links to the page where the concept is covered in depth. For model-level concepts like tokens, temperature, and RAG, see the
platform glossary
.
​
A
​
Agent teams
Multiple independent Claude Code sessions coordinated by a team lead, with a shared task list and peer-to-peer messaging. Unlike
subagents
, which run within a single session and report only to the parent, teammates each have their own context window and you can interact with any of them directly. Agent teams are experimental and must be enabled by setting
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
.
Learn more:
Run agent teams
​
Agentic coding
A workflow where the AI can read files, run commands, and make changes autonomously while you watch, redirect, or step away, as opposed to chat-based assistants that only respond with text you must apply yourself. Claude Code is agentic because it has
tools
that let it act, not just advise.
Learn more:
How Claude Code works
​
Agentic harness
The tools, context management, and execution environment that turn a language model into a capable coding agent. Claude Code is the harness; Claude is the model inside it. The harness supplies file access, shell execution, permission gating, memory loading, and the loop that chains actions together.
Learn more:
How Claude Code works
​
Agentic loop
The cycle Claude works through for every task: gather context, take action, verify results, and repeat until done. Each tool use returns information that informs the next step. You can interrupt the loop at any point to redirect. Most extension points, including
hooks
,
skills
, and
MCP
, plug into specific phases of this loop.
Learn more:
How Claude Code works
​
Auto memory
Notes Claude writes for itself based on your corrections and preferences, stored per git repository under
~/.claude/projects/
. All worktrees of the same repository share one auto memory directory. The first 200 lines or 25 KB of the
MEMORY.md
index loads at the start of every session. Auto memory is the Claude-written counterpart to
CLAUDE.md
, which you write.
Learn more:
Auto memory
​
Auto mode
A
permission mode
where a separate classifier model reviews each action in the background instead of showing you approval prompts. The classifier blocks scope escalation, untrusted infrastructure, and
prompt injection
. It never sees tool results, so injected instructions cannot influence its decisions. Auto mode is a research preview available on Max, Team, Enterprise, and API plans.
Learn more:
Eliminate prompts with auto mode
​
B
​
Bare mode
A startup flag,
--bare
, that skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Only flags you pass explicitly take effect. Recommended for CI and scripted calls where you need identical behavior across machines regardless of local configuration.
Learn more:
Start faster with bare mode
​
Bundled skills
Prompt-based playbooks included with Claude Code, such as
/batch
,
/simplify
,
/debug
, and
/loop
. Unlike built-in commands, which execute fixed logic, bundled skills give Claude a detailed prompt and let it orchestrate the work, so they can spawn agents, read files, and adapt to your codebase.
Learn more:
Bundled skills
​
C
​
Channel
An
MCP server
that pushes events into your running session so Claude can react to things that happen while you’re away from the terminal. Channels can be two-way: Claude reads an inbound event and replies back through the same channel. Telegram, Discord, and iMessage are included in the research preview.
Learn more:
Channels
​
Checkpoint
A restore point created at each prompt you send. Claude Code snapshots files before every edit so a checkpoint can revert them. Press
Esc
twice or run
/rewind
to restore code, conversation, or both to an earlier point, or to summarize part of the conversation from a selected message. Checkpoints are local to the session, separate from git, and don’t track changes made through the Bash tool.
Learn more:
Checkpointing
​
.claude
directory
The directory where Claude Code reads project-scoped configuration: settings, hooks, skills, subagents, rules, and auto memory. A project has
.claude/
at its root; your user-level defaults are at
~/.claude/
.
Learn more:
The
.claude
directory
​
CLAUDE.md
A markdown file of persistent instructions you write for Claude, loaded at the start of every session as a user message after the system prompt. Put project conventions, architecture notes, and “always do X” rules here. CLAUDE.md survives
compaction
and is re-read fresh from disk afterward.
You can place CLAUDE.md at project scope in
./CLAUDE.md
or
./.claude/CLAUDE.md
, at user scope in
~/.claude/CLAUDE.md
, or as
managed policy
for your organization. More specific locations take precedence.
Learn more:
CLAUDE.md files
​
Command
A reusable instruction you invoke by typing
/name
in the prompt. Built-in commands such as
/clear
,
/model
, and
/compact
control the session. You can define your own commands as files in
.claude/commands/
, or install them from a
plugin
.
Skills
are the recommended way to package multi-step commands.
Learn more:
Commands
·
Skills
​
Compaction
Automatic summarization of your conversation when the
context window
approaches its limit. Older tool outputs are cleared first, then the conversation is summarized. Project-root CLAUDE.md and auto memory survive compaction and reload from disk; instructions given only in conversation may be lost. Run
/compact
to trigger manually, optionally with a focus like
/compact focus on the API changes
.
Learn more:
What survives compaction
·
When context fills up
​
Context window
The working memory for a session, holding conversation history, file contents, command outputs, CLAUDE.md, auto memory, loaded skills, and system instructions. As you work, context fills up until
compaction
summarizes it. Run
/context
to see what’s using space. For the underlying model concept, see the
platform glossary
.
Learn more:
Explore the context window
​
D
​
Dispatch
A phone-initiated task router that spawns a Claude Code session in the Desktop app when you send a coding task from the Claude mobile app. Your prompt routes to the right tool automatically. Available on Pro and Max plans.
Learn more:
Sessions from Dispatch
​
E
​
Effort level
A setting that controls how much of the adaptive-reasoning thinking budget Claude uses on each turn. Higher effort means more thinking tokens and deeper reasoning; lower effort is faster and cheaper. Effort is supported on Opus 4.7, Opus 4.6, and Sonnet 4.6.
Learn more:
Adjust effort level
​
Extended thinking
Visible step-by-step reasoning the model performs before responding. You can cap thinking tokens with
MAX_THINKING_TOKENS
or adjust the
effort level
. Thinking appears in gray italic text in the terminal.
Learn more:
Use extended thinking
​
H
​
Hook
A user-defined handler that executes automatically at a specific point in Claude Code’s lifecycle, such as before a tool runs, after a file edit, or at session start. Handlers can be a shell command, HTTP endpoint, MCP tool, LLM prompt, or subagent. Hooks are deterministic: they fire at fixed lifecycle points rather than at the model’s discretion.
A hook configuration has three levels:
Hook event
: the lifecycle point
Matcher
: filters which events fire it
Hook handler
: what runs
Learn more:
Get started with hooks
·
Hooks reference
​
M
​
Managed settings
A settings file enforced org-wide by IT or DevOps, placed at an OS-level path outside
~/.claude
. Users cannot override or exclude managed settings. Use this for security policies, compliance requirements, or standardized tooling across a fleet.
Learn more:
Server-managed settings
​
MCP (Model Context Protocol)
An open standard for connecting AI tools to external data sources and services. MCP servers give Claude new tools for Slack, Jira, databases, browsers, and hundreds of other integrations. You connect servers via
/mcp
or by adding them to
.mcp.json
. For the protocol itself, see the
platform glossary
.
Learn more:
Model Context Protocol
​
MCP Tool Search
A context-saving mechanism that defers MCP tool schemas until needed. Only tool names load at startup; Claude fetches the full schema on demand when it decides to use a specific tool. This keeps idle MCP servers from consuming much context.
Learn more:
Scale with MCP Tool Search
​
N
​
Non-interactive mode
A mode that executes a single prompt and exits without a conversational session, invoked with
-p
or
--print
. Used for CI, scripts, and piping. The
Agent SDK
is the Python and TypeScript equivalent. Formerly called headless mode.
Learn more:
Run Claude Code programmatically
​
O
​
Output style
A configuration that modifies Claude’s system prompt to change response behavior, tone, or format. Output styles turn off the software-engineering-specific parts of the default system prompt, unlike
CLAUDE.md
which is delivered as a user message following the system prompt. Built-in styles include Default, Proactive, Explanatory, and Learning.
Learn more:
Output styles
​
P
​
Permission mode
The baseline approval behavior for the session. Cycle with
Shift+Tab
in the CLI or use the mode selector in VS Code, Desktop, and claude.ai. Available modes are
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
, and
bypassPermissions
.
Learn more:
Choose a permission mode
​
Permission rule
A settings entry that allows, asks about, or denies a tool invocation based on the tool name and argument pattern. Rules are evaluated deny→ask→allow, first match wins. Permission rules are fine-grained controls layered on top of the broader
permission mode
.
Learn more:
Configure permissions
​
Plan mode
A
permission mode
where Claude researches and proposes changes without editing your source files. It can read, search, and run exploration commands, then presents a plan for approval before touching anything. Enter plan mode with
/plan
or by pressing
Shift+Tab
.
Learn more:
Analyze before you edit with plan mode
​
Plugin
A bundle of skills, hooks, subagents, and MCP servers packaged as a single installable unit. Plugin skills are namespaced as
plugin-name:skill-name
so multiple plugins coexist. Distribute plugins across teams via a
marketplace
.
Learn more:
Plugins
​
Project trust
A one-time dialog accepting a directory before Claude Code loads its configuration. Trust gates auto-installation of marketplace plugins and execution of project-defined hooks. Trusting a directory means its
.claude/settings.json
,
.mcp.json
, and other config files take effect.
Learn more:
The
.claude
directory
​
Prompt injection
Hostile instructions embedded in a file, web page, or tool result that attempt to redirect Claude toward actions you never asked for. Claude Code’s defenses include the permission system, command blocklists, and trust verification.
Auto mode
adds a server-side probe that scans tool results for suspicious content and a classifier that never sees tool results, so injected text cannot influence its approval decisions.
Learn more:
Protect against prompt injection
​
R
​
Remote Control
A way to continue a local Claude Code session from your phone or browser via claude.ai. Your code stays on your machine; only the UI is remote. Different from Claude Code on the web, which runs in a cloud sandbox.
Learn more:
Remote Control
​
Rules
Modular instruction files in
.claude/rules/
that load alongside CLAUDE.md. A rule can be path-scoped with YAML
paths:
frontmatter so it only loads when Claude reads a matching file, keeping context lean until it’s relevant.
Learn more:
Organize rules with
.claude/rules/
​
S
​
Sandboxing
OS-level filesystem and network isolation for the Bash tool. Commands run inside a boundary you define upfront, so Claude can work freely within it without per-command approval prompts. Sandboxing is a separate layer from
permission rules
.
Learn more:
Sandboxing
​
Session
A conversation tied to your current directory, with its own independent
context window
. Sessions can be resumed with
claude -c
, forked with
--fork-session
to preserve history under a new session ID, or run in parallel across terminals. Running
/clear
starts a new session; the previous one stays stored and is available via
/resume
. Each session’s transcript is stored under
~/.claude/projects/
.
Learn more:
Work with sessions
​
Settings layers
The hierarchy Claude Code reads configuration from, in precedence order from highest to lowest:
managed policy
, command-line arguments, local settings at
.claude/settings.local.json
, project settings at
.claude/settings.json
, then user settings at
~/.claude/settings.json
. Arrays merge across layers; scalars at a higher layer override lower ones.
Learn more:
Settings files
​
Skill
A
SKILL.md
file containing instructions, knowledge, or a workflow that Claude adds to its toolkit. Claude loads a skill automatically when relevant, or you invoke it directly with
/skill-name
. Skills follow the Agent Skills open standard; Claude Code extends it with invocation control and subagent execution.
Skills are the recommended successor to custom commands. A file at
.claude/commands/deploy.md
and one at
.claude/skills/deploy/SKILL.md
both create
/deploy
and work the same way; existing command files continue to work.
Learn more:
Extend Claude with skills
​
Subagent
A specialized AI assistant that runs in its own context window with a custom system prompt, specific tool access, and independent permissions. It works on a delegated task and returns a summary to the main conversation. Use subagents to keep large explorations out of your primary context or to run parallel research. Different from
agent teams
, where each agent is a full independent session you can talk to directly.
Built-in subagents include Explore, Plan, and general-purpose.
Learn more:
Create custom subagents
​
Surface
Any place you access Claude Code: the CLI, VS Code, JetBrains, Desktop, or claude.ai. All surfaces share the same engine, so your CLAUDE.md, settings, and skills work the same way across them. Slack and the Chrome extension are integrations that connect to a surface rather than surfaces themselves.
Learn more:
Platforms and integrations
​
T
​
Teleport
A command,
/teleport
, that pulls a cloud Claude Code session into your local terminal. Claude fetches the branch, loads the conversation history, and resumes from the web session’s last state. The reverse direction is
--remote
, which sends a local task to run on the web.
Learn more:
From web to terminal
​
Tool
An action Claude can take: read a file, edit code, run a shell command, search the web, spawn a subagent. Tools are what make Claude Code agentic. Without them, Claude can only respond with text. Each tool use returns a result that informs Claude’s next decision in the
agentic loop
.
Learn more:
Tools available to Claude
​
Turn
One complete response from Claude within a
session
. A turn begins when you send a message and ends when Claude finishes responding, with any number of
tool
calls in between.
Stop hooks
fire at the end of each turn. A session consists of many turns, and the
agentic loop
describes what happens inside one.
Learn more:
How Claude Code works
​
W
​
Worktree isolation
An isolation mode that runs Claude in a separate git worktree under
.claude/worktrees/
, enabled with the
-w
flag or
isolation: worktree
in subagent config. Changes stay on a separate branch in a separate directory, so parallel agents don’t overwrite each other’s files.
Learn more:
Run parallel sessions with git worktrees
​
Deprecated and renamed terms
These terms appear in older docs, blog posts, and community content. Use the current name when searching this site.
Old term
Now called
Notes
Headless mode
Non-interactive mode
Same
-p
flag, same behavior
Custom commands
Skills
.claude/commands/
files still work
Slash commands
Commands
”Slash” dropped from product copy
Was this page helpful?
Yes
No
Channels reference
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/glossary" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Modifying system prompts</title>
  <link>https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts</guid>
  <pubDate>Tue, 09 Apr 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Modifying system prompts
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SD...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Modifying system prompts
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
System prompts define Claude’s behavior, capabilities, and response style. Start from the
claude_code
preset for CLI or IDE-like coding tools where a human watches and steers the work. Write your own prompt for agents with a different surface, identity, or permission model.
This page covers:
How system prompts work
, with a decision table for choosing between the preset, the preset with
append
, and a custom prompt
Customize agent behavior
with CLAUDE.md files, output styles,
append
, or a custom string
Compare the four approaches
by persistence, scope, and what they preserve
Combine approaches
to layer customization methods together
​
How system prompts work
A system prompt is the initial instruction set that shapes how Claude behaves throughout a conversation. The Agent SDK has three starting points for it:
Minimal default
: when you don’t set
systemPrompt
in TypeScript or
system_prompt
in Python, the SDK uses a minimal prompt that covers tool calling but omits Claude Code’s coding guidelines, response style, and project context. This differs from
claude -p
, which uses the full Claude Code prompt by default. If you’re migrating from the CLI and want matching behavior, set the
claude_code
preset.
claude_code
preset
: the full system prompt that the Claude Code CLI uses, with tool usage instructions, code style and formatting guidelines, response tone and verbosity rules, security and safety instructions, and context about the working directory and environment. Set
systemPrompt: { type: "preset", preset: "claude_code" }
in TypeScript or
system_prompt={"type": "preset", "preset": "claude_code"}
in Python, optionally with
append
to add your own instructions on the end.
Custom string
: a prompt you write yourself. The SDK sends only what you provide.
​
Decide on a starting point
The deciding factor is how closely your agent resembles Claude Code: a coding agent operating in a repository, with a human watching streaming output and steering the work. The further your product is from that, the more you’ll want to write your own prompt.
You’re building
Use
What you get
A CLI or IDE-like coding tool where a human watches and steers, and Claude Code’s defaults are what you want
claude_code
preset
The full Claude Code prompt: tool guidance, safety rules, terminal-friendly responses, repo-convention awareness
The same kind of tool, plus product-specific rules like coding standards, output format, or domain context
claude_code
preset with
append
Everything above, with your instructions added after the preset. Nothing is removed, so this is the lowest-risk customization
An agent with a different surface, identity, or permission model, or a non-coding agent
Custom prompt string
Only what you write. You take responsibility for replacing the tool guidance and safety instructions your agent still needs
A thin tool-calling loop with no agent persona, where you supply all behavior in the user prompt
No
systemPrompt
option
The minimal default: tool-calling support and nothing else
“Different from Claude Code” usually means one of the following:
Different surface
: the output isn’t read in a terminal by the person who triggered it. Chat UIs, structured-output consumers, and non-coding automation each need a prompt that matches how their output is rendered and reviewed. Unattended coding automation, like a CI job that fixes lint errors or reviews diffs, still fits the preset because the work itself is what the preset is written for.
Different identity
: the agent shouldn’t present itself as Claude Code. A support bot, a data-analysis assistant, or any domain-specific agent needs its own name, scope, and persona.
Different permission model
: the agent runs autonomously without a human approving each step, or operates on a narrow set of resources. Claude Code’s prompt assumes a human is in the loop with access to a full toolset.
Non-coding tasks
: most of Claude Code’s prompt is coding guidance. For research, content, or operations agents, that guidance competes with the instructions you actually need.
The
comparison table
shows what each customization method preserves.
​
Customize agent behavior
Output styles,
append
, and a custom prompt string each change the system prompt directly. CLAUDE.md takes a different path: the SDK reads it and injects its content into the conversation as project context, not into the system prompt, so it shapes behavior alongside whichever system prompt you choose.
Skills
,
hooks
, and
permissions
also shape behavior outside the system prompt and are covered on their own pages.
​
CLAUDE.md files for project-level instructions
CLAUDE.md files give Claude persistent project context and instructions. The SDK injects their content into the conversation, not into the system prompt, so they work with any system prompt configuration. For what to put in CLAUDE.md, where to place it, and how to write effective instructions, see
How Claude remembers your project
. This section covers what’s specific to the SDK: how CLAUDE.md loads.
The SDK reads CLAUDE.md when the matching setting source is enabled:
'project'
loads
CLAUDE.md
or
.claude/CLAUDE.md
from the working directory, and
'user'
loads
~/.claude/CLAUDE.md
. Default
query()
options enable both sources, so CLAUDE.md loads automatically. If you set
settingSources
in TypeScript or
setting_sources
in Python explicitly, include the sources you need. CLAUDE.md loading is controlled by setting sources, not by the
claude_code
preset.
​
Load CLAUDE.md with the SDK
To load CLAUDE.md, set
settingSources
to include the level your CLAUDE.md lives at. The example below loads a project-level CLAUDE.md alongside the
claude_code
preset, so Claude has both the full coding-agent prompt and your project’s conventions:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Add a new React component for user profiles"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
// Use Claude Code's system prompt
},
settingSources:
[
"project"
]
// Loads CLAUDE.md from project
}
})) {
messages
.
push
(
message
);
}
// Now Claude has access to your project guidelines from CLAUDE.md
CLAUDE.md is persistent across all sessions in a project, shared with your team through git, and discovered automatically without code changes. It is not loaded if you pass an empty
settingSources
array.
​
Output styles for persistent configurations
Output styles are saved configurations that modify Claude’s system prompt. They’re stored as markdown files and can be reused across sessions and projects.
​
Create an output style
An output style is a markdown file with
frontmatter
for metadata, followed by the prompt content. Save it to
~/.claude/output-styles/
for a user-level style available in every project, or
.claude/output-styles/
in your repository for a project-level style you can commit and share with your team.
By default, a custom output style replaces the
claude_code
preset’s software engineering instructions with your own. To keep them and layer your instructions on top, set
keep-coding-instructions: true
in the frontmatter. Keep them when your agent is still doing software engineering work. Leave them out when you’re replacing the role entirely.
The example below defines a code-review persona that keeps the coding instructions, since reviewing code still benefits from Claude Code’s security and code-quality guidance. Save it as
~/.claude/output-styles/code-reviewer.md
to make it available across projects:
~/.claude/output-styles/code-reviewer.md
---
name
:
Code Reviewer
description
:
Thorough code review assistant
keep-coding-instructions
:
true
---
You are an expert code reviewer.
For every code submission:
1.
Check for bugs and security issues
2.
Evaluate performance
3.
Suggest improvements
4.
Rate code quality (1-10)
​
Activate an output style
Once created, activate output styles via:
CLI
: run
/config
and select an output style
Settings
: set
outputStyle
in
.claude/settings.local.json
TypeScript SDK
: set
options.outputStyle
to the style’s name
The Python SDK does not have an option to select an output style programmatically. For code-only deployments where you can’t write to
.claude/settings.local.json
, use
append
or a custom prompt string instead.
Note for SDK users:
Output styles are loaded when you include
settingSources: ['user']
or
settingSources: ['project']
(TypeScript) /
setting_sources=["user"]
or
setting_sources=["project"]
(Python) in your options.
​
Append to the
claude_code
preset
You can use the Claude Code preset with an
append
property to add your custom instructions while preserving all built-in functionality.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Help me write a Python function to calculate fibonacci numbers"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
"Always include detailed docstrings and type hints in Python code."
}
}
})) {
messages
.
push
(
message
);
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
​
Improve prompt caching across users and machines
By default, two sessions that use the same
claude_code
preset and
append
text still cannot share a prompt cache entry if they run from different working directories. This is because the preset embeds per-session context in the system prompt ahead of your
append
text: the working directory, whether it’s a git repository, the platform, the active shell, the OS version, and auto-memory paths. Any difference in that context produces a different system prompt and a cache miss. CLAUDE.md content doesn’t affect the system prompt cache because the SDK injects it into the conversation, not the system prompt.
To make the system prompt identical across sessions, set
excludeDynamicSections: true
in TypeScript or
"exclude_dynamic_sections": True
in Python. The per-session context moves into the first user message, leaving only the static preset and your
append
text in the system prompt so identical configurations share a cache entry across users and machines.
excludeDynamicSections
requires
@anthropic-ai/claude-agent-sdk
v0.2.98 or later, or
claude-agent-sdk
v0.1.58 or later for Python. It applies only to the preset object form and has no effect when
systemPrompt
is a string.
The following example pairs a shared
append
block with
excludeDynamicSections
so a fleet of agents running from different directories can reuse the same cached system prompt:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Triage the open issues in this repo"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
"You operate Acme's internal triage workflow. Label issues by component and severity."
,
excludeDynamicSections:
true
}
}
})) {
// ...
}
Tradeoffs:
the working directory, the git-repo flag, the platform, the active shell, the OS version, and auto-memory paths still reach Claude, but as part of the first user message rather than the system prompt. Instructions in the user message carry marginally less weight than the same text in the system prompt, so Claude may rely on them less strongly when reasoning about the current directory or auto-memory paths. Enable this option when cross-session cache reuse matters more than maximally authoritative environment context.
For the equivalent flag in non-interactive CLI mode, see
--exclude-dynamic-system-prompt-sections
.
​
Custom system prompts
You can provide a custom string as
systemPrompt
to replace the default entirely with your own instructions.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
customPrompt
=
`You are a Python coding specialist.
Follow these guidelines:
- Write clean, well-documented code
- Use type hints for all functions
- Include comprehensive docstrings
- Prefer functional programming patterns when appropriate
- Always explain your code choices`
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Create a data processing pipeline"
,
options:
{
systemPrompt:
customPrompt
}
})) {
messages
.
push
(
message
);
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
​
Compare the four approaches
The four customization methods differ in where they live, how they’re shared, and what they preserve from the
claude_code
preset.
Feature
CLAUDE.md
Output Styles
systemPrompt
with append
Custom
systemPrompt
Persistence
Per-project file
Saved as files
Session only
Session only
Reusability
Per-project
Across projects
Code duplication
Code duplication
Management
On filesystem
CLI + files
In code
In code
Default tools
Preserved
Preserved
Preserved
Lost (unless included)
Built-in safety
Maintained
Maintained
Maintained
Must be added
Environment context
Automatic
Automatic
Automatic
Must be provided
Customization level
Additions only
Replace or extend default
Additions only
Complete control
Version control
With project
Yes
With code
With code
Scope
Project-specific
User or project
Code session
Code session
“With append” means using
systemPrompt: { type: "preset", preset: "claude_code", append: "..." }
in TypeScript or
system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}
in Python. CLAUDE.md doesn’t change the system prompt itself: the SDK injects its content into the conversation as project context.
​
Use cases and best practices
​
When to use CLAUDE.md
Use CLAUDE.md for instructions that should apply to every session in a project, regardless of which system prompt the session uses: coding standards, common commands, architecture context, and team conventions. CLAUDE.md is committed to your repository, so it stays in sync with the code it describes. See
When to add to CLAUDE.md
for full guidance.
CLAUDE.md files load when the
project
setting source is enabled, which it is for default
query()
options. If you set
settingSources
in TypeScript or
setting_sources
in Python explicitly, include
'project'
to keep loading project-level CLAUDE.md.
​
When to use output styles
Output styles are for personas you want to reuse across the CLI and SDK without changing application code. Because they live as files in
.claude/output-styles
, the same persona is available from
/config
in the CLI and from any SDK session that loads the matching setting source.
Best for:
Persistent behavior changes across sessions
Team-shared configurations
Specialized assistants like a code reviewer, data scientist, or DevOps assistant
Complex prompt modifications that need versioning
Examples:
Creating a dedicated SQL optimization assistant
Building a security-focused code reviewer
Developing a teaching assistant with specific pedagogy
​
When to use
systemPrompt
with append
Use
append
when the
claude_code
preset already fits your product and you only need to layer in extra instructions. You keep the preset’s tool guidance, safety rules, and coding conventions without reimplementing them.
Best for:
Adding specific coding standards or preferences
Customizing output formatting
Adding domain-specific knowledge
Modifying response verbosity
Enhancing Claude Code’s default behavior without losing tool instructions
​
When to use custom
systemPrompt
Use a custom prompt when your agent’s surface, identity, or permission model differs from Claude Code’s, as described in
Decide on a starting point
. You define the full instruction set, including any tool guidance and safety rules your agent needs.
Best for:
Complete control over Claude’s behavior
Specialized single-session tasks
Testing new prompt strategies
Situations where default tools aren’t needed
Building specialized agents with unique behavior
​
Combine approaches
These methods compose. A persistent output style or CLAUDE.md sets the long-lived behavior, and
append
layers session-specific instructions on top without touching the saved configuration.
​
Combine an output style with session-specific additions
The example below assumes a Code Reviewer output style is already active. The
append
block layers session-specific focus areas on top of the persona, so a single review session can prioritize OAuth and token storage without changing the saved output style:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Assuming "Code Reviewer" output style is active (via /config or settings)
// Add session-specific focus areas
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Review this authentication module"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
`
For this review, prioritize:
- OAuth 2.0 compliance
- Token storage security
- Session management
`
}
}
})) {
messages
.
push
(
message
);
}
​
See also
Output styles
: create, manage, and share output styles for the CLI, including the file format and storage locations
How Claude remembers your project
: what to put in CLAUDE.md, where to place it, and how to write effective project instructions
TypeScript SDK reference
: the full
Options
type, including
systemPrompt
,
settingSources
, and
outputStyle
Python SDK reference
: the full
ClaudeAgentOptions
type, including
system_prompt
and
setting_sources
Settings
: the
settings.json
reference, including where output styles and other configuration are stored
Was this page helpful?
Yes
No
Subagents in the SDK
Slash Commands in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Modifying system prompts
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SD...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Modifying system prompts
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
System prompts define Claude’s behavior, capabilities, and response style. Start from the
claude_code
preset for CLI or IDE-like coding tools where a human watches and steers the work. Write your own prompt for agents with a different surface, identity, or permission model.
This page covers:
How system prompts work
, with a decision table for choosing between the preset, the preset with
append
, and a custom prompt
Customize agent behavior
with CLAUDE.md files, output styles,
append
, or a custom string
Compare the four approaches
by persistence, scope, and what they preserve
Combine approaches
to layer customization methods together
​
How system prompts work
A system prompt is the initial instruction set that shapes how Claude behaves throughout a conversation. The Agent SDK has three starting points for it:
Minimal default
: when you don’t set
systemPrompt
in TypeScript or
system_prompt
in Python, the SDK uses a minimal prompt that covers tool calling but omits Claude Code’s coding guidelines, response style, and project context. This differs from
claude -p
, which uses the full Claude Code prompt by default. If you’re migrating from the CLI and want matching behavior, set the
claude_code
preset.
claude_code
preset
: the full system prompt that the Claude Code CLI uses, with tool usage instructions, code style and formatting guidelines, response tone and verbosity rules, security and safety instructions, and context about the working directory and environment. Set
systemPrompt: { type: "preset", preset: "claude_code" }
in TypeScript or
system_prompt={"type": "preset", "preset": "claude_code"}
in Python, optionally with
append
to add your own instructions on the end.
Custom string
: a prompt you write yourself. The SDK sends only what you provide.
​
Decide on a starting point
The deciding factor is how closely your agent resembles Claude Code: a coding agent operating in a repository, with a human watching streaming output and steering the work. The further your product is from that, the more you’ll want to write your own prompt.
You’re building
Use
What you get
A CLI or IDE-like coding tool where a human watches and steers, and Claude Code’s defaults are what you want
claude_code
preset
The full Claude Code prompt: tool guidance, safety rules, terminal-friendly responses, repo-convention awareness
The same kind of tool, plus product-specific rules like coding standards, output format, or domain context
claude_code
preset with
append
Everything above, with your instructions added after the preset. Nothing is removed, so this is the lowest-risk customization
An agent with a different surface, identity, or permission model, or a non-coding agent
Custom prompt string
Only what you write. You take responsibility for replacing the tool guidance and safety instructions your agent still needs
A thin tool-calling loop with no agent persona, where you supply all behavior in the user prompt
No
systemPrompt
option
The minimal default: tool-calling support and nothing else
“Different from Claude Code” usually means one of the following:
Different surface
: the output isn’t read in a terminal by the person who triggered it. Chat UIs, structured-output consumers, and non-coding automation each need a prompt that matches how their output is rendered and reviewed. Unattended coding automation, like a CI job that fixes lint errors or reviews diffs, still fits the preset because the work itself is what the preset is written for.
Different identity
: the agent shouldn’t present itself as Claude Code. A support bot, a data-analysis assistant, or any domain-specific agent needs its own name, scope, and persona.
Different permission model
: the agent runs autonomously without a human approving each step, or operates on a narrow set of resources. Claude Code’s prompt assumes a human is in the loop with access to a full toolset.
Non-coding tasks
: most of Claude Code’s prompt is coding guidance. For research, content, or operations agents, that guidance competes with the instructions you actually need.
The
comparison table
shows what each customization method preserves.
​
Customize agent behavior
Output styles,
append
, and a custom prompt string each change the system prompt directly. CLAUDE.md takes a different path: the SDK reads it and injects its content into the conversation as project context, not into the system prompt, so it shapes behavior alongside whichever system prompt you choose.
Skills
,
hooks
, and
permissions
also shape behavior outside the system prompt and are covered on their own pages.
​
CLAUDE.md files for project-level instructions
CLAUDE.md files give Claude persistent project context and instructions. The SDK injects their content into the conversation, not into the system prompt, so they work with any system prompt configuration. For what to put in CLAUDE.md, where to place it, and how to write effective instructions, see
How Claude remembers your project
. This section covers what’s specific to the SDK: how CLAUDE.md loads.
The SDK reads CLAUDE.md when the matching setting source is enabled:
'project'
loads
CLAUDE.md
or
.claude/CLAUDE.md
from the working directory, and
'user'
loads
~/.claude/CLAUDE.md
. Default
query()
options enable both sources, so CLAUDE.md loads automatically. If you set
settingSources
in TypeScript or
setting_sources
in Python explicitly, include the sources you need. CLAUDE.md loading is controlled by setting sources, not by the
claude_code
preset.
​
Load CLAUDE.md with the SDK
To load CLAUDE.md, set
settingSources
to include the level your CLAUDE.md lives at. The example below loads a project-level CLAUDE.md alongside the
claude_code
preset, so Claude has both the full coding-agent prompt and your project’s conventions:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Add a new React component for user profiles"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
// Use Claude Code's system prompt
},
settingSources:
[
"project"
]
// Loads CLAUDE.md from project
}
})) {
messages
.
push
(
message
);
}
// Now Claude has access to your project guidelines from CLAUDE.md
CLAUDE.md is persistent across all sessions in a project, shared with your team through git, and discovered automatically without code changes. It is not loaded if you pass an empty
settingSources
array.
​
Output styles for persistent configurations
Output styles are saved configurations that modify Claude’s system prompt. They’re stored as markdown files and can be reused across sessions and projects.
​
Create an output style
An output style is a markdown file with
frontmatter
for metadata, followed by the prompt content. Save it to
~/.claude/output-styles/
for a user-level style available in every project, or
.claude/output-styles/
in your repository for a project-level style you can commit and share with your team.
By default, a custom output style replaces the
claude_code
preset’s software engineering instructions with your own. To keep them and layer your instructions on top, set
keep-coding-instructions: true
in the frontmatter. Keep them when your agent is still doing software engineering work. Leave them out when you’re replacing the role entirely.
The example below defines a code-review persona that keeps the coding instructions, since reviewing code still benefits from Claude Code’s security and code-quality guidance. Save it as
~/.claude/output-styles/code-reviewer.md
to make it available across projects:
~/.claude/output-styles/code-reviewer.md
---
name
:
Code Reviewer
description
:
Thorough code review assistant
keep-coding-instructions
:
true
---
You are an expert code reviewer.
For every code submission:
1.
Check for bugs and security issues
2.
Evaluate performance
3.
Suggest improvements
4.
Rate code quality (1-10)
​
Activate an output style
Once created, activate output styles via:
CLI
: run
/config
and select an output style
Settings
: set
outputStyle
in
.claude/settings.local.json
TypeScript SDK
: set
options.outputStyle
to the style’s name
The Python SDK does not have an option to select an output style programmatically. For code-only deployments where you can’t write to
.claude/settings.local.json
, use
append
or a custom prompt string instead.
Note for SDK users:
Output styles are loaded when you include
settingSources: ['user']
or
settingSources: ['project']
(TypeScript) /
setting_sources=["user"]
or
setting_sources=["project"]
(Python) in your options.
​
Append to the
claude_code
preset
You can use the Claude Code preset with an
append
property to add your custom instructions while preserving all built-in functionality.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Help me write a Python function to calculate fibonacci numbers"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
"Always include detailed docstrings and type hints in Python code."
}
}
})) {
messages
.
push
(
message
);
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
​
Improve prompt caching across users and machines
By default, two sessions that use the same
claude_code
preset and
append
text still cannot share a prompt cache entry if they run from different working directories. This is because the preset embeds per-session context in the system prompt ahead of your
append
text: the working directory, whether it’s a git repository, the platform, the active shell, the OS version, and auto-memory paths. Any difference in that context produces a different system prompt and a cache miss. CLAUDE.md content doesn’t affect the system prompt cache because the SDK injects it into the conversation, not the system prompt.
To make the system prompt identical across sessions, set
excludeDynamicSections: true
in TypeScript or
"exclude_dynamic_sections": True
in Python. The per-session context moves into the first user message, leaving only the static preset and your
append
text in the system prompt so identical configurations share a cache entry across users and machines.
excludeDynamicSections
requires
@anthropic-ai/claude-agent-sdk
v0.2.98 or later, or
claude-agent-sdk
v0.1.58 or later for Python. It applies only to the preset object form and has no effect when
systemPrompt
is a string.
The following example pairs a shared
append
block with
excludeDynamicSections
so a fleet of agents running from different directories can reuse the same cached system prompt:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Triage the open issues in this repo"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
"You operate Acme's internal triage workflow. Label issues by component and severity."
,
excludeDynamicSections:
true
}
}
})) {
// ...
}
Tradeoffs:
the working directory, the git-repo flag, the platform, the active shell, the OS version, and auto-memory paths still reach Claude, but as part of the first user message rather than the system prompt. Instructions in the user message carry marginally less weight than the same text in the system prompt, so Claude may rely on them less strongly when reasoning about the current directory or auto-memory paths. Enable this option when cross-session cache reuse matters more than maximally authoritative environment context.
For the equivalent flag in non-interactive CLI mode, see
--exclude-dynamic-system-prompt-sections
.
​
Custom system prompts
You can provide a custom string as
systemPrompt
to replace the default entirely with your own instructions.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
customPrompt
=
`You are a Python coding specialist.
Follow these guidelines:
- Write clean, well-documented code
- Use type hints for all functions
- Include comprehensive docstrings
- Prefer functional programming patterns when appropriate
- Always explain your code choices`
;
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Create a data processing pipeline"
,
options:
{
systemPrompt:
customPrompt
}
})) {
messages
.
push
(
message
);
if
(
message
.
type
===
"assistant"
) {
console
.
log
(
message
.
message
.
content
);
}
}
​
Compare the four approaches
The four customization methods differ in where they live, how they’re shared, and what they preserve from the
claude_code
preset.
Feature
CLAUDE.md
Output Styles
systemPrompt
with append
Custom
systemPrompt
Persistence
Per-project file
Saved as files
Session only
Session only
Reusability
Per-project
Across projects
Code duplication
Code duplication
Management
On filesystem
CLI + files
In code
In code
Default tools
Preserved
Preserved
Preserved
Lost (unless included)
Built-in safety
Maintained
Maintained
Maintained
Must be added
Environment context
Automatic
Automatic
Automatic
Must be provided
Customization level
Additions only
Replace or extend default
Additions only
Complete control
Version control
With project
Yes
With code
With code
Scope
Project-specific
User or project
Code session
Code session
“With append” means using
systemPrompt: { type: "preset", preset: "claude_code", append: "..." }
in TypeScript or
system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}
in Python. CLAUDE.md doesn’t change the system prompt itself: the SDK injects its content into the conversation as project context.
​
Use cases and best practices
​
When to use CLAUDE.md
Use CLAUDE.md for instructions that should apply to every session in a project, regardless of which system prompt the session uses: coding standards, common commands, architecture context, and team conventions. CLAUDE.md is committed to your repository, so it stays in sync with the code it describes. See
When to add to CLAUDE.md
for full guidance.
CLAUDE.md files load when the
project
setting source is enabled, which it is for default
query()
options. If you set
settingSources
in TypeScript or
setting_sources
in Python explicitly, include
'project'
to keep loading project-level CLAUDE.md.
​
When to use output styles
Output styles are for personas you want to reuse across the CLI and SDK without changing application code. Because they live as files in
.claude/output-styles
, the same persona is available from
/config
in the CLI and from any SDK session that loads the matching setting source.
Best for:
Persistent behavior changes across sessions
Team-shared configurations
Specialized assistants like a code reviewer, data scientist, or DevOps assistant
Complex prompt modifications that need versioning
Examples:
Creating a dedicated SQL optimization assistant
Building a security-focused code reviewer
Developing a teaching assistant with specific pedagogy
​
When to use
systemPrompt
with append
Use
append
when the
claude_code
preset already fits your product and you only need to layer in extra instructions. You keep the preset’s tool guidance, safety rules, and coding conventions without reimplementing them.
Best for:
Adding specific coding standards or preferences
Customizing output formatting
Adding domain-specific knowledge
Modifying response verbosity
Enhancing Claude Code’s default behavior without losing tool instructions
​
When to use custom
systemPrompt
Use a custom prompt when your agent’s surface, identity, or permission model differs from Claude Code’s, as described in
Decide on a starting point
. You define the full instruction set, including any tool guidance and safety rules your agent needs.
Best for:
Complete control over Claude’s behavior
Specialized single-session tasks
Testing new prompt strategies
Situations where default tools aren’t needed
Building specialized agents with unique behavior
​
Combine approaches
These methods compose. A persistent output style or CLAUDE.md sets the long-lived behavior, and
append
layers session-specific instructions on top without touching the saved configuration.
​
Combine an output style with session-specific additions
The example below assumes a Code Reviewer output style is already active. The
append
block layers session-specific focus areas on top of the persona, so a single review session can prioritize OAuth and token storage without changing the saved output style:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Assuming "Code Reviewer" output style is active (via /config or settings)
// Add session-specific focus areas
const
messages
=
[];
for
await
(
const
message
of
query
({
prompt:
"Review this authentication module"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
,
append:
`
For this review, prioritize:
- OAuth 2.0 compliance
- Token storage security
- Session management
`
}
}
})) {
messages
.
push
(
message
);
}
​
See also
Output styles
: create, manage, and share output styles for the CLI, including the file format and storage locations
How Claude remembers your project
: what to put in CLAUDE.md, where to place it, and how to write effective project instructions
TypeScript SDK reference
: the full
Options
type, including
systemPrompt
,
settingSources
, and
outputStyle
Python SDK reference
: the full
ClaudeAgentOptions
type, including
system_prompt
and
setting_sources
Settings
: the
settings.json
reference, including where output styles and other configuration are stored
Was this page helpful?
Yes
No
Subagents in the SDK
Slash Commands in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Discover and install prebuilt plugins through marketplaces</title>
  <link>https://code.claude.com/docs/en/discover-plugins</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/discover-plugins</guid>
  <pubDate>Mon, 08 Apr 2024 00:00:00 +0000</pubDate>
  <category>Plugins</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Discover and install prebuilt plugins through marketplaces
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Progra...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Discover and install prebuilt plugins through marketplaces
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins extend Claude Code with skills, agents, hooks, and MCP servers. Plugin marketplaces are catalogs that help you discover and install these extensions without building them yourself.
Looking to create and distribute your own marketplace? See
Create and distribute a plugin marketplace
.
​
How marketplaces work
A marketplace is a catalog of plugins that someone else has created and shared. Using a marketplace is a two-step process:
1
Add the marketplace
This registers the catalog with Claude Code so you can browse what’s available. No plugins are installed yet.
2
Install individual plugins
Browse the catalog and install the plugins you want.
Think of it like adding an app store: adding the store gives you access to browse its collection, but you still choose which apps to download individually.
​
Official Anthropic marketplace
The official Anthropic marketplace (
claude-plugins-official
) is automatically available when you start Claude Code. Run
/plugin
and go to the
Discover
tab to browse what’s available, or view the catalog at
claude.com/plugins
.
To install a plugin from the official marketplace, use
/plugin install <name>@claude-plugins-official
. For example, to install the GitHub integration:
/plugin
install
github@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
The official marketplace is maintained by Anthropic. To submit a plugin to the official marketplace, use one of the in-app submission forms:
Claude.ai
:
claude.ai/settings/plugins/submit
Console
:
platform.claude.com/plugins/submit
To distribute plugins independently,
create your own marketplace
and share it with users.
The official marketplace includes several categories of plugins:
​
Code intelligence
Code intelligence plugins enable Claude Code’s built-in LSP tool, giving Claude the ability to jump to definitions, find references, and see type errors immediately after edits. These plugins configure
Language Server Protocol
connections, the same technology that powers VS Code’s code intelligence.
These plugins require the language server binary to be installed on your system. If you already have a language server installed, Claude may prompt you to install the corresponding plugin when you open a project.
Language
Plugin
Binary required
C/C++
clangd-lsp
clangd
C#
csharp-lsp
csharp-ls
Go
gopls-lsp
gopls
Java
jdtls-lsp
jdtls
Kotlin
kotlin-lsp
kotlin-language-server
Lua
lua-lsp
lua-language-server
PHP
php-lsp
intelephense
Python
pyright-lsp
pyright-langserver
Rust
rust-analyzer-lsp
rust-analyzer
Swift
swift-lsp
sourcekit-lsp
TypeScript
typescript-lsp
typescript-language-server
You can also
create your own LSP plugin
for other languages.
If you see
Executable not found in $PATH
in the
/plugin
Errors tab after installing a plugin, install the required binary from the table above.
​
What Claude gains from code intelligence plugins
Once a code intelligence plugin is installed and its language server binary is available, Claude gains two capabilities:
Automatic diagnostics
: after every file edit Claude makes, the language server analyzes the changes and reports errors and warnings back automatically. Claude sees type errors, missing imports, and syntax issues without needing to run a compiler or linter. If Claude introduces an error, it notices and fixes the issue in the same turn. This requires no configuration beyond installing the plugin. You can see diagnostics inline by pressing
Ctrl+O
when the “diagnostics found” indicator appears.
Code navigation
: Claude can use the language server to jump to definitions, find references, get type info on hover, list symbols, find implementations, and trace call hierarchies. These operations give Claude more precise navigation than grep-based search, though availability may vary by language and environment.
If you run into issues, see
Code intelligence troubleshooting
.
​
External integrations
These plugins bundle pre-configured
MCP servers
so you can connect Claude to external services without manual setup:
Source control
:
github
,
gitlab
Project management
:
atlassian
(Jira/Confluence),
asana
,
linear
,
notion
Design
:
figma
Infrastructure
:
vercel
,
firebase
,
supabase
Communication
:
slack
Monitoring
:
sentry
​
Development workflows
Plugins that add skills and agents for common development tasks:
commit-commands
: Git commit workflows including commit, push, and PR creation
pr-review-toolkit
: Specialized agents for reviewing pull requests
agent-sdk-dev
: Tools for building with the Claude Agent SDK
plugin-dev
: Toolkit for creating your own plugins
​
Output styles
Customize how Claude responds:
explanatory-output-style
: Educational insights about implementation choices
learning-output-style
: Interactive learning mode for skill building
​
Try it: add the demo marketplace
Anthropic also maintains a
demo plugins marketplace
(
claude-code-plugins
) with example plugins that show what’s possible with the plugin system. Unlike the official marketplace, you need to add this one manually.
1
Add the marketplace
From within Claude Code, run the
plugin marketplace add
command for the
anthropics/claude-code
marketplace:
/plugin
marketplace
add
anthropics/claude-code
This downloads the marketplace catalog and makes its plugins available to you.
2
Browse available plugins
Run
/plugin
to open the plugin manager. This opens a tabbed interface with four tabs you can cycle through using
Tab
(or
Shift+Tab
to go backward):
Discover
: browse available plugins from all your marketplaces
Installed
: view and manage your installed plugins
Marketplaces
: add, remove, or update your added marketplaces
Errors
: view any plugin loading errors
Go to the
Discover
tab to see plugins from the marketplace you just added.
3
Install a plugin
Select a plugin to view its details, then choose an installation scope:
User scope
: install for yourself across all projects
Project scope
: install for all collaborators on this repository
Local scope
: install for yourself in this repository only
For example, select
commit-commands
(a plugin that adds git workflow skills) and install it to your user scope.
You can also install directly from the command line:
/plugin
install
commit-commands@anthropics-claude-code
See
Configuration scopes
to learn more about scopes.
4
Use your new plugin
After installing, run
/reload-plugins
to activate the plugin. Plugin skills are namespaced by the plugin name, so
commit-commands
provides skills like
/commit-commands:commit
.
Try it out by making a change to a file and running:
/commit-commands:commit
This stages your changes, generates a commit message, and creates the commit.
Each plugin works differently. Check the plugin’s description in the
Discover
tab or its homepage to learn what skills and capabilities it provides.
The rest of this guide covers all the ways you can add marketplaces, install plugins, and manage your configuration.
​
Add marketplaces
Use the
/plugin marketplace add
command to add marketplaces from different sources.
Shortcuts
: You can use
/plugin market
instead of
/plugin marketplace
, and
rm
instead of
remove
.
GitHub repositories
:
owner/repo
format (for example,
anthropics/claude-code
)
Git URLs
: any git repository URL (GitLab, Bitbucket, self-hosted)
Local paths
: directories or direct paths to
marketplace.json
files
Remote URLs
: direct URLs to hosted
marketplace.json
files
​
Add from GitHub
Add a GitHub repository that contains a
.claude-plugin/marketplace.json
file using the
owner/repo
format—where
owner
is the GitHub username or organization and
repo
is the repository name.
For example,
anthropics/claude-code
refers to the
claude-code
repository owned by
anthropics
:
/plugin
marketplace
add
anthropics/claude-code
​
Add from other Git hosts
Add any git repository by providing the full URL. This works with any Git host, including GitLab, Bitbucket, and self-hosted servers. Include the
.git
suffix so Claude Code clones the repository rather than treating the URL as a direct link to a hosted
marketplace.json
file.
Using HTTPS:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git
Using SSH:
/plugin
marketplace
add
git@gitlab.com:company/plugins.git
To add a specific branch or tag, append
#
followed by the ref:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git#v1.0.0
​
Add from local paths
Add a local directory that contains a
.claude-plugin/marketplace.json
file:
/plugin
marketplace
add
./my-marketplace
You can also add a direct path to a
marketplace.json
file:
/plugin
marketplace
add
./path/to/marketplace.json
​
Add from remote URLs
Add a remote
marketplace.json
file via URL:
/plugin
marketplace
add
https://example.com/marketplace.json
URL-based marketplaces have some limitations compared to Git-based marketplaces. If you encounter “path not found” errors when installing plugins, see
Troubleshooting
.
​
Install plugins
Once you’ve added marketplaces, you can install plugins directly (installs to user scope by default):
/plugin
install
plugin-name@marketplace-name
To choose a different
installation scope
, use the interactive UI: run
/plugin
, go to the
Discover
tab, and press
Enter
on a plugin. You’ll see options for:
User scope
(default): install for yourself across all projects
Project scope
: install for all collaborators on this repository (adds to
.claude/settings.json
)
Local scope
: install for yourself in this repository only (not shared with collaborators)
You may also see plugins with
managed
scope—these are installed by administrators via
managed settings
and cannot be modified.
Make sure you trust a plugin before installing it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they work as intended. Check each plugin’s homepage for more information.
​
Manage installed plugins
Run
/plugin
and go to the
Installed
tab to view, enable, disable, or uninstall your plugins. The list is grouped by scope and sorted so you see problems first: plugins with load errors or unresolved dependencies appear at the top, followed by your favorites, with disabled plugins folded behind a collapsed header at the bottom.
From the list you can:
press
f
to favorite or unfavorite the selected plugin
type to filter by plugin name or description
press Enter to open a plugin’s detail view and enable, disable, or uninstall it
When you install a plugin that declares dependencies, the install output lists which dependencies were auto-installed alongside it.
You can also manage plugins with direct commands.
Disable a plugin without uninstalling:
/plugin
disable
plugin-name@marketplace-name
Re-enable a disabled plugin:
/plugin
enable
plugin-name@marketplace-name
Completely remove a plugin:
/plugin
uninstall
plugin-name@marketplace-name
The
--scope
option lets you target a specific scope with CLI commands:
claude
plugin
install
formatter@your-org
--scope
project
claude
plugin
uninstall
formatter@your-org
--scope
project
​
Apply plugin changes without restarting
When you install, enable, or disable plugins during a session, run
/reload-plugins
to pick up all changes without restarting:
/reload-plugins
Claude Code reloads all active plugins and shows counts for plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers.
​
Manage marketplaces
You can manage marketplaces through the interactive
/plugin
interface or with CLI commands.
​
Use the interactive interface
Run
/plugin
and go to the
Marketplaces
tab to:
View all your added marketplaces with their sources and status
Add new marketplaces
Update marketplace listings to fetch the latest plugins
Remove marketplaces you no longer need
​
Use CLI commands
You can also manage marketplaces with direct commands.
List all configured marketplaces:
/plugin
marketplace
list
Refresh plugin listings from a marketplace:
/plugin
marketplace
update
marketplace-name
Remove a marketplace:
/plugin
marketplace
remove
marketplace-name
Removing a marketplace will uninstall any plugins you installed from it.
​
Configure auto-updates
Claude Code can automatically update marketplaces and their installed plugins at startup. When auto-update is enabled for a marketplace, Claude Code refreshes the marketplace data and updates installed plugins to their latest versions. If any plugins were updated, you’ll see a notification prompting you to run
/reload-plugins
.
Toggle auto-update for individual marketplaces through the UI:
Run
/plugin
to open the plugin manager
Select
Marketplaces
Choose a marketplace from the list
Select
Enable auto-update
or
Disable auto-update
Official Anthropic marketplaces have auto-update enabled by default. Third-party and local development marketplaces have auto-update disabled by default.
Administrators can also set
"autoUpdate": true
on each
extraKnownMarketplaces
entry in managed settings to enable auto-update for an organization marketplace without requiring each user to toggle it.
To disable all automatic updates entirely for both Claude Code and all plugins, set the
DISABLE_AUTOUPDATER
environment variable. See
Auto updates
for details.
To keep plugin auto-updates enabled while disabling Claude Code auto-updates, set
FORCE_AUTOUPDATE_PLUGINS=1
along with
DISABLE_AUTOUPDATER
:
export
DISABLE_AUTOUPDATER
=
1
export
FORCE_AUTOUPDATE_PLUGINS
=
1
This is useful when you want to manage Claude Code updates manually but still receive automatic plugin updates.
​
Configure team marketplaces
Team admins can set up automatic marketplace installation for projects by adding marketplace configuration to
.claude/settings.json
. When team members trust the repository folder, Claude Code prompts them to install these marketplaces and plugins.
Add
extraKnownMarketplaces
to your project’s
.claude/settings.json
:
{
"extraKnownMarketplaces"
: {
"my-team-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"your-org/claude-plugins"
}
}
}
}
For full configuration options including
extraKnownMarketplaces
and
enabledPlugins
, see
Plugin settings
.
​
Security
Plugins and marketplaces are highly trusted components that can execute arbitrary code on your machine with your user privileges. Only install plugins and add marketplaces from sources you trust. Organizations can restrict which marketplaces users are allowed to add using
managed marketplace restrictions
.
​
Troubleshooting
​
/plugin command not recognized
If you see “unknown command” or the
/plugin
command doesn’t appear:
Check your version
: Run
claude --version
to see what’s installed.
Update Claude Code
:
Homebrew
:
brew upgrade claude-code
(or
brew upgrade claude-code@latest
if you installed that cask)
npm
:
npm install -g @anthropic-ai/claude-code@latest
Native installer
: Re-run the install command from
Setup
Restart Claude Code
: After updating, restart your terminal and run
claude
again.
​
Common issues
Marketplace not loading
: Verify the URL is accessible and that
.claude-plugin/marketplace.json
exists at the path
Plugin installation failures
: Check that plugin source URLs are accessible and repositories are public (or you have access)
Files not found after installation
: Plugins are copied to a cache, so paths referencing files outside the plugin directory won’t work
Plugin skills not appearing
: Clear the cache with
rm -rf ~/.claude/plugins/cache
, restart Claude Code, and reinstall the plugin.
For detailed troubleshooting with solutions, see
Troubleshooting
in the marketplace guide. For debugging tools, see
Debugging and development tools
.
​
Code intelligence issues
Language server not starting
: verify the binary is installed and available in your
$PATH
. Check the
/plugin
Errors tab for details.
High memory usage
: language servers like
rust-analyzer
and
pyright
can consume significant memory on large projects. If you experience memory issues, disable the plugin with
/plugin disable <plugin-name>
and rely on Claude’s built-in search tools instead.
False positive diagnostics in monorepos
: language servers may report unresolved import errors for internal packages if the workspace isn’t configured correctly. These don’t affect Claude’s ability to edit code.
​
Next steps
Build your own plugins
: See
Plugins
to create skills, agents, and hooks
Create a marketplace
: See
Create a plugin marketplace
to distribute plugins to your team or community
Technical reference
: See
Plugins reference
for complete specifications
Was this page helpful?
Yes
No
Model Context Protocol (MCP)
Create plugins
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/discover-plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Discover and install prebuilt plugins through marketplaces
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Progra...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Discover and install prebuilt plugins through marketplaces
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugins extend Claude Code with skills, agents, hooks, and MCP servers. Plugin marketplaces are catalogs that help you discover and install these extensions without building them yourself.
Looking to create and distribute your own marketplace? See
Create and distribute a plugin marketplace
.
​
How marketplaces work
A marketplace is a catalog of plugins that someone else has created and shared. Using a marketplace is a two-step process:
1
Add the marketplace
This registers the catalog with Claude Code so you can browse what’s available. No plugins are installed yet.
2
Install individual plugins
Browse the catalog and install the plugins you want.
Think of it like adding an app store: adding the store gives you access to browse its collection, but you still choose which apps to download individually.
​
Official Anthropic marketplace
The official Anthropic marketplace (
claude-plugins-official
) is automatically available when you start Claude Code. Run
/plugin
and go to the
Discover
tab to browse what’s available, or view the catalog at
claude.com/plugins
.
To install a plugin from the official marketplace, use
/plugin install <name>@claude-plugins-official
. For example, to install the GitHub integration:
/plugin
install
github@claude-plugins-official
If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run
/plugin marketplace update claude-plugins-official
to refresh it, or
/plugin marketplace add anthropics/claude-plugins-official
if you haven’t added it before. Then retry the install.
The official marketplace is maintained by Anthropic. To submit a plugin to the official marketplace, use one of the in-app submission forms:
Claude.ai
:
claude.ai/settings/plugins/submit
Console
:
platform.claude.com/plugins/submit
To distribute plugins independently,
create your own marketplace
and share it with users.
The official marketplace includes several categories of plugins:
​
Code intelligence
Code intelligence plugins enable Claude Code’s built-in LSP tool, giving Claude the ability to jump to definitions, find references, and see type errors immediately after edits. These plugins configure
Language Server Protocol
connections, the same technology that powers VS Code’s code intelligence.
These plugins require the language server binary to be installed on your system. If you already have a language server installed, Claude may prompt you to install the corresponding plugin when you open a project.
Language
Plugin
Binary required
C/C++
clangd-lsp
clangd
C#
csharp-lsp
csharp-ls
Go
gopls-lsp
gopls
Java
jdtls-lsp
jdtls
Kotlin
kotlin-lsp
kotlin-language-server
Lua
lua-lsp
lua-language-server
PHP
php-lsp
intelephense
Python
pyright-lsp
pyright-langserver
Rust
rust-analyzer-lsp
rust-analyzer
Swift
swift-lsp
sourcekit-lsp
TypeScript
typescript-lsp
typescript-language-server
You can also
create your own LSP plugin
for other languages.
If you see
Executable not found in $PATH
in the
/plugin
Errors tab after installing a plugin, install the required binary from the table above.
​
What Claude gains from code intelligence plugins
Once a code intelligence plugin is installed and its language server binary is available, Claude gains two capabilities:
Automatic diagnostics
: after every file edit Claude makes, the language server analyzes the changes and reports errors and warnings back automatically. Claude sees type errors, missing imports, and syntax issues without needing to run a compiler or linter. If Claude introduces an error, it notices and fixes the issue in the same turn. This requires no configuration beyond installing the plugin. You can see diagnostics inline by pressing
Ctrl+O
when the “diagnostics found” indicator appears.
Code navigation
: Claude can use the language server to jump to definitions, find references, get type info on hover, list symbols, find implementations, and trace call hierarchies. These operations give Claude more precise navigation than grep-based search, though availability may vary by language and environment.
If you run into issues, see
Code intelligence troubleshooting
.
​
External integrations
These plugins bundle pre-configured
MCP servers
so you can connect Claude to external services without manual setup:
Source control
:
github
,
gitlab
Project management
:
atlassian
(Jira/Confluence),
asana
,
linear
,
notion
Design
:
figma
Infrastructure
:
vercel
,
firebase
,
supabase
Communication
:
slack
Monitoring
:
sentry
​
Development workflows
Plugins that add skills and agents for common development tasks:
commit-commands
: Git commit workflows including commit, push, and PR creation
pr-review-toolkit
: Specialized agents for reviewing pull requests
agent-sdk-dev
: Tools for building with the Claude Agent SDK
plugin-dev
: Toolkit for creating your own plugins
​
Output styles
Customize how Claude responds:
explanatory-output-style
: Educational insights about implementation choices
learning-output-style
: Interactive learning mode for skill building
​
Try it: add the demo marketplace
Anthropic also maintains a
demo plugins marketplace
(
claude-code-plugins
) with example plugins that show what’s possible with the plugin system. Unlike the official marketplace, you need to add this one manually.
1
Add the marketplace
From within Claude Code, run the
plugin marketplace add
command for the
anthropics/claude-code
marketplace:
/plugin
marketplace
add
anthropics/claude-code
This downloads the marketplace catalog and makes its plugins available to you.
2
Browse available plugins
Run
/plugin
to open the plugin manager. This opens a tabbed interface with four tabs you can cycle through using
Tab
(or
Shift+Tab
to go backward):
Discover
: browse available plugins from all your marketplaces
Installed
: view and manage your installed plugins
Marketplaces
: add, remove, or update your added marketplaces
Errors
: view any plugin loading errors
Go to the
Discover
tab to see plugins from the marketplace you just added.
3
Install a plugin
Select a plugin to view its details, then choose an installation scope:
User scope
: install for yourself across all projects
Project scope
: install for all collaborators on this repository
Local scope
: install for yourself in this repository only
For example, select
commit-commands
(a plugin that adds git workflow skills) and install it to your user scope.
You can also install directly from the command line:
/plugin
install
commit-commands@anthropics-claude-code
See
Configuration scopes
to learn more about scopes.
4
Use your new plugin
After installing, run
/reload-plugins
to activate the plugin. Plugin skills are namespaced by the plugin name, so
commit-commands
provides skills like
/commit-commands:commit
.
Try it out by making a change to a file and running:
/commit-commands:commit
This stages your changes, generates a commit message, and creates the commit.
Each plugin works differently. Check the plugin’s description in the
Discover
tab or its homepage to learn what skills and capabilities it provides.
The rest of this guide covers all the ways you can add marketplaces, install plugins, and manage your configuration.
​
Add marketplaces
Use the
/plugin marketplace add
command to add marketplaces from different sources.
Shortcuts
: You can use
/plugin market
instead of
/plugin marketplace
, and
rm
instead of
remove
.
GitHub repositories
:
owner/repo
format (for example,
anthropics/claude-code
)
Git URLs
: any git repository URL (GitLab, Bitbucket, self-hosted)
Local paths
: directories or direct paths to
marketplace.json
files
Remote URLs
: direct URLs to hosted
marketplace.json
files
​
Add from GitHub
Add a GitHub repository that contains a
.claude-plugin/marketplace.json
file using the
owner/repo
format—where
owner
is the GitHub username or organization and
repo
is the repository name.
For example,
anthropics/claude-code
refers to the
claude-code
repository owned by
anthropics
:
/plugin
marketplace
add
anthropics/claude-code
​
Add from other Git hosts
Add any git repository by providing the full URL. This works with any Git host, including GitLab, Bitbucket, and self-hosted servers. Include the
.git
suffix so Claude Code clones the repository rather than treating the URL as a direct link to a hosted
marketplace.json
file.
Using HTTPS:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git
Using SSH:
/plugin
marketplace
add
git@gitlab.com:company/plugins.git
To add a specific branch or tag, append
#
followed by the ref:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git#v1.0.0
​
Add from local paths
Add a local directory that contains a
.claude-plugin/marketplace.json
file:
/plugin
marketplace
add
./my-marketplace
You can also add a direct path to a
marketplace.json
file:
/plugin
marketplace
add
./path/to/marketplace.json
​
Add from remote URLs
Add a remote
marketplace.json
file via URL:
/plugin
marketplace
add
https://example.com/marketplace.json
URL-based marketplaces have some limitations compared to Git-based marketplaces. If you encounter “path not found” errors when installing plugins, see
Troubleshooting
.
​
Install plugins
Once you’ve added marketplaces, you can install plugins directly (installs to user scope by default):
/plugin
install
plugin-name@marketplace-name
To choose a different
installation scope
, use the interactive UI: run
/plugin
, go to the
Discover
tab, and press
Enter
on a plugin. You’ll see options for:
User scope
(default): install for yourself across all projects
Project scope
: install for all collaborators on this repository (adds to
.claude/settings.json
)
Local scope
: install for yourself in this repository only (not shared with collaborators)
You may also see plugins with
managed
scope—these are installed by administrators via
managed settings
and cannot be modified.
Make sure you trust a plugin before installing it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they work as intended. Check each plugin’s homepage for more information.
​
Manage installed plugins
Run
/plugin
and go to the
Installed
tab to view, enable, disable, or uninstall your plugins. The list is grouped by scope and sorted so you see problems first: plugins with load errors or unresolved dependencies appear at the top, followed by your favorites, with disabled plugins folded behind a collapsed header at the bottom.
From the list you can:
press
f
to favorite or unfavorite the selected plugin
type to filter by plugin name or description
press Enter to open a plugin’s detail view and enable, disable, or uninstall it
When you install a plugin that declares dependencies, the install output lists which dependencies were auto-installed alongside it.
You can also manage plugins with direct commands.
Disable a plugin without uninstalling:
/plugin
disable
plugin-name@marketplace-name
Re-enable a disabled plugin:
/plugin
enable
plugin-name@marketplace-name
Completely remove a plugin:
/plugin
uninstall
plugin-name@marketplace-name
The
--scope
option lets you target a specific scope with CLI commands:
claude
plugin
install
formatter@your-org
--scope
project
claude
plugin
uninstall
formatter@your-org
--scope
project
​
Apply plugin changes without restarting
When you install, enable, or disable plugins during a session, run
/reload-plugins
to pick up all changes without restarting:
/reload-plugins
Claude Code reloads all active plugins and shows counts for plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers.
​
Manage marketplaces
You can manage marketplaces through the interactive
/plugin
interface or with CLI commands.
​
Use the interactive interface
Run
/plugin
and go to the
Marketplaces
tab to:
View all your added marketplaces with their sources and status
Add new marketplaces
Update marketplace listings to fetch the latest plugins
Remove marketplaces you no longer need
​
Use CLI commands
You can also manage marketplaces with direct commands.
List all configured marketplaces:
/plugin
marketplace
list
Refresh plugin listings from a marketplace:
/plugin
marketplace
update
marketplace-name
Remove a marketplace:
/plugin
marketplace
remove
marketplace-name
Removing a marketplace will uninstall any plugins you installed from it.
​
Configure auto-updates
Claude Code can automatically update marketplaces and their installed plugins at startup. When auto-update is enabled for a marketplace, Claude Code refreshes the marketplace data and updates installed plugins to their latest versions. If any plugins were updated, you’ll see a notification prompting you to run
/reload-plugins
.
Toggle auto-update for individual marketplaces through the UI:
Run
/plugin
to open the plugin manager
Select
Marketplaces
Choose a marketplace from the list
Select
Enable auto-update
or
Disable auto-update
Official Anthropic marketplaces have auto-update enabled by default. Third-party and local development marketplaces have auto-update disabled by default.
Administrators can also set
"autoUpdate": true
on each
extraKnownMarketplaces
entry in managed settings to enable auto-update for an organization marketplace without requiring each user to toggle it.
To disable all automatic updates entirely for both Claude Code and all plugins, set the
DISABLE_AUTOUPDATER
environment variable. See
Auto updates
for details.
To keep plugin auto-updates enabled while disabling Claude Code auto-updates, set
FORCE_AUTOUPDATE_PLUGINS=1
along with
DISABLE_AUTOUPDATER
:
export
DISABLE_AUTOUPDATER
=
1
export
FORCE_AUTOUPDATE_PLUGINS
=
1
This is useful when you want to manage Claude Code updates manually but still receive automatic plugin updates.
​
Configure team marketplaces
Team admins can set up automatic marketplace installation for projects by adding marketplace configuration to
.claude/settings.json
. When team members trust the repository folder, Claude Code prompts them to install these marketplaces and plugins.
Add
extraKnownMarketplaces
to your project’s
.claude/settings.json
:
{
"extraKnownMarketplaces"
: {
"my-team-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"your-org/claude-plugins"
}
}
}
}
For full configuration options including
extraKnownMarketplaces
and
enabledPlugins
, see
Plugin settings
.
​
Security
Plugins and marketplaces are highly trusted components that can execute arbitrary code on your machine with your user privileges. Only install plugins and add marketplaces from sources you trust. Organizations can restrict which marketplaces users are allowed to add using
managed marketplace restrictions
.
​
Troubleshooting
​
/plugin command not recognized
If you see “unknown command” or the
/plugin
command doesn’t appear:
Check your version
: Run
claude --version
to see what’s installed.
Update Claude Code
:
Homebrew
:
brew upgrade claude-code
(or
brew upgrade claude-code@latest
if you installed that cask)
npm
:
npm install -g @anthropic-ai/claude-code@latest
Native installer
: Re-run the install command from
Setup
Restart Claude Code
: After updating, restart your terminal and run
claude
again.
​
Common issues
Marketplace not loading
: Verify the URL is accessible and that
.claude-plugin/marketplace.json
exists at the path
Plugin installation failures
: Check that plugin source URLs are accessible and repositories are public (or you have access)
Files not found after installation
: Plugins are copied to a cache, so paths referencing files outside the plugin directory won’t work
Plugin skills not appearing
: Clear the cache with
rm -rf ~/.claude/plugins/cache
, restart Claude Code, and reinstall the plugin.
For detailed troubleshooting with solutions, see
Troubleshooting
in the marketplace guide. For debugging tools, see
Debugging and development tools
.
​
Code intelligence issues
Language server not starting
: verify the binary is installed and available in your
$PATH
. Check the
/plugin
Errors tab for details.
High memory usage
: language servers like
rust-analyzer
and
pyright
can consume significant memory on large projects. If you experience memory issues, disable the plugin with
/plugin disable <plugin-name>
and rely on Claude’s built-in search tools instead.
False positive diagnostics in monorepos
: language servers may report unresolved import errors for internal packages if the workspace isn’t configured correctly. These don’t affect Claude’s ability to edit code.
​
Next steps
Build your own plugins
: See
Plugins
to create skills, agents, and hooks
Create a marketplace
: See
Create a plugin marketplace
to distribute plugins to your team or community
Technical reference
: See
Plugins reference
for complete specifications
Was this page helpful?
Yes
No
Model Context Protocol (MCP)
Create plugins
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/discover-plugins" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Connect Claude Code to tools via MCP</title>
  <link>https://code.claude.com/docs/en/mcp</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/mcp</guid>
  <pubDate>Fri, 05 Apr 2024 00:00:00 +0000</pubDate>
  <category>MCP</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Connect Claude Code to tools via MCP
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch se...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Connect Claude Code to tools via MCP
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code can connect to hundreds of external tools and data sources through the
Model Context Protocol (MCP)
, an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs.
Connect a server when you find yourself copying data into chat from another tool, like an issue tracker or a monitoring dashboard. Once connected, Claude can read and act on that system directly instead of working from what you paste.
​
What you can do with MCP
With MCP servers connected, you can ask Claude Code to:
Implement features from issue trackers
: “Add the feature described in JIRA issue ENG-4521 and create a PR on GitHub.”
Analyze monitoring data
: “Check Sentry and Statsig to check the usage of the feature described in ENG-4521.”
Query databases
: “Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database.”
Integrate designs
: “Update our standard email template based on the new Figma designs that were posted in Slack”
Automate workflows
: “Create Gmail drafts inviting these 10 users to a feedback session about the new feature.”
React to external events
: An MCP server can also act as a
channel
that pushes messages into your session, so Claude reacts to Telegram messages, Discord chats, or webhook events while you’re away.
​
Find and build MCP servers
Browse reviewed connectors in the
Anthropic Directory
. Directory connectors use the same MCP infrastructure as Claude Code, so you can add any remote server listed there with
claude mcp add
.
Verify you trust each server before connecting it. Servers that fetch external content can expose you to
prompt injection risk
.
To build your own server, see the
MCP server guide
for protocol fundamentals and the
Claude connector building docs
for authentication, testing, and Directory submission.
You can also have Claude scaffold a server for you with the official
mcp-server-dev
plugin
.
1
Install the plugin
In a Claude Code session, run:
/plugin install mcp-server-dev@claude-plugins-official
Then run
/reload-plugins
to activate it in the current session.
2
Run the build skill
/mcp-server-dev:build-mcp-server
Claude asks about your use case and scaffolds a remote HTTP or local stdio server.
​
Installing MCP servers
MCP servers can be configured in three different ways depending on your needs:
​
Option 1: Add a remote HTTP server
HTTP servers are the recommended option for connecting to remote MCP servers. This is the most widely supported transport for cloud-based services.
# Basic syntax
claude
mcp
add
--transport
http
<
nam
e
>
<
ur
l
>
# Real example: Connect to Notion
claude
mcp
add
--transport
http
notion
https://mcp.notion.com/mcp
# Example with Bearer token
claude
mcp
add
--transport
http
secure-api
https://api.example.com/mcp
\
--header
"Authorization: Bearer your-token"
When configuring MCP servers via JSON in
.mcp.json
,
~/.claude.json
, or
claude mcp add-json
, the
type
field accepts
streamable-http
as an alias for
http
. The MCP specification uses the name
streamable-http
for this transport, so configurations copied from server documentation work without modification.
​
Option 2: Add a remote SSE server
The SSE (Server-Sent Events) transport is deprecated. Use HTTP servers instead, where available.
# Basic syntax
claude
mcp
add
--transport
sse
<
nam
e
>
<
ur
l
>
# Real example: Connect to Asana
claude
mcp
add
--transport
sse
asana
https://mcp.asana.com/sse
# Example with authentication header
claude
mcp
add
--transport
sse
private-api
https://api.company.com/sse
\
--header
"X-API-Key: your-key-here"
​
Option 3: Add a local stdio server
Stdio servers run as local processes on your machine. They’re ideal for tools that need direct system access or custom scripts.
Claude Code sets
CLAUDE_PROJECT_DIR
in the spawned server’s environment to the project root, so your server can resolve project-relative paths without depending on the working directory. This is the same directory hooks receive in their
CLAUDE_PROJECT_DIR
variable. Read it from inside your server process, for example
process.env.CLAUDE_PROJECT_DIR
in Node or
os.environ["CLAUDE_PROJECT_DIR"]
in Python. Your server can also call the MCP
roots/list
request, which returns the directory Claude Code was launched from.
This variable is set in the server’s environment, not in Claude Code’s own environment, so referencing it via
${VAR}
expansion in a project- or user-scoped
.mcp.json
command
or
args
requires a default such as
${CLAUDE_PROJECT_DIR:-.}
. Plugin-provided MCP configurations substitute
${CLAUDE_PROJECT_DIR}
directly and don’t need the default.
# Basic syntax
claude
mcp
add
[options]
<
name
>
--
<
command
>
[args...]
# Real example: Add Airtable server
claude
mcp
add
--transport
stdio
--env
AIRTABLE_API_KEY=YOUR_KEY
airtable
\
--
npx
-y
airtable-mcp-server
Important: Option ordering
All options (
--transport
,
--env
,
--scope
,
--header
) must come
before
the server name. The
--
(double dash) then separates the server name from the command and arguments that get passed to the MCP server.
For example:
claude mcp add --transport stdio myserver -- npx server
→ runs
npx server
claude mcp add --transport stdio --env KEY=value myserver -- python server.py --port 8080
→ runs
python server.py --port 8080
with
KEY=value
in environment
This prevents conflicts between Claude’s flags and the server’s flags.
​
Managing your servers
Once configured, you can manage your MCP servers with these commands:
# List all configured servers
claude
mcp
list
# Get details for a specific server
claude
mcp
get
github
# Remove a server
claude
mcp
remove
github
# (within Claude Code) Check server status
/mcp
The
/mcp
panel shows the tool count next to each connected server and flags servers that advertise the tools capability but expose no tools.
The server name
workspace
is reserved for internal use. If your configuration defines a server with that name, Claude Code skips it at load time and shows a warning asking you to rename it.
​
Dynamic tool updates
Claude Code supports MCP
list_changed
notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a
list_changed
notification, Claude Code automatically refreshes the available capabilities from that server.
​
Automatic reconnection
If an HTTP or SSE server disconnects mid-session, Claude Code automatically reconnects with exponential backoff: up to five attempts, starting at a one-second delay and doubling each time. The server appears as pending in
/mcp
while reconnection is in progress. After five failed attempts the server is marked as failed and you can retry manually from
/mcp
. Stdio servers are local processes and are not reconnected automatically.
The same backoff applies when an HTTP or SSE server fails its initial connection at startup. As of v2.1.121, Claude Code retries the initial connection up to three times on transient errors such as a 5xx response, a connection refused, or a timeout, then marks the server as failed if it still cannot connect. Authentication and not-found errors are not retried because they require a configuration change to resolve.
​
Push messages with channels
An MCP server can also push messages directly into your session so Claude can react to external events like CI results, monitoring alerts, or chat messages. To enable this, your server declares the
claude/channel
capability and you opt it in with the
--channels
flag at startup. See
Channels
to use an officially supported channel, or
Channels reference
to build your own.
Tips:
Use the
--scope
flag to specify where the configuration is stored:
local
(default): Available only to you in the current project (was called
project
in older versions)
project
: Shared with everyone in the project via
.mcp.json
file
user
: Available to you across all projects (was called
global
in older versions)
Set environment variables with
--env
flags (for example,
--env KEY=value
)
Configure MCP server startup timeout using the MCP_TIMEOUT environment variable (for example,
MCP_TIMEOUT=10000 claude
sets a 10-second timeout)
Claude Code will display a warning when MCP tool output exceeds 10,000 tokens. To increase this limit, set the
MAX_MCP_OUTPUT_TOKENS
environment variable (for example,
MAX_MCP_OUTPUT_TOKENS=50000
)
Use
/mcp
to authenticate with remote servers that require OAuth 2.0 authentication
​
Plugin-provided MCP servers
Plugins
can bundle MCP servers, automatically providing tools and integrations when the plugin is enabled. Plugin MCP servers work identically to user-configured servers.
How plugin MCP servers work
:
Plugins define MCP servers in
.mcp.json
at the plugin root or inline in
plugin.json
When a plugin is enabled, its MCP servers start automatically
Plugin MCP tools appear alongside manually configured MCP tools
Plugin servers are managed through plugin installation (not
/mcp
commands)
Example plugin MCP configuration
:
In
.mcp.json
at plugin root:
{
"mcpServers"
: {
"database-tools"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
],
"env"
: {
"DB_URL"
:
"${DB_URL}"
}
}
}
}
Or inline in
plugin.json
:
{
"name"
:
"my-plugin"
,
"mcpServers"
: {
"plugin-api"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/api-server"
,
"args"
: [
"--port"
,
"8080"
]
}
}
}
Plugin MCP features
:
Automatic lifecycle
: At session startup, servers for enabled plugins connect automatically. If you enable or disable a plugin during a session, run
/reload-plugins
to connect or disconnect its MCP servers
Environment variables
: use
${CLAUDE_PLUGIN_ROOT}
for bundled plugin files,
${CLAUDE_PLUGIN_DATA}
for
persistent state
that survives plugin updates, and
${CLAUDE_PROJECT_DIR}
for the stable project root
User environment access
: Access to same environment variables as manually configured servers
Multiple transport types
: Support stdio, SSE, and HTTP transports (transport support may vary by server)
Viewing plugin MCP servers
:
# Within Claude Code, see all MCP servers including plugin ones
/mcp
Plugin servers appear in the list with indicators showing they come from plugins.
Benefits of plugin MCP servers
:
Bundled distribution
: Tools and servers packaged together
Automatic setup
: No manual MCP configuration needed
Team consistency
: Everyone gets the same tools when plugin is installed
See the
plugin components reference
for details on bundling MCP servers with plugins.
​
MCP installation scopes
MCP servers can be configured at three scopes. The scope you choose controls which projects the server loads in and whether the configuration is shared with your team. Administrators can also deploy servers at the enterprise level via
managed configuration
.
Scope
Loads in
Shared with team
Stored in
Local
Current project only
No
~/.claude.json
Project
Current project only
Yes, via version control
.mcp.json
in project root
User
All your projects
No
~/.claude.json
​
Local scope
Local scope is the default. A local-scoped server loads only in the project where you added it and stays private to you. Claude Code stores it in
~/.claude.json
under that project’s path, so the same server won’t appear in your other projects. Use local scope for personal development servers, experimental configurations, or servers with credentials you don’t want in version control.
The term “local scope” for MCP servers differs from general local settings. MCP local-scoped servers are stored in
~/.claude.json
(your home directory), while general local settings use
.claude/settings.local.json
(in the project directory). See
Settings
for details on settings file locations.
# Add a local-scoped server (default)
claude
mcp
add
--transport
http
stripe
https://mcp.stripe.com
# Explicitly specify local scope
claude
mcp
add
--transport
http
stripe
--scope
local
https://mcp.stripe.com
The command writes the server into the entry for your current project inside
~/.claude.json
. The example below shows the result when you run it from
/path/to/your/project
:
{
"projects"
: {
"/path/to/your/project"
: {
"mcpServers"
: {
"stripe"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.stripe.com"
}
}
}
}
}
​
Project scope
Project-scoped servers enable team collaboration by storing configurations in a
.mcp.json
file at your project’s root directory. This file is designed to be checked into version control, ensuring all team members have access to the same MCP tools and services. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure.
# Add a project-scoped server
claude
mcp
add
--transport
http
paypal
--scope
project
https://mcp.paypal.com/mcp
The resulting
.mcp.json
file follows a standardized format:
{
"mcpServers"
: {
"shared-server"
: {
"command"
:
"/path/to/server"
,
"args"
: [],
"env"
: {}
}
}
}
For security reasons, Claude Code prompts for approval before using project-scoped servers from
.mcp.json
files. If you need to reset these approval choices, use the
claude mcp reset-project-choices
command.
​
User scope
User-scoped servers are stored in
~/.claude.json
and provide cross-project accessibility, making them available across all projects on your machine while remaining private to your user account. This scope works well for personal utility servers, development tools, or services you frequently use across different projects.
# Add a user server
claude
mcp
add
--transport
http
hubspot
--scope
user
https://mcp.hubspot.com/anthropic
​
Scope hierarchy and precedence
When the same server is defined in more than one place, Claude Code connects to it once, using the definition from the highest-precedence source:
Local scope
Project scope
User scope
Plugin-provided servers
claude.ai connectors
The three scopes match duplicates by name. Plugins and connectors match by endpoint, so one that points at the same URL or command as a server above is treated as a duplicate.
​
Environment variable expansion in
.mcp.json
Claude Code supports environment variable expansion in
.mcp.json
files, allowing teams to share configurations while maintaining flexibility for machine-specific paths and sensitive values like API keys.
Supported syntax:
${VAR}
- Expands to the value of environment variable
VAR
${VAR:-default}
- Expands to
VAR
if set, otherwise uses
default
Expansion locations:
Environment variables can be expanded in:
command
- The server executable path
args
- Command-line arguments
env
- Environment variables passed to the server
url
- For HTTP server types
headers
- For HTTP server authentication
Example with variable expansion:
{
"mcpServers"
: {
"api-server"
: {
"type"
:
"http"
,
"url"
:
"${API_BASE_URL:-https://api.example.com}/mcp"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_KEY}"
}
}
}
}
If a required environment variable is not set and has no default value, Claude Code will fail to parse the config.
​
Practical examples
​
Example: Monitor errors with Sentry
claude
mcp
add
--transport
http
sentry
https://mcp.sentry.dev/mcp
Authenticate with your Sentry account:
/mcp
Then debug production issues:
What are the most common errors in the last 24 hours?
Show me the stack trace for error ID abc123
Which deployment introduced these new errors?
​
Example: Connect to GitHub for code reviews
GitHub’s remote MCP server authenticates with a GitHub personal access token passed as a header. To get one, open your
GitHub token settings
, generate a new fine-grained token with access to the repositories you want Claude to work with, then add the server:
claude
mcp
add
--transport
http
github
https://api.githubcopilot.com/mcp/
\
--header
"Authorization: Bearer YOUR_GITHUB_PAT"
Then work with GitHub:
Review PR #456 and suggest improvements
Create a new issue for the bug we just found
Show me all open PRs assigned to me
​
Example: Query your PostgreSQL database
claude
mcp
add
--transport
stdio
db
--
npx
-y
@bytebase/dbhub
\
--dsn
"postgresql://readonly:pass@prod.db.com:5432/analytics"
Then query your database naturally:
What's our total revenue this month?
Show me the schema for the orders table
Find customers who haven't made a purchase in 90 days
​
Authenticate with remote MCP servers
Many cloud-based MCP servers require authentication. Claude Code supports OAuth 2.0 for secure connections.
Claude Code marks a remote server as needing authentication when the server responds with
401 Unauthorized
or
403 Forbidden
. Either status code flags the server in
/mcp
so you can complete the OAuth flow. A custom server that returns a
WWW-Authenticate
header pointing to its authorization server gets the same automatic discovery as any other remote server.
1
Add the server that requires authentication
For example:
claude
mcp
add
--transport
http
sentry
https://mcp.sentry.dev/mcp
2
Use the /mcp command within Claude Code
In Claude code, use the command:
/mcp
Then follow the steps in your browser to login.
Tips:
Authentication tokens are stored securely and refreshed automatically
Use “Clear authentication” in the
/mcp
menu to revoke access
If your browser doesn’t open automatically, copy the provided URL and open it manually
If the browser redirect fails with a connection error after authenticating, paste the full callback URL from your browser’s address bar into the URL prompt that appears in Claude Code
OAuth authentication works with HTTP servers
​
Use a fixed OAuth callback port
Some MCP servers require a specific redirect URI registered in advance. By default, Claude Code picks a random available port for the OAuth callback. Use
--callback-port
to fix the port so it matches a pre-registered redirect URI of the form
http://localhost:PORT/callback
.
You can use
--callback-port
on its own (with dynamic client registration) or together with
--client-id
(with pre-configured credentials).
# Fixed callback port with dynamic client registration
claude
mcp
add
--transport
http
\
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
​
Use pre-configured OAuth credentials
Some MCP servers don’t support automatic OAuth setup via Dynamic Client Registration. If you see an error like “Incompatible auth server: does not support dynamic client registration,” the server requires pre-configured credentials. Claude Code also supports servers that use a Client ID Metadata Document (CIMD) instead of Dynamic Client Registration, and discovers these automatically. If automatic discovery fails, register an OAuth app through the server’s developer portal first, then provide the credentials when adding the server.
1
Register an OAuth app with the server
Create an app through the server’s developer portal and note your client ID and client secret.
Many servers also require a redirect URI. If so, choose a port and register a redirect URI in the format
http://localhost:PORT/callback
. Use that same port with
--callback-port
in the next step.
2
Add the server with your credentials
Choose one of the following methods. The port used for
--callback-port
can be any available port. It just needs to match the redirect URI you registered in the previous step.
claude mcp add
claude mcp add-json
claude mcp add-json (callback port only)
CI / env var
Use
--client-id
to pass your app’s client ID. The
--client-secret
flag prompts for the secret with masked input:
claude
mcp
add
--transport
http
\
--client-id
your-client-id
--client-secret
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
Include the
oauth
object in the JSON config and pass
--client-secret
as a separate flag:
claude
mcp
add-json
my-server
\
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}'
\
--client-secret
Use
--callback-port
without a client ID to fix the port while using dynamic client registration:
claude
mcp
add-json
my-server
\
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'
Set the secret via environment variable to skip the interactive prompt:
MCP_CLIENT_SECRET
=
your-secret
claude
mcp
add
--transport
http
\
--client-id
your-client-id
--client-secret
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
3
Authenticate in Claude Code
Run
/mcp
in Claude Code and follow the browser login flow.
Tips:
The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config
If the server uses a public OAuth client with no secret, use only
--client-id
without
--client-secret
--callback-port
can be used with or without
--client-id
These flags only apply to HTTP and SSE transports. They have no effect on stdio servers
Use
claude mcp get <name>
to verify that OAuth credentials are configured for a server
​
Override OAuth metadata discovery
Point Claude Code at a specific OAuth authorization server metadata URL to bypass the default discovery chain. Set
authServerMetadataUrl
when the MCP server’s standard endpoints error, or when you want to route discovery through an internal proxy. By default, Claude Code first checks RFC 9728 Protected Resource Metadata at
/.well-known/oauth-protected-resource
, then falls back to RFC 8414 authorization server metadata at
/.well-known/oauth-authorization-server
.
Set
authServerMetadataUrl
in the
oauth
object of your server’s config in
.mcp.json
:
{
"mcpServers"
: {
"my-server"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.example.com/mcp"
,
"oauth"
: {
"authServerMetadataUrl"
:
"https://auth.example.com/.well-known/openid-configuration"
}
}
}
}
The URL must use
https://
.
authServerMetadataUrl
requires Claude Code v2.1.64 or later. The metadata URL’s
scopes_supported
overrides the scopes the upstream server advertises.
​
Restrict OAuth scopes
Set
oauth.scopes
to pin the scopes Claude Code requests during the authorization flow. This is the supported way to restrict an MCP server to a security-team-approved subset when the upstream authorization server advertises more scopes than you want to grant. The value is a single space-separated string, matching the
scope
parameter format in RFC 6749 §3.3.
{
"mcpServers"
: {
"slack"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.slack.com/mcp"
,
"oauth"
: {
"scopes"
:
"channels:read chat:write search:read"
}
}
}
}
oauth.scopes
takes precedence over both
authServerMetadataUrl
and the scopes the server discovers at
/.well-known
. Leave it unset to let the MCP server determine the requested scope set.
If the authorization server advertises
offline_access
in
scopes_supported
, Claude Code appends it to the pinned scopes so the access token can be refreshed without a new browser sign-in.
If the server later returns a 403
insufficient_scope
for a tool call, Claude Code re-authenticates with the same pinned scopes. Widen
oauth.scopes
when a tool you need requires a scope outside the pin.
​
Use dynamic headers for custom authentication
If your MCP server uses an authentication scheme other than OAuth (such as Kerberos, short-lived tokens, or an internal SSO), use
headersHelper
to generate request headers at connection time. Claude Code runs the command and merges its output into the connection headers.
{
"mcpServers"
: {
"internal-api"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.internal.example.com"
,
"headersHelper"
:
"/opt/bin/get-mcp-auth-headers.sh"
}
}
}
The command can also be inline:
{
"mcpServers"
: {
"internal-api"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.internal.example.com"
,
"headersHelper"
:
"echo '{
\"
Authorization
\"
:
\"
Bearer '
\"
$(get-token)
\"
'
\"
}'"
}
}
}
Requirements:
The command must write a JSON object of string key-value pairs to stdout
The command runs in a shell with a 10-second timeout
Dynamic headers override any static
headers
with the same name
The helper runs fresh on each connection (at session start and on reconnect). There is no caching, so your script is responsible for any token reuse.
Claude Code sets these environment variables when executing the helper:
Variable
Value
CLAUDE_CODE_MCP_SERVER_NAME
the name of the MCP server
CLAUDE_CODE_MCP_SERVER_URL
the URL of the MCP server
Use these to write a single helper script that serves multiple MCP servers.
headersHelper
executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.
​
Add MCP servers from JSON configuration
If you have a JSON configuration for an MCP server, you can add it directly:
1
Add an MCP server from JSON
# Basic syntax
claude
mcp
add-json
<
nam
e
>
'<json>'
# Example: Adding an HTTP server with JSON configuration
claude
mcp
add-json
weather-api
'{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
# Example: Adding a stdio server with JSON configuration
claude
mcp
add-json
local-weather
'{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'
# Example: Adding an HTTP server with pre-configured OAuth credentials
claude
mcp
add-json
my-server
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}'
--client-secret
2
Verify the server was added
claude
mcp
get
weather-api
Tips:
Make sure the JSON is properly escaped in your shell
The JSON must conform to the MCP server configuration schema
You can use
--scope user
to add the server to your user configuration instead of the project-specific one
​
Import MCP servers from Claude Desktop
If you’ve already configured MCP servers in Claude Desktop, you can import them:
1
Import servers from Claude Desktop
# Basic syntax
claude
mcp
add-from-claude-desktop
2
Select which servers to import
After running the command, you’ll see an interactive dialog that allows you to select which servers you want to import.
3
Verify the servers were imported
claude
mcp
list
Tips:
This feature only works on macOS and Windows Subsystem for Linux (WSL)
It reads the Claude Desktop configuration file from its standard location on those platforms
Use the
--scope user
flag to add servers to your user configuration
Imported servers will have the same names as in Claude Desktop
If servers with the same names already exist, they will get a numerical suffix (for example,
server_1
)
​
Use MCP servers from Claude.ai
If you’ve logged into Claude Code with a
Claude.ai
account, MCP servers you’ve added in Claude.ai are automatically available in Claude Code:
1
Configure MCP servers in Claude.ai
Add servers at
claude.ai/customize/connectors
. On Team and Enterprise plans, only admins can add servers.
2
Authenticate the MCP server
Complete any required authentication steps in Claude.ai.
3
View and manage servers in Claude Code
In Claude Code, use the command:
/mcp
Claude.ai servers appear in the list with indicators showing they come from Claude.ai.
A server you’ve added in Claude Code takes
precedence
over a claude.ai connector that points at the same URL. When this happens,
/mcp
lists the connector as hidden and shows how to remove the duplicate if you’d rather use the connector.
To disable claude.ai MCP servers in Claude Code, set the
ENABLE_CLAUDEAI_MCP_SERVERS
environment variable to
false
:
ENABLE_CLAUDEAI_MCP_SERVERS
=
false
claude
​
Use Claude Code as an MCP server
You can use Claude Code itself as an MCP server that other applications can connect to:
# Start Claude as a stdio MCP server
claude
mcp
serve
You can use this in Claude Desktop by adding this configuration to claude_desktop_config.json:
{
"mcpServers"
: {
"claude-code"
: {
"type"
:
"stdio"
,
"command"
:
"claude"
,
"args"
: [
"mcp"
,
"serve"
],
"env"
: {}
}
}
}
Configuring the executable path
: The
command
field must reference the Claude Code executable. If the
claude
command is not in your system’s PATH, you’ll need to specify the full path to the executable.
To find the full path:
which
claude
Then use the full path in your configuration:
{
"mcpServers"
: {
"claude-code"
: {
"type"
:
"stdio"
,
"command"
:
"/full/path/to/claude"
,
"args"
: [
"mcp"
,
"serve"
],
"env"
: {}
}
}
}
Without the correct executable path, you’ll encounter errors like
spawn claude ENOENT
.
Tips:
The server provides access to Claude’s tools like View, Edit, LS, etc.
In Claude Desktop, try asking Claude to read files in a directory, make edits, and more.
Note that this MCP server is only exposing Claude Code’s tools to your MCP client, so your own client is responsible for implementing user confirmation for individual tool calls.
​
MCP output limits and warnings
When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context:
Output warning threshold
: Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens
Configurable limit
: you can adjust the maximum allowed MCP output tokens using the
MAX_MCP_OUTPUT_TOKENS
environment variable
Default limit
: the default maximum is 25,000 tokens
Scope
: the environment variable applies to tools that don’t declare their own limit. Tools that set
anthropic/maxResultSizeChars
use that value instead for text content, regardless of what
MAX_MCP_OUTPUT_TOKENS
is set to. Tools that return image data are still subject to
MAX_MCP_OUTPUT_TOKENS
To increase the limit for tools that produce large outputs:
export
MAX_MCP_OUTPUT_TOKENS
=
50000
claude
This is particularly useful when working with MCP servers that:
Query large datasets or databases
Generate detailed reports or documentation
Process extensive log files or debugging information
​
Raise the limit for a specific tool
If you’re building an MCP server, you can allow individual tools to return results larger than the default persist-to-disk threshold by setting
_meta["anthropic/maxResultSizeChars"]
in the tool’s
tools/list
response entry. Claude Code raises that tool’s threshold to the annotated value, up to a hard ceiling of 500,000 characters.
This is useful for tools that return inherently large but necessary outputs, such as database schemas or full file trees. Without the annotation, results that exceed the default threshold are persisted to disk and replaced with a file reference in the conversation.
{
"name"
:
"get_schema"
,
"description"
:
"Returns the full database schema"
,
"_meta"
: {
"anthropic/maxResultSizeChars"
:
200000
}
}
The annotation applies independently of
MAX_MCP_OUTPUT_TOKENS
for text content, so users don’t need to raise the environment variable for tools that declare it. Tools that return image data are still subject to the token limit.
If you frequently encounter output warnings with specific MCP servers you don’t control, consider increasing the
MAX_MCP_OUTPUT_TOKENS
limit. You can also ask the server author to add the
anthropic/maxResultSizeChars
annotation or to paginate their responses. The annotation has no effect on tools that return image content; for those, raising
MAX_MCP_OUTPUT_TOKENS
is the only option.
​
Respond to MCP elicitation requests
MCP servers can request structured input from you mid-task using elicitation. When a server needs information it can’t get on its own, Claude Code displays an interactive dialog and passes your response back to the server. No configuration is required on your side: elicitation dialogs appear automatically when a server requests them.
Servers can request input in two ways:
Form mode
: Claude Code shows a dialog with form fields defined by the server (for example, a username and password prompt). Fill in the fields and submit.
URL mode
: Claude Code opens a browser URL for authentication or approval. Complete the flow in the browser, then confirm in the CLI.
To auto-respond to elicitation requests without showing a dialog, use the
Elicitation
hook
.
If you’re building an MCP server that uses elicitation, see the
MCP elicitation specification
for protocol details and schema examples.
​
Use MCP resources
MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files.
​
Reference MCP resources
1
List available resources
Type
@
in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu.
2
Reference a specific resource
Use the format
@server:protocol://resource/path
to reference a resource:
Can you analyze @github:issue://123 and suggest a fix?
Please review the API documentation at @docs:file://api/authentication
3
Multiple resource references
You can reference multiple resources in a single prompt:
Compare @postgres:schema://users with @docs:file://database/user-model
Tips:
Resources are automatically fetched and included as attachments when referenced
Resource paths are fuzzy-searchable in the @ mention autocomplete
Claude Code automatically provides tools to list and read MCP resources when servers support them
Resources can contain any type of content that the MCP server provides (text, JSON, structured data, etc.)
​
Scale with MCP Tool Search
Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names load at session start, so adding more MCP servers has minimal impact on your context window.
​
How it works
Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront, and Claude uses a search tool to discover relevant ones when a task needs them. Only the tools Claude actually uses enter context. From your perspective, MCP tools work exactly as before.
If you prefer threshold-based loading, set
ENABLE_TOOL_SEARCH=auto
to load schemas upfront when they fit within 10% of the context window and defer only the overflow. See
Configure tool search
for all options.
​
For MCP server authors
If you’re building an MCP server, the server instructions field becomes more useful with Tool Search enabled. Server instructions help Claude understand when to search for your tools, similar to how
skills
work.
Add clear, descriptive server instructions that explain:
What category of tasks your tools handle
When Claude should search for your tools
Key capabilities your server provides
Claude Code truncates tool descriptions and server instructions at 2KB each. Keep them concise to avoid truncation, and put critical details near the start.
​
Configure tool search
Tool search is enabled by default: MCP tools are deferred and discovered on demand. Claude Code disables it by default on Vertex AI. It is also disabled when
ANTHROPIC_BASE_URL
points to a non-first-party host, since most proxies do not forward
tool_reference
blocks. Set
ENABLE_TOOL_SEARCH
explicitly to override either fallback.
Tool search requires a model that supports
tool_reference
blocks: Sonnet 4 and later, or Opus 4 and later. Haiku models do not support it. On Vertex AI, tool search is supported for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later.
Control tool search behavior with the
ENABLE_TOOL_SEARCH
environment variable:
Value
Behavior
(unset)
All MCP tools deferred and loaded on demand. Falls back to loading upfront on Vertex AI or when
ANTHROPIC_BASE_URL
is a non-first-party host
true
All MCP tools deferred. Claude Code sends the beta header even on Vertex AI and through proxies. Requests fail on Vertex AI models earlier than Sonnet 4.5 or Opus 4.5, or on proxies that do not support
tool_reference
blocks
auto
Threshold mode: tools load upfront if they fit within 10% of the context window, deferred otherwise
auto:N
Threshold mode with a custom percentage, where
N
is 0-100. For example,
auto:5
for 5%
false
All MCP tools loaded upfront, no deferral
# Use a custom 5% threshold
ENABLE_TOOL_SEARCH
=
auto:5
claude
# Disable tool search entirely
ENABLE_TOOL_SEARCH
=
false
claude
Or set the value in your
settings.json
env
field
.
You can also disable the
ToolSearch
tool specifically:
{
"permissions"
: {
"deny"
: [
"ToolSearch"
]
}
}
​
Exempt a server from deferral
If a server’s tools should always be visible to Claude without a search step, set
alwaysLoad
to
true
in that server’s configuration. Every tool from that server then loads into context at session start regardless of the
ENABLE_TOOL_SEARCH
setting. Use this for a small number of tools that Claude needs on every turn, since each upfront tool consumes context that would otherwise be available for your conversation.
The following
.mcp.json
entry exempts one HTTP server while leaving other servers deferred:
{
"mcpServers"
: {
"core-tools"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.example.com/mcp"
,
"alwaysLoad"
:
true
}
}
}
The
alwaysLoad
field is available on all server types and requires Claude Code v2.1.121 or later. An MCP server can also mark individual tools as always-loaded by including
"anthropic/alwaysLoad": true
in the tool’s
_meta
object, which has the same effect for that tool only.
Setting
alwaysLoad: true
also blocks startup until the server connects, capped at the standard 5-second connect timeout. This applies even when
MCP_CONNECTION_NONBLOCKING=1
is set, since the tools must be present when the first prompt is built. Other servers still connect in the background when nonblocking is enabled.
​
Use MCP prompts as commands
MCP servers can expose prompts that become available as commands in Claude Code.
​
Execute MCP prompts
1
Discover available prompts
Type
/
to see all available commands, including those from MCP servers. MCP prompts appear with the format
/mcp__servername__promptname
.
2
Execute a prompt without arguments
/mcp__github__list_prs
3
Execute a prompt with arguments
Many prompts accept arguments. Pass them space-separated after the command:
/mcp__github__pr_review 456
/mcp__jira__create_issue "Bug in login flow" high
Tips:
MCP prompts are dynamically discovered from connected servers
Arguments are parsed based on the prompt’s defined parameters
Prompt results are injected directly into the conversation
Server and prompt names are normalized (spaces become underscores)
​
Managed MCP configuration
For organizations that need centralized control over MCP servers, Claude Code supports two configuration options:
Exclusive control with
managed-mcp.json
: Deploy a fixed set of MCP servers that users cannot modify or extend
Policy-based control with allowlists/denylists
: Allow users to add their own servers, but restrict which ones are permitted
These options allow IT administrators to:
Control which MCP servers employees can access
: Deploy a standardized set of approved MCP servers across the organization
Prevent unauthorized MCP servers
: Restrict users from adding unapproved MCP servers
Disable MCP entirely
: Remove MCP functionality completely if needed
​
Option 1: Exclusive control with managed-mcp.json
When you deploy a
managed-mcp.json
file, it takes
exclusive control
over all MCP servers. Users cannot add, modify, or use any MCP servers other than those defined in this file. This is the simplest approach for organizations that want complete control.
System administrators deploy the configuration file to a system-wide directory:
macOS:
/Library/Application Support/ClaudeCode/managed-mcp.json
Linux and WSL:
/etc/claude-code/managed-mcp.json
Windows:
C:\Program Files\ClaudeCode\managed-mcp.json
These are system-wide paths (not user home directories like
~/Library/...
) that require administrator privileges. They are designed to be deployed by IT administrators.
The
managed-mcp.json
file uses the same format as a standard
.mcp.json
file:
{
"mcpServers"
: {
"github"
: {
"type"
:
"http"
,
"url"
:
"https://api.githubcopilot.com/mcp/"
},
"sentry"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.sentry.dev/mcp"
},
"company-internal"
: {
"type"
:
"stdio"
,
"command"
:
"/usr/local/bin/company-mcp-server"
,
"args"
: [
"--config"
,
"/etc/company/mcp-config.json"
],
"env"
: {
"COMPANY_API_URL"
:
"https://internal.company.com"
}
}
}
}
​
Option 2: Policy-based control with allowlists and denylists
Instead of taking exclusive control, administrators can allow users to configure their own MCP servers while enforcing restrictions on which servers are permitted. This approach uses
allowedMcpServers
and
deniedMcpServers
in the
managed settings file
.
Choosing between options
: Use Option 1 (
managed-mcp.json
) when you want to deploy a fixed set of servers with no user customization. Use Option 2 (allowlists/denylists) when you want to allow users to add their own servers within policy constraints.
​
Restriction options
Each entry in the allowlist or denylist can restrict servers in three ways:
By server name
(
serverName
): Matches the configured name of the server
By command
(
serverCommand
): Matches the exact command and arguments used to start stdio servers
By URL pattern
(
serverUrl
): Matches remote server URLs with wildcard support
Important
: Each entry must have exactly one of
serverName
,
serverCommand
, or
serverUrl
.
​
Example configuration
{
"allowedMcpServers"
: [
// Allow by server name
{
"serverName"
:
"github"
},
{
"serverName"
:
"sentry"
},
// Allow by exact command (for stdio servers)
{
"serverCommand"
: [
"npx"
,
"-y"
,
"@modelcontextprotocol/server-filesystem"
] },
{
"serverCommand"
: [
"python"
,
"/usr/local/bin/approved-server.py"
] },
// Allow by URL pattern (for remote servers)
{
"serverUrl"
:
"https://mcp.company.com/*"
},
{
"serverUrl"
:
"https://*.internal.corp/*"
}
],
"deniedMcpServers"
: [
// Block by server name
{
"serverName"
:
"dangerous-server"
},
// Block by exact command (for stdio servers)
{
"serverCommand"
: [
"npx"
,
"-y"
,
"unapproved-package"
] },
// Block by URL pattern (for remote servers)
{
"serverUrl"
:
"https://*.untrusted.com/*"
}
]
}
​
How command-based restrictions work
Exact matching
:
Command arrays must match
exactly
- both the command and all arguments in the correct order
Example:
["npx", "-y", "server"]
will NOT match
["npx", "server"]
or
["npx", "-y", "server", "--flag"]
Stdio server behavior
:
When the allowlist contains
any
serverCommand
entries, stdio servers
must
match one of those commands
Stdio servers cannot pass by name alone when command restrictions are present
This ensures administrators can enforce which commands are allowed to run
Non-stdio server behavior
:
Remote servers (HTTP, SSE, WebSocket) use URL-based matching when
serverUrl
entries exist in the allowlist
If no URL entries exist, remote servers fall back to name-based matching
Command restrictions do not apply to remote servers
​
How URL-based restrictions work
URL patterns support wildcards using
*
to match any sequence of characters. This is useful for allowing entire domains or subdomains.
Wildcard examples
:
https://mcp.company.com/*
- Allow all paths on a specific domain
https://*.example.com/*
- Allow any subdomain of example.com
http://localhost:*/*
- Allow any port on localhost
Hostname matching is case-insensitive and ignores a trailing FQDN dot, matching DNS semantics. A pattern like
*://Mcp.Example.com/*
matches
https://mcp.example.com/api
, and
https://mcp.example.com.
is treated the same as
https://mcp.example.com
. Paths remain case-sensitive.
Remote server behavior
:
When the allowlist contains
any
serverUrl
entries, remote servers
must
match one of those URL patterns
Remote servers cannot pass by name alone when URL restrictions are present
This ensures administrators can enforce which remote endpoints are allowed
Example: URL-only allowlist
{
"allowedMcpServers"
: [
{
"serverUrl"
:
"https://mcp.company.com/*"
},
{
"serverUrl"
:
"https://*.internal.corp/*"
}
]
}
Result
:
HTTP server at
https://mcp.company.com/api
: ✅ Allowed (matches URL pattern)
HTTP server at
https://api.internal.corp/mcp
: ✅ Allowed (matches wildcard subdomain)
HTTP server at
https://external.com/mcp
: ❌ Blocked (doesn’t match any URL pattern)
Stdio server with any command: ❌ Blocked (no name or command entries to match)
Example: Command-only allowlist
{
"allowedMcpServers"
: [
{
"serverCommand"
: [
"npx"
,
"-y"
,
"approved-package"
] }
]
}
Result
:
Stdio server with
["npx", "-y", "approved-package"]
: ✅ Allowed (matches command)
Stdio server with
["node", "server.js"]
: ❌ Blocked (doesn’t match command)
HTTP server named “my-api”: ❌ Blocked (no name entries to match)
Example: Mixed name and command allowlist
{
"allowedMcpServers"
: [
{
"serverName"
:
"github"
},
{
"serverCommand"
: [
"npx"
,
"-y"
,
"approved-package"
] }
]
}
Result
:
Stdio server named “local-tool” with
["npx", "-y", "approved-package"]
: ✅ Allowed (matches command)
Stdio server named “local-tool” with
["node", "server.js"]
: ❌ Blocked (command entries exist but doesn’t match)
Stdio server named “github” with
["node", "server.js"]
: ❌ Blocked (stdio servers must match commands when command entries exist)
HTTP server named “github”: ✅ Allowed (matches name)
HTTP server named “other-api”: ❌ Blocked (name doesn’t match)
Example: Name-only allowlist
{
"allowedMcpServers"
: [
{
"serverName"
:
"github"
},
{
"serverName"
:
"internal-tool"
}
]
}
Result
:
Stdio server named “github” with any command: ✅ Allowed (no command restrictions)
Stdio server named “internal-tool” with any command: ✅ Allowed (no command restrictions)
HTTP server named “github”: ✅ Allowed (matches name)
Any server named “other”: ❌ Blocked (name doesn’t match)
​
Allowlist behavior (
allowedMcpServers
)
undefined
(default): No restrictions - users can configure any MCP server
Empty array
[]
: Complete lockdown - users cannot configure any MCP servers
List of entries: Users can only configure servers that match by name, command, or URL pattern
​
Denylist behavior (
deniedMcpServers
)
undefined
(default): No servers are blocked
Empty array
[]
: No servers are blocked
List of entries: Specified servers are explicitly blocked across all scopes
​
Important notes
Option 1 and Option 2 can be combined
: If
managed-mcp.json
exists, it has exclusive control and users cannot add servers. Allowlists/denylists still apply to the managed servers themselves.
Denylist takes absolute precedence
: If a server matches a denylist entry (by name, command, or URL), it will be blocked even if it’s on the allowlist
Name-based, command-based, and URL-based restrictions work together: a server passes if it matches
either
a name entry, a command entry, or a URL pattern (unless blocked by denylist)
When using
managed-mcp.json
: Users cannot add MCP servers through
claude mcp add
or configuration files. The
allowedMcpServers
and
deniedMcpServers
settings still apply to filter which managed servers are actually loaded.
Was this page helpful?
Yes
No
Isolate sessions with worktrees
Discover and install prebuilt plugins
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/mcp" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Connect Claude Code to tools via MCP
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch se...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Connect Claude Code to tools via MCP
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code can connect to hundreds of external tools and data sources through the
Model Context Protocol (MCP)
, an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs.
Connect a server when you find yourself copying data into chat from another tool, like an issue tracker or a monitoring dashboard. Once connected, Claude can read and act on that system directly instead of working from what you paste.
​
What you can do with MCP
With MCP servers connected, you can ask Claude Code to:
Implement features from issue trackers
: “Add the feature described in JIRA issue ENG-4521 and create a PR on GitHub.”
Analyze monitoring data
: “Check Sentry and Statsig to check the usage of the feature described in ENG-4521.”
Query databases
: “Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database.”
Integrate designs
: “Update our standard email template based on the new Figma designs that were posted in Slack”
Automate workflows
: “Create Gmail drafts inviting these 10 users to a feedback session about the new feature.”
React to external events
: An MCP server can also act as a
channel
that pushes messages into your session, so Claude reacts to Telegram messages, Discord chats, or webhook events while you’re away.
​
Find and build MCP servers
Browse reviewed connectors in the
Anthropic Directory
. Directory connectors use the same MCP infrastructure as Claude Code, so you can add any remote server listed there with
claude mcp add
.
Verify you trust each server before connecting it. Servers that fetch external content can expose you to
prompt injection risk
.
To build your own server, see the
MCP server guide
for protocol fundamentals and the
Claude connector building docs
for authentication, testing, and Directory submission.
You can also have Claude scaffold a server for you with the official
mcp-server-dev
plugin
.
1
Install the plugin
In a Claude Code session, run:
/plugin install mcp-server-dev@claude-plugins-official
Then run
/reload-plugins
to activate it in the current session.
2
Run the build skill
/mcp-server-dev:build-mcp-server
Claude asks about your use case and scaffolds a remote HTTP or local stdio server.
​
Installing MCP servers
MCP servers can be configured in three different ways depending on your needs:
​
Option 1: Add a remote HTTP server
HTTP servers are the recommended option for connecting to remote MCP servers. This is the most widely supported transport for cloud-based services.
# Basic syntax
claude
mcp
add
--transport
http
<
nam
e
>
<
ur
l
>
# Real example: Connect to Notion
claude
mcp
add
--transport
http
notion
https://mcp.notion.com/mcp
# Example with Bearer token
claude
mcp
add
--transport
http
secure-api
https://api.example.com/mcp
\
--header
"Authorization: Bearer your-token"
When configuring MCP servers via JSON in
.mcp.json
,
~/.claude.json
, or
claude mcp add-json
, the
type
field accepts
streamable-http
as an alias for
http
. The MCP specification uses the name
streamable-http
for this transport, so configurations copied from server documentation work without modification.
​
Option 2: Add a remote SSE server
The SSE (Server-Sent Events) transport is deprecated. Use HTTP servers instead, where available.
# Basic syntax
claude
mcp
add
--transport
sse
<
nam
e
>
<
ur
l
>
# Real example: Connect to Asana
claude
mcp
add
--transport
sse
asana
https://mcp.asana.com/sse
# Example with authentication header
claude
mcp
add
--transport
sse
private-api
https://api.company.com/sse
\
--header
"X-API-Key: your-key-here"
​
Option 3: Add a local stdio server
Stdio servers run as local processes on your machine. They’re ideal for tools that need direct system access or custom scripts.
Claude Code sets
CLAUDE_PROJECT_DIR
in the spawned server’s environment to the project root, so your server can resolve project-relative paths without depending on the working directory. This is the same directory hooks receive in their
CLAUDE_PROJECT_DIR
variable. Read it from inside your server process, for example
process.env.CLAUDE_PROJECT_DIR
in Node or
os.environ["CLAUDE_PROJECT_DIR"]
in Python. Your server can also call the MCP
roots/list
request, which returns the directory Claude Code was launched from.
This variable is set in the server’s environment, not in Claude Code’s own environment, so referencing it via
${VAR}
expansion in a project- or user-scoped
.mcp.json
command
or
args
requires a default such as
${CLAUDE_PROJECT_DIR:-.}
. Plugin-provided MCP configurations substitute
${CLAUDE_PROJECT_DIR}
directly and don’t need the default.
# Basic syntax
claude
mcp
add
[options]
<
name
>
--
<
command
>
[args...]
# Real example: Add Airtable server
claude
mcp
add
--transport
stdio
--env
AIRTABLE_API_KEY=YOUR_KEY
airtable
\
--
npx
-y
airtable-mcp-server
Important: Option ordering
All options (
--transport
,
--env
,
--scope
,
--header
) must come
before
the server name. The
--
(double dash) then separates the server name from the command and arguments that get passed to the MCP server.
For example:
claude mcp add --transport stdio myserver -- npx server
→ runs
npx server
claude mcp add --transport stdio --env KEY=value myserver -- python server.py --port 8080
→ runs
python server.py --port 8080
with
KEY=value
in environment
This prevents conflicts between Claude’s flags and the server’s flags.
​
Managing your servers
Once configured, you can manage your MCP servers with these commands:
# List all configured servers
claude
mcp
list
# Get details for a specific server
claude
mcp
get
github
# Remove a server
claude
mcp
remove
github
# (within Claude Code) Check server status
/mcp
The
/mcp
panel shows the tool count next to each connected server and flags servers that advertise the tools capability but expose no tools.
The server name
workspace
is reserved for internal use. If your configuration defines a server with that name, Claude Code skips it at load time and shows a warning asking you to rename it.
​
Dynamic tool updates
Claude Code supports MCP
list_changed
notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a
list_changed
notification, Claude Code automatically refreshes the available capabilities from that server.
​
Automatic reconnection
If an HTTP or SSE server disconnects mid-session, Claude Code automatically reconnects with exponential backoff: up to five attempts, starting at a one-second delay and doubling each time. The server appears as pending in
/mcp
while reconnection is in progress. After five failed attempts the server is marked as failed and you can retry manually from
/mcp
. Stdio servers are local processes and are not reconnected automatically.
The same backoff applies when an HTTP or SSE server fails its initial connection at startup. As of v2.1.121, Claude Code retries the initial connection up to three times on transient errors such as a 5xx response, a connection refused, or a timeout, then marks the server as failed if it still cannot connect. Authentication and not-found errors are not retried because they require a configuration change to resolve.
​
Push messages with channels
An MCP server can also push messages directly into your session so Claude can react to external events like CI results, monitoring alerts, or chat messages. To enable this, your server declares the
claude/channel
capability and you opt it in with the
--channels
flag at startup. See
Channels
to use an officially supported channel, or
Channels reference
to build your own.
Tips:
Use the
--scope
flag to specify where the configuration is stored:
local
(default): Available only to you in the current project (was called
project
in older versions)
project
: Shared with everyone in the project via
.mcp.json
file
user
: Available to you across all projects (was called
global
in older versions)
Set environment variables with
--env
flags (for example,
--env KEY=value
)
Configure MCP server startup timeout using the MCP_TIMEOUT environment variable (for example,
MCP_TIMEOUT=10000 claude
sets a 10-second timeout)
Claude Code will display a warning when MCP tool output exceeds 10,000 tokens. To increase this limit, set the
MAX_MCP_OUTPUT_TOKENS
environment variable (for example,
MAX_MCP_OUTPUT_TOKENS=50000
)
Use
/mcp
to authenticate with remote servers that require OAuth 2.0 authentication
​
Plugin-provided MCP servers
Plugins
can bundle MCP servers, automatically providing tools and integrations when the plugin is enabled. Plugin MCP servers work identically to user-configured servers.
How plugin MCP servers work
:
Plugins define MCP servers in
.mcp.json
at the plugin root or inline in
plugin.json
When a plugin is enabled, its MCP servers start automatically
Plugin MCP tools appear alongside manually configured MCP tools
Plugin servers are managed through plugin installation (not
/mcp
commands)
Example plugin MCP configuration
:
In
.mcp.json
at plugin root:
{
"mcpServers"
: {
"database-tools"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
],
"env"
: {
"DB_URL"
:
"${DB_URL}"
}
}
}
}
Or inline in
plugin.json
:
{
"name"
:
"my-plugin"
,
"mcpServers"
: {
"plugin-api"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/api-server"
,
"args"
: [
"--port"
,
"8080"
]
}
}
}
Plugin MCP features
:
Automatic lifecycle
: At session startup, servers for enabled plugins connect automatically. If you enable or disable a plugin during a session, run
/reload-plugins
to connect or disconnect its MCP servers
Environment variables
: use
${CLAUDE_PLUGIN_ROOT}
for bundled plugin files,
${CLAUDE_PLUGIN_DATA}
for
persistent state
that survives plugin updates, and
${CLAUDE_PROJECT_DIR}
for the stable project root
User environment access
: Access to same environment variables as manually configured servers
Multiple transport types
: Support stdio, SSE, and HTTP transports (transport support may vary by server)
Viewing plugin MCP servers
:
# Within Claude Code, see all MCP servers including plugin ones
/mcp
Plugin servers appear in the list with indicators showing they come from plugins.
Benefits of plugin MCP servers
:
Bundled distribution
: Tools and servers packaged together
Automatic setup
: No manual MCP configuration needed
Team consistency
: Everyone gets the same tools when plugin is installed
See the
plugin components reference
for details on bundling MCP servers with plugins.
​
MCP installation scopes
MCP servers can be configured at three scopes. The scope you choose controls which projects the server loads in and whether the configuration is shared with your team. Administrators can also deploy servers at the enterprise level via
managed configuration
.
Scope
Loads in
Shared with team
Stored in
Local
Current project only
No
~/.claude.json
Project
Current project only
Yes, via version control
.mcp.json
in project root
User
All your projects
No
~/.claude.json
​
Local scope
Local scope is the default. A local-scoped server loads only in the project where you added it and stays private to you. Claude Code stores it in
~/.claude.json
under that project’s path, so the same server won’t appear in your other projects. Use local scope for personal development servers, experimental configurations, or servers with credentials you don’t want in version control.
The term “local scope” for MCP servers differs from general local settings. MCP local-scoped servers are stored in
~/.claude.json
(your home directory), while general local settings use
.claude/settings.local.json
(in the project directory). See
Settings
for details on settings file locations.
# Add a local-scoped server (default)
claude
mcp
add
--transport
http
stripe
https://mcp.stripe.com
# Explicitly specify local scope
claude
mcp
add
--transport
http
stripe
--scope
local
https://mcp.stripe.com
The command writes the server into the entry for your current project inside
~/.claude.json
. The example below shows the result when you run it from
/path/to/your/project
:
{
"projects"
: {
"/path/to/your/project"
: {
"mcpServers"
: {
"stripe"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.stripe.com"
}
}
}
}
}
​
Project scope
Project-scoped servers enable team collaboration by storing configurations in a
.mcp.json
file at your project’s root directory. This file is designed to be checked into version control, ensuring all team members have access to the same MCP tools and services. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure.
# Add a project-scoped server
claude
mcp
add
--transport
http
paypal
--scope
project
https://mcp.paypal.com/mcp
The resulting
.mcp.json
file follows a standardized format:
{
"mcpServers"
: {
"shared-server"
: {
"command"
:
"/path/to/server"
,
"args"
: [],
"env"
: {}
}
}
}
For security reasons, Claude Code prompts for approval before using project-scoped servers from
.mcp.json
files. If you need to reset these approval choices, use the
claude mcp reset-project-choices
command.
​
User scope
User-scoped servers are stored in
~/.claude.json
and provide cross-project accessibility, making them available across all projects on your machine while remaining private to your user account. This scope works well for personal utility servers, development tools, or services you frequently use across different projects.
# Add a user server
claude
mcp
add
--transport
http
hubspot
--scope
user
https://mcp.hubspot.com/anthropic
​
Scope hierarchy and precedence
When the same server is defined in more than one place, Claude Code connects to it once, using the definition from the highest-precedence source:
Local scope
Project scope
User scope
Plugin-provided servers
claude.ai connectors
The three scopes match duplicates by name. Plugins and connectors match by endpoint, so one that points at the same URL or command as a server above is treated as a duplicate.
​
Environment variable expansion in
.mcp.json
Claude Code supports environment variable expansion in
.mcp.json
files, allowing teams to share configurations while maintaining flexibility for machine-specific paths and sensitive values like API keys.
Supported syntax:
${VAR}
- Expands to the value of environment variable
VAR
${VAR:-default}
- Expands to
VAR
if set, otherwise uses
default
Expansion locations:
Environment variables can be expanded in:
command
- The server executable path
args
- Command-line arguments
env
- Environment variables passed to the server
url
- For HTTP server types
headers
- For HTTP server authentication
Example with variable expansion:
{
"mcpServers"
: {
"api-server"
: {
"type"
:
"http"
,
"url"
:
"${API_BASE_URL:-https://api.example.com}/mcp"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_KEY}"
}
}
}
}
If a required environment variable is not set and has no default value, Claude Code will fail to parse the config.
​
Practical examples
​
Example: Monitor errors with Sentry
claude
mcp
add
--transport
http
sentry
https://mcp.sentry.dev/mcp
Authenticate with your Sentry account:
/mcp
Then debug production issues:
What are the most common errors in the last 24 hours?
Show me the stack trace for error ID abc123
Which deployment introduced these new errors?
​
Example: Connect to GitHub for code reviews
GitHub’s remote MCP server authenticates with a GitHub personal access token passed as a header. To get one, open your
GitHub token settings
, generate a new fine-grained token with access to the repositories you want Claude to work with, then add the server:
claude
mcp
add
--transport
http
github
https://api.githubcopilot.com/mcp/
\
--header
"Authorization: Bearer YOUR_GITHUB_PAT"
Then work with GitHub:
Review PR #456 and suggest improvements
Create a new issue for the bug we just found
Show me all open PRs assigned to me
​
Example: Query your PostgreSQL database
claude
mcp
add
--transport
stdio
db
--
npx
-y
@bytebase/dbhub
\
--dsn
"postgresql://readonly:pass@prod.db.com:5432/analytics"
Then query your database naturally:
What's our total revenue this month?
Show me the schema for the orders table
Find customers who haven't made a purchase in 90 days
​
Authenticate with remote MCP servers
Many cloud-based MCP servers require authentication. Claude Code supports OAuth 2.0 for secure connections.
Claude Code marks a remote server as needing authentication when the server responds with
401 Unauthorized
or
403 Forbidden
. Either status code flags the server in
/mcp
so you can complete the OAuth flow. A custom server that returns a
WWW-Authenticate
header pointing to its authorization server gets the same automatic discovery as any other remote server.
1
Add the server that requires authentication
For example:
claude
mcp
add
--transport
http
sentry
https://mcp.sentry.dev/mcp
2
Use the /mcp command within Claude Code
In Claude code, use the command:
/mcp
Then follow the steps in your browser to login.
Tips:
Authentication tokens are stored securely and refreshed automatically
Use “Clear authentication” in the
/mcp
menu to revoke access
If your browser doesn’t open automatically, copy the provided URL and open it manually
If the browser redirect fails with a connection error after authenticating, paste the full callback URL from your browser’s address bar into the URL prompt that appears in Claude Code
OAuth authentication works with HTTP servers
​
Use a fixed OAuth callback port
Some MCP servers require a specific redirect URI registered in advance. By default, Claude Code picks a random available port for the OAuth callback. Use
--callback-port
to fix the port so it matches a pre-registered redirect URI of the form
http://localhost:PORT/callback
.
You can use
--callback-port
on its own (with dynamic client registration) or together with
--client-id
(with pre-configured credentials).
# Fixed callback port with dynamic client registration
claude
mcp
add
--transport
http
\
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
​
Use pre-configured OAuth credentials
Some MCP servers don’t support automatic OAuth setup via Dynamic Client Registration. If you see an error like “Incompatible auth server: does not support dynamic client registration,” the server requires pre-configured credentials. Claude Code also supports servers that use a Client ID Metadata Document (CIMD) instead of Dynamic Client Registration, and discovers these automatically. If automatic discovery fails, register an OAuth app through the server’s developer portal first, then provide the credentials when adding the server.
1
Register an OAuth app with the server
Create an app through the server’s developer portal and note your client ID and client secret.
Many servers also require a redirect URI. If so, choose a port and register a redirect URI in the format
http://localhost:PORT/callback
. Use that same port with
--callback-port
in the next step.
2
Add the server with your credentials
Choose one of the following methods. The port used for
--callback-port
can be any available port. It just needs to match the redirect URI you registered in the previous step.
claude mcp add
claude mcp add-json
claude mcp add-json (callback port only)
CI / env var
Use
--client-id
to pass your app’s client ID. The
--client-secret
flag prompts for the secret with masked input:
claude
mcp
add
--transport
http
\
--client-id
your-client-id
--client-secret
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
Include the
oauth
object in the JSON config and pass
--client-secret
as a separate flag:
claude
mcp
add-json
my-server
\
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}'
\
--client-secret
Use
--callback-port
without a client ID to fix the port while using dynamic client registration:
claude
mcp
add-json
my-server
\
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'
Set the secret via environment variable to skip the interactive prompt:
MCP_CLIENT_SECRET
=
your-secret
claude
mcp
add
--transport
http
\
--client-id
your-client-id
--client-secret
--callback-port
8080
\
my-server
https://mcp.example.com/mcp
3
Authenticate in Claude Code
Run
/mcp
in Claude Code and follow the browser login flow.
Tips:
The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config
If the server uses a public OAuth client with no secret, use only
--client-id
without
--client-secret
--callback-port
can be used with or without
--client-id
These flags only apply to HTTP and SSE transports. They have no effect on stdio servers
Use
claude mcp get <name>
to verify that OAuth credentials are configured for a server
​
Override OAuth metadata discovery
Point Claude Code at a specific OAuth authorization server metadata URL to bypass the default discovery chain. Set
authServerMetadataUrl
when the MCP server’s standard endpoints error, or when you want to route discovery through an internal proxy. By default, Claude Code first checks RFC 9728 Protected Resource Metadata at
/.well-known/oauth-protected-resource
, then falls back to RFC 8414 authorization server metadata at
/.well-known/oauth-authorization-server
.
Set
authServerMetadataUrl
in the
oauth
object of your server’s config in
.mcp.json
:
{
"mcpServers"
: {
"my-server"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.example.com/mcp"
,
"oauth"
: {
"authServerMetadataUrl"
:
"https://auth.example.com/.well-known/openid-configuration"
}
}
}
}
The URL must use
https://
.
authServerMetadataUrl
requires Claude Code v2.1.64 or later. The metadata URL’s
scopes_supported
overrides the scopes the upstream server advertises.
​
Restrict OAuth scopes
Set
oauth.scopes
to pin the scopes Claude Code requests during the authorization flow. This is the supported way to restrict an MCP server to a security-team-approved subset when the upstream authorization server advertises more scopes than you want to grant. The value is a single space-separated string, matching the
scope
parameter format in RFC 6749 §3.3.
{
"mcpServers"
: {
"slack"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.slack.com/mcp"
,
"oauth"
: {
"scopes"
:
"channels:read chat:write search:read"
}
}
}
}
oauth.scopes
takes precedence over both
authServerMetadataUrl
and the scopes the server discovers at
/.well-known
. Leave it unset to let the MCP server determine the requested scope set.
If the authorization server advertises
offline_access
in
scopes_supported
, Claude Code appends it to the pinned scopes so the access token can be refreshed without a new browser sign-in.
If the server later returns a 403
insufficient_scope
for a tool call, Claude Code re-authenticates with the same pinned scopes. Widen
oauth.scopes
when a tool you need requires a scope outside the pin.
​
Use dynamic headers for custom authentication
If your MCP server uses an authentication scheme other than OAuth (such as Kerberos, short-lived tokens, or an internal SSO), use
headersHelper
to generate request headers at connection time. Claude Code runs the command and merges its output into the connection headers.
{
"mcpServers"
: {
"internal-api"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.internal.example.com"
,
"headersHelper"
:
"/opt/bin/get-mcp-auth-headers.sh"
}
}
}
The command can also be inline:
{
"mcpServers"
: {
"internal-api"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.internal.example.com"
,
"headersHelper"
:
"echo '{
\"
Authorization
\"
:
\"
Bearer '
\"
$(get-token)
\"
'
\"
}'"
}
}
}
Requirements:
The command must write a JSON object of string key-value pairs to stdout
The command runs in a shell with a 10-second timeout
Dynamic headers override any static
headers
with the same name
The helper runs fresh on each connection (at session start and on reconnect). There is no caching, so your script is responsible for any token reuse.
Claude Code sets these environment variables when executing the helper:
Variable
Value
CLAUDE_CODE_MCP_SERVER_NAME
the name of the MCP server
CLAUDE_CODE_MCP_SERVER_URL
the URL of the MCP server
Use these to write a single helper script that serves multiple MCP servers.
headersHelper
executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.
​
Add MCP servers from JSON configuration
If you have a JSON configuration for an MCP server, you can add it directly:
1
Add an MCP server from JSON
# Basic syntax
claude
mcp
add-json
<
nam
e
>
'<json>'
# Example: Adding an HTTP server with JSON configuration
claude
mcp
add-json
weather-api
'{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
# Example: Adding a stdio server with JSON configuration
claude
mcp
add-json
local-weather
'{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'
# Example: Adding an HTTP server with pre-configured OAuth credentials
claude
mcp
add-json
my-server
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}'
--client-secret
2
Verify the server was added
claude
mcp
get
weather-api
Tips:
Make sure the JSON is properly escaped in your shell
The JSON must conform to the MCP server configuration schema
You can use
--scope user
to add the server to your user configuration instead of the project-specific one
​
Import MCP servers from Claude Desktop
If you’ve already configured MCP servers in Claude Desktop, you can import them:
1
Import servers from Claude Desktop
# Basic syntax
claude
mcp
add-from-claude-desktop
2
Select which servers to import
After running the command, you’ll see an interactive dialog that allows you to select which servers you want to import.
3
Verify the servers were imported
claude
mcp
list
Tips:
This feature only works on macOS and Windows Subsystem for Linux (WSL)
It reads the Claude Desktop configuration file from its standard location on those platforms
Use the
--scope user
flag to add servers to your user configuration
Imported servers will have the same names as in Claude Desktop
If servers with the same names already exist, they will get a numerical suffix (for example,
server_1
)
​
Use MCP servers from Claude.ai
If you’ve logged into Claude Code with a
Claude.ai
account, MCP servers you’ve added in Claude.ai are automatically available in Claude Code:
1
Configure MCP servers in Claude.ai
Add servers at
claude.ai/customize/connectors
. On Team and Enterprise plans, only admins can add servers.
2
Authenticate the MCP server
Complete any required authentication steps in Claude.ai.
3
View and manage servers in Claude Code
In Claude Code, use the command:
/mcp
Claude.ai servers appear in the list with indicators showing they come from Claude.ai.
A server you’ve added in Claude Code takes
precedence
over a claude.ai connector that points at the same URL. When this happens,
/mcp
lists the connector as hidden and shows how to remove the duplicate if you’d rather use the connector.
To disable claude.ai MCP servers in Claude Code, set the
ENABLE_CLAUDEAI_MCP_SERVERS
environment variable to
false
:
ENABLE_CLAUDEAI_MCP_SERVERS
=
false
claude
​
Use Claude Code as an MCP server
You can use Claude Code itself as an MCP server that other applications can connect to:
# Start Claude as a stdio MCP server
claude
mcp
serve
You can use this in Claude Desktop by adding this configuration to claude_desktop_config.json:
{
"mcpServers"
: {
"claude-code"
: {
"type"
:
"stdio"
,
"command"
:
"claude"
,
"args"
: [
"mcp"
,
"serve"
],
"env"
: {}
}
}
}
Configuring the executable path
: The
command
field must reference the Claude Code executable. If the
claude
command is not in your system’s PATH, you’ll need to specify the full path to the executable.
To find the full path:
which
claude
Then use the full path in your configuration:
{
"mcpServers"
: {
"claude-code"
: {
"type"
:
"stdio"
,
"command"
:
"/full/path/to/claude"
,
"args"
: [
"mcp"
,
"serve"
],
"env"
: {}
}
}
}
Without the correct executable path, you’ll encounter errors like
spawn claude ENOENT
.
Tips:
The server provides access to Claude’s tools like View, Edit, LS, etc.
In Claude Desktop, try asking Claude to read files in a directory, make edits, and more.
Note that this MCP server is only exposing Claude Code’s tools to your MCP client, so your own client is responsible for implementing user confirmation for individual tool calls.
​
MCP output limits and warnings
When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context:
Output warning threshold
: Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens
Configurable limit
: you can adjust the maximum allowed MCP output tokens using the
MAX_MCP_OUTPUT_TOKENS
environment variable
Default limit
: the default maximum is 25,000 tokens
Scope
: the environment variable applies to tools that don’t declare their own limit. Tools that set
anthropic/maxResultSizeChars
use that value instead for text content, regardless of what
MAX_MCP_OUTPUT_TOKENS
is set to. Tools that return image data are still subject to
MAX_MCP_OUTPUT_TOKENS
To increase the limit for tools that produce large outputs:
export
MAX_MCP_OUTPUT_TOKENS
=
50000
claude
This is particularly useful when working with MCP servers that:
Query large datasets or databases
Generate detailed reports or documentation
Process extensive log files or debugging information
​
Raise the limit for a specific tool
If you’re building an MCP server, you can allow individual tools to return results larger than the default persist-to-disk threshold by setting
_meta["anthropic/maxResultSizeChars"]
in the tool’s
tools/list
response entry. Claude Code raises that tool’s threshold to the annotated value, up to a hard ceiling of 500,000 characters.
This is useful for tools that return inherently large but necessary outputs, such as database schemas or full file trees. Without the annotation, results that exceed the default threshold are persisted to disk and replaced with a file reference in the conversation.
{
"name"
:
"get_schema"
,
"description"
:
"Returns the full database schema"
,
"_meta"
: {
"anthropic/maxResultSizeChars"
:
200000
}
}
The annotation applies independently of
MAX_MCP_OUTPUT_TOKENS
for text content, so users don’t need to raise the environment variable for tools that declare it. Tools that return image data are still subject to the token limit.
If you frequently encounter output warnings with specific MCP servers you don’t control, consider increasing the
MAX_MCP_OUTPUT_TOKENS
limit. You can also ask the server author to add the
anthropic/maxResultSizeChars
annotation or to paginate their responses. The annotation has no effect on tools that return image content; for those, raising
MAX_MCP_OUTPUT_TOKENS
is the only option.
​
Respond to MCP elicitation requests
MCP servers can request structured input from you mid-task using elicitation. When a server needs information it can’t get on its own, Claude Code displays an interactive dialog and passes your response back to the server. No configuration is required on your side: elicitation dialogs appear automatically when a server requests them.
Servers can request input in two ways:
Form mode
: Claude Code shows a dialog with form fields defined by the server (for example, a username and password prompt). Fill in the fields and submit.
URL mode
: Claude Code opens a browser URL for authentication or approval. Complete the flow in the browser, then confirm in the CLI.
To auto-respond to elicitation requests without showing a dialog, use the
Elicitation
hook
.
If you’re building an MCP server that uses elicitation, see the
MCP elicitation specification
for protocol details and schema examples.
​
Use MCP resources
MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files.
​
Reference MCP resources
1
List available resources
Type
@
in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu.
2
Reference a specific resource
Use the format
@server:protocol://resource/path
to reference a resource:
Can you analyze @github:issue://123 and suggest a fix?
Please review the API documentation at @docs:file://api/authentication
3
Multiple resource references
You can reference multiple resources in a single prompt:
Compare @postgres:schema://users with @docs:file://database/user-model
Tips:
Resources are automatically fetched and included as attachments when referenced
Resource paths are fuzzy-searchable in the @ mention autocomplete
Claude Code automatically provides tools to list and read MCP resources when servers support them
Resources can contain any type of content that the MCP server provides (text, JSON, structured data, etc.)
​
Scale with MCP Tool Search
Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names load at session start, so adding more MCP servers has minimal impact on your context window.
​
How it works
Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront, and Claude uses a search tool to discover relevant ones when a task needs them. Only the tools Claude actually uses enter context. From your perspective, MCP tools work exactly as before.
If you prefer threshold-based loading, set
ENABLE_TOOL_SEARCH=auto
to load schemas upfront when they fit within 10% of the context window and defer only the overflow. See
Configure tool search
for all options.
​
For MCP server authors
If you’re building an MCP server, the server instructions field becomes more useful with Tool Search enabled. Server instructions help Claude understand when to search for your tools, similar to how
skills
work.
Add clear, descriptive server instructions that explain:
What category of tasks your tools handle
When Claude should search for your tools
Key capabilities your server provides
Claude Code truncates tool descriptions and server instructions at 2KB each. Keep them concise to avoid truncation, and put critical details near the start.
​
Configure tool search
Tool search is enabled by default: MCP tools are deferred and discovered on demand. Claude Code disables it by default on Vertex AI. It is also disabled when
ANTHROPIC_BASE_URL
points to a non-first-party host, since most proxies do not forward
tool_reference
blocks. Set
ENABLE_TOOL_SEARCH
explicitly to override either fallback.
Tool search requires a model that supports
tool_reference
blocks: Sonnet 4 and later, or Opus 4 and later. Haiku models do not support it. On Vertex AI, tool search is supported for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later.
Control tool search behavior with the
ENABLE_TOOL_SEARCH
environment variable:
Value
Behavior
(unset)
All MCP tools deferred and loaded on demand. Falls back to loading upfront on Vertex AI or when
ANTHROPIC_BASE_URL
is a non-first-party host
true
All MCP tools deferred. Claude Code sends the beta header even on Vertex AI and through proxies. Requests fail on Vertex AI models earlier than Sonnet 4.5 or Opus 4.5, or on proxies that do not support
tool_reference
blocks
auto
Threshold mode: tools load upfront if they fit within 10% of the context window, deferred otherwise
auto:N
Threshold mode with a custom percentage, where
N
is 0-100. For example,
auto:5
for 5%
false
All MCP tools loaded upfront, no deferral
# Use a custom 5% threshold
ENABLE_TOOL_SEARCH
=
auto:5
claude
# Disable tool search entirely
ENABLE_TOOL_SEARCH
=
false
claude
Or set the value in your
settings.json
env
field
.
You can also disable the
ToolSearch
tool specifically:
{
"permissions"
: {
"deny"
: [
"ToolSearch"
]
}
}
​
Exempt a server from deferral
If a server’s tools should always be visible to Claude without a search step, set
alwaysLoad
to
true
in that server’s configuration. Every tool from that server then loads into context at session start regardless of the
ENABLE_TOOL_SEARCH
setting. Use this for a small number of tools that Claude needs on every turn, since each upfront tool consumes context that would otherwise be available for your conversation.
The following
.mcp.json
entry exempts one HTTP server while leaving other servers deferred:
{
"mcpServers"
: {
"core-tools"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.example.com/mcp"
,
"alwaysLoad"
:
true
}
}
}
The
alwaysLoad
field is available on all server types and requires Claude Code v2.1.121 or later. An MCP server can also mark individual tools as always-loaded by including
"anthropic/alwaysLoad": true
in the tool’s
_meta
object, which has the same effect for that tool only.
Setting
alwaysLoad: true
also blocks startup until the server connects, capped at the standard 5-second connect timeout. This applies even when
MCP_CONNECTION_NONBLOCKING=1
is set, since the tools must be present when the first prompt is built. Other servers still connect in the background when nonblocking is enabled.
​
Use MCP prompts as commands
MCP servers can expose prompts that become available as commands in Claude Code.
​
Execute MCP prompts
1
Discover available prompts
Type
/
to see all available commands, including those from MCP servers. MCP prompts appear with the format
/mcp__servername__promptname
.
2
Execute a prompt without arguments
/mcp__github__list_prs
3
Execute a prompt with arguments
Many prompts accept arguments. Pass them space-separated after the command:
/mcp__github__pr_review 456
/mcp__jira__create_issue "Bug in login flow" high
Tips:
MCP prompts are dynamically discovered from connected servers
Arguments are parsed based on the prompt’s defined parameters
Prompt results are injected directly into the conversation
Server and prompt names are normalized (spaces become underscores)
​
Managed MCP configuration
For organizations that need centralized control over MCP servers, Claude Code supports two configuration options:
Exclusive control with
managed-mcp.json
: Deploy a fixed set of MCP servers that users cannot modify or extend
Policy-based control with allowlists/denylists
: Allow users to add their own servers, but restrict which ones are permitted
These options allow IT administrators to:
Control which MCP servers employees can access
: Deploy a standardized set of approved MCP servers across the organization
Prevent unauthorized MCP servers
: Restrict users from adding unapproved MCP servers
Disable MCP entirely
: Remove MCP functionality completely if needed
​
Option 1: Exclusive control with managed-mcp.json
When you deploy a
managed-mcp.json
file, it takes
exclusive control
over all MCP servers. Users cannot add, modify, or use any MCP servers other than those defined in this file. This is the simplest approach for organizations that want complete control.
System administrators deploy the configuration file to a system-wide directory:
macOS:
/Library/Application Support/ClaudeCode/managed-mcp.json
Linux and WSL:
/etc/claude-code/managed-mcp.json
Windows:
C:\Program Files\ClaudeCode\managed-mcp.json
These are system-wide paths (not user home directories like
~/Library/...
) that require administrator privileges. They are designed to be deployed by IT administrators.
The
managed-mcp.json
file uses the same format as a standard
.mcp.json
file:
{
"mcpServers"
: {
"github"
: {
"type"
:
"http"
,
"url"
:
"https://api.githubcopilot.com/mcp/"
},
"sentry"
: {
"type"
:
"http"
,
"url"
:
"https://mcp.sentry.dev/mcp"
},
"company-internal"
: {
"type"
:
"stdio"
,
"command"
:
"/usr/local/bin/company-mcp-server"
,
"args"
: [
"--config"
,
"/etc/company/mcp-config.json"
],
"env"
: {
"COMPANY_API_URL"
:
"https://internal.company.com"
}
}
}
}
​
Option 2: Policy-based control with allowlists and denylists
Instead of taking exclusive control, administrators can allow users to configure their own MCP servers while enforcing restrictions on which servers are permitted. This approach uses
allowedMcpServers
and
deniedMcpServers
in the
managed settings file
.
Choosing between options
: Use Option 1 (
managed-mcp.json
) when you want to deploy a fixed set of servers with no user customization. Use Option 2 (allowlists/denylists) when you want to allow users to add their own servers within policy constraints.
​
Restriction options
Each entry in the allowlist or denylist can restrict servers in three ways:
By server name
(
serverName
): Matches the configured name of the server
By command
(
serverCommand
): Matches the exact command and arguments used to start stdio servers
By URL pattern
(
serverUrl
): Matches remote server URLs with wildcard support
Important
: Each entry must have exactly one of
serverName
,
serverCommand
, or
serverUrl
.
​
Example configuration
{
"allowedMcpServers"
: [
// Allow by server name
{
"serverName"
:
"github"
},
{
"serverName"
:
"sentry"
},
// Allow by exact command (for stdio servers)
{
"serverCommand"
: [
"npx"
,
"-y"
,
"@modelcontextprotocol/server-filesystem"
] },
{
"serverCommand"
: [
"python"
,
"/usr/local/bin/approved-server.py"
] },
// Allow by URL pattern (for remote servers)
{
"serverUrl"
:
"https://mcp.company.com/*"
},
{
"serverUrl"
:
"https://*.internal.corp/*"
}
],
"deniedMcpServers"
: [
// Block by server name
{
"serverName"
:
"dangerous-server"
},
// Block by exact command (for stdio servers)
{
"serverCommand"
: [
"npx"
,
"-y"
,
"unapproved-package"
] },
// Block by URL pattern (for remote servers)
{
"serverUrl"
:
"https://*.untrusted.com/*"
}
]
}
​
How command-based restrictions work
Exact matching
:
Command arrays must match
exactly
- both the command and all arguments in the correct order
Example:
["npx", "-y", "server"]
will NOT match
["npx", "server"]
or
["npx", "-y", "server", "--flag"]
Stdio server behavior
:
When the allowlist contains
any
serverCommand
entries, stdio servers
must
match one of those commands
Stdio servers cannot pass by name alone when command restrictions are present
This ensures administrators can enforce which commands are allowed to run
Non-stdio server behavior
:
Remote servers (HTTP, SSE, WebSocket) use URL-based matching when
serverUrl
entries exist in the allowlist
If no URL entries exist, remote servers fall back to name-based matching
Command restrictions do not apply to remote servers
​
How URL-based restrictions work
URL patterns support wildcards using
*
to match any sequence of characters. This is useful for allowing entire domains or subdomains.
Wildcard examples
:
https://mcp.company.com/*
- Allow all paths on a specific domain
https://*.example.com/*
- Allow any subdomain of example.com
http://localhost:*/*
- Allow any port on localhost
Hostname matching is case-insensitive and ignores a trailing FQDN dot, matching DNS semantics. A pattern like
*://Mcp.Example.com/*
matches
https://mcp.example.com/api
, and
https://mcp.example.com.
is treated the same as
https://mcp.example.com
. Paths remain case-sensitive.
Remote server behavior
:
When the allowlist contains
any
serverUrl
entries, remote servers
must
match one of those URL patterns
Remote servers cannot pass by name alone when URL restrictions are present
This ensures administrators can enforce which remote endpoints are allowed
Example: URL-only allowlist
{
"allowedMcpServers"
: [
{
"serverUrl"
:
"https://mcp.company.com/*"
},
{
"serverUrl"
:
"https://*.internal.corp/*"
}
]
}
Result
:
HTTP server at
https://mcp.company.com/api
: ✅ Allowed (matches URL pattern)
HTTP server at
https://api.internal.corp/mcp
: ✅ Allowed (matches wildcard subdomain)
HTTP server at
https://external.com/mcp
: ❌ Blocked (doesn’t match any URL pattern)
Stdio server with any command: ❌ Blocked (no name or command entries to match)
Example: Command-only allowlist
{
"allowedMcpServers"
: [
{
"serverCommand"
: [
"npx"
,
"-y"
,
"approved-package"
] }
]
}
Result
:
Stdio server with
["npx", "-y", "approved-package"]
: ✅ Allowed (matches command)
Stdio server with
["node", "server.js"]
: ❌ Blocked (doesn’t match command)
HTTP server named “my-api”: ❌ Blocked (no name entries to match)
Example: Mixed name and command allowlist
{
"allowedMcpServers"
: [
{
"serverName"
:
"github"
},
{
"serverCommand"
: [
"npx"
,
"-y"
,
"approved-package"
] }
]
}
Result
:
Stdio server named “local-tool” with
["npx", "-y", "approved-package"]
: ✅ Allowed (matches command)
Stdio server named “local-tool” with
["node", "server.js"]
: ❌ Blocked (command entries exist but doesn’t match)
Stdio server named “github” with
["node", "server.js"]
: ❌ Blocked (stdio servers must match commands when command entries exist)
HTTP server named “github”: ✅ Allowed (matches name)
HTTP server named “other-api”: ❌ Blocked (name doesn’t match)
Example: Name-only allowlist
{
"allowedMcpServers"
: [
{
"serverName"
:
"github"
},
{
"serverName"
:
"internal-tool"
}
]
}
Result
:
Stdio server named “github” with any command: ✅ Allowed (no command restrictions)
Stdio server named “internal-tool” with any command: ✅ Allowed (no command restrictions)
HTTP server named “github”: ✅ Allowed (matches name)
Any server named “other”: ❌ Blocked (name doesn’t match)
​
Allowlist behavior (
allowedMcpServers
)
undefined
(default): No restrictions - users can configure any MCP server
Empty array
[]
: Complete lockdown - users cannot configure any MCP servers
List of entries: Users can only configure servers that match by name, command, or URL pattern
​
Denylist behavior (
deniedMcpServers
)
undefined
(default): No servers are blocked
Empty array
[]
: No servers are blocked
List of entries: Specified servers are explicitly blocked across all scopes
​
Important notes
Option 1 and Option 2 can be combined
: If
managed-mcp.json
exists, it has exclusive control and users cannot add servers. Allowlists/denylists still apply to the managed servers themselves.
Denylist takes absolute precedence
: If a server matches a denylist entry (by name, command, or URL), it will be blocked even if it’s on the allowlist
Name-based, command-based, and URL-based restrictions work together: a server passes if it matches
either
a name entry, a command entry, or a URL pattern (unless blocked by denylist)
When using
managed-mcp.json
: Users cannot add MCP servers through
claude mcp add
or configuration files. The
allowedMcpServers
and
deniedMcpServers
settings still apply to filter which managed servers are actually loaded.
Was this page helpful?
Yes
No
Isolate sessions with worktrees
Discover and install prebuilt plugins
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/mcp" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code in Slack</title>
  <link>https://code.claude.com/docs/en/slack</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/slack</guid>
  <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Claude Code in Slack
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (be...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Claude Code in Slack
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code in Slack brings the power of Claude Code directly into your Slack workspace. When you mention
@Claude
with a coding task, Claude automatically detects the intent and creates a Claude Code session on the web, allowing you to delegate development work without leaving your team conversations.
This integration is built on the existing Claude for Slack app but adds intelligent routing to Claude Code on the web for coding-related requests.
​
Use cases
Bug investigation and fixes
: Ask Claude to investigate and fix bugs as soon as they’re reported in Slack channels.
Quick code reviews and modifications
: Have Claude implement small features or refactor code based on team feedback.
Collaborative debugging
: When team discussions provide crucial context (e.g., error reproductions or user reports), Claude can use that information to inform its debugging approach.
Parallel task execution
: Kick off coding tasks in Slack while you continue other work, receiving notifications when complete.
​
Prerequisites
Before using Claude Code in Slack, ensure you have the following:
Requirement
Details
Claude Plan
Pro, Max, Team, or Enterprise with Claude Code access (premium seats or Chat + Claude Code seats)
Claude Code on the web
Access to
Claude Code on the web
must be enabled
GitHub Account
Connected to Claude Code on the web with at least one repository authenticated
Slack Authentication
Your Slack account linked to your Claude account via the Claude app
​
Setting up Claude Code in Slack
1
Install the Claude App in Slack
A workspace administrator must install the Claude app from the Slack App Marketplace. Visit the
Slack App Marketplace
and click “Add to Slack” to begin the installation process.
2
Connect your Claude account
After the app is installed, authenticate your individual Claude account:
Open the Claude app in Slack by clicking on “Claude” in your Apps section
Navigate to the App Home tab
Click “Connect” to link your Slack account with your Claude account
Complete the authentication flow in your browser
3
Configure Claude Code on the web
Ensure your Claude Code on the web is properly configured:
Visit
claude.ai/code
and sign in with the same account you connected to Slack
Connect your GitHub account if not already connected
Authenticate at least one repository that you want Claude to work with
4
Choose your routing mode
After connecting your accounts, configure how Claude handles your messages in Slack. Navigate to the Claude App Home in Slack to find the
Routing Mode
setting.
Mode
Behavior
Code only
Claude routes all @mentions to Claude Code sessions. Best for teams using Claude in Slack exclusively for development tasks.
Code + Chat
Claude analyzes each message and intelligently routes between Claude Code (for coding tasks) and Claude Chat (for writing, analysis, and general questions). Best for teams who want a single @Claude entry point for all types of work.
In Code + Chat mode, if Claude routes a message to Chat but you wanted a coding session, you can click “Retry as Code” to create a Claude Code session instead. Similarly, if it’s routed to Code but you wanted a Chat session, you can choose that option in that thread.
5
Add Claude to channels
Claude is not automatically added to any channels after installation. To use Claude in a channel, invite it by typing
/invite @Claude
in that channel. Claude can only respond to @mentions in channels where it has been added.
​
How it works
​
Automatic detection
When you mention @Claude in a Slack channel or thread, Claude automatically analyzes your message to determine if it’s a coding task. If Claude detects coding intent, it will route your request to Claude Code on the web instead of responding as a regular chat assistant.
You can also explicitly tell Claude to handle a request as a coding task, even if it doesn’t automatically detect it.
Claude Code in Slack only works in channels (public or private). It does not work in direct messages (DMs).
​
Context gathering
From threads
: When you @mention Claude in a thread, it gathers context from all messages in that thread to understand the full conversation.
From channels
: When mentioned directly in a channel, Claude looks at recent channel messages for relevant context.
This context helps Claude understand the problem, select the appropriate repository, and inform its approach to the task.
When @Claude is invoked in Slack, Claude is given access to the conversation context to better understand your request. Claude may follow directions from other messages in the context, so users should make sure to only use Claude in trusted Slack conversations.
​
Session flow
Initiation
: You @mention Claude with a coding request
Detection
: Claude analyzes your message and detects coding intent
Session creation
: A new Claude Code session is created on claude.ai/code
Progress updates
: Claude posts status updates to your Slack thread as work progresses
Completion
: When finished, Claude @mentions you with a summary and action buttons
Review
: Click “View Session” to see the full transcript, or “Create PR” to open a pull request
​
User interface elements
​
App Home
The App Home tab shows your connection status and allows you to connect or disconnect your Claude account from Slack.
​
Message actions
View Session
: Opens the full Claude Code session in your browser where you can see all work performed, continue the session, or make additional requests.
Create PR
: Creates a pull request directly from the session’s changes.
Retry as Code
: If Claude initially responds as a chat assistant but you wanted a coding session, click this button to retry the request as a Claude Code task.
Change Repo
: Allows you to select a different repository if Claude chose incorrectly.
​
Repository selection
Claude automatically selects a repository based on context from your Slack conversation. If multiple repositories could apply, Claude may display a dropdown allowing you to choose the correct one.
​
Access and permissions
​
User-level access
Access Type
Requirement
Claude Code Sessions
Each user runs sessions under their own Claude account
Usage & Rate Limits
Sessions count against the individual user’s plan limits
Repository Access
Users can only access repositories they’ve personally connected
Session History
Sessions appear in your Claude Code history on claude.ai/code
​
Workspace-level access
Slack workspace administrators control whether the Claude app is available in their workspace:
Control
Description
App installation
Workspace admins decide whether to install the Claude app from the Slack App Marketplace
Enterprise Grid distribution
For Enterprise Grid organizations, organization admins can control which workspaces have access to the Claude app
App removal
Removing the app from a workspace immediately revokes access for all users in that workspace
​
Channel-based access control
Claude is not automatically added to any channels after installation. Users must explicitly invite Claude to channels where they want to use it:
Invite required
: Type
/invite @Claude
in any channel to add Claude to that channel
Channel membership controls access
: Claude can only respond to @mentions in channels where it has been added
Access gating through channels
: Admins can control who uses Claude Code by managing which channels Claude is invited to and who has access to those channels
Private channel support
: Claude works in both public and private channels, giving teams flexibility in controlling visibility
This channel-based model allows teams to restrict Claude Code usage to specific channels, providing an additional layer of access control beyond workspace-level permissions.
​
What’s accessible where
In Slack
: You’ll see status updates, completion summaries, and action buttons. The full transcript is preserved and always accessible.
On the web
: The complete Claude Code session with full conversation history, all code changes, file operations, and the ability to continue the session or create pull requests.
For Enterprise and Team accounts, sessions created from Claude in Slack are
automatically visible to the organization. See
Claude Code on the Web sharing
for more details.
​
Best practices
​
Writing effective requests
Be specific
: Include file names, function names, or error messages when relevant.
Provide context
: Mention the repository or project if it’s not clear from the conversation.
Define success
: Explain what “done” looks like—should Claude write tests? Update documentation? Create a PR?
Use threads
: Reply in threads when discussing bugs or features so Claude can gather the full context.
​
When to use Slack vs. web
Use Slack when
: Context already exists in a Slack discussion, you want to kick off a task asynchronously, or you’re collaborating with teammates who need visibility.
Use the web directly when
: You need to upload files, want real-time interaction during development, or are working on longer, more complex tasks.
​
Troubleshooting
​
Sessions not starting
Verify your Claude account is connected in the Claude App Home
Check that you have Claude Code on the web access enabled
Ensure you have at least one GitHub repository connected to Claude Code
​
Repository not showing
Connect the repository in Claude Code on the web at
claude.ai/code
Verify your GitHub permissions for that repository
Try disconnecting and reconnecting your GitHub account
​
Wrong repository selected
Click the “Change Repo” button to select a different repository
Include the repository name in your request for more accurate selection
​
Authentication errors
Disconnect and reconnect your Claude account in the App Home
Ensure you’re signed into the correct Claude account in your browser
Check that your Claude plan includes Claude Code access
​
Session expiration
Sessions remain accessible in your Claude Code history on the web
You can continue or reference past sessions from
claude.ai/code
​
Current limitations
GitHub only
: Currently supports repositories on GitHub.
One PR at a time
: Each session can create one pull request.
Rate limits apply
: Sessions use your individual Claude plan’s rate limits.
Web access required
: Users must have Claude Code on the web access; those without it will only get standard Claude chat responses.
​
Related resources
Claude Code on the web
Learn more about Claude Code on the web
Claude for Slack
General Claude for Slack documentation
Slack App Marketplace
Install the Claude app from the Slack Marketplace
Claude Help Center
Get additional support
Was this page helpful?
Yes
No
GitLab CI/CD
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/slack" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Claude Code in Slack
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (be...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Claude Code in Slack
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code in Slack brings the power of Claude Code directly into your Slack workspace. When you mention
@Claude
with a coding task, Claude automatically detects the intent and creates a Claude Code session on the web, allowing you to delegate development work without leaving your team conversations.
This integration is built on the existing Claude for Slack app but adds intelligent routing to Claude Code on the web for coding-related requests.
​
Use cases
Bug investigation and fixes
: Ask Claude to investigate and fix bugs as soon as they’re reported in Slack channels.
Quick code reviews and modifications
: Have Claude implement small features or refactor code based on team feedback.
Collaborative debugging
: When team discussions provide crucial context (e.g., error reproductions or user reports), Claude can use that information to inform its debugging approach.
Parallel task execution
: Kick off coding tasks in Slack while you continue other work, receiving notifications when complete.
​
Prerequisites
Before using Claude Code in Slack, ensure you have the following:
Requirement
Details
Claude Plan
Pro, Max, Team, or Enterprise with Claude Code access (premium seats or Chat + Claude Code seats)
Claude Code on the web
Access to
Claude Code on the web
must be enabled
GitHub Account
Connected to Claude Code on the web with at least one repository authenticated
Slack Authentication
Your Slack account linked to your Claude account via the Claude app
​
Setting up Claude Code in Slack
1
Install the Claude App in Slack
A workspace administrator must install the Claude app from the Slack App Marketplace. Visit the
Slack App Marketplace
and click “Add to Slack” to begin the installation process.
2
Connect your Claude account
After the app is installed, authenticate your individual Claude account:
Open the Claude app in Slack by clicking on “Claude” in your Apps section
Navigate to the App Home tab
Click “Connect” to link your Slack account with your Claude account
Complete the authentication flow in your browser
3
Configure Claude Code on the web
Ensure your Claude Code on the web is properly configured:
Visit
claude.ai/code
and sign in with the same account you connected to Slack
Connect your GitHub account if not already connected
Authenticate at least one repository that you want Claude to work with
4
Choose your routing mode
After connecting your accounts, configure how Claude handles your messages in Slack. Navigate to the Claude App Home in Slack to find the
Routing Mode
setting.
Mode
Behavior
Code only
Claude routes all @mentions to Claude Code sessions. Best for teams using Claude in Slack exclusively for development tasks.
Code + Chat
Claude analyzes each message and intelligently routes between Claude Code (for coding tasks) and Claude Chat (for writing, analysis, and general questions). Best for teams who want a single @Claude entry point for all types of work.
In Code + Chat mode, if Claude routes a message to Chat but you wanted a coding session, you can click “Retry as Code” to create a Claude Code session instead. Similarly, if it’s routed to Code but you wanted a Chat session, you can choose that option in that thread.
5
Add Claude to channels
Claude is not automatically added to any channels after installation. To use Claude in a channel, invite it by typing
/invite @Claude
in that channel. Claude can only respond to @mentions in channels where it has been added.
​
How it works
​
Automatic detection
When you mention @Claude in a Slack channel or thread, Claude automatically analyzes your message to determine if it’s a coding task. If Claude detects coding intent, it will route your request to Claude Code on the web instead of responding as a regular chat assistant.
You can also explicitly tell Claude to handle a request as a coding task, even if it doesn’t automatically detect it.
Claude Code in Slack only works in channels (public or private). It does not work in direct messages (DMs).
​
Context gathering
From threads
: When you @mention Claude in a thread, it gathers context from all messages in that thread to understand the full conversation.
From channels
: When mentioned directly in a channel, Claude looks at recent channel messages for relevant context.
This context helps Claude understand the problem, select the appropriate repository, and inform its approach to the task.
When @Claude is invoked in Slack, Claude is given access to the conversation context to better understand your request. Claude may follow directions from other messages in the context, so users should make sure to only use Claude in trusted Slack conversations.
​
Session flow
Initiation
: You @mention Claude with a coding request
Detection
: Claude analyzes your message and detects coding intent
Session creation
: A new Claude Code session is created on claude.ai/code
Progress updates
: Claude posts status updates to your Slack thread as work progresses
Completion
: When finished, Claude @mentions you with a summary and action buttons
Review
: Click “View Session” to see the full transcript, or “Create PR” to open a pull request
​
User interface elements
​
App Home
The App Home tab shows your connection status and allows you to connect or disconnect your Claude account from Slack.
​
Message actions
View Session
: Opens the full Claude Code session in your browser where you can see all work performed, continue the session, or make additional requests.
Create PR
: Creates a pull request directly from the session’s changes.
Retry as Code
: If Claude initially responds as a chat assistant but you wanted a coding session, click this button to retry the request as a Claude Code task.
Change Repo
: Allows you to select a different repository if Claude chose incorrectly.
​
Repository selection
Claude automatically selects a repository based on context from your Slack conversation. If multiple repositories could apply, Claude may display a dropdown allowing you to choose the correct one.
​
Access and permissions
​
User-level access
Access Type
Requirement
Claude Code Sessions
Each user runs sessions under their own Claude account
Usage & Rate Limits
Sessions count against the individual user’s plan limits
Repository Access
Users can only access repositories they’ve personally connected
Session History
Sessions appear in your Claude Code history on claude.ai/code
​
Workspace-level access
Slack workspace administrators control whether the Claude app is available in their workspace:
Control
Description
App installation
Workspace admins decide whether to install the Claude app from the Slack App Marketplace
Enterprise Grid distribution
For Enterprise Grid organizations, organization admins can control which workspaces have access to the Claude app
App removal
Removing the app from a workspace immediately revokes access for all users in that workspace
​
Channel-based access control
Claude is not automatically added to any channels after installation. Users must explicitly invite Claude to channels where they want to use it:
Invite required
: Type
/invite @Claude
in any channel to add Claude to that channel
Channel membership controls access
: Claude can only respond to @mentions in channels where it has been added
Access gating through channels
: Admins can control who uses Claude Code by managing which channels Claude is invited to and who has access to those channels
Private channel support
: Claude works in both public and private channels, giving teams flexibility in controlling visibility
This channel-based model allows teams to restrict Claude Code usage to specific channels, providing an additional layer of access control beyond workspace-level permissions.
​
What’s accessible where
In Slack
: You’ll see status updates, completion summaries, and action buttons. The full transcript is preserved and always accessible.
On the web
: The complete Claude Code session with full conversation history, all code changes, file operations, and the ability to continue the session or create pull requests.
For Enterprise and Team accounts, sessions created from Claude in Slack are
automatically visible to the organization. See
Claude Code on the Web sharing
for more details.
​
Best practices
​
Writing effective requests
Be specific
: Include file names, function names, or error messages when relevant.
Provide context
: Mention the repository or project if it’s not clear from the conversation.
Define success
: Explain what “done” looks like—should Claude write tests? Update documentation? Create a PR?
Use threads
: Reply in threads when discussing bugs or features so Claude can gather the full context.
​
When to use Slack vs. web
Use Slack when
: Context already exists in a Slack discussion, you want to kick off a task asynchronously, or you’re collaborating with teammates who need visibility.
Use the web directly when
: You need to upload files, want real-time interaction during development, or are working on longer, more complex tasks.
​
Troubleshooting
​
Sessions not starting
Verify your Claude account is connected in the Claude App Home
Check that you have Claude Code on the web access enabled
Ensure you have at least one GitHub repository connected to Claude Code
​
Repository not showing
Connect the repository in Claude Code on the web at
claude.ai/code
Verify your GitHub permissions for that repository
Try disconnecting and reconnecting your GitHub account
​
Wrong repository selected
Click the “Change Repo” button to select a different repository
Include the repository name in your request for more accurate selection
​
Authentication errors
Disconnect and reconnect your Claude account in the App Home
Ensure you’re signed into the correct Claude account in your browser
Check that your Claude plan includes Claude Code access
​
Session expiration
Sessions remain accessible in your Claude Code history on the web
You can continue or reference past sessions from
claude.ai/code
​
Current limitations
GitHub only
: Currently supports repositories on GitHub.
One PR at a time
: Each session can create one pull request.
Rate limits apply
: Sessions use your individual Claude plan’s rate limits.
Web access required
: Users must have Claude Code on the web access; those without it will only get standard Claude chat responses.
​
Related resources
Claude Code on the web
Learn more about Claude Code on the web
Claude for Slack
General Claude for Slack documentation
Slack App Marketplace
Install the Claude app from the Slack Marketplace
Claude Help Center
Get additional support
Was this page helpful?
Yes
No
GitLab CI/CD
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/slack" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Connect to external tools with MCP</title>
  <link>https://code.claude.com/docs/en/agent-sdk/mcp</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/mcp</guid>
  <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Connect to external tools with MCP
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Connect to external tools with MCP
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The
Model Context Protocol (MCP)
is an open standard for connecting AI agents to external tools and data sources. With MCP, your agent can query databases, integrate with APIs like Slack and GitHub, and connect to other services without writing custom tool implementations.
MCP servers can run as local processes, connect over HTTP, or execute directly within your SDK application.
This page covers MCP configuration for the Agent SDK. To add MCP servers to the Claude Code CLI so they load in every project, see
MCP installation scopes
.
​
Quickstart
This example connects to the
Claude Code documentation
MCP server using
HTTP transport
and uses
allowedTools
with a wildcard to permit all tools from the server.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Use the docs MCP server to explain what hooks are in Claude Code"
,
options:
{
mcpServers:
{
"claude-code-docs"
:
{
type:
"http"
,
url:
"https://code.claude.com/docs/mcp"
}
},
allowedTools:
[
"mcp__claude-code-docs__*"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
The agent connects to the documentation server, searches for information about hooks, and returns the results.
​
Add an MCP server
You can configure MCP servers in code when calling
query()
, or in a
.mcp.json
file loaded via
settingSources
.
​
In code
Pass MCP servers directly in the
mcpServers
option:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"List files in my project"
,
options:
{
mcpServers:
{
filesystem:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-filesystem"
,
"/Users/me/projects"
]
}
},
allowedTools:
[
"mcp__filesystem__*"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
From a config file
Create a
.mcp.json
file at your project root. The file is picked up when the
project
setting source is enabled, which it is for default
query()
options. If you set
settingSources
explicitly, include
"project"
for this file to load:
{
"mcpServers"
: {
"filesystem"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-filesystem"
,
"/Users/me/projects"
]
}
}
}
​
Allow MCP tools
MCP tools require explicit permission before Claude can use them. Without permission, Claude will see that tools are available but won’t be able to call them.
​
Tool naming convention
MCP tools follow the naming pattern
mcp__<server-name>__<tool-name>
. For example, a GitHub server named
"github"
with a
list_issues
tool becomes
mcp__github__list_issues
.
​
Grant access with allowedTools
Use
allowedTools
to specify which MCP tools Claude can use:
const
_
=
{
options:
{
mcpServers:
{
// your servers
},
allowedTools:
[
"mcp__github__*"
,
// All tools from the github server
"mcp__db__query"
,
// Only the query tool from db server
"mcp__slack__send_message"
// Only send_message from slack server
]
}
};
Wildcards (
*
) let you allow all tools from a server without listing each one individually.
Prefer
allowedTools
over permission modes for MCP access.
permissionMode: "acceptEdits"
does not auto-approve MCP tools (only file edits and filesystem Bash commands).
permissionMode: "bypassPermissions"
does auto-approve MCP tools but also disables all other safety prompts, which is broader than necessary. A wildcard in
allowedTools
grants exactly the MCP server you want and nothing more. See
Permission modes
for a full comparison.
​
Discover available tools
To see what tools an MCP server provides, check the server’s documentation or connect to the server and inspect the
system
init message:
for
await
(
const
message
of
query
({
prompt:
"..."
,
options
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"Available MCP tools:"
,
message
.
mcp_servers
);
}
}
​
Transport types
MCP servers communicate with your agent using different transport protocols. Check the server’s documentation to see which transport it supports:
If the docs give you a
command to run
(like
npx @modelcontextprotocol/server-github
), use stdio
If the docs give you a
URL
, use HTTP or SSE
If you’re building your own tools in code, use an SDK MCP server
​
stdio servers
Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
,
"mcp__github__search_issues"
]
}
};
{
"mcpServers"
: {
"github"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-github"
],
"env"
: {
"GITHUB_TOKEN"
:
"${GITHUB_TOKEN}"
}
}
}
}
​
HTTP/SSE servers
Use HTTP or SSE for cloud-hosted MCP servers and remote APIs:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
"remote-api"
:
{
type:
"sse"
,
url:
"https://api.example.com/mcp/sse"
,
headers:
{
Authorization:
`Bearer
${
process
.
env
.
API_TOKEN
}
`
}
}
},
allowedTools:
[
"mcp__remote-api__*"
]
}
};
{
"mcpServers"
: {
"remote-api"
: {
"type"
:
"sse"
,
"url"
:
"https://api.example.com/mcp/sse"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_TOKEN}"
}
}
}
}
For the streamable HTTP transport, use
"type": "http"
instead. In
.mcp.json
and other JSON config files,
"streamable-http"
is accepted as an alias for
"http"
. The programmatic
mcpServers
option accepts only
"http"
.
​
SDK MCP servers
Define custom tools directly in your application code instead of running a separate server process. See the
custom tools guide
for implementation details.
​
MCP tool search
When you have many MCP tools configured, tool definitions can consume a significant portion of your context window. Tool search solves this by withholding tool definitions from context and loading only the ones Claude needs for each turn.
Tool search is enabled by default. See
Tool search
for configuration options and details.
For more detail, including best practices and using tool search with custom SDK tools, see the
tool search guide
.
​
Authentication
Most MCP servers require authentication to access external services. Pass credentials through environment variables in the server configuration.
​
Pass credentials via environment variables
Use the
env
field to pass API keys, tokens, and other credentials to the MCP server:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
]
}
};
{
"mcpServers"
: {
"github"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-github"
],
"env"
: {
"GITHUB_TOKEN"
:
"${GITHUB_TOKEN}"
}
}
}
}
The
${GITHUB_TOKEN}
syntax expands environment variables at runtime.
See
List issues from a repository
for a complete working example with debug logging.
​
HTTP headers for remote servers
For HTTP and SSE servers, pass authentication headers directly in the server configuration:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
"secure-api"
:
{
type:
"http"
,
url:
"https://api.example.com/mcp"
,
headers:
{
Authorization:
`Bearer
${
process
.
env
.
API_TOKEN
}
`
}
}
},
allowedTools:
[
"mcp__secure-api__*"
]
}
};
{
"mcpServers"
: {
"secure-api"
: {
"type"
:
"http"
,
"url"
:
"https://api.example.com/mcp"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_TOKEN}"
}
}
}
}
The
${API_TOKEN}
syntax expands environment variables at runtime.
​
OAuth2 authentication
The
MCP specification supports OAuth 2.1
for authorization. The SDK doesn’t handle OAuth flows automatically, but you can pass access tokens via headers after completing the OAuth flow in your application:
TypeScript
Python
// After completing OAuth flow in your app
const
accessToken
=
await
getAccessTokenFromOAuthFlow
();
const
options
=
{
mcpServers:
{
"oauth-api"
:
{
type:
"http"
,
url:
"https://api.example.com/mcp"
,
headers:
{
Authorization:
`Bearer
${
accessToken
}
`
}
}
},
allowedTools:
[
"mcp__oauth-api__*"
]
};
​
Examples
​
List issues from a repository
This example connects to the
GitHub MCP server
to list recent issues. The example includes debug logging to verify the MCP connection and tool calls.
Before running, create a
GitHub personal access token
with
repo
scope and set it as an environment variable:
export
GITHUB_TOKEN
=
ghp_xxxxxxxxxxxxxxxxxxxx
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"List the 3 most recent issues in anthropics/claude-code"
,
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
]
}
})) {
// Verify MCP server connected successfully
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"MCP servers:"
,
message
.
mcp_servers
);
}
// Log when Claude calls an MCP tool
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
.
startsWith
(
"mcp__"
)) {
console
.
log
(
"MCP tool called:"
,
block
.
name
);
}
}
}
// Print the final result
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Query a database
This example uses the
Postgres MCP server
to query a database. The connection string is passed as an argument to the server. The agent automatically discovers the database schema, writes the SQL query, and returns the results:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Connection string from environment variable
const
connectionString
=
process
.
env
.
DATABASE_URL
;
for
await
(
const
message
of
query
({
// Natural language query - Claude writes the SQL
prompt:
"How many users signed up last week? Break it down by day."
,
options:
{
mcpServers:
{
postgres:
{
command:
"npx"
,
// Pass connection string as argument to the server
args:
[
"-y"
,
"@modelcontextprotocol/server-postgres"
,
connectionString
]
}
},
// Allow only read queries, not writes
allowedTools:
[
"mcp__postgres__query"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Error handling
MCP servers can fail to connect for various reasons: the server process might not be installed, credentials might be invalid, or a remote server might be unreachable.
The SDK emits a
system
message with subtype
init
at the start of each query. This message includes the connection status for each MCP server. Check the
status
field to detect connection failures before the agent starts working:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Process data"
,
options:
{
mcpServers:
{
"data-processor"
:
dataServer
}
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
const
failedServers
=
message
.
mcp_servers
.
filter
((
s
)
=>
s
.
status
!==
"connected"
);
if
(
failedServers
.
length
>
0
) {
console
.
warn
(
"Failed to connect:"
,
failedServers
);
}
}
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"error_during_execution"
) {
console
.
error
(
"Execution failed"
);
}
}
​
Troubleshooting
​
Server shows “failed” status
Check the
init
message to see which servers failed to connect:
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
for
(
const
server
of
message
.
mcp_servers
) {
if
(
server
.
status
===
"failed"
) {
console
.
error
(
`Server
${
server
.
name
}
failed to connect`
);
}
}
}
Common causes:
Missing environment variables
: Ensure required tokens and credentials are set. For stdio servers, check the
env
field matches what the server expects.
Server not installed
: For
npx
commands, verify the package exists and Node.js is in your PATH.
Invalid connection string
: For database servers, verify the connection string format and that the database is accessible.
Network issues
: For remote HTTP/SSE servers, check the URL is reachable and any firewalls allow the connection.
​
Tools not being called
If Claude sees tools but doesn’t use them, check that you’ve granted permission with
allowedTools
:
const
_
=
{
options:
{
mcpServers:
{
// your servers
},
allowedTools:
[
"mcp__servername__*"
]
// Required for Claude to use the tools
}
};
​
Connection timeouts
The MCP SDK has a default timeout of 60 seconds for server connections. If your server takes longer to start, the connection will fail. For servers that need more startup time, consider:
Using a lighter-weight server if available
Pre-warming the server before starting your agent
Checking server logs for slow initialization causes
​
Related resources
Custom tools guide
: Build your own MCP server that runs in-process with your SDK application
Permissions
: Control which MCP tools your agent can use with
allowedTools
and
disallowedTools
TypeScript SDK reference
: Full API reference including MCP configuration options
Python SDK reference
: Full API reference including MCP configuration options
MCP server directory
: Browse available MCP servers for databases, APIs, and more
Was this page helpful?
Yes
No
Give Claude custom tools
Scale to many tools with tool search
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/mcp" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Connect to external tools with MCP
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Connect to external tools with MCP
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The
Model Context Protocol (MCP)
is an open standard for connecting AI agents to external tools and data sources. With MCP, your agent can query databases, integrate with APIs like Slack and GitHub, and connect to other services without writing custom tool implementations.
MCP servers can run as local processes, connect over HTTP, or execute directly within your SDK application.
This page covers MCP configuration for the Agent SDK. To add MCP servers to the Claude Code CLI so they load in every project, see
MCP installation scopes
.
​
Quickstart
This example connects to the
Claude Code documentation
MCP server using
HTTP transport
and uses
allowedTools
with a wildcard to permit all tools from the server.
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Use the docs MCP server to explain what hooks are in Claude Code"
,
options:
{
mcpServers:
{
"claude-code-docs"
:
{
type:
"http"
,
url:
"https://code.claude.com/docs/mcp"
}
},
allowedTools:
[
"mcp__claude-code-docs__*"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
The agent connects to the documentation server, searches for information about hooks, and returns the results.
​
Add an MCP server
You can configure MCP servers in code when calling
query()
, or in a
.mcp.json
file loaded via
settingSources
.
​
In code
Pass MCP servers directly in the
mcpServers
option:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"List files in my project"
,
options:
{
mcpServers:
{
filesystem:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-filesystem"
,
"/Users/me/projects"
]
}
},
allowedTools:
[
"mcp__filesystem__*"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
From a config file
Create a
.mcp.json
file at your project root. The file is picked up when the
project
setting source is enabled, which it is for default
query()
options. If you set
settingSources
explicitly, include
"project"
for this file to load:
{
"mcpServers"
: {
"filesystem"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-filesystem"
,
"/Users/me/projects"
]
}
}
}
​
Allow MCP tools
MCP tools require explicit permission before Claude can use them. Without permission, Claude will see that tools are available but won’t be able to call them.
​
Tool naming convention
MCP tools follow the naming pattern
mcp__<server-name>__<tool-name>
. For example, a GitHub server named
"github"
with a
list_issues
tool becomes
mcp__github__list_issues
.
​
Grant access with allowedTools
Use
allowedTools
to specify which MCP tools Claude can use:
const
_
=
{
options:
{
mcpServers:
{
// your servers
},
allowedTools:
[
"mcp__github__*"
,
// All tools from the github server
"mcp__db__query"
,
// Only the query tool from db server
"mcp__slack__send_message"
// Only send_message from slack server
]
}
};
Wildcards (
*
) let you allow all tools from a server without listing each one individually.
Prefer
allowedTools
over permission modes for MCP access.
permissionMode: "acceptEdits"
does not auto-approve MCP tools (only file edits and filesystem Bash commands).
permissionMode: "bypassPermissions"
does auto-approve MCP tools but also disables all other safety prompts, which is broader than necessary. A wildcard in
allowedTools
grants exactly the MCP server you want and nothing more. See
Permission modes
for a full comparison.
​
Discover available tools
To see what tools an MCP server provides, check the server’s documentation or connect to the server and inspect the
system
init message:
for
await
(
const
message
of
query
({
prompt:
"..."
,
options
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"Available MCP tools:"
,
message
.
mcp_servers
);
}
}
​
Transport types
MCP servers communicate with your agent using different transport protocols. Check the server’s documentation to see which transport it supports:
If the docs give you a
command to run
(like
npx @modelcontextprotocol/server-github
), use stdio
If the docs give you a
URL
, use HTTP or SSE
If you’re building your own tools in code, use an SDK MCP server
​
stdio servers
Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
,
"mcp__github__search_issues"
]
}
};
{
"mcpServers"
: {
"github"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-github"
],
"env"
: {
"GITHUB_TOKEN"
:
"${GITHUB_TOKEN}"
}
}
}
}
​
HTTP/SSE servers
Use HTTP or SSE for cloud-hosted MCP servers and remote APIs:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
"remote-api"
:
{
type:
"sse"
,
url:
"https://api.example.com/mcp/sse"
,
headers:
{
Authorization:
`Bearer
${
process
.
env
.
API_TOKEN
}
`
}
}
},
allowedTools:
[
"mcp__remote-api__*"
]
}
};
{
"mcpServers"
: {
"remote-api"
: {
"type"
:
"sse"
,
"url"
:
"https://api.example.com/mcp/sse"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_TOKEN}"
}
}
}
}
For the streamable HTTP transport, use
"type": "http"
instead. In
.mcp.json
and other JSON config files,
"streamable-http"
is accepted as an alias for
"http"
. The programmatic
mcpServers
option accepts only
"http"
.
​
SDK MCP servers
Define custom tools directly in your application code instead of running a separate server process. See the
custom tools guide
for implementation details.
​
MCP tool search
When you have many MCP tools configured, tool definitions can consume a significant portion of your context window. Tool search solves this by withholding tool definitions from context and loading only the ones Claude needs for each turn.
Tool search is enabled by default. See
Tool search
for configuration options and details.
For more detail, including best practices and using tool search with custom SDK tools, see the
tool search guide
.
​
Authentication
Most MCP servers require authentication to access external services. Pass credentials through environment variables in the server configuration.
​
Pass credentials via environment variables
Use the
env
field to pass API keys, tokens, and other credentials to the MCP server:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
]
}
};
{
"mcpServers"
: {
"github"
: {
"command"
:
"npx"
,
"args"
: [
"-y"
,
"@modelcontextprotocol/server-github"
],
"env"
: {
"GITHUB_TOKEN"
:
"${GITHUB_TOKEN}"
}
}
}
}
The
${GITHUB_TOKEN}
syntax expands environment variables at runtime.
See
List issues from a repository
for a complete working example with debug logging.
​
HTTP headers for remote servers
For HTTP and SSE servers, pass authentication headers directly in the server configuration:
In code
.mcp.json
TypeScript
Python
const
_
=
{
options:
{
mcpServers:
{
"secure-api"
:
{
type:
"http"
,
url:
"https://api.example.com/mcp"
,
headers:
{
Authorization:
`Bearer
${
process
.
env
.
API_TOKEN
}
`
}
}
},
allowedTools:
[
"mcp__secure-api__*"
]
}
};
{
"mcpServers"
: {
"secure-api"
: {
"type"
:
"http"
,
"url"
:
"https://api.example.com/mcp"
,
"headers"
: {
"Authorization"
:
"Bearer ${API_TOKEN}"
}
}
}
}
The
${API_TOKEN}
syntax expands environment variables at runtime.
​
OAuth2 authentication
The
MCP specification supports OAuth 2.1
for authorization. The SDK doesn’t handle OAuth flows automatically, but you can pass access tokens via headers after completing the OAuth flow in your application:
TypeScript
Python
// After completing OAuth flow in your app
const
accessToken
=
await
getAccessTokenFromOAuthFlow
();
const
options
=
{
mcpServers:
{
"oauth-api"
:
{
type:
"http"
,
url:
"https://api.example.com/mcp"
,
headers:
{
Authorization:
`Bearer
${
accessToken
}
`
}
}
},
allowedTools:
[
"mcp__oauth-api__*"
]
};
​
Examples
​
List issues from a repository
This example connects to the
GitHub MCP server
to list recent issues. The example includes debug logging to verify the MCP connection and tool calls.
Before running, create a
GitHub personal access token
with
repo
scope and set it as an environment variable:
export
GITHUB_TOKEN
=
ghp_xxxxxxxxxxxxxxxxxxxx
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"List the 3 most recent issues in anthropics/claude-code"
,
options:
{
mcpServers:
{
github:
{
command:
"npx"
,
args:
[
"-y"
,
"@modelcontextprotocol/server-github"
],
env:
{
GITHUB_TOKEN:
process
.
env
.
GITHUB_TOKEN
}
}
},
allowedTools:
[
"mcp__github__list_issues"
]
}
})) {
// Verify MCP server connected successfully
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
console
.
log
(
"MCP servers:"
,
message
.
mcp_servers
);
}
// Log when Claude calls an MCP tool
if
(
message
.
type
===
"assistant"
) {
for
(
const
block
of
message
.
message
.
content
) {
if
(
block
.
type
===
"tool_use"
&&
block
.
name
.
startsWith
(
"mcp__"
)) {
console
.
log
(
"MCP tool called:"
,
block
.
name
);
}
}
}
// Print the final result
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Query a database
This example uses the
Postgres MCP server
to query a database. The connection string is passed as an argument to the server. The agent automatically discovers the database schema, writes the SQL query, and returns the results:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Connection string from environment variable
const
connectionString
=
process
.
env
.
DATABASE_URL
;
for
await
(
const
message
of
query
({
// Natural language query - Claude writes the SQL
prompt:
"How many users signed up last week? Break it down by day."
,
options:
{
mcpServers:
{
postgres:
{
command:
"npx"
,
// Pass connection string as argument to the server
args:
[
"-y"
,
"@modelcontextprotocol/server-postgres"
,
connectionString
]
}
},
// Allow only read queries, not writes
allowedTools:
[
"mcp__postgres__query"
]
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
​
Error handling
MCP servers can fail to connect for various reasons: the server process might not be installed, credentials might be invalid, or a remote server might be unreachable.
The SDK emits a
system
message with subtype
init
at the start of each query. This message includes the connection status for each MCP server. Check the
status
field to detect connection failures before the agent starts working:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Process data"
,
options:
{
mcpServers:
{
"data-processor"
:
dataServer
}
}
})) {
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
const
failedServers
=
message
.
mcp_servers
.
filter
((
s
)
=>
s
.
status
!==
"connected"
);
if
(
failedServers
.
length
>
0
) {
console
.
warn
(
"Failed to connect:"
,
failedServers
);
}
}
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"error_during_execution"
) {
console
.
error
(
"Execution failed"
);
}
}
​
Troubleshooting
​
Server shows “failed” status
Check the
init
message to see which servers failed to connect:
if
(
message
.
type
===
"system"
&&
message
.
subtype
===
"init"
) {
for
(
const
server
of
message
.
mcp_servers
) {
if
(
server
.
status
===
"failed"
) {
console
.
error
(
`Server
${
server
.
name
}
failed to connect`
);
}
}
}
Common causes:
Missing environment variables
: Ensure required tokens and credentials are set. For stdio servers, check the
env
field matches what the server expects.
Server not installed
: For
npx
commands, verify the package exists and Node.js is in your PATH.
Invalid connection string
: For database servers, verify the connection string format and that the database is accessible.
Network issues
: For remote HTTP/SSE servers, check the URL is reachable and any firewalls allow the connection.
​
Tools not being called
If Claude sees tools but doesn’t use them, check that you’ve granted permission with
allowedTools
:
const
_
=
{
options:
{
mcpServers:
{
// your servers
},
allowedTools:
[
"mcp__servername__*"
]
// Required for Claude to use the tools
}
};
​
Connection timeouts
The MCP SDK has a default timeout of 60 seconds for server connections. If your server takes longer to start, the connection will fail. For servers that need more startup time, consider:
Using a lighter-weight server if available
Pre-warming the server before starting your agent
Checking server logs for slow initialization causes
​
Related resources
Custom tools guide
: Build your own MCP server that runs in-process with your SDK application
Permissions
: Control which MCP tools your agent can use with
allowedTools
and
disallowedTools
TypeScript SDK reference
: Full API reference including MCP configuration options
Python SDK reference
: Full API reference including MCP configuration options
MCP server directory
: Browse available MCP servers for databases, APIs, and more
Was this page helpful?
Yes
No
Give Claude custom tools
Scale to many tools with tool search
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/mcp" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Track team usage with analytics</title>
  <link>https://code.claude.com/docs/en/analytics</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/analytics</guid>
  <pubDate>Sun, 17 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Track team usage with analytics
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin m...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Track team usage with analytics
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code provides analytics dashboards to help organizations understand developer usage patterns, track contribution metrics, and measure how Claude Code impacts engineering velocity. Access the dashboard for your plan:
Plan
Dashboard URL
Includes
Read more
Claude for Teams / Enterprise
claude.ai/analytics/claude-code
Usage metrics, contribution metrics with GitHub integration, leaderboard, data export
Details
API (Claude Console)
platform.claude.com/claude-code
Usage metrics, spend tracking, team insights
Details
​
Access analytics for Team and Enterprise
Navigate to
claude.ai/analytics/claude-code
. Admins and Owners can view the dashboard.
The Team and Enterprise dashboard includes:
Usage metrics
: lines of code accepted, suggestion accept rate, daily active users and sessions
Contribution metrics
: PRs and lines of code shipped with Claude Code assistance, with
GitHub integration
Leaderboard
: top contributors ranked by Claude Code usage
Data export
: download contribution data as CSV for custom reporting
For per-user token counts and cost estimates, configure
OpenTelemetry export
.
​
Enable contribution metrics
Contribution metrics are in public beta and available on Claude for Teams and Claude for Enterprise plans. These metrics only cover users within your claude.ai organization. Usage through the Claude Console API or third-party integrations is not included.
Usage and adoption data is available for all Claude for Teams and Claude for Enterprise accounts. Contribution metrics require additional setup to connect your GitHub organization.
You need the Owner role to configure analytics settings. A GitHub admin must install the GitHub app.
Contribution metrics are not available for organizations with
Zero Data Retention
enabled. The analytics dashboard will show usage metrics only.
1
Install the GitHub app
A GitHub admin installs the Claude GitHub app on your organization’s GitHub account at
github.com/apps/claude
.
2
Enable Claude Code analytics
A Claude Owner navigates to
claude.ai/admin-settings/claude-code
and enables the Claude Code analytics feature.
3
Enable GitHub analytics
On the same page, enable the “GitHub analytics” toggle.
4
Authenticate with GitHub
Complete the GitHub authentication flow and select which GitHub organizations to include in the analysis.
Data typically appears within 24 hours after enabling, with daily updates. If no data appears, you may see one of these messages:
“GitHub app required”
: install the GitHub app to view contribution metrics
“Data processing in progress”
: check back in a few days and confirm the GitHub app is installed if data doesn’t appear
Contribution metrics support GitHub Cloud and GitHub Enterprise Server.
​
Review summary metrics
These metrics are deliberately conservative and represent an underestimate of Claude Code’s actual impact. Only lines and PRs where there is high confidence in Claude Code’s involvement are counted.
The dashboard displays these summary metrics at the top:
PRs with CC
: total count of merged pull requests that contain at least one line of code written with Claude Code
Lines of code with CC
: total lines of code across all merged PRs that were written with Claude Code assistance. Only “effective lines” are counted: lines with more than 3 characters after normalization, excluding empty lines and lines with only brackets or trivial punctuation.
PRs with Claude Code (%)
: percentage of all merged PRs that contain Claude Code-assisted code
Suggestion accept rate
: percentage of times users accept Claude Code’s code editing suggestions, including Edit, Write, and NotebookEdit tool usage
Lines of code accepted
: total lines of code written by Claude Code that users have accepted in their sessions. This excludes rejected suggestions and does not track subsequent deletions.
​
Explore the charts
The dashboard includes several charts to visualize trends over time.
​
Track adoption
The Adoption chart shows daily usage trends:
users
: daily active users
sessions
: number of active Claude Code sessions per day
​
Measure PRs per user
This chart displays individual developer activity over time:
PRs per user
: total number of PRs merged per day divided by daily active users
users
: daily active users
Use this to understand how individual productivity changes as Claude Code adoption increases.
​
View pull requests breakdown
The Pull requests chart shows a daily breakdown of merged PRs:
PRs with CC
: pull requests containing Claude Code-assisted code
PRs without CC
: pull requests without Claude Code-assisted code
Toggle to
Lines of code
view to see the same breakdown by lines of code rather than PR count.
​
Find top contributors
The Leaderboard shows the top 10 users ranked by contribution volume. Toggle between:
Pull requests
: shows PRs with Claude Code vs All PRs for each user
Lines of code
: shows lines with Claude Code vs All lines for each user
Click
Export all users
to download complete contribution data for all users as a CSV file. The export includes all users, not just the top 10 displayed.
​
PR attribution
When contribution metrics are enabled, Claude Code analyzes merged pull requests to determine which code was written with Claude Code assistance. This is done by matching Claude Code session activity against the code in each PR.
​
Tagging criteria
PRs are tagged as “with Claude Code” if they contain at least one line of code written during a Claude Code session. The system uses conservative matching: only code where there is high confidence in Claude Code’s involvement is counted as assisted.
​
Attribution process
When a pull request is merged:
Added lines are extracted from the PR diff
Claude Code sessions that edited matching files within a time window are identified
PR lines are matched against Claude Code output using multiple strategies
Metrics are calculated for AI-assisted lines and total lines
Before comparison, lines are normalized: whitespace is trimmed, multiple spaces are collapsed, quotes are standardized, and text is converted to lowercase.
Merged pull requests containing Claude Code-assisted lines are labeled as
claude-code-assisted
in GitHub.
​
Time window
Sessions from 21 days before to 2 days after the PR merge date are considered for attribution matching.
​
Excluded files
Certain files are automatically excluded from analysis because they are auto-generated:
Lock files: package-lock.json, yarn.lock, Cargo.lock, and similar
Generated code: Protobuf outputs, build artifacts, minified files
Build directories: dist/, build/, node_modules/, target/
Test fixtures: snapshots, cassettes, mock data
Lines over 1,000 characters, which are likely minified or generated
​
Attribution notes
Keep these additional details in mind when interpreting attribution data:
Code substantially rewritten by developers, with more than 20% difference, is not attributed to Claude Code
Sessions outside the 21-day window are not considered
The algorithm does not consider the PR source or destination branch when performing attribution
​
Get the most from analytics
Use contribution metrics to demonstrate ROI, identify adoption patterns, and find team members who can help others get started.
​
Monitor adoption
Track the Adoption chart and user counts to identify:
Active users who can share best practices
Overall adoption trends across your organization
Dips in usage that may indicate friction or issues
​
Measure ROI
Contribution metrics help answer “Is this tool worth the investment?” with data from your own codebase:
Track changes in PRs per user over time as adoption increases
Compare PRs and lines of code shipped with vs. without Claude Code
Use alongside
DORA metrics
, sprint velocity, or other engineering KPIs to understand changes from adopting Claude Code
​
Identify power users
The Leaderboard helps you find team members with high Claude Code adoption who can:
Share prompting techniques and workflows with the team
Provide feedback on what’s working well
Help onboard new users
​
Access data programmatically
To query this data through GitHub, search for PRs labeled with
claude-code-assisted
.
​
Access analytics for API customers
API customers using the Claude Console can access analytics at
platform.claude.com/claude-code
. You need the UsageView permission to access the dashboard, which is granted to Developer, Billing, Admin, Owner, and Primary Owner roles.
Contribution metrics with GitHub integration are not currently available for API customers. The Console dashboard shows usage and spend metrics only.
The Console dashboard displays:
Lines of code accepted
: total lines of code written by Claude Code that users have accepted in their sessions. This excludes rejected suggestions and does not track subsequent deletions.
Suggestion accept rate
: percentage of times users accept code editing tool usage, including Edit, Write, and NotebookEdit tools.
Activity
: daily active users and sessions shown on a chart.
Spend
: daily API costs in dollars alongside user count.
​
View team insights
The team insights table shows per-user metrics:
Members
: all users who have authenticated to Claude Code. API key users display by key identifier, OAuth users display by email address.
Spend this month
: per-user total API costs for the current month.
Lines this month
: per-user total of accepted code lines for the current month.
Spend figures in the Console dashboard are estimates for analytics purposes. For actual costs, refer to your billing page.
​
Related resources
Monitoring with OpenTelemetry
: export real-time metrics and events to your observability stack
Manage costs effectively
: set spend limits and optimize token usage
Permissions
: configure roles and permissions
Was this page helpful?
Yes
No
Costs
Create and distribute a plugin marketplace
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/analytics" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Track team usage with analytics
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin m...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Track team usage with analytics
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code provides analytics dashboards to help organizations understand developer usage patterns, track contribution metrics, and measure how Claude Code impacts engineering velocity. Access the dashboard for your plan:
Plan
Dashboard URL
Includes
Read more
Claude for Teams / Enterprise
claude.ai/analytics/claude-code
Usage metrics, contribution metrics with GitHub integration, leaderboard, data export
Details
API (Claude Console)
platform.claude.com/claude-code
Usage metrics, spend tracking, team insights
Details
​
Access analytics for Team and Enterprise
Navigate to
claude.ai/analytics/claude-code
. Admins and Owners can view the dashboard.
The Team and Enterprise dashboard includes:
Usage metrics
: lines of code accepted, suggestion accept rate, daily active users and sessions
Contribution metrics
: PRs and lines of code shipped with Claude Code assistance, with
GitHub integration
Leaderboard
: top contributors ranked by Claude Code usage
Data export
: download contribution data as CSV for custom reporting
For per-user token counts and cost estimates, configure
OpenTelemetry export
.
​
Enable contribution metrics
Contribution metrics are in public beta and available on Claude for Teams and Claude for Enterprise plans. These metrics only cover users within your claude.ai organization. Usage through the Claude Console API or third-party integrations is not included.
Usage and adoption data is available for all Claude for Teams and Claude for Enterprise accounts. Contribution metrics require additional setup to connect your GitHub organization.
You need the Owner role to configure analytics settings. A GitHub admin must install the GitHub app.
Contribution metrics are not available for organizations with
Zero Data Retention
enabled. The analytics dashboard will show usage metrics only.
1
Install the GitHub app
A GitHub admin installs the Claude GitHub app on your organization’s GitHub account at
github.com/apps/claude
.
2
Enable Claude Code analytics
A Claude Owner navigates to
claude.ai/admin-settings/claude-code
and enables the Claude Code analytics feature.
3
Enable GitHub analytics
On the same page, enable the “GitHub analytics” toggle.
4
Authenticate with GitHub
Complete the GitHub authentication flow and select which GitHub organizations to include in the analysis.
Data typically appears within 24 hours after enabling, with daily updates. If no data appears, you may see one of these messages:
“GitHub app required”
: install the GitHub app to view contribution metrics
“Data processing in progress”
: check back in a few days and confirm the GitHub app is installed if data doesn’t appear
Contribution metrics support GitHub Cloud and GitHub Enterprise Server.
​
Review summary metrics
These metrics are deliberately conservative and represent an underestimate of Claude Code’s actual impact. Only lines and PRs where there is high confidence in Claude Code’s involvement are counted.
The dashboard displays these summary metrics at the top:
PRs with CC
: total count of merged pull requests that contain at least one line of code written with Claude Code
Lines of code with CC
: total lines of code across all merged PRs that were written with Claude Code assistance. Only “effective lines” are counted: lines with more than 3 characters after normalization, excluding empty lines and lines with only brackets or trivial punctuation.
PRs with Claude Code (%)
: percentage of all merged PRs that contain Claude Code-assisted code
Suggestion accept rate
: percentage of times users accept Claude Code’s code editing suggestions, including Edit, Write, and NotebookEdit tool usage
Lines of code accepted
: total lines of code written by Claude Code that users have accepted in their sessions. This excludes rejected suggestions and does not track subsequent deletions.
​
Explore the charts
The dashboard includes several charts to visualize trends over time.
​
Track adoption
The Adoption chart shows daily usage trends:
users
: daily active users
sessions
: number of active Claude Code sessions per day
​
Measure PRs per user
This chart displays individual developer activity over time:
PRs per user
: total number of PRs merged per day divided by daily active users
users
: daily active users
Use this to understand how individual productivity changes as Claude Code adoption increases.
​
View pull requests breakdown
The Pull requests chart shows a daily breakdown of merged PRs:
PRs with CC
: pull requests containing Claude Code-assisted code
PRs without CC
: pull requests without Claude Code-assisted code
Toggle to
Lines of code
view to see the same breakdown by lines of code rather than PR count.
​
Find top contributors
The Leaderboard shows the top 10 users ranked by contribution volume. Toggle between:
Pull requests
: shows PRs with Claude Code vs All PRs for each user
Lines of code
: shows lines with Claude Code vs All lines for each user
Click
Export all users
to download complete contribution data for all users as a CSV file. The export includes all users, not just the top 10 displayed.
​
PR attribution
When contribution metrics are enabled, Claude Code analyzes merged pull requests to determine which code was written with Claude Code assistance. This is done by matching Claude Code session activity against the code in each PR.
​
Tagging criteria
PRs are tagged as “with Claude Code” if they contain at least one line of code written during a Claude Code session. The system uses conservative matching: only code where there is high confidence in Claude Code’s involvement is counted as assisted.
​
Attribution process
When a pull request is merged:
Added lines are extracted from the PR diff
Claude Code sessions that edited matching files within a time window are identified
PR lines are matched against Claude Code output using multiple strategies
Metrics are calculated for AI-assisted lines and total lines
Before comparison, lines are normalized: whitespace is trimmed, multiple spaces are collapsed, quotes are standardized, and text is converted to lowercase.
Merged pull requests containing Claude Code-assisted lines are labeled as
claude-code-assisted
in GitHub.
​
Time window
Sessions from 21 days before to 2 days after the PR merge date are considered for attribution matching.
​
Excluded files
Certain files are automatically excluded from analysis because they are auto-generated:
Lock files: package-lock.json, yarn.lock, Cargo.lock, and similar
Generated code: Protobuf outputs, build artifacts, minified files
Build directories: dist/, build/, node_modules/, target/
Test fixtures: snapshots, cassettes, mock data
Lines over 1,000 characters, which are likely minified or generated
​
Attribution notes
Keep these additional details in mind when interpreting attribution data:
Code substantially rewritten by developers, with more than 20% difference, is not attributed to Claude Code
Sessions outside the 21-day window are not considered
The algorithm does not consider the PR source or destination branch when performing attribution
​
Get the most from analytics
Use contribution metrics to demonstrate ROI, identify adoption patterns, and find team members who can help others get started.
​
Monitor adoption
Track the Adoption chart and user counts to identify:
Active users who can share best practices
Overall adoption trends across your organization
Dips in usage that may indicate friction or issues
​
Measure ROI
Contribution metrics help answer “Is this tool worth the investment?” with data from your own codebase:
Track changes in PRs per user over time as adoption increases
Compare PRs and lines of code shipped with vs. without Claude Code
Use alongside
DORA metrics
, sprint velocity, or other engineering KPIs to understand changes from adopting Claude Code
​
Identify power users
The Leaderboard helps you find team members with high Claude Code adoption who can:
Share prompting techniques and workflows with the team
Provide feedback on what’s working well
Help onboard new users
​
Access data programmatically
To query this data through GitHub, search for PRs labeled with
claude-code-assisted
.
​
Access analytics for API customers
API customers using the Claude Console can access analytics at
platform.claude.com/claude-code
. You need the UsageView permission to access the dashboard, which is granted to Developer, Billing, Admin, Owner, and Primary Owner roles.
Contribution metrics with GitHub integration are not currently available for API customers. The Console dashboard shows usage and spend metrics only.
The Console dashboard displays:
Lines of code accepted
: total lines of code written by Claude Code that users have accepted in their sessions. This excludes rejected suggestions and does not track subsequent deletions.
Suggestion accept rate
: percentage of times users accept code editing tool usage, including Edit, Write, and NotebookEdit tools.
Activity
: daily active users and sessions shown on a chart.
Spend
: daily API costs in dollars alongside user count.
​
View team insights
The team insights table shows per-user metrics:
Members
: all users who have authenticated to Claude Code. API key users display by key identifier, OAuth users display by email address.
Spend this month
: per-user total API costs for the current month.
Lines this month
: per-user total of accepted code lines for the current month.
Spend figures in the Console dashboard are estimates for analytics purposes. For actual costs, refer to your billing page.
​
Related resources
Monitoring with OpenTelemetry
: export real-time metrics and events to your observability stack
Manage costs effectively
: set spend limits and optimize token usage
Permissions
: configure roles and permissions
Was this page helpful?
Yes
No
Costs
Create and distribute a plugin marketplace
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/analytics" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Common workflows</title>
  <link>https://code.claude.com/docs/en/common-workflows</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/common-workflows</guid>
  <pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Common workflows
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer us...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Common workflows
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page collects short recipes for everyday development. For higher-level guidance on prompting and context management, see
Best practices
.
This page covers:
Prompt recipes
for exploring code, fixing bugs, refactoring, testing, PRs, and documentation
Resume previous conversations
so a task can span multiple sittings
Run parallel sessions with worktrees
so concurrent edits don’t collide
Plan before editing
to review changes before they touch disk
Delegate research to subagents
to keep your main context clean
Pipe Claude into scripts
for CI and batch processing
​
Prompt recipes
These are prompt patterns for everyday tasks like exploring unfamiliar code, debugging, refactoring, writing tests, and creating PRs. Each works in any Claude Code surface; adapt the wording to your project.
​
Understand new codebases
​
Get a quick codebase overview
Suppose you’ve just joined a new project and need to understand its structure quickly.
1
Navigate to the project root directory
cd
/path/to/project
2
Start Claude Code
claude
3
Ask for a high-level overview
give me an overview of this codebase
4
Dive deeper into specific components
explain the main architecture patterns used here
what are the key data models?
how is authentication handled?
Tips:
Start with broad questions, then narrow down to specific areas
Ask about coding conventions and patterns used in the project
Request a glossary of project-specific terms
​
Find relevant code
Suppose you need to locate code related to a specific feature or functionality.
1
Ask Claude to find relevant files
find the files that handle user authentication
2
Get context on how components interact
how do these authentication files work together?
3
Understand the execution flow
trace the login process from front-end to database
Tips:
Be specific about what you’re looking for
Use domain language from the project
Install a
code intelligence plugin
for your language to give Claude precise “go to definition” and “find references” navigation
​
Fix bugs efficiently
Suppose you’ve encountered an error message and need to find and fix its source.
1
Share the error with Claude
I'm seeing an error when I run npm test
2
Ask for fix recommendations
suggest a few ways to fix the @ts-ignore in user.ts
3
Apply the fix
update user.ts to add the null check you suggested
Tips:
Tell Claude the command to reproduce the issue and get a stack trace
Mention any steps to reproduce the error
Let Claude know if the error is intermittent or consistent
​
Refactor code
Suppose you need to update old code to use modern patterns and practices.
1
Identify legacy code for refactoring
find deprecated API usage in our codebase
2
Get refactoring recommendations
suggest how to refactor utils.js to use modern JavaScript features
3
Apply the changes safely
refactor utils.js to use ES2024 features while maintaining the same behavior
4
Verify the refactoring
run tests for the refactored code
Tips:
Ask Claude to explain the benefits of the modern approach
Request that changes maintain backward compatibility when needed
Do refactoring in small, testable increments
​
Work with tests
Suppose you need to add tests for uncovered code.
1
Identify untested code
find functions in NotificationsService.swift that are not covered by tests
2
Generate test scaffolding
add tests for the notification service
3
Add meaningful test cases
add test cases for edge conditions in the notification service
4
Run and verify tests
run the new tests and fix any failures
Claude can generate tests that follow your project’s existing patterns and conventions. When asking for tests, be specific about what behavior you want to verify. Claude examines your existing test files to match the style, frameworks, and assertion patterns already in use.
For comprehensive coverage, ask Claude to identify edge cases you might have missed. Claude can analyze your code paths and suggest tests for error conditions, boundary values, and unexpected inputs that are easy to overlook.
​
Create pull requests
You can create pull requests by asking Claude directly (“create a pr for my changes”), or guide Claude through it step-by-step:
1
Summarize your changes
summarize the changes I've made to the authentication module
2
Generate a pull request
create a pr
3
Review and refine
enhance the PR description with more context about the security improvements
When you create a PR using
gh pr create
, the session is automatically linked to that PR. To return to it later, run
claude --from-pr <number>
or paste the PR URL into the
/resume
picker
search.
Review Claude’s generated PR before submitting and ask Claude to highlight potential risks or considerations.
​
Handle documentation
Suppose you need to add or update documentation for your code.
1
Identify undocumented code
find functions without proper JSDoc comments in the auth module
2
Generate documentation
add JSDoc comments to the undocumented functions in auth.js
3
Review and enhance
improve the generated documentation with more context and examples
4
Verify documentation
check if the documentation follows our project standards
Tips:
Specify the documentation style you want (JSDoc, docstrings, etc.)
Ask for examples in the documentation
Request documentation for public APIs, interfaces, and complex logic
​
Work in notes and non-code folders
Claude Code works in any directory. Run it inside a notes vault, a documentation folder, or any collection of markdown files to search, edit, and reorganize content the same way you would code.
The
.claude/
directory and
CLAUDE.md
sit alongside other tools’ config directories without conflict. Claude reads files fresh on each tool call, so it sees edits you make in another application the next time it reads that file.
​
Work with images
Suppose you need to work with images in your codebase, and you want Claude’s help analyzing image content.
1
Add an image to the conversation
You can use any of these methods:
Drag and drop an image into the Claude Code window
Copy an image and paste it into the CLI with ctrl+v (Do not use cmd+v)
Provide an image path to Claude. E.g., “Analyze this image: /path/to/your/image.png”
2
Ask Claude to analyze the image
What does this image show?
Describe the UI elements in this screenshot
Are there any problematic elements in this diagram?
3
Use images for context
Here's a screenshot of the error. What's causing it?
This is our current database schema. How should we modify it for the new feature?
4
Get code suggestions from visual content
Generate CSS to match this design mockup
What HTML structure would recreate this component?
Tips:
Use images when text descriptions would be unclear or cumbersome
Include screenshots of errors, UI designs, or diagrams for better context
You can work with multiple images in a conversation
Image analysis works with diagrams, screenshots, mockups, and more
When Claude references images (for example,
[Image #1]
),
Cmd+Click
(Mac) or
Ctrl+Click
(Windows/Linux) the link to open the image in your default viewer
​
Reference files and directories
Use @ to quickly include files or directories without waiting for Claude to read them.
1
Reference a single file
Explain the logic in @src/utils/auth.js
This includes the full content of the file in the conversation.
2
Reference a directory
What's the structure of @src/components?
This provides a directory listing with file information.
3
Reference MCP resources
Show me the data from @github:repos/owner/repo/issues
This fetches data from connected MCP servers using the format @server:resource. See
MCP resources
for details.
Tips:
File paths can be relative or absolute
@ file references add
CLAUDE.md
in the file’s directory and parent directories to context
Directory references show file listings, not contents
You can reference multiple files in a single message (for example, “@file1.js and @file2.js”)
​
Run Claude on a schedule
Suppose you want Claude to handle a task automatically on a recurring basis, like reviewing open PRs every morning, auditing dependencies weekly, or checking for CI failures overnight.
Pick a scheduling option based on where you want the task to run:
Option
Where it runs
Best for
Routines
Anthropic-managed infrastructure
Tasks that should run even when your computer is off. Can also trigger on API calls or GitHub events in addition to a schedule. Configure at
claude.ai/code/routines
.
Desktop scheduled tasks
Your machine, via the desktop app
Tasks that need direct access to local files, tools, or uncommitted changes.
GitHub Actions
Your CI pipeline
Tasks tied to repo events like opened PRs, or cron schedules that should live alongside your workflow config.
/loop
The current CLI session
Quick polling while a session is open. Tasks stop when you start a new conversation;
--resume
and
--continue
restore unexpired ones.
When writing prompts for scheduled tasks, be explicit about what success looks like and what to do with results. The task runs autonomously, so it can’t ask clarifying questions. For example: “Review open PRs labeled
needs-review
, leave inline comments on any issues, and post a summary in the
#eng-reviews
Slack channel.”
​
Ask Claude about its capabilities
Claude has built-in access to its documentation and can answer questions about its own features and limitations.
​
Example questions
can Claude Code create pull requests?
how does Claude Code handle permissions?
what skills are available?
how do I use MCP with Claude Code?
how do I configure Claude Code for Amazon Bedrock?
what are the limitations of Claude Code?
Claude provides documentation-based answers to these questions. For hands-on demonstrations, run
/powerup
for interactive lessons with animated demos, or refer to the specific workflow sections above.
Tips:
Claude always has access to the latest Claude Code documentation, regardless of the version you’re using
Ask specific questions to get detailed answers
Claude can explain complex features like MCP integration, enterprise configurations, and advanced workflows
​
Resume previous conversations
When a task spans multiple sittings, pick up where you left off instead of re-explaining context. Claude Code saves every conversation locally.
claude
--continue
This resumes the most recent session in the current directory; if there isn’t one yet, it prints
No conversation found to continue
and exits. Use
claude --resume
to choose from a list, or
/resume
from inside a running session. See
Manage sessions
for naming, branching, and the full picker reference.
​
Run parallel sessions with worktrees
Work on a feature in one terminal while Claude fixes a bug in another, without the edits colliding. Each worktree is a separate checkout on its own branch.
claude
--worktree
feature-auth
Run the same command with a different name in a second terminal to start an isolated parallel session. See
Worktrees
for cleanup,
.worktreeinclude
, and non-git VCS support. To monitor parallel sessions from one screen instead of separate terminals, see
background agents
.
​
Plan before editing
For changes you want to review before they touch disk, switch to plan mode. Claude reads files and proposes a plan but makes no edits until you approve.
claude
--permission-mode
plan
You can also press
Shift+Tab
mid-session to toggle into plan mode. See
Plan mode
for the approval flow and editing the plan in your text editor.
​
Delegate research to subagents
Exploring a large codebase fills your context with file reads. Delegate the exploration so only the findings come back.
use a subagent to investigate how our auth system handles token refresh
The subagent reads files in its own context window and reports a summary. See
Subagents
for defining custom agents with their own tools and prompts.
​
Pipe Claude into scripts
Run Claude non-interactively for CI, pre-commit hooks, or batch processing. Stdin and stdout work like any Unix tool.
git
log
--oneline
-20
|
claude
-p
"summarize these recent commits"
See
Non-interactive mode
for output formats, permission flags, and fan-out patterns.
​
Next steps
Best practices
Patterns for getting the most out of Claude Code
Manage sessions
Resume, name, and branch conversations
Worktrees
Run isolated parallel sessions
Extend Claude Code
Add skills, hooks, MCP, subagents, and plugins
Was this page helpful?
Yes
No
Permission modes
Best practices
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/common-workflows" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Common workflows
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer us...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Use Claude Code
Common workflows
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page collects short recipes for everyday development. For higher-level guidance on prompting and context management, see
Best practices
.
This page covers:
Prompt recipes
for exploring code, fixing bugs, refactoring, testing, PRs, and documentation
Resume previous conversations
so a task can span multiple sittings
Run parallel sessions with worktrees
so concurrent edits don’t collide
Plan before editing
to review changes before they touch disk
Delegate research to subagents
to keep your main context clean
Pipe Claude into scripts
for CI and batch processing
​
Prompt recipes
These are prompt patterns for everyday tasks like exploring unfamiliar code, debugging, refactoring, writing tests, and creating PRs. Each works in any Claude Code surface; adapt the wording to your project.
​
Understand new codebases
​
Get a quick codebase overview
Suppose you’ve just joined a new project and need to understand its structure quickly.
1
Navigate to the project root directory
cd
/path/to/project
2
Start Claude Code
claude
3
Ask for a high-level overview
give me an overview of this codebase
4
Dive deeper into specific components
explain the main architecture patterns used here
what are the key data models?
how is authentication handled?
Tips:
Start with broad questions, then narrow down to specific areas
Ask about coding conventions and patterns used in the project
Request a glossary of project-specific terms
​
Find relevant code
Suppose you need to locate code related to a specific feature or functionality.
1
Ask Claude to find relevant files
find the files that handle user authentication
2
Get context on how components interact
how do these authentication files work together?
3
Understand the execution flow
trace the login process from front-end to database
Tips:
Be specific about what you’re looking for
Use domain language from the project
Install a
code intelligence plugin
for your language to give Claude precise “go to definition” and “find references” navigation
​
Fix bugs efficiently
Suppose you’ve encountered an error message and need to find and fix its source.
1
Share the error with Claude
I'm seeing an error when I run npm test
2
Ask for fix recommendations
suggest a few ways to fix the @ts-ignore in user.ts
3
Apply the fix
update user.ts to add the null check you suggested
Tips:
Tell Claude the command to reproduce the issue and get a stack trace
Mention any steps to reproduce the error
Let Claude know if the error is intermittent or consistent
​
Refactor code
Suppose you need to update old code to use modern patterns and practices.
1
Identify legacy code for refactoring
find deprecated API usage in our codebase
2
Get refactoring recommendations
suggest how to refactor utils.js to use modern JavaScript features
3
Apply the changes safely
refactor utils.js to use ES2024 features while maintaining the same behavior
4
Verify the refactoring
run tests for the refactored code
Tips:
Ask Claude to explain the benefits of the modern approach
Request that changes maintain backward compatibility when needed
Do refactoring in small, testable increments
​
Work with tests
Suppose you need to add tests for uncovered code.
1
Identify untested code
find functions in NotificationsService.swift that are not covered by tests
2
Generate test scaffolding
add tests for the notification service
3
Add meaningful test cases
add test cases for edge conditions in the notification service
4
Run and verify tests
run the new tests and fix any failures
Claude can generate tests that follow your project’s existing patterns and conventions. When asking for tests, be specific about what behavior you want to verify. Claude examines your existing test files to match the style, frameworks, and assertion patterns already in use.
For comprehensive coverage, ask Claude to identify edge cases you might have missed. Claude can analyze your code paths and suggest tests for error conditions, boundary values, and unexpected inputs that are easy to overlook.
​
Create pull requests
You can create pull requests by asking Claude directly (“create a pr for my changes”), or guide Claude through it step-by-step:
1
Summarize your changes
summarize the changes I've made to the authentication module
2
Generate a pull request
create a pr
3
Review and refine
enhance the PR description with more context about the security improvements
When you create a PR using
gh pr create
, the session is automatically linked to that PR. To return to it later, run
claude --from-pr <number>
or paste the PR URL into the
/resume
picker
search.
Review Claude’s generated PR before submitting and ask Claude to highlight potential risks or considerations.
​
Handle documentation
Suppose you need to add or update documentation for your code.
1
Identify undocumented code
find functions without proper JSDoc comments in the auth module
2
Generate documentation
add JSDoc comments to the undocumented functions in auth.js
3
Review and enhance
improve the generated documentation with more context and examples
4
Verify documentation
check if the documentation follows our project standards
Tips:
Specify the documentation style you want (JSDoc, docstrings, etc.)
Ask for examples in the documentation
Request documentation for public APIs, interfaces, and complex logic
​
Work in notes and non-code folders
Claude Code works in any directory. Run it inside a notes vault, a documentation folder, or any collection of markdown files to search, edit, and reorganize content the same way you would code.
The
.claude/
directory and
CLAUDE.md
sit alongside other tools’ config directories without conflict. Claude reads files fresh on each tool call, so it sees edits you make in another application the next time it reads that file.
​
Work with images
Suppose you need to work with images in your codebase, and you want Claude’s help analyzing image content.
1
Add an image to the conversation
You can use any of these methods:
Drag and drop an image into the Claude Code window
Copy an image and paste it into the CLI with ctrl+v (Do not use cmd+v)
Provide an image path to Claude. E.g., “Analyze this image: /path/to/your/image.png”
2
Ask Claude to analyze the image
What does this image show?
Describe the UI elements in this screenshot
Are there any problematic elements in this diagram?
3
Use images for context
Here's a screenshot of the error. What's causing it?
This is our current database schema. How should we modify it for the new feature?
4
Get code suggestions from visual content
Generate CSS to match this design mockup
What HTML structure would recreate this component?
Tips:
Use images when text descriptions would be unclear or cumbersome
Include screenshots of errors, UI designs, or diagrams for better context
You can work with multiple images in a conversation
Image analysis works with diagrams, screenshots, mockups, and more
When Claude references images (for example,
[Image #1]
),
Cmd+Click
(Mac) or
Ctrl+Click
(Windows/Linux) the link to open the image in your default viewer
​
Reference files and directories
Use @ to quickly include files or directories without waiting for Claude to read them.
1
Reference a single file
Explain the logic in @src/utils/auth.js
This includes the full content of the file in the conversation.
2
Reference a directory
What's the structure of @src/components?
This provides a directory listing with file information.
3
Reference MCP resources
Show me the data from @github:repos/owner/repo/issues
This fetches data from connected MCP servers using the format @server:resource. See
MCP resources
for details.
Tips:
File paths can be relative or absolute
@ file references add
CLAUDE.md
in the file’s directory and parent directories to context
Directory references show file listings, not contents
You can reference multiple files in a single message (for example, “@file1.js and @file2.js”)
​
Run Claude on a schedule
Suppose you want Claude to handle a task automatically on a recurring basis, like reviewing open PRs every morning, auditing dependencies weekly, or checking for CI failures overnight.
Pick a scheduling option based on where you want the task to run:
Option
Where it runs
Best for
Routines
Anthropic-managed infrastructure
Tasks that should run even when your computer is off. Can also trigger on API calls or GitHub events in addition to a schedule. Configure at
claude.ai/code/routines
.
Desktop scheduled tasks
Your machine, via the desktop app
Tasks that need direct access to local files, tools, or uncommitted changes.
GitHub Actions
Your CI pipeline
Tasks tied to repo events like opened PRs, or cron schedules that should live alongside your workflow config.
/loop
The current CLI session
Quick polling while a session is open. Tasks stop when you start a new conversation;
--resume
and
--continue
restore unexpired ones.
When writing prompts for scheduled tasks, be explicit about what success looks like and what to do with results. The task runs autonomously, so it can’t ask clarifying questions. For example: “Review open PRs labeled
needs-review
, leave inline comments on any issues, and post a summary in the
#eng-reviews
Slack channel.”
​
Ask Claude about its capabilities
Claude has built-in access to its documentation and can answer questions about its own features and limitations.
​
Example questions
can Claude Code create pull requests?
how does Claude Code handle permissions?
what skills are available?
how do I use MCP with Claude Code?
how do I configure Claude Code for Amazon Bedrock?
what are the limitations of Claude Code?
Claude provides documentation-based answers to these questions. For hands-on demonstrations, run
/powerup
for interactive lessons with animated demos, or refer to the specific workflow sections above.
Tips:
Claude always has access to the latest Claude Code documentation, regardless of the version you’re using
Ask specific questions to get detailed answers
Claude can explain complex features like MCP integration, enterprise configurations, and advanced workflows
​
Resume previous conversations
When a task spans multiple sittings, pick up where you left off instead of re-explaining context. Claude Code saves every conversation locally.
claude
--continue
This resumes the most recent session in the current directory; if there isn’t one yet, it prints
No conversation found to continue
and exits. Use
claude --resume
to choose from a list, or
/resume
from inside a running session. See
Manage sessions
for naming, branching, and the full picker reference.
​
Run parallel sessions with worktrees
Work on a feature in one terminal while Claude fixes a bug in another, without the edits colliding. Each worktree is a separate checkout on its own branch.
claude
--worktree
feature-auth
Run the same command with a different name in a second terminal to start an isolated parallel session. See
Worktrees
for cleanup,
.worktreeinclude
, and non-git VCS support. To monitor parallel sessions from one screen instead of separate terminals, see
background agents
.
​
Plan before editing
For changes you want to review before they touch disk, switch to plan mode. Claude reads files and proposes a plan but makes no edits until you approve.
claude
--permission-mode
plan
You can also press
Shift+Tab
mid-session to toggle into plan mode. See
Plan mode
for the approval flow and editing the plan in your text editor.
​
Delegate research to subagents
Exploring a large codebase fills your context with file reads. Delegate the exploration so only the findings come back.
use a subagent to investigate how our auth system handles token refresh
The subagent reads files in its own context window and reports a summary. See
Subagents
for defining custom agents with their own tools and prompts.
​
Pipe Claude into scripts
Run Claude non-interactively for CI, pre-commit hooks, or batch processing. Stdin and stdout work like any Unix tool.
git
log
--oneline
-20
|
claude
-p
"summarize these recent commits"
See
Non-interactive mode
for output formats, permission flags, and fan-out patterns.
​
Next steps
Best practices
Patterns for getting the most out of Claude Code
Manage sessions
Resume, name, and branch conversations
Worktrees
Run isolated parallel sessions
Extend Claude Code
Add skills, hooks, MCP, subagents, and plugins
Was this page helpful?
Yes
No
Permission modes
Best practices
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/common-workflows" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Explore the .claude directory</title>
  <link>https://code.claude.com/docs/en/claude-directory</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/claude-directory</guid>
  <pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the .claude directory
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the .claude directory
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code reads instructions, settings, skills, subagents, and memory from your project directory and from
~/.claude
in your home directory. Commit project files to git to share them with your team; files in
~/.claude
are personal configuration that applies across all your projects.
On Windows,
~/.claude
resolves to
%USERPROFILE%\.claude
. If you set
CLAUDE_CONFIG_DIR
, every
~/.claude
path on this page lives under that directory instead.
Most users only edit
CLAUDE.md
and
settings.json
. The rest of the directory is optional: add skills, rules, or subagents as you need them.
​
Explore the directory
Click files in the tree to see what each one does, when it loads, and an example.
The interactive explorer works best on a larger screen. See the
file reference table
below, or
show the explorer anyway
.
Project
Global (~/)
⊞
⛶
CLAUDE.md
{}
.mcp.json
.worktreeinclude
▾
.claude/
{}
settings.json
{}
settings.local.json
▾
rules/
testing.md
api-design.md
▾
skills/
▾
security-review/
SKILL.md
checklist.md
▾
commands/
fix-issue.md
▸
output-styles/
▾
agents/
code-reviewer.md
▾
agent-memory/
▾
<agent-name>/
MEMORY.md
CLAUDE.md selected
your-project
/
CLAUDE.md
CLAUDE.md
Project instructions Claude reads every session
committed
When it loads
Loaded into context at the start of every session
Project-specific instructions that shape how Claude works in this repository. Put your conventions, common commands, and architectural context here so Claude operates with the same assumptions your team does.
Tips
●
Target under 200 lines. Longer files still load in full but may reduce adherence
●
CLAUDE.md loads into every session. If something only matters for specific tasks, move it to a
skill
or a path-scoped
rule
so it loads only when needed
●
List the commands you run most, like build, test, and format, so Claude knows them without you spelling them out each time
●
Run
/memory
to open and edit CLAUDE.md from within a session
●
Also works at
.claude/CLAUDE.md
if you prefer to keep the project root clean
This example is for a TypeScript and React project. It lists the build and test commands, the framework conventions Claude should follow, and project-specific rules like export style and file layout.
CLAUDE.md
Copy
# Project conventions
## Commands
- Build: `npm run build`
- Test: `npm test`
- Lint: `npm run lint`
## Stack
- TypeScript with strict mode
- React 19, functional components only
## Rules
- Named exports, never default exports
- Tests live next to source: `foo.ts` -> `foo.test.ts`
- All API routes return `{ data, error }` shape
Full docs →
​
What’s not shown
The explorer covers files you author and edit. A few related files live elsewhere:
File
Location
Purpose
managed-settings.json
System-level, varies by OS
Enterprise-enforced settings that you can’t override. See
server-managed settings
.
CLAUDE.local.md
Project root
Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to
.gitignore
.
Installed plugins
~/.claude/plugins
Cloned marketplaces, installed plugin versions, and per-plugin data, managed by
claude plugin
commands. Orphaned versions are deleted 7 days after a plugin update or uninstall. See
plugin caching
.
~/.claude
also holds data Claude Code writes as you work: transcripts, prompt history, file snapshots, caches, and logs. See
application data
below.
​
Choose the right file
Different kinds of customization live in different files. Use this table to find where a change belongs.
You want to
Edit
Scope
Reference
Give Claude project context and conventions
CLAUDE.md
project or global
Memory
Allow or block specific tool calls
settings.json
permissions
or
hooks
project or global
Permissions
,
Hooks
Run a script before or after tool calls
settings.json
hooks
project or global
Hooks
Set environment variables for the session
settings.json
env
project or global
Settings
Keep personal overrides out of git
settings.local.json
project only
Settings scopes
Add a prompt or capability you invoke with
/name
skills/<name>/SKILL.md
project or global
Skills
Define a specialized subagent with its own tools
agents/*.md
project or global
Subagents
Connect external tools over MCP
.mcp.json
project only
MCP
Change how Claude formats responses
output-styles/*.md
project or global
Output styles
​
File reference
This table lists every file the explorer covers. Project-scope files live in your repo under
.claude/
(or at the root for
CLAUDE.md
,
.mcp.json
, and
.worktreeinclude
). Global-scope files live in
~/.claude/
and apply across all projects.
Several things can override what you put in these files:
Managed settings
deployed by your organization take precedence over everything
CLI flags like
--permission-mode
or
--settings
override
settings.json
for that session
Some environment variables take precedence over their equivalent setting, but this varies: check the
environment variables reference
for each one
See
settings precedence
for the full order.
Click a filename to open that node in the explorer above.
File
Scope
Commit
What it does
Reference
CLAUDE.md
Project and global
✓
Instructions loaded every session
Memory
rules/*.md
Project and global
✓
Topic-scoped instructions, optionally path-gated
Rules
settings.json
Project and global
✓
Permissions, hooks, env vars, model defaults
Settings
settings.local.json
Project only
Your personal overrides, auto-gitignored
Settings scopes
.mcp.json
Project only
✓
Team-shared MCP servers
MCP scopes
.worktreeinclude
Project only
✓
Gitignored files to copy into new worktrees
Worktrees
skills/<name>/SKILL.md
Project and global
✓
Reusable prompts invoked with
/name
or auto-invoked
Skills
commands/*.md
Project and global
✓
Single-file prompts; same mechanism as skills
Skills
output-styles/*.md
Project and global
✓
Custom system-prompt sections
Output styles
agents/*.md
Project and global
✓
Subagent definitions with their own prompt and tools
Subagents
agent-memory/<name>/
Project and global
✓
Persistent memory for subagents
Persistent memory
~/.claude.json
Global only
App state, OAuth, UI toggles, personal MCP servers
Global config
projects/<project>/memory/
Global only
Auto memory: Claude’s notes to itself across sessions
Auto memory
keybindings.json
Global only
Custom keyboard shortcuts
Keybindings
themes/*.json
Global only
Custom color themes
Custom themes
​
Troubleshoot configuration
If a setting, hook, or file isn’t taking effect, see
Debug your configuration
for the inspection commands and a symptom-first lookup table.
​
Application data
Beyond the config you author,
~/.claude
holds data Claude Code writes during sessions. These files are plaintext. Anything that passes through a tool lands in a transcript on disk: file contents, command output, pasted text.
​
Cleaned up automatically
Files in the paths below are deleted on startup once they’re older than
cleanupPeriodDays
. The default is 30 days.
Path under
~/.claude/
Contents
projects/<project>/<session>.jsonl
Full conversation transcript: every message, tool call, and tool result
projects/<project>/<session>/subagents/
Subagent
conversation transcripts, removed with the parent session transcript when it ages out
projects/<project>/<session>/tool-results/
Large tool outputs spilled to separate files
file-history/<session>/
Pre-edit snapshots of files Claude changed, used for
checkpoint restore
plans/
Plan files written during
plan mode
debug/
Per-session debug logs, written only when you start with
--debug
or run
/debug
paste-cache/
,
image-cache/
Contents of large pastes and attached images
session-env/
Per-session environment metadata
tasks/
Per-session task lists written by the task tools
shell-snapshots/
Captured shell environment used by the Bash tool. Removed on clean exit. The sweep clears any left after a crash.
backups/
Timestamped copies of
~/.claude.json
taken before config migrations
feedback-bundles/
Redacted transcript archives written by
/feedback
on third-party providers, for sending to your Anthropic account team
​
Kept until you delete them
The following paths are not covered by automatic cleanup and persist indefinitely.
Path under
~/.claude/
Contents
history.jsonl
Every prompt you’ve typed, with timestamp and project path. Used for up-arrow recall.
stats-cache.json
Aggregated token and cost counts shown by
/usage
remote-settings.json
Cached copy of
server-managed settings
for your organization. Only present when your organization has configured them. Refreshed on each launch.
todos/
Legacy per-session task lists. No longer written by current versions; safe to delete.
Other small cache and lock files appear depending on which features you use and are safe to delete.
​
Plaintext storage
Transcripts and history are not encrypted at rest. OS file permissions are the only protection. If a tool reads a
.env
file or a command prints a credential, that value is written to
projects/<project>/<session>.jsonl
. To reduce exposure:
Lower
cleanupPeriodDays
to shorten how long transcripts are kept
Set the
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable to skip writing transcripts and prompt history in any mode. In non-interactive mode, you can instead pass
--no-session-persistence
alongside
-p
, or set
persistSession: false
in the Agent SDK.
Use
permission rules
to deny reads of credential files
​
Clear local data
Run
claude project purge
to delete the state Claude Code holds for one project:
Transcripts and auto memory under
projects/
Per-session
tasks/
,
debug/
, and
file-history/
entries
Matching prompt lines in
history.jsonl
The project’s entry in
~/.claude.json
The command prints the full deletion plan and asks for confirmation before removing anything.
Preview the plan without deleting anything:
claude
project
purge
~/work/my-repo
--dry-run
Delete with a single confirmation prompt:
claude
project
purge
~/work/my-repo
Omit the path to pick a project from an interactive list.
Skip the confirmation prompt for use in scripts:
claude
project
purge
~/work/my-repo
--yes
Pass
--all
instead of a path to purge state for every project at once, which deletes
history.jsonl
outright rather than filtering it. Pass
-i
to step through the deletion plan one item at a time.
The command leaves
shell-snapshots/
and
backups/
alone because those are not project-scoped, and warns about them in the plan output. It exits with status 1 if no state matches the given path.
You can also delete any of the application-data paths above by hand. New sessions are unaffected. The table below shows what you lose for past sessions.
Delete
You lose
~/.claude/projects/
Resume, continue, and rewind for past sessions
~/.claude/history.jsonl
Up-arrow prompt recall
~/.claude/file-history/
Checkpoint restore for past sessions
~/.claude/stats-cache.json
Historical totals shown by
/usage
~/.claude/remote-settings.json
Nothing. Re-fetched on next launch.
~/.claude/debug/
,
~/.claude/plans/
,
~/.claude/paste-cache/
,
~/.claude/image-cache/
,
~/.claude/session-env/
,
~/.claude/tasks/
,
~/.claude/shell-snapshots/
,
~/.claude/backups/
Nothing user-facing
~/.claude/todos/
Nothing. Legacy directory not written by current versions.
Don’t delete
~/.claude.json
,
~/.claude/settings.json
, or
~/.claude/plugins/
: those hold your auth, preferences, and installed plugins.
​
Related resources
Manage Claude’s memory
: write and organize CLAUDE.md, rules, and auto memory
Configure settings
: set permissions, hooks, environment variables, and model defaults
Create skills
: build reusable prompts and workflows
Configure subagents
: define specialized agents with their own context
Was this page helpful?
Yes
No
Extend Claude Code
Explore the context window
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-directory" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the .claude directory
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
Explore the .claude directory
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code reads instructions, settings, skills, subagents, and memory from your project directory and from
~/.claude
in your home directory. Commit project files to git to share them with your team; files in
~/.claude
are personal configuration that applies across all your projects.
On Windows,
~/.claude
resolves to
%USERPROFILE%\.claude
. If you set
CLAUDE_CONFIG_DIR
, every
~/.claude
path on this page lives under that directory instead.
Most users only edit
CLAUDE.md
and
settings.json
. The rest of the directory is optional: add skills, rules, or subagents as you need them.
​
Explore the directory
Click files in the tree to see what each one does, when it loads, and an example.
The interactive explorer works best on a larger screen. See the
file reference table
below, or
show the explorer anyway
.
Project
Global (~/)
⊞
⛶
CLAUDE.md
{}
.mcp.json
.worktreeinclude
▾
.claude/
{}
settings.json
{}
settings.local.json
▾
rules/
testing.md
api-design.md
▾
skills/
▾
security-review/
SKILL.md
checklist.md
▾
commands/
fix-issue.md
▸
output-styles/
▾
agents/
code-reviewer.md
▾
agent-memory/
▾
<agent-name>/
MEMORY.md
CLAUDE.md selected
your-project
/
CLAUDE.md
CLAUDE.md
Project instructions Claude reads every session
committed
When it loads
Loaded into context at the start of every session
Project-specific instructions that shape how Claude works in this repository. Put your conventions, common commands, and architectural context here so Claude operates with the same assumptions your team does.
Tips
●
Target under 200 lines. Longer files still load in full but may reduce adherence
●
CLAUDE.md loads into every session. If something only matters for specific tasks, move it to a
skill
or a path-scoped
rule
so it loads only when needed
●
List the commands you run most, like build, test, and format, so Claude knows them without you spelling them out each time
●
Run
/memory
to open and edit CLAUDE.md from within a session
●
Also works at
.claude/CLAUDE.md
if you prefer to keep the project root clean
This example is for a TypeScript and React project. It lists the build and test commands, the framework conventions Claude should follow, and project-specific rules like export style and file layout.
CLAUDE.md
Copy
# Project conventions
## Commands
- Build: `npm run build`
- Test: `npm test`
- Lint: `npm run lint`
## Stack
- TypeScript with strict mode
- React 19, functional components only
## Rules
- Named exports, never default exports
- Tests live next to source: `foo.ts` -> `foo.test.ts`
- All API routes return `{ data, error }` shape
Full docs →
​
What’s not shown
The explorer covers files you author and edit. A few related files live elsewhere:
File
Location
Purpose
managed-settings.json
System-level, varies by OS
Enterprise-enforced settings that you can’t override. See
server-managed settings
.
CLAUDE.local.md
Project root
Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to
.gitignore
.
Installed plugins
~/.claude/plugins
Cloned marketplaces, installed plugin versions, and per-plugin data, managed by
claude plugin
commands. Orphaned versions are deleted 7 days after a plugin update or uninstall. See
plugin caching
.
~/.claude
also holds data Claude Code writes as you work: transcripts, prompt history, file snapshots, caches, and logs. See
application data
below.
​
Choose the right file
Different kinds of customization live in different files. Use this table to find where a change belongs.
You want to
Edit
Scope
Reference
Give Claude project context and conventions
CLAUDE.md
project or global
Memory
Allow or block specific tool calls
settings.json
permissions
or
hooks
project or global
Permissions
,
Hooks
Run a script before or after tool calls
settings.json
hooks
project or global
Hooks
Set environment variables for the session
settings.json
env
project or global
Settings
Keep personal overrides out of git
settings.local.json
project only
Settings scopes
Add a prompt or capability you invoke with
/name
skills/<name>/SKILL.md
project or global
Skills
Define a specialized subagent with its own tools
agents/*.md
project or global
Subagents
Connect external tools over MCP
.mcp.json
project only
MCP
Change how Claude formats responses
output-styles/*.md
project or global
Output styles
​
File reference
This table lists every file the explorer covers. Project-scope files live in your repo under
.claude/
(or at the root for
CLAUDE.md
,
.mcp.json
, and
.worktreeinclude
). Global-scope files live in
~/.claude/
and apply across all projects.
Several things can override what you put in these files:
Managed settings
deployed by your organization take precedence over everything
CLI flags like
--permission-mode
or
--settings
override
settings.json
for that session
Some environment variables take precedence over their equivalent setting, but this varies: check the
environment variables reference
for each one
See
settings precedence
for the full order.
Click a filename to open that node in the explorer above.
File
Scope
Commit
What it does
Reference
CLAUDE.md
Project and global
✓
Instructions loaded every session
Memory
rules/*.md
Project and global
✓
Topic-scoped instructions, optionally path-gated
Rules
settings.json
Project and global
✓
Permissions, hooks, env vars, model defaults
Settings
settings.local.json
Project only
Your personal overrides, auto-gitignored
Settings scopes
.mcp.json
Project only
✓
Team-shared MCP servers
MCP scopes
.worktreeinclude
Project only
✓
Gitignored files to copy into new worktrees
Worktrees
skills/<name>/SKILL.md
Project and global
✓
Reusable prompts invoked with
/name
or auto-invoked
Skills
commands/*.md
Project and global
✓
Single-file prompts; same mechanism as skills
Skills
output-styles/*.md
Project and global
✓
Custom system-prompt sections
Output styles
agents/*.md
Project and global
✓
Subagent definitions with their own prompt and tools
Subagents
agent-memory/<name>/
Project and global
✓
Persistent memory for subagents
Persistent memory
~/.claude.json
Global only
App state, OAuth, UI toggles, personal MCP servers
Global config
projects/<project>/memory/
Global only
Auto memory: Claude’s notes to itself across sessions
Auto memory
keybindings.json
Global only
Custom keyboard shortcuts
Keybindings
themes/*.json
Global only
Custom color themes
Custom themes
​
Troubleshoot configuration
If a setting, hook, or file isn’t taking effect, see
Debug your configuration
for the inspection commands and a symptom-first lookup table.
​
Application data
Beyond the config you author,
~/.claude
holds data Claude Code writes during sessions. These files are plaintext. Anything that passes through a tool lands in a transcript on disk: file contents, command output, pasted text.
​
Cleaned up automatically
Files in the paths below are deleted on startup once they’re older than
cleanupPeriodDays
. The default is 30 days.
Path under
~/.claude/
Contents
projects/<project>/<session>.jsonl
Full conversation transcript: every message, tool call, and tool result
projects/<project>/<session>/subagents/
Subagent
conversation transcripts, removed with the parent session transcript when it ages out
projects/<project>/<session>/tool-results/
Large tool outputs spilled to separate files
file-history/<session>/
Pre-edit snapshots of files Claude changed, used for
checkpoint restore
plans/
Plan files written during
plan mode
debug/
Per-session debug logs, written only when you start with
--debug
or run
/debug
paste-cache/
,
image-cache/
Contents of large pastes and attached images
session-env/
Per-session environment metadata
tasks/
Per-session task lists written by the task tools
shell-snapshots/
Captured shell environment used by the Bash tool. Removed on clean exit. The sweep clears any left after a crash.
backups/
Timestamped copies of
~/.claude.json
taken before config migrations
feedback-bundles/
Redacted transcript archives written by
/feedback
on third-party providers, for sending to your Anthropic account team
​
Kept until you delete them
The following paths are not covered by automatic cleanup and persist indefinitely.
Path under
~/.claude/
Contents
history.jsonl
Every prompt you’ve typed, with timestamp and project path. Used for up-arrow recall.
stats-cache.json
Aggregated token and cost counts shown by
/usage
remote-settings.json
Cached copy of
server-managed settings
for your organization. Only present when your organization has configured them. Refreshed on each launch.
todos/
Legacy per-session task lists. No longer written by current versions; safe to delete.
Other small cache and lock files appear depending on which features you use and are safe to delete.
​
Plaintext storage
Transcripts and history are not encrypted at rest. OS file permissions are the only protection. If a tool reads a
.env
file or a command prints a credential, that value is written to
projects/<project>/<session>.jsonl
. To reduce exposure:
Lower
cleanupPeriodDays
to shorten how long transcripts are kept
Set the
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable to skip writing transcripts and prompt history in any mode. In non-interactive mode, you can instead pass
--no-session-persistence
alongside
-p
, or set
persistSession: false
in the Agent SDK.
Use
permission rules
to deny reads of credential files
​
Clear local data
Run
claude project purge
to delete the state Claude Code holds for one project:
Transcripts and auto memory under
projects/
Per-session
tasks/
,
debug/
, and
file-history/
entries
Matching prompt lines in
history.jsonl
The project’s entry in
~/.claude.json
The command prints the full deletion plan and asks for confirmation before removing anything.
Preview the plan without deleting anything:
claude
project
purge
~/work/my-repo
--dry-run
Delete with a single confirmation prompt:
claude
project
purge
~/work/my-repo
Omit the path to pick a project from an interactive list.
Skip the confirmation prompt for use in scripts:
claude
project
purge
~/work/my-repo
--yes
Pass
--all
instead of a path to purge state for every project at once, which deletes
history.jsonl
outright rather than filtering it. Pass
-i
to step through the deletion plan one item at a time.
The command leaves
shell-snapshots/
and
backups/
alone because those are not project-scoped, and warns about them in the plan output. It exits with status 1 if no state matches the given path.
You can also delete any of the application-data paths above by hand. New sessions are unaffected. The table below shows what you lose for past sessions.
Delete
You lose
~/.claude/projects/
Resume, continue, and rewind for past sessions
~/.claude/history.jsonl
Up-arrow prompt recall
~/.claude/file-history/
Checkpoint restore for past sessions
~/.claude/stats-cache.json
Historical totals shown by
/usage
~/.claude/remote-settings.json
Nothing. Re-fetched on next launch.
~/.claude/debug/
,
~/.claude/plans/
,
~/.claude/paste-cache/
,
~/.claude/image-cache/
,
~/.claude/session-env/
,
~/.claude/tasks/
,
~/.claude/shell-snapshots/
,
~/.claude/backups/
Nothing user-facing
~/.claude/todos/
Nothing. Legacy directory not written by current versions.
Don’t delete
~/.claude.json
,
~/.claude/settings.json
, or
~/.claude/plugins/
: those hold your auth, preferences, and installed plugins.
​
Related resources
Manage Claude’s memory
: write and organize CLAUDE.md, rules, and auto memory
Configure settings
: set permissions, hooks, environment variables, and model defaults
Create skills
: build reusable prompts and workflows
Configure subagents
: define specialized agents with their own context
Was this page helpful?
Yes
No
Extend Claude Code
Explore the context window
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-directory" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Desktop changelog</title>
  <link>https://code.claude.com/docs/en/desktop-changelog</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/desktop-changelog</guid>
  <pubDate>Mon, 11 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Desktop changelog
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Sched...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Desktop changelog
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers Claude Code-specific changes in the Desktop app. For changes to the Claude Code CLI bundled inside the app, see the
CLI changelog
.
​
1.7196.0
May 12, 2026
Fixed auto-update hanging indefinitely on Relaunch to Update when popout windows refused to close.
Fixed local sessions failing to start after a corrupted bundled Claude Code binary was cached.
Fixed the credential helper opening duplicate browser sign-in tabs when starting a new conversation.
Fixed Code tab PR status icons showing the wrong state for merged, merge-queued, and draft pull requests.
Fixed Quick Entry dropping characters entered with a Korean, Japanese, or Chinese input method.
Added an “Also delete files on disk” option to the scheduled task delete dialog; checking it removes the task’s
SKILL.md
file and associated data from
~/.claude/scheduled-tasks/
.
Added support for mouse back and forward buttons for navigating the chat view.
3P managed deployments
Added an organization banner across the top of the app window, configured by IT administrators.
​
1.6889.0
May 8, 2026
Added MCP App widget rendering in Code tab sessions.
Added an OS notification when a Code session finishes a task and you aren’t currently viewing it.
Added automatic detection and re-download of corrupted Claude Code CLI binaries on macOS.
Added support for scheduled tasks to modify their own schedule or prompt during a run using the
update_scheduled_task
MCP tool.
Updated the list of available MCP tools to reload automatically when the local MCP configuration changes.
Updated PR auto-fix to post a reply on each review thread it addresses and mark the thread resolved.
Improved SSH session startup speed by preconnecting saved SSH configurations at app launch.
Fixed pasting a code block into a busy terminal; the app now opens a new terminal tab when the existing one has a process running.
Fixed PR bar issues in Code sessions: each row now shows its own diff, and the sidebar status icon updates when a PR is merged.
Fixed garbled scrollback, such as stray
%
marks and half-wrapped prompts, when opening the terminal pane after running a code block.
Fixed Code session links opening with overlapping window controls when reached via Handoff or share links.
Fixed git commit signing failing in local sessions when the signing key is held by 1Password or Secretive.
Fixed locally installed plugins disappearing from sessions after the plugin registry file became corrupted by concurrent writes.
Fixed scheduled tasks running with auto-approve echoing tool-use suggestions into the session.
Fixed SSH plugin sync so a single problematic plugin no longer blocks sync for the rest.
3P managed deployments
Added support for stdio-transport local MCP servers via the
managedMcpServers
managed-settings key; the connector detail panel now shows the command and arguments, and environment variable values are masked outside the admin Setup screen.
Added a managed-settings option to disable
claude://
deep-link handling.
Added support for customizing model display names in the model picker via
labelOverride
.
Fixed per-tool MCP server policies set by administrators not being enforced in all session types.
​
1.6608.0
May 7, 2026
Fixed scheduled tasks failing to run when a previous run was stuck waiting on a permission prompt.
Fixed scheduled tasks repeatedly retrying a failed run instead of waiting for the next scheduled time.
Fixed scheduled-task history incorrectly showing “computer asleep” for runs skipped due to a concurrency limit.
Added per-plugin auto-install for organization-provisioned plugins via the plugin manifest.
Added Unarchive to the Code session context menu; sending a message in an archived session now restores it automatically.
Added a warning when archiving a Code session that has uncommitted changes in its worktree.
Added a warning when quitting or restarting the app while local Code sessions are running.
Added csh and tcsh login shell support when connecting to remote SSH hosts.
Fixed folder permission rules failing to match when the connected folder is a drive root.
Fixed Windows installs leaving an empty folder under
%LOCALAPPDATA%
.
​
1.6259.0
May 5, 2026
Code sessions now default the working directory to the home folder when none is configured.
settings.json
project settings now cascade from the SSH host for SSH Code sessions.
“Always allow” tool permissions now persist across app restarts and display their scope.
Added automatic detection and re-download of corrupted Claude Code CLI binaries on Windows.
The PR bar now shows stacked and sibling pull requests alongside the branch’s own PR.
Messages sent while a turn is running are now queued rather than dropped.
Opening a Code session link on iOS now continues the session on macOS via Handoff.
​
1.5354.0
April 29, 2026
Disabling the org Skills toggle in the admin console now removes the skill management tools
list_skills
,
save_skill
, and
propose_skills
from Code sessions.
The preview pane now opens automatically when a session’s working directory is a symlink.
Improved login-shell PATH extraction for more reliable tool discovery.
​
1.5220.0
April 28, 2026
Added a multi-tab terminal pane; click
+
in the terminal pane header to open a second tab, or right-click a folder in the chat to choose
Open in terminal
.
Fixed worktree pool re-lease creating a fresh worktree on checkout failure instead of re-using an existing one.
Fixed rewind selecting the wrong assistant message after a previous rewind created a fork.
​
1.5186.0
April 28, 2026
Added
list_sessions
,
search_session_transcripts
, and
archive_session
MCP tools for managing Code sessions from within a session.
Improved SSH wake-path reliability and surfaced
ProxyCommand
stderr output for easier debugging.
Fixed login-shell PATH extraction for fish shell users. It was returning a newline-separated list instead of a colon-separated one.
Fixed the SSH remote control socket directory permissions so
~/.claude/remote
is no longer world-traversable.
PR review bodies and issue comments are now forwarded to the auto-fix engine.
Added a category-driven error UI for Code sessions that groups failures by type and surfaces actionable recovery steps.
Was this page helpful?
Yes
No
Scheduled tasks
Chrome extension (beta)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-changelog" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Desktop changelog
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Sched...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Desktop changelog
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers Claude Code-specific changes in the Desktop app. For changes to the Claude Code CLI bundled inside the app, see the
CLI changelog
.
​
1.7196.0
May 12, 2026
Fixed auto-update hanging indefinitely on Relaunch to Update when popout windows refused to close.
Fixed local sessions failing to start after a corrupted bundled Claude Code binary was cached.
Fixed the credential helper opening duplicate browser sign-in tabs when starting a new conversation.
Fixed Code tab PR status icons showing the wrong state for merged, merge-queued, and draft pull requests.
Fixed Quick Entry dropping characters entered with a Korean, Japanese, or Chinese input method.
Added an “Also delete files on disk” option to the scheduled task delete dialog; checking it removes the task’s
SKILL.md
file and associated data from
~/.claude/scheduled-tasks/
.
Added support for mouse back and forward buttons for navigating the chat view.
3P managed deployments
Added an organization banner across the top of the app window, configured by IT administrators.
​
1.6889.0
May 8, 2026
Added MCP App widget rendering in Code tab sessions.
Added an OS notification when a Code session finishes a task and you aren’t currently viewing it.
Added automatic detection and re-download of corrupted Claude Code CLI binaries on macOS.
Added support for scheduled tasks to modify their own schedule or prompt during a run using the
update_scheduled_task
MCP tool.
Updated the list of available MCP tools to reload automatically when the local MCP configuration changes.
Updated PR auto-fix to post a reply on each review thread it addresses and mark the thread resolved.
Improved SSH session startup speed by preconnecting saved SSH configurations at app launch.
Fixed pasting a code block into a busy terminal; the app now opens a new terminal tab when the existing one has a process running.
Fixed PR bar issues in Code sessions: each row now shows its own diff, and the sidebar status icon updates when a PR is merged.
Fixed garbled scrollback, such as stray
%
marks and half-wrapped prompts, when opening the terminal pane after running a code block.
Fixed Code session links opening with overlapping window controls when reached via Handoff or share links.
Fixed git commit signing failing in local sessions when the signing key is held by 1Password or Secretive.
Fixed locally installed plugins disappearing from sessions after the plugin registry file became corrupted by concurrent writes.
Fixed scheduled tasks running with auto-approve echoing tool-use suggestions into the session.
Fixed SSH plugin sync so a single problematic plugin no longer blocks sync for the rest.
3P managed deployments
Added support for stdio-transport local MCP servers via the
managedMcpServers
managed-settings key; the connector detail panel now shows the command and arguments, and environment variable values are masked outside the admin Setup screen.
Added a managed-settings option to disable
claude://
deep-link handling.
Added support for customizing model display names in the model picker via
labelOverride
.
Fixed per-tool MCP server policies set by administrators not being enforced in all session types.
​
1.6608.0
May 7, 2026
Fixed scheduled tasks failing to run when a previous run was stuck waiting on a permission prompt.
Fixed scheduled tasks repeatedly retrying a failed run instead of waiting for the next scheduled time.
Fixed scheduled-task history incorrectly showing “computer asleep” for runs skipped due to a concurrency limit.
Added per-plugin auto-install for organization-provisioned plugins via the plugin manifest.
Added Unarchive to the Code session context menu; sending a message in an archived session now restores it automatically.
Added a warning when archiving a Code session that has uncommitted changes in its worktree.
Added a warning when quitting or restarting the app while local Code sessions are running.
Added csh and tcsh login shell support when connecting to remote SSH hosts.
Fixed folder permission rules failing to match when the connected folder is a drive root.
Fixed Windows installs leaving an empty folder under
%LOCALAPPDATA%
.
​
1.6259.0
May 5, 2026
Code sessions now default the working directory to the home folder when none is configured.
settings.json
project settings now cascade from the SSH host for SSH Code sessions.
“Always allow” tool permissions now persist across app restarts and display their scope.
Added automatic detection and re-download of corrupted Claude Code CLI binaries on Windows.
The PR bar now shows stacked and sibling pull requests alongside the branch’s own PR.
Messages sent while a turn is running are now queued rather than dropped.
Opening a Code session link on iOS now continues the session on macOS via Handoff.
​
1.5354.0
April 29, 2026
Disabling the org Skills toggle in the admin console now removes the skill management tools
list_skills
,
save_skill
, and
propose_skills
from Code sessions.
The preview pane now opens automatically when a session’s working directory is a symlink.
Improved login-shell PATH extraction for more reliable tool discovery.
​
1.5220.0
April 28, 2026
Added a multi-tab terminal pane; click
+
in the terminal pane header to open a second tab, or right-click a folder in the chat to choose
Open in terminal
.
Fixed worktree pool re-lease creating a fresh worktree on checkout failure instead of re-using an existing one.
Fixed rewind selecting the wrong assistant message after a previous rewind created a fork.
​
1.5186.0
April 28, 2026
Added
list_sessions
,
search_session_transcripts
, and
archive_session
MCP tools for managing Code sessions from within a session.
Improved SSH wake-path reliability and surfaced
ProxyCommand
stderr output for easier debugging.
Fixed login-shell PATH extraction for fish shell users. It was returning a newline-separated list instead of a colon-separated one.
Fixed the SSH remote control socket directory permissions so
~/.claude/remote
is no longer world-traversable.
PR review bodies and issue comments are now forwarded to the auto-fix engine.
Added a category-driven error UI for Code sessions that groups failures by type and surfaces actionable recovery steps.
Was this page helpful?
Yes
No
Scheduled tasks
Chrome extension (beta)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-changelog" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Customize your status line</title>
  <link>https://code.claude.com/docs/en/statusline</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/statusline</guid>
  <pubDate>Fri, 01 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize your status line
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize your status line
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The status line is a customizable bar at the bottom of Claude Code that runs any shell script you configure. It receives JSON session data on stdin and displays whatever your script prints, giving you a persistent, at-a-glance view of context usage, costs, git status, or anything else you want to track.
Status lines are useful when you:
Want to monitor context window usage as you work
Need to track session costs
Work across multiple sessions and need to distinguish them
Want git branch and status always visible
Here’s an example of a
multi-line status line
that displays git info on the first line and a color-coded context bar on the second.
This page walks through
setting up a basic status line
, explains
how the data flows
from Claude Code to your script, lists
all the fields you can display
, and provides
ready-to-use examples
for common patterns like git status, cost tracking, and progress bars.
​
Set up a status line
Use the
/statusline
command
to have Claude Code generate a script for you, or
manually create a script
and add it to your settings.
​
Use the /statusline command
The
/statusline
command accepts natural language instructions describing what you want displayed. Claude Code generates a script file in
~/.claude/
and updates your settings automatically:
/statusline show model name and context percentage with a progress bar
​
Manually configure a status line
Add a
statusLine
field to your user settings (
~/.claude/settings.json
, where
~
is your home directory) or
project settings
. Set
type
to
"command"
and point
command
to a script path or an inline shell command. For a full walkthrough of creating a script, see
Build a status line step by step
.
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
,
"padding"
:
2
}
}
The
command
field runs in a shell, so you can also use inline commands instead of a script file. This example uses
jq
to parse the JSON input and display the model name and context percentage:
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"jq -r '
\"
[
\\
(.model.display_name)]
\\
(.context_window.used_percentage // 0)% context
\"
'"
}
}
The optional
padding
field adds extra horizontal spacing (in characters) to the status line content. Defaults to
0
. This padding is in addition to the interface’s built-in spacing, so it controls relative indentation rather than absolute distance from the terminal edge.
The optional
refreshInterval
field re-runs your command every N seconds in addition to the
event-driven updates
. The minimum is
1
. Set this when your status line shows time-based data such as a clock, or when background subagents change git state while the main session is idle. Leave it unset to run only on events.
The optional
hideVimModeIndicator
field suppresses the built-in
-- INSERT --
text below the prompt. Set this to
true
when your script renders
vim.mode
itself, so the mode is not shown twice.
​
Disable the status line
Run
/statusline
and ask it to remove or clear your status line (e.g.,
/statusline delete
,
/statusline clear
,
/statusline remove it
). You can also manually delete the
statusLine
field from your settings.json.
​
Build a status line step by step
This walkthrough shows what’s happening under the hood by manually creating a status line that displays the current model, working directory, and context window usage percentage.
Running
/statusline
with a description of what you want configures all of this for you automatically.
These examples use Bash scripts, which work on macOS and Linux. On Windows, see
Windows configuration
for PowerShell and Git Bash examples.
1
Create a script that reads JSON and prints output
Claude Code sends JSON data to your script via stdin. This script uses
jq
, a command-line JSON parser you may need to install, to extract the model name, directory, and context percentage, then prints a formatted line.
Save this to
~/.claude/statusline.sh
(where
~
is your home directory, such as
/Users/username
on macOS or
/home/username
on Linux):
#!/bin/bash
# Read JSON data that Claude Code sends to stdin
input
=
$(
cat
)
# Extract fields using jq
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
# The "// 0" provides a fallback if the field is null
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
# Output the status line - ${DIR##*/} extracts just the folder name
echo
"[
$MODEL
] 📁 ${
DIR
##*/
} | ${
PCT
}% context"
2
Make it executable
Mark the script as executable so your shell can run it:
chmod
+x
~/.claude/statusline.sh
3
Add to settings
Tell Claude Code to run your script as the status line. Add this configuration to
~/.claude/settings.json
, which sets
type
to
"command"
(meaning “run this shell command”) and points
command
to your script:
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
}
}
Your status line appears at the bottom of the interface. Settings reload automatically, but changes won’t appear until your next interaction with Claude Code.
​
How status lines work
Claude Code runs your script and pipes
JSON session data
to it via stdin. Your script reads the JSON, extracts what it needs, and prints text to stdout. Claude Code displays whatever your script prints.
When it updates
Your script runs after each new assistant message, after
/compact
finishes, when the permission mode changes, or when vim mode toggles. Updates are debounced at 300ms, meaning rapid changes batch together and your script runs once things settle. If a new update triggers while your script is still running, the in-flight execution is cancelled. If you edit your script, the changes won’t appear until your next interaction with Claude Code triggers an update.
These triggers can go quiet when the main session is idle, for example while a coordinator waits on background subagents. To keep time-based or externally-sourced segments current during idle periods, set
refreshInterval
to also re-run the command on a fixed timer.
What your script can output
Multiple lines
: each
echo
or
print
statement displays as a separate row. See the
multi-line example
.
Colors
: use
ANSI escape codes
like
\033[32m
for green (terminal must support them). See the
git status example
.
Links
: use
OSC 8 escape sequences
to make text clickable (Cmd+click on macOS, Ctrl+click on Windows/Linux). Requires a terminal that supports hyperlinks like iTerm2, Kitty, or WezTerm. See the
clickable links example
.
The status line runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including autocomplete suggestions, the help menu, and permission prompts.
​
Available data
Claude Code sends the following JSON fields to your script via stdin:
Field
Description
model.id
,
model.display_name
Current model identifier and display name
cwd
,
workspace.current_dir
Current working directory. Both fields contain the same value;
workspace.current_dir
is preferred for consistency with
workspace.project_dir
.
workspace.project_dir
Directory where Claude Code was launched, which may differ from
cwd
if the working directory changes during a session
workspace.added_dirs
Additional directories added via
/add-dir
or
--add-dir
. Empty array if none have been added
workspace.git_worktree
Git worktree name when the current directory is inside a linked worktree created with
git worktree add
. Absent in the main working tree. Populated for any git worktree, unlike
worktree.*
which applies only to
--worktree
sessions
cost.total_cost_usd
Estimated session cost in USD, computed client-side. May differ from your actual bill
cost.total_duration_ms
Total wall-clock time since the session started, in milliseconds
cost.total_api_duration_ms
Total time spent waiting for API responses in milliseconds
cost.total_lines_added
,
cost.total_lines_removed
Lines of code changed
context_window.total_input_tokens
,
context_window.total_output_tokens
Token counts currently in the context window, from the most recent API response. Input includes cache reads and writes. Before v2.1.132 these were cumulative session totals
context_window.context_window_size
Maximum context window size in tokens. 200000 by default, or 1000000 for models with extended context.
context_window.used_percentage
Pre-calculated percentage of context window used
context_window.remaining_percentage
Pre-calculated percentage of context window remaining
context_window.current_usage
Token counts from the last API call, described in
context window fields
exceeds_200k_tokens
Whether the total token count (input, cache, and output tokens combined) from the most recent API response exceeds 200k. This is a fixed threshold regardless of actual context window size.
effort.level
Current reasoning effort (
low
,
medium
,
high
,
xhigh
, or
max
). Reflects the live session value, including mid-session
/effort
changes. Absent when the current model does not support the effort parameter
thinking.enabled
Whether extended thinking is enabled for the session
rate_limits.five_hour.used_percentage
,
rate_limits.seven_day.used_percentage
Percentage of the 5-hour or 7-day rate limit consumed, from 0 to 100
rate_limits.five_hour.resets_at
,
rate_limits.seven_day.resets_at
Unix epoch seconds when the 5-hour or 7-day rate limit window resets
session_id
Unique session identifier
session_name
Custom session name set with the
--name
flag or
/rename
. Absent if no custom name has been set
transcript_path
Path to conversation transcript file
version
Claude Code version
output_style.name
Name of the current output style
vim.mode
Current vim mode (
NORMAL
,
INSERT
,
VISUAL
, or
VISUAL LINE
) when
vim mode
is enabled
agent.name
Agent name when running with the
--agent
flag or agent settings configured
worktree.name
Name of the active worktree. Present only during
--worktree
sessions
worktree.path
Absolute path to the worktree directory
worktree.branch
Git branch name for the worktree (for example,
"worktree-my-feature"
). Absent for hook-based worktrees
worktree.original_cwd
The directory Claude was in before entering the worktree
worktree.original_branch
Git branch checked out before entering the worktree. Absent for hook-based worktrees
Full JSON schema
Your status line command receives this JSON structure via stdin:
{
"cwd"
:
"/current/working/directory"
,
"session_id"
:
"abc123..."
,
"session_name"
:
"my-session"
,
"transcript_path"
:
"/path/to/transcript.jsonl"
,
"model"
: {
"id"
:
"claude-opus-4-7"
,
"display_name"
:
"Opus"
},
"workspace"
: {
"current_dir"
:
"/current/working/directory"
,
"project_dir"
:
"/original/project/directory"
,
"added_dirs"
: [],
"git_worktree"
:
"feature-xyz"
},
"version"
:
"2.1.90"
,
"output_style"
: {
"name"
:
"default"
},
"cost"
: {
"total_cost_usd"
:
0.01234
,
"total_duration_ms"
:
45000
,
"total_api_duration_ms"
:
2300
,
"total_lines_added"
:
156
,
"total_lines_removed"
:
23
},
"context_window"
: {
"total_input_tokens"
:
15500
,
"total_output_tokens"
:
1200
,
"context_window_size"
:
200000
,
"used_percentage"
:
8
,
"remaining_percentage"
:
92
,
"current_usage"
: {
"input_tokens"
:
8500
,
"output_tokens"
:
1200
,
"cache_creation_input_tokens"
:
5000
,
"cache_read_input_tokens"
:
2000
}
},
"exceeds_200k_tokens"
:
false
,
"effort"
: {
"level"
:
"high"
},
"thinking"
: {
"enabled"
:
true
},
"rate_limits"
: {
"five_hour"
: {
"used_percentage"
:
23.5
,
"resets_at"
:
1738425600
},
"seven_day"
: {
"used_percentage"
:
41.2
,
"resets_at"
:
1738857600
}
},
"vim"
: {
"mode"
:
"NORMAL"
},
"agent"
: {
"name"
:
"security-reviewer"
},
"worktree"
: {
"name"
:
"my-feature"
,
"path"
:
"/path/to/.claude/worktrees/my-feature"
,
"branch"
:
"worktree-my-feature"
,
"original_cwd"
:
"/path/to/project"
,
"original_branch"
:
"main"
}
}
Fields that may be absent
(not present in JSON):
session_name
: appears only when a custom name has been set with
--name
or
/rename
workspace.git_worktree
: appears only when the current directory is inside a linked git worktree
effort
: appears only when the current model supports the reasoning effort parameter
vim
: appears only when vim mode is enabled
agent
: appears only when running with the
--agent
flag or agent settings configured
worktree
: appears only during
--worktree
sessions. When present,
branch
and
original_branch
may also be absent for hook-based worktrees
rate_limits
: appears only for Claude.ai subscribers (Pro/Max) after the first API response in the session. Each window (
five_hour
,
seven_day
) may be independently absent. Use
jq -r '.rate_limits.five_hour.used_percentage // empty'
to handle absence gracefully.
Fields that may be
null
:
context_window.current_usage
:
null
before the first API call in a session, and again after
/compact
until the next API call repopulates it
context_window.used_percentage
,
context_window.remaining_percentage
: may be
null
early in the session
Handle missing fields with conditional access and null values with fallback defaults in your scripts.
​
Context window fields
The
context_window
object describes the live context window from the most recent API response. As of v2.1.132,
total_input_tokens
and
total_output_tokens
reflect current context usage, not cumulative session totals.
Combined totals
(
total_input_tokens
,
total_output_tokens
): tokens currently in the context window.
total_input_tokens
is the sum of
input_tokens
,
cache_creation_input_tokens
, and
cache_read_input_tokens
;
total_output_tokens
is the output tokens from the most recent response. Both are
0
before the first API response.
Per-component usage
(
current_usage
): the same token counts broken out by category. Use this when you need cache hits separate from fresh input.
The
current_usage
object contains:
input_tokens
: input tokens in current context
output_tokens
: output tokens generated
cache_creation_input_tokens
: tokens written to cache
cache_read_input_tokens
: tokens read from cache
The
used_percentage
field is calculated from input tokens only:
input_tokens + cache_creation_input_tokens + cache_read_input_tokens
. It does not include
output_tokens
.
If you calculate context percentage manually from
current_usage
, use the same input-only formula to match
used_percentage
.
The
current_usage
object is
null
before the first API call in a session, and again immediately after
/compact
until the next API call repopulates it.
​
Examples
These examples show common status line patterns. To use any example:
Save the script to a file like
~/.claude/statusline.sh
(or
.py
/
.js
)
Make it executable:
chmod +x ~/.claude/statusline.sh
Add the path to your
settings
The Bash examples use
jq
to parse JSON. Python and Node.js have built-in JSON parsing.
​
Context window usage
Display the current model and context window usage with a visual progress bar. Each script reads JSON from stdin, extracts the
used_percentage
field, and builds a 10-character bar where filled blocks (▓) represent usage:
Bash
Python
Node.js
#!/bin/bash
# Read all of stdin into a variable
input
=
$(
cat
)
# Extract fields with jq, "// 0" provides fallback for null
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
# Build progress bar: printf -v creates a run of spaces, then
# ${var// /▓} replaces each space with a block character
BAR_WIDTH
=
10
FILLED
=
$((
PCT
*
BAR_WIDTH
/
100
))
EMPTY
=
$((
BAR_WIDTH
-
FILLED
))
BAR
=
""
[
"
$FILLED
"
-gt
0
] &&
printf
-v
FILL
"%${
FILLED
}s"
&&
BAR
=
"${
FILL
//
/
▓}"
[
"
$EMPTY
"
-gt
0
] &&
printf
-v
PAD
"%${
EMPTY
}s"
&&
BAR
=
"${
BAR
}${
PAD
//
/
░}"
echo
"[
$MODEL
]
$BAR
$PCT
%"
​
Git status with colors
Show git branch with color-coded indicators for staged and modified files. This script uses
ANSI escape codes
for terminal colors:
\033[32m
is green,
\033[33m
is yellow, and
\033[0m
resets to default.
Each script checks if the current directory is a git repository, counts staged and modified files, and displays color-coded indicators:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
GREEN
=
'\033[32m'
YELLOW
=
'\033[33m'
RESET
=
'\033[0m'
if
git
rev-parse
--git-dir
>
/dev/null
2>&1
;
then
BRANCH
=
$(
git
branch
--show-current
2>
/dev/null
)
STAGED
=
$(
git
diff
--cached
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
MODIFIED
=
$(
git
diff
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
GIT_STATUS
=
""
[
"
$STAGED
"
-gt
0
] &&
GIT_STATUS
=
"${
GREEN
}+${
STAGED
}${
RESET
}"
[
"
$MODIFIED
"
-gt
0
] &&
GIT_STATUS
=
"${
GIT_STATUS
}${
YELLOW
}~${
MODIFIED
}${
RESET
}"
echo
-e
"[
$MODEL
] 📁 ${
DIR
##*/
} | 🌿
$BRANCH
$GIT_STATUS
"
else
echo
"[
$MODEL
] 📁 ${
DIR
##*/
}"
fi
​
Cost and duration tracking
Track your session’s API costs and elapsed time. The
cost.total_cost_usd
field accumulates the estimated cost of all API calls in the current session. The
cost.total_duration_ms
field measures total elapsed time since the session started, while
cost.total_api_duration_ms
tracks only the time spent waiting for API responses.
Each script formats cost as currency and converts milliseconds to minutes and seconds:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
COST
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_cost_usd // 0'
)
DURATION_MS
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_duration_ms // 0'
)
COST_FMT
=
$(
printf
'$%.2f'
"
$COST
"
)
DURATION_SEC
=
$((
DURATION_MS
/
1000
))
MINS
=
$((
DURATION_SEC
/
60
))
SECS
=
$((
DURATION_SEC
%
60
))
echo
"[
$MODEL
] 💰
$COST_FMT
| ⏱️ ${
MINS
}m ${
SECS
}s"
​
Display multiple lines
Your script can output multiple lines to create a richer display. Each
echo
statement produces a separate row in the status area.
This example combines several techniques: threshold-based colors (green under 70%, yellow 70-89%, red 90%+), a progress bar, and git branch info. Each
print
or
echo
statement creates a separate row:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
COST
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_cost_usd // 0'
)
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
DURATION_MS
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_duration_ms // 0'
)
CYAN
=
'\033[36m'
;
GREEN
=
'\033[32m'
;
YELLOW
=
'\033[33m'
;
RED
=
'\033[31m'
;
RESET
=
'\033[0m'
# Pick bar color based on context usage
if
[
"
$PCT
"
-ge
90
];
then
BAR_COLOR
=
"
$RED
"
elif
[
"
$PCT
"
-ge
70
];
then
BAR_COLOR
=
"
$YELLOW
"
else
BAR_COLOR
=
"
$GREEN
"
;
fi
FILLED
=
$((
PCT
/
10
));
EMPTY
=
$((
10
-
FILLED
))
printf
-v
FILL
"%${
FILLED
}s"
;
printf
-v
PAD
"%${
EMPTY
}s"
BAR
=
"${
FILL
//
/
█}${
PAD
//
/
░}"
MINS
=
$((
DURATION_MS
/
60000
));
SECS
=
$(((
DURATION_MS
%
60000
)
/
1000
))
BRANCH
=
""
git
rev-parse
--git-dir
>
/dev/null
2>&1
&&
BRANCH
=
" | 🌿 $(
git
branch
--show-current
2>
/dev/null)"
echo
-e
"${
CYAN
}[
$MODEL
]${
RESET
} 📁 ${
DIR
##*/
}
$BRANCH
"
COST_FMT
=
$(
printf
'$%.2f'
"
$COST
"
)
echo
-e
"${
BAR_COLOR
}${
BAR
}${
RESET
} ${
PCT
}% | ${
YELLOW
}${
COST_FMT
}${
RESET
} | ⏱️ ${
MINS
}m ${
SECS
}s"
​
Clickable links
This example creates a clickable link to your GitHub repository. It reads the git remote URL, converts SSH format to HTTPS with
sed
, and wraps the repo name in OSC 8 escape codes. Hold Cmd (macOS) or Ctrl (Windows/Linux) and click to open the link in your browser.
Each script gets the git remote URL, converts SSH format to HTTPS, and wraps the repo name in OSC 8 escape codes. The Bash version uses
printf '%b'
which interprets backslash escapes more reliably than
echo -e
across different shells:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
# Convert git SSH URL to HTTPS
REMOTE
=
$(
git
remote
get-url
origin
2>
/dev/null
|
sed
's/git@github.com:/https:\/\/github.com\//'
|
sed
's/\.git$//'
)
if
[
-n
"
$REMOTE
"
];
then
REPO_NAME
=
$(
basename
"
$REMOTE
"
)
# OSC 8 format: \e]8;;URL\a then TEXT then \e]8;;\a
# printf %b interprets escape sequences reliably across shells
printf
'%b'
"[
$MODEL
] 🔗 \e]8;;${
REMOTE
}\a${
REPO_NAME
}\e]8;;\a\n"
else
echo
"[
$MODEL
]"
fi
​
Rate limit usage
Display Claude.ai subscription rate limit usage in the status line. The
rate_limits
object contains
five_hour
(5-hour rolling window) and
seven_day
(weekly) windows. Each window provides
used_percentage
(0-100) and
resets_at
(Unix epoch seconds when the window resets).
This field is only present for Claude.ai subscribers (Pro/Max) after the first API response. Each script handles the absent field gracefully:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
# "// empty" produces no output when rate_limits is absent
FIVE_H
=
$(
echo
"
$input
"
|
jq
-r
'.rate_limits.five_hour.used_percentage // empty'
)
WEEK
=
$(
echo
"
$input
"
|
jq
-r
'.rate_limits.seven_day.used_percentage // empty'
)
LIMITS
=
""
[
-n
"
$FIVE_H
"
] &&
LIMITS
=
"5h: $(
printf
'%.0f' "
$FIVE_H
")%"
[
-n
"
$WEEK
"
] &&
LIMITS
=
"${
LIMITS
:
+
$LIMITS
}7d: $(
printf
'%.0f' "
$WEEK
")%"
[
-n
"
$LIMITS
"
] &&
echo
"[
$MODEL
] |
$LIMITS
"
||
echo
"[
$MODEL
]"
​
Cache expensive operations
Your status line script runs frequently during active sessions. Commands like
git status
or
git diff
can be slow, especially in large repositories. This example caches git information to a temp file and only refreshes it every 5 seconds.
The cache filename needs to be stable across status line invocations within a session, but unique across sessions so concurrent sessions in different repositories don’t read each other’s cached git state. Process-based identifiers like
$$
,
os.getpid()
, or
process.pid
change on every invocation and defeat the cache. Use the
session_id
from the JSON input instead: it’s stable for the lifetime of a session and unique per session.
Each script checks if the cache file is missing or older than 5 seconds before running git commands:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
SESSION_ID
=
$(
echo
"
$input
"
|
jq
-r
'.session_id'
)
CACHE_FILE
=
"/tmp/statusline-git-cache-
$SESSION_ID
"
CACHE_MAX_AGE
=
5
# seconds
cache_is_stale
() {
[
!
-f
"
$CACHE_FILE
"
]
||
\
# stat -f %m is macOS, stat -c %Y is Linux
[ $(($(
date
+%s
) - $(
stat
-f
%m
"
$CACHE_FILE
"
2>
/dev/null
||
stat
-c
%Y
"
$CACHE_FILE
"
2>
/dev/null
||
echo
0
)))
-gt
$CACHE_MAX_AGE
]
}
if
cache_is_stale
;
then
if
git
rev-parse
--git-dir
>
/dev/null
2>&1
;
then
BRANCH
=
$(
git
branch
--show-current
2>
/dev/null
)
STAGED
=
$(
git
diff
--cached
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
MODIFIED
=
$(
git
diff
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
echo
"
$BRANCH
|
$STAGED
|
$MODIFIED
"
>
"
$CACHE_FILE
"
else
echo
"||"
>
"
$CACHE_FILE
"
fi
fi
IFS
=
'|'
read
-r
BRANCH
STAGED
MODIFIED
<
"
$CACHE_FILE
"
if
[
-n
"
$BRANCH
"
];
then
echo
"[
$MODEL
] 📁 ${
DIR
##*/
} | 🌿
$BRANCH
+
$STAGED
~
$MODIFIED
"
else
echo
"[
$MODEL
] 📁 ${
DIR
##*/
}"
fi
​
Windows configuration
On Windows, Claude Code runs status line commands through Git Bash when Git Bash is installed, or through PowerShell when Git Bash is absent. To run a PowerShell script as your status line, invoke it via
powershell
; this works from either shell:
settings.json
statusline.ps1
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
}
}
Or, when Git Bash is installed, run a Bash script directly:
settings.json
statusline.sh
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
}
}
​
Subagent status lines
The
subagentStatusLine
setting renders a custom row body for each
subagent
shown in the agent panel below the prompt. Use it to replace the default
name · description · token count
row with your own formatting.
{
"subagentStatusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/subagent-statusline.sh"
}
}
The command runs once per refresh tick with all visible subagent rows passed as a single JSON object on stdin. The input includes the
base hook fields
plus
columns
(the usable row width) and a
tasks
array, where each task has
id
,
name
,
type
,
status
,
description
,
label
,
startTime
,
tokenCount
,
tokenSamples
, and
cwd
.
Write one JSON line to stdout per row you want to override, in the form
{"id": "<task id>", "content": "<row body>"}
. The
content
string is rendered as-is, including ANSI colors and OSC 8 hyperlinks. Omit a task’s
id
to keep the default rendering for that row; emit an empty
content
string to hide it.
The same trust and
disableAllHooks
gates that apply to
statusLine
apply here. Plugins can ship a default
subagentStatusLine
in their
settings.json
.
​
Tips
Test with mock input
:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ./statusline.sh
Keep output short
: the status bar has limited width, so long output may get truncated or wrap awkwardly
Cache slow operations
: your script runs frequently during active sessions, so commands like
git status
can cause lag. See the
caching example
for how to handle this.
Community projects like
ccstatusline
and
starship-claude
provide pre-built configurations with themes and additional features.
​
Troubleshooting
Status line not appearing
Verify your script is executable:
chmod +x ~/.claude/statusline.sh
Check that your script outputs to stdout, not stderr
Run your script manually to verify it produces output
If
disableAllHooks
is set to
true
in your settings, the status line is also disabled. Remove this setting or set it to
false
to re-enable.
Run
claude --debug
to log the exit code and stderr from the first status line invocation in a session
Ask Claude to read your settings file and execute the
statusLine
command directly to surface errors
Status line shows
--
or empty values
Fields may be
null
before the first API response completes
Handle null values in your script with fallbacks such as
// 0
in jq
Restart Claude Code if values remain empty after multiple messages
Context percentage shows unexpected values
Use
used_percentage
for the simplest accurate context state
Context percentage may differ from
/context
output due to when each is calculated
OSC 8 links not clickable
Verify your terminal supports OSC 8 hyperlinks (iTerm2, Kitty, WezTerm)
Terminal.app does not support clickable links
If link text appears but isn’t clickable, Claude Code may not have detected hyperlink support in your terminal. This commonly affects Windows Terminal and other emulators not in the auto-detection list. Set the
FORCE_HYPERLINK
environment variable to override detection before launching Claude Code:
FORCE_HYPERLINK
=
1
claude
In PowerShell, set the variable in the current session first:
$
env:
FORCE_HYPERLINK
=
"1"
; claude
SSH and tmux sessions may strip OSC sequences depending on configuration
If escape sequences appear as literal text like
\e]8;;
, use
printf '%b'
instead of
echo -e
for more reliable escape handling
Display glitches with escape sequences
Complex escape sequences (ANSI colors, OSC 8 links) can occasionally cause garbled output if they overlap with other UI updates
If you see corrupted text, try simplifying your script to plain text output
Multi-line status lines with escape codes are more prone to rendering issues than single-line plain text
Workspace trust required
The status line command only runs if you’ve accepted the workspace trust dialog for the current directory. Because
statusLine
executes a shell command, it requires the same trust acceptance as hooks and other shell-executing settings.
If trust isn’t accepted, you’ll see the notification
statusline skipped · restart to fix
instead of your status line output. Restart Claude Code and accept the trust prompt to enable it.
Script errors or hangs
Scripts that exit with non-zero codes or produce no output cause the status line to go blank
Slow scripts block the status line from updating until they complete. Keep scripts fast to avoid stale output.
If a new update triggers while a slow script is running, the in-flight script is cancelled
Test your script independently with mock input before configuring it
Notifications share the status line row
System notifications like MCP server errors and auto-updates display on the right side of the same row as your status line. Transient notifications such as the context-low warning also cycle through this area.
Enabling verbose mode adds a token counter to this area
On narrow terminals, these notifications may truncate your status line output
Was this page helpful?
Yes
No
Voice dictation
Customize keyboard shortcuts
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/statusline" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize your status line
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Interface
Customize your status line
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The status line is a customizable bar at the bottom of Claude Code that runs any shell script you configure. It receives JSON session data on stdin and displays whatever your script prints, giving you a persistent, at-a-glance view of context usage, costs, git status, or anything else you want to track.
Status lines are useful when you:
Want to monitor context window usage as you work
Need to track session costs
Work across multiple sessions and need to distinguish them
Want git branch and status always visible
Here’s an example of a
multi-line status line
that displays git info on the first line and a color-coded context bar on the second.
This page walks through
setting up a basic status line
, explains
how the data flows
from Claude Code to your script, lists
all the fields you can display
, and provides
ready-to-use examples
for common patterns like git status, cost tracking, and progress bars.
​
Set up a status line
Use the
/statusline
command
to have Claude Code generate a script for you, or
manually create a script
and add it to your settings.
​
Use the /statusline command
The
/statusline
command accepts natural language instructions describing what you want displayed. Claude Code generates a script file in
~/.claude/
and updates your settings automatically:
/statusline show model name and context percentage with a progress bar
​
Manually configure a status line
Add a
statusLine
field to your user settings (
~/.claude/settings.json
, where
~
is your home directory) or
project settings
. Set
type
to
"command"
and point
command
to a script path or an inline shell command. For a full walkthrough of creating a script, see
Build a status line step by step
.
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
,
"padding"
:
2
}
}
The
command
field runs in a shell, so you can also use inline commands instead of a script file. This example uses
jq
to parse the JSON input and display the model name and context percentage:
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"jq -r '
\"
[
\\
(.model.display_name)]
\\
(.context_window.used_percentage // 0)% context
\"
'"
}
}
The optional
padding
field adds extra horizontal spacing (in characters) to the status line content. Defaults to
0
. This padding is in addition to the interface’s built-in spacing, so it controls relative indentation rather than absolute distance from the terminal edge.
The optional
refreshInterval
field re-runs your command every N seconds in addition to the
event-driven updates
. The minimum is
1
. Set this when your status line shows time-based data such as a clock, or when background subagents change git state while the main session is idle. Leave it unset to run only on events.
The optional
hideVimModeIndicator
field suppresses the built-in
-- INSERT --
text below the prompt. Set this to
true
when your script renders
vim.mode
itself, so the mode is not shown twice.
​
Disable the status line
Run
/statusline
and ask it to remove or clear your status line (e.g.,
/statusline delete
,
/statusline clear
,
/statusline remove it
). You can also manually delete the
statusLine
field from your settings.json.
​
Build a status line step by step
This walkthrough shows what’s happening under the hood by manually creating a status line that displays the current model, working directory, and context window usage percentage.
Running
/statusline
with a description of what you want configures all of this for you automatically.
These examples use Bash scripts, which work on macOS and Linux. On Windows, see
Windows configuration
for PowerShell and Git Bash examples.
1
Create a script that reads JSON and prints output
Claude Code sends JSON data to your script via stdin. This script uses
jq
, a command-line JSON parser you may need to install, to extract the model name, directory, and context percentage, then prints a formatted line.
Save this to
~/.claude/statusline.sh
(where
~
is your home directory, such as
/Users/username
on macOS or
/home/username
on Linux):
#!/bin/bash
# Read JSON data that Claude Code sends to stdin
input
=
$(
cat
)
# Extract fields using jq
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
# The "// 0" provides a fallback if the field is null
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
# Output the status line - ${DIR##*/} extracts just the folder name
echo
"[
$MODEL
] 📁 ${
DIR
##*/
} | ${
PCT
}% context"
2
Make it executable
Mark the script as executable so your shell can run it:
chmod
+x
~/.claude/statusline.sh
3
Add to settings
Tell Claude Code to run your script as the status line. Add this configuration to
~/.claude/settings.json
, which sets
type
to
"command"
(meaning “run this shell command”) and points
command
to your script:
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
}
}
Your status line appears at the bottom of the interface. Settings reload automatically, but changes won’t appear until your next interaction with Claude Code.
​
How status lines work
Claude Code runs your script and pipes
JSON session data
to it via stdin. Your script reads the JSON, extracts what it needs, and prints text to stdout. Claude Code displays whatever your script prints.
When it updates
Your script runs after each new assistant message, after
/compact
finishes, when the permission mode changes, or when vim mode toggles. Updates are debounced at 300ms, meaning rapid changes batch together and your script runs once things settle. If a new update triggers while your script is still running, the in-flight execution is cancelled. If you edit your script, the changes won’t appear until your next interaction with Claude Code triggers an update.
These triggers can go quiet when the main session is idle, for example while a coordinator waits on background subagents. To keep time-based or externally-sourced segments current during idle periods, set
refreshInterval
to also re-run the command on a fixed timer.
What your script can output
Multiple lines
: each
echo
or
print
statement displays as a separate row. See the
multi-line example
.
Colors
: use
ANSI escape codes
like
\033[32m
for green (terminal must support them). See the
git status example
.
Links
: use
OSC 8 escape sequences
to make text clickable (Cmd+click on macOS, Ctrl+click on Windows/Linux). Requires a terminal that supports hyperlinks like iTerm2, Kitty, or WezTerm. See the
clickable links example
.
The status line runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including autocomplete suggestions, the help menu, and permission prompts.
​
Available data
Claude Code sends the following JSON fields to your script via stdin:
Field
Description
model.id
,
model.display_name
Current model identifier and display name
cwd
,
workspace.current_dir
Current working directory. Both fields contain the same value;
workspace.current_dir
is preferred for consistency with
workspace.project_dir
.
workspace.project_dir
Directory where Claude Code was launched, which may differ from
cwd
if the working directory changes during a session
workspace.added_dirs
Additional directories added via
/add-dir
or
--add-dir
. Empty array if none have been added
workspace.git_worktree
Git worktree name when the current directory is inside a linked worktree created with
git worktree add
. Absent in the main working tree. Populated for any git worktree, unlike
worktree.*
which applies only to
--worktree
sessions
cost.total_cost_usd
Estimated session cost in USD, computed client-side. May differ from your actual bill
cost.total_duration_ms
Total wall-clock time since the session started, in milliseconds
cost.total_api_duration_ms
Total time spent waiting for API responses in milliseconds
cost.total_lines_added
,
cost.total_lines_removed
Lines of code changed
context_window.total_input_tokens
,
context_window.total_output_tokens
Token counts currently in the context window, from the most recent API response. Input includes cache reads and writes. Before v2.1.132 these were cumulative session totals
context_window.context_window_size
Maximum context window size in tokens. 200000 by default, or 1000000 for models with extended context.
context_window.used_percentage
Pre-calculated percentage of context window used
context_window.remaining_percentage
Pre-calculated percentage of context window remaining
context_window.current_usage
Token counts from the last API call, described in
context window fields
exceeds_200k_tokens
Whether the total token count (input, cache, and output tokens combined) from the most recent API response exceeds 200k. This is a fixed threshold regardless of actual context window size.
effort.level
Current reasoning effort (
low
,
medium
,
high
,
xhigh
, or
max
). Reflects the live session value, including mid-session
/effort
changes. Absent when the current model does not support the effort parameter
thinking.enabled
Whether extended thinking is enabled for the session
rate_limits.five_hour.used_percentage
,
rate_limits.seven_day.used_percentage
Percentage of the 5-hour or 7-day rate limit consumed, from 0 to 100
rate_limits.five_hour.resets_at
,
rate_limits.seven_day.resets_at
Unix epoch seconds when the 5-hour or 7-day rate limit window resets
session_id
Unique session identifier
session_name
Custom session name set with the
--name
flag or
/rename
. Absent if no custom name has been set
transcript_path
Path to conversation transcript file
version
Claude Code version
output_style.name
Name of the current output style
vim.mode
Current vim mode (
NORMAL
,
INSERT
,
VISUAL
, or
VISUAL LINE
) when
vim mode
is enabled
agent.name
Agent name when running with the
--agent
flag or agent settings configured
worktree.name
Name of the active worktree. Present only during
--worktree
sessions
worktree.path
Absolute path to the worktree directory
worktree.branch
Git branch name for the worktree (for example,
"worktree-my-feature"
). Absent for hook-based worktrees
worktree.original_cwd
The directory Claude was in before entering the worktree
worktree.original_branch
Git branch checked out before entering the worktree. Absent for hook-based worktrees
Full JSON schema
Your status line command receives this JSON structure via stdin:
{
"cwd"
:
"/current/working/directory"
,
"session_id"
:
"abc123..."
,
"session_name"
:
"my-session"
,
"transcript_path"
:
"/path/to/transcript.jsonl"
,
"model"
: {
"id"
:
"claude-opus-4-7"
,
"display_name"
:
"Opus"
},
"workspace"
: {
"current_dir"
:
"/current/working/directory"
,
"project_dir"
:
"/original/project/directory"
,
"added_dirs"
: [],
"git_worktree"
:
"feature-xyz"
},
"version"
:
"2.1.90"
,
"output_style"
: {
"name"
:
"default"
},
"cost"
: {
"total_cost_usd"
:
0.01234
,
"total_duration_ms"
:
45000
,
"total_api_duration_ms"
:
2300
,
"total_lines_added"
:
156
,
"total_lines_removed"
:
23
},
"context_window"
: {
"total_input_tokens"
:
15500
,
"total_output_tokens"
:
1200
,
"context_window_size"
:
200000
,
"used_percentage"
:
8
,
"remaining_percentage"
:
92
,
"current_usage"
: {
"input_tokens"
:
8500
,
"output_tokens"
:
1200
,
"cache_creation_input_tokens"
:
5000
,
"cache_read_input_tokens"
:
2000
}
},
"exceeds_200k_tokens"
:
false
,
"effort"
: {
"level"
:
"high"
},
"thinking"
: {
"enabled"
:
true
},
"rate_limits"
: {
"five_hour"
: {
"used_percentage"
:
23.5
,
"resets_at"
:
1738425600
},
"seven_day"
: {
"used_percentage"
:
41.2
,
"resets_at"
:
1738857600
}
},
"vim"
: {
"mode"
:
"NORMAL"
},
"agent"
: {
"name"
:
"security-reviewer"
},
"worktree"
: {
"name"
:
"my-feature"
,
"path"
:
"/path/to/.claude/worktrees/my-feature"
,
"branch"
:
"worktree-my-feature"
,
"original_cwd"
:
"/path/to/project"
,
"original_branch"
:
"main"
}
}
Fields that may be absent
(not present in JSON):
session_name
: appears only when a custom name has been set with
--name
or
/rename
workspace.git_worktree
: appears only when the current directory is inside a linked git worktree
effort
: appears only when the current model supports the reasoning effort parameter
vim
: appears only when vim mode is enabled
agent
: appears only when running with the
--agent
flag or agent settings configured
worktree
: appears only during
--worktree
sessions. When present,
branch
and
original_branch
may also be absent for hook-based worktrees
rate_limits
: appears only for Claude.ai subscribers (Pro/Max) after the first API response in the session. Each window (
five_hour
,
seven_day
) may be independently absent. Use
jq -r '.rate_limits.five_hour.used_percentage // empty'
to handle absence gracefully.
Fields that may be
null
:
context_window.current_usage
:
null
before the first API call in a session, and again after
/compact
until the next API call repopulates it
context_window.used_percentage
,
context_window.remaining_percentage
: may be
null
early in the session
Handle missing fields with conditional access and null values with fallback defaults in your scripts.
​
Context window fields
The
context_window
object describes the live context window from the most recent API response. As of v2.1.132,
total_input_tokens
and
total_output_tokens
reflect current context usage, not cumulative session totals.
Combined totals
(
total_input_tokens
,
total_output_tokens
): tokens currently in the context window.
total_input_tokens
is the sum of
input_tokens
,
cache_creation_input_tokens
, and
cache_read_input_tokens
;
total_output_tokens
is the output tokens from the most recent response. Both are
0
before the first API response.
Per-component usage
(
current_usage
): the same token counts broken out by category. Use this when you need cache hits separate from fresh input.
The
current_usage
object contains:
input_tokens
: input tokens in current context
output_tokens
: output tokens generated
cache_creation_input_tokens
: tokens written to cache
cache_read_input_tokens
: tokens read from cache
The
used_percentage
field is calculated from input tokens only:
input_tokens + cache_creation_input_tokens + cache_read_input_tokens
. It does not include
output_tokens
.
If you calculate context percentage manually from
current_usage
, use the same input-only formula to match
used_percentage
.
The
current_usage
object is
null
before the first API call in a session, and again immediately after
/compact
until the next API call repopulates it.
​
Examples
These examples show common status line patterns. To use any example:
Save the script to a file like
~/.claude/statusline.sh
(or
.py
/
.js
)
Make it executable:
chmod +x ~/.claude/statusline.sh
Add the path to your
settings
The Bash examples use
jq
to parse JSON. Python and Node.js have built-in JSON parsing.
​
Context window usage
Display the current model and context window usage with a visual progress bar. Each script reads JSON from stdin, extracts the
used_percentage
field, and builds a 10-character bar where filled blocks (▓) represent usage:
Bash
Python
Node.js
#!/bin/bash
# Read all of stdin into a variable
input
=
$(
cat
)
# Extract fields with jq, "// 0" provides fallback for null
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
# Build progress bar: printf -v creates a run of spaces, then
# ${var// /▓} replaces each space with a block character
BAR_WIDTH
=
10
FILLED
=
$((
PCT
*
BAR_WIDTH
/
100
))
EMPTY
=
$((
BAR_WIDTH
-
FILLED
))
BAR
=
""
[
"
$FILLED
"
-gt
0
] &&
printf
-v
FILL
"%${
FILLED
}s"
&&
BAR
=
"${
FILL
//
/
▓}"
[
"
$EMPTY
"
-gt
0
] &&
printf
-v
PAD
"%${
EMPTY
}s"
&&
BAR
=
"${
BAR
}${
PAD
//
/
░}"
echo
"[
$MODEL
]
$BAR
$PCT
%"
​
Git status with colors
Show git branch with color-coded indicators for staged and modified files. This script uses
ANSI escape codes
for terminal colors:
\033[32m
is green,
\033[33m
is yellow, and
\033[0m
resets to default.
Each script checks if the current directory is a git repository, counts staged and modified files, and displays color-coded indicators:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
GREEN
=
'\033[32m'
YELLOW
=
'\033[33m'
RESET
=
'\033[0m'
if
git
rev-parse
--git-dir
>
/dev/null
2>&1
;
then
BRANCH
=
$(
git
branch
--show-current
2>
/dev/null
)
STAGED
=
$(
git
diff
--cached
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
MODIFIED
=
$(
git
diff
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
GIT_STATUS
=
""
[
"
$STAGED
"
-gt
0
] &&
GIT_STATUS
=
"${
GREEN
}+${
STAGED
}${
RESET
}"
[
"
$MODIFIED
"
-gt
0
] &&
GIT_STATUS
=
"${
GIT_STATUS
}${
YELLOW
}~${
MODIFIED
}${
RESET
}"
echo
-e
"[
$MODEL
] 📁 ${
DIR
##*/
} | 🌿
$BRANCH
$GIT_STATUS
"
else
echo
"[
$MODEL
] 📁 ${
DIR
##*/
}"
fi
​
Cost and duration tracking
Track your session’s API costs and elapsed time. The
cost.total_cost_usd
field accumulates the estimated cost of all API calls in the current session. The
cost.total_duration_ms
field measures total elapsed time since the session started, while
cost.total_api_duration_ms
tracks only the time spent waiting for API responses.
Each script formats cost as currency and converts milliseconds to minutes and seconds:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
COST
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_cost_usd // 0'
)
DURATION_MS
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_duration_ms // 0'
)
COST_FMT
=
$(
printf
'$%.2f'
"
$COST
"
)
DURATION_SEC
=
$((
DURATION_MS
/
1000
))
MINS
=
$((
DURATION_SEC
/
60
))
SECS
=
$((
DURATION_SEC
%
60
))
echo
"[
$MODEL
] 💰
$COST_FMT
| ⏱️ ${
MINS
}m ${
SECS
}s"
​
Display multiple lines
Your script can output multiple lines to create a richer display. Each
echo
statement produces a separate row in the status area.
This example combines several techniques: threshold-based colors (green under 70%, yellow 70-89%, red 90%+), a progress bar, and git branch info. Each
print
or
echo
statement creates a separate row:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
COST
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_cost_usd // 0'
)
PCT
=
$(
echo
"
$input
"
|
jq
-r
'.context_window.used_percentage // 0'
|
cut
-d.
-f1
)
DURATION_MS
=
$(
echo
"
$input
"
|
jq
-r
'.cost.total_duration_ms // 0'
)
CYAN
=
'\033[36m'
;
GREEN
=
'\033[32m'
;
YELLOW
=
'\033[33m'
;
RED
=
'\033[31m'
;
RESET
=
'\033[0m'
# Pick bar color based on context usage
if
[
"
$PCT
"
-ge
90
];
then
BAR_COLOR
=
"
$RED
"
elif
[
"
$PCT
"
-ge
70
];
then
BAR_COLOR
=
"
$YELLOW
"
else
BAR_COLOR
=
"
$GREEN
"
;
fi
FILLED
=
$((
PCT
/
10
));
EMPTY
=
$((
10
-
FILLED
))
printf
-v
FILL
"%${
FILLED
}s"
;
printf
-v
PAD
"%${
EMPTY
}s"
BAR
=
"${
FILL
//
/
█}${
PAD
//
/
░}"
MINS
=
$((
DURATION_MS
/
60000
));
SECS
=
$(((
DURATION_MS
%
60000
)
/
1000
))
BRANCH
=
""
git
rev-parse
--git-dir
>
/dev/null
2>&1
&&
BRANCH
=
" | 🌿 $(
git
branch
--show-current
2>
/dev/null)"
echo
-e
"${
CYAN
}[
$MODEL
]${
RESET
} 📁 ${
DIR
##*/
}
$BRANCH
"
COST_FMT
=
$(
printf
'$%.2f'
"
$COST
"
)
echo
-e
"${
BAR_COLOR
}${
BAR
}${
RESET
} ${
PCT
}% | ${
YELLOW
}${
COST_FMT
}${
RESET
} | ⏱️ ${
MINS
}m ${
SECS
}s"
​
Clickable links
This example creates a clickable link to your GitHub repository. It reads the git remote URL, converts SSH format to HTTPS with
sed
, and wraps the repo name in OSC 8 escape codes. Hold Cmd (macOS) or Ctrl (Windows/Linux) and click to open the link in your browser.
Each script gets the git remote URL, converts SSH format to HTTPS, and wraps the repo name in OSC 8 escape codes. The Bash version uses
printf '%b'
which interprets backslash escapes more reliably than
echo -e
across different shells:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
# Convert git SSH URL to HTTPS
REMOTE
=
$(
git
remote
get-url
origin
2>
/dev/null
|
sed
's/git@github.com:/https:\/\/github.com\//'
|
sed
's/\.git$//'
)
if
[
-n
"
$REMOTE
"
];
then
REPO_NAME
=
$(
basename
"
$REMOTE
"
)
# OSC 8 format: \e]8;;URL\a then TEXT then \e]8;;\a
# printf %b interprets escape sequences reliably across shells
printf
'%b'
"[
$MODEL
] 🔗 \e]8;;${
REMOTE
}\a${
REPO_NAME
}\e]8;;\a\n"
else
echo
"[
$MODEL
]"
fi
​
Rate limit usage
Display Claude.ai subscription rate limit usage in the status line. The
rate_limits
object contains
five_hour
(5-hour rolling window) and
seven_day
(weekly) windows. Each window provides
used_percentage
(0-100) and
resets_at
(Unix epoch seconds when the window resets).
This field is only present for Claude.ai subscribers (Pro/Max) after the first API response. Each script handles the absent field gracefully:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
# "// empty" produces no output when rate_limits is absent
FIVE_H
=
$(
echo
"
$input
"
|
jq
-r
'.rate_limits.five_hour.used_percentage // empty'
)
WEEK
=
$(
echo
"
$input
"
|
jq
-r
'.rate_limits.seven_day.used_percentage // empty'
)
LIMITS
=
""
[
-n
"
$FIVE_H
"
] &&
LIMITS
=
"5h: $(
printf
'%.0f' "
$FIVE_H
")%"
[
-n
"
$WEEK
"
] &&
LIMITS
=
"${
LIMITS
:
+
$LIMITS
}7d: $(
printf
'%.0f' "
$WEEK
")%"
[
-n
"
$LIMITS
"
] &&
echo
"[
$MODEL
] |
$LIMITS
"
||
echo
"[
$MODEL
]"
​
Cache expensive operations
Your status line script runs frequently during active sessions. Commands like
git status
or
git diff
can be slow, especially in large repositories. This example caches git information to a temp file and only refreshes it every 5 seconds.
The cache filename needs to be stable across status line invocations within a session, but unique across sessions so concurrent sessions in different repositories don’t read each other’s cached git state. Process-based identifiers like
$$
,
os.getpid()
, or
process.pid
change on every invocation and defeat the cache. Use the
session_id
from the JSON input instead: it’s stable for the lifetime of a session and unique per session.
Each script checks if the cache file is missing or older than 5 seconds before running git commands:
Bash
Python
Node.js
#!/bin/bash
input
=
$(
cat
)
MODEL
=
$(
echo
"
$input
"
|
jq
-r
'.model.display_name'
)
DIR
=
$(
echo
"
$input
"
|
jq
-r
'.workspace.current_dir'
)
SESSION_ID
=
$(
echo
"
$input
"
|
jq
-r
'.session_id'
)
CACHE_FILE
=
"/tmp/statusline-git-cache-
$SESSION_ID
"
CACHE_MAX_AGE
=
5
# seconds
cache_is_stale
() {
[
!
-f
"
$CACHE_FILE
"
]
||
\
# stat -f %m is macOS, stat -c %Y is Linux
[ $(($(
date
+%s
) - $(
stat
-f
%m
"
$CACHE_FILE
"
2>
/dev/null
||
stat
-c
%Y
"
$CACHE_FILE
"
2>
/dev/null
||
echo
0
)))
-gt
$CACHE_MAX_AGE
]
}
if
cache_is_stale
;
then
if
git
rev-parse
--git-dir
>
/dev/null
2>&1
;
then
BRANCH
=
$(
git
branch
--show-current
2>
/dev/null
)
STAGED
=
$(
git
diff
--cached
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
MODIFIED
=
$(
git
diff
--numstat
2>
/dev/null
|
wc
-l
|
tr
-d
' '
)
echo
"
$BRANCH
|
$STAGED
|
$MODIFIED
"
>
"
$CACHE_FILE
"
else
echo
"||"
>
"
$CACHE_FILE
"
fi
fi
IFS
=
'|'
read
-r
BRANCH
STAGED
MODIFIED
<
"
$CACHE_FILE
"
if
[
-n
"
$BRANCH
"
];
then
echo
"[
$MODEL
] 📁 ${
DIR
##*/
} | 🌿
$BRANCH
+
$STAGED
~
$MODIFIED
"
else
echo
"[
$MODEL
] 📁 ${
DIR
##*/
}"
fi
​
Windows configuration
On Windows, Claude Code runs status line commands through Git Bash when Git Bash is installed, or through PowerShell when Git Bash is absent. To run a PowerShell script as your status line, invoke it via
powershell
; this works from either shell:
settings.json
statusline.ps1
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
}
}
Or, when Git Bash is installed, run a Bash script directly:
settings.json
statusline.sh
{
"statusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/statusline.sh"
}
}
​
Subagent status lines
The
subagentStatusLine
setting renders a custom row body for each
subagent
shown in the agent panel below the prompt. Use it to replace the default
name · description · token count
row with your own formatting.
{
"subagentStatusLine"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/subagent-statusline.sh"
}
}
The command runs once per refresh tick with all visible subagent rows passed as a single JSON object on stdin. The input includes the
base hook fields
plus
columns
(the usable row width) and a
tasks
array, where each task has
id
,
name
,
type
,
status
,
description
,
label
,
startTime
,
tokenCount
,
tokenSamples
, and
cwd
.
Write one JSON line to stdout per row you want to override, in the form
{"id": "<task id>", "content": "<row body>"}
. The
content
string is rendered as-is, including ANSI colors and OSC 8 hyperlinks. Omit a task’s
id
to keep the default rendering for that row; emit an empty
content
string to hide it.
The same trust and
disableAllHooks
gates that apply to
statusLine
apply here. Plugins can ship a default
subagentStatusLine
in their
settings.json
.
​
Tips
Test with mock input
:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ./statusline.sh
Keep output short
: the status bar has limited width, so long output may get truncated or wrap awkwardly
Cache slow operations
: your script runs frequently during active sessions, so commands like
git status
can cause lag. See the
caching example
for how to handle this.
Community projects like
ccstatusline
and
starship-claude
provide pre-built configurations with themes and additional features.
​
Troubleshooting
Status line not appearing
Verify your script is executable:
chmod +x ~/.claude/statusline.sh
Check that your script outputs to stdout, not stderr
Run your script manually to verify it produces output
If
disableAllHooks
is set to
true
in your settings, the status line is also disabled. Remove this setting or set it to
false
to re-enable.
Run
claude --debug
to log the exit code and stderr from the first status line invocation in a session
Ask Claude to read your settings file and execute the
statusLine
command directly to surface errors
Status line shows
--
or empty values
Fields may be
null
before the first API response completes
Handle null values in your script with fallbacks such as
// 0
in jq
Restart Claude Code if values remain empty after multiple messages
Context percentage shows unexpected values
Use
used_percentage
for the simplest accurate context state
Context percentage may differ from
/context
output due to when each is calculated
OSC 8 links not clickable
Verify your terminal supports OSC 8 hyperlinks (iTerm2, Kitty, WezTerm)
Terminal.app does not support clickable links
If link text appears but isn’t clickable, Claude Code may not have detected hyperlink support in your terminal. This commonly affects Windows Terminal and other emulators not in the auto-detection list. Set the
FORCE_HYPERLINK
environment variable to override detection before launching Claude Code:
FORCE_HYPERLINK
=
1
claude
In PowerShell, set the variable in the current session first:
$
env:
FORCE_HYPERLINK
=
"1"
; claude
SSH and tmux sessions may strip OSC sequences depending on configuration
If escape sequences appear as literal text like
\e]8;;
, use
printf '%b'
instead of
echo -e
for more reliable escape handling
Display glitches with escape sequences
Complex escape sequences (ANSI colors, OSC 8 links) can occasionally cause garbled output if they overlap with other UI updates
If you see corrupted text, try simplifying your script to plain text output
Multi-line status lines with escape codes are more prone to rendering issues than single-line plain text
Workspace trust required
The status line command only runs if you’ve accepted the workspace trust dialog for the current directory. Because
statusLine
executes a shell command, it requires the same trust acceptance as hooks and other shell-executing settings.
If trust isn’t accepted, you’ll see the notification
statusline skipped · restart to fix
instead of your status line output. Restart Claude Code and accept the trust prompt to enable it.
Script errors or hangs
Scripts that exit with non-zero codes or produce no output cause the status line to go blank
Slow scripts block the status line from updating until they complete. Keep scripts fast to avoid stale output.
If a new update triggers while a slow script is running, the in-flight script is cancelled
Test your script independently with mock input before configuring it
Notifications share the status line row
System notifications like MCP server errors and auto-updates display on the right side of the same row as your status line. Transient notifications such as the context-low warning also cycle through this area.
Enabling verbose mode adds a token counter to this area
On narrow terminals, these notifications may truncate your status line output
Was this page helpful?
Yes
No
Voice dictation
Customize keyboard shortcuts
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/statusline" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Monitoring</title>
  <link>https://code.claude.com/docs/en/monitoring-usage</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/monitoring-usage</guid>
  <pubDate>Fri, 01 Mar 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Monitoring
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dep...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Monitoring
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Track Claude Code usage, costs, and tool activity across your organization by exporting telemetry data through OpenTelemetry (OTel). Claude Code exports metrics as time series data via the standard metrics protocol, events via the logs/events protocol, and optionally distributed traces via the
traces protocol
. Configure your metrics, logs, and traces backends to match your monitoring requirements.
​
Quick start
Configure OpenTelemetry using environment variables:
# 1. Enable telemetry
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
# 2. Choose exporters (both are optional - configure only what you need)
export
OTEL_METRICS_EXPORTER
=
otlp
# Options: otlp, prometheus, console, none
export
OTEL_LOGS_EXPORTER
=
otlp
# Options: otlp, console, none
# 3. Configure OTLP endpoint (for OTLP exporter)
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# 4. Set authentication (if required)
export
OTEL_EXPORTER_OTLP_HEADERS
=
"Authorization=Bearer your-token"
# 5. For debugging: reduce export intervals
export
OTEL_METRIC_EXPORT_INTERVAL
=
10000
# 10 seconds (default: 60000ms)
export
OTEL_LOGS_EXPORT_INTERVAL
=
5000
# 5 seconds (default: 5000ms)
# 6. Run Claude Code
claude
The default export intervals are 60 seconds for metrics and 5 seconds for logs. During setup, you may want to use shorter intervals for debugging purposes. Remember to reset these for production use.
For full configuration options, see the
OpenTelemetry specification
.
​
Administrator configuration
Administrators can configure OpenTelemetry settings for all users through the
managed settings file
. This allows for centralized control of telemetry settings across an organization. See the
settings precedence
for more information about how settings are applied.
Example managed settings configuration:
{
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
"OTEL_EXPORTER_OTLP_PROTOCOL"
:
"grpc"
,
"OTEL_EXPORTER_OTLP_ENDPOINT"
:
"http://collector.example.com:4317"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer example-token"
}
}
Managed settings can be distributed via MDM (Mobile Device Management) or other device management solutions. Environment variables defined in the managed settings file have high precedence and cannot be overridden by users.
Claude Code does not pass
OTEL_*
environment variables to the subprocesses it spawns, including the Bash tool, hooks, MCP servers, and language servers. An OpenTelemetry-instrumented application that you run through the Bash tool does not inherit Claude Code’s exporter endpoint or headers, so set those variables directly in the command if that application needs to export its own telemetry.
​
Configuration details
​
Common configuration variables
Environment Variable
Description
Example Values
CLAUDE_CODE_ENABLE_TELEMETRY
Enables telemetry collection (required)
1
OTEL_METRICS_EXPORTER
Metrics exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
prometheus
,
none
OTEL_LOGS_EXPORTER
Logs/events exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
none
OTEL_EXPORTER_OTLP_PROTOCOL
Protocol for OTLP exporter, applies to all signals
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT
OTLP collector endpoint for all signals
http://localhost:4317
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL
Protocol for metrics, overrides general setting
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
OTLP metrics endpoint, overrides general setting
http://localhost:4318/v1/metrics
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL
Protocol for logs, overrides general setting
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
OTLP logs endpoint, overrides general setting
http://localhost:4318/v1/logs
OTEL_EXPORTER_OTLP_HEADERS
Authentication headers for OTLP
Authorization=Bearer token
OTEL_METRIC_EXPORT_INTERVAL
Export interval in milliseconds (default: 60000)
5000
,
60000
OTEL_LOGS_EXPORT_INTERVAL
Logs export interval in milliseconds (default: 5000)
1000
,
10000
OTEL_LOG_USER_PROMPTS
Enable logging of user prompt content (default: disabled)
1
to enable
OTEL_LOG_TOOL_DETAILS
Enable logging of tool parameters and input arguments in tool events and trace span attributes: Bash commands, MCP server and tool names, skill names, and tool input. Also enables custom, plugin, and MCP command names on
user_prompt
events (default: disabled)
1
to enable
OTEL_LOG_TOOL_CONTENT
Enable logging of tool input and output content in span events (default: disabled). Requires
tracing
. Content is truncated at 60 KB
1
to enable
OTEL_LOG_RAW_API_BODIES
Emit the full Anthropic Messages API request and response JSON as
api_request_body
/
api_response_body
log events (default: disabled). Bodies include the entire conversation history. Enabling this implies consent to everything
OTEL_LOG_USER_PROMPTS
,
OTEL_LOG_TOOL_DETAILS
, and
OTEL_LOG_TOOL_CONTENT
would reveal
1
for inline bodies truncated at 60 KB, or
file:<dir>
for untruncated bodies on disk with a
body_ref
pointer in the event
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
Metrics temporality preference (default:
delta
). Set to
cumulative
if your backend expects cumulative temporality
delta
,
cumulative
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes)
900000
​
mTLS authentication
How you configure client certificates for the OTLP exporter depends on the OTLP protocol in use for that signal, set via
OTEL_EXPORTER_OTLP_PROTOCOL
or the per-signal override. The same configuration applies to metrics, logs, and traces.
Protocol
Client certificate variables
Trust the collector’s CA with
http/protobuf
,
http/json
CLAUDE_CODE_CLIENT_CERT
,
CLAUDE_CODE_CLIENT_KEY
, and optionally
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
. See
Network configuration
NODE_EXTRA_CA_CERTS
grpc
OTEL_EXPORTER_OTLP_CLIENT_KEY
and
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE
, or the per-signal variants such as
OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY
to use a different certificate per signal
OTEL_EXPORTER_OTLP_CERTIFICATE
For
grpc
, the OpenTelemetry SDK reads the standard OTLP variables directly, so existing configurations that set the per-signal metrics variables continue to work.
​
Metrics cardinality control
The following environment variables control which attributes are included in metrics to manage cardinality:
Environment Variable
Description
Default Value
Example to Disable
OTEL_METRICS_INCLUDE_SESSION_ID
Include session.id attribute in metrics
true
false
OTEL_METRICS_INCLUDE_VERSION
Include app.version attribute in metrics
false
true
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
Include user.account_uuid and user.account_id attributes in metrics
true
false
These variables help control the cardinality of metrics, which affects storage requirements and query performance in your metrics backend. Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.
​
Traces (beta)
Distributed tracing exports spans that link each user prompt to the API requests and tool executions it triggers, so you can view a full request as a single trace in your tracing backend.
Tracing is off by default. To enable it, set both
CLAUDE_CODE_ENABLE_TELEMETRY=1
and
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
, then set
OTEL_TRACES_EXPORTER
to choose where spans are sent. Traces reuse the
common OTLP configuration
for endpoint, protocol, headers, and
mTLS
.
Environment Variable
Description
Example Values
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA
Enable span tracing (required).
ENABLE_ENHANCED_TELEMETRY_BETA
is also accepted
1
OTEL_TRACES_EXPORTER
Traces exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
none
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL
Protocol for traces, overrides
OTEL_EXPORTER_OTLP_PROTOCOL
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
OTLP traces endpoint, overrides
OTEL_EXPORTER_OTLP_ENDPOINT
http://localhost:4318/v1/traces
OTEL_TRACES_EXPORT_INTERVAL
Span batch export interval in milliseconds (default: 5000)
1000
,
10000
Spans redact user prompt text, tool input details, and tool content by default. Set
OTEL_LOG_USER_PROMPTS=1
,
OTEL_LOG_TOOL_DETAILS=1
, and
OTEL_LOG_TOOL_CONTENT=1
to include them.
When tracing is active, Bash and PowerShell subprocesses automatically inherit a
TRACEPARENT
environment variable containing the W3C trace context of the active tool execution span. This lets any subprocess that reads
TRACEPARENT
parent its own spans under the same trace, enabling end-to-end distributed tracing through scripts and commands that Claude runs.
In Agent SDK and non-interactive sessions started with
-p
, Claude Code also reads
TRACEPARENT
and
TRACESTATE
from its own environment when starting each interaction span. This lets an embedding process pass its active W3C trace context into the subprocess so Claude Code’s spans appear as children of the caller’s distributed trace. Interactive sessions ignore inbound
TRACEPARENT
to avoid accidentally inheriting ambient values from CI or container environments.
​
Span hierarchy
Each user prompt starts a
claude_code.interaction
root span. API calls, tool calls, and hook executions are recorded as its children. Tool spans have two child spans of their own: one for the time spent waiting on a permission decision and one for the execution itself. When the Task tool spawns a subagent, the subagent’s API and tool spans nest under the parent’s
claude_code.tool
span.
claude_code.interaction
├── claude_code.llm_request
├── claude_code.hook                    (requires detailed beta tracing)
└── claude_code.tool
├── claude_code.tool.blocked_on_user
├── claude_code.tool.execution
└── (Task tool) subagent claude_code.llm_request / claude_code.tool spans
In Agent SDK and
claude -p
sessions,
claude_code.interaction
itself becomes a child of the caller’s span when
TRACEPARENT
is set in the environment.
​
Span attributes
Every span carries the
standard attributes
plus a
span.type
attribute matching its name. The tables below list the additional attributes set on each span. The
llm_request
,
tool.execution
, and
hook
spans set OpenTelemetry status
ERROR
when they record a failure; the other spans always end with status
UNSET
.
claude_code.interaction
Attribute
Description
Gated by
user_prompt
Prompt text. Value is
<REDACTED>
unless the gate is set
OTEL_LOG_USER_PROMPTS
user_prompt_length
Prompt length in characters
interaction.sequence
1-based counter of interactions in this session
interaction.duration_ms
Wall-clock duration of the turn
claude_code.llm_request
Attribute
Description
Gated by
model
Model identifier
gen_ai.system
Always
anthropic
. OpenTelemetry GenAI semantic convention
gen_ai.request.model
Same value as
model
. OpenTelemetry GenAI semantic convention
query_source
Subsystem that issued the request, such as
repl_main_thread
or a subagent name
agent_id
Identifier of the subagent or teammate that issued the request. Absent on the main session
parent_agent_id
Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it
speed
fast
or
normal
llm_request.context
interaction
,
tool
, or
standalone
depending on the parent span
duration_ms
Wall-clock duration including retries
ttft_ms
Time to first token in milliseconds
input_tokens
Input token count from the API usage block
output_tokens
Output token count
cache_read_tokens
Tokens read from prompt cache
cache_creation_tokens
Tokens written to prompt cache
request_id
Anthropic API request ID from the
request-id
response header
gen_ai.response.id
Same value as
request_id
. OpenTelemetry GenAI semantic convention
client_request_id
Client-generated
x-client-request-id
of the final attempt
attempt
Total attempts made for this request
success
true
or
false
status_code
HTTP status code when the request failed
error
Error message when the request failed
response.has_tool_call
true
when the response contained tool-use blocks
stop_reason
API response
stop_reason
, such as
end_turn
,
tool_use
,
max_tokens
,
stop_sequence
,
pause_turn
, or
refusal
gen_ai.response.finish_reasons
Same value as
stop_reason
, wrapped in a string array. OpenTelemetry GenAI semantic convention
Each retry attempt is also recorded as a
gen_ai.request.attempt
span event with
attempt
and
client_request_id
attributes.
claude_code.tool
Attribute
Description
Gated by
tool_name
Tool name
duration_ms
Wall-clock duration including permission wait and execution
result_tokens
Approximate token size of the tool result
file_path
Target file path for Read, Edit, and Write tools
OTEL_LOG_TOOL_DETAILS
full_command
Command string for the Bash tool
OTEL_LOG_TOOL_DETAILS
skill_name
Skill name for the Skill tool
OTEL_LOG_TOOL_DETAILS
subagent_type
Subagent type for the Task tool
OTEL_LOG_TOOL_DETAILS
When
OTEL_LOG_TOOL_CONTENT=1
, this span also records a
tool.output
span event whose attributes contain the tool’s input and output bodies, truncated at 60 KB per attribute.
claude_code.tool.blocked_on_user
Attribute
Description
Gated by
duration_ms
Time spent waiting for the permission decision
decision
accept
or
reject
source
Decision source, matching the
Tool decision event
claude_code.tool.execution
Attribute
Description
Gated by
duration_ms
Time spent running the tool body
success
true
or
false
error
Error category string when execution failed, such as
Error:ENOENT
or
ShellError
. Contains the full error message instead when the gate is set
OTEL_LOG_TOOL_DETAILS
claude_code.hook
This span is emitted only when detailed beta tracing is active, which requires
ENABLE_BETA_TRACING_DETAILED=1
and
BETA_TRACING_ENDPOINT
in addition to the trace exporter configuration above. In interactive CLI sessions, this also requires your organization to be allowlisted for the feature. Agent SDK and non-interactive
-p
sessions are not gated. It is not emitted when only
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA
is set.
Attribute
Description
Gated by
hook_event
Hook event type, such as
PreToolUse
hook_name
Full hook name, such as
PreToolUse:Write
num_hooks
Number of matching hook commands executed
hook_definitions
JSON-serialized hook configuration
OTEL_LOG_TOOL_DETAILS
duration_ms
Wall-clock duration of all matching hooks
num_success
Count of hooks that completed successfully
num_blocking
Count of hooks that returned a blocking decision
num_non_blocking_error
Count of hooks that failed without blocking
num_cancelled
Count of hooks cancelled before completion
Additional content-bearing attributes such as
new_context
,
system_prompt_preview
,
user_system_prompt
,
tool_input
, and
response.model_output
are emitted only when detailed beta tracing is active. They are not part of the stable span schema.
user_system_prompt
additionally requires
OTEL_LOG_USER_PROMPTS=1
. It carries only the system prompt text you provide via the
systemPrompt
SDK option or
--system-prompt
and
--append-system-prompt
flags, truncated at 60 KB, and is emitted once per session rather than per request.
​
Dynamic headers
For enterprise environments that require dynamic authentication, you can configure a script to generate headers dynamically. Dynamic headers apply only to the
http/protobuf
and
http/json
protocols. The
grpc
exporter uses only the static
OTEL_EXPORTER_OTLP_HEADERS
value.
​
Settings configuration
Add to your
.claude/settings.json
:
{
"otelHeadersHelper"
:
"/bin/generate_opentelemetry_headers.sh"
}
​
Script requirements
The script must output valid JSON with string key-value pairs representing HTTP headers:
#!/bin/bash
# Example: Multiple headers
echo
"{
\"
Authorization
\"
:
\"
Bearer $(
get-token.sh
)
\"
,
\"
X-API-Key
\"
:
\"
$(
get-api-key.sh
)
\"
}"
​
Refresh behavior
The headers helper script runs at startup and periodically thereafter to support token refresh. By default, the script runs every 29 minutes. Customize the interval with the
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
environment variable.
​
Multi-team organization support
Organizations with multiple teams or departments can add custom attributes to distinguish between different groups using the
OTEL_RESOURCE_ATTRIBUTES
environment variable:
# Add custom attributes for team identification
export
OTEL_RESOURCE_ATTRIBUTES
=
"department=engineering,team.id=platform,cost_center=eng-123"
These custom attributes will be included in all metrics and events, allowing you to:
Filter metrics by team or department
Track costs per cost center
Create team-specific dashboards
Set up alerts for specific teams
Important formatting requirements for OTEL_RESOURCE_ATTRIBUTES:
The
OTEL_RESOURCE_ATTRIBUTES
environment variable uses comma-separated key=value pairs with strict formatting requirements:
No spaces allowed
: Values cannot contain spaces. For example,
user.organizationName=My Company
is invalid
Format
: Must be comma-separated key=value pairs:
key1=value1,key2=value2
Allowed characters
: Only US-ASCII characters excluding control characters, whitespace, double quotes, commas, semicolons, and backslashes
Special characters
: Characters outside the allowed range must be percent-encoded
Examples:
# ❌ Invalid - contains spaces
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=John's Organization"
# ✅ Valid - use underscores or camelCase instead
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=Johns_Organization"
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=JohnsOrganization"
# ✅ Valid - percent-encode special characters if needed
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=John%27s%20Organization"
Note: wrapping values in quotes doesn’t escape spaces. For example,
org.name="My Company"
results in the literal value
"My Company"
(with quotes included), not
My Company
.
​
Example configurations
Set these environment variables before running
claude
. Each block shows a complete configuration for a different exporter or deployment scenario:
# Console debugging (1-second intervals)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
console
export
OTEL_METRIC_EXPORT_INTERVAL
=
1000
# OTLP/gRPC
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# Prometheus
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
prometheus
# Multiple exporters
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
console
,
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
http
/
json
# Different endpoints/backends for metrics and logs
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_LOGS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL
=
http
/
protobuf
export
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
=
http
://
metrics
.
example
.
com
:
4318
export
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
=
http
://
logs
.
example
.
com
:
4317
# Metrics only (no events/logs)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# Events/logs only (no metrics)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_LOGS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
​
Available metrics and events
​
Standard attributes
All metrics and events share these standard attributes:
Attribute
Description
Controlled By
session.id
Unique session identifier
OTEL_METRICS_INCLUDE_SESSION_ID
(default: true)
app.version
Current Claude Code version
OTEL_METRICS_INCLUDE_VERSION
(default: false)
organization.id
Organization UUID (when authenticated)
Always included when available
user.account_uuid
Account UUID (when authenticated)
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
(default: true)
user.account_id
Account ID in tagged format matching Anthropic admin APIs (when authenticated), such as
user_01BWBeN28...
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
(default: true)
user.id
Anonymous device/installation identifier, generated per Claude Code installation
Always included
user.email
User email address (when authenticated via OAuth)
Always included when available
terminal.type
Terminal type, such as
iTerm.app
,
vscode
,
cursor
, or
tmux
Always included when detected
Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:
prompt.id
: UUID correlating a user prompt with all subsequent events until the next prompt. See
Event correlation attributes
.
workspace.host_paths
: host workspace directories selected in the desktop app, as a string array
​
Metrics
Claude Code exports the following metrics:
Metric Name
Description
Unit
claude_code.session.count
Count of CLI sessions started
count
claude_code.lines_of_code.count
Count of lines of code modified
count
claude_code.pull_request.count
Number of pull requests created
count
claude_code.commit.count
Number of git commits created
count
claude_code.cost.usage
Cost of the Claude Code session
USD
claude_code.token.usage
Number of tokens used
tokens
claude_code.code_edit_tool.decision
Count of code editing tool permission decisions
count
claude_code.active_time.total
Total active time in seconds
s
​
Metric details
Each metric includes the standard attributes listed above. Metrics with additional context-specific attributes are noted below.
​
Session counter
Incremented at the start of each session.
Attributes
:
All
standard attributes
start_type
: How the session was started. One of
"fresh"
,
"resume"
, or
"continue"
​
Lines of code counter
Incremented when code is added or removed.
Attributes
:
All
standard attributes
type
: (
"added"
,
"removed"
)
​
Pull request counter
Incremented when Claude Code creates a pull request or merge request through a shell command or an MCP tool.
Attributes
:
All
standard attributes
​
Commit counter
Incremented when creating git commits via Claude Code.
Attributes
:
All
standard attributes
​
Cost counter
Incremented after each API request.
Attributes
:
All
standard attributes
model
: Model identifier (for example, “claude-sonnet-4-6”)
query_source
: Category of the subsystem that issued the request. One of
"main"
,
"subagent"
, or
"auxiliary"
speed
:
"fast"
when the request used fast mode. Absent otherwise
effort
:
Effort level
applied to the request:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. Absent when the model does not support effort.
agent.name
: Subagent type that issued the request. Built-in agent names and agents from official-marketplace plugins appear verbatim. Other user-defined agent names are replaced with
"custom"
. Absent when the request was not issued by a named subagent type.
skill.name
: Skill active for the request, set by the Skill tool, a
/
command, or inherited by a spawned subagent. Built-in, bundled, user-defined, and official-marketplace plugin skill names appear verbatim. Third-party plugin skill names are replaced with
"third-party"
. Absent when no skill is active.
plugin.name
: Owning plugin when the active skill or subagent is provided by a plugin. Official-marketplace plugin names appear verbatim. Third-party plugin names are replaced with
"third-party"
. Absent when neither the skill nor the subagent has an owning plugin.
marketplace.name
: Marketplace the owning plugin was installed from. Only emitted for official-marketplace plugins. Absent otherwise.
​
Token counter
Incremented after each API request.
Attributes
:
All
standard attributes
type
: (
"input"
,
"output"
,
"cacheRead"
,
"cacheCreation"
)
model
: Model identifier (for example, “claude-sonnet-4-6”)
query_source
: Category of the subsystem that issued the request. One of
"main"
,
"subagent"
, or
"auxiliary"
speed
:
"fast"
when the request used fast mode. Absent otherwise
effort
:
Effort level
applied to the request. See
Cost counter
for details.
agent.name
,
skill.name
,
plugin.name
,
marketplace.name
: Skill, plugin, and agent attribution for the request. See
Cost counter
for definitions and redaction behavior.
​
Code edit tool decision counter
Incremented when user accepts or rejects Edit, Write, or NotebookEdit tool usage.
Attributes
:
All
standard attributes
tool_name
: Tool name (
"Edit"
,
"Write"
,
"NotebookEdit"
)
decision
: User decision (
"accept"
,
"reject"
)
source
: Where the decision came from. One of
"config"
,
"hook"
,
"user_permanent"
,
"user_temporary"
,
"user_abort"
, or
"user_reject"
. See the
Tool decision event
for what each value means.
language
: Programming language of the edited file, such as
"TypeScript"
,
"Python"
,
"JavaScript"
, or
"Markdown"
. Returns
"unknown"
for unrecognized file extensions.
​
Active time counter
Tracks actual time spent actively using Claude Code, excluding idle time. This metric is incremented during user interactions (typing, reading responses) and during CLI processing (tool execution, AI response generation).
Attributes
:
All
standard attributes
type
:
"user"
for keyboard interactions,
"cli"
for tool execution and AI responses
​
Events
Claude Code exports the following events via OpenTelemetry logs/events (when
OTEL_LOGS_EXPORTER
is configured):
​
Event correlation attributes
When a user submits a prompt, Claude Code may make multiple API calls and run several tools. The
prompt.id
attribute lets you tie all of those events back to the single prompt that triggered them.
Attribute
Description
prompt.id
UUID v4 identifier linking all events produced while processing a single user prompt
To trace all activity triggered by a single prompt, filter your events by a specific
prompt.id
value. This returns the user_prompt event, any api_request events, and any tool_result events that occurred while processing that prompt.
prompt.id
is intentionally excluded from metrics because each prompt generates a unique ID, which would create an ever-growing number of time series. Use it for event-level analysis and audit trails only.
​
User prompt event
Logged when a user submits a prompt.
Event Name
:
claude_code.user_prompt
Attributes
:
All
standard attributes
event.name
:
"user_prompt"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
prompt_length
: Length of the prompt
prompt
: Prompt content (redacted by default, enable with
OTEL_LOG_USER_PROMPTS=1
)
command_name
: Command name when the prompt invokes one. Built-in and bundled command names such as
compact
or
debug
are emitted as-is; aliases such as
reset
emit as typed rather than the canonical name. Custom, plugin, and MCP command names collapse to
custom
or
mcp
unless
OTEL_LOG_TOOL_DETAILS=1
is set
command_source
: Origin of the command when present:
builtin
,
custom
, or
mcp
. Plugin-provided commands report as
custom
​
Tool result event
Logged when a tool completes execution.
Event Name
:
claude_code.tool_result
Attributes
:
All
standard attributes
event.name
:
"tool_result"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
tool_name
: Name of the tool
tool_use_id
: Unique identifier for this tool invocation. Matches the
tool_use_id
passed to hooks, allowing correlation between OTel events and hook-captured data.
success
:
"true"
or
"false"
duration_ms
: Execution time in milliseconds
error_type
: Error category string when the tool failed, such as
"Error:ENOENT"
or
"ShellError"
error
(when
OTEL_LOG_TOOL_DETAILS=1
): Full error message when the tool failed
decision_type
: Either
"accept"
or
"reject"
decision_source
: Where the decision came from. One of
"config"
,
"hook"
,
"user_permanent"
,
"user_temporary"
,
"user_abort"
, or
"user_reject"
. See the
Tool decision event
for what each value means.
tool_input_size_bytes
: Size of the JSON-serialized tool input in bytes
tool_result_size_bytes
: Size of the tool result in bytes
mcp_server_scope
: MCP server scope identifier (for MCP tools)
tool_parameters
(when
OTEL_LOG_TOOL_DETAILS=1
): JSON string containing tool-specific parameters:
For Bash tool: includes
bash_command
,
full_command
,
timeout
,
description
,
dangerouslyDisableSandbox
, and
git_commit_id
(the commit SHA, when a
git commit
command succeeds)
For MCP tools: includes
mcp_server_name
,
mcp_tool_name
For Skill tool: includes
skill_name
For Task tool: includes
subagent_type
tool_input
(when
OTEL_LOG_TOOL_DETAILS=1
): JSON-serialized tool arguments. Individual values over 512 characters are truncated, and the full payload is bounded to ~4 K characters. Applies to all tools including MCP tools.
​
API request event
Logged for each API request to Claude.
Event Name
:
claude_code.api_request
Attributes
:
All
standard attributes
event.name
:
"api_request"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used (for example, “claude-sonnet-4-6”)
cost_usd
: Estimated cost in USD
duration_ms
: Request duration in milliseconds
input_tokens
: Number of input tokens
output_tokens
: Number of output tokens
cache_read_tokens
: Number of tokens read from cache
cache_creation_tokens
: Number of tokens used for cache creation
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
speed
:
"fast"
or
"normal"
, indicating whether fast mode was active
query_source
: Subsystem that issued the request, such as
"repl_main_thread"
,
"compact"
, or a subagent name
effort
:
Effort level
applied to the request:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. Absent when the model does not support effort.
​
API error event
Logged when an API request to Claude fails.
Event Name
:
claude_code.api_error
Attributes
:
All
standard attributes
event.name
:
"api_error"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used (for example, “claude-sonnet-4-6”)
error
: Error message
status_code
: HTTP status code as a number. Absent for non-HTTP errors such as connection failures.
duration_ms
: Request duration in milliseconds
attempt
: Total number of attempts made, including the initial request (
1
means no retries occurred)
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
speed
:
"fast"
or
"normal"
, indicating whether fast mode was active
query_source
: Subsystem that issued the request, such as
"repl_main_thread"
,
"compact"
, or a subagent name
effort
:
Effort level
applied to the request. Absent when the model does not support effort.
​
API request body event
Logged for each API request attempt when
OTEL_LOG_RAW_API_BODIES
is set. One event is emitted per attempt, so retries with adjusted parameters each produce their own event.
Event Name
:
claude_code.api_request_body
Attributes
:
All
standard attributes
event.name
:
"api_request_body"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
body
: JSON-serialized Messages API request parameters (system prompt, messages, tools, etc.), truncated at 60 KB. Extended-thinking content in prior assistant turns is redacted. Emitted only in inline mode (
OTEL_LOG_RAW_API_BODIES=1
).
body_ref
: Absolute path to a
<dir>/<uuid>.request.json
file containing the untruncated body. Emitted only in file mode (
OTEL_LOG_RAW_API_BODIES=file:<dir>
).
body_length
: Untruncated body length. UTF-8 bytes when
OTEL_LOG_RAW_API_BODIES=file:<dir>
, or UTF-16 code units when
=1
body_truncated
:
"true"
when inline truncation occurred. Absent in file mode and when no truncation occurred.
model
: Model identifier from the request parameters
query_source
: Subsystem that issued the request (for example,
"compact"
)
​
API response body event
Logged for each successful API response when
OTEL_LOG_RAW_API_BODIES
is set.
Event Name
:
claude_code.api_response_body
Attributes
:
All
standard attributes
event.name
:
"api_response_body"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
body
: JSON-serialized Messages API response (id, content blocks, usage, stop reason), truncated at 60 KB. Extended-thinking content is redacted. Emitted only in inline mode (
OTEL_LOG_RAW_API_BODIES=1
).
body_ref
: Absolute path to a
<dir>/<request_id>.response.json
file containing the untruncated body. Emitted only in file mode (
OTEL_LOG_RAW_API_BODIES=file:<dir>
).
body_length
: Untruncated body length. UTF-8 bytes when
OTEL_LOG_RAW_API_BODIES=file:<dir>
, or UTF-16 code units when
=1
body_truncated
:
"true"
when inline truncation occurred. Absent in file mode and when no truncation occurred.
model
: Model identifier
query_source
: Subsystem that issued the request
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
​
Tool decision event
Logged when a tool permission decision is made (accept/reject).
Event Name
:
claude_code.tool_decision
Attributes
:
All
standard attributes
event.name
:
"tool_decision"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
tool_name
: Name of the tool (for example, “Read”, “Edit”, “Write”, “NotebookEdit”)
tool_use_id
: Unique identifier for this tool invocation. Matches the
tool_use_id
passed to hooks, allowing correlation between OTel events and hook-captured data.
decision
: Either
"accept"
or
"reject"
source
: Where the decision came from:
"config"
: Decided automatically without prompting, based on project settings, allow rules in the user’s personal settings, enterprise managed policy,
--allowedTools
or
--disallowedTools
flags, the active permission mode, a session-scoped grant from an earlier prompt in the same interactive CLI session, or because the tool is inherently safe. The event does not indicate which of these sources matched.
"hook"
: A
PreToolUse
or
PermissionRequest
hook returned the decision.
"user_permanent"
: Emitted when the user chose “Yes, and don’t ask again for …” at a permission prompt, which saves an allow rule to their personal settings. In the interactive CLI this is emitted only for that choice itself; later calls that match the saved rule emit
"config"
instead. In Agent SDK or non-interactive
-p
sessions, both the initial choice and later rule matches emit
"user_permanent"
. Treated as an accept.
"user_temporary"
: Emitted when the user chose “Yes” at a permission prompt for a one-time approval, or chose one of the ”… during this session” options on a file edit or read prompt. In the interactive CLI this is emitted only for the choice itself; later calls allowed by that session-scoped grant emit
"config"
instead. In Agent SDK or non-interactive
-p
sessions, both the choice and later matches emit
"user_temporary"
. Treated as an accept.
"user_abort"
: Emitted when the user dismissed the permission prompt without answering. Treated as a reject.
"user_reject"
: Emitted when the user chose “No” when prompted, or a call matched a deny rule in their personal settings. Treated as a reject.
​
Permission mode changed event
Logged when the permission mode changes, for example from
Shift+Tab
cycling, exiting plan mode, or an auto mode gate check.
Event Name
:
claude_code.permission_mode_changed
Attributes
:
All
standard attributes
event.name
:
"permission_mode_changed"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
from_mode
: The previous permission mode, for example
"default"
,
"plan"
,
"acceptEdits"
,
"auto"
, or
"bypassPermissions"
to_mode
: The new permission mode
trigger
: What caused the change. One of
"shift_tab"
,
"exit_plan_mode"
,
"auto_gate_denied"
, or
"auto_opt_in"
. Absent when the transition originates from the SDK or bridge
​
Auth event
Logged when
/login
or
/logout
completes.
Event Name
:
claude_code.auth
Attributes
:
All
standard attributes
event.name
:
"auth"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
action
:
"login"
or
"logout"
success
:
"true"
or
"false"
auth_method
: Authentication method, such as
"oauth"
error_category
: Categorical error kind when the action failed. The raw error message is never included
status_code
: HTTP status code as a string when the action failed with an HTTP error
​
MCP server connection event
Logged when an MCP server connects, disconnects, or fails to connect.
Event Name
:
claude_code.mcp_server_connection
Attributes
:
All
standard attributes
event.name
:
"mcp_server_connection"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
status
:
"connected"
,
"failed"
, or
"disconnected"
transport_type
: Server transport, such as
"stdio"
,
"sse"
, or
"http"
server_scope
: Scope the server is configured at, such as
"user"
,
"project"
, or
"local"
duration_ms
: Connection attempt duration in milliseconds
error_code
: Error code when the connection failed
server_name
(when
OTEL_LOG_TOOL_DETAILS=1
): Configured server name
error
(when
OTEL_LOG_TOOL_DETAILS=1
): Full error message when the connection failed
​
Internal error event
Logged when Claude Code catches an unexpected internal error. Only the error class name and an errno-style code are recorded. The error message and stack trace are never included. This event is not emitted when running against Bedrock, Vertex, or Foundry, or when
DISABLE_ERROR_REPORTING
is set.
Event Name
:
claude_code.internal_error
Attributes
:
All
standard attributes
event.name
:
"internal_error"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
error_name
: Error class name, such as
"TypeError"
or
"SyntaxError"
error_code
: Node.js errno code such as
"ENOENT"
when present on the error
​
Plugin installed event
Logged when a plugin finishes installing, from both the
claude plugin install
CLI command and the interactive
/plugin
UI.
Event Name
:
claude_code.plugin_installed
Attributes
:
All
standard attributes
event.name
:
"plugin_installed"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
marketplace.is_official
:
"true"
if the marketplace is an official Anthropic marketplace,
"false"
otherwise
install.trigger
:
"cli"
or
"ui"
plugin.name
: Name of the installed plugin. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
plugin.version
: Plugin version when declared in the marketplace entry. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
marketplace.name
: Marketplace the plugin was installed from. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
​
Plugin loaded event
Logged once per enabled plugin at session start. Use this event to inventory which plugins are active across your fleet, as a complement to
plugin_installed
which records the install action itself.
Event Name
:
claude_code.plugin_loaded
Attributes
:
All
standard attributes
event.name
:
"plugin_loaded"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
plugin.name
: name of the plugin. For plugins outside the official marketplace and built-in bundle the value is
"third-party"
unless
OTEL_LOG_TOOL_DETAILS=1
marketplace.name
: marketplace the plugin was installed from, when known. Redacted to
"third-party"
under the same condition as
plugin.name
plugin.version
: version from the plugin manifest. Included only when the name is not redacted and the manifest declares a version
plugin.scope
: provenance category for the plugin:
"official"
,
"org"
,
"user-local"
, or
"default-bundle"
enabled_via
: how the plugin came to be enabled:
"default-enable"
,
"org-policy"
,
"seed-mount"
, or
"user-install"
plugin_id_hash
: deterministic hash of the plugin name and marketplace, sent only to your configured exporter. Lets you count how many distinct third-party plugins are loaded across your fleet without recording their names
has_hooks
: whether the plugin contributes hooks
has_mcp
: whether the plugin contributes MCP servers
skill_path_count
: number of skill directories the plugin declares
command_path_count
: number of command directories the plugin declares
agent_path_count
: number of agent directories the plugin declares
​
Skill activated event
Logged when a skill is invoked, whether Claude calls it through the Skill tool or you run it as a
/
command.
Event Name
:
claude_code.skill_activated
Attributes
:
All
standard attributes
event.name
:
"skill_activated"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
skill.name
: Name of the skill. For user-defined and third-party plugin skills the value is the placeholder
"custom_skill"
unless
OTEL_LOG_TOOL_DETAILS=1
invocation_trigger
: How the skill was triggered (
"user-slash"
,
"claude-proactive"
, or
"nested-skill"
)
skill.source
: Where the skill was loaded from (for example,
"bundled"
,
"userSettings"
,
"projectSettings"
,
"plugin"
)
plugin.name
(when
OTEL_LOG_TOOL_DETAILS=1
or the plugin is from an official marketplace): Name of the owning plugin when the skill is provided by a plugin
marketplace.name
(when
OTEL_LOG_TOOL_DETAILS=1
or the plugin is from an official marketplace): Marketplace the owning plugin was installed from, when the skill is provided by a plugin
​
At mention event
Logged when Claude Code resolves an
@
-mention in a prompt. Not every mention emits an event: early-exit paths such as permission denials, oversized files, PDF reference attachments, and directory listing failures return without logging.
Event Name
:
claude_code.at_mention
Attributes
:
All
standard attributes
event.name
:
"at_mention"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
mention_type
: Type of mention (
"file"
,
"directory"
,
"agent"
,
"mcp_resource"
)
success
: Whether the mention resolved successfully (
"true"
or
"false"
)
​
API retries exhausted event
Logged once when an API request fails after more than one attempt. Emitted alongside the final
api_error
event.
Event Name
:
claude_code.api_retries_exhausted
Attributes
:
All
standard attributes
event.name
:
"api_retries_exhausted"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used
error
: Final error message
status_code
: HTTP status code as a number. Absent for non-HTTP errors.
total_attempts
: Total number of attempts made
total_retry_duration_ms
: Total wall-clock time across all attempts
speed
:
"fast"
or
"normal"
​
Hook registered event
Logged once per configured hook at session start. Use this event to inventory which hooks are active across your fleet, as a complement to the per-execution
hook_execution_start
and
hook_execution_complete
events.
Event Name
:
claude_code.hook_registered
Attributes
:
All
standard attributes
event.name
:
"hook_registered"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: hook event type, such as
"PreToolUse"
or
"PostToolUse"
hook_type
: hook implementation type:
"command"
,
"prompt"
,
"mcp_tool"
,
"http"
, or
"agent"
hook_source
: where the hook is defined:
"userSettings"
,
"projectSettings"
,
"localSettings"
,
"flagSettings"
,
"policySettings"
, or
"pluginHook"
hook_matcher
(when
OTEL_LOG_TOOL_DETAILS=1
): the matcher string from the hook configuration, when one is set
plugin.name
(when
hook_source
is
"pluginHook"
): name of the contributing plugin. For plugins outside the official marketplace and built-in bundle the value is
"third-party"
unless
OTEL_LOG_TOOL_DETAILS=1
plugin_id_hash
(when
hook_source
is
"pluginHook"
): deterministic hash of the plugin name and marketplace, sent only to your configured exporter. Lets you count distinct contributing plugins without recording their names
​
Hook execution start event
Logged when one or more hooks begin executing for a hook event.
Event Name
:
claude_code.hook_execution_start
Attributes
:
All
standard attributes
event.name
:
"hook_execution_start"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: Hook event type, such as
"PreToolUse"
or
"PostToolUse"
hook_name
: Full hook name including matcher, such as
"PreToolUse:Write"
num_hooks
: Number of matching hook commands
managed_only
:
"true"
when only managed-policy hooks are permitted
hook_source
:
"policySettings"
or
"merged"
hook_definitions
: JSON-serialized hook configuration. Included only when both detailed beta tracing and
OTEL_LOG_TOOL_DETAILS=1
are enabled
​
Hook execution complete event
Logged when all hooks for a hook event have finished.
Event Name
:
claude_code.hook_execution_complete
Attributes
:
All
standard attributes
event.name
:
"hook_execution_complete"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: Hook event type
hook_name
: Full hook name including matcher
num_hooks
: Number of matching hook commands
num_success
: Count that completed successfully
num_blocking
: Count that returned a blocking decision
num_non_blocking_error
: Count that failed without blocking
num_cancelled
: Count cancelled before completion
total_duration_ms
: Wall-clock duration of all matching hooks
managed_only
:
"true"
when only managed-policy hooks are permitted
hook_source
:
"policySettings"
or
"merged"
hook_definitions
: JSON-serialized hook configuration. Included only when both detailed beta tracing and
OTEL_LOG_TOOL_DETAILS=1
are enabled
​
Compaction event
Logged when conversation compaction completes.
Event Name
:
claude_code.compaction
Attributes
:
All
standard attributes
event.name
:
"compaction"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
trigger
:
"auto"
or
"manual"
success
:
"true"
or
"false"
duration_ms
: Compaction duration
pre_tokens
: Approximate token count before compaction
post_tokens
: Approximate token count after compaction
error
: Error message when compaction failed
​
Feedback survey event
Logged when a session quality survey is shown or answered. See
Session quality surveys
for what the surveys collect and how to control them.
Event Name
:
claude_code.feedback_survey
Attributes
:
All
standard attributes
event.name
:
"feedback_survey"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
event_type
: Survey lifecycle event, for example
"appeared"
,
"responded"
, or
"transcript_prompt_appeared"
appearance_id
: Unique ID linking the events emitted for one survey instance
survey_type
: Which survey produced the event.
"session"
is the “How is Claude doing?” rating prompt
response
: The user’s selection on
responded
events
enabled_via_override
:
true
when
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
is set. Emitted as a boolean, not a string. Present on
session
survey events. Filter on this attribute to confirm the override is applied across a fleet
​
Interpret metrics and events data
The exported metrics and events support a range of analyses:
​
Usage monitoring
Metric
Analysis Opportunity
claude_code.token.usage
Break down by
type
(input/output), user, team, model,
skill.name
,
plugin.name
, or
agent.name
claude_code.session.count
Track adoption and engagement over time
claude_code.lines_of_code.count
Measure productivity by tracking code additions/removals
claude_code.commit.count
&
claude_code.pull_request.count
Understand impact on development workflows
​
Cost monitoring
The
claude_code.cost.usage
metric helps with:
Tracking usage trends across teams or individuals
Identifying high-usage sessions for optimization
Attributing spend to specific skills, plugins, or subagent types via the
skill.name
,
plugin.name
, and
agent.name
attributes
Cost metrics are approximations. For official billing data, refer to your API provider (Claude Console, Amazon Bedrock, or Google Cloud Vertex).
​
Alerting and segmentation
Common alerts to consider:
Cost spikes
Unusual token consumption
High session volume from specific users
All metrics can be segmented by
user.account_uuid
,
user.account_id
,
organization.id
,
session.id
,
model
, and
app.version
.
​
Detect retry exhaustion
Claude Code retries failed API requests internally and emits a single
claude_code.api_error
event only after it gives up, so the event itself is the terminal signal for that request. Intermediate retry attempts are not logged as separate events.
The
attempt
attribute on the event records how many attempts were made in total. A value greater than
CLAUDE_CODE_MAX_RETRIES
(default
10
) indicates the request exhausted all retries on a transient error. A lower value indicates a non-retryable error such as a
400
response.
To distinguish a session that recovered from one that stalled, group events by
session.id
and check whether a later
api_request
event exists after the error.
​
Event analysis
The event data provides detailed insights into Claude Code interactions:
Tool Usage Patterns
: analyze tool result events to identify:
Most frequently used tools
Tool success rates
Average tool execution times
Error patterns by tool type
Performance Monitoring
: track API request durations and tool execution times to identify performance bottlenecks.
​
Audit security events
OpenTelemetry events are the audit data source for Claude Code activity. Every event carries identity attributes that tie tool calls, MCP activity, and permission decisions back to the user who triggered them, and the OTLP logs exporter can deliver these events to any Security Information and Event Management (SIEM) platform with an OTLP receiver or to an OpenTelemetry Collector that forwards to your SIEM.
​
Attribute actions to users
The
standard attributes
on each event include the authenticated user’s identity:
user.email
,
user.account_uuid
,
user.account_id
, and
organization.id
when signed in with a Claude account, plus the installation-scoped
user.id
and the per-session
session.id
.
MCP tool calls, Bash commands, and file edits are therefore attributed to the developer who started the session. Claude Code does not act under a separate service account; the identity recorded on each event is the developer’s own Claude account.
When Claude Code authenticates with a direct API key, or against Bedrock, Vertex AI, or Microsoft Foundry, there is no Claude account in the session and only
user.id
and
session.id
are populated. In these deployments, attach user identity yourself with
OTEL_RESOURCE_ATTRIBUTES
, set per user through the
managed settings
file or a launch wrapper:
export
OTEL_RESOURCE_ATTRIBUTES
=
"enduser.id=jdoe@example.com,enduser.directory_id=S-1-5-21-..."
​
Audit MCP activity
To capture MCP server activity with full call detail, enable the logs exporter and set
OTEL_LOG_TOOL_DETAILS=1
. Each MCP operation then produces structured events that carry the server name, tool name, and call arguments alongside the standard identity attributes:
Event
What it records for MCP
mcp_server_connection
Server connect, disconnect, and connection failure with
server_name
,
transport_type
,
server_scope
, and error detail
tool_result
Each MCP tool call with
tool_name
and
mcp_server_scope
, a
tool_parameters
payload containing
mcp_server_name
and
mcp_tool_name
, and a
tool_input
payload containing the call arguments
tool_decision
Whether the call was allowed or denied, and whether the decision came from config, a hook, or the user
Without
OTEL_LOG_TOOL_DETAILS
,
tool_result
events still carry
tool_name
and
mcp_server_scope
but omit the
mcp_server_name
/
mcp_tool_name
breakdown and the arguments, and
mcp_server_connection
events omit
server_name
and the error message.
​
Map security questions to events
When building detection rules, look up the signal you want to monitor and query your backend for the corresponding event and attributes:
Signal
Event
Key attributes
Tool call allowed or denied, and by what
tool_decision
decision
,
source
,
tool_name
Permission mode escalation
permission_mode_changed
from_mode
,
to_mode
,
trigger
Policy hook blocked an action
hook_execution_complete
hook_event
,
num_blocking
Login, logout, and authentication failure
auth
action
,
success
,
error_category
MCP server connect or failure
mcp_server_connection
status
,
server_name
,
error_code
Plugin installed and its source
plugin_installed
plugin.name
,
marketplace.name
,
marketplace.is_official
Commands run and files touched
tool_result
with
OTEL_LOG_TOOL_DETAILS=1
tool_parameters
,
tool_input
Claude Code emits the raw event stream only. Anomaly detection, baselining, correlation across sessions, and alerting are the responsibility of your SIEM or observability backend.
​
Send events to a SIEM
Point
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
at your SIEM’s OTLP receiver, or at an OpenTelemetry Collector that forwards to your SIEM’s native ingest API. The following managed-settings example exports events only, with full tool detail enabled for MCP and Bash auditing:
{
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
"OTEL_LOG_TOOL_DETAILS"
:
"1"
,
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL"
:
"http/protobuf"
,
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
:
"https://siem.example.com:4318/v1/logs"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer your-siem-token"
}
}
​
Backend considerations
Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:
​
For metrics
Time series databases (for example, Prometheus)
: Rate calculations, aggregated metrics
Columnar stores (for example, ClickHouse)
: Complex queries, unique user analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Advanced querying, visualization, alerting
​
For events/logs
Log aggregation systems (for example, Elasticsearch, Loki)
: Full-text search, log analysis
Columnar stores (for example, ClickHouse)
: Structured event analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Correlation between metrics and events
​
For traces
Choose a backend that supports distributed trace storage and span correlation:
Distributed tracing systems (for example, Jaeger, Zipkin, Grafana Tempo)
: Span visualization, request waterfalls, latency analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Trace search and correlation with metrics and logs
For organizations requiring Daily/Weekly/Monthly Active User (DAU/WAU/MAU) metrics, consider backends that support efficient unique value queries.
​
Service information
All metrics and events are exported with the following resource attributes:
service.name
:
claude-code
service.version
: Current Claude Code version
os.type
: Operating system type (for example,
linux
,
darwin
,
windows
)
os.version
: Operating system version string
host.arch
: Host architecture (for example,
amd64
,
arm64
)
wsl.version
: WSL version number (only present when running on Windows Subsystem for Linux)
Meter Name:
com.anthropic.claude_code
​
ROI measurement resources
For a comprehensive guide on measuring return on investment for Claude Code, including telemetry setup, cost analysis, productivity metrics, and automated reporting, see the
Claude Code ROI Measurement Guide
. This repository provides ready-to-use Docker Compose configurations, Prometheus and OpenTelemetry setups, and templates for generating productivity reports integrated with tools like Linear.
​
Security and privacy
OpenTelemetry export to your backend is opt-in and requires explicit configuration. For Anthropic’s separate operational telemetry and how to disable it, see
Data usage
Raw file contents and code snippets are not included in metrics or events. Trace spans are a separate data path: see the
OTEL_LOG_TOOL_CONTENT
bullet below
When authenticated via OAuth,
user.email
is included in telemetry attributes. If this is a concern for your organization, work with your telemetry backend to filter or redact this field
User prompt content is not collected by default. Only prompt length is recorded. To include prompt content, set
OTEL_LOG_USER_PROMPTS=1
Tool input arguments and parameters are not logged by default. To include them, set
OTEL_LOG_TOOL_DETAILS=1
. When enabled,
tool_result
events include a
tool_parameters
attribute with Bash commands, MCP server and tool names, and skill names, plus a
tool_input
attribute with file paths, URLs, search patterns, and other arguments.
user_prompt
events include the verbatim
command_name
for custom, plugin, and MCP commands. Trace spans include the same
tool_input
attribute and input-derived attributes such as
file_path
. Individual values over 512 characters are truncated and the total is bounded to ~4 K characters, but the arguments may still contain sensitive values. Configure your telemetry backend to filter or redact these attributes as needed
Tool input and output content is not logged in trace spans by default. To include it, set
OTEL_LOG_TOOL_CONTENT=1
. When enabled, span events include full tool input and output content truncated at 60 KB per span. This can include raw file contents from Read tool results and Bash command output. Configure your telemetry backend to filter or redact these attributes as needed
Raw Anthropic Messages API request and response bodies are not logged by default. To include them, set
OTEL_LOG_RAW_API_BODIES
. With
=1
, each API call emits
api_request_body
and
api_response_body
log events whose
body
attribute is the JSON-serialized payload, truncated at 60 KB. With
=file:<dir>
, untruncated bodies are written to
.request.json
and
.response.json
files under that directory and the events carry a
body_ref
path instead of the inline body. Ship the directory with a log collector or sidecar rather than through the telemetry stream. In both modes, bodies contain the full conversation history (system prompt, every prior user and assistant turn, tool results), so enabling this implies consent to everything the other
OTEL_LOG_*
content flags would reveal. Claude’s extended-thinking content is always redacted from these bodies regardless of other settings
​
Monitor Claude Code on Amazon Bedrock
For detailed Claude Code usage monitoring guidance for Amazon Bedrock, see
Claude Code Monitoring Implementation (Bedrock)
.
Was this page helpful?
Yes
No
Development containers
Costs
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/monitoring-usage" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Monitoring
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dep...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Usage and costs
Monitoring
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Track Claude Code usage, costs, and tool activity across your organization by exporting telemetry data through OpenTelemetry (OTel). Claude Code exports metrics as time series data via the standard metrics protocol, events via the logs/events protocol, and optionally distributed traces via the
traces protocol
. Configure your metrics, logs, and traces backends to match your monitoring requirements.
​
Quick start
Configure OpenTelemetry using environment variables:
# 1. Enable telemetry
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
# 2. Choose exporters (both are optional - configure only what you need)
export
OTEL_METRICS_EXPORTER
=
otlp
# Options: otlp, prometheus, console, none
export
OTEL_LOGS_EXPORTER
=
otlp
# Options: otlp, console, none
# 3. Configure OTLP endpoint (for OTLP exporter)
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# 4. Set authentication (if required)
export
OTEL_EXPORTER_OTLP_HEADERS
=
"Authorization=Bearer your-token"
# 5. For debugging: reduce export intervals
export
OTEL_METRIC_EXPORT_INTERVAL
=
10000
# 10 seconds (default: 60000ms)
export
OTEL_LOGS_EXPORT_INTERVAL
=
5000
# 5 seconds (default: 5000ms)
# 6. Run Claude Code
claude
The default export intervals are 60 seconds for metrics and 5 seconds for logs. During setup, you may want to use shorter intervals for debugging purposes. Remember to reset these for production use.
For full configuration options, see the
OpenTelemetry specification
.
​
Administrator configuration
Administrators can configure OpenTelemetry settings for all users through the
managed settings file
. This allows for centralized control of telemetry settings across an organization. See the
settings precedence
for more information about how settings are applied.
Example managed settings configuration:
{
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
"OTEL_EXPORTER_OTLP_PROTOCOL"
:
"grpc"
,
"OTEL_EXPORTER_OTLP_ENDPOINT"
:
"http://collector.example.com:4317"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer example-token"
}
}
Managed settings can be distributed via MDM (Mobile Device Management) or other device management solutions. Environment variables defined in the managed settings file have high precedence and cannot be overridden by users.
Claude Code does not pass
OTEL_*
environment variables to the subprocesses it spawns, including the Bash tool, hooks, MCP servers, and language servers. An OpenTelemetry-instrumented application that you run through the Bash tool does not inherit Claude Code’s exporter endpoint or headers, so set those variables directly in the command if that application needs to export its own telemetry.
​
Configuration details
​
Common configuration variables
Environment Variable
Description
Example Values
CLAUDE_CODE_ENABLE_TELEMETRY
Enables telemetry collection (required)
1
OTEL_METRICS_EXPORTER
Metrics exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
prometheus
,
none
OTEL_LOGS_EXPORTER
Logs/events exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
none
OTEL_EXPORTER_OTLP_PROTOCOL
Protocol for OTLP exporter, applies to all signals
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT
OTLP collector endpoint for all signals
http://localhost:4317
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL
Protocol for metrics, overrides general setting
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
OTLP metrics endpoint, overrides general setting
http://localhost:4318/v1/metrics
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL
Protocol for logs, overrides general setting
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
OTLP logs endpoint, overrides general setting
http://localhost:4318/v1/logs
OTEL_EXPORTER_OTLP_HEADERS
Authentication headers for OTLP
Authorization=Bearer token
OTEL_METRIC_EXPORT_INTERVAL
Export interval in milliseconds (default: 60000)
5000
,
60000
OTEL_LOGS_EXPORT_INTERVAL
Logs export interval in milliseconds (default: 5000)
1000
,
10000
OTEL_LOG_USER_PROMPTS
Enable logging of user prompt content (default: disabled)
1
to enable
OTEL_LOG_TOOL_DETAILS
Enable logging of tool parameters and input arguments in tool events and trace span attributes: Bash commands, MCP server and tool names, skill names, and tool input. Also enables custom, plugin, and MCP command names on
user_prompt
events (default: disabled)
1
to enable
OTEL_LOG_TOOL_CONTENT
Enable logging of tool input and output content in span events (default: disabled). Requires
tracing
. Content is truncated at 60 KB
1
to enable
OTEL_LOG_RAW_API_BODIES
Emit the full Anthropic Messages API request and response JSON as
api_request_body
/
api_response_body
log events (default: disabled). Bodies include the entire conversation history. Enabling this implies consent to everything
OTEL_LOG_USER_PROMPTS
,
OTEL_LOG_TOOL_DETAILS
, and
OTEL_LOG_TOOL_CONTENT
would reveal
1
for inline bodies truncated at 60 KB, or
file:<dir>
for untruncated bodies on disk with a
body_ref
pointer in the event
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
Metrics temporality preference (default:
delta
). Set to
cumulative
if your backend expects cumulative temporality
delta
,
cumulative
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes)
900000
​
mTLS authentication
How you configure client certificates for the OTLP exporter depends on the OTLP protocol in use for that signal, set via
OTEL_EXPORTER_OTLP_PROTOCOL
or the per-signal override. The same configuration applies to metrics, logs, and traces.
Protocol
Client certificate variables
Trust the collector’s CA with
http/protobuf
,
http/json
CLAUDE_CODE_CLIENT_CERT
,
CLAUDE_CODE_CLIENT_KEY
, and optionally
CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
. See
Network configuration
NODE_EXTRA_CA_CERTS
grpc
OTEL_EXPORTER_OTLP_CLIENT_KEY
and
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE
, or the per-signal variants such as
OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY
to use a different certificate per signal
OTEL_EXPORTER_OTLP_CERTIFICATE
For
grpc
, the OpenTelemetry SDK reads the standard OTLP variables directly, so existing configurations that set the per-signal metrics variables continue to work.
​
Metrics cardinality control
The following environment variables control which attributes are included in metrics to manage cardinality:
Environment Variable
Description
Default Value
Example to Disable
OTEL_METRICS_INCLUDE_SESSION_ID
Include session.id attribute in metrics
true
false
OTEL_METRICS_INCLUDE_VERSION
Include app.version attribute in metrics
false
true
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
Include user.account_uuid and user.account_id attributes in metrics
true
false
These variables help control the cardinality of metrics, which affects storage requirements and query performance in your metrics backend. Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.
​
Traces (beta)
Distributed tracing exports spans that link each user prompt to the API requests and tool executions it triggers, so you can view a full request as a single trace in your tracing backend.
Tracing is off by default. To enable it, set both
CLAUDE_CODE_ENABLE_TELEMETRY=1
and
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
, then set
OTEL_TRACES_EXPORTER
to choose where spans are sent. Traces reuse the
common OTLP configuration
for endpoint, protocol, headers, and
mTLS
.
Environment Variable
Description
Example Values
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA
Enable span tracing (required).
ENABLE_ENHANCED_TELEMETRY_BETA
is also accepted
1
OTEL_TRACES_EXPORTER
Traces exporter types, comma-separated. Use
none
to disable
console
,
otlp
,
none
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL
Protocol for traces, overrides
OTEL_EXPORTER_OTLP_PROTOCOL
grpc
,
http/json
,
http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
OTLP traces endpoint, overrides
OTEL_EXPORTER_OTLP_ENDPOINT
http://localhost:4318/v1/traces
OTEL_TRACES_EXPORT_INTERVAL
Span batch export interval in milliseconds (default: 5000)
1000
,
10000
Spans redact user prompt text, tool input details, and tool content by default. Set
OTEL_LOG_USER_PROMPTS=1
,
OTEL_LOG_TOOL_DETAILS=1
, and
OTEL_LOG_TOOL_CONTENT=1
to include them.
When tracing is active, Bash and PowerShell subprocesses automatically inherit a
TRACEPARENT
environment variable containing the W3C trace context of the active tool execution span. This lets any subprocess that reads
TRACEPARENT
parent its own spans under the same trace, enabling end-to-end distributed tracing through scripts and commands that Claude runs.
In Agent SDK and non-interactive sessions started with
-p
, Claude Code also reads
TRACEPARENT
and
TRACESTATE
from its own environment when starting each interaction span. This lets an embedding process pass its active W3C trace context into the subprocess so Claude Code’s spans appear as children of the caller’s distributed trace. Interactive sessions ignore inbound
TRACEPARENT
to avoid accidentally inheriting ambient values from CI or container environments.
​
Span hierarchy
Each user prompt starts a
claude_code.interaction
root span. API calls, tool calls, and hook executions are recorded as its children. Tool spans have two child spans of their own: one for the time spent waiting on a permission decision and one for the execution itself. When the Task tool spawns a subagent, the subagent’s API and tool spans nest under the parent’s
claude_code.tool
span.
claude_code.interaction
├── claude_code.llm_request
├── claude_code.hook                    (requires detailed beta tracing)
└── claude_code.tool
├── claude_code.tool.blocked_on_user
├── claude_code.tool.execution
└── (Task tool) subagent claude_code.llm_request / claude_code.tool spans
In Agent SDK and
claude -p
sessions,
claude_code.interaction
itself becomes a child of the caller’s span when
TRACEPARENT
is set in the environment.
​
Span attributes
Every span carries the
standard attributes
plus a
span.type
attribute matching its name. The tables below list the additional attributes set on each span. The
llm_request
,
tool.execution
, and
hook
spans set OpenTelemetry status
ERROR
when they record a failure; the other spans always end with status
UNSET
.
claude_code.interaction
Attribute
Description
Gated by
user_prompt
Prompt text. Value is
<REDACTED>
unless the gate is set
OTEL_LOG_USER_PROMPTS
user_prompt_length
Prompt length in characters
interaction.sequence
1-based counter of interactions in this session
interaction.duration_ms
Wall-clock duration of the turn
claude_code.llm_request
Attribute
Description
Gated by
model
Model identifier
gen_ai.system
Always
anthropic
. OpenTelemetry GenAI semantic convention
gen_ai.request.model
Same value as
model
. OpenTelemetry GenAI semantic convention
query_source
Subsystem that issued the request, such as
repl_main_thread
or a subagent name
agent_id
Identifier of the subagent or teammate that issued the request. Absent on the main session
parent_agent_id
Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it
speed
fast
or
normal
llm_request.context
interaction
,
tool
, or
standalone
depending on the parent span
duration_ms
Wall-clock duration including retries
ttft_ms
Time to first token in milliseconds
input_tokens
Input token count from the API usage block
output_tokens
Output token count
cache_read_tokens
Tokens read from prompt cache
cache_creation_tokens
Tokens written to prompt cache
request_id
Anthropic API request ID from the
request-id
response header
gen_ai.response.id
Same value as
request_id
. OpenTelemetry GenAI semantic convention
client_request_id
Client-generated
x-client-request-id
of the final attempt
attempt
Total attempts made for this request
success
true
or
false
status_code
HTTP status code when the request failed
error
Error message when the request failed
response.has_tool_call
true
when the response contained tool-use blocks
stop_reason
API response
stop_reason
, such as
end_turn
,
tool_use
,
max_tokens
,
stop_sequence
,
pause_turn
, or
refusal
gen_ai.response.finish_reasons
Same value as
stop_reason
, wrapped in a string array. OpenTelemetry GenAI semantic convention
Each retry attempt is also recorded as a
gen_ai.request.attempt
span event with
attempt
and
client_request_id
attributes.
claude_code.tool
Attribute
Description
Gated by
tool_name
Tool name
duration_ms
Wall-clock duration including permission wait and execution
result_tokens
Approximate token size of the tool result
file_path
Target file path for Read, Edit, and Write tools
OTEL_LOG_TOOL_DETAILS
full_command
Command string for the Bash tool
OTEL_LOG_TOOL_DETAILS
skill_name
Skill name for the Skill tool
OTEL_LOG_TOOL_DETAILS
subagent_type
Subagent type for the Task tool
OTEL_LOG_TOOL_DETAILS
When
OTEL_LOG_TOOL_CONTENT=1
, this span also records a
tool.output
span event whose attributes contain the tool’s input and output bodies, truncated at 60 KB per attribute.
claude_code.tool.blocked_on_user
Attribute
Description
Gated by
duration_ms
Time spent waiting for the permission decision
decision
accept
or
reject
source
Decision source, matching the
Tool decision event
claude_code.tool.execution
Attribute
Description
Gated by
duration_ms
Time spent running the tool body
success
true
or
false
error
Error category string when execution failed, such as
Error:ENOENT
or
ShellError
. Contains the full error message instead when the gate is set
OTEL_LOG_TOOL_DETAILS
claude_code.hook
This span is emitted only when detailed beta tracing is active, which requires
ENABLE_BETA_TRACING_DETAILED=1
and
BETA_TRACING_ENDPOINT
in addition to the trace exporter configuration above. In interactive CLI sessions, this also requires your organization to be allowlisted for the feature. Agent SDK and non-interactive
-p
sessions are not gated. It is not emitted when only
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA
is set.
Attribute
Description
Gated by
hook_event
Hook event type, such as
PreToolUse
hook_name
Full hook name, such as
PreToolUse:Write
num_hooks
Number of matching hook commands executed
hook_definitions
JSON-serialized hook configuration
OTEL_LOG_TOOL_DETAILS
duration_ms
Wall-clock duration of all matching hooks
num_success
Count of hooks that completed successfully
num_blocking
Count of hooks that returned a blocking decision
num_non_blocking_error
Count of hooks that failed without blocking
num_cancelled
Count of hooks cancelled before completion
Additional content-bearing attributes such as
new_context
,
system_prompt_preview
,
user_system_prompt
,
tool_input
, and
response.model_output
are emitted only when detailed beta tracing is active. They are not part of the stable span schema.
user_system_prompt
additionally requires
OTEL_LOG_USER_PROMPTS=1
. It carries only the system prompt text you provide via the
systemPrompt
SDK option or
--system-prompt
and
--append-system-prompt
flags, truncated at 60 KB, and is emitted once per session rather than per request.
​
Dynamic headers
For enterprise environments that require dynamic authentication, you can configure a script to generate headers dynamically. Dynamic headers apply only to the
http/protobuf
and
http/json
protocols. The
grpc
exporter uses only the static
OTEL_EXPORTER_OTLP_HEADERS
value.
​
Settings configuration
Add to your
.claude/settings.json
:
{
"otelHeadersHelper"
:
"/bin/generate_opentelemetry_headers.sh"
}
​
Script requirements
The script must output valid JSON with string key-value pairs representing HTTP headers:
#!/bin/bash
# Example: Multiple headers
echo
"{
\"
Authorization
\"
:
\"
Bearer $(
get-token.sh
)
\"
,
\"
X-API-Key
\"
:
\"
$(
get-api-key.sh
)
\"
}"
​
Refresh behavior
The headers helper script runs at startup and periodically thereafter to support token refresh. By default, the script runs every 29 minutes. Customize the interval with the
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
environment variable.
​
Multi-team organization support
Organizations with multiple teams or departments can add custom attributes to distinguish between different groups using the
OTEL_RESOURCE_ATTRIBUTES
environment variable:
# Add custom attributes for team identification
export
OTEL_RESOURCE_ATTRIBUTES
=
"department=engineering,team.id=platform,cost_center=eng-123"
These custom attributes will be included in all metrics and events, allowing you to:
Filter metrics by team or department
Track costs per cost center
Create team-specific dashboards
Set up alerts for specific teams
Important formatting requirements for OTEL_RESOURCE_ATTRIBUTES:
The
OTEL_RESOURCE_ATTRIBUTES
environment variable uses comma-separated key=value pairs with strict formatting requirements:
No spaces allowed
: Values cannot contain spaces. For example,
user.organizationName=My Company
is invalid
Format
: Must be comma-separated key=value pairs:
key1=value1,key2=value2
Allowed characters
: Only US-ASCII characters excluding control characters, whitespace, double quotes, commas, semicolons, and backslashes
Special characters
: Characters outside the allowed range must be percent-encoded
Examples:
# ❌ Invalid - contains spaces
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=John's Organization"
# ✅ Valid - use underscores or camelCase instead
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=Johns_Organization"
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=JohnsOrganization"
# ✅ Valid - percent-encode special characters if needed
export
OTEL_RESOURCE_ATTRIBUTES
=
"org.name=John%27s%20Organization"
Note: wrapping values in quotes doesn’t escape spaces. For example,
org.name="My Company"
results in the literal value
"My Company"
(with quotes included), not
My Company
.
​
Example configurations
Set these environment variables before running
claude
. Each block shows a complete configuration for a different exporter or deployment scenario:
# Console debugging (1-second intervals)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
console
export
OTEL_METRIC_EXPORT_INTERVAL
=
1000
# OTLP/gRPC
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# Prometheus
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
prometheus
# Multiple exporters
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
console
,
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
http
/
json
# Different endpoints/backends for metrics and logs
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_LOGS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL
=
http
/
protobuf
export
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
=
http
://
metrics
.
example
.
com
:
4318
export
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
=
http
://
logs
.
example
.
com
:
4317
# Metrics only (no events/logs)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_METRICS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
# Events/logs only (no metrics)
export
CLAUDE_CODE_ENABLE_TELEMETRY
=
1
export
OTEL_LOGS_EXPORTER
=
otlp
export
OTEL_EXPORTER_OTLP_PROTOCOL
=
grpc
export
OTEL_EXPORTER_OTLP_ENDPOINT
=
http
://
localhost
:
4317
​
Available metrics and events
​
Standard attributes
All metrics and events share these standard attributes:
Attribute
Description
Controlled By
session.id
Unique session identifier
OTEL_METRICS_INCLUDE_SESSION_ID
(default: true)
app.version
Current Claude Code version
OTEL_METRICS_INCLUDE_VERSION
(default: false)
organization.id
Organization UUID (when authenticated)
Always included when available
user.account_uuid
Account UUID (when authenticated)
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
(default: true)
user.account_id
Account ID in tagged format matching Anthropic admin APIs (when authenticated), such as
user_01BWBeN28...
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
(default: true)
user.id
Anonymous device/installation identifier, generated per Claude Code installation
Always included
user.email
User email address (when authenticated via OAuth)
Always included when available
terminal.type
Terminal type, such as
iTerm.app
,
vscode
,
cursor
, or
tmux
Always included when detected
Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:
prompt.id
: UUID correlating a user prompt with all subsequent events until the next prompt. See
Event correlation attributes
.
workspace.host_paths
: host workspace directories selected in the desktop app, as a string array
​
Metrics
Claude Code exports the following metrics:
Metric Name
Description
Unit
claude_code.session.count
Count of CLI sessions started
count
claude_code.lines_of_code.count
Count of lines of code modified
count
claude_code.pull_request.count
Number of pull requests created
count
claude_code.commit.count
Number of git commits created
count
claude_code.cost.usage
Cost of the Claude Code session
USD
claude_code.token.usage
Number of tokens used
tokens
claude_code.code_edit_tool.decision
Count of code editing tool permission decisions
count
claude_code.active_time.total
Total active time in seconds
s
​
Metric details
Each metric includes the standard attributes listed above. Metrics with additional context-specific attributes are noted below.
​
Session counter
Incremented at the start of each session.
Attributes
:
All
standard attributes
start_type
: How the session was started. One of
"fresh"
,
"resume"
, or
"continue"
​
Lines of code counter
Incremented when code is added or removed.
Attributes
:
All
standard attributes
type
: (
"added"
,
"removed"
)
​
Pull request counter
Incremented when Claude Code creates a pull request or merge request through a shell command or an MCP tool.
Attributes
:
All
standard attributes
​
Commit counter
Incremented when creating git commits via Claude Code.
Attributes
:
All
standard attributes
​
Cost counter
Incremented after each API request.
Attributes
:
All
standard attributes
model
: Model identifier (for example, “claude-sonnet-4-6”)
query_source
: Category of the subsystem that issued the request. One of
"main"
,
"subagent"
, or
"auxiliary"
speed
:
"fast"
when the request used fast mode. Absent otherwise
effort
:
Effort level
applied to the request:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. Absent when the model does not support effort.
agent.name
: Subagent type that issued the request. Built-in agent names and agents from official-marketplace plugins appear verbatim. Other user-defined agent names are replaced with
"custom"
. Absent when the request was not issued by a named subagent type.
skill.name
: Skill active for the request, set by the Skill tool, a
/
command, or inherited by a spawned subagent. Built-in, bundled, user-defined, and official-marketplace plugin skill names appear verbatim. Third-party plugin skill names are replaced with
"third-party"
. Absent when no skill is active.
plugin.name
: Owning plugin when the active skill or subagent is provided by a plugin. Official-marketplace plugin names appear verbatim. Third-party plugin names are replaced with
"third-party"
. Absent when neither the skill nor the subagent has an owning plugin.
marketplace.name
: Marketplace the owning plugin was installed from. Only emitted for official-marketplace plugins. Absent otherwise.
​
Token counter
Incremented after each API request.
Attributes
:
All
standard attributes
type
: (
"input"
,
"output"
,
"cacheRead"
,
"cacheCreation"
)
model
: Model identifier (for example, “claude-sonnet-4-6”)
query_source
: Category of the subsystem that issued the request. One of
"main"
,
"subagent"
, or
"auxiliary"
speed
:
"fast"
when the request used fast mode. Absent otherwise
effort
:
Effort level
applied to the request. See
Cost counter
for details.
agent.name
,
skill.name
,
plugin.name
,
marketplace.name
: Skill, plugin, and agent attribution for the request. See
Cost counter
for definitions and redaction behavior.
​
Code edit tool decision counter
Incremented when user accepts or rejects Edit, Write, or NotebookEdit tool usage.
Attributes
:
All
standard attributes
tool_name
: Tool name (
"Edit"
,
"Write"
,
"NotebookEdit"
)
decision
: User decision (
"accept"
,
"reject"
)
source
: Where the decision came from. One of
"config"
,
"hook"
,
"user_permanent"
,
"user_temporary"
,
"user_abort"
, or
"user_reject"
. See the
Tool decision event
for what each value means.
language
: Programming language of the edited file, such as
"TypeScript"
,
"Python"
,
"JavaScript"
, or
"Markdown"
. Returns
"unknown"
for unrecognized file extensions.
​
Active time counter
Tracks actual time spent actively using Claude Code, excluding idle time. This metric is incremented during user interactions (typing, reading responses) and during CLI processing (tool execution, AI response generation).
Attributes
:
All
standard attributes
type
:
"user"
for keyboard interactions,
"cli"
for tool execution and AI responses
​
Events
Claude Code exports the following events via OpenTelemetry logs/events (when
OTEL_LOGS_EXPORTER
is configured):
​
Event correlation attributes
When a user submits a prompt, Claude Code may make multiple API calls and run several tools. The
prompt.id
attribute lets you tie all of those events back to the single prompt that triggered them.
Attribute
Description
prompt.id
UUID v4 identifier linking all events produced while processing a single user prompt
To trace all activity triggered by a single prompt, filter your events by a specific
prompt.id
value. This returns the user_prompt event, any api_request events, and any tool_result events that occurred while processing that prompt.
prompt.id
is intentionally excluded from metrics because each prompt generates a unique ID, which would create an ever-growing number of time series. Use it for event-level analysis and audit trails only.
​
User prompt event
Logged when a user submits a prompt.
Event Name
:
claude_code.user_prompt
Attributes
:
All
standard attributes
event.name
:
"user_prompt"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
prompt_length
: Length of the prompt
prompt
: Prompt content (redacted by default, enable with
OTEL_LOG_USER_PROMPTS=1
)
command_name
: Command name when the prompt invokes one. Built-in and bundled command names such as
compact
or
debug
are emitted as-is; aliases such as
reset
emit as typed rather than the canonical name. Custom, plugin, and MCP command names collapse to
custom
or
mcp
unless
OTEL_LOG_TOOL_DETAILS=1
is set
command_source
: Origin of the command when present:
builtin
,
custom
, or
mcp
. Plugin-provided commands report as
custom
​
Tool result event
Logged when a tool completes execution.
Event Name
:
claude_code.tool_result
Attributes
:
All
standard attributes
event.name
:
"tool_result"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
tool_name
: Name of the tool
tool_use_id
: Unique identifier for this tool invocation. Matches the
tool_use_id
passed to hooks, allowing correlation between OTel events and hook-captured data.
success
:
"true"
or
"false"
duration_ms
: Execution time in milliseconds
error_type
: Error category string when the tool failed, such as
"Error:ENOENT"
or
"ShellError"
error
(when
OTEL_LOG_TOOL_DETAILS=1
): Full error message when the tool failed
decision_type
: Either
"accept"
or
"reject"
decision_source
: Where the decision came from. One of
"config"
,
"hook"
,
"user_permanent"
,
"user_temporary"
,
"user_abort"
, or
"user_reject"
. See the
Tool decision event
for what each value means.
tool_input_size_bytes
: Size of the JSON-serialized tool input in bytes
tool_result_size_bytes
: Size of the tool result in bytes
mcp_server_scope
: MCP server scope identifier (for MCP tools)
tool_parameters
(when
OTEL_LOG_TOOL_DETAILS=1
): JSON string containing tool-specific parameters:
For Bash tool: includes
bash_command
,
full_command
,
timeout
,
description
,
dangerouslyDisableSandbox
, and
git_commit_id
(the commit SHA, when a
git commit
command succeeds)
For MCP tools: includes
mcp_server_name
,
mcp_tool_name
For Skill tool: includes
skill_name
For Task tool: includes
subagent_type
tool_input
(when
OTEL_LOG_TOOL_DETAILS=1
): JSON-serialized tool arguments. Individual values over 512 characters are truncated, and the full payload is bounded to ~4 K characters. Applies to all tools including MCP tools.
​
API request event
Logged for each API request to Claude.
Event Name
:
claude_code.api_request
Attributes
:
All
standard attributes
event.name
:
"api_request"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used (for example, “claude-sonnet-4-6”)
cost_usd
: Estimated cost in USD
duration_ms
: Request duration in milliseconds
input_tokens
: Number of input tokens
output_tokens
: Number of output tokens
cache_read_tokens
: Number of tokens read from cache
cache_creation_tokens
: Number of tokens used for cache creation
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
speed
:
"fast"
or
"normal"
, indicating whether fast mode was active
query_source
: Subsystem that issued the request, such as
"repl_main_thread"
,
"compact"
, or a subagent name
effort
:
Effort level
applied to the request:
"low"
,
"medium"
,
"high"
,
"xhigh"
, or
"max"
. Absent when the model does not support effort.
​
API error event
Logged when an API request to Claude fails.
Event Name
:
claude_code.api_error
Attributes
:
All
standard attributes
event.name
:
"api_error"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used (for example, “claude-sonnet-4-6”)
error
: Error message
status_code
: HTTP status code as a number. Absent for non-HTTP errors such as connection failures.
duration_ms
: Request duration in milliseconds
attempt
: Total number of attempts made, including the initial request (
1
means no retries occurred)
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
speed
:
"fast"
or
"normal"
, indicating whether fast mode was active
query_source
: Subsystem that issued the request, such as
"repl_main_thread"
,
"compact"
, or a subagent name
effort
:
Effort level
applied to the request. Absent when the model does not support effort.
​
API request body event
Logged for each API request attempt when
OTEL_LOG_RAW_API_BODIES
is set. One event is emitted per attempt, so retries with adjusted parameters each produce their own event.
Event Name
:
claude_code.api_request_body
Attributes
:
All
standard attributes
event.name
:
"api_request_body"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
body
: JSON-serialized Messages API request parameters (system prompt, messages, tools, etc.), truncated at 60 KB. Extended-thinking content in prior assistant turns is redacted. Emitted only in inline mode (
OTEL_LOG_RAW_API_BODIES=1
).
body_ref
: Absolute path to a
<dir>/<uuid>.request.json
file containing the untruncated body. Emitted only in file mode (
OTEL_LOG_RAW_API_BODIES=file:<dir>
).
body_length
: Untruncated body length. UTF-8 bytes when
OTEL_LOG_RAW_API_BODIES=file:<dir>
, or UTF-16 code units when
=1
body_truncated
:
"true"
when inline truncation occurred. Absent in file mode and when no truncation occurred.
model
: Model identifier from the request parameters
query_source
: Subsystem that issued the request (for example,
"compact"
)
​
API response body event
Logged for each successful API response when
OTEL_LOG_RAW_API_BODIES
is set.
Event Name
:
claude_code.api_response_body
Attributes
:
All
standard attributes
event.name
:
"api_response_body"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
body
: JSON-serialized Messages API response (id, content blocks, usage, stop reason), truncated at 60 KB. Extended-thinking content is redacted. Emitted only in inline mode (
OTEL_LOG_RAW_API_BODIES=1
).
body_ref
: Absolute path to a
<dir>/<request_id>.response.json
file containing the untruncated body. Emitted only in file mode (
OTEL_LOG_RAW_API_BODIES=file:<dir>
).
body_length
: Untruncated body length. UTF-8 bytes when
OTEL_LOG_RAW_API_BODIES=file:<dir>
, or UTF-16 code units when
=1
body_truncated
:
"true"
when inline truncation occurred. Absent in file mode and when no truncation occurred.
model
: Model identifier
query_source
: Subsystem that issued the request
request_id
: Anthropic API request ID from the response’s
request-id
header, such as
"req_011..."
. Present only when the API returns one.
​
Tool decision event
Logged when a tool permission decision is made (accept/reject).
Event Name
:
claude_code.tool_decision
Attributes
:
All
standard attributes
event.name
:
"tool_decision"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
tool_name
: Name of the tool (for example, “Read”, “Edit”, “Write”, “NotebookEdit”)
tool_use_id
: Unique identifier for this tool invocation. Matches the
tool_use_id
passed to hooks, allowing correlation between OTel events and hook-captured data.
decision
: Either
"accept"
or
"reject"
source
: Where the decision came from:
"config"
: Decided automatically without prompting, based on project settings, allow rules in the user’s personal settings, enterprise managed policy,
--allowedTools
or
--disallowedTools
flags, the active permission mode, a session-scoped grant from an earlier prompt in the same interactive CLI session, or because the tool is inherently safe. The event does not indicate which of these sources matched.
"hook"
: A
PreToolUse
or
PermissionRequest
hook returned the decision.
"user_permanent"
: Emitted when the user chose “Yes, and don’t ask again for …” at a permission prompt, which saves an allow rule to their personal settings. In the interactive CLI this is emitted only for that choice itself; later calls that match the saved rule emit
"config"
instead. In Agent SDK or non-interactive
-p
sessions, both the initial choice and later rule matches emit
"user_permanent"
. Treated as an accept.
"user_temporary"
: Emitted when the user chose “Yes” at a permission prompt for a one-time approval, or chose one of the ”… during this session” options on a file edit or read prompt. In the interactive CLI this is emitted only for the choice itself; later calls allowed by that session-scoped grant emit
"config"
instead. In Agent SDK or non-interactive
-p
sessions, both the choice and later matches emit
"user_temporary"
. Treated as an accept.
"user_abort"
: Emitted when the user dismissed the permission prompt without answering. Treated as a reject.
"user_reject"
: Emitted when the user chose “No” when prompted, or a call matched a deny rule in their personal settings. Treated as a reject.
​
Permission mode changed event
Logged when the permission mode changes, for example from
Shift+Tab
cycling, exiting plan mode, or an auto mode gate check.
Event Name
:
claude_code.permission_mode_changed
Attributes
:
All
standard attributes
event.name
:
"permission_mode_changed"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
from_mode
: The previous permission mode, for example
"default"
,
"plan"
,
"acceptEdits"
,
"auto"
, or
"bypassPermissions"
to_mode
: The new permission mode
trigger
: What caused the change. One of
"shift_tab"
,
"exit_plan_mode"
,
"auto_gate_denied"
, or
"auto_opt_in"
. Absent when the transition originates from the SDK or bridge
​
Auth event
Logged when
/login
or
/logout
completes.
Event Name
:
claude_code.auth
Attributes
:
All
standard attributes
event.name
:
"auth"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
action
:
"login"
or
"logout"
success
:
"true"
or
"false"
auth_method
: Authentication method, such as
"oauth"
error_category
: Categorical error kind when the action failed. The raw error message is never included
status_code
: HTTP status code as a string when the action failed with an HTTP error
​
MCP server connection event
Logged when an MCP server connects, disconnects, or fails to connect.
Event Name
:
claude_code.mcp_server_connection
Attributes
:
All
standard attributes
event.name
:
"mcp_server_connection"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
status
:
"connected"
,
"failed"
, or
"disconnected"
transport_type
: Server transport, such as
"stdio"
,
"sse"
, or
"http"
server_scope
: Scope the server is configured at, such as
"user"
,
"project"
, or
"local"
duration_ms
: Connection attempt duration in milliseconds
error_code
: Error code when the connection failed
server_name
(when
OTEL_LOG_TOOL_DETAILS=1
): Configured server name
error
(when
OTEL_LOG_TOOL_DETAILS=1
): Full error message when the connection failed
​
Internal error event
Logged when Claude Code catches an unexpected internal error. Only the error class name and an errno-style code are recorded. The error message and stack trace are never included. This event is not emitted when running against Bedrock, Vertex, or Foundry, or when
DISABLE_ERROR_REPORTING
is set.
Event Name
:
claude_code.internal_error
Attributes
:
All
standard attributes
event.name
:
"internal_error"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
error_name
: Error class name, such as
"TypeError"
or
"SyntaxError"
error_code
: Node.js errno code such as
"ENOENT"
when present on the error
​
Plugin installed event
Logged when a plugin finishes installing, from both the
claude plugin install
CLI command and the interactive
/plugin
UI.
Event Name
:
claude_code.plugin_installed
Attributes
:
All
standard attributes
event.name
:
"plugin_installed"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
marketplace.is_official
:
"true"
if the marketplace is an official Anthropic marketplace,
"false"
otherwise
install.trigger
:
"cli"
or
"ui"
plugin.name
: Name of the installed plugin. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
plugin.version
: Plugin version when declared in the marketplace entry. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
marketplace.name
: Marketplace the plugin was installed from. For third-party marketplaces this is included only when
OTEL_LOG_TOOL_DETAILS=1
​
Plugin loaded event
Logged once per enabled plugin at session start. Use this event to inventory which plugins are active across your fleet, as a complement to
plugin_installed
which records the install action itself.
Event Name
:
claude_code.plugin_loaded
Attributes
:
All
standard attributes
event.name
:
"plugin_loaded"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
plugin.name
: name of the plugin. For plugins outside the official marketplace and built-in bundle the value is
"third-party"
unless
OTEL_LOG_TOOL_DETAILS=1
marketplace.name
: marketplace the plugin was installed from, when known. Redacted to
"third-party"
under the same condition as
plugin.name
plugin.version
: version from the plugin manifest. Included only when the name is not redacted and the manifest declares a version
plugin.scope
: provenance category for the plugin:
"official"
,
"org"
,
"user-local"
, or
"default-bundle"
enabled_via
: how the plugin came to be enabled:
"default-enable"
,
"org-policy"
,
"seed-mount"
, or
"user-install"
plugin_id_hash
: deterministic hash of the plugin name and marketplace, sent only to your configured exporter. Lets you count how many distinct third-party plugins are loaded across your fleet without recording their names
has_hooks
: whether the plugin contributes hooks
has_mcp
: whether the plugin contributes MCP servers
skill_path_count
: number of skill directories the plugin declares
command_path_count
: number of command directories the plugin declares
agent_path_count
: number of agent directories the plugin declares
​
Skill activated event
Logged when a skill is invoked, whether Claude calls it through the Skill tool or you run it as a
/
command.
Event Name
:
claude_code.skill_activated
Attributes
:
All
standard attributes
event.name
:
"skill_activated"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
skill.name
: Name of the skill. For user-defined and third-party plugin skills the value is the placeholder
"custom_skill"
unless
OTEL_LOG_TOOL_DETAILS=1
invocation_trigger
: How the skill was triggered (
"user-slash"
,
"claude-proactive"
, or
"nested-skill"
)
skill.source
: Where the skill was loaded from (for example,
"bundled"
,
"userSettings"
,
"projectSettings"
,
"plugin"
)
plugin.name
(when
OTEL_LOG_TOOL_DETAILS=1
or the plugin is from an official marketplace): Name of the owning plugin when the skill is provided by a plugin
marketplace.name
(when
OTEL_LOG_TOOL_DETAILS=1
or the plugin is from an official marketplace): Marketplace the owning plugin was installed from, when the skill is provided by a plugin
​
At mention event
Logged when Claude Code resolves an
@
-mention in a prompt. Not every mention emits an event: early-exit paths such as permission denials, oversized files, PDF reference attachments, and directory listing failures return without logging.
Event Name
:
claude_code.at_mention
Attributes
:
All
standard attributes
event.name
:
"at_mention"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
mention_type
: Type of mention (
"file"
,
"directory"
,
"agent"
,
"mcp_resource"
)
success
: Whether the mention resolved successfully (
"true"
or
"false"
)
​
API retries exhausted event
Logged once when an API request fails after more than one attempt. Emitted alongside the final
api_error
event.
Event Name
:
claude_code.api_retries_exhausted
Attributes
:
All
standard attributes
event.name
:
"api_retries_exhausted"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
model
: Model used
error
: Final error message
status_code
: HTTP status code as a number. Absent for non-HTTP errors.
total_attempts
: Total number of attempts made
total_retry_duration_ms
: Total wall-clock time across all attempts
speed
:
"fast"
or
"normal"
​
Hook registered event
Logged once per configured hook at session start. Use this event to inventory which hooks are active across your fleet, as a complement to the per-execution
hook_execution_start
and
hook_execution_complete
events.
Event Name
:
claude_code.hook_registered
Attributes
:
All
standard attributes
event.name
:
"hook_registered"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: hook event type, such as
"PreToolUse"
or
"PostToolUse"
hook_type
: hook implementation type:
"command"
,
"prompt"
,
"mcp_tool"
,
"http"
, or
"agent"
hook_source
: where the hook is defined:
"userSettings"
,
"projectSettings"
,
"localSettings"
,
"flagSettings"
,
"policySettings"
, or
"pluginHook"
hook_matcher
(when
OTEL_LOG_TOOL_DETAILS=1
): the matcher string from the hook configuration, when one is set
plugin.name
(when
hook_source
is
"pluginHook"
): name of the contributing plugin. For plugins outside the official marketplace and built-in bundle the value is
"third-party"
unless
OTEL_LOG_TOOL_DETAILS=1
plugin_id_hash
(when
hook_source
is
"pluginHook"
): deterministic hash of the plugin name and marketplace, sent only to your configured exporter. Lets you count distinct contributing plugins without recording their names
​
Hook execution start event
Logged when one or more hooks begin executing for a hook event.
Event Name
:
claude_code.hook_execution_start
Attributes
:
All
standard attributes
event.name
:
"hook_execution_start"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: Hook event type, such as
"PreToolUse"
or
"PostToolUse"
hook_name
: Full hook name including matcher, such as
"PreToolUse:Write"
num_hooks
: Number of matching hook commands
managed_only
:
"true"
when only managed-policy hooks are permitted
hook_source
:
"policySettings"
or
"merged"
hook_definitions
: JSON-serialized hook configuration. Included only when both detailed beta tracing and
OTEL_LOG_TOOL_DETAILS=1
are enabled
​
Hook execution complete event
Logged when all hooks for a hook event have finished.
Event Name
:
claude_code.hook_execution_complete
Attributes
:
All
standard attributes
event.name
:
"hook_execution_complete"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
hook_event
: Hook event type
hook_name
: Full hook name including matcher
num_hooks
: Number of matching hook commands
num_success
: Count that completed successfully
num_blocking
: Count that returned a blocking decision
num_non_blocking_error
: Count that failed without blocking
num_cancelled
: Count cancelled before completion
total_duration_ms
: Wall-clock duration of all matching hooks
managed_only
:
"true"
when only managed-policy hooks are permitted
hook_source
:
"policySettings"
or
"merged"
hook_definitions
: JSON-serialized hook configuration. Included only when both detailed beta tracing and
OTEL_LOG_TOOL_DETAILS=1
are enabled
​
Compaction event
Logged when conversation compaction completes.
Event Name
:
claude_code.compaction
Attributes
:
All
standard attributes
event.name
:
"compaction"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
trigger
:
"auto"
or
"manual"
success
:
"true"
or
"false"
duration_ms
: Compaction duration
pre_tokens
: Approximate token count before compaction
post_tokens
: Approximate token count after compaction
error
: Error message when compaction failed
​
Feedback survey event
Logged when a session quality survey is shown or answered. See
Session quality surveys
for what the surveys collect and how to control them.
Event Name
:
claude_code.feedback_survey
Attributes
:
All
standard attributes
event.name
:
"feedback_survey"
event.timestamp
: ISO 8601 timestamp
event.sequence
: monotonically increasing counter for ordering events within a session
event_type
: Survey lifecycle event, for example
"appeared"
,
"responded"
, or
"transcript_prompt_appeared"
appearance_id
: Unique ID linking the events emitted for one survey instance
survey_type
: Which survey produced the event.
"session"
is the “How is Claude doing?” rating prompt
response
: The user’s selection on
responded
events
enabled_via_override
:
true
when
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
is set. Emitted as a boolean, not a string. Present on
session
survey events. Filter on this attribute to confirm the override is applied across a fleet
​
Interpret metrics and events data
The exported metrics and events support a range of analyses:
​
Usage monitoring
Metric
Analysis Opportunity
claude_code.token.usage
Break down by
type
(input/output), user, team, model,
skill.name
,
plugin.name
, or
agent.name
claude_code.session.count
Track adoption and engagement over time
claude_code.lines_of_code.count
Measure productivity by tracking code additions/removals
claude_code.commit.count
&
claude_code.pull_request.count
Understand impact on development workflows
​
Cost monitoring
The
claude_code.cost.usage
metric helps with:
Tracking usage trends across teams or individuals
Identifying high-usage sessions for optimization
Attributing spend to specific skills, plugins, or subagent types via the
skill.name
,
plugin.name
, and
agent.name
attributes
Cost metrics are approximations. For official billing data, refer to your API provider (Claude Console, Amazon Bedrock, or Google Cloud Vertex).
​
Alerting and segmentation
Common alerts to consider:
Cost spikes
Unusual token consumption
High session volume from specific users
All metrics can be segmented by
user.account_uuid
,
user.account_id
,
organization.id
,
session.id
,
model
, and
app.version
.
​
Detect retry exhaustion
Claude Code retries failed API requests internally and emits a single
claude_code.api_error
event only after it gives up, so the event itself is the terminal signal for that request. Intermediate retry attempts are not logged as separate events.
The
attempt
attribute on the event records how many attempts were made in total. A value greater than
CLAUDE_CODE_MAX_RETRIES
(default
10
) indicates the request exhausted all retries on a transient error. A lower value indicates a non-retryable error such as a
400
response.
To distinguish a session that recovered from one that stalled, group events by
session.id
and check whether a later
api_request
event exists after the error.
​
Event analysis
The event data provides detailed insights into Claude Code interactions:
Tool Usage Patterns
: analyze tool result events to identify:
Most frequently used tools
Tool success rates
Average tool execution times
Error patterns by tool type
Performance Monitoring
: track API request durations and tool execution times to identify performance bottlenecks.
​
Audit security events
OpenTelemetry events are the audit data source for Claude Code activity. Every event carries identity attributes that tie tool calls, MCP activity, and permission decisions back to the user who triggered them, and the OTLP logs exporter can deliver these events to any Security Information and Event Management (SIEM) platform with an OTLP receiver or to an OpenTelemetry Collector that forwards to your SIEM.
​
Attribute actions to users
The
standard attributes
on each event include the authenticated user’s identity:
user.email
,
user.account_uuid
,
user.account_id
, and
organization.id
when signed in with a Claude account, plus the installation-scoped
user.id
and the per-session
session.id
.
MCP tool calls, Bash commands, and file edits are therefore attributed to the developer who started the session. Claude Code does not act under a separate service account; the identity recorded on each event is the developer’s own Claude account.
When Claude Code authenticates with a direct API key, or against Bedrock, Vertex AI, or Microsoft Foundry, there is no Claude account in the session and only
user.id
and
session.id
are populated. In these deployments, attach user identity yourself with
OTEL_RESOURCE_ATTRIBUTES
, set per user through the
managed settings
file or a launch wrapper:
export
OTEL_RESOURCE_ATTRIBUTES
=
"enduser.id=jdoe@example.com,enduser.directory_id=S-1-5-21-..."
​
Audit MCP activity
To capture MCP server activity with full call detail, enable the logs exporter and set
OTEL_LOG_TOOL_DETAILS=1
. Each MCP operation then produces structured events that carry the server name, tool name, and call arguments alongside the standard identity attributes:
Event
What it records for MCP
mcp_server_connection
Server connect, disconnect, and connection failure with
server_name
,
transport_type
,
server_scope
, and error detail
tool_result
Each MCP tool call with
tool_name
and
mcp_server_scope
, a
tool_parameters
payload containing
mcp_server_name
and
mcp_tool_name
, and a
tool_input
payload containing the call arguments
tool_decision
Whether the call was allowed or denied, and whether the decision came from config, a hook, or the user
Without
OTEL_LOG_TOOL_DETAILS
,
tool_result
events still carry
tool_name
and
mcp_server_scope
but omit the
mcp_server_name
/
mcp_tool_name
breakdown and the arguments, and
mcp_server_connection
events omit
server_name
and the error message.
​
Map security questions to events
When building detection rules, look up the signal you want to monitor and query your backend for the corresponding event and attributes:
Signal
Event
Key attributes
Tool call allowed or denied, and by what
tool_decision
decision
,
source
,
tool_name
Permission mode escalation
permission_mode_changed
from_mode
,
to_mode
,
trigger
Policy hook blocked an action
hook_execution_complete
hook_event
,
num_blocking
Login, logout, and authentication failure
auth
action
,
success
,
error_category
MCP server connect or failure
mcp_server_connection
status
,
server_name
,
error_code
Plugin installed and its source
plugin_installed
plugin.name
,
marketplace.name
,
marketplace.is_official
Commands run and files touched
tool_result
with
OTEL_LOG_TOOL_DETAILS=1
tool_parameters
,
tool_input
Claude Code emits the raw event stream only. Anomaly detection, baselining, correlation across sessions, and alerting are the responsibility of your SIEM or observability backend.
​
Send events to a SIEM
Point
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
at your SIEM’s OTLP receiver, or at an OpenTelemetry Collector that forwards to your SIEM’s native ingest API. The following managed-settings example exports events only, with full tool detail enabled for MCP and Bash auditing:
{
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_LOGS_EXPORTER"
:
"otlp"
,
"OTEL_LOG_TOOL_DETAILS"
:
"1"
,
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL"
:
"http/protobuf"
,
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
:
"https://siem.example.com:4318/v1/logs"
,
"OTEL_EXPORTER_OTLP_HEADERS"
:
"Authorization=Bearer your-siem-token"
}
}
​
Backend considerations
Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:
​
For metrics
Time series databases (for example, Prometheus)
: Rate calculations, aggregated metrics
Columnar stores (for example, ClickHouse)
: Complex queries, unique user analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Advanced querying, visualization, alerting
​
For events/logs
Log aggregation systems (for example, Elasticsearch, Loki)
: Full-text search, log analysis
Columnar stores (for example, ClickHouse)
: Structured event analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Correlation between metrics and events
​
For traces
Choose a backend that supports distributed trace storage and span correlation:
Distributed tracing systems (for example, Jaeger, Zipkin, Grafana Tempo)
: Span visualization, request waterfalls, latency analysis
Full-featured observability platforms (for example, Honeycomb, Datadog)
: Trace search and correlation with metrics and logs
For organizations requiring Daily/Weekly/Monthly Active User (DAU/WAU/MAU) metrics, consider backends that support efficient unique value queries.
​
Service information
All metrics and events are exported with the following resource attributes:
service.name
:
claude-code
service.version
: Current Claude Code version
os.type
: Operating system type (for example,
linux
,
darwin
,
windows
)
os.version
: Operating system version string
host.arch
: Host architecture (for example,
amd64
,
arm64
)
wsl.version
: WSL version number (only present when running on Windows Subsystem for Linux)
Meter Name:
com.anthropic.claude_code
​
ROI measurement resources
For a comprehensive guide on measuring return on investment for Claude Code, including telemetry setup, cost analysis, productivity metrics, and automated reporting, see the
Claude Code ROI Measurement Guide
. This repository provides ready-to-use Docker Compose configurations, Prometheus and OpenTelemetry setups, and templates for generating productivity reports integrated with tools like Linear.
​
Security and privacy
OpenTelemetry export to your backend is opt-in and requires explicit configuration. For Anthropic’s separate operational telemetry and how to disable it, see
Data usage
Raw file contents and code snippets are not included in metrics or events. Trace spans are a separate data path: see the
OTEL_LOG_TOOL_CONTENT
bullet below
When authenticated via OAuth,
user.email
is included in telemetry attributes. If this is a concern for your organization, work with your telemetry backend to filter or redact this field
User prompt content is not collected by default. Only prompt length is recorded. To include prompt content, set
OTEL_LOG_USER_PROMPTS=1
Tool input arguments and parameters are not logged by default. To include them, set
OTEL_LOG_TOOL_DETAILS=1
. When enabled,
tool_result
events include a
tool_parameters
attribute with Bash commands, MCP server and tool names, and skill names, plus a
tool_input
attribute with file paths, URLs, search patterns, and other arguments.
user_prompt
events include the verbatim
command_name
for custom, plugin, and MCP commands. Trace spans include the same
tool_input
attribute and input-derived attributes such as
file_path
. Individual values over 512 characters are truncated and the total is bounded to ~4 K characters, but the arguments may still contain sensitive values. Configure your telemetry backend to filter or redact these attributes as needed
Tool input and output content is not logged in trace spans by default. To include it, set
OTEL_LOG_TOOL_CONTENT=1
. When enabled, span events include full tool input and output content truncated at 60 KB per span. This can include raw file contents from Read tool results and Bash command output. Configure your telemetry backend to filter or redact these attributes as needed
Raw Anthropic Messages API request and response bodies are not logged by default. To include them, set
OTEL_LOG_RAW_API_BODIES
. With
=1
, each API call emits
api_request_body
and
api_response_body
log events whose
body
attribute is the JSON-serialized payload, truncated at 60 KB. With
=file:<dir>
, untruncated bodies are written to
.request.json
and
.response.json
files under that directory and the events carry a
body_ref
path instead of the inline body. Ship the directory with a log collector or sidecar rather than through the telemetry stream. In both modes, bodies contain the full conversation history (system prompt, every prior user and assistant turn, tool results), so enabling this implies consent to everything the other
OTEL_LOG_*
content flags would reveal. Claude’s extended-thinking content is always redacted from these bodies regardless of other settings
​
Monitor Claude Code on Amazon Bedrock
For detailed Claude Code usage monitoring guidance for Amazon Bedrock, see
Claude Code Monitoring Implementation (Bedrock)
.
Was this page helpful?
Yes
No
Development containers
Costs
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/monitoring-usage" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Extend Claude with skills</title>
  <link>https://code.claude.com/docs/en/skills</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/skills</guid>
  <pubDate>Tue, 27 Feb 2024 00:00:00 +0000</pubDate>
  <category>Skills</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Extend Claude with skills
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Extend Claude with skills
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Skills extend what Claude can do. Create a
SKILL.md
file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with
/skill-name
.
Create a skill when you keep pasting the same instructions, checklist, or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact. Unlike CLAUDE.md content, a skill’s body loads only when it’s used, so long reference material costs almost nothing until you need it.
For built-in commands like
/help
and
/compact
, and bundled skills like
/debug
and
/simplify
, see the
commands reference
.
Custom commands have been merged into skills.
A file at
.claude/commands/deploy.md
and a skill at
.claude/skills/deploy/SKILL.md
both create
/deploy
and work the same way. Your existing
.claude/commands/
files keep working. Skills add optional features: a directory for supporting files, frontmatter to
control whether you or Claude invokes them
, and the ability for Claude to load them automatically when relevant.
Claude Code skills follow the
Agent Skills
open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like
invocation control
,
subagent execution
, and
dynamic context injection
.
​
Bundled skills
Claude Code includes a set of bundled skills that are available in every session, including
/simplify
,
/batch
,
/debug
,
/loop
, and
/claude-api
. Unlike most built-in commands, which execute fixed logic directly, bundled skills are prompt-based: they give Claude detailed instructions and let it orchestrate the work using its tools. You invoke them the same way as any other skill, by typing
/
followed by the skill name.
Bundled skills are listed alongside built-in commands in the
commands reference
, marked
Skill
in the Purpose column.
​
Getting started
​
Create your first skill
This example creates a skill that summarizes the uncommitted changes in your git repository and flags anything risky. It pulls the live diff into the prompt before Claude reads it, so the response is grounded in your actual working tree rather than what Claude can guess from open files. Claude loads the skill automatically when you ask about your changes, or you can invoke it directly with
/summarize-changes
.
1
Create the skill directory
Create a directory for the skill in your personal skills folder. Personal skills are available across all your projects.
mkdir
-p
~/.claude/skills/summarize-changes
2
Write SKILL.md
Every skill needs a
SKILL.md
file with two parts: YAML frontmatter between
---
markers that tells Claude when to use the skill, and markdown content with the instructions Claude follows when the skill runs. The directory name becomes the command you type, and the
description
helps Claude decide when to load the skill automatically.
Save this to
~/.claude/skills/summarize-changes/SKILL.md
:
---
description
:
Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---
## Current changes
!`git
diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes.
The
!`git diff HEAD`
line uses
dynamic context injection
: Claude Code runs the command and replaces the line with its output before Claude sees the skill content, so the instructions arrive with the current diff already inlined.
3
Test the skill
Open a git project, make a small edit to any file, and start Claude Code by running
claude
. You can test the skill two ways.
Let Claude invoke it automatically
by asking something that matches the description:
What did I change?
Or invoke it directly
with the skill name:
/summarize-changes
Either way, Claude should respond with a short summary of your edit and a list of risks.
​
Where skills live
Where you store a skill determines who can use it:
Location
Path
Applies to
Enterprise
See
managed settings
All users in your organization
Personal
~/.claude/skills/<skill-name>/SKILL.md
All your projects
Project
.claude/skills/<skill-name>/SKILL.md
This project only
Plugin
<plugin>/skills/<skill-name>/SKILL.md
Where plugin is enabled
When skills share the same name across levels, enterprise overrides personal, and personal overrides project. Plugin skills use a
plugin-name:skill-name
namespace, so they cannot conflict with other levels. If you have files in
.claude/commands/
, those work the same way, but if a skill and a command share the same name, the skill takes precedence.
​
Live change detection
Claude Code watches skill directories for file changes. Adding, editing, or removing a skill under
~/.claude/skills/
, the project
.claude/skills/
, or a
.claude/skills/
inside an
--add-dir
directory takes effect within the current session without restarting. Creating a top-level skills directory that did not exist when the session started requires restarting Claude Code so the new directory can be watched.
​
Automatic discovery from parent and nested directories
Project skills load from
.claude/skills/
in your starting directory and in every parent directory up to the repository root, so starting Claude in a subdirectory still picks up skills defined at the root. When you work with files in subdirectories below your starting directory, Claude Code also discovers skills from nested
.claude/skills/
directories on demand. For example, if you’re editing a file in
packages/frontend/
, Claude Code also looks for skills in
packages/frontend/.claude/skills/
. This supports monorepo setups where packages have their own skills.
Each skill is a directory with
SKILL.md
as the entrypoint:
my-skill/
├── SKILL.md           # Main instructions (required)
├── template.md        # Template for Claude to fill in
├── examples/
│   └── sample.md      # Example output showing expected format
└── scripts/
└── validate.sh    # Script Claude can execute
The
SKILL.md
contains the main instructions and is required. Other files are optional and let you build more powerful skills: templates for Claude to fill in, example outputs showing the expected format, scripts Claude can execute, or detailed reference documentation. Reference these files from your
SKILL.md
so Claude knows what they contain and when to load them. See
Add supporting files
for more details.
Files in
.claude/commands/
still work and support the same
frontmatter
. Skills are recommended since they support additional features like supporting files.
​
Skills from additional directories
The
--add-dir
flag
grants file access
rather than configuration discovery, but skills are an exception:
.claude/skills/
within an added directory is loaded automatically. See
Live change detection
for how edits are picked up during a session.
Other
.claude/
configuration such as subagents, commands, and output styles is not loaded from additional directories. See the
exceptions table
for the complete list of what is and isn’t loaded, and the recommended ways to share configuration across projects.
CLAUDE.md files from
--add-dir
directories are not loaded by default. To load them, set
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1
. See
Load from additional directories
.
​
Configure skills
Skills are configured through YAML frontmatter at the top of
SKILL.md
and the markdown content that follows.
​
Types of skill content
Skill files can contain any instructions, but thinking about how you want to invoke them helps guide what to include:
Reference content
adds knowledge Claude applies to your current work. Conventions, patterns, style guides, domain knowledge. This content runs inline so Claude can use it alongside your conversation context.
---
name
:
api-conventions
description
:
API design patterns for this codebase
---
When writing API endpoints
:
-
Use RESTful naming conventions
-
Return consistent error formats
-
Include request validation
Task content
gives Claude step-by-step instructions for a specific action, like deployments, commits, or code generation. These are often actions you want to invoke directly with
/skill-name
rather than letting Claude decide when to run them. Add
disable-model-invocation: true
to prevent Claude from triggering it automatically.
---
name
:
deploy
description
:
Deploy the application to production
context
:
fork
disable-model-invocation
:
true
---
Deploy the application
:
1. Run the test suite
2. Build the application
3. Push to the deployment target
Your
SKILL.md
can contain anything, but thinking through how you want the skill invoked (by you, by Claude, or both) and where you want it to run (inline or in a subagent) helps guide what to include. For complex skills, you can also
add supporting files
to keep the main skill focused.
Keep the body itself concise. Once a skill loads, its content
stays in context across turns
, so every line is a recurring token cost. State what to do rather than narrating how or why, and apply the same conciseness test you would for
CLAUDE.md content
.
​
Frontmatter reference
Beyond the markdown content, you can configure skill behavior using YAML frontmatter fields between
---
markers at the top of your
SKILL.md
file:
---
name
:
my-skill
description
:
What this skill does
disable-model-invocation
:
true
allowed-tools
:
Read Grep
---
Your skill instructions here...
All fields are optional. Only
description
is recommended so Claude knows when to use the skill.
Field
Required
Description
name
No
Display name for the skill. If omitted, uses the directory name. Lowercase letters, numbers, and hyphens only (max 64 characters).
description
Recommended
What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. Put the key use case first: the combined
description
and
when_to_use
text is truncated at 1,536 characters in the skill listing to reduce context usage.
when_to_use
No
Additional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to
description
in the skill listing and counts toward the 1,536-character cap.
argument-hint
No
Hint shown during autocomplete to indicate expected arguments. Example:
[issue-number]
or
[filename] [format]
.
arguments
No
Named positional arguments for
$name
substitution
in the skill content. Accepts a space-separated string or a YAML list. Names map to argument positions in order.
disable-model-invocation
No
Set to
true
to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with
/name
. Also prevents the skill from being
preloaded into subagents
. Default:
false
.
user-invocable
No
Set to
false
to hide from the
/
menu. Use for background knowledge users shouldn’t invoke directly. Default:
true
.
allowed-tools
No
Tools Claude can use without asking permission when this skill is active. Accepts a space-separated string or a YAML list.
model
No
Model to use when this skill is active. The override applies for the rest of the current turn and is not saved to settings; the session model resumes on your next prompt. Accepts the same values as
/model
, or
inherit
to keep the active model.
effort
No
Effort level
when this skill is active. Overrides the session effort level. Default: inherits from session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model.
context
No
Set to
fork
to run in a forked subagent context.
agent
No
Which subagent type to use when
context: fork
is set.
hooks
No
Hooks scoped to this skill’s lifecycle. See
Hooks in skills and agents
for configuration format.
paths
No
Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as
path-specific rules
.
shell
No
Shell to use for
!`command`
and
```!
blocks in this skill. Accepts
bash
(default) or
powershell
. Setting
powershell
runs inline shell commands via PowerShell on Windows. Requires
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
.
​
Available string substitutions
Skills support string substitution for dynamic values in the skill content:
Variable
Description
$ARGUMENTS
All arguments passed when invoking the skill. If
$ARGUMENTS
is not present in the content, arguments are appended as
ARGUMENTS: <value>
.
$ARGUMENTS[N]
Access a specific argument by 0-based index, such as
$ARGUMENTS[0]
for the first argument.
$N
Shorthand for
$ARGUMENTS[N]
, such as
$0
for the first argument or
$1
for the second.
$name
Named argument declared in the
arguments
frontmatter list. Names map to positions in order, so with
arguments: [issue, branch]
the placeholder
$issue
expands to the first argument and
$branch
to the second.
${CLAUDE_SESSION_ID}
The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions.
${CLAUDE_EFFORT}
The current effort level:
low
,
medium
,
high
,
xhigh
, or
max
. Use this to adapt skill instructions to the active effort setting.
${CLAUDE_SKILL_DIR}
The directory containing the skill’s
SKILL.md
file. For plugin skills, this is the skill’s subdirectory within the plugin, not the plugin root. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory.
Indexed arguments use shell-style quoting, so wrap multi-word values in quotes to pass them as a single argument. For example,
/my-skill "hello world" second
makes
$0
expand to
hello world
and
$1
to
second
. The
$ARGUMENTS
placeholder always expands to the full argument string as typed.
Example using substitutions:
---
name
:
session-logger
description
:
Log activity for this session
---
Log the following to logs/${CLAUDE_SESSION_ID}.log
:
$ARGUMENTS
​
Add supporting files
Skills can include multiple files in their directory. This keeps
SKILL.md
focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don’t need to load into context every time the skill runs.
my-skill/
├── SKILL.md (required - overview and navigation)
├── reference.md (detailed API docs - loaded when needed)
├── examples.md (usage examples - loaded when needed)
└── scripts/
└── helper.py (utility script - executed, not loaded)
Reference supporting files from
SKILL.md
so Claude knows what each file contains and when to load it:
## Additional resources
-
For complete API details, see [
reference.md
](
reference.md
)
-
For usage examples, see [
examples.md
](
examples.md
)
Keep
SKILL.md
under 500 lines. Move detailed reference material to separate files.
​
Control who invokes a skill
By default, both you and Claude can invoke any skill. You can type
/skill-name
to invoke it directly, and Claude can load it automatically when relevant to your conversation. Two frontmatter fields let you restrict this:
disable-model-invocation: true
: Only you can invoke the skill. Use this for workflows with side effects or that you want to control timing, like
/commit
,
/deploy
, or
/send-slack-message
. You don’t want Claude deciding to deploy because your code looks ready.
user-invocable: false
: Only Claude can invoke the skill. Use this for background knowledge that isn’t actionable as a command. A
legacy-system-context
skill explains how an old system works. Claude should know this when relevant, but
/legacy-system-context
isn’t a meaningful action for users to take.
This example creates a deploy skill that only you can trigger. The
disable-model-invocation: true
field prevents Claude from running it automatically:
---
name
:
deploy
description
:
Deploy the application to production
disable-model-invocation
:
true
---
Deploy $ARGUMENTS to production
:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded
Here’s how the two fields affect invocation and context loading:
Frontmatter
You can invoke
Claude can invoke
When loaded into context
(default)
Yes
Yes
Description always in context, full skill loads when invoked
disable-model-invocation: true
Yes
No
Description not in context, full skill loads when you invoke
user-invocable: false
No
Yes
Description always in context, full skill loads when invoked
In a regular session, skill descriptions are loaded into context so Claude knows what’s available, but full skill content only loads when invoked.
Subagents with preloaded skills
work differently: the full skill content is injected at startup.
​
Skill content lifecycle
When you or Claude invoke a skill, the rendered
SKILL.md
content enters the conversation as a single message and stays there for the rest of the session. Claude Code does not re-read the skill file on later turns, so write guidance that should apply throughout a task as standing instructions rather than one-time steps.
Auto-compaction
carries invoked skills forward within a token budget. When the conversation is summarized to free context, Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session.
If a skill seems to stop influencing behavior after the first response, the content is usually still present and the model is choosing other tools or approaches. Strengthen the skill’s
description
and instructions so the model keeps preferring it, or use
hooks
to enforce behavior deterministically. If the skill is large or you invoked several others after it, re-invoke it after compaction to restore the full content.
​
Pre-approve tools for a skill
The
allowed-tools
field grants permission for the listed tools while the skill is active, so Claude can use them without prompting you for approval. It does not restrict which tools are available: every tool remains callable, and your
permission settings
still govern tools that are not listed.
For skills checked into a project’s
.claude/skills/
directory,
allowed-tools
takes effect after you accept the workspace trust dialog for that folder, the same as permission rules in
.claude/settings.json
. Review project skills before trusting a repository, since a skill can grant itself broad tool access.
This skill lets Claude run git commands without per-use approval whenever you invoke it:
---
name
:
commit
description
:
Stage and commit the current changes
disable-model-invocation
:
true
allowed-tools
:
Bash(git add *) Bash(git commit *) Bash(git status *)
---
To block a skill from using certain tools, add deny rules in your
permission settings
instead.
​
Pass arguments to skills
Both you and Claude can pass arguments when invoking a skill. Arguments are available via the
$ARGUMENTS
placeholder.
This skill fixes a GitHub issue by number. The
$ARGUMENTS
placeholder gets replaced with whatever follows the skill name:
---
name
:
fix-issue
description
:
Fix a GitHub issue
disable-model-invocation
:
true
---
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit
When you run
/fix-issue 123
, Claude receives “Fix GitHub issue 123 following our coding standards…”
If you invoke a skill with arguments but the skill doesn’t include
$ARGUMENTS
, Claude Code appends
ARGUMENTS: <your input>
to the end of the skill content so Claude still sees what you typed.
To access individual arguments by position, use
$ARGUMENTS[N]
or the shorter
$N
:
---
name
:
migrate-component
description
:
Migrate a component from one framework to another
---
Migrate the $ARGUMENTS[0] component from $ARGUMENTS[1] to $ARGUMENTS[2].
Preserve all existing behavior and tests.
Running
/migrate-component SearchBar React Vue
replaces
$ARGUMENTS[0]
with
SearchBar
,
$ARGUMENTS[1]
with
React
, and
$ARGUMENTS[2]
with
Vue
. The same skill using the
$N
shorthand:
---
name
:
migrate-component
description
:
Migrate a component from one framework to another
---
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.
​
Advanced patterns
​
Inject dynamic context
The
!`<command>`
syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself.
This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The
!`gh pr diff`
and other commands run first, and their output gets inserted into the prompt:
---
name
:
pr-summary
description
:
Summarize changes in a pull request
context
:
fork
agent
:
Explore
allowed-tools
:
Bash(gh *)
---
## Pull request context
-
PR diff
:
!`gh
pr diff`
-
PR comments
:
!`gh
pr view --comments`
-
Changed files
:
!`gh
pr diff --name-only`
## Your task
Summarize this pull request...
When this skill runs:
Each
!`<command>`
executes immediately (before Claude sees anything)
The output replaces the placeholder in the skill content
Claude receives the fully-rendered prompt with actual PR data
This is preprocessing, not something Claude executes. Claude only sees the final result.
Substitution runs once over the original file. Command output is inserted as plain text and is not re-scanned for further
!`<command>`
placeholders, so a command cannot emit a placeholder for a later pass to expand.
For multi-line commands, use a fenced code block opened with
```!
instead of the inline form:
## Environment
```!
node --version
npm --version
git status --short
```
To disable this behavior for skills and custom commands from user, project, plugin, or
additional-directory
sources, set
"disableSkillShellExecution": true
in
settings
. Each command is replaced with
[shell command execution disabled by policy]
instead of being run. Bundled and managed skills are not affected. This setting is most useful in
managed settings
, where users cannot override it.
To request deeper reasoning when a skill runs, include
ultrathink
anywhere in the skill content. See
Use ultrathink for one-off deep reasoning
.
​
Run skills in a subagent
Add
context: fork
to your frontmatter when you want a skill to run in isolation. The skill content becomes the prompt that drives the subagent. It won’t have access to your conversation history.
context: fork
only makes sense for skills with explicit instructions. If your skill contains guidelines like “use these API conventions” without a task, the subagent receives the guidelines but no actionable prompt, and returns without meaningful output.
Skills and
subagents
work together in two directions:
Approach
System prompt
Task
Also loads
Skill with
context: fork
From agent type (
Explore
,
Plan
, etc.)
SKILL.md content
CLAUDE.md
Subagent with
skills
field
Subagent’s markdown body
Claude’s delegation message
Preloaded skills + CLAUDE.md
With
context: fork
, you write the task in your skill and pick an agent type to execute it. For the inverse (defining a custom subagent that uses skills as reference material), see
Subagents
.
​
Example: Research skill using Explore agent
This skill runs research in a forked Explore agent. The skill content becomes the task, and the agent provides read-only tools optimized for codebase exploration:
---
name
:
deep-research
description
:
Research a topic thoroughly
context
:
fork
agent
:
Explore
---
Research $ARGUMENTS thoroughly
:
1. Find relevant files using Glob and Grep
2. Read and analyze the code
3. Summarize findings with specific file references
When this skill runs:
A new isolated context is created
The subagent receives the skill content as its prompt (“Research $ARGUMENTS thoroughly…”)
The
agent
field determines the execution environment (model, tools, and permissions)
Results are summarized and returned to your main conversation
The
agent
field specifies which subagent configuration to use. Options include built-in agents (
Explore
,
Plan
,
general-purpose
) or any custom subagent from
.claude/agents/
. If omitted, uses
general-purpose
.
​
Restrict Claude’s skill access
By default, Claude can invoke any skill that doesn’t have
disable-model-invocation: true
set. Skills that define
allowed-tools
grant Claude access to those tools without per-use approval when the skill is active. Your
permission settings
still govern baseline approval behavior for all other tools. A few built-in commands are also available through the Skill tool, including
/init
,
/review
, and
/security-review
. Other built-in commands such as
/compact
are not.
Three ways to control which skills Claude can invoke:
Disable all skills
by denying the Skill tool in
/permissions
:
# Add to deny rules:
Skill
Allow or deny specific skills
using
permission rules
:
# Allow only specific skills
Skill(commit)
Skill(review-pr *)
# Deny specific skills
Skill(deploy *)
Permission syntax:
Skill(name)
for exact match,
Skill(name *)
for prefix match with any arguments.
Hide individual skills
by adding
disable-model-invocation: true
to their frontmatter. This removes the skill from Claude’s context entirely.
The
user-invocable
field only controls menu visibility, not Skill tool access. Use
disable-model-invocation: true
to block programmatic invocation.
​
Override skill visibility from settings
The
skillOverrides
setting controls skill visibility from your
settings
instead of the skill’s own frontmatter. Use it for skills whose SKILL.md you don’t want to edit, such as ones checked into a shared project repo or provided by an MCP server. The
/skills
menu writes it for you: highlight a skill and press
Space
to cycle states, then
Enter
to save to
.claude/settings.local.json
.
Each key is a skill name and each value is one of four states:
Value
Listed to Claude
In
/
menu
"on"
Name and description
Yes
"name-only"
Name only
Yes
"user-invocable-only"
Hidden
Yes
"off"
Hidden
Hidden
A skill that is absent from
skillOverrides
is treated as
"on"
. The example below collapses one skill to its name and turns another off entirely:
{
"skillOverrides"
: {
"legacy-context"
:
"name-only"
,
"deploy"
:
"off"
}
}
Plugin skills are not affected by
skillOverrides
. Manage those through
/plugin
instead.
​
Share skills
Skills can be distributed at different scopes depending on your audience:
Project skills
: Commit
.claude/skills/
to version control
Plugins
: Create a
skills/
directory in your
plugin
Managed
: Deploy organization-wide through
managed settings
​
Generate visual output
Skills can bundle and run scripts in any language, giving Claude capabilities beyond what’s possible in a single prompt. One powerful pattern is generating visual output: interactive HTML files that open in your browser for exploring data, debugging, or creating reports.
This example creates a codebase explorer: an interactive tree view where you can expand and collapse directories, see file sizes at a glance, and identify file types by color.
Create the Skill directory:
mkdir
-p
~/.claude/skills/codebase-visualizer/scripts
Save this to
~/.claude/skills/codebase-visualizer/SKILL.md
. The description tells Claude when to activate this Skill, and the instructions tell Claude to run the bundled script. The script path uses
${CLAUDE_SKILL_DIR}
so it resolves correctly whether the skill is installed at the personal, project, or plugin level:
---
name
:
codebase-visualizer
description
:
Generate an interactive collapsible tree visualization of your codebase. Use when exploring a new repo, understanding project structure, or identifying large files.
allowed-tools
:
Bash(python3 *)
---
# Codebase Visualizer
Generate an interactive HTML tree view that shows your project's file structure with collapsible directories.
## Usage
Run the visualization script from your project root
:
```
bash
python3 ${CLAUDE_SKILL_DIR}/scripts/visualize.py .
```
This creates `codebase-map.html` in the current directory and opens it in your default browser.
## What the visualization shows
-
*
*Collapsible
directories**
:
Click folders to expand/collapse
-
*
*File
sizes**
:
Displayed next to each file
-
*
*Colors**:
Different colors for different file types
-
*
*Directory
totals**
:
Shows aggregate size of each folder
Save this to
~/.claude/skills/codebase-visualizer/scripts/visualize.py
. This script scans a directory tree and generates a self-contained HTML file with:
A
summary sidebar
showing file count, directory count, total size, and number of file types
A
bar chart
breaking down the codebase by file type (top 8 by size)
A
collapsible tree
where you can expand and collapse directories, with color-coded file type indicators
The script requires Python 3 but uses only built-in libraries, so there are no packages to install:
#!/usr/bin/env python3
"""Generate an interactive collapsible tree visualization of a codebase."""
import
json
import
sys
import
webbrowser
from
html
import
escape
from
pathlib
import
Path
from
collections
import
Counter
IGNORE
=
{
'.git'
,
'node_modules'
,
'__pycache__'
,
'.venv'
,
'venv'
,
'dist'
,
'build'
}
def
scan
(
path
: Path,
stats
:
dict
) ->
dict
:
result
=
{
"name"
: path.name,
"children"
: [],
"size"
:
0
}
try
:
for
item
in
sorted
(path.iterdir()):
if
item.name
in
IGNORE
or
item.name.startswith(
'.'
):
continue
if
item.is_file():
size
=
item.stat().st_size
ext
=
item.suffix.lower()
or
'(no ext)'
result[
"children"
].append({
"name"
: item.name,
"size"
: size,
"ext"
: ext})
result[
"size"
]
+=
size
stats[
"files"
]
+=
1
stats[
"extensions"
][ext]
+=
1
stats[
"ext_sizes"
][ext]
+=
size
elif
item.is_dir():
stats[
"dirs"
]
+=
1
child
=
scan(item, stats)
if
child[
"children"
]:
result[
"children"
].append(child)
result[
"size"
]
+=
child[
"size"
]
except
PermissionError
:
pass
return
result
def
generate_html
(
data
:
dict
,
stats
:
dict
,
output
: Path) ->
None
:
ext_sizes
=
stats[
"ext_sizes"
]
total_size
=
sum
(ext_sizes.values())
or
1
sorted_exts
=
sorted
(ext_sizes.items(),
key
=
lambda
x
:
-
x[
1
])[:
8
]
colors
=
{
'.js'
:
'#f7df1e'
,
'.ts'
:
'#3178c6'
,
'.py'
:
'#3776ab'
,
'.go'
:
'#00add8'
,
'.rs'
:
'#dea584'
,
'.rb'
:
'#cc342d'
,
'.css'
:
'#264de4'
,
'.html'
:
'#e34c26'
,
'.json'
:
'#6b7280'
,
'.md'
:
'#083fa1'
,
'.yaml'
:
'#cb171e'
,
'.yml'
:
'#cb171e'
,
'.mdx'
:
'#083fa1'
,
'.tsx'
:
'#3178c6'
,
'.jsx'
:
'#61dafb'
,
'.sh'
:
'#4eaa25'
,
}
lang_bars
=
""
.join(
f
'<div class="bar-row"><span class="bar-label">
{
ext
}
</span>'
f
'<div class="bar" style="width:
{
(size
/
total_size)
*
100
}
%;background:
{
colors.get(ext,
"#6b7280"
)
}
"></div>'
f
'<span class="bar-pct">
{
(size
/
total_size)
*
100
:.1f}
%</span></div>'
for
ext, size
in
sorted_exts
)
def
fmt
(
b
):
if
b
<
1024
:
return
f
"
{
b
}
B"
if
b
<
1048576
:
return
f
"
{
b
/
1024
:.1f}
KB"
return
f
"
{
b
/
1048576
:.1f}
MB"
html
=
f
'''<!DOCTYPE html>
<html><head>
<meta charset="utf-8"><title>Codebase Explorer</title>
<style>
body
{{
font: 14px/1.5 system-ui, sans-serif; margin: 0; background: #1a1a2e; color: #eee;
}}
.container
{{
display: flex; height: 100vh;
}}
.sidebar
{{
width: 280px; background: #252542; padding: 20px; border-right: 1px solid #3d3d5c; overflow-y: auto; flex-shrink: 0;
}}
.main
{{
flex: 1; padding: 20px; overflow-y: auto;
}}
h1
{{
margin: 0 0 10px 0; font-size: 18px;
}}
h2
{{
margin: 20px 0 10px 0; font-size: 14px; color: #888; text-transform: uppercase;
}}
.stat
{{
display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #3d3d5c;
}}
.stat-value
{{
font-weight: bold;
}}
.bar-row
{{
display: flex; align-items: center; margin: 6px 0;
}}
.bar-label
{{
width: 55px; font-size: 12px; color: #aaa;
}}
.bar
{{
height: 18px; border-radius: 3px;
}}
.bar-pct
{{
margin-left: 8px; font-size: 12px; color: #666;
}}
.tree
{{
list-style: none; padding-left: 20px;
}}
details
{{
cursor: pointer;
}}
summary
{{
padding: 4px 8px; border-radius: 4px;
}}
summary:hover
{{
background: #2d2d44;
}}
.folder
{{
color: #ffd700;
}}
.file
{{
display: flex; align-items: center; padding: 4px 8px; border-radius: 4px;
}}
.file:hover
{{
background: #2d2d44;
}}
.size
{{
color: #888; margin-left: auto; font-size: 12px;
}}
.dot
{{
width: 8px; height: 8px; border-radius: 50%; margin-right: 8px;
}}
</style>
</head><body>
<div class="container">
<div class="sidebar">
<h1>📊 Summary</h1>
<div class="stat"><span>Files</span><span class="stat-value">
{
stats[
"files"
]
:,}
</span></div>
<div class="stat"><span>Directories</span><span class="stat-value">
{
stats[
"dirs"
]
:,}
</span></div>
<div class="stat"><span>Total size</span><span class="stat-value">
{
fmt(data[
"size"
])
}
</span></div>
<div class="stat"><span>File types</span><span class="stat-value">
{
len
(stats[
"extensions"
])
}
</span></div>
<h2>By file type</h2>
{
lang_bars
}
</div>
<div class="main">
<h1>📁
{
escape(data[
"name"
])
}
</h1>
<ul class="tree" id="root"></ul>
</div>
</div>
<script>
const data =
{
json.dumps(data)
}
;
const colors =
{
json.dumps(colors)
}
;
function fmt(b)
{{
if (b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; return (b/1048576).toFixed(1) + ' MB';
}}
function esc(s)
{{
return s.replace(/[&<>"']/g, c => (
{{
"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"
}}
[c]));
}}
function render(node, parent)
{{
if (node.children)
{{
const det = document.createElement('details');
det.open = parent === document.getElementById('root');
det.innerHTML = `<summary><span class="folder">📁 $
{{
esc(node.name)
}}
</span><span class="size">$
{{
fmt(node.size)
}}
</span></summary>`;
const ul = document.createElement('ul'); ul.className = 'tree';
node.children.sort((a,b) => (b.children?1:0)-(a.children?1:0) || a.name.localeCompare(b.name));
node.children.forEach(c => render(c, ul));
det.appendChild(ul);
const li = document.createElement('li'); li.appendChild(det); parent.appendChild(li);
}}
else
{{
const li = document.createElement('li'); li.className = 'file';
li.innerHTML = `<span class="dot" style="background:$
{{
colors[node.ext]||'#6b7280'
}}
"></span>$
{{
esc(node.name)
}}
<span class="size">$
{{
fmt(node.size)
}}
</span>`;
parent.appendChild(li);
}}
}}
data.children.forEach(c => render(c, document.getElementById('root')));
</script>
</body></html>'''
output.write_text(html)
if
__name__
==
'__main__'
:
target
=
Path(sys.argv[
1
]
if
len
(sys.argv)
>
1
else
'.'
).resolve()
stats
=
{
"files"
:
0
,
"dirs"
:
0
,
"extensions"
: Counter(),
"ext_sizes"
: Counter()}
data
=
scan(target, stats)
out
=
Path(
'codebase-map.html'
)
generate_html(data, stats, out)
print
(
f
'Generated
{
out.absolute()
}
'
)
webbrowser.open(
f
'file://
{
out.absolute()
}
'
)
See all 133 lines
To test, open Claude Code in any project and ask “Visualize this codebase.” Claude runs the script, generates
codebase-map.html
, and opens it in your browser.
This pattern works for any visual output: dependency graphs, test coverage reports, API documentation, or database schema visualizations. The bundled script does the work while Claude handles orchestration.
​
Troubleshooting
​
Skill not triggering
If Claude doesn’t use your skill when expected:
Check the description includes keywords users would naturally say
Verify the skill appears in
What skills are available?
Try rephrasing your request to match the description more closely
Invoke it directly with
/skill-name
if the skill is user-invocable
​
Skill triggers too often
If Claude uses your skill when you don’t want it:
Make the description more specific
Add
disable-model-invocation: true
if you only want manual invocation
​
Skill descriptions are cut short
Skill descriptions are loaded into context so Claude knows what’s available. All skill names are always included, but if you have many skills, descriptions are shortened to fit the character budget, which can strip the keywords Claude needs to match your request. The budget scales at 1% of the model’s context window. When it overflows, descriptions for the skills you invoke least are dropped first, so the skills you actually use keep their full text. Run
/doctor
to see whether the budget is overflowing and which skills are affected.
To raise the budget, set the
skillListingBudgetFraction
setting (e.g.
0.02
= 2%) or the
SLASH_COMMAND_TOOL_CHAR_BUDGET
environment variable to a fixed character count. To free budget for other skills, set low-priority entries to
"name-only"
in
skillOverrides
so they list without a description. You can also trim the
description
and
when_to_use
text at the source: put the key use case first, since each entry’s combined text is capped at 1,536 characters regardless of budget. The cap is configurable with
maxSkillDescriptionChars
.
​
Related resources
Debug your configuration
: diagnose why a skill isn’t appearing or triggering
Subagents
: delegate tasks to specialized agents
Plugins
: package and distribute skills with other extensions
Hooks
: automate workflows around tool events
Memory
: manage CLAUDE.md files for persistent context
Commands
: reference for built-in commands and bundled skills
Permissions
: control tool and skill access
Was this page helpful?
Yes
No
Create plugins
Automate with hooks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/skills" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Extend Claude with skills
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Tools and plugins
Extend Claude with skills
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Skills extend what Claude can do. Create a
SKILL.md
file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with
/skill-name
.
Create a skill when you keep pasting the same instructions, checklist, or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact. Unlike CLAUDE.md content, a skill’s body loads only when it’s used, so long reference material costs almost nothing until you need it.
For built-in commands like
/help
and
/compact
, and bundled skills like
/debug
and
/simplify
, see the
commands reference
.
Custom commands have been merged into skills.
A file at
.claude/commands/deploy.md
and a skill at
.claude/skills/deploy/SKILL.md
both create
/deploy
and work the same way. Your existing
.claude/commands/
files keep working. Skills add optional features: a directory for supporting files, frontmatter to
control whether you or Claude invokes them
, and the ability for Claude to load them automatically when relevant.
Claude Code skills follow the
Agent Skills
open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like
invocation control
,
subagent execution
, and
dynamic context injection
.
​
Bundled skills
Claude Code includes a set of bundled skills that are available in every session, including
/simplify
,
/batch
,
/debug
,
/loop
, and
/claude-api
. Unlike most built-in commands, which execute fixed logic directly, bundled skills are prompt-based: they give Claude detailed instructions and let it orchestrate the work using its tools. You invoke them the same way as any other skill, by typing
/
followed by the skill name.
Bundled skills are listed alongside built-in commands in the
commands reference
, marked
Skill
in the Purpose column.
​
Getting started
​
Create your first skill
This example creates a skill that summarizes the uncommitted changes in your git repository and flags anything risky. It pulls the live diff into the prompt before Claude reads it, so the response is grounded in your actual working tree rather than what Claude can guess from open files. Claude loads the skill automatically when you ask about your changes, or you can invoke it directly with
/summarize-changes
.
1
Create the skill directory
Create a directory for the skill in your personal skills folder. Personal skills are available across all your projects.
mkdir
-p
~/.claude/skills/summarize-changes
2
Write SKILL.md
Every skill needs a
SKILL.md
file with two parts: YAML frontmatter between
---
markers that tells Claude when to use the skill, and markdown content with the instructions Claude follows when the skill runs. The directory name becomes the command you type, and the
description
helps Claude decide when to load the skill automatically.
Save this to
~/.claude/skills/summarize-changes/SKILL.md
:
---
description
:
Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---
## Current changes
!`git
diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes.
The
!`git diff HEAD`
line uses
dynamic context injection
: Claude Code runs the command and replaces the line with its output before Claude sees the skill content, so the instructions arrive with the current diff already inlined.
3
Test the skill
Open a git project, make a small edit to any file, and start Claude Code by running
claude
. You can test the skill two ways.
Let Claude invoke it automatically
by asking something that matches the description:
What did I change?
Or invoke it directly
with the skill name:
/summarize-changes
Either way, Claude should respond with a short summary of your edit and a list of risks.
​
Where skills live
Where you store a skill determines who can use it:
Location
Path
Applies to
Enterprise
See
managed settings
All users in your organization
Personal
~/.claude/skills/<skill-name>/SKILL.md
All your projects
Project
.claude/skills/<skill-name>/SKILL.md
This project only
Plugin
<plugin>/skills/<skill-name>/SKILL.md
Where plugin is enabled
When skills share the same name across levels, enterprise overrides personal, and personal overrides project. Plugin skills use a
plugin-name:skill-name
namespace, so they cannot conflict with other levels. If you have files in
.claude/commands/
, those work the same way, but if a skill and a command share the same name, the skill takes precedence.
​
Live change detection
Claude Code watches skill directories for file changes. Adding, editing, or removing a skill under
~/.claude/skills/
, the project
.claude/skills/
, or a
.claude/skills/
inside an
--add-dir
directory takes effect within the current session without restarting. Creating a top-level skills directory that did not exist when the session started requires restarting Claude Code so the new directory can be watched.
​
Automatic discovery from parent and nested directories
Project skills load from
.claude/skills/
in your starting directory and in every parent directory up to the repository root, so starting Claude in a subdirectory still picks up skills defined at the root. When you work with files in subdirectories below your starting directory, Claude Code also discovers skills from nested
.claude/skills/
directories on demand. For example, if you’re editing a file in
packages/frontend/
, Claude Code also looks for skills in
packages/frontend/.claude/skills/
. This supports monorepo setups where packages have their own skills.
Each skill is a directory with
SKILL.md
as the entrypoint:
my-skill/
├── SKILL.md           # Main instructions (required)
├── template.md        # Template for Claude to fill in
├── examples/
│   └── sample.md      # Example output showing expected format
└── scripts/
└── validate.sh    # Script Claude can execute
The
SKILL.md
contains the main instructions and is required. Other files are optional and let you build more powerful skills: templates for Claude to fill in, example outputs showing the expected format, scripts Claude can execute, or detailed reference documentation. Reference these files from your
SKILL.md
so Claude knows what they contain and when to load them. See
Add supporting files
for more details.
Files in
.claude/commands/
still work and support the same
frontmatter
. Skills are recommended since they support additional features like supporting files.
​
Skills from additional directories
The
--add-dir
flag
grants file access
rather than configuration discovery, but skills are an exception:
.claude/skills/
within an added directory is loaded automatically. See
Live change detection
for how edits are picked up during a session.
Other
.claude/
configuration such as subagents, commands, and output styles is not loaded from additional directories. See the
exceptions table
for the complete list of what is and isn’t loaded, and the recommended ways to share configuration across projects.
CLAUDE.md files from
--add-dir
directories are not loaded by default. To load them, set
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1
. See
Load from additional directories
.
​
Configure skills
Skills are configured through YAML frontmatter at the top of
SKILL.md
and the markdown content that follows.
​
Types of skill content
Skill files can contain any instructions, but thinking about how you want to invoke them helps guide what to include:
Reference content
adds knowledge Claude applies to your current work. Conventions, patterns, style guides, domain knowledge. This content runs inline so Claude can use it alongside your conversation context.
---
name
:
api-conventions
description
:
API design patterns for this codebase
---
When writing API endpoints
:
-
Use RESTful naming conventions
-
Return consistent error formats
-
Include request validation
Task content
gives Claude step-by-step instructions for a specific action, like deployments, commits, or code generation. These are often actions you want to invoke directly with
/skill-name
rather than letting Claude decide when to run them. Add
disable-model-invocation: true
to prevent Claude from triggering it automatically.
---
name
:
deploy
description
:
Deploy the application to production
context
:
fork
disable-model-invocation
:
true
---
Deploy the application
:
1. Run the test suite
2. Build the application
3. Push to the deployment target
Your
SKILL.md
can contain anything, but thinking through how you want the skill invoked (by you, by Claude, or both) and where you want it to run (inline or in a subagent) helps guide what to include. For complex skills, you can also
add supporting files
to keep the main skill focused.
Keep the body itself concise. Once a skill loads, its content
stays in context across turns
, so every line is a recurring token cost. State what to do rather than narrating how or why, and apply the same conciseness test you would for
CLAUDE.md content
.
​
Frontmatter reference
Beyond the markdown content, you can configure skill behavior using YAML frontmatter fields between
---
markers at the top of your
SKILL.md
file:
---
name
:
my-skill
description
:
What this skill does
disable-model-invocation
:
true
allowed-tools
:
Read Grep
---
Your skill instructions here...
All fields are optional. Only
description
is recommended so Claude knows when to use the skill.
Field
Required
Description
name
No
Display name for the skill. If omitted, uses the directory name. Lowercase letters, numbers, and hyphens only (max 64 characters).
description
Recommended
What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. Put the key use case first: the combined
description
and
when_to_use
text is truncated at 1,536 characters in the skill listing to reduce context usage.
when_to_use
No
Additional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to
description
in the skill listing and counts toward the 1,536-character cap.
argument-hint
No
Hint shown during autocomplete to indicate expected arguments. Example:
[issue-number]
or
[filename] [format]
.
arguments
No
Named positional arguments for
$name
substitution
in the skill content. Accepts a space-separated string or a YAML list. Names map to argument positions in order.
disable-model-invocation
No
Set to
true
to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with
/name
. Also prevents the skill from being
preloaded into subagents
. Default:
false
.
user-invocable
No
Set to
false
to hide from the
/
menu. Use for background knowledge users shouldn’t invoke directly. Default:
true
.
allowed-tools
No
Tools Claude can use without asking permission when this skill is active. Accepts a space-separated string or a YAML list.
model
No
Model to use when this skill is active. The override applies for the rest of the current turn and is not saved to settings; the session model resumes on your next prompt. Accepts the same values as
/model
, or
inherit
to keep the active model.
effort
No
Effort level
when this skill is active. Overrides the session effort level. Default: inherits from session. Options:
low
,
medium
,
high
,
xhigh
,
max
; available levels depend on the model.
context
No
Set to
fork
to run in a forked subagent context.
agent
No
Which subagent type to use when
context: fork
is set.
hooks
No
Hooks scoped to this skill’s lifecycle. See
Hooks in skills and agents
for configuration format.
paths
No
Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as
path-specific rules
.
shell
No
Shell to use for
!`command`
and
```!
blocks in this skill. Accepts
bash
(default) or
powershell
. Setting
powershell
runs inline shell commands via PowerShell on Windows. Requires
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
.
​
Available string substitutions
Skills support string substitution for dynamic values in the skill content:
Variable
Description
$ARGUMENTS
All arguments passed when invoking the skill. If
$ARGUMENTS
is not present in the content, arguments are appended as
ARGUMENTS: <value>
.
$ARGUMENTS[N]
Access a specific argument by 0-based index, such as
$ARGUMENTS[0]
for the first argument.
$N
Shorthand for
$ARGUMENTS[N]
, such as
$0
for the first argument or
$1
for the second.
$name
Named argument declared in the
arguments
frontmatter list. Names map to positions in order, so with
arguments: [issue, branch]
the placeholder
$issue
expands to the first argument and
$branch
to the second.
${CLAUDE_SESSION_ID}
The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions.
${CLAUDE_EFFORT}
The current effort level:
low
,
medium
,
high
,
xhigh
, or
max
. Use this to adapt skill instructions to the active effort setting.
${CLAUDE_SKILL_DIR}
The directory containing the skill’s
SKILL.md
file. For plugin skills, this is the skill’s subdirectory within the plugin, not the plugin root. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory.
Indexed arguments use shell-style quoting, so wrap multi-word values in quotes to pass them as a single argument. For example,
/my-skill "hello world" second
makes
$0
expand to
hello world
and
$1
to
second
. The
$ARGUMENTS
placeholder always expands to the full argument string as typed.
Example using substitutions:
---
name
:
session-logger
description
:
Log activity for this session
---
Log the following to logs/${CLAUDE_SESSION_ID}.log
:
$ARGUMENTS
​
Add supporting files
Skills can include multiple files in their directory. This keeps
SKILL.md
focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don’t need to load into context every time the skill runs.
my-skill/
├── SKILL.md (required - overview and navigation)
├── reference.md (detailed API docs - loaded when needed)
├── examples.md (usage examples - loaded when needed)
└── scripts/
└── helper.py (utility script - executed, not loaded)
Reference supporting files from
SKILL.md
so Claude knows what each file contains and when to load it:
## Additional resources
-
For complete API details, see [
reference.md
](
reference.md
)
-
For usage examples, see [
examples.md
](
examples.md
)
Keep
SKILL.md
under 500 lines. Move detailed reference material to separate files.
​
Control who invokes a skill
By default, both you and Claude can invoke any skill. You can type
/skill-name
to invoke it directly, and Claude can load it automatically when relevant to your conversation. Two frontmatter fields let you restrict this:
disable-model-invocation: true
: Only you can invoke the skill. Use this for workflows with side effects or that you want to control timing, like
/commit
,
/deploy
, or
/send-slack-message
. You don’t want Claude deciding to deploy because your code looks ready.
user-invocable: false
: Only Claude can invoke the skill. Use this for background knowledge that isn’t actionable as a command. A
legacy-system-context
skill explains how an old system works. Claude should know this when relevant, but
/legacy-system-context
isn’t a meaningful action for users to take.
This example creates a deploy skill that only you can trigger. The
disable-model-invocation: true
field prevents Claude from running it automatically:
---
name
:
deploy
description
:
Deploy the application to production
disable-model-invocation
:
true
---
Deploy $ARGUMENTS to production
:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded
Here’s how the two fields affect invocation and context loading:
Frontmatter
You can invoke
Claude can invoke
When loaded into context
(default)
Yes
Yes
Description always in context, full skill loads when invoked
disable-model-invocation: true
Yes
No
Description not in context, full skill loads when you invoke
user-invocable: false
No
Yes
Description always in context, full skill loads when invoked
In a regular session, skill descriptions are loaded into context so Claude knows what’s available, but full skill content only loads when invoked.
Subagents with preloaded skills
work differently: the full skill content is injected at startup.
​
Skill content lifecycle
When you or Claude invoke a skill, the rendered
SKILL.md
content enters the conversation as a single message and stays there for the rest of the session. Claude Code does not re-read the skill file on later turns, so write guidance that should apply throughout a task as standing instructions rather than one-time steps.
Auto-compaction
carries invoked skills forward within a token budget. When the conversation is summarized to free context, Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session.
If a skill seems to stop influencing behavior after the first response, the content is usually still present and the model is choosing other tools or approaches. Strengthen the skill’s
description
and instructions so the model keeps preferring it, or use
hooks
to enforce behavior deterministically. If the skill is large or you invoked several others after it, re-invoke it after compaction to restore the full content.
​
Pre-approve tools for a skill
The
allowed-tools
field grants permission for the listed tools while the skill is active, so Claude can use them without prompting you for approval. It does not restrict which tools are available: every tool remains callable, and your
permission settings
still govern tools that are not listed.
For skills checked into a project’s
.claude/skills/
directory,
allowed-tools
takes effect after you accept the workspace trust dialog for that folder, the same as permission rules in
.claude/settings.json
. Review project skills before trusting a repository, since a skill can grant itself broad tool access.
This skill lets Claude run git commands without per-use approval whenever you invoke it:
---
name
:
commit
description
:
Stage and commit the current changes
disable-model-invocation
:
true
allowed-tools
:
Bash(git add *) Bash(git commit *) Bash(git status *)
---
To block a skill from using certain tools, add deny rules in your
permission settings
instead.
​
Pass arguments to skills
Both you and Claude can pass arguments when invoking a skill. Arguments are available via the
$ARGUMENTS
placeholder.
This skill fixes a GitHub issue by number. The
$ARGUMENTS
placeholder gets replaced with whatever follows the skill name:
---
name
:
fix-issue
description
:
Fix a GitHub issue
disable-model-invocation
:
true
---
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit
When you run
/fix-issue 123
, Claude receives “Fix GitHub issue 123 following our coding standards…”
If you invoke a skill with arguments but the skill doesn’t include
$ARGUMENTS
, Claude Code appends
ARGUMENTS: <your input>
to the end of the skill content so Claude still sees what you typed.
To access individual arguments by position, use
$ARGUMENTS[N]
or the shorter
$N
:
---
name
:
migrate-component
description
:
Migrate a component from one framework to another
---
Migrate the $ARGUMENTS[0] component from $ARGUMENTS[1] to $ARGUMENTS[2].
Preserve all existing behavior and tests.
Running
/migrate-component SearchBar React Vue
replaces
$ARGUMENTS[0]
with
SearchBar
,
$ARGUMENTS[1]
with
React
, and
$ARGUMENTS[2]
with
Vue
. The same skill using the
$N
shorthand:
---
name
:
migrate-component
description
:
Migrate a component from one framework to another
---
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.
​
Advanced patterns
​
Inject dynamic context
The
!`<command>`
syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself.
This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The
!`gh pr diff`
and other commands run first, and their output gets inserted into the prompt:
---
name
:
pr-summary
description
:
Summarize changes in a pull request
context
:
fork
agent
:
Explore
allowed-tools
:
Bash(gh *)
---
## Pull request context
-
PR diff
:
!`gh
pr diff`
-
PR comments
:
!`gh
pr view --comments`
-
Changed files
:
!`gh
pr diff --name-only`
## Your task
Summarize this pull request...
When this skill runs:
Each
!`<command>`
executes immediately (before Claude sees anything)
The output replaces the placeholder in the skill content
Claude receives the fully-rendered prompt with actual PR data
This is preprocessing, not something Claude executes. Claude only sees the final result.
Substitution runs once over the original file. Command output is inserted as plain text and is not re-scanned for further
!`<command>`
placeholders, so a command cannot emit a placeholder for a later pass to expand.
For multi-line commands, use a fenced code block opened with
```!
instead of the inline form:
## Environment
```!
node --version
npm --version
git status --short
```
To disable this behavior for skills and custom commands from user, project, plugin, or
additional-directory
sources, set
"disableSkillShellExecution": true
in
settings
. Each command is replaced with
[shell command execution disabled by policy]
instead of being run. Bundled and managed skills are not affected. This setting is most useful in
managed settings
, where users cannot override it.
To request deeper reasoning when a skill runs, include
ultrathink
anywhere in the skill content. See
Use ultrathink for one-off deep reasoning
.
​
Run skills in a subagent
Add
context: fork
to your frontmatter when you want a skill to run in isolation. The skill content becomes the prompt that drives the subagent. It won’t have access to your conversation history.
context: fork
only makes sense for skills with explicit instructions. If your skill contains guidelines like “use these API conventions” without a task, the subagent receives the guidelines but no actionable prompt, and returns without meaningful output.
Skills and
subagents
work together in two directions:
Approach
System prompt
Task
Also loads
Skill with
context: fork
From agent type (
Explore
,
Plan
, etc.)
SKILL.md content
CLAUDE.md
Subagent with
skills
field
Subagent’s markdown body
Claude’s delegation message
Preloaded skills + CLAUDE.md
With
context: fork
, you write the task in your skill and pick an agent type to execute it. For the inverse (defining a custom subagent that uses skills as reference material), see
Subagents
.
​
Example: Research skill using Explore agent
This skill runs research in a forked Explore agent. The skill content becomes the task, and the agent provides read-only tools optimized for codebase exploration:
---
name
:
deep-research
description
:
Research a topic thoroughly
context
:
fork
agent
:
Explore
---
Research $ARGUMENTS thoroughly
:
1. Find relevant files using Glob and Grep
2. Read and analyze the code
3. Summarize findings with specific file references
When this skill runs:
A new isolated context is created
The subagent receives the skill content as its prompt (“Research $ARGUMENTS thoroughly…”)
The
agent
field determines the execution environment (model, tools, and permissions)
Results are summarized and returned to your main conversation
The
agent
field specifies which subagent configuration to use. Options include built-in agents (
Explore
,
Plan
,
general-purpose
) or any custom subagent from
.claude/agents/
. If omitted, uses
general-purpose
.
​
Restrict Claude’s skill access
By default, Claude can invoke any skill that doesn’t have
disable-model-invocation: true
set. Skills that define
allowed-tools
grant Claude access to those tools without per-use approval when the skill is active. Your
permission settings
still govern baseline approval behavior for all other tools. A few built-in commands are also available through the Skill tool, including
/init
,
/review
, and
/security-review
. Other built-in commands such as
/compact
are not.
Three ways to control which skills Claude can invoke:
Disable all skills
by denying the Skill tool in
/permissions
:
# Add to deny rules:
Skill
Allow or deny specific skills
using
permission rules
:
# Allow only specific skills
Skill(commit)
Skill(review-pr *)
# Deny specific skills
Skill(deploy *)
Permission syntax:
Skill(name)
for exact match,
Skill(name *)
for prefix match with any arguments.
Hide individual skills
by adding
disable-model-invocation: true
to their frontmatter. This removes the skill from Claude’s context entirely.
The
user-invocable
field only controls menu visibility, not Skill tool access. Use
disable-model-invocation: true
to block programmatic invocation.
​
Override skill visibility from settings
The
skillOverrides
setting controls skill visibility from your
settings
instead of the skill’s own frontmatter. Use it for skills whose SKILL.md you don’t want to edit, such as ones checked into a shared project repo or provided by an MCP server. The
/skills
menu writes it for you: highlight a skill and press
Space
to cycle states, then
Enter
to save to
.claude/settings.local.json
.
Each key is a skill name and each value is one of four states:
Value
Listed to Claude
In
/
menu
"on"
Name and description
Yes
"name-only"
Name only
Yes
"user-invocable-only"
Hidden
Yes
"off"
Hidden
Hidden
A skill that is absent from
skillOverrides
is treated as
"on"
. The example below collapses one skill to its name and turns another off entirely:
{
"skillOverrides"
: {
"legacy-context"
:
"name-only"
,
"deploy"
:
"off"
}
}
Plugin skills are not affected by
skillOverrides
. Manage those through
/plugin
instead.
​
Share skills
Skills can be distributed at different scopes depending on your audience:
Project skills
: Commit
.claude/skills/
to version control
Plugins
: Create a
skills/
directory in your
plugin
Managed
: Deploy organization-wide through
managed settings
​
Generate visual output
Skills can bundle and run scripts in any language, giving Claude capabilities beyond what’s possible in a single prompt. One powerful pattern is generating visual output: interactive HTML files that open in your browser for exploring data, debugging, or creating reports.
This example creates a codebase explorer: an interactive tree view where you can expand and collapse directories, see file sizes at a glance, and identify file types by color.
Create the Skill directory:
mkdir
-p
~/.claude/skills/codebase-visualizer/scripts
Save this to
~/.claude/skills/codebase-visualizer/SKILL.md
. The description tells Claude when to activate this Skill, and the instructions tell Claude to run the bundled script. The script path uses
${CLAUDE_SKILL_DIR}
so it resolves correctly whether the skill is installed at the personal, project, or plugin level:
---
name
:
codebase-visualizer
description
:
Generate an interactive collapsible tree visualization of your codebase. Use when exploring a new repo, understanding project structure, or identifying large files.
allowed-tools
:
Bash(python3 *)
---
# Codebase Visualizer
Generate an interactive HTML tree view that shows your project's file structure with collapsible directories.
## Usage
Run the visualization script from your project root
:
```
bash
python3 ${CLAUDE_SKILL_DIR}/scripts/visualize.py .
```
This creates `codebase-map.html` in the current directory and opens it in your default browser.
## What the visualization shows
-
*
*Collapsible
directories**
:
Click folders to expand/collapse
-
*
*File
sizes**
:
Displayed next to each file
-
*
*Colors**:
Different colors for different file types
-
*
*Directory
totals**
:
Shows aggregate size of each folder
Save this to
~/.claude/skills/codebase-visualizer/scripts/visualize.py
. This script scans a directory tree and generates a self-contained HTML file with:
A
summary sidebar
showing file count, directory count, total size, and number of file types
A
bar chart
breaking down the codebase by file type (top 8 by size)
A
collapsible tree
where you can expand and collapse directories, with color-coded file type indicators
The script requires Python 3 but uses only built-in libraries, so there are no packages to install:
#!/usr/bin/env python3
"""Generate an interactive collapsible tree visualization of a codebase."""
import
json
import
sys
import
webbrowser
from
html
import
escape
from
pathlib
import
Path
from
collections
import
Counter
IGNORE
=
{
'.git'
,
'node_modules'
,
'__pycache__'
,
'.venv'
,
'venv'
,
'dist'
,
'build'
}
def
scan
(
path
: Path,
stats
:
dict
) ->
dict
:
result
=
{
"name"
: path.name,
"children"
: [],
"size"
:
0
}
try
:
for
item
in
sorted
(path.iterdir()):
if
item.name
in
IGNORE
or
item.name.startswith(
'.'
):
continue
if
item.is_file():
size
=
item.stat().st_size
ext
=
item.suffix.lower()
or
'(no ext)'
result[
"children"
].append({
"name"
: item.name,
"size"
: size,
"ext"
: ext})
result[
"size"
]
+=
size
stats[
"files"
]
+=
1
stats[
"extensions"
][ext]
+=
1
stats[
"ext_sizes"
][ext]
+=
size
elif
item.is_dir():
stats[
"dirs"
]
+=
1
child
=
scan(item, stats)
if
child[
"children"
]:
result[
"children"
].append(child)
result[
"size"
]
+=
child[
"size"
]
except
PermissionError
:
pass
return
result
def
generate_html
(
data
:
dict
,
stats
:
dict
,
output
: Path) ->
None
:
ext_sizes
=
stats[
"ext_sizes"
]
total_size
=
sum
(ext_sizes.values())
or
1
sorted_exts
=
sorted
(ext_sizes.items(),
key
=
lambda
x
:
-
x[
1
])[:
8
]
colors
=
{
'.js'
:
'#f7df1e'
,
'.ts'
:
'#3178c6'
,
'.py'
:
'#3776ab'
,
'.go'
:
'#00add8'
,
'.rs'
:
'#dea584'
,
'.rb'
:
'#cc342d'
,
'.css'
:
'#264de4'
,
'.html'
:
'#e34c26'
,
'.json'
:
'#6b7280'
,
'.md'
:
'#083fa1'
,
'.yaml'
:
'#cb171e'
,
'.yml'
:
'#cb171e'
,
'.mdx'
:
'#083fa1'
,
'.tsx'
:
'#3178c6'
,
'.jsx'
:
'#61dafb'
,
'.sh'
:
'#4eaa25'
,
}
lang_bars
=
""
.join(
f
'<div class="bar-row"><span class="bar-label">
{
ext
}
</span>'
f
'<div class="bar" style="width:
{
(size
/
total_size)
*
100
}
%;background:
{
colors.get(ext,
"#6b7280"
)
}
"></div>'
f
'<span class="bar-pct">
{
(size
/
total_size)
*
100
:.1f}
%</span></div>'
for
ext, size
in
sorted_exts
)
def
fmt
(
b
):
if
b
<
1024
:
return
f
"
{
b
}
B"
if
b
<
1048576
:
return
f
"
{
b
/
1024
:.1f}
KB"
return
f
"
{
b
/
1048576
:.1f}
MB"
html
=
f
'''<!DOCTYPE html>
<html><head>
<meta charset="utf-8"><title>Codebase Explorer</title>
<style>
body
{{
font: 14px/1.5 system-ui, sans-serif; margin: 0; background: #1a1a2e; color: #eee;
}}
.container
{{
display: flex; height: 100vh;
}}
.sidebar
{{
width: 280px; background: #252542; padding: 20px; border-right: 1px solid #3d3d5c; overflow-y: auto; flex-shrink: 0;
}}
.main
{{
flex: 1; padding: 20px; overflow-y: auto;
}}
h1
{{
margin: 0 0 10px 0; font-size: 18px;
}}
h2
{{
margin: 20px 0 10px 0; font-size: 14px; color: #888; text-transform: uppercase;
}}
.stat
{{
display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #3d3d5c;
}}
.stat-value
{{
font-weight: bold;
}}
.bar-row
{{
display: flex; align-items: center; margin: 6px 0;
}}
.bar-label
{{
width: 55px; font-size: 12px; color: #aaa;
}}
.bar
{{
height: 18px; border-radius: 3px;
}}
.bar-pct
{{
margin-left: 8px; font-size: 12px; color: #666;
}}
.tree
{{
list-style: none; padding-left: 20px;
}}
details
{{
cursor: pointer;
}}
summary
{{
padding: 4px 8px; border-radius: 4px;
}}
summary:hover
{{
background: #2d2d44;
}}
.folder
{{
color: #ffd700;
}}
.file
{{
display: flex; align-items: center; padding: 4px 8px; border-radius: 4px;
}}
.file:hover
{{
background: #2d2d44;
}}
.size
{{
color: #888; margin-left: auto; font-size: 12px;
}}
.dot
{{
width: 8px; height: 8px; border-radius: 50%; margin-right: 8px;
}}
</style>
</head><body>
<div class="container">
<div class="sidebar">
<h1>📊 Summary</h1>
<div class="stat"><span>Files</span><span class="stat-value">
{
stats[
"files"
]
:,}
</span></div>
<div class="stat"><span>Directories</span><span class="stat-value">
{
stats[
"dirs"
]
:,}
</span></div>
<div class="stat"><span>Total size</span><span class="stat-value">
{
fmt(data[
"size"
])
}
</span></div>
<div class="stat"><span>File types</span><span class="stat-value">
{
len
(stats[
"extensions"
])
}
</span></div>
<h2>By file type</h2>
{
lang_bars
}
</div>
<div class="main">
<h1>📁
{
escape(data[
"name"
])
}
</h1>
<ul class="tree" id="root"></ul>
</div>
</div>
<script>
const data =
{
json.dumps(data)
}
;
const colors =
{
json.dumps(colors)
}
;
function fmt(b)
{{
if (b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; return (b/1048576).toFixed(1) + ' MB';
}}
function esc(s)
{{
return s.replace(/[&<>"']/g, c => (
{{
"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"
}}
[c]));
}}
function render(node, parent)
{{
if (node.children)
{{
const det = document.createElement('details');
det.open = parent === document.getElementById('root');
det.innerHTML = `<summary><span class="folder">📁 $
{{
esc(node.name)
}}
</span><span class="size">$
{{
fmt(node.size)
}}
</span></summary>`;
const ul = document.createElement('ul'); ul.className = 'tree';
node.children.sort((a,b) => (b.children?1:0)-(a.children?1:0) || a.name.localeCompare(b.name));
node.children.forEach(c => render(c, ul));
det.appendChild(ul);
const li = document.createElement('li'); li.appendChild(det); parent.appendChild(li);
}}
else
{{
const li = document.createElement('li'); li.className = 'file';
li.innerHTML = `<span class="dot" style="background:$
{{
colors[node.ext]||'#6b7280'
}}
"></span>$
{{
esc(node.name)
}}
<span class="size">$
{{
fmt(node.size)
}}
</span>`;
parent.appendChild(li);
}}
}}
data.children.forEach(c => render(c, document.getElementById('root')));
</script>
</body></html>'''
output.write_text(html)
if
__name__
==
'__main__'
:
target
=
Path(sys.argv[
1
]
if
len
(sys.argv)
>
1
else
'.'
).resolve()
stats
=
{
"files"
:
0
,
"dirs"
:
0
,
"extensions"
: Counter(),
"ext_sizes"
: Counter()}
data
=
scan(target, stats)
out
=
Path(
'codebase-map.html'
)
generate_html(data, stats, out)
print
(
f
'Generated
{
out.absolute()
}
'
)
webbrowser.open(
f
'file://
{
out.absolute()
}
'
)
See all 133 lines
To test, open Claude Code in any project and ask “Visualize this codebase.” Claude runs the script, generates
codebase-map.html
, and opens it in your browser.
This pattern works for any visual output: dependency graphs, test coverage reports, API documentation, or database schema visualizations. The bundled script does the work while Claude handles orchestration.
​
Troubleshooting
​
Skill not triggering
If Claude doesn’t use your skill when expected:
Check the description includes keywords users would naturally say
Verify the skill appears in
What skills are available?
Try rephrasing your request to match the description more closely
Invoke it directly with
/skill-name
if the skill is user-invocable
​
Skill triggers too often
If Claude uses your skill when you don’t want it:
Make the description more specific
Add
disable-model-invocation: true
if you only want manual invocation
​
Skill descriptions are cut short
Skill descriptions are loaded into context so Claude knows what’s available. All skill names are always included, but if you have many skills, descriptions are shortened to fit the character budget, which can strip the keywords Claude needs to match your request. The budget scales at 1% of the model’s context window. When it overflows, descriptions for the skills you invoke least are dropped first, so the skills you actually use keep their full text. Run
/doctor
to see whether the budget is overflowing and which skills are affected.
To raise the budget, set the
skillListingBudgetFraction
setting (e.g.
0.02
= 2%) or the
SLASH_COMMAND_TOOL_CHAR_BUDGET
environment variable to a fixed character count. To free budget for other skills, set low-priority entries to
"name-only"
in
skillOverrides
so they list without a description. You can also trim the
description
and
when_to_use
text at the source: put the key use case first, since each entry’s combined text is capped at 1,536 characters regardless of budget. The cap is configurable with
maxSkillDescriptionChars
.
​
Related resources
Debug your configuration
: diagnose why a skill isn’t appearing or triggering
Subagents
: delegate tasks to specialized agents
Plugins
: package and distribute skills with other extensions
Hooks
: automate workflows around tool events
Memory
: manage CLAUDE.md files for persistent context
Commands
: reference for built-in commands and bundled skills
Permissions
: control tool and skill access
Was this page helpful?
Yes
No
Create plugins
Automate with hooks
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/skills" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Agent SDK reference - TypeScript</title>
  <link>https://code.claude.com/docs/en/agent-sdk/typescript</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/typescript</guid>
  <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - TypeScript
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - TypeScript
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Installation
npm
install
@anthropic-ai/claude-agent-sdk
The SDK bundles a native Claude Code binary for your platform as an optional dependency such as
@anthropic-ai/claude-agent-sdk-darwin-arm64
. You don’t need to install Claude Code separately. If your package manager skips optional dependencies, the SDK throws
Native CLI binary for <platform> not found
; set
pathToClaudeCodeExecutable
to a separately installed
claude
binary instead.
​
Functions
​
query()
The primary function for interacting with Claude Code. Creates an async generator that streams messages as they arrive.
function
query
({
prompt
,
options
}
:
{
prompt
:
string
|
AsyncIterable
<
SDKUserMessage
>;
options
?:
Options
;
})
:
Query
;
​
Parameters
Parameter
Type
Description
prompt
string | AsyncIterable<
SDKUserMessage
>
The input prompt as a string or async iterable for streaming mode
options
Options
Optional configuration object (see Options type below)
​
Returns
Returns a
Query
object that extends
AsyncGenerator<
SDKMessage
, void>
with additional methods.
​
startup()
Pre-warms the CLI subprocess by spawning it and completing the initialize handshake before a prompt is available. The returned
WarmQuery
handle accepts a prompt later and writes it to an already-ready process, so the first
query()
call resolves without paying subprocess spawn and initialization cost inline.
function
startup
(
params
?:
{
options
?:
Options
;
initializeTimeoutMs
?:
number
;
})
:
Promise
<
WarmQuery
>;
​
Parameters
Parameter
Type
Description
options
Options
Optional configuration object. Same as the
options
parameter to
query()
initializeTimeoutMs
number
Maximum time in milliseconds to wait for subprocess initialization. Defaults to
60000
. If initialization does not complete in time, the promise rejects with a timeout error
​
Returns
Returns a
Promise<
WarmQuery
>
that resolves once the subprocess has spawned and completed its initialize handshake.
​
Example
Call
startup()
early, for example on application boot, then call
.query()
on the returned handle once a prompt is ready. This moves subprocess spawn and initialization out of the critical path.
import
{
startup
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Pay startup cost upfront
const
warm
=
await
startup
({
options:
{
maxTurns:
3
} });
// Later, when a prompt is ready, this is immediate
for
await
(
const
message
of
warm
.
query
(
"What files are here?"
)) {
console
.
log
(
message
);
}
​
tool()
Creates a type-safe MCP tool definition for use with SDK MCP servers.
function
tool
<
Schema
extends
AnyZodRawShape
>(
name
:
string
,
description
:
string
,
inputSchema
:
Schema
,
handler
:
(
args
:
InferShape
<
Schema
>,
extra
:
unknown
)
=>
Promise
<
CallToolResult
>,
extras
?:
{
annotations
?:
ToolAnnotations
}
)
:
SdkMcpToolDefinition
<
Schema
>;
​
Parameters
Parameter
Type
Description
name
string
The name of the tool
description
string
A description of what the tool does
inputSchema
Schema extends AnyZodRawShape
Zod schema defining the tool’s input parameters (supports both Zod 3 and Zod 4)
handler
(args, extra) => Promise<
CallToolResult
>
Async function that executes the tool logic
extras
{ annotations?:
ToolAnnotations
}
Optional MCP tool annotations providing behavioral hints to clients
​
ToolAnnotations
Re-exported from
@modelcontextprotocol/sdk/types.js
. All fields are optional hints; clients should not rely on them for security decisions.
Field
Type
Default
Description
title
string
undefined
Human-readable title for the tool
readOnlyHint
boolean
false
If
true
, the tool does not modify its environment
destructiveHint
boolean
true
If
true
, the tool may perform destructive updates (only meaningful when
readOnlyHint
is
false
)
idempotentHint
boolean
false
If
true
, repeated calls with the same arguments have no additional effect (only meaningful when
readOnlyHint
is
false
)
openWorldHint
boolean
true
If
true
, the tool interacts with external entities (for example, web search). If
false
, the tool’s domain is closed (for example, a memory tool)
import
{
tool
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
{
z
}
from
"zod"
;
const
searchTool
=
tool
(
"search"
,
"Search the web"
,
{
query:
z
.
string
() },
async
({
query
})
=>
{
return
{
content:
[{
type:
"text"
,
text:
`Results for:
${
query
}
`
}] };
},
{
annotations:
{
readOnlyHint:
true
,
openWorldHint:
true
} }
);
​
createSdkMcpServer()
Creates an MCP server instance that runs in the same process as your application.
function
createSdkMcpServer
(
options
:
{
name
:
string
;
version
?:
string
;
tools
?:
Array
<
SdkMcpToolDefinition
<
any
>>;
})
:
McpSdkServerConfigWithInstance
;
​
Parameters
Parameter
Type
Description
options.name
string
The name of the MCP server
options.version
string
Optional version string
options.tools
Array<SdkMcpToolDefinition>
Array of tool definitions created with
tool()
​
listSessions()
Discovers and lists past sessions with light metadata. Filter by project directory or list sessions across all projects.
function
listSessions
(
options
?:
ListSessionsOptions
)
:
Promise
<
SDKSessionInfo
[]>;
​
Parameters
Parameter
Type
Default
Description
options.dir
string
undefined
Directory to list sessions for. When omitted, returns sessions across all projects
options.limit
number
undefined
Maximum number of sessions to return
options.includeWorktrees
boolean
true
When
dir
is inside a git repository, include sessions from all worktree paths
​
Return type:
SDKSessionInfo
Property
Type
Description
sessionId
string
Unique session identifier (UUID)
summary
string
Display title: custom title, auto-generated summary, or first prompt
lastModified
number
Last modified time in milliseconds since epoch
fileSize
number | undefined
Session file size in bytes. Only populated for local JSONL storage
customTitle
string | undefined
User-set session title (via
/rename
)
firstPrompt
string | undefined
First meaningful user prompt in the session
gitBranch
string | undefined
Git branch at the end of the session
cwd
string | undefined
Working directory for the session
tag
string | undefined
User-set session tag (see
tagSession()
)
createdAt
number | undefined
Creation time in milliseconds since epoch, from the first entry’s timestamp
​
Example
Print the 10 most recent sessions for a project. Results are sorted by
lastModified
descending, so the first item is the newest. Omit
dir
to search across all projects.
import
{
listSessions
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
sessions
=
await
listSessions
({
dir:
"/path/to/project"
,
limit:
10
});
for
(
const
session
of
sessions
) {
console
.
log
(
`
${
session
.
summary
}
(
${
session
.
sessionId
}
)`
);
}
​
getSessionMessages()
Reads user and assistant messages from a past session transcript.
function
getSessionMessages
(
sessionId
:
string
,
options
?:
GetSessionMessagesOptions
)
:
Promise
<
SessionMessage
[]>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
Session UUID to read (see
listSessions()
)
options.dir
string
undefined
Project directory to find the session in. When omitted, searches all projects
options.limit
number
undefined
Maximum number of messages to return
options.offset
number
undefined
Number of messages to skip from the start
​
Return type:
SessionMessage
Property
Type
Description
type
"user" | "assistant"
Message role
uuid
string
Unique message identifier
session_id
string
Session this message belongs to
message
unknown
Raw message payload from the transcript
parent_tool_use_id
null
Reserved
​
Example
import
{
listSessions
,
getSessionMessages
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
[
latest
]
=
await
listSessions
({
dir:
"/path/to/project"
,
limit:
1
});
if
(
latest
) {
const
messages
=
await
getSessionMessages
(
latest
.
sessionId
, {
dir:
"/path/to/project"
,
limit:
20
});
for
(
const
msg
of
messages
) {
console
.
log
(
`[
${
msg
.
type
}
]
${
msg
.
uuid
}
`
);
}
}
​
getSessionInfo()
Reads metadata for a single session by ID without scanning the full project directory.
function
getSessionInfo
(
sessionId
:
string
,
options
?:
GetSessionInfoOptions
)
:
Promise
<
SDKSessionInfo
|
undefined
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to look up
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
Returns
SDKSessionInfo
, or
undefined
if the session is not found.
​
renameSession()
Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins.
function
renameSession
(
sessionId
:
string
,
title
:
string
,
options
?:
SessionMutationOptions
)
:
Promise
<
void
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to rename
title
string
required
New title. Must be non-empty after trimming whitespace
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
​
tagSession()
Tags a session. Pass
null
to clear the tag. Repeated calls are safe; the most recent tag wins.
function
tagSession
(
sessionId
:
string
,
tag
:
string
|
null
,
options
?:
SessionMutationOptions
)
:
Promise
<
void
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to tag
tag
string | null
required
Tag string, or
null
to clear
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
​
resolveSettings()
Resolves the effective Claude Code settings for a given directory using the same merge engine as the CLI, without spawning the Claude CLI. Use it to inspect what configuration a
query()
call would see before invoking one.
This function is alpha and its API may change before stabilization. It reads MDM sources, including macOS plist and Windows HKLM/HKCU, for parity with CLI startup, but does not execute the admin-configured
policyHelper
subprocess. The
permissions.defaultMode
field is returned as-is from all tiers including project settings. The trust filter the CLI applies before honoring escalating permission modes is not applied.
function
resolveSettings
(
options
?:
ResolveSettingsOptions
)
:
Promise
<
ResolvedSettings
>;
​
Parameters
resolveSettings()
accepts a single options object. All fields are optional.
Parameter
Type
Default
Description
options.cwd
string
process.cwd()
Directory to resolve project and local settings relative to
options.settingSources
SettingSource
[]
All sources
Which filesystem sources to load. Pass
[]
to skip user, project, and local settings. Managed policy settings load in all cases
options.managedSettings
Settings
undefined
Restrictive policy-tier settings supplied by the embedding host. Dropped by default when an admin-deployed managed tier is present; merged under that tier when
parentSettingsBehavior
is
"merge"
. Non-restrictive keys such as
model
are silently dropped so this option can tighten managed policy but not loosen it
options.serverManagedSettings
Settings
undefined
Server-managed settings payload from
/api/claude_code/settings
. Non-restrictive keys pass through unfiltered
​
Return type:
ResolvedSettings
resolveSettings()
returns an object describing the merged settings and the source that contributed each key.
Property
Type
Description
effective
Settings
Merged settings after applying all enabled sources in precedence order
provenance
Partial<Record<keyof Settings, ProvenanceEntry>>
For each top-level key in
effective
, which source supplied the value
sources
Array<{ source, settings, path?, policyOrigin? }>
Per-source raw settings, ordered from lowest to highest precedence
​
Example
The example below resolves settings for a project directory and prints the source that controls the cleanup period.
import
{
resolveSettings
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
{
effective
,
provenance
}
=
await
resolveSettings
({
cwd:
"/path/to/project"
,
settingSources:
[
"user"
,
"project"
,
"local"
],
});
console
.
log
(
`Cleanup period:
${
effective
.
cleanupPeriodDays
}
days`
);
console
.
log
(
`Set by:
${
provenance
.
cleanupPeriodDays
?.
source
}
`
);
​
Types
​
Options
Configuration object for the
query()
function.
Property
Type
Default
Description
abortController
AbortController
new AbortController()
Controller for cancelling operations
additionalDirectories
string[]
[]
Additional directories Claude can access
agent
string
undefined
Agent name for the main thread. The agent must be defined in the
agents
option or in settings
agents
Record<string, [
AgentDefinition
](#agentdefinition)>
undefined
Programmatically define subagents
allowDangerouslySkipPermissions
boolean
false
Enable bypassing permissions. Required when using
permissionMode: 'bypassPermissions'
allowedTools
string[]
[]
Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to
permissionMode
and
canUseTool
. Use
disallowedTools
to block tools. See
Permissions
betas
SdkBeta
[]
[]
Enable beta features
canUseTool
CanUseTool
undefined
Custom permission function for tool usage
continue
boolean
false
Continue the most recent conversation
cwd
string
process.cwd()
Current working directory
debug
boolean
false
Enable debug mode for the Claude Code process
debugFile
string
undefined
Write debug logs to a specific file path. Implicitly enables debug mode
disallowedTools
string[]
[]
Tools to always deny. Deny rules are checked first and override
allowedTools
and
permissionMode
(including
bypassPermissions
)
effort
'low' | 'medium' | 'high' | 'xhigh' | 'max'
'high'
Controls how much effort Claude puts into its response. Works with adaptive thinking to guide thinking depth
enableFileCheckpointing
boolean
false
Enable file change tracking for rewinding. See
File checkpointing
env
Record<string, string | undefined>
process.env
Environment variables. See
Environment variables
for variables the underlying CLI reads, and
Handle slow or stalled API responses
for timeout-related variables. Set
CLAUDE_AGENT_SDK_CLIENT_APP
to identify your app in the User-Agent header
executable
'bun' | 'deno' | 'node'
Auto-detected
JavaScript runtime to use
executableArgs
string[]
[]
Arguments to pass to the executable
extraArgs
Record<string, string | null>
{}
Additional arguments
fallbackModel
string
undefined
Model to use if primary fails
forkSession
boolean
false
When resuming with
resume
, fork to a new session ID instead of continuing the original session
hooks
Partial<Record<
HookEvent
,
HookCallbackMatcher
[]>>
{}
Hook callbacks for events
includeHookEvents
boolean
false
Include hook lifecycle events in the message stream as
SDKHookStartedMessage
,
SDKHookProgressMessage
, and
SDKHookResponseMessage
includePartialMessages
boolean
false
Include partial message events
maxBudgetUsd
number
undefined
Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as
total_cost_usd
; see
Track cost and usage
for accuracy caveats
maxThinkingTokens
number
undefined
Deprecated:
Use
thinking
instead. Maximum tokens for thinking process
maxTurns
number
undefined
Maximum agentic turns (tool-use round trips)
mcpServers
Record<string, [
McpServerConfig
](#mcpserverconfig)>
{}
MCP server configurations
model
string
Default from CLI
Claude model to use
outputFormat
{ type: 'json_schema', schema: JSONSchema }
undefined
Define output format for agent results. See
Structured outputs
for details
outputStyle
string
undefined
Name of an
output style
to activate for the session. The style must exist in a loaded
settingSources
location, such as
.claude/output-styles/
. See
Activate an output style
pathToClaudeCodeExecutable
string
Auto-resolved from bundled native binary
Path to Claude Code executable. Only needed if optional dependencies were skipped during install or your platform isn’t in the supported set
permissionMode
PermissionMode
'default'
Permission mode for the session
permissionPromptToolName
string
undefined
MCP tool name for permission prompts
persistSession
boolean
true
When
false
, disables session persistence to disk. Sessions cannot be resumed later
plugins
SdkPluginConfig
[]
[]
Load custom plugins from local paths. See
Plugins
for details
promptSuggestions
boolean
false
Enable prompt suggestions. Emits a
prompt_suggestion
message after each turn with a predicted next user prompt
resume
string
undefined
Session ID to resume
resumeSessionAt
string
undefined
Resume session at a specific message UUID
sandbox
SandboxSettings
undefined
Configure sandbox behavior programmatically. See
Sandbox settings
for details
sessionId
string
Auto-generated
Use a specific UUID for the session instead of auto-generating one
sessionStore
SessionStore
undefined
Mirror session transcripts to an external backend so any host can resume them. See
Persist sessions to external storage
settings
string | Settings
undefined
Inline
settings
object or path to a settings file. Populates the flag-settings layer in the
precedence order
. Change at runtime with
applyFlagSettings()
settingSources
SettingSource
[]
CLI defaults (all sources)
Control which filesystem settings to load. Pass
[]
to disable user, project, and local settings. Managed policy settings load regardless. See
Use Claude Code features
skills
string[] | 'all'
undefined
Skills available to the session. Pass
'all'
to enable every discovered skill, or a list of skill names. When set, the SDK enables the Skill tool automatically without listing it in
allowedTools
. See
Skills
spawnClaudeCodeProcess
(options: SpawnOptions) => SpawnedProcess
undefined
Custom function to spawn the Claude Code process. Use to run Claude Code in VMs, containers, or remote environments
stderr
(data: string) => void
undefined
Callback for stderr output
strictMcpConfig
boolean
false
Enforce strict MCP validation
systemPrompt
string | { type: 'preset'; preset: 'claude_code'; append?: string; excludeDynamicSections?: boolean }
undefined
(minimal prompt)
System prompt configuration. Pass a string for custom prompt, or
{ type: 'preset', preset: 'claude_code' }
to use Claude Code’s system prompt. When using the preset object form, add
append
to extend it with additional instructions, and set
excludeDynamicSections: true
to move per-session context into the first user message for
better prompt-cache reuse across machines
thinking
ThinkingConfig
{ type: 'adaptive' }
for supported models
Controls Claude’s thinking/reasoning behavior. See
ThinkingConfig
for options
toolConfig
ToolConfig
undefined
Configuration for built-in tool behavior. See
ToolConfig
for details
tools
string[] | { type: 'preset'; preset: 'claude_code' }
undefined
Tool configuration. Pass an array of tool names or use the preset to get Claude Code’s default tools
​
Handle slow or stalled API responses
The CLI subprocess reads several environment variables that control API timeouts and stall detection. Pass them through the
env
option:
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
env:
{
...
process
.
env
,
API_TIMEOUT_MS:
"120000"
,
CLAUDE_CODE_MAX_RETRIES:
"2"
,
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS:
"120000"
,
},
},
});
API_TIMEOUT_MS
: per-request timeout on the Anthropic client, in milliseconds. Default
600000
. Applies to the main loop and all subagents.
CLAUDE_CODE_MAX_RETRIES
: maximum API retries. Default
10
. Each retry gets its own
API_TIMEOUT_MS
window, so worst-case wall time is roughly
API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)
plus backoff.
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
: stall watchdog for subagents launched with
run_in_background
. Default
600000
. Resets on each stream event; on stall it aborts the subagent, marks the task failed, and surfaces the error to the parent with any partial result. Does not apply to synchronous subagents.
CLAUDE_ENABLE_STREAM_WATCHDOG=1
with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
: aborts the request when headers have arrived but the response body stops streaming. Off by default.
CLAUDE_STREAM_IDLE_TIMEOUT_MS
defaults to
300000
and is clamped to that minimum. The aborted request goes through the normal retry path.
​
Query
object
Interface returned by the
query()
function.
interface
Query
extends
AsyncGenerator
<
SDKMessage
,
void
> {
interrupt
()
:
Promise
<
void
>;
rewindFiles
(
userMessageId
:
string
,
options
?:
{
dryRun
?:
boolean
}
)
:
Promise
<
RewindFilesResult
>;
setPermissionMode
(
mode
:
PermissionMode
)
:
Promise
<
void
>;
setModel
(
model
?:
string
)
:
Promise
<
void
>;
setMaxThinkingTokens
(
maxThinkingTokens
:
number
|
null
)
:
Promise
<
void
>;
applyFlagSettings
(
settings
:
{ [
K
in
keyof
Settings
]
?:
Settings
[
K
]
|
null
})
:
Promise
<
void
>;
initializationResult
()
:
Promise
<
SDKControlInitializeResponse
>;
supportedCommands
()
:
Promise
<
SlashCommand
[]>;
supportedModels
()
:
Promise
<
ModelInfo
[]>;
supportedAgents
()
:
Promise
<
AgentInfo
[]>;
mcpServerStatus
()
:
Promise
<
McpServerStatus
[]>;
accountInfo
()
:
Promise
<
AccountInfo
>;
reconnectMcpServer
(
serverName
:
string
)
:
Promise
<
void
>;
toggleMcpServer
(
serverName
:
string
,
enabled
:
boolean
)
:
Promise
<
void
>;
setMcpServers
(
servers
:
Record
<
string
,
McpServerConfig
>)
:
Promise
<
McpSetServersResult
>;
streamInput
(
stream
:
AsyncIterable
<
SDKUserMessage
>)
:
Promise
<
void
>;
stopTask
(
taskId
:
string
)
:
Promise
<
void
>;
close
()
:
void
;
}
​
Methods
Method
Description
interrupt()
Interrupts the query (only available in streaming input mode)
rewindFiles(userMessageId, options?)
Restores files to their state at the specified user message. Pass
{ dryRun: true }
to preview changes. Requires
enableFileCheckpointing: true
. See
File checkpointing
setPermissionMode()
Changes the permission mode (only available in streaming input mode)
setModel()
Changes the model (only available in streaming input mode)
setMaxThinkingTokens()
Deprecated:
Use the
thinking
option instead. Changes the maximum thinking tokens
applyFlagSettings(settings)
Merges settings into the session’s flag settings layer at runtime (only available in streaming input mode). See
applyFlagSettings()
initializationResult()
Returns the full initialization result including supported commands, models, account info, and output style configuration
supportedCommands()
Returns available slash commands
supportedModels()
Returns available models with display info
supportedAgents()
Returns available subagents as
AgentInfo
[]
mcpServerStatus()
Returns status of connected MCP servers
accountInfo()
Returns account information
reconnectMcpServer(serverName)
Reconnect an MCP server by name
toggleMcpServer(serverName, enabled)
Enable or disable an MCP server by name
setMcpServers(servers)
Dynamically replace the set of MCP servers for this session. Returns info about which servers were added, removed, and any errors
streamInput(stream)
Stream input messages to the query for multi-turn conversations
stopTask(taskId)
Stop a running background task by ID
close()
Close the query and terminate the underlying process. Forcefully ends the query and cleans up all resources
​
applyFlagSettings()
Changes any
setting
on a running session without restarting the query. Use it when a setting that has no dedicated setter needs to change mid-session, such as tightening
permissions
after the agent reads untrusted input.
setModel()
and
setPermissionMode()
are dedicated setters for those two keys;
applyFlagSettings()
is the general form that accepts any subset of the settings keys, and passing
model
here behaves the same as
setModel()
.
The values are written to the flag-settings layer, the same layer the inline
settings
option of
query()
populates at startup. Flag settings sit near the top of the
settings precedence order
: they override user, project, and local settings, and only managed policy settings can override them. This is the same tier the
on-page precedence section
calls programmatic options.
Successive calls shallow-merge top-level keys. A second call with
{ permissions: {...} }
replaces the entire
permissions
object from the prior call rather than deep-merging into it. To clear a key from the flag layer and fall back to lower-precedence sources, pass
null
for that key. Passing
undefined
has no effect because JSON serialization drops it.
Only available in streaming input mode, the same constraint as
setModel()
and
setPermissionMode()
.
The example below switches the active model mid-session, then clears the override so the model falls back to whatever the user or project settings specify.
const
q
=
query
({
prompt:
messageStream
});
// Override the model for the rest of the session
await
q
.
applyFlagSettings
({
model:
"claude-opus-4-6"
});
// Later: clear the override and fall back to lower-precedence settings
await
q
.
applyFlagSettings
({
model:
null
});
applyFlagSettings()
is TypeScript-only. The Python SDK does not expose an equivalent method.
​
WarmQuery
Handle returned by
startup()
. The subprocess is already spawned and initialized, so calling
query()
on this handle writes the prompt directly to a ready process with no startup latency.
interface
WarmQuery
extends
AsyncDisposable
{
query
(
prompt
:
string
|
AsyncIterable
<
SDKUserMessage
>)
:
Query
;
close
()
:
void
;
}
​
Methods
Method
Description
query(prompt)
Send a prompt to the pre-warmed subprocess and return a
Query
. Can only be called once per
WarmQuery
close()
Close the subprocess without sending a prompt. Use this to discard a warm query that is no longer needed
WarmQuery
implements
AsyncDisposable
, so it can be used with
await using
for automatic cleanup.
​
SDKControlInitializeResponse
Return type of
initializationResult()
. Contains session initialization data.
type
SDKControlInitializeResponse
=
{
commands
:
SlashCommand
[];
agents
:
AgentInfo
[];
output_style
:
string
;
available_output_styles
:
string
[];
models
:
ModelInfo
[];
account
:
AccountInfo
;
fast_mode_state
?:
"off"
|
"cooldown"
|
"on"
;
};
​
AgentDefinition
Configuration for a subagent defined programmatically.
type
AgentDefinition
=
{
description
:
string
;
tools
?:
string
[];
disallowedTools
?:
string
[];
prompt
:
string
;
model
?:
string
;
mcpServers
?:
AgentMcpServerSpec
[];
skills
?:
string
[];
initialPrompt
?:
string
;
maxTurns
?:
number
;
background
?:
boolean
;
memory
?:
"user"
|
"project"
|
"local"
;
effort
?:
"low"
|
"medium"
|
"high"
|
"xhigh"
|
"max"
|
number
;
permissionMode
?:
PermissionMode
;
criticalSystemReminder_EXPERIMENTAL
?:
string
;
};
Field
Required
Description
description
Yes
Natural language description of when to use this agent
tools
No
Array of allowed tool names. If omitted, inherits all tools from parent. To preload Skills into the agent’s context, use the
skills
field rather than listing
'Skill'
here
disallowedTools
No
Array of tool names to explicitly disallow for this agent
prompt
Yes
The agent’s system prompt
model
No
Model override for this agent. Accepts an alias such as
'sonnet'
,
'opus'
,
'haiku'
,
'inherit'
, or a full model ID. If omitted or
'inherit'
, uses the main model
mcpServers
No
MCP server specifications for this agent
skills
No
Array of skill names to preload into the agent context
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main thread agent
maxTurns
No
Maximum number of agentic turns (API round-trips) before stopping
background
No
Run this agent as a non-blocking background task when invoked
memory
No
Memory source for this agent:
'user'
,
'project'
, or
'local'
effort
No
Reasoning effort level for this agent. Accepts a named level or an integer
permissionMode
No
Permission mode for tool execution within this agent. See
PermissionMode
criticalSystemReminder_EXPERIMENTAL
No
Experimental: Critical reminder added to the system prompt
​
AgentMcpServerSpec
Specifies MCP servers available to a subagent. Can be a server name (string referencing a server from the parent’s
mcpServers
config) or an inline server configuration record mapping server names to configs.
type
AgentMcpServerSpec
=
string
|
Record
<
string
,
McpServerConfigForProcessTransport
>;
Where
McpServerConfigForProcessTransport
is
McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
.
​
SettingSource
Controls which filesystem-based configuration sources the SDK loads settings from.
type
SettingSource
=
"user"
|
"project"
|
"local"
;
Value
Description
Location
'user'
Global user settings
~/.claude/settings.json
'project'
Shared project settings (version controlled)
.claude/settings.json
'local'
Local project settings (gitignored)
.claude/settings.local.json
​
Default behavior
When
settingSources
is omitted or
undefined
,
query()
loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See
What settingSources does not control
for inputs that are read regardless of this option, and how to disable them.
​
Why use settingSources
Disable filesystem settings:
// Do not load user, project, or local settings from disk
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
settingSources:
[] }
});
Load all filesystem settings explicitly:
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
settingSources:
[
"user"
,
"project"
,
"local"
]
// Load all settings
}
});
Load only specific setting sources:
// Load only project settings, ignore user and local
const
result
=
query
({
prompt:
"Run CI checks"
,
options:
{
settingSources:
[
"project"
]
// Only .claude/settings.json
}
});
Testing and CI environments:
// Ensure consistent behavior in CI by excluding local settings
const
result
=
query
({
prompt:
"Run tests"
,
options:
{
settingSources:
[
"project"
],
// Only team-shared settings
permissionMode:
"bypassPermissions"
}
});
SDK-only applications:
// Define everything programmatically.
// Pass [] to opt out of filesystem setting sources.
const
result
=
query
({
prompt:
"Review this PR"
,
options:
{
settingSources:
[],
agents:
{
/* ... */
},
mcpServers:
{
/* ... */
},
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
]
}
});
Loading CLAUDE.md project instructions:
// Load project settings to include CLAUDE.md files
const
result
=
query
({
prompt:
"Add a new feature following project conventions"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
// Use Claude Code's system prompt
},
settingSources:
[
"project"
],
// Loads CLAUDE.md from project directory
allowedTools:
[
"Read"
,
"Write"
,
"Edit"
]
}
});
​
Settings precedence
When multiple sources are loaded, settings are merged with this precedence (highest to lowest):
Local settings (
.claude/settings.local.json
)
Project settings (
.claude/settings.json
)
User settings (
~/.claude/settings.json
)
Programmatic options such as
agents
,
allowedTools
, and
settings
override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.
​
PermissionMode
type
PermissionMode
=
|
"default"
// Standard permission behavior
|
"acceptEdits"
// Auto-accept file edits
|
"bypassPermissions"
// Bypass all permission checks
|
"plan"
// Planning mode - read-only tools only
|
"dontAsk"
// Don't prompt for permissions, deny if not pre-approved
|
"auto"
;
// Use a model classifier to approve or deny each tool call
​
CanUseTool
Custom permission function type for controlling tool usage.
type
CanUseTool
=
(
toolName
:
string
,
input
:
Record
<
string
,
unknown
>,
options
:
{
signal
:
AbortSignal
;
suggestions
?:
PermissionUpdate
[];
blockedPath
?:
string
;
decisionReason
?:
string
;
toolUseID
:
string
;
agentID
?:
string
;
}
)
=>
Promise
<
PermissionResult
>;
Option
Type
Description
signal
AbortSignal
Signaled if the operation should be aborted
suggestions
PermissionUpdate
[]
Suggested permission updates so the user is not prompted again for this tool. Bash prompts include a suggestion with the
localSettings
destination
, so returning it in
updatedPermissions
writes the rule to
.claude/settings.local.json
and persists across sessions.
blockedPath
string
The file path that triggered the permission request, if applicable
decisionReason
string
Explains why this permission request was triggered
toolUseID
string
Unique identifier for this specific tool call within the assistant message
agentID
string
If running within a sub-agent, the sub-agent’s ID
​
PermissionResult
Result of a permission check.
type
PermissionResult
=
|
{
behavior
:
"allow"
;
updatedInput
?:
Record
<
string
,
unknown
>;
updatedPermissions
?:
PermissionUpdate
[];
toolUseID
?:
string
;
}
|
{
behavior
:
"deny"
;
message
:
string
;
interrupt
?:
boolean
;
toolUseID
?:
string
;
};
​
ToolConfig
Configuration for built-in tool behavior.
type
ToolConfig
=
{
askUserQuestion
?:
{
previewFormat
?:
"markdown"
|
"html"
;
};
};
Field
Type
Description
askUserQuestion.previewFormat
'markdown' | 'html'
Opts into the
preview
field on
AskUserQuestion
options and sets its content format. When unset, Claude does not emit previews
​
McpServerConfig
Configuration for MCP servers.
type
McpServerConfig
=
|
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfigWithInstance
;
​
McpStdioServerConfig
type
McpStdioServerConfig
=
{
type
?:
"stdio"
;
command
:
string
;
args
?:
string
[];
env
?:
Record
<
string
,
string
>;
};
​
McpSSEServerConfig
type
McpSSEServerConfig
=
{
type
:
"sse"
;
url
:
string
;
headers
?:
Record
<
string
,
string
>;
};
​
McpHttpServerConfig
type
McpHttpServerConfig
=
{
type
:
"http"
;
url
:
string
;
headers
?:
Record
<
string
,
string
>;
};
​
McpSdkServerConfigWithInstance
type
McpSdkServerConfigWithInstance
=
{
type
:
"sdk"
;
name
:
string
;
instance
:
McpServer
;
};
​
McpClaudeAIProxyServerConfig
type
McpClaudeAIProxyServerConfig
=
{
type
:
"claudeai-proxy"
;
url
:
string
;
id
:
string
;
};
​
SdkPluginConfig
Configuration for loading plugins in the SDK.
type
SdkPluginConfig
=
{
type
:
"local"
;
path
:
string
;
};
Field
Type
Description
type
'local'
Must be
'local'
(only local plugins currently supported)
path
string
Absolute or relative path to the plugin directory
Example:
plugins
: [
{
type:
"local"
,
path:
"./my-plugin"
},
{
type:
"local"
,
path:
"/absolute/path/to/plugin"
}
];
For complete information on creating and using plugins, see
Plugins
.
​
Message Types
​
SDKMessage
Union type of all possible messages returned by the query.
type
SDKMessage
=
|
SDKAssistantMessage
|
SDKUserMessage
|
SDKUserMessageReplay
|
SDKResultMessage
|
SDKSystemMessage
|
SDKPartialAssistantMessage
|
SDKCompactBoundaryMessage
|
SDKStatusMessage
|
SDKLocalCommandOutputMessage
|
SDKHookStartedMessage
|
SDKHookProgressMessage
|
SDKHookResponseMessage
|
SDKPluginInstallMessage
|
SDKToolProgressMessage
|
SDKAuthStatusMessage
|
SDKTaskNotificationMessage
|
SDKTaskStartedMessage
|
SDKTaskProgressMessage
|
SDKTaskUpdatedMessage
|
SDKFilesPersistedEvent
|
SDKToolUseSummaryMessage
|
SDKRateLimitEvent
|
SDKPermissionDeniedMessage
|
SDKPromptSuggestionMessage
;
​
SDKAssistantMessage
Assistant response message.
type
SDKAssistantMessage
=
{
type
:
"assistant"
;
uuid
:
UUID
;
session_id
:
string
;
message
:
BetaMessage
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
error
?:
SDKAssistantMessageError
;
};
The
message
field is a
BetaMessage
from the Anthropic SDK. It includes fields like
id
,
content
,
model
,
stop_reason
, and
usage
.
SDKAssistantMessageError
is one of:
'authentication_failed'
,
'oauth_org_not_allowed'
,
'billing_error'
,
'rate_limit'
,
'invalid_request'
,
'server_error'
,
'max_output_tokens'
, or
'unknown'
.
​
SDKUserMessage
User input message.
type
SDKUserMessage
=
{
type
:
"user"
;
uuid
?:
UUID
;
session_id
?:
string
;
message
:
MessageParam
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
isSynthetic
?:
boolean
;
shouldQuery
?:
boolean
;
tool_use_result
?:
unknown
;
origin
?:
SDKMessageOrigin
;
};
Set
shouldQuery
to
false
to append the message to the transcript without triggering an assistant turn. The message is held and merged into the next user message that does trigger a turn. Use this to inject context, such as the output of a command you ran out of band, without spending a model call on it.
​
SDKUserMessageReplay
Replayed user message with required UUID.
type
SDKUserMessageReplay
=
{
type
:
"user"
;
uuid
:
UUID
;
session_id
:
string
;
message
:
MessageParam
;
parent_tool_use_id
:
string
|
null
;
isSynthetic
?:
boolean
;
tool_use_result
?:
unknown
;
origin
?:
SDKMessageOrigin
;
isReplay
:
true
;
};
​
SDKResultMessage
Final result message.
type
SDKResultMessage
=
|
{
type
:
"result"
;
subtype
:
"success"
;
uuid
:
UUID
;
session_id
:
string
;
duration_ms
:
number
;
duration_api_ms
:
number
;
is_error
:
boolean
;
num_turns
:
number
;
result
:
string
;
stop_reason
:
string
|
null
;
total_cost_usd
:
number
;
usage
:
NonNullableUsage
;
modelUsage
:
{ [
modelName
:
string
]
:
ModelUsage
};
permission_denials
:
SDKPermissionDenial
[];
structured_output
?:
unknown
;
deferred_tool_use
?:
{
id
:
string
;
name
:
string
;
input
:
Record
<
string
,
unknown
> };
origin
?:
SDKMessageOrigin
;
}
|
{
type
:
"result"
;
subtype
:
|
"error_max_turns"
|
"error_during_execution"
|
"error_max_budget_usd"
|
"error_max_structured_output_retries"
;
uuid
:
UUID
;
session_id
:
string
;
duration_ms
:
number
;
duration_api_ms
:
number
;
is_error
:
boolean
;
num_turns
:
number
;
stop_reason
:
string
|
null
;
total_cost_usd
:
number
;
usage
:
NonNullableUsage
;
modelUsage
:
{ [
modelName
:
string
]
:
ModelUsage
};
permission_denials
:
SDKPermissionDenial
[];
errors
:
string
[];
origin
?:
SDKMessageOrigin
;
};
The
origin
field forwards the
SDKMessageOrigin
of the user message that triggered this result. When a background task finishes and the SDK injects a synthetic follow-up turn, the resulting
SDKResultMessage
carries
origin: { kind: "task-notification" }
. Check this field to distinguish results that answer your prompt from results emitted for background-task follow-ups, so you can route or suppress the latter. The field is absent for results emitted before any user turn, such as startup errors.
When a
PreToolUse
hook returns
permissionDecision: "defer"
, the result has
stop_reason: "tool_deferred"
and
deferred_tool_use
carries the pending tool’s
id
,
name
, and
input
. Read this field to surface the request in your own UI, then resume with the same
session_id
to continue. See
Defer a tool call for later
for the full round trip.
​
SDKSystemMessage
System initialization message.
type
SDKSystemMessage
=
{
type
:
"system"
;
subtype
:
"init"
;
uuid
:
UUID
;
session_id
:
string
;
agents
?:
string
[];
apiKeySource
:
ApiKeySource
;
betas
?:
string
[];
claude_code_version
:
string
;
cwd
:
string
;
tools
:
string
[];
mcp_servers
:
{
name
:
string
;
status
:
string
;
}[];
model
:
string
;
permissionMode
:
PermissionMode
;
slash_commands
:
string
[];
output_style
:
string
;
skills
:
string
[];
plugins
:
{
name
:
string
;
path
:
string
}[];
};
​
SDKPartialAssistantMessage
Streaming partial message (only when
includePartialMessages
is true).
type
SDKPartialAssistantMessage
=
{
type
:
"stream_event"
;
event
:
BetaRawMessageStreamEvent
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKCompactBoundaryMessage
Message indicating a conversation compaction boundary.
type
SDKCompactBoundaryMessage
=
{
type
:
"system"
;
subtype
:
"compact_boundary"
;
uuid
:
UUID
;
session_id
:
string
;
compact_metadata
:
{
trigger
:
"manual"
|
"auto"
;
pre_tokens
:
number
;
};
};
​
SDKPluginInstallMessage
Plugin installation progress event. Emitted when
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, so your Agent SDK application can track marketplace plugin installation before the first turn. The
started
and
completed
statuses bracket the overall install. The
installed
and
failed
statuses report individual marketplaces and include
name
.
type
SDKPluginInstallMessage
=
{
type
:
"system"
;
subtype
:
"plugin_install"
;
status
:
"started"
|
"installed"
|
"failed"
|
"completed"
;
name
?:
string
;
error
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKPermissionDeniedMessage
Stream event emitted when the permission system auto-denies a tool call without an interactive prompt. Use it to render the denial in your UI as it happens, rather than only observing the
is_error
tool result that follows. The interactive ask path reaches your application separately through the
canUseTool
callback. Denials issued by a
PreToolUse
hook are not reported through this event.
This event requires Claude Code v2.1.136 or later.
type
SDKPermissionDeniedMessage
=
{
type
:
"system"
;
subtype
:
"permission_denied"
;
tool_name
:
string
;
tool_use_id
:
string
;
agent_id
?:
string
;
decision_reason_type
?:
string
;
decision_reason
?:
string
;
message
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
Field
Type
Description
tool_name
string
Name of the tool that was denied
tool_use_id
string
ID of the
tool_use
block this denial answers
agent_id
string
Subagent ID when the denied call originated inside a subagent. Mirrors the field on
can_use_tool
for host-side routing
decision_reason_type
string
Discriminator for the component that decided, such as
"rule"
,
"mode"
,
"classifier"
, or
"asyncAgent"
decision_reason
string
Human-readable reason from the deciding component, when available
message
string
Rejection message returned to the model in the
tool_result
​
SDKPermissionDenial
Information about a denied tool use.
type
SDKPermissionDenial
=
{
tool_name
:
string
;
tool_use_id
:
string
;
tool_input
:
Record
<
string
,
unknown
>;
};
​
SDKMessageOrigin
Provenance of a user-role message. This appears as
origin
on
SDKUserMessage
and is forwarded onto the corresponding
SDKResultMessage
so you can tell what triggered a given turn.
type
SDKMessageOrigin
=
|
{
kind
:
"human"
}
|
{
kind
:
"channel"
;
server
:
string
}
|
{
kind
:
"peer"
;
from
:
string
;
name
?:
string
}
|
{
kind
:
"task-notification"
}
|
{
kind
:
"coordinator"
};
kind
Meaning
human
Direct input from the end user. On user messages, an absent
origin
also means human input.
channel
Message arriving on a
channel
.
server
is the source MCP server name.
peer
Message from another agent session via
SendMessage
.
from
is the sender address;
name
is the sender’s display name when available.
task-notification
Synthetic turn injected after a background task finished. See
SDKTaskNotificationMessage
.
coordinator
Message from a team coordinator in an
agent team
.
​
Hook Types
For a comprehensive guide on using hooks with examples and common patterns, see the
Hooks guide
.
​
HookEvent
Available hook events.
type
HookEvent
=
|
"PreToolUse"
|
"PostToolUse"
|
"PostToolUseFailure"
|
"PostToolBatch"
|
"Notification"
|
"UserPromptSubmit"
|
"SessionStart"
|
"SessionEnd"
|
"Stop"
|
"SubagentStart"
|
"SubagentStop"
|
"PreCompact"
|
"PermissionRequest"
|
"Setup"
|
"TeammateIdle"
|
"TaskCompleted"
|
"ConfigChange"
|
"WorktreeCreate"
|
"WorktreeRemove"
;
​
HookCallback
Hook callback function type.
type
HookCallback
=
(
input
:
HookInput
,
// Union of all hook input types
toolUseID
:
string
|
undefined
,
options
:
{
signal
:
AbortSignal
}
)
=>
Promise
<
HookJSONOutput
>;
​
HookCallbackMatcher
Hook configuration with optional matcher.
interface
HookCallbackMatcher
{
matcher
?:
string
;
hooks
:
HookCallback
[];
timeout
?:
number
;
// Timeout in seconds for all hooks in this matcher
}
​
HookInput
Union type of all hook input types.
type
HookInput
=
|
PreToolUseHookInput
|
PostToolUseHookInput
|
PostToolUseFailureHookInput
|
PostToolBatchHookInput
|
NotificationHookInput
|
UserPromptSubmitHookInput
|
SessionStartHookInput
|
SessionEndHookInput
|
StopHookInput
|
SubagentStartHookInput
|
SubagentStopHookInput
|
PreCompactHookInput
|
PermissionRequestHookInput
|
SetupHookInput
|
TeammateIdleHookInput
|
TaskCompletedHookInput
|
ConfigChangeHookInput
|
WorktreeCreateHookInput
|
WorktreeRemoveHookInput
;
​
BaseHookInput
Base interface that all hook input types extend.
type
BaseHookInput
=
{
session_id
:
string
;
transcript_path
:
string
;
cwd
:
string
;
permission_mode
?:
string
;
effort
?:
{
level
:
string
};
agent_id
?:
string
;
agent_type
?:
string
;
};
​
PreToolUseHookInput
type
PreToolUseHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PreToolUse"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
};
​
PostToolUseHookInput
type
PostToolUseHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolUse"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_response
:
unknown
;
tool_use_id
:
string
;
duration_ms
?:
number
;
};
​
PostToolUseFailureHookInput
type
PostToolUseFailureHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolUseFailure"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
error
:
string
;
is_interrupt
?:
boolean
;
duration_ms
?:
number
;
};
​
PostToolBatchHookInput
Fires once after every tool call in a batch has resolved, before the next model request.
tool_response
carries the serialized
tool_result
content the model sees; the shape differs from
PostToolUseHookInput
’s structured
Output
object.
type
PostToolBatchHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolBatch"
;
tool_calls
:
PostToolBatchToolCall
[];
};
type
PostToolBatchToolCall
=
{
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
tool_response
?:
unknown
;
};
​
NotificationHookInput
type
NotificationHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Notification"
;
message
:
string
;
title
?:
string
;
notification_type
:
string
;
};
​
UserPromptSubmitHookInput
type
UserPromptSubmitHookInput
=
BaseHookInput
&
{
hook_event_name
:
"UserPromptSubmit"
;
prompt
:
string
;
};
​
SessionStartHookInput
type
SessionStartHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SessionStart"
;
source
:
"startup"
|
"resume"
|
"clear"
|
"compact"
;
agent_type
?:
string
;
model
?:
string
;
};
​
SessionEndHookInput
type
SessionEndHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SessionEnd"
;
reason
:
ExitReason
;
// String from EXIT_REASONS array
};
​
StopHookInput
type
StopHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Stop"
;
stop_hook_active
:
boolean
;
last_assistant_message
?:
string
;
};
​
SubagentStartHookInput
type
SubagentStartHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SubagentStart"
;
agent_id
:
string
;
agent_type
:
string
;
};
​
SubagentStopHookInput
type
SubagentStopHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SubagentStop"
;
stop_hook_active
:
boolean
;
agent_id
:
string
;
agent_transcript_path
:
string
;
agent_type
:
string
;
last_assistant_message
?:
string
;
};
​
PreCompactHookInput
type
PreCompactHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PreCompact"
;
trigger
:
"manual"
|
"auto"
;
custom_instructions
:
string
|
null
;
};
​
PermissionRequestHookInput
type
PermissionRequestHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PermissionRequest"
;
tool_name
:
string
;
tool_input
:
unknown
;
permission_suggestions
?:
PermissionUpdate
[];
};
​
SetupHookInput
type
SetupHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Setup"
;
trigger
:
"init"
|
"maintenance"
;
};
​
TeammateIdleHookInput
type
TeammateIdleHookInput
=
BaseHookInput
&
{
hook_event_name
:
"TeammateIdle"
;
teammate_name
:
string
;
team_name
:
string
;
};
​
TaskCompletedHookInput
type
TaskCompletedHookInput
=
BaseHookInput
&
{
hook_event_name
:
"TaskCompleted"
;
task_id
:
string
;
task_subject
:
string
;
task_description
?:
string
;
teammate_name
?:
string
;
team_name
?:
string
;
};
​
ConfigChangeHookInput
type
ConfigChangeHookInput
=
BaseHookInput
&
{
hook_event_name
:
"ConfigChange"
;
source
:
|
"user_settings"
|
"project_settings"
|
"local_settings"
|
"policy_settings"
|
"skills"
;
file_path
?:
string
;
};
​
WorktreeCreateHookInput
type
WorktreeCreateHookInput
=
BaseHookInput
&
{
hook_event_name
:
"WorktreeCreate"
;
name
:
string
;
};
​
WorktreeRemoveHookInput
type
WorktreeRemoveHookInput
=
BaseHookInput
&
{
hook_event_name
:
"WorktreeRemove"
;
worktree_path
:
string
;
};
​
HookJSONOutput
Hook return value.
type
HookJSONOutput
=
AsyncHookJSONOutput
|
SyncHookJSONOutput
;
​
AsyncHookJSONOutput
type
AsyncHookJSONOutput
=
{
async
:
true
;
asyncTimeout
?:
number
;
};
​
SyncHookJSONOutput
type
SyncHookJSONOutput
=
{
continue
?:
boolean
;
suppressOutput
?:
boolean
;
stopReason
?:
string
;
decision
?:
"approve"
|
"block"
;
systemMessage
?:
string
;
reason
?:
string
;
hookSpecificOutput
?:
|
{
hookEventName
:
"PreToolUse"
;
permissionDecision
?:
"allow"
|
"deny"
|
"ask"
|
"defer"
;
permissionDecisionReason
?:
string
;
updatedInput
?:
Record
<
string
,
unknown
>;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"UserPromptSubmit"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"SessionStart"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"Setup"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"SubagentStart"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PostToolUse"
;
additionalContext
?:
string
;
updatedToolOutput
?:
unknown
;
/**
@deprecated
Use `updatedToolOutput`, which works for all tools. */
updatedMCPToolOutput
?:
unknown
;
}
|
{
hookEventName
:
"PostToolUseFailure"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PostToolBatch"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"Notification"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PermissionRequest"
;
decision
:
|
{
behavior
:
"allow"
;
updatedInput
?:
Record
<
string
,
unknown
>;
updatedPermissions
?:
PermissionUpdate
[];
}
|
{
behavior
:
"deny"
;
message
?:
string
;
interrupt
?:
boolean
;
};
};
};
​
Tool Input Types
Documentation of input schemas for all built-in Claude Code tools. These types are exported from
@anthropic-ai/claude-agent-sdk
and can be used for type-safe tool interactions.
​
ToolInputSchemas
Union of all tool input types, exported from
@anthropic-ai/claude-agent-sdk
.
type
ToolInputSchemas
=
|
AgentInput
|
AskUserQuestionInput
|
BashInput
|
TaskOutputInput
|
EnterWorktreeInput
|
ExitPlanModeInput
|
FileEditInput
|
FileReadInput
|
FileWriteInput
|
GlobInput
|
GrepInput
|
ListMcpResourcesInput
|
McpInput
|
MonitorInput
|
NotebookEditInput
|
ReadMcpResourceInput
|
SubscribeMcpResourceInput
|
SubscribePollingInput
|
TaskCreateInput
|
TaskGetInput
|
TaskListInput
|
TaskStopInput
|
TaskUpdateInput
|
TodoWriteInput
|
UnsubscribeMcpResourceInput
|
UnsubscribePollingInput
|
WebFetchInput
|
WebSearchInput
;
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
type
AgentInput
=
{
description
:
string
;
prompt
:
string
;
subagent_type
:
string
;
model
?:
"sonnet"
|
"opus"
|
"haiku"
;
resume
?:
string
;
run_in_background
?:
boolean
;
max_turns
?:
number
;
name
?:
string
;
team_name
?:
string
;
mode
?:
"acceptEdits"
|
"bypassPermissions"
|
"default"
|
"dontAsk"
|
"plan"
;
isolation
?:
"worktree"
;
};
Launches a new agent to handle complex, multi-step tasks autonomously.
​
AskUserQuestion
Tool name:
AskUserQuestion
type
AskUserQuestionInput
=
{
questions
:
Array
<{
question
:
string
;
header
:
string
;
options
:
Array
<{
label
:
string
;
description
:
string
;
preview
?:
string
}>;
multiSelect
:
boolean
;
}>;
};
Asks the user clarifying questions during execution. See
Handle approvals and user input
for usage details.
​
Bash
Tool name:
Bash
type
BashInput
=
{
command
:
string
;
timeout
?:
number
;
description
?:
string
;
run_in_background
?:
boolean
;
dangerouslyDisableSandbox
?:
boolean
;
};
Executes bash commands in a persistent shell session with optional timeout and background execution.
​
Monitor
Tool name:
Monitor
type
MonitorInput
=
{
command
:
string
;
description
:
string
;
timeout_ms
?:
number
;
persistent
?:
boolean
;
};
Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Set
persistent: true
for session-length watches such as log tails. Monitor follows the same permission rules as Bash. See the
Monitor tool reference
for behavior and provider availability.
​
TaskOutput
Tool name:
TaskOutput
type
TaskOutputInput
=
{
task_id
:
string
;
block
:
boolean
;
timeout
:
number
;
};
Retrieves output from a running or completed background task.
​
Edit
Tool name:
Edit
type
FileEditInput
=
{
file_path
:
string
;
old_string
:
string
;
new_string
:
string
;
replace_all
?:
boolean
;
};
Performs exact string replacements in files.
​
Read
Tool name:
Read
type
FileReadInput
=
{
file_path
:
string
;
offset
?:
number
;
limit
?:
number
;
pages
?:
string
;
};
Reads files from the local filesystem, including text, images, PDFs, and Jupyter notebooks. Use
pages
for PDF page ranges (for example,
"1-5"
).
​
Write
Tool name:
Write
type
FileWriteInput
=
{
file_path
:
string
;
content
:
string
;
};
Writes a file to the local filesystem, overwriting if it exists.
​
Glob
Tool name:
Glob
type
GlobInput
=
{
pattern
:
string
;
path
?:
string
;
};
Fast file pattern matching that works with any codebase size.
​
Grep
Tool name:
Grep
type
GrepInput
=
{
pattern
:
string
;
path
?:
string
;
glob
?:
string
;
type
?:
string
;
output_mode
?:
"content"
|
"files_with_matches"
|
"count"
;
"-i"
?:
boolean
;
"-n"
?:
boolean
;
"-B"
?:
number
;
"-A"
?:
number
;
"-C"
?:
number
;
context
?:
number
;
head_limit
?:
number
;
offset
?:
number
;
multiline
?:
boolean
;
};
Powerful search tool built on ripgrep with regex support.
​
TaskStop
Tool name:
TaskStop
type
TaskStopInput
=
{
task_id
?:
string
;
shell_id
?:
string
;
// Deprecated: use task_id
};
Stops a running background task or shell by ID.
​
NotebookEdit
Tool name:
NotebookEdit
type
NotebookEditInput
=
{
notebook_path
:
string
;
cell_id
?:
string
;
new_source
:
string
;
cell_type
?:
"code"
|
"markdown"
;
edit_mode
?:
"replace"
|
"insert"
|
"delete"
;
};
Edits cells in Jupyter notebook files.
​
WebFetch
Tool name:
WebFetch
type
WebFetchInput
=
{
url
:
string
;
prompt
:
string
;
};
Fetches content from a URL and processes it with an AI model.
​
WebSearch
Tool name:
WebSearch
type
WebSearchInput
=
{
query
:
string
;
allowed_domains
?:
string
[];
blocked_domains
?:
string
[];
};
Searches the web and returns formatted results.
​
TodoWrite
Tool name:
TodoWrite
type
TodoWriteInput
=
{
todos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
};
Creates and manages a structured task list for tracking progress.
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
​
TaskCreate
Tool name:
TaskCreate
type
TaskCreateInput
=
{
subject
:
string
;
description
:
string
;
activeForm
?:
string
;
metadata
?:
Record
<
string
,
unknown
>;
};
Creates a single task and returns its assigned ID.
​
TaskUpdate
Tool name:
TaskUpdate
type
TaskUpdateInput
=
{
taskId
:
string
;
status
?:
"pending"
|
"in_progress"
|
"completed"
|
"deleted"
;
subject
?:
string
;
description
?:
string
;
activeForm
?:
string
;
addBlocks
?:
string
[];
addBlockedBy
?:
string
[];
owner
?:
string
;
metadata
?:
Record
<
string
,
unknown
>;
};
Patches one task by ID. Set
status
to
"deleted"
to remove it.
​
TaskGet
Tool name:
TaskGet
type
TaskGetInput
=
{
taskId
:
string
;
};
Returns full details for one task, or
null
when the ID is not found.
​
TaskList
Tool name:
TaskList
type
TaskListInput
=
{};
Returns a snapshot of all tasks in the current list.
​
ExitPlanMode
Tool name:
ExitPlanMode
type
ExitPlanModeInput
=
{
allowedPrompts
?:
Array
<{
tool
:
"Bash"
;
prompt
:
string
;
}>;
};
Exits planning mode. Optionally specifies prompt-based permissions needed to implement the plan.
​
ListMcpResources
Tool name:
ListMcpResources
type
ListMcpResourcesInput
=
{
server
?:
string
;
};
Lists available MCP resources from connected servers.
​
ReadMcpResource
Tool name:
ReadMcpResource
type
ReadMcpResourceInput
=
{
server
:
string
;
uri
:
string
;
};
Reads a specific MCP resource from a server.
​
EnterWorktree
Tool name:
EnterWorktree
type
EnterWorktreeInput
=
{
name
?:
string
;
path
?:
string
;
};
Creates and enters a temporary git worktree for isolated work. Pass
path
to switch into an existing worktree of the current repository instead of creating a new one.
name
and
path
are mutually exclusive.
​
Tool Output Types
Documentation of output schemas for all built-in Claude Code tools. These types are exported from
@anthropic-ai/claude-agent-sdk
and represent the actual response data returned by each tool.
​
ToolOutputSchemas
Union of all tool output types.
type
ToolOutputSchemas
=
|
AgentOutput
|
AskUserQuestionOutput
|
BashOutput
|
EnterWorktreeOutput
|
ExitPlanModeOutput
|
FileEditOutput
|
FileReadOutput
|
FileWriteOutput
|
GlobOutput
|
GrepOutput
|
ListMcpResourcesOutput
|
MonitorOutput
|
NotebookEditOutput
|
ReadMcpResourceOutput
|
TaskCreateOutput
|
TaskGetOutput
|
TaskListOutput
|
TaskStopOutput
|
TaskUpdateOutput
|
TodoWriteOutput
|
WebFetchOutput
|
WebSearchOutput
;
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
type
AgentOutput
=
|
{
status
:
"completed"
;
agentId
:
string
;
content
:
Array
<{
type
:
"text"
;
text
:
string
}>;
totalToolUseCount
:
number
;
totalDurationMs
:
number
;
totalTokens
:
number
;
usage
:
{
input_tokens
:
number
;
output_tokens
:
number
;
cache_creation_input_tokens
:
number
|
null
;
cache_read_input_tokens
:
number
|
null
;
server_tool_use
:
{
web_search_requests
:
number
;
web_fetch_requests
:
number
;
}
|
null
;
service_tier
:
(
"standard"
|
"priority"
|
"batch"
)
|
null
;
cache_creation
:
{
ephemeral_1h_input_tokens
:
number
;
ephemeral_5m_input_tokens
:
number
;
}
|
null
;
};
prompt
:
string
;
}
|
{
status
:
"async_launched"
;
agentId
:
string
;
description
:
string
;
prompt
:
string
;
outputFile
:
string
;
canReadOutputFile
?:
boolean
;
}
|
{
status
:
"sub_agent_entered"
;
description
:
string
;
message
:
string
;
};
Returns the result from the subagent. Discriminated on the
status
field:
"completed"
for finished tasks,
"async_launched"
for background tasks, and
"sub_agent_entered"
for interactive subagents.
​
AskUserQuestion
Tool name:
AskUserQuestion
type
AskUserQuestionOutput
=
{
questions
:
Array
<{
question
:
string
;
header
:
string
;
options
:
Array
<{
label
:
string
;
description
:
string
;
preview
?:
string
}>;
multiSelect
:
boolean
;
}>;
answers
:
Record
<
string
,
string
>;
};
Returns the questions asked and the user’s answers.
​
Bash
Tool name:
Bash
type
BashOutput
=
{
stdout
:
string
;
stderr
:
string
;
rawOutputPath
?:
string
;
interrupted
:
boolean
;
isImage
?:
boolean
;
backgroundTaskId
?:
string
;
backgroundedByUser
?:
boolean
;
dangerouslyDisableSandbox
?:
boolean
;
returnCodeInterpretation
?:
string
;
structuredContent
?:
unknown
[];
persistedOutputPath
?:
string
;
persistedOutputSize
?:
number
;
};
Returns command output with stdout/stderr split. Background commands include a
backgroundTaskId
.
​
Monitor
Tool name:
Monitor
type
MonitorOutput
=
{
taskId
:
string
;
timeoutMs
:
number
;
persistent
?:
boolean
;
};
Returns the background task ID for the running monitor. Use this ID with
TaskStop
to cancel the watch early.
​
Edit
Tool name:
Edit
type
FileEditOutput
=
{
filePath
:
string
;
oldString
:
string
;
newString
:
string
;
originalFile
:
string
;
structuredPatch
:
Array
<{
oldStart
:
number
;
oldLines
:
number
;
newStart
:
number
;
newLines
:
number
;
lines
:
string
[];
}>;
userModified
:
boolean
;
replaceAll
:
boolean
;
gitDiff
?:
{
filename
:
string
;
status
:
"modified"
|
"added"
;
additions
:
number
;
deletions
:
number
;
changes
:
number
;
patch
:
string
;
};
};
Returns the structured diff of the edit operation.
​
Read
Tool name:
Read
type
FileReadOutput
=
|
{
type
:
"text"
;
file
:
{
filePath
:
string
;
content
:
string
;
numLines
:
number
;
startLine
:
number
;
totalLines
:
number
;
};
}
|
{
type
:
"image"
;
file
:
{
base64
:
string
;
type
:
"image/jpeg"
|
"image/png"
|
"image/gif"
|
"image/webp"
;
originalSize
:
number
;
dimensions
?:
{
originalWidth
?:
number
;
originalHeight
?:
number
;
displayWidth
?:
number
;
displayHeight
?:
number
;
};
};
}
|
{
type
:
"notebook"
;
file
:
{
filePath
:
string
;
cells
:
unknown
[];
};
}
|
{
type
:
"pdf"
;
file
:
{
filePath
:
string
;
base64
:
string
;
originalSize
:
number
;
};
}
|
{
type
:
"parts"
;
file
:
{
filePath
:
string
;
originalSize
:
number
;
count
:
number
;
outputDir
:
string
;
};
};
Returns file contents in a format appropriate to the file type. Discriminated on the
type
field.
​
Write
Tool name:
Write
type
FileWriteOutput
=
{
type
:
"create"
|
"update"
;
filePath
:
string
;
content
:
string
;
structuredPatch
:
Array
<{
oldStart
:
number
;
oldLines
:
number
;
newStart
:
number
;
newLines
:
number
;
lines
:
string
[];
}>;
originalFile
:
string
|
null
;
gitDiff
?:
{
filename
:
string
;
status
:
"modified"
|
"added"
;
additions
:
number
;
deletions
:
number
;
changes
:
number
;
patch
:
string
;
};
};
Returns the write result with structured diff information.
​
Glob
Tool name:
Glob
type
GlobOutput
=
{
durationMs
:
number
;
numFiles
:
number
;
filenames
:
string
[];
truncated
:
boolean
;
};
Returns file paths matching the glob pattern, sorted by modification time.
​
Grep
Tool name:
Grep
type
GrepOutput
=
{
mode
?:
"content"
|
"files_with_matches"
|
"count"
;
numFiles
:
number
;
filenames
:
string
[];
content
?:
string
;
numLines
?:
number
;
numMatches
?:
number
;
appliedLimit
?:
number
;
appliedOffset
?:
number
;
};
Returns search results. The shape varies by
mode
: file list, content with matches, or match counts.
​
TaskStop
Tool name:
TaskStop
type
TaskStopOutput
=
{
message
:
string
;
task_id
:
string
;
task_type
:
string
;
command
?:
string
;
};
Returns confirmation after stopping the background task.
​
NotebookEdit
Tool name:
NotebookEdit
type
NotebookEditOutput
=
{
new_source
:
string
;
cell_id
?:
string
;
cell_type
:
"code"
|
"markdown"
;
language
:
string
;
edit_mode
:
string
;
error
?:
string
;
notebook_path
:
string
;
original_file
:
string
;
updated_file
:
string
;
};
Returns the result of the notebook edit with original and updated file contents.
​
WebFetch
Tool name:
WebFetch
type
WebFetchOutput
=
{
bytes
:
number
;
code
:
number
;
codeText
:
string
;
result
:
string
;
durationMs
:
number
;
url
:
string
;
};
Returns the fetched content with HTTP status and metadata.
​
WebSearch
Tool name:
WebSearch
type
WebSearchOutput
=
{
query
:
string
;
results
:
Array
<
|
{
tool_use_id
:
string
;
content
:
Array
<{
title
:
string
;
url
:
string
}>;
}
|
string
>;
durationSeconds
:
number
;
};
Returns search results from the web.
​
TodoWrite
Tool name:
TodoWrite
type
TodoWriteOutput
=
{
oldTodos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
newTodos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
};
Returns the previous and updated task lists.
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
​
TaskCreate
Tool name:
TaskCreate
type
TaskCreateOutput
=
{
task
:
{
id
:
string
;
subject
:
string
;
};
};
Returns the created task with its assigned ID.
​
TaskUpdate
Tool name:
TaskUpdate
type
TaskUpdateOutput
=
{
success
:
boolean
;
taskId
:
string
;
updatedFields
:
string
[];
error
?:
string
;
statusChange
?:
{
from
:
string
;
to
:
string
;
};
};
Returns the update result, including which fields changed.
​
TaskGet
Tool name:
TaskGet
type
TaskGetOutput
=
{
task
:
{
id
:
string
;
subject
:
string
;
description
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
blocks
:
string
[];
blockedBy
:
string
[];
}
|
null
;
};
Returns the full task record, or
null
when the ID is not found.
​
TaskList
Tool name:
TaskList
type
TaskListOutput
=
{
tasks
:
Array
<{
id
:
string
;
subject
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
owner
?:
string
;
blockedBy
:
string
[];
}>;
};
Returns a snapshot of all tasks in the current list.
​
ExitPlanMode
Tool name:
ExitPlanMode
type
ExitPlanModeOutput
=
{
plan
:
string
|
null
;
isAgent
:
boolean
;
filePath
?:
string
;
hasTaskTool
?:
boolean
;
awaitingLeaderApproval
?:
boolean
;
requestId
?:
string
;
};
Returns the plan state after exiting plan mode.
​
ListMcpResources
Tool name:
ListMcpResources
type
ListMcpResourcesOutput
=
Array
<{
uri
:
string
;
name
:
string
;
mimeType
?:
string
;
description
?:
string
;
server
:
string
;
}>;
Returns an array of available MCP resources.
​
ReadMcpResource
Tool name:
ReadMcpResource
type
ReadMcpResourceOutput
=
{
contents
:
Array
<{
uri
:
string
;
mimeType
?:
string
;
text
?:
string
;
}>;
};
Returns the contents of the requested MCP resource.
​
EnterWorktree
Tool name:
EnterWorktree
type
EnterWorktreeOutput
=
{
worktreePath
:
string
;
worktreeBranch
?:
string
;
message
:
string
;
};
Returns information about the git worktree.
​
Permission Types
​
PermissionUpdate
Operations for updating permissions.
type
PermissionUpdate
=
|
{
type
:
"addRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"replaceRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"removeRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"setMode"
;
mode
:
PermissionMode
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"addDirectories"
;
directories
:
string
[];
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"removeDirectories"
;
directories
:
string
[];
destination
:
PermissionUpdateDestination
;
};
​
PermissionBehavior
type
PermissionBehavior
=
"allow"
|
"deny"
|
"ask"
;
​
PermissionUpdateDestination
type
PermissionUpdateDestination
=
|
"userSettings"
// Global user settings
|
"projectSettings"
// Per-directory project settings
|
"localSettings"
// Gitignored local settings
|
"session"
// Current session only
|
"cliArg"
;
// CLI argument
​
PermissionRuleValue
type
PermissionRuleValue
=
{
toolName
:
string
;
ruleContent
?:
string
;
};
​
Other Types
​
ApiKeySource
type
ApiKeySource
=
"user"
|
"project"
|
"org"
|
"temporary"
|
"oauth"
;
​
SdkBeta
Available beta features that can be enabled via the
betas
option. See
Beta headers
for more information.
type
SdkBeta
=
"context-1m-2025-08-07"
;
The
context-1m-2025-08-07
beta is retired as of April 30, 2026. Passing this value with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to
Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7
, which include 1M context at standard pricing with no beta header required.
​
SlashCommand
Information about an available slash command.
type
SlashCommand
=
{
name
:
string
;
description
:
string
;
argumentHint
:
string
;
aliases
?:
string
[];
};
​
ModelInfo
Information about an available model.
type
ModelInfo
=
{
value
:
string
;
displayName
:
string
;
description
:
string
;
supportsEffort
?:
boolean
;
supportedEffortLevels
?:
(
"low"
|
"medium"
|
"high"
|
"xhigh"
|
"max"
)[];
supportsAdaptiveThinking
?:
boolean
;
supportsFastMode
?:
boolean
;
};
​
AgentInfo
Information about an available subagent that can be invoked via the Agent tool.
type
AgentInfo
=
{
name
:
string
;
description
:
string
;
model
?:
string
;
};
Field
Type
Description
name
string
Agent type identifier (e.g.,
"Explore"
,
"general-purpose"
)
description
string
Description of when to use this agent
model
string | undefined
Model alias this agent uses. If omitted, inherits the parent’s model
​
McpServerStatus
Status of a connected MCP server.
type
McpServerStatus
=
{
name
:
string
;
status
:
"connected"
|
"failed"
|
"needs-auth"
|
"pending"
|
"disabled"
;
serverInfo
?:
{
name
:
string
;
version
:
string
;
};
error
?:
string
;
config
?:
McpServerStatusConfig
;
scope
?:
string
;
tools
?:
{
name
:
string
;
description
?:
string
;
annotations
?:
{
readOnly
?:
boolean
;
destructive
?:
boolean
;
openWorld
?:
boolean
;
};
}[];
};
​
McpServerStatusConfig
The configuration of an MCP server as reported by
mcpServerStatus()
. This is the union of all MCP server transport types.
type
McpServerStatusConfig
=
|
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfig
|
McpClaudeAIProxyServerConfig
;
See
McpServerConfig
for details on each transport type.
​
AccountInfo
Account information for the authenticated user.
type
AccountInfo
=
{
email
?:
string
;
organization
?:
string
;
subscriptionType
?:
string
;
tokenSource
?:
string
;
apiKeySource
?:
string
;
};
​
ModelUsage
Per-model usage statistics returned in result messages. The
costUSD
value is a client-side estimate. See
Track cost and usage
for billing caveats.
type
ModelUsage
=
{
inputTokens
:
number
;
outputTokens
:
number
;
cacheReadInputTokens
:
number
;
cacheCreationInputTokens
:
number
;
webSearchRequests
:
number
;
costUSD
:
number
;
contextWindow
:
number
;
maxOutputTokens
:
number
;
};
​
ConfigScope
type
ConfigScope
=
"local"
|
"user"
|
"project"
;
​
NonNullableUsage
A version of
Usage
with all nullable fields made non-nullable.
type
NonNullableUsage
=
{
[
K
in
keyof
Usage
]
:
NonNullable
<
Usage
[
K
]>;
};
​
Usage
Token usage statistics (from
@anthropic-ai/sdk
).
type
Usage
=
{
input_tokens
:
number
|
null
;
output_tokens
:
number
|
null
;
cache_creation_input_tokens
?:
number
|
null
;
cache_read_input_tokens
?:
number
|
null
;
};
​
CallToolResult
MCP tool result type (from
@modelcontextprotocol/sdk/types.js
).
structuredContent
is a JSON object that can be returned alongside
content
, including image blocks. See
Return structured data
.
type
CallToolResult
=
{
content
:
Array
<{
type
:
"text"
|
"image"
|
"resource"
;
// Additional fields vary by type
}>;
structuredContent
?:
Record
<
string
,
unknown
>;
isError
?:
boolean
;
};
​
ThinkingConfig
Controls Claude’s thinking/reasoning behavior. Takes precedence over the deprecated
maxThinkingTokens
.
type
ThinkingConfig
=
|
{
type
:
"adaptive"
}
// The model determines when and how much to reason (Opus 4.6+)
|
{
type
:
"enabled"
;
budgetTokens
?:
number
}
// Fixed thinking token budget
|
{
type
:
"disabled"
};
// No extended thinking
​
SpawnedProcess
Interface for custom process spawning (used with
spawnClaudeCodeProcess
option).
ChildProcess
already satisfies this interface.
interface
SpawnedProcess
{
stdin
:
Writable
;
stdout
:
Readable
;
readonly
killed
:
boolean
;
readonly
exitCode
:
number
|
null
;
kill
(
signal
:
NodeJS
.
Signals
)
:
boolean
;
on
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
on
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
once
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
once
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
off
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
off
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
}
​
SpawnOptions
Options passed to the custom spawn function.
interface
SpawnOptions
{
command
:
string
;
args
:
string
[];
cwd
?:
string
;
env
:
Record
<
string
,
string
|
undefined
>;
signal
:
AbortSignal
;
}
​
McpSetServersResult
Result of a
setMcpServers()
operation.
type
McpSetServersResult
=
{
added
:
string
[];
removed
:
string
[];
errors
:
Record
<
string
,
string
>;
};
​
RewindFilesResult
Result of a
rewindFiles()
operation.
type
RewindFilesResult
=
{
canRewind
:
boolean
;
error
?:
string
;
filesChanged
?:
string
[];
insertions
?:
number
;
deletions
?:
number
;
};
​
SDKStatusMessage
Status update message (e.g., compacting).
type
SDKStatusMessage
=
{
type
:
"system"
;
subtype
:
"status"
;
status
:
"compacting"
|
null
;
permissionMode
?:
PermissionMode
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskNotificationMessage
Notification when a background task completes, fails, or is stopped. Background tasks include
run_in_background
Bash commands,
Monitor
watches, and background subagents.
type
SDKTaskNotificationMessage
=
{
type
:
"system"
;
subtype
:
"task_notification"
;
task_id
:
string
;
tool_use_id
?:
string
;
status
:
"completed"
|
"failed"
|
"stopped"
;
output_file
:
string
;
summary
:
string
;
usage
?:
{
total_tokens
:
number
;
tool_uses
:
number
;
duration_ms
:
number
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKToolUseSummaryMessage
Summary of tool usage in a conversation.
type
SDKToolUseSummaryMessage
=
{
type
:
"tool_use_summary"
;
summary
:
string
;
preceding_tool_use_ids
:
string
[];
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookStartedMessage
Emitted when a hook begins executing.
type
SDKHookStartedMessage
=
{
type
:
"system"
;
subtype
:
"hook_started"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookProgressMessage
Emitted while a hook is running, with stdout/stderr output.
type
SDKHookProgressMessage
=
{
type
:
"system"
;
subtype
:
"hook_progress"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
stdout
:
string
;
stderr
:
string
;
output
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookResponseMessage
Emitted when a hook finishes executing.
type
SDKHookResponseMessage
=
{
type
:
"system"
;
subtype
:
"hook_response"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
output
:
string
;
stdout
:
string
;
stderr
:
string
;
exit_code
?:
number
;
outcome
:
"success"
|
"error"
|
"cancelled"
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKToolProgressMessage
Emitted periodically while a tool is executing to indicate progress.
type
SDKToolProgressMessage
=
{
type
:
"tool_progress"
;
tool_use_id
:
string
;
tool_name
:
string
;
parent_tool_use_id
:
string
|
null
;
elapsed_time_seconds
:
number
;
task_id
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKAuthStatusMessage
Emitted during authentication flows.
type
SDKAuthStatusMessage
=
{
type
:
"auth_status"
;
isAuthenticating
:
boolean
;
output
:
string
[];
error
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskStartedMessage
Emitted when a background task begins. The
task_type
field is
"local_bash"
for background Bash commands and
Monitor
watches,
"local_agent"
for subagents, or
"remote_agent"
.
type
SDKTaskStartedMessage
=
{
type
:
"system"
;
subtype
:
"task_started"
;
task_id
:
string
;
tool_use_id
?:
string
;
description
:
string
;
task_type
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskProgressMessage
Emitted periodically while a background task is running.
type
SDKTaskProgressMessage
=
{
type
:
"system"
;
subtype
:
"task_progress"
;
task_id
:
string
;
tool_use_id
?:
string
;
description
:
string
;
usage
:
{
total_tokens
:
number
;
tool_uses
:
number
;
duration_ms
:
number
;
};
last_tool_name
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskUpdatedMessage
Emitted when a background task’s state changes, such as when it transitions from
running
to
completed
. Merge
patch
into your local task map keyed by
task_id
. The
end_time
field is a Unix epoch timestamp in milliseconds, comparable with
Date.now()
.
type
SDKTaskUpdatedMessage
=
{
type
:
"system"
;
subtype
:
"task_updated"
;
task_id
:
string
;
patch
:
{
status
?:
"pending"
|
"running"
|
"completed"
|
"failed"
|
"killed"
;
description
?:
string
;
end_time
?:
number
;
total_paused_ms
?:
number
;
error
?:
string
;
is_backgrounded
?:
boolean
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKFilesPersistedEvent
Emitted when file checkpoints are persisted to disk.
type
SDKFilesPersistedEvent
=
{
type
:
"system"
;
subtype
:
"files_persisted"
;
files
:
{
filename
:
string
;
file_id
:
string
}[];
failed
:
{
filename
:
string
;
error
:
string
}[];
processed_at
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKRateLimitEvent
Emitted when the session encounters a rate limit.
type
SDKRateLimitEvent
=
{
type
:
"rate_limit_event"
;
rate_limit_info
:
{
status
:
"allowed"
|
"allowed_warning"
|
"rejected"
;
resetsAt
?:
number
;
utilization
?:
number
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKLocalCommandOutputMessage
Output from a local slash command (for example,
/voice
or
/usage
). Displayed as assistant-style text in the transcript.
type
SDKLocalCommandOutputMessage
=
{
type
:
"system"
;
subtype
:
"local_command_output"
;
content
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKPromptSuggestionMessage
Emitted after each turn when
promptSuggestions
is enabled. Contains a predicted next user prompt.
type
SDKPromptSuggestionMessage
=
{
type
:
"prompt_suggestion"
;
suggestion
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
AbortError
Custom error class for abort operations.
class
AbortError
extends
Error
{}
​
Sandbox Configuration
​
SandboxSettings
Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.
type
SandboxSettings
=
{
enabled
?:
boolean
;
autoAllowBashIfSandboxed
?:
boolean
;
excludedCommands
?:
string
[];
allowUnsandboxedCommands
?:
boolean
;
network
?:
SandboxNetworkConfig
;
filesystem
?:
SandboxFilesystemConfig
;
ignoreViolations
?:
Record
<
string
,
string
[]>;
enableWeakerNestedSandbox
?:
boolean
;
ripgrep
?:
{
command
:
string
;
args
?:
string
[] };
};
Property
Type
Default
Description
enabled
boolean
false
Enable sandbox mode for command execution
autoAllowBashIfSandboxed
boolean
true
Auto-approve bash commands when sandbox is enabled
excludedCommands
string[]
[]
Commands that always bypass sandbox restrictions (e.g.,
['docker']
). These run unsandboxed automatically without model involvement
allowUnsandboxedCommands
boolean
true
Allow the model to request running commands outside the sandbox. When
true
, the model can set
dangerouslyDisableSandbox
in tool input, which falls back to the
permissions system
network
SandboxNetworkConfig
undefined
Network-specific sandbox configuration
filesystem
SandboxFilesystemConfig
undefined
Filesystem-specific sandbox configuration for read/write restrictions
ignoreViolations
Record<string, string[]>
undefined
Map of violation categories to patterns to ignore (e.g.,
{ file: ['/tmp/*'], network: ['localhost'] }
)
enableWeakerNestedSandbox
boolean
false
Enable a weaker nested sandbox for compatibility
ripgrep
{ command: string; args?: string[] }
undefined
Custom ripgrep binary configuration for sandbox environments
​
Example usage
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Build and test my project"
,
options:
{
sandbox:
{
enabled:
true
,
autoAllowBashIfSandboxed:
true
,
network:
{
allowLocalBinding:
true
}
}
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
Unix socket security:
The
allowUnixSockets
option can grant access to powerful system services. For example, allowing
/var/run/docker.sock
effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.
​
SandboxNetworkConfig
Network-specific configuration for sandbox mode.
type
SandboxNetworkConfig
=
{
allowedDomains
?:
string
[];
deniedDomains
?:
string
[];
allowManagedDomainsOnly
?:
boolean
;
allowLocalBinding
?:
boolean
;
allowUnixSockets
?:
string
[];
allowAllUnixSockets
?:
boolean
;
httpProxyPort
?:
number
;
socksProxyPort
?:
number
;
};
Property
Type
Default
Description
allowedDomains
string[]
[]
Domain names that sandboxed processes can access
deniedDomains
string[]
[]
Domain names that sandboxed processes cannot access. Takes precedence over
allowedDomains
allowManagedDomainsOnly
boolean
false
Restrict network access to only the domains in
allowedDomains
allowLocalBinding
boolean
false
Allow processes to bind to local ports (e.g., for dev servers)
allowUnixSockets
string[]
[]
Unix socket paths that processes can access (e.g., Docker socket)
allowAllUnixSockets
boolean
false
Allow access to all Unix sockets
httpProxyPort
number
undefined
HTTP proxy port for network requests
socksProxyPort
number
undefined
SOCKS proxy port for network requests
The built-in sandbox proxy enforces
allowedDomains
based on the requested hostname and does not terminate or inspect TLS traffic, so techniques such as
domain fronting
can potentially bypass it. See
Sandboxing security limitations
for details and
Secure deployment
for configuring a TLS-terminating proxy.
​
SandboxFilesystemConfig
Filesystem-specific configuration for sandbox mode.
type
SandboxFilesystemConfig
=
{
allowWrite
?:
string
[];
denyWrite
?:
string
[];
denyRead
?:
string
[];
};
Property
Type
Default
Description
allowWrite
string[]
[]
File path patterns to allow write access to
denyWrite
string[]
[]
File path patterns to deny write access to
denyRead
string[]
[]
File path patterns to deny read access to
​
Permissions Fallback for Unsandboxed Commands
When
allowUnsandboxedCommands
is enabled, the model can request to run commands outside the sandbox by setting
dangerouslyDisableSandbox: true
in the tool input. These requests fall back to the existing permissions system, meaning your
canUseTool
handler is invoked, allowing you to implement custom authorization logic.
excludedCommands
vs
allowUnsandboxedCommands
:
excludedCommands
: A static list of commands that always bypass the sandbox automatically (e.g.,
['docker']
). The model has no control over this.
allowUnsandboxedCommands
: Lets the model decide at runtime whether to request unsandboxed execution by setting
dangerouslyDisableSandbox: true
in the tool input.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Deploy my application"
,
options:
{
sandbox:
{
enabled:
true
,
allowUnsandboxedCommands:
true
// Model can request unsandboxed execution
},
permissionMode:
"default"
,
canUseTool
:
async
(
tool
,
input
)
=>
{
// Check if the model is requesting to bypass the sandbox
if
(
tool
===
"Bash"
&&
input
.
dangerouslyDisableSandbox
) {
// The model is requesting to run this command outside the sandbox
console
.
log
(
`Unsandboxed command requested:
${
input
.
command
}
`
);
if
(
isCommandAuthorized
(
input
.
command
)) {
return
{
behavior:
"allow"
as
const
,
updatedInput:
input
};
}
return
{
behavior:
"deny"
as
const
,
message:
"Command not authorized for unsandboxed execution"
};
}
return
{
behavior:
"allow"
as
const
,
updatedInput:
input
};
}
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
This pattern enables you to:
Audit model requests:
Log when the model requests unsandboxed execution
Implement allowlists:
Only permit specific commands to run unsandboxed
Add approval workflows:
Require explicit authorization for privileged operations
Commands running with
dangerouslyDisableSandbox: true
have full system access. Ensure your
canUseTool
handler validates these requests carefully.
If
permissionMode
is set to
bypassPermissions
and
allowUnsandboxedCommands
is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.
​
See also
SDK overview
- General SDK concepts
Python SDK reference
- Python SDK documentation
CLI reference
- Command-line interface
Common workflows
- Step-by-step guides
Was this page helpful?
Yes
No
Securely deploying AI agents
TypeScript V2 (deprecated)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/typescript" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - TypeScript
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
SDK references
Agent SDK reference - TypeScript
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
​
Installation
npm
install
@anthropic-ai/claude-agent-sdk
The SDK bundles a native Claude Code binary for your platform as an optional dependency such as
@anthropic-ai/claude-agent-sdk-darwin-arm64
. You don’t need to install Claude Code separately. If your package manager skips optional dependencies, the SDK throws
Native CLI binary for <platform> not found
; set
pathToClaudeCodeExecutable
to a separately installed
claude
binary instead.
​
Functions
​
query()
The primary function for interacting with Claude Code. Creates an async generator that streams messages as they arrive.
function
query
({
prompt
,
options
}
:
{
prompt
:
string
|
AsyncIterable
<
SDKUserMessage
>;
options
?:
Options
;
})
:
Query
;
​
Parameters
Parameter
Type
Description
prompt
string | AsyncIterable<
SDKUserMessage
>
The input prompt as a string or async iterable for streaming mode
options
Options
Optional configuration object (see Options type below)
​
Returns
Returns a
Query
object that extends
AsyncGenerator<
SDKMessage
, void>
with additional methods.
​
startup()
Pre-warms the CLI subprocess by spawning it and completing the initialize handshake before a prompt is available. The returned
WarmQuery
handle accepts a prompt later and writes it to an already-ready process, so the first
query()
call resolves without paying subprocess spawn and initialization cost inline.
function
startup
(
params
?:
{
options
?:
Options
;
initializeTimeoutMs
?:
number
;
})
:
Promise
<
WarmQuery
>;
​
Parameters
Parameter
Type
Description
options
Options
Optional configuration object. Same as the
options
parameter to
query()
initializeTimeoutMs
number
Maximum time in milliseconds to wait for subprocess initialization. Defaults to
60000
. If initialization does not complete in time, the promise rejects with a timeout error
​
Returns
Returns a
Promise<
WarmQuery
>
that resolves once the subprocess has spawned and completed its initialize handshake.
​
Example
Call
startup()
early, for example on application boot, then call
.query()
on the returned handle once a prompt is ready. This moves subprocess spawn and initialization out of the critical path.
import
{
startup
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Pay startup cost upfront
const
warm
=
await
startup
({
options:
{
maxTurns:
3
} });
// Later, when a prompt is ready, this is immediate
for
await
(
const
message
of
warm
.
query
(
"What files are here?"
)) {
console
.
log
(
message
);
}
​
tool()
Creates a type-safe MCP tool definition for use with SDK MCP servers.
function
tool
<
Schema
extends
AnyZodRawShape
>(
name
:
string
,
description
:
string
,
inputSchema
:
Schema
,
handler
:
(
args
:
InferShape
<
Schema
>,
extra
:
unknown
)
=>
Promise
<
CallToolResult
>,
extras
?:
{
annotations
?:
ToolAnnotations
}
)
:
SdkMcpToolDefinition
<
Schema
>;
​
Parameters
Parameter
Type
Description
name
string
The name of the tool
description
string
A description of what the tool does
inputSchema
Schema extends AnyZodRawShape
Zod schema defining the tool’s input parameters (supports both Zod 3 and Zod 4)
handler
(args, extra) => Promise<
CallToolResult
>
Async function that executes the tool logic
extras
{ annotations?:
ToolAnnotations
}
Optional MCP tool annotations providing behavioral hints to clients
​
ToolAnnotations
Re-exported from
@modelcontextprotocol/sdk/types.js
. All fields are optional hints; clients should not rely on them for security decisions.
Field
Type
Default
Description
title
string
undefined
Human-readable title for the tool
readOnlyHint
boolean
false
If
true
, the tool does not modify its environment
destructiveHint
boolean
true
If
true
, the tool may perform destructive updates (only meaningful when
readOnlyHint
is
false
)
idempotentHint
boolean
false
If
true
, repeated calls with the same arguments have no additional effect (only meaningful when
readOnlyHint
is
false
)
openWorldHint
boolean
true
If
true
, the tool interacts with external entities (for example, web search). If
false
, the tool’s domain is closed (for example, a memory tool)
import
{
tool
}
from
"@anthropic-ai/claude-agent-sdk"
;
import
{
z
}
from
"zod"
;
const
searchTool
=
tool
(
"search"
,
"Search the web"
,
{
query:
z
.
string
() },
async
({
query
})
=>
{
return
{
content:
[{
type:
"text"
,
text:
`Results for:
${
query
}
`
}] };
},
{
annotations:
{
readOnlyHint:
true
,
openWorldHint:
true
} }
);
​
createSdkMcpServer()
Creates an MCP server instance that runs in the same process as your application.
function
createSdkMcpServer
(
options
:
{
name
:
string
;
version
?:
string
;
tools
?:
Array
<
SdkMcpToolDefinition
<
any
>>;
})
:
McpSdkServerConfigWithInstance
;
​
Parameters
Parameter
Type
Description
options.name
string
The name of the MCP server
options.version
string
Optional version string
options.tools
Array<SdkMcpToolDefinition>
Array of tool definitions created with
tool()
​
listSessions()
Discovers and lists past sessions with light metadata. Filter by project directory or list sessions across all projects.
function
listSessions
(
options
?:
ListSessionsOptions
)
:
Promise
<
SDKSessionInfo
[]>;
​
Parameters
Parameter
Type
Default
Description
options.dir
string
undefined
Directory to list sessions for. When omitted, returns sessions across all projects
options.limit
number
undefined
Maximum number of sessions to return
options.includeWorktrees
boolean
true
When
dir
is inside a git repository, include sessions from all worktree paths
​
Return type:
SDKSessionInfo
Property
Type
Description
sessionId
string
Unique session identifier (UUID)
summary
string
Display title: custom title, auto-generated summary, or first prompt
lastModified
number
Last modified time in milliseconds since epoch
fileSize
number | undefined
Session file size in bytes. Only populated for local JSONL storage
customTitle
string | undefined
User-set session title (via
/rename
)
firstPrompt
string | undefined
First meaningful user prompt in the session
gitBranch
string | undefined
Git branch at the end of the session
cwd
string | undefined
Working directory for the session
tag
string | undefined
User-set session tag (see
tagSession()
)
createdAt
number | undefined
Creation time in milliseconds since epoch, from the first entry’s timestamp
​
Example
Print the 10 most recent sessions for a project. Results are sorted by
lastModified
descending, so the first item is the newest. Omit
dir
to search across all projects.
import
{
listSessions
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
sessions
=
await
listSessions
({
dir:
"/path/to/project"
,
limit:
10
});
for
(
const
session
of
sessions
) {
console
.
log
(
`
${
session
.
summary
}
(
${
session
.
sessionId
}
)`
);
}
​
getSessionMessages()
Reads user and assistant messages from a past session transcript.
function
getSessionMessages
(
sessionId
:
string
,
options
?:
GetSessionMessagesOptions
)
:
Promise
<
SessionMessage
[]>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
Session UUID to read (see
listSessions()
)
options.dir
string
undefined
Project directory to find the session in. When omitted, searches all projects
options.limit
number
undefined
Maximum number of messages to return
options.offset
number
undefined
Number of messages to skip from the start
​
Return type:
SessionMessage
Property
Type
Description
type
"user" | "assistant"
Message role
uuid
string
Unique message identifier
session_id
string
Session this message belongs to
message
unknown
Raw message payload from the transcript
parent_tool_use_id
null
Reserved
​
Example
import
{
listSessions
,
getSessionMessages
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
[
latest
]
=
await
listSessions
({
dir:
"/path/to/project"
,
limit:
1
});
if
(
latest
) {
const
messages
=
await
getSessionMessages
(
latest
.
sessionId
, {
dir:
"/path/to/project"
,
limit:
20
});
for
(
const
msg
of
messages
) {
console
.
log
(
`[
${
msg
.
type
}
]
${
msg
.
uuid
}
`
);
}
}
​
getSessionInfo()
Reads metadata for a single session by ID without scanning the full project directory.
function
getSessionInfo
(
sessionId
:
string
,
options
?:
GetSessionInfoOptions
)
:
Promise
<
SDKSessionInfo
|
undefined
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to look up
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
Returns
SDKSessionInfo
, or
undefined
if the session is not found.
​
renameSession()
Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins.
function
renameSession
(
sessionId
:
string
,
title
:
string
,
options
?:
SessionMutationOptions
)
:
Promise
<
void
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to rename
title
string
required
New title. Must be non-empty after trimming whitespace
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
​
tagSession()
Tags a session. Pass
null
to clear the tag. Repeated calls are safe; the most recent tag wins.
function
tagSession
(
sessionId
:
string
,
tag
:
string
|
null
,
options
?:
SessionMutationOptions
)
:
Promise
<
void
>;
​
Parameters
Parameter
Type
Default
Description
sessionId
string
required
UUID of the session to tag
tag
string | null
required
Tag string, or
null
to clear
options.dir
string
undefined
Project directory path. When omitted, searches all project directories
​
resolveSettings()
Resolves the effective Claude Code settings for a given directory using the same merge engine as the CLI, without spawning the Claude CLI. Use it to inspect what configuration a
query()
call would see before invoking one.
This function is alpha and its API may change before stabilization. It reads MDM sources, including macOS plist and Windows HKLM/HKCU, for parity with CLI startup, but does not execute the admin-configured
policyHelper
subprocess. The
permissions.defaultMode
field is returned as-is from all tiers including project settings. The trust filter the CLI applies before honoring escalating permission modes is not applied.
function
resolveSettings
(
options
?:
ResolveSettingsOptions
)
:
Promise
<
ResolvedSettings
>;
​
Parameters
resolveSettings()
accepts a single options object. All fields are optional.
Parameter
Type
Default
Description
options.cwd
string
process.cwd()
Directory to resolve project and local settings relative to
options.settingSources
SettingSource
[]
All sources
Which filesystem sources to load. Pass
[]
to skip user, project, and local settings. Managed policy settings load in all cases
options.managedSettings
Settings
undefined
Restrictive policy-tier settings supplied by the embedding host. Dropped by default when an admin-deployed managed tier is present; merged under that tier when
parentSettingsBehavior
is
"merge"
. Non-restrictive keys such as
model
are silently dropped so this option can tighten managed policy but not loosen it
options.serverManagedSettings
Settings
undefined
Server-managed settings payload from
/api/claude_code/settings
. Non-restrictive keys pass through unfiltered
​
Return type:
ResolvedSettings
resolveSettings()
returns an object describing the merged settings and the source that contributed each key.
Property
Type
Description
effective
Settings
Merged settings after applying all enabled sources in precedence order
provenance
Partial<Record<keyof Settings, ProvenanceEntry>>
For each top-level key in
effective
, which source supplied the value
sources
Array<{ source, settings, path?, policyOrigin? }>
Per-source raw settings, ordered from lowest to highest precedence
​
Example
The example below resolves settings for a project directory and prints the source that controls the cleanup period.
import
{
resolveSettings
}
from
"@anthropic-ai/claude-agent-sdk"
;
const
{
effective
,
provenance
}
=
await
resolveSettings
({
cwd:
"/path/to/project"
,
settingSources:
[
"user"
,
"project"
,
"local"
],
});
console
.
log
(
`Cleanup period:
${
effective
.
cleanupPeriodDays
}
days`
);
console
.
log
(
`Set by:
${
provenance
.
cleanupPeriodDays
?.
source
}
`
);
​
Types
​
Options
Configuration object for the
query()
function.
Property
Type
Default
Description
abortController
AbortController
new AbortController()
Controller for cancelling operations
additionalDirectories
string[]
[]
Additional directories Claude can access
agent
string
undefined
Agent name for the main thread. The agent must be defined in the
agents
option or in settings
agents
Record<string, [
AgentDefinition
](#agentdefinition)>
undefined
Programmatically define subagents
allowDangerouslySkipPermissions
boolean
false
Enable bypassing permissions. Required when using
permissionMode: 'bypassPermissions'
allowedTools
string[]
[]
Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to
permissionMode
and
canUseTool
. Use
disallowedTools
to block tools. See
Permissions
betas
SdkBeta
[]
[]
Enable beta features
canUseTool
CanUseTool
undefined
Custom permission function for tool usage
continue
boolean
false
Continue the most recent conversation
cwd
string
process.cwd()
Current working directory
debug
boolean
false
Enable debug mode for the Claude Code process
debugFile
string
undefined
Write debug logs to a specific file path. Implicitly enables debug mode
disallowedTools
string[]
[]
Tools to always deny. Deny rules are checked first and override
allowedTools
and
permissionMode
(including
bypassPermissions
)
effort
'low' | 'medium' | 'high' | 'xhigh' | 'max'
'high'
Controls how much effort Claude puts into its response. Works with adaptive thinking to guide thinking depth
enableFileCheckpointing
boolean
false
Enable file change tracking for rewinding. See
File checkpointing
env
Record<string, string | undefined>
process.env
Environment variables. See
Environment variables
for variables the underlying CLI reads, and
Handle slow or stalled API responses
for timeout-related variables. Set
CLAUDE_AGENT_SDK_CLIENT_APP
to identify your app in the User-Agent header
executable
'bun' | 'deno' | 'node'
Auto-detected
JavaScript runtime to use
executableArgs
string[]
[]
Arguments to pass to the executable
extraArgs
Record<string, string | null>
{}
Additional arguments
fallbackModel
string
undefined
Model to use if primary fails
forkSession
boolean
false
When resuming with
resume
, fork to a new session ID instead of continuing the original session
hooks
Partial<Record<
HookEvent
,
HookCallbackMatcher
[]>>
{}
Hook callbacks for events
includeHookEvents
boolean
false
Include hook lifecycle events in the message stream as
SDKHookStartedMessage
,
SDKHookProgressMessage
, and
SDKHookResponseMessage
includePartialMessages
boolean
false
Include partial message events
maxBudgetUsd
number
undefined
Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as
total_cost_usd
; see
Track cost and usage
for accuracy caveats
maxThinkingTokens
number
undefined
Deprecated:
Use
thinking
instead. Maximum tokens for thinking process
maxTurns
number
undefined
Maximum agentic turns (tool-use round trips)
mcpServers
Record<string, [
McpServerConfig
](#mcpserverconfig)>
{}
MCP server configurations
model
string
Default from CLI
Claude model to use
outputFormat
{ type: 'json_schema', schema: JSONSchema }
undefined
Define output format for agent results. See
Structured outputs
for details
outputStyle
string
undefined
Name of an
output style
to activate for the session. The style must exist in a loaded
settingSources
location, such as
.claude/output-styles/
. See
Activate an output style
pathToClaudeCodeExecutable
string
Auto-resolved from bundled native binary
Path to Claude Code executable. Only needed if optional dependencies were skipped during install or your platform isn’t in the supported set
permissionMode
PermissionMode
'default'
Permission mode for the session
permissionPromptToolName
string
undefined
MCP tool name for permission prompts
persistSession
boolean
true
When
false
, disables session persistence to disk. Sessions cannot be resumed later
plugins
SdkPluginConfig
[]
[]
Load custom plugins from local paths. See
Plugins
for details
promptSuggestions
boolean
false
Enable prompt suggestions. Emits a
prompt_suggestion
message after each turn with a predicted next user prompt
resume
string
undefined
Session ID to resume
resumeSessionAt
string
undefined
Resume session at a specific message UUID
sandbox
SandboxSettings
undefined
Configure sandbox behavior programmatically. See
Sandbox settings
for details
sessionId
string
Auto-generated
Use a specific UUID for the session instead of auto-generating one
sessionStore
SessionStore
undefined
Mirror session transcripts to an external backend so any host can resume them. See
Persist sessions to external storage
settings
string | Settings
undefined
Inline
settings
object or path to a settings file. Populates the flag-settings layer in the
precedence order
. Change at runtime with
applyFlagSettings()
settingSources
SettingSource
[]
CLI defaults (all sources)
Control which filesystem settings to load. Pass
[]
to disable user, project, and local settings. Managed policy settings load regardless. See
Use Claude Code features
skills
string[] | 'all'
undefined
Skills available to the session. Pass
'all'
to enable every discovered skill, or a list of skill names. When set, the SDK enables the Skill tool automatically without listing it in
allowedTools
. See
Skills
spawnClaudeCodeProcess
(options: SpawnOptions) => SpawnedProcess
undefined
Custom function to spawn the Claude Code process. Use to run Claude Code in VMs, containers, or remote environments
stderr
(data: string) => void
undefined
Callback for stderr output
strictMcpConfig
boolean
false
Enforce strict MCP validation
systemPrompt
string | { type: 'preset'; preset: 'claude_code'; append?: string; excludeDynamicSections?: boolean }
undefined
(minimal prompt)
System prompt configuration. Pass a string for custom prompt, or
{ type: 'preset', preset: 'claude_code' }
to use Claude Code’s system prompt. When using the preset object form, add
append
to extend it with additional instructions, and set
excludeDynamicSections: true
to move per-session context into the first user message for
better prompt-cache reuse across machines
thinking
ThinkingConfig
{ type: 'adaptive' }
for supported models
Controls Claude’s thinking/reasoning behavior. See
ThinkingConfig
for options
toolConfig
ToolConfig
undefined
Configuration for built-in tool behavior. See
ToolConfig
for details
tools
string[] | { type: 'preset'; preset: 'claude_code' }
undefined
Tool configuration. Pass an array of tool names or use the preset to get Claude Code’s default tools
​
Handle slow or stalled API responses
The CLI subprocess reads several environment variables that control API timeouts and stall detection. Pass them through the
env
option:
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
env:
{
...
process
.
env
,
API_TIMEOUT_MS:
"120000"
,
CLAUDE_CODE_MAX_RETRIES:
"2"
,
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS:
"120000"
,
},
},
});
API_TIMEOUT_MS
: per-request timeout on the Anthropic client, in milliseconds. Default
600000
. Applies to the main loop and all subagents.
CLAUDE_CODE_MAX_RETRIES
: maximum API retries. Default
10
. Each retry gets its own
API_TIMEOUT_MS
window, so worst-case wall time is roughly
API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)
plus backoff.
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS
: stall watchdog for subagents launched with
run_in_background
. Default
600000
. Resets on each stream event; on stall it aborts the subagent, marks the task failed, and surfaces the error to the parent with any partial result. Does not apply to synchronous subagents.
CLAUDE_ENABLE_STREAM_WATCHDOG=1
with
CLAUDE_STREAM_IDLE_TIMEOUT_MS
: aborts the request when headers have arrived but the response body stops streaming. Off by default.
CLAUDE_STREAM_IDLE_TIMEOUT_MS
defaults to
300000
and is clamped to that minimum. The aborted request goes through the normal retry path.
​
Query
object
Interface returned by the
query()
function.
interface
Query
extends
AsyncGenerator
<
SDKMessage
,
void
> {
interrupt
()
:
Promise
<
void
>;
rewindFiles
(
userMessageId
:
string
,
options
?:
{
dryRun
?:
boolean
}
)
:
Promise
<
RewindFilesResult
>;
setPermissionMode
(
mode
:
PermissionMode
)
:
Promise
<
void
>;
setModel
(
model
?:
string
)
:
Promise
<
void
>;
setMaxThinkingTokens
(
maxThinkingTokens
:
number
|
null
)
:
Promise
<
void
>;
applyFlagSettings
(
settings
:
{ [
K
in
keyof
Settings
]
?:
Settings
[
K
]
|
null
})
:
Promise
<
void
>;
initializationResult
()
:
Promise
<
SDKControlInitializeResponse
>;
supportedCommands
()
:
Promise
<
SlashCommand
[]>;
supportedModels
()
:
Promise
<
ModelInfo
[]>;
supportedAgents
()
:
Promise
<
AgentInfo
[]>;
mcpServerStatus
()
:
Promise
<
McpServerStatus
[]>;
accountInfo
()
:
Promise
<
AccountInfo
>;
reconnectMcpServer
(
serverName
:
string
)
:
Promise
<
void
>;
toggleMcpServer
(
serverName
:
string
,
enabled
:
boolean
)
:
Promise
<
void
>;
setMcpServers
(
servers
:
Record
<
string
,
McpServerConfig
>)
:
Promise
<
McpSetServersResult
>;
streamInput
(
stream
:
AsyncIterable
<
SDKUserMessage
>)
:
Promise
<
void
>;
stopTask
(
taskId
:
string
)
:
Promise
<
void
>;
close
()
:
void
;
}
​
Methods
Method
Description
interrupt()
Interrupts the query (only available in streaming input mode)
rewindFiles(userMessageId, options?)
Restores files to their state at the specified user message. Pass
{ dryRun: true }
to preview changes. Requires
enableFileCheckpointing: true
. See
File checkpointing
setPermissionMode()
Changes the permission mode (only available in streaming input mode)
setModel()
Changes the model (only available in streaming input mode)
setMaxThinkingTokens()
Deprecated:
Use the
thinking
option instead. Changes the maximum thinking tokens
applyFlagSettings(settings)
Merges settings into the session’s flag settings layer at runtime (only available in streaming input mode). See
applyFlagSettings()
initializationResult()
Returns the full initialization result including supported commands, models, account info, and output style configuration
supportedCommands()
Returns available slash commands
supportedModels()
Returns available models with display info
supportedAgents()
Returns available subagents as
AgentInfo
[]
mcpServerStatus()
Returns status of connected MCP servers
accountInfo()
Returns account information
reconnectMcpServer(serverName)
Reconnect an MCP server by name
toggleMcpServer(serverName, enabled)
Enable or disable an MCP server by name
setMcpServers(servers)
Dynamically replace the set of MCP servers for this session. Returns info about which servers were added, removed, and any errors
streamInput(stream)
Stream input messages to the query for multi-turn conversations
stopTask(taskId)
Stop a running background task by ID
close()
Close the query and terminate the underlying process. Forcefully ends the query and cleans up all resources
​
applyFlagSettings()
Changes any
setting
on a running session without restarting the query. Use it when a setting that has no dedicated setter needs to change mid-session, such as tightening
permissions
after the agent reads untrusted input.
setModel()
and
setPermissionMode()
are dedicated setters for those two keys;
applyFlagSettings()
is the general form that accepts any subset of the settings keys, and passing
model
here behaves the same as
setModel()
.
The values are written to the flag-settings layer, the same layer the inline
settings
option of
query()
populates at startup. Flag settings sit near the top of the
settings precedence order
: they override user, project, and local settings, and only managed policy settings can override them. This is the same tier the
on-page precedence section
calls programmatic options.
Successive calls shallow-merge top-level keys. A second call with
{ permissions: {...} }
replaces the entire
permissions
object from the prior call rather than deep-merging into it. To clear a key from the flag layer and fall back to lower-precedence sources, pass
null
for that key. Passing
undefined
has no effect because JSON serialization drops it.
Only available in streaming input mode, the same constraint as
setModel()
and
setPermissionMode()
.
The example below switches the active model mid-session, then clears the override so the model falls back to whatever the user or project settings specify.
const
q
=
query
({
prompt:
messageStream
});
// Override the model for the rest of the session
await
q
.
applyFlagSettings
({
model:
"claude-opus-4-6"
});
// Later: clear the override and fall back to lower-precedence settings
await
q
.
applyFlagSettings
({
model:
null
});
applyFlagSettings()
is TypeScript-only. The Python SDK does not expose an equivalent method.
​
WarmQuery
Handle returned by
startup()
. The subprocess is already spawned and initialized, so calling
query()
on this handle writes the prompt directly to a ready process with no startup latency.
interface
WarmQuery
extends
AsyncDisposable
{
query
(
prompt
:
string
|
AsyncIterable
<
SDKUserMessage
>)
:
Query
;
close
()
:
void
;
}
​
Methods
Method
Description
query(prompt)
Send a prompt to the pre-warmed subprocess and return a
Query
. Can only be called once per
WarmQuery
close()
Close the subprocess without sending a prompt. Use this to discard a warm query that is no longer needed
WarmQuery
implements
AsyncDisposable
, so it can be used with
await using
for automatic cleanup.
​
SDKControlInitializeResponse
Return type of
initializationResult()
. Contains session initialization data.
type
SDKControlInitializeResponse
=
{
commands
:
SlashCommand
[];
agents
:
AgentInfo
[];
output_style
:
string
;
available_output_styles
:
string
[];
models
:
ModelInfo
[];
account
:
AccountInfo
;
fast_mode_state
?:
"off"
|
"cooldown"
|
"on"
;
};
​
AgentDefinition
Configuration for a subagent defined programmatically.
type
AgentDefinition
=
{
description
:
string
;
tools
?:
string
[];
disallowedTools
?:
string
[];
prompt
:
string
;
model
?:
string
;
mcpServers
?:
AgentMcpServerSpec
[];
skills
?:
string
[];
initialPrompt
?:
string
;
maxTurns
?:
number
;
background
?:
boolean
;
memory
?:
"user"
|
"project"
|
"local"
;
effort
?:
"low"
|
"medium"
|
"high"
|
"xhigh"
|
"max"
|
number
;
permissionMode
?:
PermissionMode
;
criticalSystemReminder_EXPERIMENTAL
?:
string
;
};
Field
Required
Description
description
Yes
Natural language description of when to use this agent
tools
No
Array of allowed tool names. If omitted, inherits all tools from parent. To preload Skills into the agent’s context, use the
skills
field rather than listing
'Skill'
here
disallowedTools
No
Array of tool names to explicitly disallow for this agent
prompt
Yes
The agent’s system prompt
model
No
Model override for this agent. Accepts an alias such as
'sonnet'
,
'opus'
,
'haiku'
,
'inherit'
, or a full model ID. If omitted or
'inherit'
, uses the main model
mcpServers
No
MCP server specifications for this agent
skills
No
Array of skill names to preload into the agent context
initialPrompt
No
Auto-submitted as the first user turn when this agent runs as the main thread agent
maxTurns
No
Maximum number of agentic turns (API round-trips) before stopping
background
No
Run this agent as a non-blocking background task when invoked
memory
No
Memory source for this agent:
'user'
,
'project'
, or
'local'
effort
No
Reasoning effort level for this agent. Accepts a named level or an integer
permissionMode
No
Permission mode for tool execution within this agent. See
PermissionMode
criticalSystemReminder_EXPERIMENTAL
No
Experimental: Critical reminder added to the system prompt
​
AgentMcpServerSpec
Specifies MCP servers available to a subagent. Can be a server name (string referencing a server from the parent’s
mcpServers
config) or an inline server configuration record mapping server names to configs.
type
AgentMcpServerSpec
=
string
|
Record
<
string
,
McpServerConfigForProcessTransport
>;
Where
McpServerConfigForProcessTransport
is
McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
.
​
SettingSource
Controls which filesystem-based configuration sources the SDK loads settings from.
type
SettingSource
=
"user"
|
"project"
|
"local"
;
Value
Description
Location
'user'
Global user settings
~/.claude/settings.json
'project'
Shared project settings (version controlled)
.claude/settings.json
'local'
Local project settings (gitignored)
.claude/settings.local.json
​
Default behavior
When
settingSources
is omitted or
undefined
,
query()
loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See
What settingSources does not control
for inputs that are read regardless of this option, and how to disable them.
​
Why use settingSources
Disable filesystem settings:
// Do not load user, project, or local settings from disk
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
settingSources:
[] }
});
Load all filesystem settings explicitly:
const
result
=
query
({
prompt:
"Analyze this code"
,
options:
{
settingSources:
[
"user"
,
"project"
,
"local"
]
// Load all settings
}
});
Load only specific setting sources:
// Load only project settings, ignore user and local
const
result
=
query
({
prompt:
"Run CI checks"
,
options:
{
settingSources:
[
"project"
]
// Only .claude/settings.json
}
});
Testing and CI environments:
// Ensure consistent behavior in CI by excluding local settings
const
result
=
query
({
prompt:
"Run tests"
,
options:
{
settingSources:
[
"project"
],
// Only team-shared settings
permissionMode:
"bypassPermissions"
}
});
SDK-only applications:
// Define everything programmatically.
// Pass [] to opt out of filesystem setting sources.
const
result
=
query
({
prompt:
"Review this PR"
,
options:
{
settingSources:
[],
agents:
{
/* ... */
},
mcpServers:
{
/* ... */
},
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
]
}
});
Loading CLAUDE.md project instructions:
// Load project settings to include CLAUDE.md files
const
result
=
query
({
prompt:
"Add a new feature following project conventions"
,
options:
{
systemPrompt:
{
type:
"preset"
,
preset:
"claude_code"
// Use Claude Code's system prompt
},
settingSources:
[
"project"
],
// Loads CLAUDE.md from project directory
allowedTools:
[
"Read"
,
"Write"
,
"Edit"
]
}
});
​
Settings precedence
When multiple sources are loaded, settings are merged with this precedence (highest to lowest):
Local settings (
.claude/settings.local.json
)
Project settings (
.claude/settings.json
)
User settings (
~/.claude/settings.json
)
Programmatic options such as
agents
,
allowedTools
, and
settings
override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.
​
PermissionMode
type
PermissionMode
=
|
"default"
// Standard permission behavior
|
"acceptEdits"
// Auto-accept file edits
|
"bypassPermissions"
// Bypass all permission checks
|
"plan"
// Planning mode - read-only tools only
|
"dontAsk"
// Don't prompt for permissions, deny if not pre-approved
|
"auto"
;
// Use a model classifier to approve or deny each tool call
​
CanUseTool
Custom permission function type for controlling tool usage.
type
CanUseTool
=
(
toolName
:
string
,
input
:
Record
<
string
,
unknown
>,
options
:
{
signal
:
AbortSignal
;
suggestions
?:
PermissionUpdate
[];
blockedPath
?:
string
;
decisionReason
?:
string
;
toolUseID
:
string
;
agentID
?:
string
;
}
)
=>
Promise
<
PermissionResult
>;
Option
Type
Description
signal
AbortSignal
Signaled if the operation should be aborted
suggestions
PermissionUpdate
[]
Suggested permission updates so the user is not prompted again for this tool. Bash prompts include a suggestion with the
localSettings
destination
, so returning it in
updatedPermissions
writes the rule to
.claude/settings.local.json
and persists across sessions.
blockedPath
string
The file path that triggered the permission request, if applicable
decisionReason
string
Explains why this permission request was triggered
toolUseID
string
Unique identifier for this specific tool call within the assistant message
agentID
string
If running within a sub-agent, the sub-agent’s ID
​
PermissionResult
Result of a permission check.
type
PermissionResult
=
|
{
behavior
:
"allow"
;
updatedInput
?:
Record
<
string
,
unknown
>;
updatedPermissions
?:
PermissionUpdate
[];
toolUseID
?:
string
;
}
|
{
behavior
:
"deny"
;
message
:
string
;
interrupt
?:
boolean
;
toolUseID
?:
string
;
};
​
ToolConfig
Configuration for built-in tool behavior.
type
ToolConfig
=
{
askUserQuestion
?:
{
previewFormat
?:
"markdown"
|
"html"
;
};
};
Field
Type
Description
askUserQuestion.previewFormat
'markdown' | 'html'
Opts into the
preview
field on
AskUserQuestion
options and sets its content format. When unset, Claude does not emit previews
​
McpServerConfig
Configuration for MCP servers.
type
McpServerConfig
=
|
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfigWithInstance
;
​
McpStdioServerConfig
type
McpStdioServerConfig
=
{
type
?:
"stdio"
;
command
:
string
;
args
?:
string
[];
env
?:
Record
<
string
,
string
>;
};
​
McpSSEServerConfig
type
McpSSEServerConfig
=
{
type
:
"sse"
;
url
:
string
;
headers
?:
Record
<
string
,
string
>;
};
​
McpHttpServerConfig
type
McpHttpServerConfig
=
{
type
:
"http"
;
url
:
string
;
headers
?:
Record
<
string
,
string
>;
};
​
McpSdkServerConfigWithInstance
type
McpSdkServerConfigWithInstance
=
{
type
:
"sdk"
;
name
:
string
;
instance
:
McpServer
;
};
​
McpClaudeAIProxyServerConfig
type
McpClaudeAIProxyServerConfig
=
{
type
:
"claudeai-proxy"
;
url
:
string
;
id
:
string
;
};
​
SdkPluginConfig
Configuration for loading plugins in the SDK.
type
SdkPluginConfig
=
{
type
:
"local"
;
path
:
string
;
};
Field
Type
Description
type
'local'
Must be
'local'
(only local plugins currently supported)
path
string
Absolute or relative path to the plugin directory
Example:
plugins
: [
{
type:
"local"
,
path:
"./my-plugin"
},
{
type:
"local"
,
path:
"/absolute/path/to/plugin"
}
];
For complete information on creating and using plugins, see
Plugins
.
​
Message Types
​
SDKMessage
Union type of all possible messages returned by the query.
type
SDKMessage
=
|
SDKAssistantMessage
|
SDKUserMessage
|
SDKUserMessageReplay
|
SDKResultMessage
|
SDKSystemMessage
|
SDKPartialAssistantMessage
|
SDKCompactBoundaryMessage
|
SDKStatusMessage
|
SDKLocalCommandOutputMessage
|
SDKHookStartedMessage
|
SDKHookProgressMessage
|
SDKHookResponseMessage
|
SDKPluginInstallMessage
|
SDKToolProgressMessage
|
SDKAuthStatusMessage
|
SDKTaskNotificationMessage
|
SDKTaskStartedMessage
|
SDKTaskProgressMessage
|
SDKTaskUpdatedMessage
|
SDKFilesPersistedEvent
|
SDKToolUseSummaryMessage
|
SDKRateLimitEvent
|
SDKPermissionDeniedMessage
|
SDKPromptSuggestionMessage
;
​
SDKAssistantMessage
Assistant response message.
type
SDKAssistantMessage
=
{
type
:
"assistant"
;
uuid
:
UUID
;
session_id
:
string
;
message
:
BetaMessage
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
error
?:
SDKAssistantMessageError
;
};
The
message
field is a
BetaMessage
from the Anthropic SDK. It includes fields like
id
,
content
,
model
,
stop_reason
, and
usage
.
SDKAssistantMessageError
is one of:
'authentication_failed'
,
'oauth_org_not_allowed'
,
'billing_error'
,
'rate_limit'
,
'invalid_request'
,
'server_error'
,
'max_output_tokens'
, or
'unknown'
.
​
SDKUserMessage
User input message.
type
SDKUserMessage
=
{
type
:
"user"
;
uuid
?:
UUID
;
session_id
?:
string
;
message
:
MessageParam
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
isSynthetic
?:
boolean
;
shouldQuery
?:
boolean
;
tool_use_result
?:
unknown
;
origin
?:
SDKMessageOrigin
;
};
Set
shouldQuery
to
false
to append the message to the transcript without triggering an assistant turn. The message is held and merged into the next user message that does trigger a turn. Use this to inject context, such as the output of a command you ran out of band, without spending a model call on it.
​
SDKUserMessageReplay
Replayed user message with required UUID.
type
SDKUserMessageReplay
=
{
type
:
"user"
;
uuid
:
UUID
;
session_id
:
string
;
message
:
MessageParam
;
parent_tool_use_id
:
string
|
null
;
isSynthetic
?:
boolean
;
tool_use_result
?:
unknown
;
origin
?:
SDKMessageOrigin
;
isReplay
:
true
;
};
​
SDKResultMessage
Final result message.
type
SDKResultMessage
=
|
{
type
:
"result"
;
subtype
:
"success"
;
uuid
:
UUID
;
session_id
:
string
;
duration_ms
:
number
;
duration_api_ms
:
number
;
is_error
:
boolean
;
num_turns
:
number
;
result
:
string
;
stop_reason
:
string
|
null
;
total_cost_usd
:
number
;
usage
:
NonNullableUsage
;
modelUsage
:
{ [
modelName
:
string
]
:
ModelUsage
};
permission_denials
:
SDKPermissionDenial
[];
structured_output
?:
unknown
;
deferred_tool_use
?:
{
id
:
string
;
name
:
string
;
input
:
Record
<
string
,
unknown
> };
origin
?:
SDKMessageOrigin
;
}
|
{
type
:
"result"
;
subtype
:
|
"error_max_turns"
|
"error_during_execution"
|
"error_max_budget_usd"
|
"error_max_structured_output_retries"
;
uuid
:
UUID
;
session_id
:
string
;
duration_ms
:
number
;
duration_api_ms
:
number
;
is_error
:
boolean
;
num_turns
:
number
;
stop_reason
:
string
|
null
;
total_cost_usd
:
number
;
usage
:
NonNullableUsage
;
modelUsage
:
{ [
modelName
:
string
]
:
ModelUsage
};
permission_denials
:
SDKPermissionDenial
[];
errors
:
string
[];
origin
?:
SDKMessageOrigin
;
};
The
origin
field forwards the
SDKMessageOrigin
of the user message that triggered this result. When a background task finishes and the SDK injects a synthetic follow-up turn, the resulting
SDKResultMessage
carries
origin: { kind: "task-notification" }
. Check this field to distinguish results that answer your prompt from results emitted for background-task follow-ups, so you can route or suppress the latter. The field is absent for results emitted before any user turn, such as startup errors.
When a
PreToolUse
hook returns
permissionDecision: "defer"
, the result has
stop_reason: "tool_deferred"
and
deferred_tool_use
carries the pending tool’s
id
,
name
, and
input
. Read this field to surface the request in your own UI, then resume with the same
session_id
to continue. See
Defer a tool call for later
for the full round trip.
​
SDKSystemMessage
System initialization message.
type
SDKSystemMessage
=
{
type
:
"system"
;
subtype
:
"init"
;
uuid
:
UUID
;
session_id
:
string
;
agents
?:
string
[];
apiKeySource
:
ApiKeySource
;
betas
?:
string
[];
claude_code_version
:
string
;
cwd
:
string
;
tools
:
string
[];
mcp_servers
:
{
name
:
string
;
status
:
string
;
}[];
model
:
string
;
permissionMode
:
PermissionMode
;
slash_commands
:
string
[];
output_style
:
string
;
skills
:
string
[];
plugins
:
{
name
:
string
;
path
:
string
}[];
};
​
SDKPartialAssistantMessage
Streaming partial message (only when
includePartialMessages
is true).
type
SDKPartialAssistantMessage
=
{
type
:
"stream_event"
;
event
:
BetaRawMessageStreamEvent
;
// From Anthropic SDK
parent_tool_use_id
:
string
|
null
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKCompactBoundaryMessage
Message indicating a conversation compaction boundary.
type
SDKCompactBoundaryMessage
=
{
type
:
"system"
;
subtype
:
"compact_boundary"
;
uuid
:
UUID
;
session_id
:
string
;
compact_metadata
:
{
trigger
:
"manual"
|
"auto"
;
pre_tokens
:
number
;
};
};
​
SDKPluginInstallMessage
Plugin installation progress event. Emitted when
CLAUDE_CODE_SYNC_PLUGIN_INSTALL
is set, so your Agent SDK application can track marketplace plugin installation before the first turn. The
started
and
completed
statuses bracket the overall install. The
installed
and
failed
statuses report individual marketplaces and include
name
.
type
SDKPluginInstallMessage
=
{
type
:
"system"
;
subtype
:
"plugin_install"
;
status
:
"started"
|
"installed"
|
"failed"
|
"completed"
;
name
?:
string
;
error
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKPermissionDeniedMessage
Stream event emitted when the permission system auto-denies a tool call without an interactive prompt. Use it to render the denial in your UI as it happens, rather than only observing the
is_error
tool result that follows. The interactive ask path reaches your application separately through the
canUseTool
callback. Denials issued by a
PreToolUse
hook are not reported through this event.
This event requires Claude Code v2.1.136 or later.
type
SDKPermissionDeniedMessage
=
{
type
:
"system"
;
subtype
:
"permission_denied"
;
tool_name
:
string
;
tool_use_id
:
string
;
agent_id
?:
string
;
decision_reason_type
?:
string
;
decision_reason
?:
string
;
message
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
Field
Type
Description
tool_name
string
Name of the tool that was denied
tool_use_id
string
ID of the
tool_use
block this denial answers
agent_id
string
Subagent ID when the denied call originated inside a subagent. Mirrors the field on
can_use_tool
for host-side routing
decision_reason_type
string
Discriminator for the component that decided, such as
"rule"
,
"mode"
,
"classifier"
, or
"asyncAgent"
decision_reason
string
Human-readable reason from the deciding component, when available
message
string
Rejection message returned to the model in the
tool_result
​
SDKPermissionDenial
Information about a denied tool use.
type
SDKPermissionDenial
=
{
tool_name
:
string
;
tool_use_id
:
string
;
tool_input
:
Record
<
string
,
unknown
>;
};
​
SDKMessageOrigin
Provenance of a user-role message. This appears as
origin
on
SDKUserMessage
and is forwarded onto the corresponding
SDKResultMessage
so you can tell what triggered a given turn.
type
SDKMessageOrigin
=
|
{
kind
:
"human"
}
|
{
kind
:
"channel"
;
server
:
string
}
|
{
kind
:
"peer"
;
from
:
string
;
name
?:
string
}
|
{
kind
:
"task-notification"
}
|
{
kind
:
"coordinator"
};
kind
Meaning
human
Direct input from the end user. On user messages, an absent
origin
also means human input.
channel
Message arriving on a
channel
.
server
is the source MCP server name.
peer
Message from another agent session via
SendMessage
.
from
is the sender address;
name
is the sender’s display name when available.
task-notification
Synthetic turn injected after a background task finished. See
SDKTaskNotificationMessage
.
coordinator
Message from a team coordinator in an
agent team
.
​
Hook Types
For a comprehensive guide on using hooks with examples and common patterns, see the
Hooks guide
.
​
HookEvent
Available hook events.
type
HookEvent
=
|
"PreToolUse"
|
"PostToolUse"
|
"PostToolUseFailure"
|
"PostToolBatch"
|
"Notification"
|
"UserPromptSubmit"
|
"SessionStart"
|
"SessionEnd"
|
"Stop"
|
"SubagentStart"
|
"SubagentStop"
|
"PreCompact"
|
"PermissionRequest"
|
"Setup"
|
"TeammateIdle"
|
"TaskCompleted"
|
"ConfigChange"
|
"WorktreeCreate"
|
"WorktreeRemove"
;
​
HookCallback
Hook callback function type.
type
HookCallback
=
(
input
:
HookInput
,
// Union of all hook input types
toolUseID
:
string
|
undefined
,
options
:
{
signal
:
AbortSignal
}
)
=>
Promise
<
HookJSONOutput
>;
​
HookCallbackMatcher
Hook configuration with optional matcher.
interface
HookCallbackMatcher
{
matcher
?:
string
;
hooks
:
HookCallback
[];
timeout
?:
number
;
// Timeout in seconds for all hooks in this matcher
}
​
HookInput
Union type of all hook input types.
type
HookInput
=
|
PreToolUseHookInput
|
PostToolUseHookInput
|
PostToolUseFailureHookInput
|
PostToolBatchHookInput
|
NotificationHookInput
|
UserPromptSubmitHookInput
|
SessionStartHookInput
|
SessionEndHookInput
|
StopHookInput
|
SubagentStartHookInput
|
SubagentStopHookInput
|
PreCompactHookInput
|
PermissionRequestHookInput
|
SetupHookInput
|
TeammateIdleHookInput
|
TaskCompletedHookInput
|
ConfigChangeHookInput
|
WorktreeCreateHookInput
|
WorktreeRemoveHookInput
;
​
BaseHookInput
Base interface that all hook input types extend.
type
BaseHookInput
=
{
session_id
:
string
;
transcript_path
:
string
;
cwd
:
string
;
permission_mode
?:
string
;
effort
?:
{
level
:
string
};
agent_id
?:
string
;
agent_type
?:
string
;
};
​
PreToolUseHookInput
type
PreToolUseHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PreToolUse"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
};
​
PostToolUseHookInput
type
PostToolUseHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolUse"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_response
:
unknown
;
tool_use_id
:
string
;
duration_ms
?:
number
;
};
​
PostToolUseFailureHookInput
type
PostToolUseFailureHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolUseFailure"
;
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
error
:
string
;
is_interrupt
?:
boolean
;
duration_ms
?:
number
;
};
​
PostToolBatchHookInput
Fires once after every tool call in a batch has resolved, before the next model request.
tool_response
carries the serialized
tool_result
content the model sees; the shape differs from
PostToolUseHookInput
’s structured
Output
object.
type
PostToolBatchHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PostToolBatch"
;
tool_calls
:
PostToolBatchToolCall
[];
};
type
PostToolBatchToolCall
=
{
tool_name
:
string
;
tool_input
:
unknown
;
tool_use_id
:
string
;
tool_response
?:
unknown
;
};
​
NotificationHookInput
type
NotificationHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Notification"
;
message
:
string
;
title
?:
string
;
notification_type
:
string
;
};
​
UserPromptSubmitHookInput
type
UserPromptSubmitHookInput
=
BaseHookInput
&
{
hook_event_name
:
"UserPromptSubmit"
;
prompt
:
string
;
};
​
SessionStartHookInput
type
SessionStartHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SessionStart"
;
source
:
"startup"
|
"resume"
|
"clear"
|
"compact"
;
agent_type
?:
string
;
model
?:
string
;
};
​
SessionEndHookInput
type
SessionEndHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SessionEnd"
;
reason
:
ExitReason
;
// String from EXIT_REASONS array
};
​
StopHookInput
type
StopHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Stop"
;
stop_hook_active
:
boolean
;
last_assistant_message
?:
string
;
};
​
SubagentStartHookInput
type
SubagentStartHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SubagentStart"
;
agent_id
:
string
;
agent_type
:
string
;
};
​
SubagentStopHookInput
type
SubagentStopHookInput
=
BaseHookInput
&
{
hook_event_name
:
"SubagentStop"
;
stop_hook_active
:
boolean
;
agent_id
:
string
;
agent_transcript_path
:
string
;
agent_type
:
string
;
last_assistant_message
?:
string
;
};
​
PreCompactHookInput
type
PreCompactHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PreCompact"
;
trigger
:
"manual"
|
"auto"
;
custom_instructions
:
string
|
null
;
};
​
PermissionRequestHookInput
type
PermissionRequestHookInput
=
BaseHookInput
&
{
hook_event_name
:
"PermissionRequest"
;
tool_name
:
string
;
tool_input
:
unknown
;
permission_suggestions
?:
PermissionUpdate
[];
};
​
SetupHookInput
type
SetupHookInput
=
BaseHookInput
&
{
hook_event_name
:
"Setup"
;
trigger
:
"init"
|
"maintenance"
;
};
​
TeammateIdleHookInput
type
TeammateIdleHookInput
=
BaseHookInput
&
{
hook_event_name
:
"TeammateIdle"
;
teammate_name
:
string
;
team_name
:
string
;
};
​
TaskCompletedHookInput
type
TaskCompletedHookInput
=
BaseHookInput
&
{
hook_event_name
:
"TaskCompleted"
;
task_id
:
string
;
task_subject
:
string
;
task_description
?:
string
;
teammate_name
?:
string
;
team_name
?:
string
;
};
​
ConfigChangeHookInput
type
ConfigChangeHookInput
=
BaseHookInput
&
{
hook_event_name
:
"ConfigChange"
;
source
:
|
"user_settings"
|
"project_settings"
|
"local_settings"
|
"policy_settings"
|
"skills"
;
file_path
?:
string
;
};
​
WorktreeCreateHookInput
type
WorktreeCreateHookInput
=
BaseHookInput
&
{
hook_event_name
:
"WorktreeCreate"
;
name
:
string
;
};
​
WorktreeRemoveHookInput
type
WorktreeRemoveHookInput
=
BaseHookInput
&
{
hook_event_name
:
"WorktreeRemove"
;
worktree_path
:
string
;
};
​
HookJSONOutput
Hook return value.
type
HookJSONOutput
=
AsyncHookJSONOutput
|
SyncHookJSONOutput
;
​
AsyncHookJSONOutput
type
AsyncHookJSONOutput
=
{
async
:
true
;
asyncTimeout
?:
number
;
};
​
SyncHookJSONOutput
type
SyncHookJSONOutput
=
{
continue
?:
boolean
;
suppressOutput
?:
boolean
;
stopReason
?:
string
;
decision
?:
"approve"
|
"block"
;
systemMessage
?:
string
;
reason
?:
string
;
hookSpecificOutput
?:
|
{
hookEventName
:
"PreToolUse"
;
permissionDecision
?:
"allow"
|
"deny"
|
"ask"
|
"defer"
;
permissionDecisionReason
?:
string
;
updatedInput
?:
Record
<
string
,
unknown
>;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"UserPromptSubmit"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"SessionStart"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"Setup"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"SubagentStart"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PostToolUse"
;
additionalContext
?:
string
;
updatedToolOutput
?:
unknown
;
/**
@deprecated
Use `updatedToolOutput`, which works for all tools. */
updatedMCPToolOutput
?:
unknown
;
}
|
{
hookEventName
:
"PostToolUseFailure"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PostToolBatch"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"Notification"
;
additionalContext
?:
string
;
}
|
{
hookEventName
:
"PermissionRequest"
;
decision
:
|
{
behavior
:
"allow"
;
updatedInput
?:
Record
<
string
,
unknown
>;
updatedPermissions
?:
PermissionUpdate
[];
}
|
{
behavior
:
"deny"
;
message
?:
string
;
interrupt
?:
boolean
;
};
};
};
​
Tool Input Types
Documentation of input schemas for all built-in Claude Code tools. These types are exported from
@anthropic-ai/claude-agent-sdk
and can be used for type-safe tool interactions.
​
ToolInputSchemas
Union of all tool input types, exported from
@anthropic-ai/claude-agent-sdk
.
type
ToolInputSchemas
=
|
AgentInput
|
AskUserQuestionInput
|
BashInput
|
TaskOutputInput
|
EnterWorktreeInput
|
ExitPlanModeInput
|
FileEditInput
|
FileReadInput
|
FileWriteInput
|
GlobInput
|
GrepInput
|
ListMcpResourcesInput
|
McpInput
|
MonitorInput
|
NotebookEditInput
|
ReadMcpResourceInput
|
SubscribeMcpResourceInput
|
SubscribePollingInput
|
TaskCreateInput
|
TaskGetInput
|
TaskListInput
|
TaskStopInput
|
TaskUpdateInput
|
TodoWriteInput
|
UnsubscribeMcpResourceInput
|
UnsubscribePollingInput
|
WebFetchInput
|
WebSearchInput
;
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
type
AgentInput
=
{
description
:
string
;
prompt
:
string
;
subagent_type
:
string
;
model
?:
"sonnet"
|
"opus"
|
"haiku"
;
resume
?:
string
;
run_in_background
?:
boolean
;
max_turns
?:
number
;
name
?:
string
;
team_name
?:
string
;
mode
?:
"acceptEdits"
|
"bypassPermissions"
|
"default"
|
"dontAsk"
|
"plan"
;
isolation
?:
"worktree"
;
};
Launches a new agent to handle complex, multi-step tasks autonomously.
​
AskUserQuestion
Tool name:
AskUserQuestion
type
AskUserQuestionInput
=
{
questions
:
Array
<{
question
:
string
;
header
:
string
;
options
:
Array
<{
label
:
string
;
description
:
string
;
preview
?:
string
}>;
multiSelect
:
boolean
;
}>;
};
Asks the user clarifying questions during execution. See
Handle approvals and user input
for usage details.
​
Bash
Tool name:
Bash
type
BashInput
=
{
command
:
string
;
timeout
?:
number
;
description
?:
string
;
run_in_background
?:
boolean
;
dangerouslyDisableSandbox
?:
boolean
;
};
Executes bash commands in a persistent shell session with optional timeout and background execution.
​
Monitor
Tool name:
Monitor
type
MonitorInput
=
{
command
:
string
;
description
:
string
;
timeout_ms
?:
number
;
persistent
?:
boolean
;
};
Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Set
persistent: true
for session-length watches such as log tails. Monitor follows the same permission rules as Bash. See the
Monitor tool reference
for behavior and provider availability.
​
TaskOutput
Tool name:
TaskOutput
type
TaskOutputInput
=
{
task_id
:
string
;
block
:
boolean
;
timeout
:
number
;
};
Retrieves output from a running or completed background task.
​
Edit
Tool name:
Edit
type
FileEditInput
=
{
file_path
:
string
;
old_string
:
string
;
new_string
:
string
;
replace_all
?:
boolean
;
};
Performs exact string replacements in files.
​
Read
Tool name:
Read
type
FileReadInput
=
{
file_path
:
string
;
offset
?:
number
;
limit
?:
number
;
pages
?:
string
;
};
Reads files from the local filesystem, including text, images, PDFs, and Jupyter notebooks. Use
pages
for PDF page ranges (for example,
"1-5"
).
​
Write
Tool name:
Write
type
FileWriteInput
=
{
file_path
:
string
;
content
:
string
;
};
Writes a file to the local filesystem, overwriting if it exists.
​
Glob
Tool name:
Glob
type
GlobInput
=
{
pattern
:
string
;
path
?:
string
;
};
Fast file pattern matching that works with any codebase size.
​
Grep
Tool name:
Grep
type
GrepInput
=
{
pattern
:
string
;
path
?:
string
;
glob
?:
string
;
type
?:
string
;
output_mode
?:
"content"
|
"files_with_matches"
|
"count"
;
"-i"
?:
boolean
;
"-n"
?:
boolean
;
"-B"
?:
number
;
"-A"
?:
number
;
"-C"
?:
number
;
context
?:
number
;
head_limit
?:
number
;
offset
?:
number
;
multiline
?:
boolean
;
};
Powerful search tool built on ripgrep with regex support.
​
TaskStop
Tool name:
TaskStop
type
TaskStopInput
=
{
task_id
?:
string
;
shell_id
?:
string
;
// Deprecated: use task_id
};
Stops a running background task or shell by ID.
​
NotebookEdit
Tool name:
NotebookEdit
type
NotebookEditInput
=
{
notebook_path
:
string
;
cell_id
?:
string
;
new_source
:
string
;
cell_type
?:
"code"
|
"markdown"
;
edit_mode
?:
"replace"
|
"insert"
|
"delete"
;
};
Edits cells in Jupyter notebook files.
​
WebFetch
Tool name:
WebFetch
type
WebFetchInput
=
{
url
:
string
;
prompt
:
string
;
};
Fetches content from a URL and processes it with an AI model.
​
WebSearch
Tool name:
WebSearch
type
WebSearchInput
=
{
query
:
string
;
allowed_domains
?:
string
[];
blocked_domains
?:
string
[];
};
Searches the web and returns formatted results.
​
TodoWrite
Tool name:
TodoWrite
type
TodoWriteInput
=
{
todos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
};
Creates and manages a structured task list for tracking progress.
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
​
TaskCreate
Tool name:
TaskCreate
type
TaskCreateInput
=
{
subject
:
string
;
description
:
string
;
activeForm
?:
string
;
metadata
?:
Record
<
string
,
unknown
>;
};
Creates a single task and returns its assigned ID.
​
TaskUpdate
Tool name:
TaskUpdate
type
TaskUpdateInput
=
{
taskId
:
string
;
status
?:
"pending"
|
"in_progress"
|
"completed"
|
"deleted"
;
subject
?:
string
;
description
?:
string
;
activeForm
?:
string
;
addBlocks
?:
string
[];
addBlockedBy
?:
string
[];
owner
?:
string
;
metadata
?:
Record
<
string
,
unknown
>;
};
Patches one task by ID. Set
status
to
"deleted"
to remove it.
​
TaskGet
Tool name:
TaskGet
type
TaskGetInput
=
{
taskId
:
string
;
};
Returns full details for one task, or
null
when the ID is not found.
​
TaskList
Tool name:
TaskList
type
TaskListInput
=
{};
Returns a snapshot of all tasks in the current list.
​
ExitPlanMode
Tool name:
ExitPlanMode
type
ExitPlanModeInput
=
{
allowedPrompts
?:
Array
<{
tool
:
"Bash"
;
prompt
:
string
;
}>;
};
Exits planning mode. Optionally specifies prompt-based permissions needed to implement the plan.
​
ListMcpResources
Tool name:
ListMcpResources
type
ListMcpResourcesInput
=
{
server
?:
string
;
};
Lists available MCP resources from connected servers.
​
ReadMcpResource
Tool name:
ReadMcpResource
type
ReadMcpResourceInput
=
{
server
:
string
;
uri
:
string
;
};
Reads a specific MCP resource from a server.
​
EnterWorktree
Tool name:
EnterWorktree
type
EnterWorktreeInput
=
{
name
?:
string
;
path
?:
string
;
};
Creates and enters a temporary git worktree for isolated work. Pass
path
to switch into an existing worktree of the current repository instead of creating a new one.
name
and
path
are mutually exclusive.
​
Tool Output Types
Documentation of output schemas for all built-in Claude Code tools. These types are exported from
@anthropic-ai/claude-agent-sdk
and represent the actual response data returned by each tool.
​
ToolOutputSchemas
Union of all tool output types.
type
ToolOutputSchemas
=
|
AgentOutput
|
AskUserQuestionOutput
|
BashOutput
|
EnterWorktreeOutput
|
ExitPlanModeOutput
|
FileEditOutput
|
FileReadOutput
|
FileWriteOutput
|
GlobOutput
|
GrepOutput
|
ListMcpResourcesOutput
|
MonitorOutput
|
NotebookEditOutput
|
ReadMcpResourceOutput
|
TaskCreateOutput
|
TaskGetOutput
|
TaskListOutput
|
TaskStopOutput
|
TaskUpdateOutput
|
TodoWriteOutput
|
WebFetchOutput
|
WebSearchOutput
;
​
Agent
Tool name:
Agent
(previously
Task
, which is still accepted as an alias)
type
AgentOutput
=
|
{
status
:
"completed"
;
agentId
:
string
;
content
:
Array
<{
type
:
"text"
;
text
:
string
}>;
totalToolUseCount
:
number
;
totalDurationMs
:
number
;
totalTokens
:
number
;
usage
:
{
input_tokens
:
number
;
output_tokens
:
number
;
cache_creation_input_tokens
:
number
|
null
;
cache_read_input_tokens
:
number
|
null
;
server_tool_use
:
{
web_search_requests
:
number
;
web_fetch_requests
:
number
;
}
|
null
;
service_tier
:
(
"standard"
|
"priority"
|
"batch"
)
|
null
;
cache_creation
:
{
ephemeral_1h_input_tokens
:
number
;
ephemeral_5m_input_tokens
:
number
;
}
|
null
;
};
prompt
:
string
;
}
|
{
status
:
"async_launched"
;
agentId
:
string
;
description
:
string
;
prompt
:
string
;
outputFile
:
string
;
canReadOutputFile
?:
boolean
;
}
|
{
status
:
"sub_agent_entered"
;
description
:
string
;
message
:
string
;
};
Returns the result from the subagent. Discriminated on the
status
field:
"completed"
for finished tasks,
"async_launched"
for background tasks, and
"sub_agent_entered"
for interactive subagents.
​
AskUserQuestion
Tool name:
AskUserQuestion
type
AskUserQuestionOutput
=
{
questions
:
Array
<{
question
:
string
;
header
:
string
;
options
:
Array
<{
label
:
string
;
description
:
string
;
preview
?:
string
}>;
multiSelect
:
boolean
;
}>;
answers
:
Record
<
string
,
string
>;
};
Returns the questions asked and the user’s answers.
​
Bash
Tool name:
Bash
type
BashOutput
=
{
stdout
:
string
;
stderr
:
string
;
rawOutputPath
?:
string
;
interrupted
:
boolean
;
isImage
?:
boolean
;
backgroundTaskId
?:
string
;
backgroundedByUser
?:
boolean
;
dangerouslyDisableSandbox
?:
boolean
;
returnCodeInterpretation
?:
string
;
structuredContent
?:
unknown
[];
persistedOutputPath
?:
string
;
persistedOutputSize
?:
number
;
};
Returns command output with stdout/stderr split. Background commands include a
backgroundTaskId
.
​
Monitor
Tool name:
Monitor
type
MonitorOutput
=
{
taskId
:
string
;
timeoutMs
:
number
;
persistent
?:
boolean
;
};
Returns the background task ID for the running monitor. Use this ID with
TaskStop
to cancel the watch early.
​
Edit
Tool name:
Edit
type
FileEditOutput
=
{
filePath
:
string
;
oldString
:
string
;
newString
:
string
;
originalFile
:
string
;
structuredPatch
:
Array
<{
oldStart
:
number
;
oldLines
:
number
;
newStart
:
number
;
newLines
:
number
;
lines
:
string
[];
}>;
userModified
:
boolean
;
replaceAll
:
boolean
;
gitDiff
?:
{
filename
:
string
;
status
:
"modified"
|
"added"
;
additions
:
number
;
deletions
:
number
;
changes
:
number
;
patch
:
string
;
};
};
Returns the structured diff of the edit operation.
​
Read
Tool name:
Read
type
FileReadOutput
=
|
{
type
:
"text"
;
file
:
{
filePath
:
string
;
content
:
string
;
numLines
:
number
;
startLine
:
number
;
totalLines
:
number
;
};
}
|
{
type
:
"image"
;
file
:
{
base64
:
string
;
type
:
"image/jpeg"
|
"image/png"
|
"image/gif"
|
"image/webp"
;
originalSize
:
number
;
dimensions
?:
{
originalWidth
?:
number
;
originalHeight
?:
number
;
displayWidth
?:
number
;
displayHeight
?:
number
;
};
};
}
|
{
type
:
"notebook"
;
file
:
{
filePath
:
string
;
cells
:
unknown
[];
};
}
|
{
type
:
"pdf"
;
file
:
{
filePath
:
string
;
base64
:
string
;
originalSize
:
number
;
};
}
|
{
type
:
"parts"
;
file
:
{
filePath
:
string
;
originalSize
:
number
;
count
:
number
;
outputDir
:
string
;
};
};
Returns file contents in a format appropriate to the file type. Discriminated on the
type
field.
​
Write
Tool name:
Write
type
FileWriteOutput
=
{
type
:
"create"
|
"update"
;
filePath
:
string
;
content
:
string
;
structuredPatch
:
Array
<{
oldStart
:
number
;
oldLines
:
number
;
newStart
:
number
;
newLines
:
number
;
lines
:
string
[];
}>;
originalFile
:
string
|
null
;
gitDiff
?:
{
filename
:
string
;
status
:
"modified"
|
"added"
;
additions
:
number
;
deletions
:
number
;
changes
:
number
;
patch
:
string
;
};
};
Returns the write result with structured diff information.
​
Glob
Tool name:
Glob
type
GlobOutput
=
{
durationMs
:
number
;
numFiles
:
number
;
filenames
:
string
[];
truncated
:
boolean
;
};
Returns file paths matching the glob pattern, sorted by modification time.
​
Grep
Tool name:
Grep
type
GrepOutput
=
{
mode
?:
"content"
|
"files_with_matches"
|
"count"
;
numFiles
:
number
;
filenames
:
string
[];
content
?:
string
;
numLines
?:
number
;
numMatches
?:
number
;
appliedLimit
?:
number
;
appliedOffset
?:
number
;
};
Returns search results. The shape varies by
mode
: file list, content with matches, or match counts.
​
TaskStop
Tool name:
TaskStop
type
TaskStopOutput
=
{
message
:
string
;
task_id
:
string
;
task_type
:
string
;
command
?:
string
;
};
Returns confirmation after stopping the background task.
​
NotebookEdit
Tool name:
NotebookEdit
type
NotebookEditOutput
=
{
new_source
:
string
;
cell_id
?:
string
;
cell_type
:
"code"
|
"markdown"
;
language
:
string
;
edit_mode
:
string
;
error
?:
string
;
notebook_path
:
string
;
original_file
:
string
;
updated_file
:
string
;
};
Returns the result of the notebook edit with original and updated file contents.
​
WebFetch
Tool name:
WebFetch
type
WebFetchOutput
=
{
bytes
:
number
;
code
:
number
;
codeText
:
string
;
result
:
string
;
durationMs
:
number
;
url
:
string
;
};
Returns the fetched content with HTTP status and metadata.
​
WebSearch
Tool name:
WebSearch
type
WebSearchOutput
=
{
query
:
string
;
results
:
Array
<
|
{
tool_use_id
:
string
;
content
:
Array
<{
title
:
string
;
url
:
string
}>;
}
|
string
>;
durationSeconds
:
number
;
};
Returns search results from the web.
​
TodoWrite
Tool name:
TodoWrite
type
TodoWriteOutput
=
{
oldTodos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
newTodos
:
Array
<{
content
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
activeForm
:
string
;
}>;
};
Returns the previous and updated task lists.
TodoWrite
is deprecated and will be removed in a future release. Use
TaskCreate
,
TaskGet
,
TaskUpdate
, and
TaskList
instead. Set
CLAUDE_CODE_ENABLE_TASKS=1
to opt in. See
Migrate to Task tools
for how monitoring code changes.
​
TaskCreate
Tool name:
TaskCreate
type
TaskCreateOutput
=
{
task
:
{
id
:
string
;
subject
:
string
;
};
};
Returns the created task with its assigned ID.
​
TaskUpdate
Tool name:
TaskUpdate
type
TaskUpdateOutput
=
{
success
:
boolean
;
taskId
:
string
;
updatedFields
:
string
[];
error
?:
string
;
statusChange
?:
{
from
:
string
;
to
:
string
;
};
};
Returns the update result, including which fields changed.
​
TaskGet
Tool name:
TaskGet
type
TaskGetOutput
=
{
task
:
{
id
:
string
;
subject
:
string
;
description
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
blocks
:
string
[];
blockedBy
:
string
[];
}
|
null
;
};
Returns the full task record, or
null
when the ID is not found.
​
TaskList
Tool name:
TaskList
type
TaskListOutput
=
{
tasks
:
Array
<{
id
:
string
;
subject
:
string
;
status
:
"pending"
|
"in_progress"
|
"completed"
;
owner
?:
string
;
blockedBy
:
string
[];
}>;
};
Returns a snapshot of all tasks in the current list.
​
ExitPlanMode
Tool name:
ExitPlanMode
type
ExitPlanModeOutput
=
{
plan
:
string
|
null
;
isAgent
:
boolean
;
filePath
?:
string
;
hasTaskTool
?:
boolean
;
awaitingLeaderApproval
?:
boolean
;
requestId
?:
string
;
};
Returns the plan state after exiting plan mode.
​
ListMcpResources
Tool name:
ListMcpResources
type
ListMcpResourcesOutput
=
Array
<{
uri
:
string
;
name
:
string
;
mimeType
?:
string
;
description
?:
string
;
server
:
string
;
}>;
Returns an array of available MCP resources.
​
ReadMcpResource
Tool name:
ReadMcpResource
type
ReadMcpResourceOutput
=
{
contents
:
Array
<{
uri
:
string
;
mimeType
?:
string
;
text
?:
string
;
}>;
};
Returns the contents of the requested MCP resource.
​
EnterWorktree
Tool name:
EnterWorktree
type
EnterWorktreeOutput
=
{
worktreePath
:
string
;
worktreeBranch
?:
string
;
message
:
string
;
};
Returns information about the git worktree.
​
Permission Types
​
PermissionUpdate
Operations for updating permissions.
type
PermissionUpdate
=
|
{
type
:
"addRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"replaceRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"removeRules"
;
rules
:
PermissionRuleValue
[];
behavior
:
PermissionBehavior
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"setMode"
;
mode
:
PermissionMode
;
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"addDirectories"
;
directories
:
string
[];
destination
:
PermissionUpdateDestination
;
}
|
{
type
:
"removeDirectories"
;
directories
:
string
[];
destination
:
PermissionUpdateDestination
;
};
​
PermissionBehavior
type
PermissionBehavior
=
"allow"
|
"deny"
|
"ask"
;
​
PermissionUpdateDestination
type
PermissionUpdateDestination
=
|
"userSettings"
// Global user settings
|
"projectSettings"
// Per-directory project settings
|
"localSettings"
// Gitignored local settings
|
"session"
// Current session only
|
"cliArg"
;
// CLI argument
​
PermissionRuleValue
type
PermissionRuleValue
=
{
toolName
:
string
;
ruleContent
?:
string
;
};
​
Other Types
​
ApiKeySource
type
ApiKeySource
=
"user"
|
"project"
|
"org"
|
"temporary"
|
"oauth"
;
​
SdkBeta
Available beta features that can be enabled via the
betas
option. See
Beta headers
for more information.
type
SdkBeta
=
"context-1m-2025-08-07"
;
The
context-1m-2025-08-07
beta is retired as of April 30, 2026. Passing this value with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to
Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7
, which include 1M context at standard pricing with no beta header required.
​
SlashCommand
Information about an available slash command.
type
SlashCommand
=
{
name
:
string
;
description
:
string
;
argumentHint
:
string
;
aliases
?:
string
[];
};
​
ModelInfo
Information about an available model.
type
ModelInfo
=
{
value
:
string
;
displayName
:
string
;
description
:
string
;
supportsEffort
?:
boolean
;
supportedEffortLevels
?:
(
"low"
|
"medium"
|
"high"
|
"xhigh"
|
"max"
)[];
supportsAdaptiveThinking
?:
boolean
;
supportsFastMode
?:
boolean
;
};
​
AgentInfo
Information about an available subagent that can be invoked via the Agent tool.
type
AgentInfo
=
{
name
:
string
;
description
:
string
;
model
?:
string
;
};
Field
Type
Description
name
string
Agent type identifier (e.g.,
"Explore"
,
"general-purpose"
)
description
string
Description of when to use this agent
model
string | undefined
Model alias this agent uses. If omitted, inherits the parent’s model
​
McpServerStatus
Status of a connected MCP server.
type
McpServerStatus
=
{
name
:
string
;
status
:
"connected"
|
"failed"
|
"needs-auth"
|
"pending"
|
"disabled"
;
serverInfo
?:
{
name
:
string
;
version
:
string
;
};
error
?:
string
;
config
?:
McpServerStatusConfig
;
scope
?:
string
;
tools
?:
{
name
:
string
;
description
?:
string
;
annotations
?:
{
readOnly
?:
boolean
;
destructive
?:
boolean
;
openWorld
?:
boolean
;
};
}[];
};
​
McpServerStatusConfig
The configuration of an MCP server as reported by
mcpServerStatus()
. This is the union of all MCP server transport types.
type
McpServerStatusConfig
=
|
McpStdioServerConfig
|
McpSSEServerConfig
|
McpHttpServerConfig
|
McpSdkServerConfig
|
McpClaudeAIProxyServerConfig
;
See
McpServerConfig
for details on each transport type.
​
AccountInfo
Account information for the authenticated user.
type
AccountInfo
=
{
email
?:
string
;
organization
?:
string
;
subscriptionType
?:
string
;
tokenSource
?:
string
;
apiKeySource
?:
string
;
};
​
ModelUsage
Per-model usage statistics returned in result messages. The
costUSD
value is a client-side estimate. See
Track cost and usage
for billing caveats.
type
ModelUsage
=
{
inputTokens
:
number
;
outputTokens
:
number
;
cacheReadInputTokens
:
number
;
cacheCreationInputTokens
:
number
;
webSearchRequests
:
number
;
costUSD
:
number
;
contextWindow
:
number
;
maxOutputTokens
:
number
;
};
​
ConfigScope
type
ConfigScope
=
"local"
|
"user"
|
"project"
;
​
NonNullableUsage
A version of
Usage
with all nullable fields made non-nullable.
type
NonNullableUsage
=
{
[
K
in
keyof
Usage
]
:
NonNullable
<
Usage
[
K
]>;
};
​
Usage
Token usage statistics (from
@anthropic-ai/sdk
).
type
Usage
=
{
input_tokens
:
number
|
null
;
output_tokens
:
number
|
null
;
cache_creation_input_tokens
?:
number
|
null
;
cache_read_input_tokens
?:
number
|
null
;
};
​
CallToolResult
MCP tool result type (from
@modelcontextprotocol/sdk/types.js
).
structuredContent
is a JSON object that can be returned alongside
content
, including image blocks. See
Return structured data
.
type
CallToolResult
=
{
content
:
Array
<{
type
:
"text"
|
"image"
|
"resource"
;
// Additional fields vary by type
}>;
structuredContent
?:
Record
<
string
,
unknown
>;
isError
?:
boolean
;
};
​
ThinkingConfig
Controls Claude’s thinking/reasoning behavior. Takes precedence over the deprecated
maxThinkingTokens
.
type
ThinkingConfig
=
|
{
type
:
"adaptive"
}
// The model determines when and how much to reason (Opus 4.6+)
|
{
type
:
"enabled"
;
budgetTokens
?:
number
}
// Fixed thinking token budget
|
{
type
:
"disabled"
};
// No extended thinking
​
SpawnedProcess
Interface for custom process spawning (used with
spawnClaudeCodeProcess
option).
ChildProcess
already satisfies this interface.
interface
SpawnedProcess
{
stdin
:
Writable
;
stdout
:
Readable
;
readonly
killed
:
boolean
;
readonly
exitCode
:
number
|
null
;
kill
(
signal
:
NodeJS
.
Signals
)
:
boolean
;
on
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
on
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
once
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
once
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
off
(
event
:
"exit"
,
listener
:
(
code
:
number
|
null
,
signal
:
NodeJS
.
Signals
|
null
)
=>
void
)
:
void
;
off
(
event
:
"error"
,
listener
:
(
error
:
Error
)
=>
void
)
:
void
;
}
​
SpawnOptions
Options passed to the custom spawn function.
interface
SpawnOptions
{
command
:
string
;
args
:
string
[];
cwd
?:
string
;
env
:
Record
<
string
,
string
|
undefined
>;
signal
:
AbortSignal
;
}
​
McpSetServersResult
Result of a
setMcpServers()
operation.
type
McpSetServersResult
=
{
added
:
string
[];
removed
:
string
[];
errors
:
Record
<
string
,
string
>;
};
​
RewindFilesResult
Result of a
rewindFiles()
operation.
type
RewindFilesResult
=
{
canRewind
:
boolean
;
error
?:
string
;
filesChanged
?:
string
[];
insertions
?:
number
;
deletions
?:
number
;
};
​
SDKStatusMessage
Status update message (e.g., compacting).
type
SDKStatusMessage
=
{
type
:
"system"
;
subtype
:
"status"
;
status
:
"compacting"
|
null
;
permissionMode
?:
PermissionMode
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskNotificationMessage
Notification when a background task completes, fails, or is stopped. Background tasks include
run_in_background
Bash commands,
Monitor
watches, and background subagents.
type
SDKTaskNotificationMessage
=
{
type
:
"system"
;
subtype
:
"task_notification"
;
task_id
:
string
;
tool_use_id
?:
string
;
status
:
"completed"
|
"failed"
|
"stopped"
;
output_file
:
string
;
summary
:
string
;
usage
?:
{
total_tokens
:
number
;
tool_uses
:
number
;
duration_ms
:
number
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKToolUseSummaryMessage
Summary of tool usage in a conversation.
type
SDKToolUseSummaryMessage
=
{
type
:
"tool_use_summary"
;
summary
:
string
;
preceding_tool_use_ids
:
string
[];
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookStartedMessage
Emitted when a hook begins executing.
type
SDKHookStartedMessage
=
{
type
:
"system"
;
subtype
:
"hook_started"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookProgressMessage
Emitted while a hook is running, with stdout/stderr output.
type
SDKHookProgressMessage
=
{
type
:
"system"
;
subtype
:
"hook_progress"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
stdout
:
string
;
stderr
:
string
;
output
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKHookResponseMessage
Emitted when a hook finishes executing.
type
SDKHookResponseMessage
=
{
type
:
"system"
;
subtype
:
"hook_response"
;
hook_id
:
string
;
hook_name
:
string
;
hook_event
:
string
;
output
:
string
;
stdout
:
string
;
stderr
:
string
;
exit_code
?:
number
;
outcome
:
"success"
|
"error"
|
"cancelled"
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKToolProgressMessage
Emitted periodically while a tool is executing to indicate progress.
type
SDKToolProgressMessage
=
{
type
:
"tool_progress"
;
tool_use_id
:
string
;
tool_name
:
string
;
parent_tool_use_id
:
string
|
null
;
elapsed_time_seconds
:
number
;
task_id
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKAuthStatusMessage
Emitted during authentication flows.
type
SDKAuthStatusMessage
=
{
type
:
"auth_status"
;
isAuthenticating
:
boolean
;
output
:
string
[];
error
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskStartedMessage
Emitted when a background task begins. The
task_type
field is
"local_bash"
for background Bash commands and
Monitor
watches,
"local_agent"
for subagents, or
"remote_agent"
.
type
SDKTaskStartedMessage
=
{
type
:
"system"
;
subtype
:
"task_started"
;
task_id
:
string
;
tool_use_id
?:
string
;
description
:
string
;
task_type
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskProgressMessage
Emitted periodically while a background task is running.
type
SDKTaskProgressMessage
=
{
type
:
"system"
;
subtype
:
"task_progress"
;
task_id
:
string
;
tool_use_id
?:
string
;
description
:
string
;
usage
:
{
total_tokens
:
number
;
tool_uses
:
number
;
duration_ms
:
number
;
};
last_tool_name
?:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKTaskUpdatedMessage
Emitted when a background task’s state changes, such as when it transitions from
running
to
completed
. Merge
patch
into your local task map keyed by
task_id
. The
end_time
field is a Unix epoch timestamp in milliseconds, comparable with
Date.now()
.
type
SDKTaskUpdatedMessage
=
{
type
:
"system"
;
subtype
:
"task_updated"
;
task_id
:
string
;
patch
:
{
status
?:
"pending"
|
"running"
|
"completed"
|
"failed"
|
"killed"
;
description
?:
string
;
end_time
?:
number
;
total_paused_ms
?:
number
;
error
?:
string
;
is_backgrounded
?:
boolean
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKFilesPersistedEvent
Emitted when file checkpoints are persisted to disk.
type
SDKFilesPersistedEvent
=
{
type
:
"system"
;
subtype
:
"files_persisted"
;
files
:
{
filename
:
string
;
file_id
:
string
}[];
failed
:
{
filename
:
string
;
error
:
string
}[];
processed_at
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKRateLimitEvent
Emitted when the session encounters a rate limit.
type
SDKRateLimitEvent
=
{
type
:
"rate_limit_event"
;
rate_limit_info
:
{
status
:
"allowed"
|
"allowed_warning"
|
"rejected"
;
resetsAt
?:
number
;
utilization
?:
number
;
};
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKLocalCommandOutputMessage
Output from a local slash command (for example,
/voice
or
/usage
). Displayed as assistant-style text in the transcript.
type
SDKLocalCommandOutputMessage
=
{
type
:
"system"
;
subtype
:
"local_command_output"
;
content
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
SDKPromptSuggestionMessage
Emitted after each turn when
promptSuggestions
is enabled. Contains a predicted next user prompt.
type
SDKPromptSuggestionMessage
=
{
type
:
"prompt_suggestion"
;
suggestion
:
string
;
uuid
:
UUID
;
session_id
:
string
;
};
​
AbortError
Custom error class for abort operations.
class
AbortError
extends
Error
{}
​
Sandbox Configuration
​
SandboxSettings
Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.
type
SandboxSettings
=
{
enabled
?:
boolean
;
autoAllowBashIfSandboxed
?:
boolean
;
excludedCommands
?:
string
[];
allowUnsandboxedCommands
?:
boolean
;
network
?:
SandboxNetworkConfig
;
filesystem
?:
SandboxFilesystemConfig
;
ignoreViolations
?:
Record
<
string
,
string
[]>;
enableWeakerNestedSandbox
?:
boolean
;
ripgrep
?:
{
command
:
string
;
args
?:
string
[] };
};
Property
Type
Default
Description
enabled
boolean
false
Enable sandbox mode for command execution
autoAllowBashIfSandboxed
boolean
true
Auto-approve bash commands when sandbox is enabled
excludedCommands
string[]
[]
Commands that always bypass sandbox restrictions (e.g.,
['docker']
). These run unsandboxed automatically without model involvement
allowUnsandboxedCommands
boolean
true
Allow the model to request running commands outside the sandbox. When
true
, the model can set
dangerouslyDisableSandbox
in tool input, which falls back to the
permissions system
network
SandboxNetworkConfig
undefined
Network-specific sandbox configuration
filesystem
SandboxFilesystemConfig
undefined
Filesystem-specific sandbox configuration for read/write restrictions
ignoreViolations
Record<string, string[]>
undefined
Map of violation categories to patterns to ignore (e.g.,
{ file: ['/tmp/*'], network: ['localhost'] }
)
enableWeakerNestedSandbox
boolean
false
Enable a weaker nested sandbox for compatibility
ripgrep
{ command: string; args?: string[] }
undefined
Custom ripgrep binary configuration for sandbox environments
​
Example usage
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Build and test my project"
,
options:
{
sandbox:
{
enabled:
true
,
autoAllowBashIfSandboxed:
true
,
network:
{
allowLocalBinding:
true
}
}
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
Unix socket security:
The
allowUnixSockets
option can grant access to powerful system services. For example, allowing
/var/run/docker.sock
effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.
​
SandboxNetworkConfig
Network-specific configuration for sandbox mode.
type
SandboxNetworkConfig
=
{
allowedDomains
?:
string
[];
deniedDomains
?:
string
[];
allowManagedDomainsOnly
?:
boolean
;
allowLocalBinding
?:
boolean
;
allowUnixSockets
?:
string
[];
allowAllUnixSockets
?:
boolean
;
httpProxyPort
?:
number
;
socksProxyPort
?:
number
;
};
Property
Type
Default
Description
allowedDomains
string[]
[]
Domain names that sandboxed processes can access
deniedDomains
string[]
[]
Domain names that sandboxed processes cannot access. Takes precedence over
allowedDomains
allowManagedDomainsOnly
boolean
false
Restrict network access to only the domains in
allowedDomains
allowLocalBinding
boolean
false
Allow processes to bind to local ports (e.g., for dev servers)
allowUnixSockets
string[]
[]
Unix socket paths that processes can access (e.g., Docker socket)
allowAllUnixSockets
boolean
false
Allow access to all Unix sockets
httpProxyPort
number
undefined
HTTP proxy port for network requests
socksProxyPort
number
undefined
SOCKS proxy port for network requests
The built-in sandbox proxy enforces
allowedDomains
based on the requested hostname and does not terminate or inspect TLS traffic, so techniques such as
domain fronting
can potentially bypass it. See
Sandboxing security limitations
for details and
Secure deployment
for configuring a TLS-terminating proxy.
​
SandboxFilesystemConfig
Filesystem-specific configuration for sandbox mode.
type
SandboxFilesystemConfig
=
{
allowWrite
?:
string
[];
denyWrite
?:
string
[];
denyRead
?:
string
[];
};
Property
Type
Default
Description
allowWrite
string[]
[]
File path patterns to allow write access to
denyWrite
string[]
[]
File path patterns to deny write access to
denyRead
string[]
[]
File path patterns to deny read access to
​
Permissions Fallback for Unsandboxed Commands
When
allowUnsandboxedCommands
is enabled, the model can request to run commands outside the sandbox by setting
dangerouslyDisableSandbox: true
in the tool input. These requests fall back to the existing permissions system, meaning your
canUseTool
handler is invoked, allowing you to implement custom authorization logic.
excludedCommands
vs
allowUnsandboxedCommands
:
excludedCommands
: A static list of commands that always bypass the sandbox automatically (e.g.,
['docker']
). The model has no control over this.
allowUnsandboxedCommands
: Lets the model decide at runtime whether to request unsandboxed execution by setting
dangerouslyDisableSandbox: true
in the tool input.
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Deploy my application"
,
options:
{
sandbox:
{
enabled:
true
,
allowUnsandboxedCommands:
true
// Model can request unsandboxed execution
},
permissionMode:
"default"
,
canUseTool
:
async
(
tool
,
input
)
=>
{
// Check if the model is requesting to bypass the sandbox
if
(
tool
===
"Bash"
&&
input
.
dangerouslyDisableSandbox
) {
// The model is requesting to run this command outside the sandbox
console
.
log
(
`Unsandboxed command requested:
${
input
.
command
}
`
);
if
(
isCommandAuthorized
(
input
.
command
)) {
return
{
behavior:
"allow"
as
const
,
updatedInput:
input
};
}
return
{
behavior:
"deny"
as
const
,
message:
"Command not authorized for unsandboxed execution"
};
}
return
{
behavior:
"allow"
as
const
,
updatedInput:
input
};
}
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
This pattern enables you to:
Audit model requests:
Log when the model requests unsandboxed execution
Implement allowlists:
Only permit specific commands to run unsandboxed
Add approval workflows:
Require explicit authorization for privileged operations
Commands running with
dangerouslyDisableSandbox: true
have full system access. Ensure your
canUseTool
handler validates these requests carefully.
If
permissionMode
is set to
bypassPermissions
and
allowUnsandboxedCommands
is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.
​
See also
SDK overview
- General SDK concepts
Python SDK reference
- Python SDK documentation
CLI reference
- Command-line interface
Common workflows
- Step-by-step guides
Was this page helpful?
Yes
No
Securely deploying AI agents
TypeScript V2 (deprecated)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/typescript" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Troubleshoot installation and login</title>
  <link>https://code.claude.com/docs/en/troubleshoot-install</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/troubleshoot-install</guid>
  <pubDate>Tue, 13 Feb 2024 00:00:00 +0000</pubDate>
  <category>Troubleshooting</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshoot installation and login
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshoot installation and login
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
If installation fails or you can’t sign in, find your error below. For runtime issues after Claude Code is working, see
Troubleshooting
. For configuration problems such as settings not applying or hooks not firing, see
Debug your configuration
.
​
Find your error
Match the error message or symptom you’re seeing to a fix:
What you see
Solution
command not found: claude
or
'claude' is not recognized
Fix your PATH
syntax error near unexpected token '<'
Install script returns HTML
curl: (56) Failure writing output to destination
Check connectivity or use an alternative installer
Killed
during install on Linux
Add swap space for low-memory servers
TLS connect error
or
SSL/TLS secure channel
Update CA certificates
Failed to fetch version
or can’t reach download server
Check network and proxy settings
irm is not recognized
or
&& is not valid
Use the right command for your shell
'bash' is not recognized as the name of a cmdlet
Use the Windows installer command
Claude Code on Windows requires either Git for Windows (for bash) or PowerShell
Install a shell
Claude Code does not support 32-bit Windows
Open Windows PowerShell, not the x86 entry
The process cannot access the file ... because it is being used by another process
Clear the downloads folder and retry
Error loading shared library
Wrong binary variant for your system
Illegal instruction
Architecture or CPU instruction set mismatch
cannot execute binary file: Exec format error
in WSL
WSL1 native-binary regression
PowerShell installer completes but
claude
is not found or shows an old version
Restart your terminal and verify PATH
dyld: cannot load
,
dyld: Symbol not found
, or
Abort trap
on macOS
Binary incompatibility
Invoke-Expression: Missing argument in parameter list
Install script returns HTML
App unavailable in region
Claude Code is not available in your country. See
supported countries
.
unable to get local issuer certificate
Configure corporate CA certificates
OAuth error
or
403 Forbidden
Fix authentication
Could not load the default credentials
or
Could not load credentials from any providers
Bedrock, Vertex, or Foundry credentials
ChainedTokenCredential authentication failed
or
CredentialUnavailableError
Bedrock, Vertex, or Foundry credentials
API Error: 500
,
529 Overloaded
,
429
, or other 4xx and 5xx errors not listed above
See the
Error reference
If your issue isn’t listed, work through the diagnostic checks below to narrow down the cause.
If you’d rather skip the terminal entirely, the
Claude Code Desktop app
lets you install and use Claude Code through a graphical interface. Download it for
macOS
or
Windows
and start coding without any command-line setup.
​
Run diagnostic checks
​
Check network connectivity
The installer downloads from
downloads.claude.ai
. Verify you can reach it:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
An
HTTP/2 200
line means you reached the server. If you see no output,
Could not resolve host
, or a connection timeout, your network is blocking the connection. Common causes:
Corporate firewalls or proxies blocking
downloads.claude.ai
Regional network restrictions: try a VPN or alternative network
TLS/SSL issues: update your system’s CA certificates, or check if
HTTPS_PROXY
is configured
If you’re behind a corporate proxy, set
HTTPS_PROXY
and
HTTP_PROXY
to your proxy’s address before installing. Ask your IT team for the proxy URL if you don’t know it, or check your browser’s proxy settings.
This example sets both proxy variables, then runs the installer through your proxy:
macOS/Linux
Windows PowerShell
export
HTTP_PROXY
=
http
://
proxy
.
example
.
com
:
8080
export
HTTPS_PROXY
=
http
://
proxy
.
example
.
com
:
8080
curl
-fsSL
https://claude.ai/install.sh
|
bash
$
env:
HTTP_PROXY
=
'http://proxy.example.com:8080'
$
env:
HTTPS_PROXY
=
'http://proxy.example.com:8080'
irm https:
//
claude.ai
/
install.ps1
|
iex
​
Verify your PATH
If installation succeeded but you get a
command not found
or
not recognized
error when running
claude
, the install directory isn’t in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places
claude
at
~/.local/bin/claude
on macOS/Linux or
%USERPROFILE%\.local\bin\claude.exe
on Windows.
Check if the install directory is in your PATH by listing your PATH entries and filtering for
local/bin
:
macOS/Linux
Windows PowerShell
Windows CMD
echo
$PATH
|
tr
':'
'\n'
|
grep
-Fx
"
$HOME
/.local/bin"
If this prints
/Users/you/.local/bin
or
/home/you/.local/bin
, the directory is in your PATH and you can skip to
Check for conflicting installations
. If there’s no output, add it to your shell configuration.
For Zsh, the default on macOS:
echo
'export PATH="$HOME/.local/bin:$PATH"'
>>
~/.zshrc
source
~/.zshrc
For Bash, the default on most Linux distributions:
echo
'export PATH="$HOME/.local/bin:$PATH"'
>>
~/.bashrc
source
~/.bashrc
Alternatively, close and reopen your terminal.
For other shells such as fish or Nushell, add
~/.local/bin
to your PATH using your shell’s own configuration syntax, then restart your terminal.
Verify the fix worked:
claude
--version
$
env:
PATH
-split
';'
|
Select-String
'\.local\\bin'
If there’s no output, add the install directory to your User PATH:
$currentPath
=
[
Environment
]::GetEnvironmentVariable(
'PATH'
,
'User'
)
[
Environment
]::SetEnvironmentVariable(
'PATH'
,
"
$currentPath
;
$
env:
USERPROFILE
\.local\bin"
,
'User'
)
Restart your terminal for the change to take effect.
Verify the fix worked:
claude
--
version
echo
%PATH%
|
findstr
/i
"local\bin"
If there’s no output, open System Settings, go to Environment Variables, and add
%USERPROFILE%\.local\bin
to your User PATH variable. Restart your terminal.
Verify the fix worked:
claude --version
​
Check for conflicting installations
Multiple Claude Code installations can cause version mismatches or unexpected behavior. Check what’s installed:
macOS/Linux
Windows PowerShell
List all
claude
binaries found in your PATH:
which
-a
claude
If this prints nothing, no
claude
is on your PATH yet. Go back to
Verify your PATH
.
Check the three locations a
claude
binary can come from.
~/.local/bin/claude
is the native installer,
~/.claude/local/
is a legacy local npm install created by older versions of Claude Code, and the npm global list shows a
-g
install:
ls
-la
~/.local/bin/claude
ls
-la
~/.claude/local/
npm
-g
ls
@anthropic-ai/claude-code
2>
/dev/null
List all
claude
binaries found in your PATH:
where.exe
claude
Check whether the native installer placed a binary:
Test-Path
"
$
env:
USERPROFILE
\.local\bin\claude.exe"
If you find multiple installations, keep only one. The native install at
~/.local/bin/claude
on macOS/Linux or
%USERPROFILE%\.local\bin\claude.exe
on Windows is recommended. Remove the extras:
Uninstall an npm global install:
npm
uninstall
-g
@anthropic-ai/claude-code
Remove the legacy local npm install:
rm
-rf
~/.claude/local
On Windows, use PowerShell:
Remove-Item
-
Recurse
-
Force
"
$
env:
USERPROFILE
\.claude\local"
Remove a Homebrew install on macOS. If you installed the
claude-code@latest
cask, substitute that name:
brew
uninstall
--cask
claude-code
Remove a WinGet install on Windows:
winget uninstall Anthropic.ClaudeCode
​
Check directory permissions
The installer needs write access to
~/.local/bin/
and
~/.claude/
on macOS and Linux. On Windows the install location is under
%USERPROFILE%
, which is writable by your user by default, so this section rarely applies there.
Check whether the directories are writable:
test
-w
~/.local/bin
&&
echo
"writable"
||
echo
"not writable"
test
-w
~/.claude
&&
echo
"writable"
||
echo
"not writable"
If either directory isn’t writable, create the install directory and set your user as the owner:
sudo
mkdir
-p
~/.local/bin
sudo
chown
-R
$(
whoami
)
~/.local
​
Verify the binary works
If
claude --version
prints a version but
claude
crashes or hangs on startup, run these checks to narrow down the cause. If
claude --version
says command not found, go to
Verify your PATH
first; the commands below assume
claude
is on your PATH.
Confirm the binary exists and is executable:
ls
-la
"$(
command
-v
claude)"
On Windows, use PowerShell:
Get-Command
claude
|
Select-Object
Source
On Linux, check for missing shared libraries. If
ldd
shows missing libraries, you may need to install system packages. On Alpine Linux and other musl-based distributions, see
Alpine Linux setup
.
ldd
"$(
command
-v
claude)"
|
grep
"not found"
Confirm the binary can execute:
claude
--version
​
Common installation issues
These are the most frequently encountered installation problems and their solutions.
​
Install script returns HTML instead of a shell script
When running the install command, you may see one of these errors:
bash: line 1: syntax error near unexpected token `<'
bash: line 1: `<!DOCTYPE html>'
On PowerShell, the same problem appears as:
Invoke-Expression: Missing argument in parameter list.
This means the install URL returned an HTML page instead of the install script. If the HTML page says “App unavailable in region,” Claude Code is not available in your country. See
supported countries
.
Otherwise, this can happen due to network issues, regional routing, or a temporary service disruption.
Solutions:
Use an alternative install method
:
On macOS, install via Homebrew:
brew
install
--cask
claude-code
On Windows, install via WinGet:
winget install Anthropic.ClaudeCode
Retry after a few minutes
: the issue is often temporary. Wait and try the original command again.
​
command not found: claude
after installation
The install finished but
claude
doesn’t work. The exact error varies by platform:
Platform
Error message
macOS
zsh: command not found: claude
Linux
bash: claude: command not found
Windows CMD
'claude' is not recognized as an internal or external command
PowerShell
claude : The term 'claude' is not recognized as the name of a cmdlet
This means the install directory isn’t in your shell’s search path. See
Verify your PATH
for the fix on each platform.
​
curl: (56) Failure writing output to destination
The
curl ... | bash
command downloads the script and pipes it to Bash for execution. This error means the connection broke before the script finished downloading. Common causes include network interruptions, the download being blocked mid-stream, or system resource limits.
Solutions:
Check network stability
: Claude Code binaries are hosted at
downloads.claude.ai
. Test that you can reach it:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
An
HTTP/2 200
line means you reached the server and the original failure was likely intermittent; retry the install command. If you see
Could not resolve host
or a connection timeout, your network is blocking the download.
Try an alternative install method
:
On macOS:
brew
install
--cask
claude-code
On Windows:
winget install Anthropic.ClaudeCode
​
TLS or SSL connection errors
Errors like
curl: (35) TLS connect error
,
schannel: next InitializeSecurityContext failed
, or PowerShell’s
Could not establish trust relationship for the SSL/TLS secure channel
indicate TLS handshake failures.
Solutions:
Update your system CA certificates
:
On Ubuntu/Debian:
sudo
apt-get
update
&&
sudo
apt-get
install
ca-certificates
On macOS, the system curl uses the Keychain trust store; updating macOS itself updates the root certificates.
On Windows, enable TLS 1.2
in PowerShell before running the installer:
[
Net.ServicePointManager
]::SecurityProtocol
=
[
Net.SecurityProtocolType
]::Tls12
irm https:
//
claude.ai
/
install.ps1
|
iex
Check for proxy or firewall interference
: corporate proxies that perform TLS inspection can cause these errors, including
unable to get local issuer certificate
and
SELF_SIGNED_CERT_IN_CHAIN
. For the install step, point curl at your corporate CA bundle with
--cacert
:
curl
--cacert
/path/to/corporate-ca.pem
-fsSL
https://claude.ai/install.sh
|
bash
For Claude Code itself once installed, set
NODE_EXTRA_CA_CERTS
so API requests trust the same bundle:
export
NODE_EXTRA_CA_CERTS
=
/
path
/
to
/
corporate-ca
.
pem
Ask your IT team for the certificate file if you don’t have it. You can also try on a direct connection to confirm the proxy is the cause.
On Windows, bypass certificate revocation checks
if you see
CRYPT_E_NO_REVOCATION_CHECK (0x80092012)
or
CRYPT_E_REVOCATION_OFFLINE (0x80092013)
. These mean curl reached the server but your network blocks the certificate revocation lookup, which is common behind corporate firewalls. Add
--ssl-revoke-best-effort
to the install command:
curl --ssl-revoke-best-effort -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
Alternatively, install with
winget install Anthropic.ClaudeCode
, which avoids curl entirely.
​
Failed to fetch version from downloads.claude.ai
The installer couldn’t reach the download server. This typically means
downloads.claude.ai
is blocked on your network.
Solutions:
Test connectivity directly
:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
If behind a proxy
, set
HTTPS_PROXY
so the installer can route through it. See
proxy configuration
for details.
export
HTTPS_PROXY
=
http
://
proxy
.
example
.
com
:
8080
curl
-fsSL
https://claude.ai/install.sh
|
bash
If on a restricted network
, try a different network or VPN, or use an alternative install method:
On macOS:
brew
install
--cask
claude-code
On Windows:
winget install Anthropic.ClaudeCode
​
Wrong install command on Windows
If you see
'irm' is not recognized
,
The token '&&' is not valid
, or
'bash' is not recognized as the name of a cmdlet
, you copied the install command for a different shell or operating system.
irm
not recognized
: you’re in CMD, not PowerShell. You have two options:
Open PowerShell by searching for “PowerShell” in the Start menu, then run the original install command:
irm https:
//
claude.ai
/
install.ps1
|
iex
Or stay in CMD and use the CMD installer instead:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
&&
not valid
: you’re in PowerShell but ran the CMD installer command. Use the PowerShell installer:
irm https:
//
claude.ai
/
install.ps1
|
iex
bash
not recognized
: you ran the macOS/Linux installer on Windows. Use the PowerShell installer instead:
irm https:
//
claude.ai
/
install.ps1
|
iex
​
The process cannot access the file
during Windows install
If the PowerShell installer fails with
Failed to download binary: The process cannot access the file ... because it is being used by another process
, the installer couldn’t write to
%USERPROFILE%\.claude\downloads
. This usually means a previous install attempt is still running, or antivirus software is scanning a partially downloaded binary in that folder.
Close any other PowerShell windows running the installer and wait for antivirus scans to release the file. Then delete the downloads folder and run the installer again:
Remove-Item
-
Recurse
-
Force
"
$
env:
USERPROFILE
\.claude\downloads"
irm https:
//
claude.ai
/
install.ps1
|
iex
​
Install killed on low-memory Linux servers
If you see
Killed
during installation on a VPS or cloud instance:
Setting up Claude Code...
Installing Claude Code native build latest...
bash: line 142: 34803 Killed    "$binary_path" install ${TARGET:+"$TARGET"}
The Linux OOM killer terminated the process because the system ran out of memory. Claude Code requires at least 4 GB of available RAM.
Solutions:
Add swap space
if your server has limited RAM. Swap uses disk space as overflow memory, letting the install complete even with low physical RAM.
Create a 2 GB swap file and enable it:
sudo
fallocate
-l
2G
/swapfile
sudo
chmod
600
/swapfile
sudo
mkswap
/swapfile
sudo
swapon
/swapfile
Then retry the installation:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Close other processes
to free memory before installing.
Use a larger instance
if possible. Claude Code requires at least 4 GB of RAM.
​
Install hangs in Docker
When installing Claude Code in a Docker container, installing as root into
/
can cause hangs.
Solutions:
Set a working directory
before running the installer. When run from
/
, the installer scans the entire filesystem, which causes excessive memory usage. Setting
WORKDIR
limits the scan to a small directory:
WORKDIR
/tmp
RUN
curl -fsSL https://claude.ai/install.sh | bash
Increase Docker memory limits
if using Docker Desktop:
docker
build
--memory=4g
.
​
Claude Desktop overrides the
claude
command on Windows
If you installed an older version of Claude Desktop, it may register a
Claude.exe
in the
WindowsApps
directory that takes PATH priority over Claude Code CLI. Running
claude
opens the Desktop app instead of the CLI.
Update Claude Desktop to the latest version to fix this issue.
​
Claude Code on Windows requires either Git for Windows (for bash) or PowerShell
Claude Code on native Windows needs at least one shell: either
Git for Windows
for Bash, or PowerShell. When neither is found, this error appears at startup. If only PowerShell is found, Claude Code uses the PowerShell tool instead of Bash.
If neither is installed
, install one:
Git for Windows: download from
git-scm.com/downloads/win
. During setup, select “Add to PATH.” Restart your terminal after installing.
PowerShell 7: download from
aka.ms/powershell
.
If Git is already installed
but Claude Code can’t find it, set the path in your
settings.json file
:
{
"env"
: {
"CLAUDE_CODE_GIT_BASH_PATH"
:
"C:
\\
Program Files
\\
Git
\\
bin
\\
bash.exe"
}
}
If your Git is installed somewhere else, find the path by running
where.exe git
in PowerShell and use the
bin\bash.exe
path from that directory.
​
Claude Code does not support 32-bit Windows
Windows includes two PowerShell entries in the Start menu:
Windows PowerShell
and
Windows PowerShell (x86)
. The x86 entry runs as a 32-bit process and triggers this error even on a 64-bit machine. To check which case you’re in, run this in the same window that produced the error:
[
Environment
]::Is64BitOperatingSystem
If this prints
True
, your operating system is fine. Close the window, open
Windows PowerShell
without the x86 suffix, and run the install command again.
If this prints
False
, you are on a 32-bit edition of Windows. Claude Code requires a 64-bit operating system. See the
system requirements
.
​
Linux musl or glibc binary mismatch
If you see errors about missing shared libraries like
libstdc++.so.6
or
libgcc_s.so.1
after installation, the installer may have downloaded the wrong binary variant for your system.
Error loading shared library libstdc++.so.6: No such file or directory
This can happen on glibc-based systems that have musl cross-compilation packages installed, causing the installer to misdetect the system as musl.
Solutions:
Check which libc your system uses
:
ldd
--version
2>&1
|
head
-1
Output mentioning
GNU libc
or
GLIBC
means glibc. Output mentioning
musl
means musl.
If you’re on glibc but got the musl binary
, remove the installation and reinstall. You can also manually download the correct binary using the manifest at
https://downloads.claude.ai/claude-code-releases/{VERSION}/manifest.json
. File a
GitHub issue
with the output of
ldd --version
and
ls /lib/libc.musl*
.
If you’re actually on musl
, such as Alpine Linux, install the required packages:
apk
add
libgcc
libstdc++
ripgrep
​
Illegal instruction
If running
claude
or the installer prints
Illegal instruction
, the native binary uses CPU instructions your processor doesn’t support. There are two distinct causes.
Architecture mismatch.
The installer downloaded the wrong binary, for example x86 on an ARM server. Check with
uname -m
on macOS or Linux, or
$env:PROCESSOR_ARCHITECTURE
in PowerShell. If the result doesn’t match the binary you received,
file a GitHub issue
with the output.
Missing AVX instruction set.
If your architecture is correct but you still see
Illegal instruction
, your CPU likely lacks AVX or another instruction the binary requires. This affects roughly pre-2013 Intel and AMD processors, and virtual machines where the hypervisor does not pass AVX through to the guest.
On a VPS or VM, run
grep -m1 -ow avx /proc/cpuinfo
; an empty result means AVX is not available to the guest.
There is no native-binary workaround; track
issue #50384
for status, and include your CPU model from
grep -m1 "model name" /proc/cpuinfo
on Linux or
sysctl -n machdep.cpu.brand_string
on macOS when reporting.
Alternative install methods download the same native binary and won’t resolve either cause.
​
dyld: cannot load
on macOS
If you see
dyld: cannot load
,
dyld: Symbol not found
, or
Abort trap: 6
during installation, the binary is incompatible with your macOS version or hardware.
dyld: cannot load 'claude-2.1.42-darwin-x64' (load command 0x80000034 is unknown)
Abort trap: 6
A
Symbol not found
error that references
libicucore
also indicates your macOS version is older than the binary supports:
dyld: Symbol not found: _ubrk_clone
Referenced from: claude-darwin-x64 (which was built for Mac OS X 13.0)
Expected in: /usr/lib/libicucore.A.dylib
Solutions:
Check your macOS version
: Claude Code requires macOS 13.0 or later. Open the Apple menu and select About This Mac to check your version.
Update macOS
if you’re on an older version. The binary uses load commands and system libraries that older macOS versions don’t support. Alternative install methods like Homebrew download the same binary and won’t resolve this error.
​
Exec format error
on WSL1
If running
claude
in WSL prints
cannot execute binary file: Exec format error
, you’re on WSL1 and hitting a known native-binary regression tracked in
issue #38788
. The binary’s program headers changed in a way WSL1’s loader can’t handle.
The cleanest fix is to convert your distribution to WSL2 from PowerShell:
wsl
--
set-version
<
DistroName
>
2
If you need to stay on WSL1, invoke the binary through the dynamic linker. Add this function to
~/.bashrc
inside WSL, replacing the path if your home directory differs:
claude
() {
/lib64/ld-linux-x86-64.so.2
"$(
readlink
-f
"
$HOME
/.local/bin/claude")"
"
$@
"
}
Then run
source ~/.bashrc
and retry
claude
.
​
npm install errors in WSL
These issues apply if you installed Claude Code with
npm install -g
inside WSL. If you used the
native installer
, skip this section.
OS or platform detection issues.
If npm reports a platform mismatch during install, WSL is likely picking up the Windows
npm
. Run
npm config set os linux
first, then install with
npm install -g @anthropic-ai/claude-code --force
. Do not use
sudo
.
exec: node: not found
when running
claude
.
Your WSL environment is likely using the Windows installation of Node.js. Confirm with
which npm
and
which node
: paths starting with
/mnt/c/
are Windows binaries, while Linux paths start with
/usr/
. To fix this, install Node via your Linux distribution’s package manager or via
nvm
.
nvm version conflicts.
If you have nvm installed in both WSL and Windows, switching Node versions in WSL may break because WSL imports the Windows PATH by default and the Windows nvm takes priority. The most common cause is that nvm isn’t loaded in your shell. Add the nvm loader to
~/.bashrc
or
~/.zshrc
:
export
NVM_DIR
=
"
$HOME
/.nvm"
[
-s
"
$NVM_DIR
/nvm.sh"
] &&
\.
"
$NVM_DIR
/nvm.sh"
[
-s
"
$NVM_DIR
/bash_completion"
] &&
\.
"
$NVM_DIR
/bash_completion"
Or load it in your current session:
source
~/.nvm/nvm.sh
If nvm is loaded but Windows paths still take priority, prepend your Linux Node path explicitly:
export
PATH
=
"
$HOME
/.nvm/versions/node/$(
node
-v
)/bin:
$PATH
"
Avoid disabling Windows PATH importing via
appendWindowsPath = false
as this breaks the ability to call Windows executables from WSL. Similarly, avoid uninstalling Node.js from Windows if you use it for Windows development.
​
Permission errors during installation
If the native installer fails with permission errors, the target directory may not be writable. See
Check directory permissions
.
If you previously installed with npm and are hitting npm-specific permission errors, switch to the native installer:
curl
-fsSL
https://claude.ai/install.sh
|
bash
​
Native binary not found after npm install
The
@anthropic-ai/claude-code
npm package pulls in the native binary through a per-platform optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
. If running
claude
after install prints
Could not find native binary package "@anthropic-ai/claude-code-<platform>"
, check the following causes:
Optional dependencies are disabled.
Remove
--omit=optional
from your npm install command,
--no-optional
from pnpm, or
--ignore-optional
from yarn, and check that
.npmrc
does not set
optional=false
. Then reinstall. The native binary is delivered only as an optional dependency, so there is no JavaScript fallback if it is skipped.
Unsupported platform.
Prebuilt binaries are published for
darwin-arm64
,
darwin-x64
,
linux-x64
,
linux-arm64
,
linux-x64-musl
,
linux-arm64-musl
,
win32-x64
, and
win32-arm64
. Claude Code does not ship a binary for other platforms; see the
system requirements
.
Corporate npm mirror is missing the platform packages.
Ensure your registry mirrors all eight
@anthropic-ai/claude-code-*
platform packages in addition to the meta package.
Installing with
--ignore-scripts
does not trigger this error. The postinstall step that links the binary into place is skipped, so Claude Code falls back to a wrapper that locates and spawns the platform binary on each launch. This works but starts more slowly; reinstall with scripts enabled for direct execution.
​
Login and authentication
These sections address login failures, OAuth errors, and token issues.
​
Reset your login
When login fails and the cause isn’t obvious, a clean re-authentication resolves most cases:
Run
/logout
to sign out completely
Close Claude Code
Restart with
claude
and complete the authentication process again
If the browser doesn’t open automatically during login, press
c
to copy the OAuth URL to your clipboard, then paste it into a browser manually. This also works when the URL wraps across lines in a narrow or SSH terminal and can’t be clicked directly.
​
OAuth error: Invalid code
If you see
OAuth error: Invalid code. Please make sure the full code was copied
, the login code expired or was truncated during copy-paste.
Solutions:
Press Enter to retry and complete the login quickly after the browser opens
Type
c
to copy the full URL if the browser doesn’t open automatically
If using a remote/SSH session, the browser may open on the wrong machine. Copy the URL displayed in the terminal and open it in your local browser instead.
​
403 Forbidden after login
If you see
API Error: 403 {"error":{"type":"forbidden","message":"Request not allowed"}}
after logging in:
Claude Pro/Max users
: verify your subscription is active at
claude.ai/settings
Anthropic Console users
: confirm your account has the “Claude Code” or “Developer” role. Admins assign this in the Anthropic Console under Settings → Members.
Behind a proxy
: corporate proxies can interfere with API requests. See
network configuration
for proxy setup.
​
This organization has been disabled with an active subscription
If you see
API Error: 400 ... "This organization has been disabled"
despite having an active Claude subscription, an
ANTHROPIC_API_KEY
environment variable is overriding your subscription. This commonly happens when an old API key from a previous employer or project is still set in your shell profile.
When
ANTHROPIC_API_KEY
is present and you have approved it, Claude Code uses that key instead of your subscription’s OAuth credentials. In non-interactive mode with the
-p
flag, the key is always used when present. See
authentication precedence
for the full resolution order.
To use your subscription instead, unset the environment variable and remove it from your shell profile:
unset
ANTHROPIC_API_KEY
claude
Check
~/.zshrc
,
~/.bashrc
, or
~/.profile
for
export ANTHROPIC_API_KEY=...
lines and remove them to make the change permanent. On Windows, check your PowerShell profile at
$PROFILE
and your User environment variables for
ANTHROPIC_API_KEY
. Run
/status
inside Claude Code to confirm which authentication method is active.
​
OAuth login fails in WSL2, SSH, or containers
When Claude Code runs in WSL2, on a remote machine over SSH, or inside a container, the browser usually opens on a different host and its redirect can’t reach Claude Code’s local callback server. After you sign in, the browser shows a login code instead of redirecting back automatically. Paste that code into the terminal at the
Paste code here if prompted
prompt to complete login.
If the browser doesn’t open at all from WSL2, set the
BROWSER
environment variable to your Windows browser path:
export
BROWSER
=
"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
claude
Alternatively, press
c
at the interactive login prompt to copy the OAuth URL, or copy the URL that
claude auth login
prints, and open it in a browser on your local machine.
If pasting the code into the interactive prompt does nothing, your terminal’s paste binding likely isn’t reaching the input field. Try your terminal’s alternate paste shortcut, often right-click or Shift+Insert in Windows Terminal, or use
claude auth login
instead, which reads the pasted code from standard input:
claude
auth
login
This fallback also applies on native Windows or any terminal where pasting into the interactive prompt fails.
​
Not logged in or token expired
If Claude Code prompts you to log in again after a session, your OAuth token may have expired.
Run
/login
to re-authenticate. If this happens frequently, check that your system clock is accurate, as token validation depends on correct timestamps.
On macOS, login can also fail when the Keychain is locked or its password is out of sync with your account password, which prevents Claude Code from saving credentials. Run
claude doctor
to check Keychain access. To unlock the Keychain manually, run
security unlock-keychain ~/Library/Keychains/login.keychain-db
. If unlocking doesn’t help, open Keychain Access, select the
login
keychain, and choose Edit > Change Password for Keychain “login” to resync it with your account password.
​
Bedrock, Vertex, or Foundry credentials not loading
If you configured Claude Code to use a cloud provider and see
Could not load credentials from any providers
on Bedrock,
Could not load the default credentials
on Vertex, or
ChainedTokenCredential authentication failed
on Foundry, your cloud provider CLI is likely not authenticated in the current shell.
For Bedrock, confirm your AWS credentials are valid:
aws
sts
get-caller-identity
For Vertex AI, confirm
ANTHROPIC_VERTEX_PROJECT_ID
and
CLOUD_ML_REGION
are set in your shell, then set application default credentials:
gcloud
auth
application-default
login
For Microsoft Foundry, confirm
ANTHROPIC_FOUNDRY_API_KEY
is set, or sign in with the Azure CLI so the default credential chain can find your account:
az
login
If credentials work in your terminal but not in the VS Code or JetBrains extension, the IDE process likely didn’t inherit your shell environment. Set the provider environment variables in the IDE’s own settings, or launch the IDE from a terminal where they’re already exported.
See
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
for full provider setup.
​
Still stuck
If none of the above resolves your issue:
Check the
GitHub repository
for known issues, or open a new one with your operating system, the install command you ran, and the full error output
If
claude --version
works but something else is wrong, run
claude doctor
for an automated diagnostic report
If you can start a session, use
/feedback
inside Claude Code to report the problem
Was this page helpful?
Yes
No
Launch sessions from links
Troubleshoot performance and stability
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/troubleshoot-install" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshoot installation and login
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Troubleshooting
Troubleshoot installation and login
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
If installation fails or you can’t sign in, find your error below. For runtime issues after Claude Code is working, see
Troubleshooting
. For configuration problems such as settings not applying or hooks not firing, see
Debug your configuration
.
​
Find your error
Match the error message or symptom you’re seeing to a fix:
What you see
Solution
command not found: claude
or
'claude' is not recognized
Fix your PATH
syntax error near unexpected token '<'
Install script returns HTML
curl: (56) Failure writing output to destination
Check connectivity or use an alternative installer
Killed
during install on Linux
Add swap space for low-memory servers
TLS connect error
or
SSL/TLS secure channel
Update CA certificates
Failed to fetch version
or can’t reach download server
Check network and proxy settings
irm is not recognized
or
&& is not valid
Use the right command for your shell
'bash' is not recognized as the name of a cmdlet
Use the Windows installer command
Claude Code on Windows requires either Git for Windows (for bash) or PowerShell
Install a shell
Claude Code does not support 32-bit Windows
Open Windows PowerShell, not the x86 entry
The process cannot access the file ... because it is being used by another process
Clear the downloads folder and retry
Error loading shared library
Wrong binary variant for your system
Illegal instruction
Architecture or CPU instruction set mismatch
cannot execute binary file: Exec format error
in WSL
WSL1 native-binary regression
PowerShell installer completes but
claude
is not found or shows an old version
Restart your terminal and verify PATH
dyld: cannot load
,
dyld: Symbol not found
, or
Abort trap
on macOS
Binary incompatibility
Invoke-Expression: Missing argument in parameter list
Install script returns HTML
App unavailable in region
Claude Code is not available in your country. See
supported countries
.
unable to get local issuer certificate
Configure corporate CA certificates
OAuth error
or
403 Forbidden
Fix authentication
Could not load the default credentials
or
Could not load credentials from any providers
Bedrock, Vertex, or Foundry credentials
ChainedTokenCredential authentication failed
or
CredentialUnavailableError
Bedrock, Vertex, or Foundry credentials
API Error: 500
,
529 Overloaded
,
429
, or other 4xx and 5xx errors not listed above
See the
Error reference
If your issue isn’t listed, work through the diagnostic checks below to narrow down the cause.
If you’d rather skip the terminal entirely, the
Claude Code Desktop app
lets you install and use Claude Code through a graphical interface. Download it for
macOS
or
Windows
and start coding without any command-line setup.
​
Run diagnostic checks
​
Check network connectivity
The installer downloads from
downloads.claude.ai
. Verify you can reach it:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
An
HTTP/2 200
line means you reached the server. If you see no output,
Could not resolve host
, or a connection timeout, your network is blocking the connection. Common causes:
Corporate firewalls or proxies blocking
downloads.claude.ai
Regional network restrictions: try a VPN or alternative network
TLS/SSL issues: update your system’s CA certificates, or check if
HTTPS_PROXY
is configured
If you’re behind a corporate proxy, set
HTTPS_PROXY
and
HTTP_PROXY
to your proxy’s address before installing. Ask your IT team for the proxy URL if you don’t know it, or check your browser’s proxy settings.
This example sets both proxy variables, then runs the installer through your proxy:
macOS/Linux
Windows PowerShell
export
HTTP_PROXY
=
http
://
proxy
.
example
.
com
:
8080
export
HTTPS_PROXY
=
http
://
proxy
.
example
.
com
:
8080
curl
-fsSL
https://claude.ai/install.sh
|
bash
$
env:
HTTP_PROXY
=
'http://proxy.example.com:8080'
$
env:
HTTPS_PROXY
=
'http://proxy.example.com:8080'
irm https:
//
claude.ai
/
install.ps1
|
iex
​
Verify your PATH
If installation succeeded but you get a
command not found
or
not recognized
error when running
claude
, the install directory isn’t in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places
claude
at
~/.local/bin/claude
on macOS/Linux or
%USERPROFILE%\.local\bin\claude.exe
on Windows.
Check if the install directory is in your PATH by listing your PATH entries and filtering for
local/bin
:
macOS/Linux
Windows PowerShell
Windows CMD
echo
$PATH
|
tr
':'
'\n'
|
grep
-Fx
"
$HOME
/.local/bin"
If this prints
/Users/you/.local/bin
or
/home/you/.local/bin
, the directory is in your PATH and you can skip to
Check for conflicting installations
. If there’s no output, add it to your shell configuration.
For Zsh, the default on macOS:
echo
'export PATH="$HOME/.local/bin:$PATH"'
>>
~/.zshrc
source
~/.zshrc
For Bash, the default on most Linux distributions:
echo
'export PATH="$HOME/.local/bin:$PATH"'
>>
~/.bashrc
source
~/.bashrc
Alternatively, close and reopen your terminal.
For other shells such as fish or Nushell, add
~/.local/bin
to your PATH using your shell’s own configuration syntax, then restart your terminal.
Verify the fix worked:
claude
--version
$
env:
PATH
-split
';'
|
Select-String
'\.local\\bin'
If there’s no output, add the install directory to your User PATH:
$currentPath
=
[
Environment
]::GetEnvironmentVariable(
'PATH'
,
'User'
)
[
Environment
]::SetEnvironmentVariable(
'PATH'
,
"
$currentPath
;
$
env:
USERPROFILE
\.local\bin"
,
'User'
)
Restart your terminal for the change to take effect.
Verify the fix worked:
claude
--
version
echo
%PATH%
|
findstr
/i
"local\bin"
If there’s no output, open System Settings, go to Environment Variables, and add
%USERPROFILE%\.local\bin
to your User PATH variable. Restart your terminal.
Verify the fix worked:
claude --version
​
Check for conflicting installations
Multiple Claude Code installations can cause version mismatches or unexpected behavior. Check what’s installed:
macOS/Linux
Windows PowerShell
List all
claude
binaries found in your PATH:
which
-a
claude
If this prints nothing, no
claude
is on your PATH yet. Go back to
Verify your PATH
.
Check the three locations a
claude
binary can come from.
~/.local/bin/claude
is the native installer,
~/.claude/local/
is a legacy local npm install created by older versions of Claude Code, and the npm global list shows a
-g
install:
ls
-la
~/.local/bin/claude
ls
-la
~/.claude/local/
npm
-g
ls
@anthropic-ai/claude-code
2>
/dev/null
List all
claude
binaries found in your PATH:
where.exe
claude
Check whether the native installer placed a binary:
Test-Path
"
$
env:
USERPROFILE
\.local\bin\claude.exe"
If you find multiple installations, keep only one. The native install at
~/.local/bin/claude
on macOS/Linux or
%USERPROFILE%\.local\bin\claude.exe
on Windows is recommended. Remove the extras:
Uninstall an npm global install:
npm
uninstall
-g
@anthropic-ai/claude-code
Remove the legacy local npm install:
rm
-rf
~/.claude/local
On Windows, use PowerShell:
Remove-Item
-
Recurse
-
Force
"
$
env:
USERPROFILE
\.claude\local"
Remove a Homebrew install on macOS. If you installed the
claude-code@latest
cask, substitute that name:
brew
uninstall
--cask
claude-code
Remove a WinGet install on Windows:
winget uninstall Anthropic.ClaudeCode
​
Check directory permissions
The installer needs write access to
~/.local/bin/
and
~/.claude/
on macOS and Linux. On Windows the install location is under
%USERPROFILE%
, which is writable by your user by default, so this section rarely applies there.
Check whether the directories are writable:
test
-w
~/.local/bin
&&
echo
"writable"
||
echo
"not writable"
test
-w
~/.claude
&&
echo
"writable"
||
echo
"not writable"
If either directory isn’t writable, create the install directory and set your user as the owner:
sudo
mkdir
-p
~/.local/bin
sudo
chown
-R
$(
whoami
)
~/.local
​
Verify the binary works
If
claude --version
prints a version but
claude
crashes or hangs on startup, run these checks to narrow down the cause. If
claude --version
says command not found, go to
Verify your PATH
first; the commands below assume
claude
is on your PATH.
Confirm the binary exists and is executable:
ls
-la
"$(
command
-v
claude)"
On Windows, use PowerShell:
Get-Command
claude
|
Select-Object
Source
On Linux, check for missing shared libraries. If
ldd
shows missing libraries, you may need to install system packages. On Alpine Linux and other musl-based distributions, see
Alpine Linux setup
.
ldd
"$(
command
-v
claude)"
|
grep
"not found"
Confirm the binary can execute:
claude
--version
​
Common installation issues
These are the most frequently encountered installation problems and their solutions.
​
Install script returns HTML instead of a shell script
When running the install command, you may see one of these errors:
bash: line 1: syntax error near unexpected token `<'
bash: line 1: `<!DOCTYPE html>'
On PowerShell, the same problem appears as:
Invoke-Expression: Missing argument in parameter list.
This means the install URL returned an HTML page instead of the install script. If the HTML page says “App unavailable in region,” Claude Code is not available in your country. See
supported countries
.
Otherwise, this can happen due to network issues, regional routing, or a temporary service disruption.
Solutions:
Use an alternative install method
:
On macOS, install via Homebrew:
brew
install
--cask
claude-code
On Windows, install via WinGet:
winget install Anthropic.ClaudeCode
Retry after a few minutes
: the issue is often temporary. Wait and try the original command again.
​
command not found: claude
after installation
The install finished but
claude
doesn’t work. The exact error varies by platform:
Platform
Error message
macOS
zsh: command not found: claude
Linux
bash: claude: command not found
Windows CMD
'claude' is not recognized as an internal or external command
PowerShell
claude : The term 'claude' is not recognized as the name of a cmdlet
This means the install directory isn’t in your shell’s search path. See
Verify your PATH
for the fix on each platform.
​
curl: (56) Failure writing output to destination
The
curl ... | bash
command downloads the script and pipes it to Bash for execution. This error means the connection broke before the script finished downloading. Common causes include network interruptions, the download being blocked mid-stream, or system resource limits.
Solutions:
Check network stability
: Claude Code binaries are hosted at
downloads.claude.ai
. Test that you can reach it:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
An
HTTP/2 200
line means you reached the server and the original failure was likely intermittent; retry the install command. If you see
Could not resolve host
or a connection timeout, your network is blocking the download.
Try an alternative install method
:
On macOS:
brew
install
--cask
claude-code
On Windows:
winget install Anthropic.ClaudeCode
​
TLS or SSL connection errors
Errors like
curl: (35) TLS connect error
,
schannel: next InitializeSecurityContext failed
, or PowerShell’s
Could not establish trust relationship for the SSL/TLS secure channel
indicate TLS handshake failures.
Solutions:
Update your system CA certificates
:
On Ubuntu/Debian:
sudo
apt-get
update
&&
sudo
apt-get
install
ca-certificates
On macOS, the system curl uses the Keychain trust store; updating macOS itself updates the root certificates.
On Windows, enable TLS 1.2
in PowerShell before running the installer:
[
Net.ServicePointManager
]::SecurityProtocol
=
[
Net.SecurityProtocolType
]::Tls12
irm https:
//
claude.ai
/
install.ps1
|
iex
Check for proxy or firewall interference
: corporate proxies that perform TLS inspection can cause these errors, including
unable to get local issuer certificate
and
SELF_SIGNED_CERT_IN_CHAIN
. For the install step, point curl at your corporate CA bundle with
--cacert
:
curl
--cacert
/path/to/corporate-ca.pem
-fsSL
https://claude.ai/install.sh
|
bash
For Claude Code itself once installed, set
NODE_EXTRA_CA_CERTS
so API requests trust the same bundle:
export
NODE_EXTRA_CA_CERTS
=
/
path
/
to
/
corporate-ca
.
pem
Ask your IT team for the certificate file if you don’t have it. You can also try on a direct connection to confirm the proxy is the cause.
On Windows, bypass certificate revocation checks
if you see
CRYPT_E_NO_REVOCATION_CHECK (0x80092012)
or
CRYPT_E_REVOCATION_OFFLINE (0x80092013)
. These mean curl reached the server but your network blocks the certificate revocation lookup, which is common behind corporate firewalls. Add
--ssl-revoke-best-effort
to the install command:
curl --ssl-revoke-best-effort -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
Alternatively, install with
winget install Anthropic.ClaudeCode
, which avoids curl entirely.
​
Failed to fetch version from downloads.claude.ai
The installer couldn’t reach the download server. This typically means
downloads.claude.ai
is blocked on your network.
Solutions:
Test connectivity directly
:
curl
-sI
https://downloads.claude.ai/claude-code-releases/latest
If behind a proxy
, set
HTTPS_PROXY
so the installer can route through it. See
proxy configuration
for details.
export
HTTPS_PROXY
=
http
://
proxy
.
example
.
com
:
8080
curl
-fsSL
https://claude.ai/install.sh
|
bash
If on a restricted network
, try a different network or VPN, or use an alternative install method:
On macOS:
brew
install
--cask
claude-code
On Windows:
winget install Anthropic.ClaudeCode
​
Wrong install command on Windows
If you see
'irm' is not recognized
,
The token '&&' is not valid
, or
'bash' is not recognized as the name of a cmdlet
, you copied the install command for a different shell or operating system.
irm
not recognized
: you’re in CMD, not PowerShell. You have two options:
Open PowerShell by searching for “PowerShell” in the Start menu, then run the original install command:
irm https:
//
claude.ai
/
install.ps1
|
iex
Or stay in CMD and use the CMD installer instead:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
&&
not valid
: you’re in PowerShell but ran the CMD installer command. Use the PowerShell installer:
irm https:
//
claude.ai
/
install.ps1
|
iex
bash
not recognized
: you ran the macOS/Linux installer on Windows. Use the PowerShell installer instead:
irm https:
//
claude.ai
/
install.ps1
|
iex
​
The process cannot access the file
during Windows install
If the PowerShell installer fails with
Failed to download binary: The process cannot access the file ... because it is being used by another process
, the installer couldn’t write to
%USERPROFILE%\.claude\downloads
. This usually means a previous install attempt is still running, or antivirus software is scanning a partially downloaded binary in that folder.
Close any other PowerShell windows running the installer and wait for antivirus scans to release the file. Then delete the downloads folder and run the installer again:
Remove-Item
-
Recurse
-
Force
"
$
env:
USERPROFILE
\.claude\downloads"
irm https:
//
claude.ai
/
install.ps1
|
iex
​
Install killed on low-memory Linux servers
If you see
Killed
during installation on a VPS or cloud instance:
Setting up Claude Code...
Installing Claude Code native build latest...
bash: line 142: 34803 Killed    "$binary_path" install ${TARGET:+"$TARGET"}
The Linux OOM killer terminated the process because the system ran out of memory. Claude Code requires at least 4 GB of available RAM.
Solutions:
Add swap space
if your server has limited RAM. Swap uses disk space as overflow memory, letting the install complete even with low physical RAM.
Create a 2 GB swap file and enable it:
sudo
fallocate
-l
2G
/swapfile
sudo
chmod
600
/swapfile
sudo
mkswap
/swapfile
sudo
swapon
/swapfile
Then retry the installation:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Close other processes
to free memory before installing.
Use a larger instance
if possible. Claude Code requires at least 4 GB of RAM.
​
Install hangs in Docker
When installing Claude Code in a Docker container, installing as root into
/
can cause hangs.
Solutions:
Set a working directory
before running the installer. When run from
/
, the installer scans the entire filesystem, which causes excessive memory usage. Setting
WORKDIR
limits the scan to a small directory:
WORKDIR
/tmp
RUN
curl -fsSL https://claude.ai/install.sh | bash
Increase Docker memory limits
if using Docker Desktop:
docker
build
--memory=4g
.
​
Claude Desktop overrides the
claude
command on Windows
If you installed an older version of Claude Desktop, it may register a
Claude.exe
in the
WindowsApps
directory that takes PATH priority over Claude Code CLI. Running
claude
opens the Desktop app instead of the CLI.
Update Claude Desktop to the latest version to fix this issue.
​
Claude Code on Windows requires either Git for Windows (for bash) or PowerShell
Claude Code on native Windows needs at least one shell: either
Git for Windows
for Bash, or PowerShell. When neither is found, this error appears at startup. If only PowerShell is found, Claude Code uses the PowerShell tool instead of Bash.
If neither is installed
, install one:
Git for Windows: download from
git-scm.com/downloads/win
. During setup, select “Add to PATH.” Restart your terminal after installing.
PowerShell 7: download from
aka.ms/powershell
.
If Git is already installed
but Claude Code can’t find it, set the path in your
settings.json file
:
{
"env"
: {
"CLAUDE_CODE_GIT_BASH_PATH"
:
"C:
\\
Program Files
\\
Git
\\
bin
\\
bash.exe"
}
}
If your Git is installed somewhere else, find the path by running
where.exe git
in PowerShell and use the
bin\bash.exe
path from that directory.
​
Claude Code does not support 32-bit Windows
Windows includes two PowerShell entries in the Start menu:
Windows PowerShell
and
Windows PowerShell (x86)
. The x86 entry runs as a 32-bit process and triggers this error even on a 64-bit machine. To check which case you’re in, run this in the same window that produced the error:
[
Environment
]::Is64BitOperatingSystem
If this prints
True
, your operating system is fine. Close the window, open
Windows PowerShell
without the x86 suffix, and run the install command again.
If this prints
False
, you are on a 32-bit edition of Windows. Claude Code requires a 64-bit operating system. See the
system requirements
.
​
Linux musl or glibc binary mismatch
If you see errors about missing shared libraries like
libstdc++.so.6
or
libgcc_s.so.1
after installation, the installer may have downloaded the wrong binary variant for your system.
Error loading shared library libstdc++.so.6: No such file or directory
This can happen on glibc-based systems that have musl cross-compilation packages installed, causing the installer to misdetect the system as musl.
Solutions:
Check which libc your system uses
:
ldd
--version
2>&1
|
head
-1
Output mentioning
GNU libc
or
GLIBC
means glibc. Output mentioning
musl
means musl.
If you’re on glibc but got the musl binary
, remove the installation and reinstall. You can also manually download the correct binary using the manifest at
https://downloads.claude.ai/claude-code-releases/{VERSION}/manifest.json
. File a
GitHub issue
with the output of
ldd --version
and
ls /lib/libc.musl*
.
If you’re actually on musl
, such as Alpine Linux, install the required packages:
apk
add
libgcc
libstdc++
ripgrep
​
Illegal instruction
If running
claude
or the installer prints
Illegal instruction
, the native binary uses CPU instructions your processor doesn’t support. There are two distinct causes.
Architecture mismatch.
The installer downloaded the wrong binary, for example x86 on an ARM server. Check with
uname -m
on macOS or Linux, or
$env:PROCESSOR_ARCHITECTURE
in PowerShell. If the result doesn’t match the binary you received,
file a GitHub issue
with the output.
Missing AVX instruction set.
If your architecture is correct but you still see
Illegal instruction
, your CPU likely lacks AVX or another instruction the binary requires. This affects roughly pre-2013 Intel and AMD processors, and virtual machines where the hypervisor does not pass AVX through to the guest.
On a VPS or VM, run
grep -m1 -ow avx /proc/cpuinfo
; an empty result means AVX is not available to the guest.
There is no native-binary workaround; track
issue #50384
for status, and include your CPU model from
grep -m1 "model name" /proc/cpuinfo
on Linux or
sysctl -n machdep.cpu.brand_string
on macOS when reporting.
Alternative install methods download the same native binary and won’t resolve either cause.
​
dyld: cannot load
on macOS
If you see
dyld: cannot load
,
dyld: Symbol not found
, or
Abort trap: 6
during installation, the binary is incompatible with your macOS version or hardware.
dyld: cannot load 'claude-2.1.42-darwin-x64' (load command 0x80000034 is unknown)
Abort trap: 6
A
Symbol not found
error that references
libicucore
also indicates your macOS version is older than the binary supports:
dyld: Symbol not found: _ubrk_clone
Referenced from: claude-darwin-x64 (which was built for Mac OS X 13.0)
Expected in: /usr/lib/libicucore.A.dylib
Solutions:
Check your macOS version
: Claude Code requires macOS 13.0 or later. Open the Apple menu and select About This Mac to check your version.
Update macOS
if you’re on an older version. The binary uses load commands and system libraries that older macOS versions don’t support. Alternative install methods like Homebrew download the same binary and won’t resolve this error.
​
Exec format error
on WSL1
If running
claude
in WSL prints
cannot execute binary file: Exec format error
, you’re on WSL1 and hitting a known native-binary regression tracked in
issue #38788
. The binary’s program headers changed in a way WSL1’s loader can’t handle.
The cleanest fix is to convert your distribution to WSL2 from PowerShell:
wsl
--
set-version
<
DistroName
>
2
If you need to stay on WSL1, invoke the binary through the dynamic linker. Add this function to
~/.bashrc
inside WSL, replacing the path if your home directory differs:
claude
() {
/lib64/ld-linux-x86-64.so.2
"$(
readlink
-f
"
$HOME
/.local/bin/claude")"
"
$@
"
}
Then run
source ~/.bashrc
and retry
claude
.
​
npm install errors in WSL
These issues apply if you installed Claude Code with
npm install -g
inside WSL. If you used the
native installer
, skip this section.
OS or platform detection issues.
If npm reports a platform mismatch during install, WSL is likely picking up the Windows
npm
. Run
npm config set os linux
first, then install with
npm install -g @anthropic-ai/claude-code --force
. Do not use
sudo
.
exec: node: not found
when running
claude
.
Your WSL environment is likely using the Windows installation of Node.js. Confirm with
which npm
and
which node
: paths starting with
/mnt/c/
are Windows binaries, while Linux paths start with
/usr/
. To fix this, install Node via your Linux distribution’s package manager or via
nvm
.
nvm version conflicts.
If you have nvm installed in both WSL and Windows, switching Node versions in WSL may break because WSL imports the Windows PATH by default and the Windows nvm takes priority. The most common cause is that nvm isn’t loaded in your shell. Add the nvm loader to
~/.bashrc
or
~/.zshrc
:
export
NVM_DIR
=
"
$HOME
/.nvm"
[
-s
"
$NVM_DIR
/nvm.sh"
] &&
\.
"
$NVM_DIR
/nvm.sh"
[
-s
"
$NVM_DIR
/bash_completion"
] &&
\.
"
$NVM_DIR
/bash_completion"
Or load it in your current session:
source
~/.nvm/nvm.sh
If nvm is loaded but Windows paths still take priority, prepend your Linux Node path explicitly:
export
PATH
=
"
$HOME
/.nvm/versions/node/$(
node
-v
)/bin:
$PATH
"
Avoid disabling Windows PATH importing via
appendWindowsPath = false
as this breaks the ability to call Windows executables from WSL. Similarly, avoid uninstalling Node.js from Windows if you use it for Windows development.
​
Permission errors during installation
If the native installer fails with permission errors, the target directory may not be writable. See
Check directory permissions
.
If you previously installed with npm and are hitting npm-specific permission errors, switch to the native installer:
curl
-fsSL
https://claude.ai/install.sh
|
bash
​
Native binary not found after npm install
The
@anthropic-ai/claude-code
npm package pulls in the native binary through a per-platform optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
. If running
claude
after install prints
Could not find native binary package "@anthropic-ai/claude-code-<platform>"
, check the following causes:
Optional dependencies are disabled.
Remove
--omit=optional
from your npm install command,
--no-optional
from pnpm, or
--ignore-optional
from yarn, and check that
.npmrc
does not set
optional=false
. Then reinstall. The native binary is delivered only as an optional dependency, so there is no JavaScript fallback if it is skipped.
Unsupported platform.
Prebuilt binaries are published for
darwin-arm64
,
darwin-x64
,
linux-x64
,
linux-arm64
,
linux-x64-musl
,
linux-arm64-musl
,
win32-x64
, and
win32-arm64
. Claude Code does not ship a binary for other platforms; see the
system requirements
.
Corporate npm mirror is missing the platform packages.
Ensure your registry mirrors all eight
@anthropic-ai/claude-code-*
platform packages in addition to the meta package.
Installing with
--ignore-scripts
does not trigger this error. The postinstall step that links the binary into place is skipped, so Claude Code falls back to a wrapper that locates and spawns the platform binary on each launch. This works but starts more slowly; reinstall with scripts enabled for direct execution.
​
Login and authentication
These sections address login failures, OAuth errors, and token issues.
​
Reset your login
When login fails and the cause isn’t obvious, a clean re-authentication resolves most cases:
Run
/logout
to sign out completely
Close Claude Code
Restart with
claude
and complete the authentication process again
If the browser doesn’t open automatically during login, press
c
to copy the OAuth URL to your clipboard, then paste it into a browser manually. This also works when the URL wraps across lines in a narrow or SSH terminal and can’t be clicked directly.
​
OAuth error: Invalid code
If you see
OAuth error: Invalid code. Please make sure the full code was copied
, the login code expired or was truncated during copy-paste.
Solutions:
Press Enter to retry and complete the login quickly after the browser opens
Type
c
to copy the full URL if the browser doesn’t open automatically
If using a remote/SSH session, the browser may open on the wrong machine. Copy the URL displayed in the terminal and open it in your local browser instead.
​
403 Forbidden after login
If you see
API Error: 403 {"error":{"type":"forbidden","message":"Request not allowed"}}
after logging in:
Claude Pro/Max users
: verify your subscription is active at
claude.ai/settings
Anthropic Console users
: confirm your account has the “Claude Code” or “Developer” role. Admins assign this in the Anthropic Console under Settings → Members.
Behind a proxy
: corporate proxies can interfere with API requests. See
network configuration
for proxy setup.
​
This organization has been disabled with an active subscription
If you see
API Error: 400 ... "This organization has been disabled"
despite having an active Claude subscription, an
ANTHROPIC_API_KEY
environment variable is overriding your subscription. This commonly happens when an old API key from a previous employer or project is still set in your shell profile.
When
ANTHROPIC_API_KEY
is present and you have approved it, Claude Code uses that key instead of your subscription’s OAuth credentials. In non-interactive mode with the
-p
flag, the key is always used when present. See
authentication precedence
for the full resolution order.
To use your subscription instead, unset the environment variable and remove it from your shell profile:
unset
ANTHROPIC_API_KEY
claude
Check
~/.zshrc
,
~/.bashrc
, or
~/.profile
for
export ANTHROPIC_API_KEY=...
lines and remove them to make the change permanent. On Windows, check your PowerShell profile at
$PROFILE
and your User environment variables for
ANTHROPIC_API_KEY
. Run
/status
inside Claude Code to confirm which authentication method is active.
​
OAuth login fails in WSL2, SSH, or containers
When Claude Code runs in WSL2, on a remote machine over SSH, or inside a container, the browser usually opens on a different host and its redirect can’t reach Claude Code’s local callback server. After you sign in, the browser shows a login code instead of redirecting back automatically. Paste that code into the terminal at the
Paste code here if prompted
prompt to complete login.
If the browser doesn’t open at all from WSL2, set the
BROWSER
environment variable to your Windows browser path:
export
BROWSER
=
"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
claude
Alternatively, press
c
at the interactive login prompt to copy the OAuth URL, or copy the URL that
claude auth login
prints, and open it in a browser on your local machine.
If pasting the code into the interactive prompt does nothing, your terminal’s paste binding likely isn’t reaching the input field. Try your terminal’s alternate paste shortcut, often right-click or Shift+Insert in Windows Terminal, or use
claude auth login
instead, which reads the pasted code from standard input:
claude
auth
login
This fallback also applies on native Windows or any terminal where pasting into the interactive prompt fails.
​
Not logged in or token expired
If Claude Code prompts you to log in again after a session, your OAuth token may have expired.
Run
/login
to re-authenticate. If this happens frequently, check that your system clock is accurate, as token validation depends on correct timestamps.
On macOS, login can also fail when the Keychain is locked or its password is out of sync with your account password, which prevents Claude Code from saving credentials. Run
claude doctor
to check Keychain access. To unlock the Keychain manually, run
security unlock-keychain ~/Library/Keychains/login.keychain-db
. If unlocking doesn’t help, open Keychain Access, select the
login
keychain, and choose Edit > Change Password for Keychain “login” to resync it with your account password.
​
Bedrock, Vertex, or Foundry credentials not loading
If you configured Claude Code to use a cloud provider and see
Could not load credentials from any providers
on Bedrock,
Could not load the default credentials
on Vertex, or
ChainedTokenCredential authentication failed
on Foundry, your cloud provider CLI is likely not authenticated in the current shell.
For Bedrock, confirm your AWS credentials are valid:
aws
sts
get-caller-identity
For Vertex AI, confirm
ANTHROPIC_VERTEX_PROJECT_ID
and
CLOUD_ML_REGION
are set in your shell, then set application default credentials:
gcloud
auth
application-default
login
For Microsoft Foundry, confirm
ANTHROPIC_FOUNDRY_API_KEY
is set, or sign in with the Azure CLI so the default credential chain can find your account:
az
login
If credentials work in your terminal but not in the VS Code or JetBrains extension, the IDE process likely didn’t inherit your shell environment. Set the provider environment variables in the IDE’s own settings, or launch the IDE from a terminal where they’re already exported.
See
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
for full provider setup.
​
Still stuck
If none of the above resolves your issue:
Check the
GitHub repository
for known issues, or open a new one with your operating system, the install command you ran, and the full error output
If
claude --version
works but something else is wrong, run
claude doctor
for an automated diagnostic report
If you can start a session, use
/feedback
inside Claude Code to report the problem
Was this page helpful?
Yes
No
Launch sessions from links
Troubleshoot performance and stability
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/troubleshoot-install" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Advanced setup</title>
  <link>https://code.claude.com/docs/en/setup</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/setup</guid>
  <pubDate>Mon, 12 Feb 2024 00:00:00 +0000</pubDate>
  <category>Setup</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Advanced setup
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Advanced setup
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers system requirements, platform-specific installation details, updates, and uninstallation. For a guided walkthrough of your first session, see the
quickstart
. If you’ve never used a terminal before, see the
terminal guide
.
​
System requirements
Claude Code runs on the following platforms and configurations:
Operating system
:
macOS 13.0+
Windows 10 1809+ or Windows Server 2019+
Ubuntu 20.04+
Debian 10+
Alpine Linux 3.19+
Hardware
: 4 GB+ RAM, x64 or ARM64 processor
Network
: internet connection required. See
network configuration
.
Shell
: Bash, Zsh, PowerShell, or CMD. On native Windows,
Git for Windows
is recommended; Claude Code falls back to PowerShell when Git Bash is absent. WSL setups do not require Git for Windows.
Location
:
Anthropic supported countries
​
Additional dependencies
ripgrep
: usually included with Claude Code. If search fails, see
search troubleshooting
.
​
Install Claude Code
Prefer a graphical interface? The
Desktop app
lets you use Claude Code without the terminal. Download it for
macOS
or
Windows
.
New to the terminal? See the
terminal guide
for step-by-step instructions.
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
After installation completes, open a terminal in the project you want to work in and start Claude Code:
claude
If you encounter any issues during installation, see
Troubleshoot installation and login
.
​
Set up on Windows
You can run Claude Code natively on Windows or inside WSL. Pick based on where your projects are located and which features you need:
Option
Requires
Sandboxing
When to use
Native Windows
Git for Windows
recommended; PowerShell used if absent
Not supported
Windows-native projects and tools
WSL 2
WSL 2 enabled
Supported
Linux toolchains or sandboxed command execution
WSL 1
WSL 1 enabled
Not supported
If WSL 2 is unavailable
Option 1: Native Windows with Git Bash
Install
Git for Windows
, then run the install command from PowerShell or CMD. You do not need to run as Administrator.
Whether you install from PowerShell or CMD only affects which install command you run. Your prompt shows
PS C:\Users\YourName>
in PowerShell and
C:\Users\YourName>
without the
PS
in CMD. If you’re new to the terminal, the
terminal guide
walks through each step.
After installation, launch
claude
from PowerShell, CMD, or Git Bash. When Git Bash is installed, Claude Code uses it internally to execute commands regardless of where you launched it. If Claude Code can’t find your Git Bash installation, set the path in your
settings.json file
:
{
"env"
: {
"CLAUDE_CODE_GIT_BASH_PATH"
:
"C:
\\
Program Files
\\
Git
\\
bin
\\
bash.exe"
}
}
Claude Code can also run PowerShell natively on Windows. When Git Bash is installed, the PowerShell tool is rolling out progressively as an additional option: set
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
to opt in or
0
to opt out. See
PowerShell tool
for setup and limitations.
Option 2: WSL
Open your WSL distribution and run the Linux installer from the
install instructions
above. You install and launch
claude
inside the WSL terminal, not from PowerShell or CMD.
​
Alpine Linux and musl-based distributions
The native installer on Alpine and other musl/uClibc-based distributions requires
libgcc
,
libstdc++
, and
ripgrep
. Install these using your distribution’s package manager, then set
USE_BUILTIN_RIPGREP=0
.
This example installs the required packages on Alpine:
apk
add
libgcc
libstdc++
ripgrep
Then set
USE_BUILTIN_RIPGREP
to
0
in your
settings.json
file:
{
"env"
: {
"USE_BUILTIN_RIPGREP"
:
"0"
}
}
​
Verify your installation
After installing, confirm Claude Code is working:
claude
--version
If this fails with
command not found
or another error, see
Troubleshoot installation and login
.
For a more detailed check of your installation and configuration, run
claude doctor
:
claude
doctor
​
Authenticate
Claude Code requires a Pro, Max, Team, Enterprise, or Console account. The free Claude.ai plan does not include Claude Code access. You can also use Claude Code with a third-party API provider like
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
.
After installing, log in by running
claude
and following the browser prompts. See
Authentication
for all account types and team setup options.
​
Update Claude Code
Native installations automatically update in the background. You can
configure the release channel
to control whether you receive updates immediately or on a delayed stable schedule, or
disable auto-updates
entirely. Homebrew, WinGet, and
Linux package manager
installations require manual updates by default.
​
Auto-updates
Claude Code checks for updates on startup and periodically while running. Updates download and install in the background, then take effect the next time you start Claude Code.
Homebrew, WinGet, apt, dnf, and apk installations do not auto-update by default; see below to opt in for Homebrew and WinGet. To upgrade Homebrew manually, run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed. For WinGet, run
winget upgrade Anthropic.ClaudeCode
. For Linux package managers, see the upgrade commands in
Install with Linux package managers
.
To have Claude Code run the upgrade command for you on Homebrew or WinGet, set
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
to
1
. Claude Code then runs the upgrade in the background when a new version is available and shows a restart prompt on success. The upgrade targets only the Claude Code package and does not affect other software you have installed.
On WinGet the upgrade may fail while Claude Code is running because Windows locks the executable. In that case Claude Code shows the manual command instead. apt, dnf, and apk continue to require a manual upgrade because those commands need elevated privileges.
Known issue:
Claude Code may notify you of updates before the new version is available in these package managers. If an upgrade fails, wait and try again later.
Homebrew keeps old versions on disk after upgrades. Run
brew cleanup
periodically to reclaim disk space.
​
Configure release channel
Control which release channel Claude Code follows for auto-updates and
claude update
with the
autoUpdatesChannel
setting:
"latest"
, the default: receive new features as soon as they’re released
"stable"
: use a version that is typically about one week old, skipping releases with major regressions
Configure this via
/config
→
Auto-update channel
, or add it to your
settings.json file
:
{
"autoUpdatesChannel"
:
"stable"
}
For enterprise deployments, you can enforce a consistent release channel across your organization using
managed settings
.
Homebrew installations choose a channel by cask name instead of this setting:
claude-code
tracks stable and
claude-code@latest
tracks latest.
​
Pin a minimum version
The
minimumVersion
setting establishes a floor. Background auto-updates and
claude update
refuse to install any version below this value, so moving to the
"stable"
channel does not downgrade you if you are already on a newer
"latest"
build.
Switching from
"latest"
to
"stable"
via
/config
prompts you to either stay on the current version or allow the downgrade. Choosing to stay sets
minimumVersion
to that version. Switching back to
"latest"
clears it.
Add it to your
settings.json file
to pin a floor explicitly:
{
"autoUpdatesChannel"
:
"stable"
,
"minimumVersion"
:
"2.1.100"
}
In
managed settings
, this enforces an organization-wide minimum that user and project settings cannot override.
​
Disable auto-updates
Set
DISABLE_AUTOUPDATER
to
"1"
in the
env
key of your
settings.json
file:
{
"env"
: {
"DISABLE_AUTOUPDATER"
:
"1"
}
}
DISABLE_AUTOUPDATER
only stops the background check;
claude update
and
claude install
still work. To block all update paths, including manual updates, set
DISABLE_UPDATES
instead. Use this when you distribute Claude Code through your own channels and need users to stay on the version you provide.
​
Update manually
To apply an update immediately without waiting for the next background check, run:
claude
update
​
Advanced installation options
These options are for version pinning, Linux package managers, npm, and verifying binary integrity.
​
Install a specific version
The native installer accepts either a specific version number or a release channel (
latest
or
stable
). The channel you choose at install time becomes your default for auto-updates. See
configure release channel
for more information.
To install the latest version (default):
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
irm https:
//
claude.ai
/
install.ps1
|
iex
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
To install the stable version:
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
-s
stable
&
([
scriptblock
]::Create((irm https:
//
claude.ai
/
install.ps1))) stable
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd stable
&&
del
install.cmd
To install a specific version number:
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
-s
2.1.89
&
([
scriptblock
]::Create((irm https:
//
claude.ai
/
install.ps1)))
2.1
.
89
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd 2.1.89
&&
del
install.cmd
​
Install with Linux package managers
Claude Code publishes signed apt, dnf, and apk repositories. Replace
stable
with
latest
for the rolling channel. Package manager installations do not auto-update through Claude Code; updates arrive through your normal system upgrade workflow.
All repositories are signed with the
Claude Code release signing key
. Before trusting the key, verify it as described in each tab.
apt
dnf
apk
For Debian and Ubuntu. To use the rolling channel, change both
stable
occurrences in the
deb
line: the URL path and the suite name.
sudo
install
-d
-m
0755
/etc/apt/keyrings
sudo
curl
-fsSL
https://downloads.claude.ai/keys/claude-code.asc
\
-o
/etc/apt/keyrings/claude-code.asc
echo
"deb [signed-by=/etc/apt/keyrings/claude-code.asc] https://downloads.claude.ai/claude-code/apt/stable stable main"
\
|
sudo
tee
/etc/apt/sources.list.d/claude-code.list
sudo
apt
update
sudo
apt
install
claude-code
Verify the GPG key fingerprint before trusting it:
gpg --show-keys /etc/apt/keyrings/claude-code.asc
should report
31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE
.
To upgrade later, run
sudo apt update && sudo apt upgrade claude-code
.
For Fedora and RHEL:
sudo
tee
/etc/yum.repos.d/claude-code.repo
<<
'EOF'
[claude-code]
name=Claude Code
baseurl=https://downloads.claude.ai/claude-code/rpm/stable
enabled=1
gpgcheck=1
gpgkey=https://downloads.claude.ai/keys/claude-code.asc
EOF
sudo
dnf
install
claude-code
dnf downloads the key on first install and prompts you to confirm the fingerprint. Verify it matches
31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE
before accepting.
To upgrade later, run
sudo dnf upgrade claude-code
.
For Alpine Linux:
wget
-O
/etc/apk/keys/claude-code.rsa.pub
\
https://downloads.claude.ai/keys/claude-code.rsa.pub
echo
"https://downloads.claude.ai/claude-code/apk/stable"
>>
/etc/apk/repositories
apk
add
claude-code
Verify the downloaded key with
sha256sum /etc/apk/keys/claude-code.rsa.pub
, which should report
395759c1f7449ef4cdef305a42e820f3c766d6090d142634ebdb049f113168b6
.
To upgrade later, run
apk update && apk upgrade claude-code
.
​
Install with npm
You can also install Claude Code as a global npm package. The package requires
Node.js 18 or later
.
npm
install
-g
@anthropic-ai/claude-code
The npm package installs the same native binary as the standalone installer. npm pulls the binary in through a per-platform optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
, and a postinstall step links it into place. The installed
claude
binary does not itself invoke Node.
Supported npm install platforms are
darwin-arm64
,
darwin-x64
,
linux-x64
,
linux-arm64
,
linux-x64-musl
,
linux-arm64-musl
,
win32-x64
, and
win32-arm64
. Your package manager must allow optional dependencies. See
troubleshooting
if the binary is missing after install.
To upgrade an npm installation, run
npm install -g @anthropic-ai/claude-code@latest
. Avoid
npm update -g
, which respects the semver range from the original install and may not move you to the newest release.
Do NOT use
sudo npm install -g
as this can lead to permission issues and security risks. If you encounter permission errors, see
troubleshooting permission errors
.
​
Binary integrity and code signing
Each release publishes a
manifest.json
containing SHA256 checksums for every platform binary. The manifest is signed with an Anthropic GPG key, so verifying the signature on the manifest transitively verifies every binary it lists.
​
Verify the manifest signature
Steps 1-3 require a POSIX shell with
gpg
and
curl
. On Windows, run them in Git Bash or WSL. Step 4 includes a PowerShell option.
1
Download and import the public key
The release signing key is published at a fixed URL.
curl
-fsSL
https://downloads.claude.ai/keys/claude-code.asc
|
gpg
--import
Display the fingerprint of the imported key.
gpg
--fingerprint
security@anthropic.com
Confirm the output includes this fingerprint:
31DD DE24 DDFA B679 F42D  7BD2 BAA9 29FF 1A7E CACE
2
Download the manifest and signature
Set
VERSION
to the release you want to verify.
REPO
=
https://downloads.claude.ai/claude-code-releases
VERSION
=
2.1.89
curl
-fsSLO
"
$REPO
/
$VERSION
/manifest.json"
curl
-fsSLO
"
$REPO
/
$VERSION
/manifest.json.sig"
3
Verify the signature
Verify the detached signature against the manifest.
gpg
--verify
manifest.json.sig
manifest.json
A valid result reports
Good signature from "Anthropic Claude Code Release Signing <security@anthropic.com>"
.
gpg
also prints
WARNING: This key is not certified with a trusted signature!
for any freshly imported key. This is expected. The
Good signature
line confirms the cryptographic check passed. The fingerprint comparison in Step 1 confirms the key itself is authentic.
4
Check the binary against the manifest
Compare the SHA256 checksum of your downloaded binary with the value listed under
platforms.<platform>.checksum
in
manifest.json
.
Linux
macOS
Windows PowerShell
sha256sum
claude
shasum
-a
256
claude
(
Get-FileHash
claude.exe
-
Algorithm SHA256).Hash.ToLower()
Manifest signatures are available for releases from
2.1.89
onward. Earlier releases publish checksums in
manifest.json
without a detached signature.
​
Platform code signatures
In addition to the signed manifest, individual binaries carry platform-native code signatures where supported.
macOS
: signed by “Anthropic PBC” and notarized by Apple. Verify with
codesign --verify --verbose ./claude
.
Windows
: signed by “Anthropic, PBC”. Verify with
Get-AuthenticodeSignature .\claude.exe
.
Linux
: binaries are not individually code-signed. If you download directly from the
claude-code-releases
bucket or use the native installer, verify integrity with the manifest signature above. If you install with
apt, dnf, or apk
, your package manager verifies signatures automatically using the repository signing key.
​
Uninstall Claude Code
To remove Claude Code, follow the instructions for your installation method. If
claude
still runs afterward, you likely have a second installation or a leftover shell alias from an older installer. See
Check for conflicting installations
to find and remove it.
​
Native installation
Remove the Claude Code binary and version files:
macOS, Linux, WSL
Windows PowerShell
rm
-f
~/.local/bin/claude
rm
-rf
~/.local/share/claude
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.local\bin\claude.exe"
-
Force
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.local\share\claude"
-
Recurse
-
Force
​
Homebrew installation
Remove the Homebrew cask you installed. If you installed the stable cask:
brew
uninstall
--cask
claude-code
If you installed the latest cask:
brew
uninstall
--cask
claude-code@latest
​
WinGet installation
Remove the WinGet package:
winget uninstall Anthropic.ClaudeCode
​
apt / dnf / apk
Remove the package and the repository configuration:
apt
dnf
apk
sudo
apt
remove
claude-code
sudo
rm
/etc/apt/sources.list.d/claude-code.list
/etc/apt/keyrings/claude-code.asc
sudo
dnf
remove
claude-code
sudo
rm
/etc/yum.repos.d/claude-code.repo
apk
del
claude-code
sed
-i
'\|downloads.claude.ai/claude-code/apk|d'
/etc/apk/repositories
rm
/etc/apk/keys/claude-code.rsa.pub
​
npm
Remove the global npm package:
npm
uninstall
-g
@anthropic-ai/claude-code
​
Remove configuration files
Removing configuration files will delete all your settings, allowed tools, MCP server configurations, and session history.
The VS Code extension, the JetBrains plugin, and the Desktop app also write to
~/.claude/
. If any of them is still installed, the directory is recreated the next time it runs. To remove Claude Code completely, uninstall the
VS Code extension
, the JetBrains plugin, and the Desktop app before deleting these files.
To remove Claude Code settings and cached data:
macOS, Linux, WSL
Windows PowerShell
# Remove user settings and state
rm
-rf
~/.claude
rm
~/.claude.json
# Remove project-specific settings (run from your project directory)
rm
-rf
.claude
rm
-f
.mcp.json
# Remove user settings and state
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.claude"
-
Recurse
-
Force
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.claude.json"
-
Force
# Remove project-specific settings (run from your project directory)
Remove-Item
-
Path
".claude"
-
Recurse
-
Force
Remove-Item
-
Path
".mcp.json"
-
Force
Was this page helpful?
Yes
No
Administration overview
Authentication
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/setup" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Advanced setup
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Setup and access
Advanced setup
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page covers system requirements, platform-specific installation details, updates, and uninstallation. For a guided walkthrough of your first session, see the
quickstart
. If you’ve never used a terminal before, see the
terminal guide
.
​
System requirements
Claude Code runs on the following platforms and configurations:
Operating system
:
macOS 13.0+
Windows 10 1809+ or Windows Server 2019+
Ubuntu 20.04+
Debian 10+
Alpine Linux 3.19+
Hardware
: 4 GB+ RAM, x64 or ARM64 processor
Network
: internet connection required. See
network configuration
.
Shell
: Bash, Zsh, PowerShell, or CMD. On native Windows,
Git for Windows
is recommended; Claude Code falls back to PowerShell when Git Bash is absent. WSL setups do not require Git for Windows.
Location
:
Anthropic supported countries
​
Additional dependencies
ripgrep
: usually included with Claude Code. If search fails, see
search troubleshooting
.
​
Install Claude Code
Prefer a graphical interface? The
Desktop app
lets you use Claude Code without the terminal. Download it for
macOS
or
Windows
.
New to the terminal? See the
terminal guide
for step-by-step instructions.
To install Claude Code, use one of the following methods:
Native Install (Recommended)
Homebrew
WinGet
macOS, Linux, WSL:
curl
-fsSL
https://claude.ai/install.sh
|
bash
Windows PowerShell:
irm https:
//
claude.ai
/
install.ps1
|
iex
Windows CMD:
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
If you see
The token '&&' is not a valid statement separator
, you’re in PowerShell, not CMD. If you see
'irm' is not recognized as an internal or external command
, you’re in CMD, not PowerShell. Your prompt shows
PS C:\
when you’re in PowerShell and
C:\
without the
PS
when you’re in CMD.
Git for Windows
is recommended on native Windows so Claude Code can use the Bash tool. If Git for Windows is not installed, Claude Code uses PowerShell as the shell tool instead. WSL setups do not need Git for Windows.
Native installations automatically update in the background to keep you on the latest version.
brew
install
--cask
claude-code
Homebrew offers two casks.
claude-code
tracks the stable release channel, which is typically about a week behind and skips releases with major regressions.
claude-code@latest
tracks the latest channel and receives new versions as soon as they ship.
Homebrew installations do not auto-update. Run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed, to get the latest features and security fixes.
winget install Anthropic.ClaudeCode
WinGet installations do not auto-update. Run
winget upgrade Anthropic.ClaudeCode
periodically to get the latest features and security fixes.
You can also install with
apt, dnf, or apk
on Debian, Fedora, RHEL, and Alpine.
After installation completes, open a terminal in the project you want to work in and start Claude Code:
claude
If you encounter any issues during installation, see
Troubleshoot installation and login
.
​
Set up on Windows
You can run Claude Code natively on Windows or inside WSL. Pick based on where your projects are located and which features you need:
Option
Requires
Sandboxing
When to use
Native Windows
Git for Windows
recommended; PowerShell used if absent
Not supported
Windows-native projects and tools
WSL 2
WSL 2 enabled
Supported
Linux toolchains or sandboxed command execution
WSL 1
WSL 1 enabled
Not supported
If WSL 2 is unavailable
Option 1: Native Windows with Git Bash
Install
Git for Windows
, then run the install command from PowerShell or CMD. You do not need to run as Administrator.
Whether you install from PowerShell or CMD only affects which install command you run. Your prompt shows
PS C:\Users\YourName>
in PowerShell and
C:\Users\YourName>
without the
PS
in CMD. If you’re new to the terminal, the
terminal guide
walks through each step.
After installation, launch
claude
from PowerShell, CMD, or Git Bash. When Git Bash is installed, Claude Code uses it internally to execute commands regardless of where you launched it. If Claude Code can’t find your Git Bash installation, set the path in your
settings.json file
:
{
"env"
: {
"CLAUDE_CODE_GIT_BASH_PATH"
:
"C:
\\
Program Files
\\
Git
\\
bin
\\
bash.exe"
}
}
Claude Code can also run PowerShell natively on Windows. When Git Bash is installed, the PowerShell tool is rolling out progressively as an additional option: set
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
to opt in or
0
to opt out. See
PowerShell tool
for setup and limitations.
Option 2: WSL
Open your WSL distribution and run the Linux installer from the
install instructions
above. You install and launch
claude
inside the WSL terminal, not from PowerShell or CMD.
​
Alpine Linux and musl-based distributions
The native installer on Alpine and other musl/uClibc-based distributions requires
libgcc
,
libstdc++
, and
ripgrep
. Install these using your distribution’s package manager, then set
USE_BUILTIN_RIPGREP=0
.
This example installs the required packages on Alpine:
apk
add
libgcc
libstdc++
ripgrep
Then set
USE_BUILTIN_RIPGREP
to
0
in your
settings.json
file:
{
"env"
: {
"USE_BUILTIN_RIPGREP"
:
"0"
}
}
​
Verify your installation
After installing, confirm Claude Code is working:
claude
--version
If this fails with
command not found
or another error, see
Troubleshoot installation and login
.
For a more detailed check of your installation and configuration, run
claude doctor
:
claude
doctor
​
Authenticate
Claude Code requires a Pro, Max, Team, Enterprise, or Console account. The free Claude.ai plan does not include Claude Code access. You can also use Claude Code with a third-party API provider like
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
.
After installing, log in by running
claude
and following the browser prompts. See
Authentication
for all account types and team setup options.
​
Update Claude Code
Native installations automatically update in the background. You can
configure the release channel
to control whether you receive updates immediately or on a delayed stable schedule, or
disable auto-updates
entirely. Homebrew, WinGet, and
Linux package manager
installations require manual updates by default.
​
Auto-updates
Claude Code checks for updates on startup and periodically while running. Updates download and install in the background, then take effect the next time you start Claude Code.
Homebrew, WinGet, apt, dnf, and apk installations do not auto-update by default; see below to opt in for Homebrew and WinGet. To upgrade Homebrew manually, run
brew upgrade claude-code
or
brew upgrade claude-code@latest
, depending on which cask you installed. For WinGet, run
winget upgrade Anthropic.ClaudeCode
. For Linux package managers, see the upgrade commands in
Install with Linux package managers
.
To have Claude Code run the upgrade command for you on Homebrew or WinGet, set
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
to
1
. Claude Code then runs the upgrade in the background when a new version is available and shows a restart prompt on success. The upgrade targets only the Claude Code package and does not affect other software you have installed.
On WinGet the upgrade may fail while Claude Code is running because Windows locks the executable. In that case Claude Code shows the manual command instead. apt, dnf, and apk continue to require a manual upgrade because those commands need elevated privileges.
Known issue:
Claude Code may notify you of updates before the new version is available in these package managers. If an upgrade fails, wait and try again later.
Homebrew keeps old versions on disk after upgrades. Run
brew cleanup
periodically to reclaim disk space.
​
Configure release channel
Control which release channel Claude Code follows for auto-updates and
claude update
with the
autoUpdatesChannel
setting:
"latest"
, the default: receive new features as soon as they’re released
"stable"
: use a version that is typically about one week old, skipping releases with major regressions
Configure this via
/config
→
Auto-update channel
, or add it to your
settings.json file
:
{
"autoUpdatesChannel"
:
"stable"
}
For enterprise deployments, you can enforce a consistent release channel across your organization using
managed settings
.
Homebrew installations choose a channel by cask name instead of this setting:
claude-code
tracks stable and
claude-code@latest
tracks latest.
​
Pin a minimum version
The
minimumVersion
setting establishes a floor. Background auto-updates and
claude update
refuse to install any version below this value, so moving to the
"stable"
channel does not downgrade you if you are already on a newer
"latest"
build.
Switching from
"latest"
to
"stable"
via
/config
prompts you to either stay on the current version or allow the downgrade. Choosing to stay sets
minimumVersion
to that version. Switching back to
"latest"
clears it.
Add it to your
settings.json file
to pin a floor explicitly:
{
"autoUpdatesChannel"
:
"stable"
,
"minimumVersion"
:
"2.1.100"
}
In
managed settings
, this enforces an organization-wide minimum that user and project settings cannot override.
​
Disable auto-updates
Set
DISABLE_AUTOUPDATER
to
"1"
in the
env
key of your
settings.json
file:
{
"env"
: {
"DISABLE_AUTOUPDATER"
:
"1"
}
}
DISABLE_AUTOUPDATER
only stops the background check;
claude update
and
claude install
still work. To block all update paths, including manual updates, set
DISABLE_UPDATES
instead. Use this when you distribute Claude Code through your own channels and need users to stay on the version you provide.
​
Update manually
To apply an update immediately without waiting for the next background check, run:
claude
update
​
Advanced installation options
These options are for version pinning, Linux package managers, npm, and verifying binary integrity.
​
Install a specific version
The native installer accepts either a specific version number or a release channel (
latest
or
stable
). The channel you choose at install time becomes your default for auto-updates. See
configure release channel
for more information.
To install the latest version (default):
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
irm https:
//
claude.ai
/
install.ps1
|
iex
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd
&&
del
install.cmd
To install the stable version:
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
-s
stable
&
([
scriptblock
]::Create((irm https:
//
claude.ai
/
install.ps1))) stable
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd stable
&&
del
install.cmd
To install a specific version number:
macOS, Linux, WSL
Windows PowerShell
Windows CMD
curl
-fsSL
https://claude.ai/install.sh
|
bash
-s
2.1.89
&
([
scriptblock
]::Create((irm https:
//
claude.ai
/
install.ps1)))
2.1
.
89
curl -fsSL https://claude.ai/install.cmd -o install.cmd
&&
install.cmd 2.1.89
&&
del
install.cmd
​
Install with Linux package managers
Claude Code publishes signed apt, dnf, and apk repositories. Replace
stable
with
latest
for the rolling channel. Package manager installations do not auto-update through Claude Code; updates arrive through your normal system upgrade workflow.
All repositories are signed with the
Claude Code release signing key
. Before trusting the key, verify it as described in each tab.
apt
dnf
apk
For Debian and Ubuntu. To use the rolling channel, change both
stable
occurrences in the
deb
line: the URL path and the suite name.
sudo
install
-d
-m
0755
/etc/apt/keyrings
sudo
curl
-fsSL
https://downloads.claude.ai/keys/claude-code.asc
\
-o
/etc/apt/keyrings/claude-code.asc
echo
"deb [signed-by=/etc/apt/keyrings/claude-code.asc] https://downloads.claude.ai/claude-code/apt/stable stable main"
\
|
sudo
tee
/etc/apt/sources.list.d/claude-code.list
sudo
apt
update
sudo
apt
install
claude-code
Verify the GPG key fingerprint before trusting it:
gpg --show-keys /etc/apt/keyrings/claude-code.asc
should report
31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE
.
To upgrade later, run
sudo apt update && sudo apt upgrade claude-code
.
For Fedora and RHEL:
sudo
tee
/etc/yum.repos.d/claude-code.repo
<<
'EOF'
[claude-code]
name=Claude Code
baseurl=https://downloads.claude.ai/claude-code/rpm/stable
enabled=1
gpgcheck=1
gpgkey=https://downloads.claude.ai/keys/claude-code.asc
EOF
sudo
dnf
install
claude-code
dnf downloads the key on first install and prompts you to confirm the fingerprint. Verify it matches
31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE
before accepting.
To upgrade later, run
sudo dnf upgrade claude-code
.
For Alpine Linux:
wget
-O
/etc/apk/keys/claude-code.rsa.pub
\
https://downloads.claude.ai/keys/claude-code.rsa.pub
echo
"https://downloads.claude.ai/claude-code/apk/stable"
>>
/etc/apk/repositories
apk
add
claude-code
Verify the downloaded key with
sha256sum /etc/apk/keys/claude-code.rsa.pub
, which should report
395759c1f7449ef4cdef305a42e820f3c766d6090d142634ebdb049f113168b6
.
To upgrade later, run
apk update && apk upgrade claude-code
.
​
Install with npm
You can also install Claude Code as a global npm package. The package requires
Node.js 18 or later
.
npm
install
-g
@anthropic-ai/claude-code
The npm package installs the same native binary as the standalone installer. npm pulls the binary in through a per-platform optional dependency such as
@anthropic-ai/claude-code-darwin-arm64
, and a postinstall step links it into place. The installed
claude
binary does not itself invoke Node.
Supported npm install platforms are
darwin-arm64
,
darwin-x64
,
linux-x64
,
linux-arm64
,
linux-x64-musl
,
linux-arm64-musl
,
win32-x64
, and
win32-arm64
. Your package manager must allow optional dependencies. See
troubleshooting
if the binary is missing after install.
To upgrade an npm installation, run
npm install -g @anthropic-ai/claude-code@latest
. Avoid
npm update -g
, which respects the semver range from the original install and may not move you to the newest release.
Do NOT use
sudo npm install -g
as this can lead to permission issues and security risks. If you encounter permission errors, see
troubleshooting permission errors
.
​
Binary integrity and code signing
Each release publishes a
manifest.json
containing SHA256 checksums for every platform binary. The manifest is signed with an Anthropic GPG key, so verifying the signature on the manifest transitively verifies every binary it lists.
​
Verify the manifest signature
Steps 1-3 require a POSIX shell with
gpg
and
curl
. On Windows, run them in Git Bash or WSL. Step 4 includes a PowerShell option.
1
Download and import the public key
The release signing key is published at a fixed URL.
curl
-fsSL
https://downloads.claude.ai/keys/claude-code.asc
|
gpg
--import
Display the fingerprint of the imported key.
gpg
--fingerprint
security@anthropic.com
Confirm the output includes this fingerprint:
31DD DE24 DDFA B679 F42D  7BD2 BAA9 29FF 1A7E CACE
2
Download the manifest and signature
Set
VERSION
to the release you want to verify.
REPO
=
https://downloads.claude.ai/claude-code-releases
VERSION
=
2.1.89
curl
-fsSLO
"
$REPO
/
$VERSION
/manifest.json"
curl
-fsSLO
"
$REPO
/
$VERSION
/manifest.json.sig"
3
Verify the signature
Verify the detached signature against the manifest.
gpg
--verify
manifest.json.sig
manifest.json
A valid result reports
Good signature from "Anthropic Claude Code Release Signing <security@anthropic.com>"
.
gpg
also prints
WARNING: This key is not certified with a trusted signature!
for any freshly imported key. This is expected. The
Good signature
line confirms the cryptographic check passed. The fingerprint comparison in Step 1 confirms the key itself is authentic.
4
Check the binary against the manifest
Compare the SHA256 checksum of your downloaded binary with the value listed under
platforms.<platform>.checksum
in
manifest.json
.
Linux
macOS
Windows PowerShell
sha256sum
claude
shasum
-a
256
claude
(
Get-FileHash
claude.exe
-
Algorithm SHA256).Hash.ToLower()
Manifest signatures are available for releases from
2.1.89
onward. Earlier releases publish checksums in
manifest.json
without a detached signature.
​
Platform code signatures
In addition to the signed manifest, individual binaries carry platform-native code signatures where supported.
macOS
: signed by “Anthropic PBC” and notarized by Apple. Verify with
codesign --verify --verbose ./claude
.
Windows
: signed by “Anthropic, PBC”. Verify with
Get-AuthenticodeSignature .\claude.exe
.
Linux
: binaries are not individually code-signed. If you download directly from the
claude-code-releases
bucket or use the native installer, verify integrity with the manifest signature above. If you install with
apt, dnf, or apk
, your package manager verifies signatures automatically using the repository signing key.
​
Uninstall Claude Code
To remove Claude Code, follow the instructions for your installation method. If
claude
still runs afterward, you likely have a second installation or a leftover shell alias from an older installer. See
Check for conflicting installations
to find and remove it.
​
Native installation
Remove the Claude Code binary and version files:
macOS, Linux, WSL
Windows PowerShell
rm
-f
~/.local/bin/claude
rm
-rf
~/.local/share/claude
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.local\bin\claude.exe"
-
Force
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.local\share\claude"
-
Recurse
-
Force
​
Homebrew installation
Remove the Homebrew cask you installed. If you installed the stable cask:
brew
uninstall
--cask
claude-code
If you installed the latest cask:
brew
uninstall
--cask
claude-code@latest
​
WinGet installation
Remove the WinGet package:
winget uninstall Anthropic.ClaudeCode
​
apt / dnf / apk
Remove the package and the repository configuration:
apt
dnf
apk
sudo
apt
remove
claude-code
sudo
rm
/etc/apt/sources.list.d/claude-code.list
/etc/apt/keyrings/claude-code.asc
sudo
dnf
remove
claude-code
sudo
rm
/etc/yum.repos.d/claude-code.repo
apk
del
claude-code
sed
-i
'\|downloads.claude.ai/claude-code/apk|d'
/etc/apk/repositories
rm
/etc/apk/keys/claude-code.rsa.pub
​
npm
Remove the global npm package:
npm
uninstall
-g
@anthropic-ai/claude-code
​
Remove configuration files
Removing configuration files will delete all your settings, allowed tools, MCP server configurations, and session history.
The VS Code extension, the JetBrains plugin, and the Desktop app also write to
~/.claude/
. If any of them is still installed, the directory is recreated the next time it runs. To remove Claude Code completely, uninstall the
VS Code extension
, the JetBrains plugin, and the Desktop app before deleting these files.
To remove Claude Code settings and cached data:
macOS, Linux, WSL
Windows PowerShell
# Remove user settings and state
rm
-rf
~/.claude
rm
~/.claude.json
# Remove project-specific settings (run from your project directory)
rm
-rf
.claude
rm
-f
.mcp.json
# Remove user settings and state
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.claude"
-
Recurse
-
Force
Remove-Item
-
Path
"
$
env:
USERPROFILE
\.claude.json"
-
Force
# Remove project-specific settings (run from your project directory)
Remove-Item
-
Path
".claude"
-
Recurse
-
Force
Remove-Item
-
Path
".mcp.json"
-
Force
Was this page helpful?
Yes
No
Administration overview
Authentication
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/setup" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code settings</title>
  <link>https://code.claude.com/docs/en/settings</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/settings</guid>
  <pubDate>Mon, 12 Feb 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Claude Code settings
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use thi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Claude Code settings
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code offers a variety of settings to configure its behavior to meet your needs. You can configure Claude Code by running the
/config
command when using the interactive REPL, which opens a tabbed Settings interface where you can view status information and modify configuration options.
​
Configuration scopes
Claude Code uses a
scope system
to determine where configurations apply and who they’re shared with. Understanding scopes helps you decide how to configure Claude Code for personal use, team collaboration, or enterprise deployment.
​
Available scopes
Scope
Location
Who it affects
Shared with team?
Managed
Server-managed settings, plist / registry, or system-level
managed-settings.json
All users on the machine
Yes (deployed by IT)
User
~/.claude/
directory
You, across all projects
No
Project
.claude/
in repository
All collaborators on this repository
Yes (committed to git)
Local
.claude/settings.local.json
You, in this repository only
No (gitignored)
​
When to use each scope
Managed scope
is for:
Security policies that must be enforced organization-wide
Compliance requirements that can’t be overridden
Standardized configurations deployed by IT/DevOps
User scope
is best for:
Personal preferences you want everywhere (themes, editor settings)
Tools and plugins you use across all projects
API keys and authentication (stored securely)
Project scope
is best for:
Team-shared settings (permissions, hooks, MCP servers)
Plugins the whole team should have
Standardizing tooling across collaborators
Local scope
is best for:
Personal overrides for a specific project
Testing configurations before sharing with the team
Machine-specific settings that won’t work for others
​
How scopes interact
When the same setting appears in multiple scopes, Claude Code applies them in priority order:
Managed
(highest) - can’t be overridden by anything
Command line arguments
- temporary session overrides
Local
- overrides project and user settings
Project
- overrides user settings
User
(lowest) - applies when nothing else specifies the setting
For example, if your user settings set
spinnerTipsEnabled
to
true
and project settings set it to
false
, the project value applies. Permission rules behave differently because they merge across scopes rather than override. See
Settings precedence
.
​
What uses scopes
Scopes apply to many Claude Code features:
Feature
User location
Project location
Local location
Settings
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
Subagents
~/.claude/agents/
.claude/agents/
None
MCP servers
~/.claude.json
.mcp.json
~/.claude.json
(per-project)
Plugins
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
CLAUDE.md
~/.claude/CLAUDE.md
CLAUDE.md
or
.claude/CLAUDE.md
CLAUDE.local.md
On Windows, paths shown as
~/.claude
resolve to
%USERPROFILE%\.claude
.
​
Settings files
The
settings.json
file is the official mechanism for configuring Claude
Code through hierarchical settings:
User settings
are defined in
~/.claude/settings.json
and apply to all
projects.
Project settings
are saved in your project directory:
.claude/settings.json
for settings that are checked into source control and shared with your team
.claude/settings.local.json
for settings that are not checked in, useful for personal preferences and experimentation. Claude Code will configure git to ignore
.claude/settings.local.json
when it is created.
Managed settings
: For organizations that need centralized control, Claude Code supports multiple delivery mechanisms for managed settings. All use the same JSON format and cannot be overridden by user or project settings:
Server-managed settings
: delivered from Anthropic’s servers via the Claude.ai admin console. See
server-managed settings
.
MDM/OS-level policies
: delivered through native device management on macOS and Windows:
macOS:
com.anthropic.claudecode
managed preferences domain. The plist’s top-level keys mirror
managed-settings.json
, with nested settings as dictionaries and arrays as plist arrays. Deploy via configuration profiles in Jamf, Iru (Kandji), or similar MDM tools.
Windows:
HKLM\SOFTWARE\Policies\ClaudeCode
registry key with a
Settings
value (REG_SZ or REG_EXPAND_SZ) containing JSON (deployed via Group Policy or Intune)
Windows (user-level):
HKCU\SOFTWARE\Policies\ClaudeCode
(lowest policy priority, only used when no admin-level source exists)
File-based
:
managed-settings.json
and
managed-mcp.json
deployed to system directories:
macOS:
/Library/Application Support/ClaudeCode/
Linux and WSL:
/etc/claude-code/
Windows:
C:\Program Files\ClaudeCode\
The legacy Windows path
C:\ProgramData\ClaudeCode\managed-settings.json
is no longer supported as of v2.1.75. Administrators who deployed settings to that location must migrate files to
C:\Program Files\ClaudeCode\managed-settings.json
.
File-based managed settings also support a drop-in directory at
managed-settings.d/
in the same system directory alongside
managed-settings.json
. This lets separate teams deploy independent policy fragments without coordinating edits to a single file.
Following the systemd convention,
managed-settings.json
is merged first as the base, then all
*.json
files in the drop-in directory are sorted alphabetically and merged on top. Later files override earlier ones for scalar values; arrays are concatenated and de-duplicated; objects are deep-merged. Hidden files starting with
.
are ignored.
Use numeric prefixes to control merge order, for example
10-telemetry.json
and
20-security.json
.
See
managed settings
and
Managed MCP configuration
for details.
This
repository
includes starter deployment templates for Jamf, Iru (Kandji), Intune, and Group Policy. Use these as starting points and adjust them to fit your needs.
Managed deployments can also restrict
plugin marketplace additions
using
strictKnownMarketplaces
. For more information, see
Managed marketplace restrictions
.
Other configuration
is stored in
~/.claude.json
. This file contains your OAuth session,
MCP server
configurations for user and local scopes, per-project state (allowed tools, trust settings), and various caches. Project-scoped MCP servers are stored separately in
.mcp.json
.
Claude Code automatically creates timestamped backups of configuration files and retains the five most recent backups to prevent data loss.
Example settings.json
{
"$schema"
:
"https://json.schemastore.org/claude-code-settings.json"
,
"permissions"
: {
"allow"
: [
"Bash(npm run lint)"
,
"Bash(npm run test *)"
,
"Read(~/.zshrc)"
],
"deny"
: [
"Bash(curl *)"
,
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
]
},
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
},
"companyAnnouncements"
: [
"Welcome to Acme Corp! Review our code guidelines at docs.acme.com"
,
"Reminder: Code reviews required for all PRs"
,
"New security policy in effect"
]
}
The
$schema
line in the example above points to the
official JSON schema
for Claude Code settings. Adding it to your
settings.json
enables autocomplete and inline validation in VS Code, Cursor, and any other editor that supports JSON schema validation.
The published schema is updated periodically and may not include settings added in the most recent CLI releases, so a validation warning on a recently documented field does not necessarily mean your configuration is invalid.
​
Available settings
settings.json
supports a number of options:
Key
Description
Example
agent
Run the main thread as a named subagent. Applies that subagent’s system prompt, tool restrictions, and model. See
Invoke subagents explicitly
"code-reviewer"
allowedChannelPlugins
(Managed settings only) Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Undefined = fall back to the default, empty array = block all channel plugins. Requires
channelsEnabled: true
. See
Restrict which channel plugins can run
[{ "marketplace": "claude-plugins-official", "plugin": "telegram" }]
allowedHttpHookUrls
Allowlist of URL patterns that HTTP hooks may target. Supports
*
as a wildcard. When set, hooks with non-matching URLs are blocked. Undefined = no restriction, empty array = block all HTTP hooks. Arrays merge across settings sources. See
Hook configuration
["https://hooks.example.com/*"]
allowedMcpServers
When set in managed-settings.json, allowlist of MCP servers users can configure. Undefined = no restrictions, empty array = lockdown. Applies to all scopes. Denylist takes precedence. See
Managed MCP configuration
[{ "serverName": "github" }]
allowManagedHooksOnly
(Managed settings only) Only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. User, project, and all other plugin hooks are blocked. See
Hook configuration
true
allowManagedMcpServersOnly
(Managed settings only) Only
allowedMcpServers
from managed settings are respected.
deniedMcpServers
still merges from all sources. Users can still add MCP servers, but only the admin-defined allowlist applies. See
Managed MCP configuration
true
allowManagedPermissionRulesOnly
(Managed settings only) Prevent user and project settings from defining
allow
,
ask
, or
deny
permission rules. Only rules in managed settings apply. See
Managed-only settings
true
alwaysThinkingEnabled
Enable
extended thinking
by default for all sessions. Typically configured via the
/config
command rather than editing directly. To force thinking off regardless of this setting, set
CLAUDE_CODE_DISABLE_THINKING
in
env
true
apiKeyHelper
Custom script, to be executed in
/bin/sh
, to generate an auth value. This value will be sent as
X-Api-Key
and
Authorization: Bearer
headers for model requests. Set the refresh interval with
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
/bin/generate_temp_api_key.sh
attribution
Customize attribution for git commits and pull requests. See
Attribution settings
{"commit": "🤖 Generated with Claude Code", "pr": ""}
autoMemoryDirectory
Custom directory for
auto memory
storage. Accepts an absolute path or a
~/
-prefixed path. Accepted from policy and user settings, and from the
--settings
flag. Not accepted from project or local settings, since a cloned repository could supply either file to redirect memory writes to sensitive locations
"~/my-memory-dir"
autoMemoryEnabled
Enable
auto memory
. When
false
, Claude does not read from or write to the auto memory directory. Default:
true
. You can also toggle this with
/memory
during a session. To disable via environment variable, set
CLAUDE_CODE_DISABLE_AUTO_MEMORY
in
env
false
autoMode
Customize what the
auto mode
classifier blocks and allows. Contains
environment
,
allow
,
soft_deny
, and
hard_deny
arrays of prose rules. Include the literal string
"$defaults"
in an array to inherit the built-in rules at that position. See
Configure auto mode
. Not read from shared project settings
{"soft_deny": ["$defaults", "Never run terraform apply"]}
autoScrollEnabled
In
fullscreen rendering
, follow new output to the bottom of the conversation. Default:
true
. Appears in
/config
as
Auto-scroll
. Permission prompts still scroll into view when this is off
false
autoUpdatesChannel
Release channel to follow for updates. Use
"stable"
for a version that is typically about one week old and skips versions with major regressions, or
"latest"
(default) for the most recent release. To disable auto-updates entirely, set
DISABLE_AUTOUPDATER
in
env
"stable"
availableModels
Restrict which models users can select via
/model
,
--model
, or
ANTHROPIC_MODEL
. Does not affect the Default option. See
Restrict model selection
["sonnet", "haiku"]
awaySummaryEnabled
Show a one-line session recap when you return to the terminal after a few minutes away. Set to
false
or turn off Session recap in
/config
to disable. Same as
CLAUDE_CODE_ENABLE_AWAY_SUMMARY
true
awsAuthRefresh
Custom script that modifies the
.aws
directory (see
advanced credential configuration
)
aws sso login --profile myprofile
awsCredentialExport
Custom script that outputs JSON with AWS credentials (see
advanced credential configuration
)
/bin/generate_aws_grant.sh
blockedMarketplaces
(Managed settings only) Blocklist of marketplace sources. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. Blocked sources are checked before downloading, so they never touch the filesystem. See
Managed marketplace restrictions
[{ "source": "github", "repo": "untrusted/plugins" }]
channelsEnabled
(Managed settings only) Allow
channels
for the organization. On claude.ai Team and Enterprise plans, channels are blocked when this is unset or
false
. For
Anthropic Console
accounts using API key authentication, channels are allowed by default unless your organization deploys managed settings, in which case this key must be set to
true
true
claudeMd
(Managed settings only) CLAUDE.md-style instructions injected as organization-managed memory. Only honored when set in managed or policy settings and ignored in user, project, and local settings. See
organization-wide CLAUDE.md
"Always run make lint before committing."
claudeMdExcludes
Glob patterns or absolute paths of
CLAUDE.md
files to skip when loading
memory
. Patterns match against absolute file paths. Only applies to user, project, and local memory; managed policy files cannot be excluded
["**/vendor/**/CLAUDE.md"]
cleanupPeriodDays
Session files older than this period are deleted at startup (default: 30 days, minimum 1). Setting to
0
is rejected with a validation error. Also controls the age cutoff for automatic removal of
orphaned subagent worktrees
at startup. To disable transcript writes entirely, set the
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable, or in non-interactive mode (
-p
) use the
--no-session-persistence
flag or the
persistSession: false
SDK option.
20
companyAnnouncements
Announcement to display to users at startup. If multiple announcements are provided, they will be cycled through at random.
["Welcome to Acme Corp! Review our code guidelines at docs.acme.com"]
defaultShell
Default shell for input-box
!
commands. Accepts
"bash"
(default) or
"powershell"
. Setting
"powershell"
routes interactive
!
commands through PowerShell on Windows. Requires
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
. See
PowerShell tool
"powershell"
deniedMcpServers
When set in managed-settings.json, denylist of MCP servers that are explicitly blocked. Applies to all scopes including managed servers. Denylist takes precedence over allowlist. See
Managed MCP configuration
[{ "serverName": "filesystem" }]
disableAgentView
Set to
true
to turn off
background agents and agent view
:
claude agents
,
--bg
,
/background
, and the on-demand supervisor. Typically set in
managed settings
. Equivalent to setting
CLAUDE_CODE_DISABLE_AGENT_VIEW
to
1
true
disableAllHooks
Disable all
hooks
and any custom
status line
true
disableAutoMode
Set to
"disable"
to prevent
auto mode
from being activated. Removes
auto
from the
Shift+Tab
cycle and rejects
--permission-mode auto
at startup. Most useful in
managed settings
where users cannot override it
"disable"
disableDeepLinkRegistration
Set to
"disable"
to prevent Claude Code from registering the
claude-cli://
protocol handler with the operating system on startup.
Deep links
let external tools open a Claude Code session with a pre-filled prompt. Useful in environments where protocol handler registration is restricted or managed separately
"disable"
disabledMcpjsonServers
List of specific MCP servers from
.mcp.json
files to reject
["filesystem"]
disableRemoteControl
Disable
Remote Control
: blocks
claude remote-control
, the
--remote-control
flag, auto-start, and the in-session toggle. Typically placed in
managed settings
for per-device MDM enforcement, but works from any scope. Requires Claude Code v2.1.128 or later
true
disableSkillShellExecution
Disable inline shell execution for
!`...`
and
```!
blocks in
skills
and custom commands from user, project, plugin, or additional-directory sources. Commands are replaced with
[shell command execution disabled by policy]
instead of being run. Bundled and managed skills are not affected. Most useful in
managed settings
where users cannot override it
true
editorMode
Key binding mode for the input prompt:
"normal"
or
"vim"
. Default:
"normal"
. Appears in
/config
as
Editor mode
"vim"
effortLevel
Persist the
effort level
across sessions. Accepts
"low"
,
"medium"
,
"high"
, or
"xhigh"
. Written automatically when you run
/effort
with one of those values.
--effort
and
CLAUDE_CODE_EFFORT_LEVEL
override this for one session. See
Adjust effort level
for supported models
"xhigh"
enableAllProjectMcpServers
Automatically approve all MCP servers defined in project
.mcp.json
files
true
enabledMcpjsonServers
List of specific MCP servers from
.mcp.json
files to approve
["memory", "github"]
env
Environment variables that will be applied to every session
{"FOO": "bar"}
fastModePerSessionOptIn
When
true
, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with
/fast
. The user’s fast mode preference is still saved. See
Require per-session opt-in
true
feedbackSurveyRate
Probability (0–1) that the
session quality survey
appears when eligible. Set to
0
to suppress entirely, or set
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
in
env
. Useful when using Bedrock, Vertex, or Foundry where the default sample rate does not apply
0.05
fileSuggestion
Configure a custom script for
@
file autocomplete. See
File suggestion settings
{"type": "command", "command": "~/.claude/file-suggestion.sh"}
forceLoginMethod
Use
claudeai
to restrict login to Claude.ai accounts,
console
to restrict login to Claude Console (API usage billing) accounts
claudeai
forceLoginOrgUUID
Require login to belong to a specific organization. Accepts a single UUID string, which also pre-selects that organization during login, or an array of UUIDs where any listed organization is accepted without pre-selection. When set in managed settings, login fails if the authenticated account does not belong to a listed organization; an empty array fails closed and blocks login with a misconfiguration message
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
or
["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]
forceRemoteSettingsRefresh
(Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits rather than continuing with cached or no settings. When not set, startup continues without waiting for remote settings. See
fail-closed enforcement
true
gcpAuthRefresh
Custom script that refreshes GCP Application Default Credentials when they expire or cannot be loaded. See
advanced credential configuration
gcloud auth application-default login
hooks
Configure custom commands to run at lifecycle events. See
hooks documentation
for format
See
hooks
httpHookAllowedEnvVars
Allowlist of environment variable names HTTP hooks may interpolate into headers. When set, each hook’s effective
allowedEnvVars
is the intersection with this list. Undefined = no restriction. Arrays merge across settings sources. See
Hook configuration
["MY_TOKEN", "HOOK_SECRET"]
includeCoAuthoredBy
Deprecated
: Use
attribution
instead. Whether to include the
co-authored-by Claude
byline in git commits and pull requests (default:
true
)
false
includeGitInstructions
Include built-in commit and PR workflow instructions and the git status snapshot in Claude’s system prompt (default:
true
). Set to
false
to remove both, for example when using your own git workflow skills. The
CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS
environment variable takes precedence over this setting when set
false
language
Configure Claude’s preferred response language (e.g.,
"japanese"
,
"spanish"
,
"french"
). Claude will respond in this language by default. Also sets the
voice dictation
language
"japanese"
maxSkillDescriptionChars
Per-skill character cap on the combined
description
and
when_to_use
text in the
skill listing
Claude sees each turn (default:
1536
). Text longer than this is truncated. Raise to keep long descriptions intact at the cost of more context per turn; lower to fit more skills under
skillListingBudgetFraction
. Requires Claude Code v2.1.105 or later
2048
minimumVersion
Floor that prevents background auto-updates and
claude update
from installing a version below this one. Switching from the
"latest"
channel to
"stable"
via
/config
prompts you to stay on the current version or allow the downgrade. Choosing to stay sets this value. Also useful in
managed settings
to pin an organization-wide minimum
"2.1.100"
model
Override the default model to use for Claude Code.
--model
and
ANTHROPIC_MODEL
override this for one session
"claude-sonnet-4-6"
modelOverrides
Map Anthropic model IDs to provider-specific model IDs such as Bedrock inference profile ARNs. Each model picker entry uses its mapped value when calling the provider API. See
Override model IDs per version
{"claude-opus-4-6": "arn:aws:bedrock:..."}
otelHeadersHelper
Script to generate dynamic OpenTelemetry headers. Runs at startup and periodically. Set the refresh interval with
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
. See
Dynamic headers
/bin/generate_otel_headers.sh
outputStyle
Configure an output style to adjust the system prompt. See
output styles documentation
"Explanatory"
parentSettingsBehavior
(Managed settings only) Controls whether managed settings supplied programmatically by an embedding host process, such as the Agent SDK or an IDE extension, apply when an admin-deployed managed tier is also present.
"first-wins"
: the parent-supplied settings are dropped and only the admin tier applies.
"merge"
: the parent-supplied settings apply under the admin tier, filtered so they can tighten policy but not loosen it. Has no effect when no admin tier is deployed. Default:
"first-wins"
. Requires Claude Code v2.1.133 or later
"merge"
permissions
See table below for structure of permissions.
plansDirectory
Customize where plan files are stored. Path is relative to project root. Default:
~/.claude/plans
"./plans"
pluginTrustMessage
(Managed settings only) Custom message appended to the plugin trust warning shown before installation. Use this to add organization-specific context, for example to confirm that plugins from your internal marketplace are vetted.
"All plugins from our marketplace are approved by IT"
policyHelper
Admin-deployed executable that computes managed settings dynamically at startup. Only honored from MDM or a system
managed-settings.json
file. See
Compute managed settings with a policy helper
. Requires Claude Code v2.1.136 or later
{"path": "/usr/local/bin/claude-policy"}
preferredNotifChannel
Method for task-complete and permission-prompt notifications:
"auto"
,
"terminal_bell"
,
"iterm2"
,
"iterm2_with_bell"
,
"kitty"
,
"ghostty"
, or
"notifications_disabled"
. Default:
"auto"
, which sends a desktop notification in iTerm2, Ghostty, and Kitty and does nothing in other terminals. Set
"terminal_bell"
to ring the bell character in any terminal. Appears in
/config
as
Notifications
. See
Get a terminal bell or notification
"terminal_bell"
prefersReducedMotion
Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility
true
prUrlTemplate
URL template for the PR badge shown in the footer and in tool-result summaries. Substitutes
{host}
,
{owner}
,
{repo}
,
{number}
, and
{url}
from the
gh
-reported PR URL. Use to point PR links at an internal code-review tool instead of
github.com
. Does not affect
#123
autolinks in Claude’s prose
"https://reviews.example.com/{owner}/{repo}/pull/{number}"
respectGitignore
Control whether the
@
file picker respects
.gitignore
patterns. When
true
(default), files matching
.gitignore
patterns are excluded from suggestions
false
showClearContextOnPlanAccept
Show the “clear context” option on the plan accept screen. Defaults to
false
. Set to
true
to restore the option
true
showThinkingSummaries
Show
extended thinking
summaries in interactive sessions. When unset or
false
(default in interactive mode), thinking blocks are redacted by the API and shown as a collapsed stub. Redaction only changes what you see, not what the model generates: to reduce thinking spend,
lower the budget or disable thinking
instead. Non-interactive mode (
-p
) and SDK callers always receive summaries regardless of this setting
true
showTurnDuration
Show turn duration messages after responses, e.g. “Cooked for 1m 6s”. Default:
true
. Appears in
/config
as
Show turn duration
false
skillListingBudgetFraction
Fraction of the model’s context window reserved for the
skill listing
Claude sees each turn (default:
0.01
= 1%). When the listing exceeds the budget, descriptions for the least-used skills are collapsed to bare names so Claude can still invoke them but won’t see why. Raise to keep more descriptions visible at the cost of more context per turn.
/doctor
shows the current truncation count and which skills are affected. Requires Claude Code v2.1.105 or later
0.02
skillOverrides
Per-skill visibility overrides keyed by skill name. Value is
"on"
,
"name-only"
,
"user-invocable-only"
, or
"off"
. Lets you hide or collapse a skill without editing its SKILL.md. Does not apply to plugin skills, which are managed through
/plugin
. The
/skills
menu writes these to
.claude/settings.local.json
. See
Override skill visibility from settings
. Requires Claude Code v2.1.129 or later
{"legacy-context": "name-only", "deploy": "off"}
skipWebFetchPreflight
Skip the
WebFetch domain safety check
that sends each requested hostname to
api.anthropic.com
before fetching. Set to
true
in environments that block traffic to Anthropic, such as Bedrock, Vertex AI, or Foundry deployments with restrictive egress. When skipped, WebFetch attempts any URL without consulting the blocklist
true
spinnerTipsEnabled
Show tips in the spinner while Claude is working. Set to
false
to disable tips (default:
true
)
false
spinnerTipsOverride
Override spinner tips with custom strings.
tips
: array of tip strings.
excludeDefault
: if
true
, only show custom tips; if
false
or absent, custom tips are merged with built-in tips
{ "excludeDefault": true, "tips": ["Use our internal tool X"] }
spinnerVerbs
Customize the action verbs shown in the spinner and turn duration messages. Set
mode
to
"replace"
to use only your verbs, or
"append"
to add them to the defaults
{"mode": "append", "verbs": ["Pondering", "Crafting"]}
sshConfigs
SSH connections to show in the
Desktop
environment dropdown. Each entry requires
id
,
name
, and
sshHost
;
sshPort
,
sshIdentityFile
, and
startDirectory
are optional. When set in managed settings, connections are read-only for users. Read from managed and user settings only
[{"id": "dev-vm", "name": "Dev VM", "sshHost": "user@dev.example.com"}]
statusLine
Configure a custom status line to display context. See
statusLine
documentation
{"type": "command", "command": "~/.claude/statusline.sh"}
strictKnownMarketplaces
(Managed settings only) Allowlist of plugin marketplace sources. Undefined = no restrictions, empty array = lockdown. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. See
Managed marketplace restrictions
[{ "source": "github", "repo": "acme-corp/plugins" }]
syntaxHighlightingDisabled
Disable syntax highlighting in diffs, code blocks, and file previews
true
teammateMode
How
agent team
teammates display:
auto
(picks split panes in tmux or iTerm2, in-process otherwise),
in-process
, or
tmux
.
--teammate-mode
overrides this for one session. See
choose a display mode
"in-process"
terminalProgressBarEnabled
Show the terminal progress bar in supported terminals: ConEmu, Ghostty 1.2.0+, and iTerm2 3.6.6+. Default:
true
. Appears in
/config
as
Terminal progress bar
false
tui
Terminal UI renderer. Use
"fullscreen"
for the flicker-free
alt-screen renderer
with virtualized scrollback. Use
"default"
for the classic main-screen renderer. Set via
/tui
. You can also set the
CLAUDE_CODE_NO_FLICKER
environment variable
"fullscreen"
useAutoModeDuringPlan
Whether plan mode uses auto mode semantics when auto mode is available. Default:
true
. Not read from shared project settings. Appears in
/config
as “Use auto mode during plan”
false
viewMode
Default transcript view mode on startup:
"default"
,
"verbose"
, or
"focus"
. Overrides the sticky
/focus
selection when set. The
--verbose
flag overrides this for one session
"verbose"
voice
Voice dictation
settings:
enabled
turns dictation on,
mode
selects
"hold"
or
"tap"
, and
autoSubmit
sends the prompt on key release in hold mode. Written automatically when you run
/voice
. Requires a Claude.ai account
{ "enabled": true, "mode": "tap" }
voiceEnabled
Legacy alias for
voice.enabled
. Prefer the
voice
object
true
wslInheritsWindowsSettings
(Windows managed settings only) When
true
, Claude Code on WSL reads managed settings from the Windows policy chain in addition to
/etc/claude-code
, with Windows sources taking priority. Only honored when set in the HKLM registry key or
C:\Program Files\ClaudeCode\managed-settings.json
, both of which require Windows admin to write. For HKCU policy to also apply on WSL, the flag must additionally be set in HKCU itself. Has no effect on native Windows
true
​
Global config settings
These settings are stored in
~/.claude.json
rather than
settings.json
. Adding them to
settings.json
will trigger a schema validation error.
Versions before v2.1.119 also store
autoScrollEnabled
,
editorMode
,
showTurnDuration
,
teammateMode
, and
terminalProgressBarEnabled
here instead of in
settings.json
.
Key
Description
Example
autoConnectIde
Automatically connect to a running IDE when Claude Code starts from an external terminal. Default:
false
. Appears in
/config
as
Auto-connect to IDE (external terminal)
when running outside a VS Code or JetBrains terminal. The
CLAUDE_CODE_AUTO_CONNECT_IDE
environment variable overrides this when set
true
autoInstallIdeExtension
Automatically install the Claude Code IDE extension when running from a VS Code terminal. Default:
true
. Appears in
/config
as
Auto-install IDE extension
when running inside a VS Code or JetBrains terminal. You can also set the
CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL
environment variable
false
externalEditorContext
Prepend Claude’s previous response as
#
-commented context when you open the external editor with
Ctrl+G
. Default:
false
. Appears in
/config
as
Show last response in external editor
true
teammateDefaultModel
Default model for
agent team
teammates when the spawn prompt doesn’t specify one. Set to a model alias such as
"sonnet"
, or
null
to inherit the lead’s current
/model
selection. Appears in
/config
as
Default teammate model
"sonnet"
​
Worktree settings
Configure how
--worktree
creates and manages git worktrees.
Key
Description
Example
worktree.baseRef
Which ref new worktrees branch from.
"fresh"
(default) branches from
origin/<default-branch>
for a clean tree matching the remote.
"head"
branches from your current local
HEAD
, so unpushed commits and feature-branch state are present in the worktree. Applies to
--worktree
, the
EnterWorktree
tool, and subagent isolation
"head"
worktree.symlinkDirectories
Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. No directories are symlinked by default
["node_modules", ".cache"]
worktree.sparsePaths
Directories to check out in each worktree via git sparse-checkout. Only the listed directories plus root-level files are written to disk, which is faster in large monorepos
["packages/my-app", "shared/utils"]
To copy gitignored files like
.env
into new worktrees, use a
.worktreeinclude
file
in your project root instead of a setting.
​
Permission settings
Keys
Description
Example
allow
Array of permission rules to allow tool use. See
Permission rule syntax
below for pattern matching details
[ "Bash(git diff *)" ]
ask
Array of permission rules to ask for confirmation upon tool use. See
Permission rule syntax
below
[ "Bash(git push *)" ]
deny
Array of permission rules to deny tool use. Use this to exclude sensitive files from Claude Code access. See
Permission rule syntax
and
Bash permission limitations
[ "WebFetch", "Bash(curl *)", "Read(./.env)", "Read(./secrets/**)" ]
additionalDirectories
Additional
working directories
for file access. Most
.claude/
configuration is
not discovered
from these directories
[ "../docs/" ]
defaultMode
Default
permission mode
when opening Claude Code. Valid values:
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
,
bypassPermissions
. The
--permission-mode
CLI flag overrides this setting for a single session
"acceptEdits"
disableBypassPermissionsMode
Set to
"disable"
to prevent
bypassPermissions
mode from being activated. This disables the
--dangerously-skip-permissions
command-line flag. Typically placed in
managed settings
to enforce organizational policy, but works from any scope
"disable"
skipDangerousModePermissionPrompt
Skip the confirmation prompt shown before entering bypass permissions mode via
--dangerously-skip-permissions
or
defaultMode: "bypassPermissions"
. Ignored when set in project settings (
.claude/settings.json
) to prevent untrusted repositories from auto-bypassing the prompt
true
​
Permission rule syntax
Permission rules follow the format
Tool
or
Tool(specifier)
. Rules are evaluated in order: deny rules first, then ask, then allow. The first matching rule wins.
Quick examples:
Rule
Effect
Bash
Matches all Bash commands
Bash(npm run *)
Matches commands starting with
npm run
Read(./.env)
Matches reading the
.env
file
WebFetch(domain:example.com)
Matches fetch requests to example.com
For the complete rule syntax reference, including wildcard behavior, tool-specific patterns for Read, Edit, WebFetch, MCP, and Agent rules, and security limitations of Bash patterns, see
Permission rule syntax
.
​
Sandbox settings
Configure advanced sandboxing behavior. Sandboxing isolates bash commands from your filesystem and network. See
Sandboxing
for details.
Keys
Description
Example
enabled
Enable bash sandboxing (macOS, Linux, and WSL2). Default: false
true
failIfUnavailable
Exit with an error at startup if
sandbox.enabled
is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed settings deployments that require sandboxing as a hard gate
true
autoAllowBashIfSandboxed
Auto-approve bash commands when sandboxed. Default: true
true
excludedCommands
Commands that should run outside of the sandbox
["docker *"]
allowUnsandboxedCommands
Allow commands to run outside the sandbox via the
dangerouslyDisableSandbox
parameter. When set to
false
, the
dangerouslyDisableSandbox
escape hatch is completely disabled and all commands must run sandboxed (or be in
excludedCommands
). Useful for enterprise policies that require strict sandboxing. Default: true
false
filesystem.allowWrite
Additional paths where sandboxed commands can write. Arrays are merged across all settings scopes: user, project, and managed paths are combined, not replaced. Also merged with paths from
Edit(...)
allow permission rules. See
path prefixes
below.
["/tmp/build", "~/.kube"]
filesystem.denyWrite
Paths where sandboxed commands cannot write. Arrays are merged across all settings scopes. Also merged with paths from
Edit(...)
deny permission rules.
["/etc", "/usr/local/bin"]
filesystem.denyRead
Paths where sandboxed commands cannot read. Arrays are merged across all settings scopes. Also merged with paths from
Read(...)
deny permission rules.
["~/.aws/credentials"]
filesystem.allowRead
Paths to re-allow reading within
denyRead
regions. Takes precedence over
denyRead
. Arrays are merged across all settings scopes. Use this to create workspace-only read access patterns.
["."]
filesystem.allowManagedReadPathsOnly
(Managed settings only) Only
filesystem.allowRead
paths from managed settings are respected.
denyRead
still merges from all sources. Default: false
true
network.allowUnixSockets
(macOS only) Unix socket paths accessible in sandbox. Ignored on Linux and WSL2, where the seccomp filter cannot inspect socket paths; use
allowAllUnixSockets
instead.
["~/.ssh/agent-socket"]
network.allowAllUnixSockets
Allow all Unix socket connections in sandbox. On Linux and WSL2 this is the only way to permit Unix sockets, since it skips the seccomp filter that otherwise blocks
socket(AF_UNIX, ...)
calls. Default: false
true
network.allowLocalBinding
Allow binding to localhost ports (macOS only). Default: false
true
network.allowMachLookup
Additional XPC/Mach service names the sandbox may look up (macOS only). Supports a single trailing
*
for prefix matching. Needed for tools that communicate via XPC such as the iOS Simulator or Playwright.
["com.apple.coresimulator.*"]
network.allowedDomains
Array of domains to allow for outbound network traffic. Supports wildcards (e.g.,
*.example.com
).
["github.com", "*.npmjs.org"]
network.deniedDomains
Array of domains to block for outbound network traffic. Supports the same wildcard syntax as
allowedDomains
. Takes precedence over
allowedDomains
when both match. Merged from all settings sources regardless of
allowManagedDomainsOnly
.
["sensitive.cloud.example.com"]
network.allowManagedDomainsOnly
(Managed settings only) Only
allowedDomains
and
WebFetch(domain:...)
allow rules from managed settings are respected. Domains from user, project, and local settings are ignored. Non-allowed domains are blocked automatically without prompting the user. Denied domains are still respected from all sources. Default: false
true
network.httpProxyPort
HTTP proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy.
8080
network.socksProxyPort
SOCKS5 proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy.
8081
enableWeakerNestedSandbox
Enable weaker sandbox for unprivileged Docker environments (Linux and WSL2 only).
Reduces security.
Default: false
true
enableWeakerNetworkIsolation
(macOS only) Allow access to the system TLS trust service (
com.apple.trustd.agent
) in the sandbox. Required for Go-based tools like
gh
,
gcloud
, and
terraform
to verify TLS certificates when using
httpProxyPort
with a MITM proxy and custom CA.
Reduces security
by opening a potential data exfiltration path. Default: false
true
bwrapPath
(Managed settings only, Linux/WSL2) Absolute path to the bubblewrap (
bwrap
) binary. Overrides automatic detection via
PATH
. Only honored from
managed settings
, not from user or project settings. Useful when
bwrap
is installed at a non-standard location in managed environments.
/opt/admin/bwrap
socatPath
(Managed settings only, Linux/WSL2) Absolute path to the
socat
binary used for the sandbox network proxy. Overrides automatic detection via
PATH
. Only honored from managed settings.
/opt/admin/socat
​
Sandbox path prefixes
Paths in
filesystem.allowWrite
,
filesystem.denyWrite
,
filesystem.denyRead
, and
filesystem.allowRead
support these prefixes:
Prefix
Meaning
Example
/
Absolute path from filesystem root
/tmp/build
stays
/tmp/build
~/
Relative to home directory
~/.kube
becomes
$HOME/.kube
./
or no prefix
Relative to the project root for project settings, or to
~/.claude
for user settings
./output
in
.claude/settings.json
resolves to
<project-root>/output
The older
//path
prefix for absolute paths still works. If you previously used single-slash
/path
expecting project-relative resolution, switch to
./path
. This syntax differs from
Read and Edit permission rules
, which use
//path
for absolute and
/path
for project-relative. Sandbox filesystem paths use standard conventions:
/tmp/build
is an absolute path.
Configuration example:
{
"sandbox"
: {
"enabled"
:
true
,
"autoAllowBashIfSandboxed"
:
true
,
"excludedCommands"
: [
"docker *"
],
"filesystem"
: {
"allowWrite"
: [
"/tmp/build"
,
"~/.kube"
],
"denyRead"
: [
"~/.aws/credentials"
]
},
"network"
: {
"allowedDomains"
: [
"github.com"
,
"*.npmjs.org"
,
"registry.yarnpkg.com"
],
"deniedDomains"
: [
"uploads.github.com"
],
"allowUnixSockets"
: [
"/var/run/docker.sock"
],
"allowLocalBinding"
:
true
}
}
}
Filesystem and network restrictions
can be configured in two ways that are merged together:
sandbox.filesystem
settings
(shown above): Control paths at the OS-level sandbox boundary. These restrictions apply to all subprocess commands (e.g.,
kubectl
,
terraform
,
npm
), not just Claude’s file tools.
Permission rules
: Use
Edit
allow/deny rules to control Claude’s file tool access,
Read
deny rules to block reads, and
WebFetch
allow/deny rules to control network domains. Paths from these rules are also merged into the sandbox configuration.
​
Attribution settings
Claude Code adds attribution to git commits and pull requests. These are configured separately:
Commits use
git trailers
(like
Co-Authored-By
) by default,  which can be customized or disabled
Pull request descriptions are plain text
Keys
Description
commit
Attribution for git commits, including any trailers. Empty string hides commit attribution
pr
Attribution for pull request descriptions. Empty string hides pull request attribution
Default commit attribution:
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default pull request attribution:
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Example:
{
"attribution"
: {
"commit"
:
"Generated with AI
\n\n
Co-Authored-By: AI <ai@example.com>"
,
"pr"
:
""
}
}
The
attribution
setting takes precedence over the deprecated
includeCoAuthoredBy
setting. To hide all attribution, set
commit
and
pr
to empty strings.
​
File suggestion settings
Configure a custom command for
@
file path autocomplete. The built-in file suggestion uses fast filesystem traversal, but large monorepos may benefit from project-specific indexing such as a pre-built file index or custom tooling.
{
"fileSuggestion"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/file-suggestion.sh"
}
}
The command runs with the same environment variables as
hooks
, including
CLAUDE_PROJECT_DIR
. It receives JSON via stdin with a
query
field:
{
"query"
:
"src/comp"
}
Output newline-separated file paths to stdout (currently limited to 15):
src/components/Button.tsx
src/components/Modal.tsx
src/components/Form.tsx
Example:
#!/bin/bash
query
=
$(
cat
|
jq
-r
'.query'
)
your-repo-file-index
--query
"
$query
"
|
head
-20
​
Hook configuration
These settings control which hooks are allowed to run and what HTTP hooks can access. The
allowManagedHooksOnly
setting can only be configured in
managed settings
. The URL and env var allowlists can be set at any settings level and merge across sources.
Behavior when
allowManagedHooksOnly
is
true
:
Managed hooks and SDK hooks are loaded
Hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. This lets administrators distribute vetted hooks through an organization marketplace while blocking everything else. Trust is granted by full
plugin@marketplace
ID, so a plugin with the same name from a different marketplace stays blocked
User hooks, project hooks, and all other plugin hooks are blocked
Restrict HTTP hook URLs:
Limit which URLs HTTP hooks can target. Supports
*
as a wildcard for matching. When the array is defined, HTTP hooks targeting non-matching URLs are silently blocked. Hostname matching is case-insensitive and ignores a trailing FQDN dot, matching DNS semantics.
{
"allowedHttpHookUrls"
: [
"https://hooks.example.com/*"
,
"http://localhost:*"
]
}
Restrict HTTP hook environment variables:
Limit which environment variable names HTTP hooks can interpolate into header values. Each hook’s effective
allowedEnvVars
is the intersection of its own list and this setting.
{
"httpHookAllowedEnvVars"
: [
"MY_TOKEN"
,
"HOOK_SECRET"
]
}
​
Compute managed settings with a policy helper
The
policyHelper
setting points at an executable that computes managed settings at startup, so admins can derive policy from device posture, identity, or a remote service instead of a static file. Configure it from MDM or a system
managed-settings.json
file. Claude Code ignores
policyHelper
when it appears in any other scope, including user settings, project settings, the HKCU registry hive, and
server-managed settings
.
The setting accepts these keys:
Key
Type
Description
path
string
Absolute path to the helper executable
timeoutMs
number
How long to wait for the helper before treating the run as failed
refreshIntervalMs
number
How often to re-run the helper in the background. Set to
0
to disable refresh, or to at least
60000
The helper writes a JSON envelope to stdout. Put the settings under a
managedSettings
key rather than at the top level, since a bare settings object parses with
managedSettings
undefined and applies nothing:
{
"managedSettings"
: {
"permissions"
: {
"deny"
: [
"Read(//etc/secrets/**)"
] }
},
"claudeMd"
:
"# Organization context
\n
..."
,
"appendSystemPrompt"
:
"Always cite the internal style guide."
}
When the helper emits
managedSettings
, that object replaces the file-based managed settings for the run. When the helper exits non-zero at startup, Claude Code prints the error and refuses to start, so a helper that needs outage resilience should serve from its own cache and exit
0
.
​
Settings precedence
Settings apply in order of precedence. From highest to lowest:
Managed settings
(
server-managed
,
MDM/OS-level policies
, or
managed settings
)
Policies deployed by IT through server delivery, MDM configuration profiles, registry policies, or managed settings files
Cannot be overridden by any other level, including command line arguments
Within the managed tier, precedence is: server-managed > MDM/OS-level policies > file-based (
managed-settings.d/*.json
+
managed-settings.json
) > HKCU registry (Windows only). Only one managed source is used; sources do not merge across tiers. Within the file-based tier, drop-in files and the base file are merged together.
Embedding hosts such as Claude Desktop can supply policy via the SDK
managedSettings
option. By default this is ignored when any managed-settings tier is present. Administrators can opt in by setting
parentSettingsBehavior
to
"merge"
. The embedder’s values are filtered so they can tighten managed policy but not loosen it.
Command line arguments
Temporary overrides for a specific session. JSON passed via
--settings <file-or-json>
merges with file-based settings using the same rules as the other layers: a key set here overrides the same key in local, project, or user settings, and omitting a key leaves the lower-layer value in place
Local project settings
(
.claude/settings.local.json
)
Personal project-specific settings
Shared project settings
(
.claude/settings.json
)
Team-shared project settings in source control
User settings
(
~/.claude/settings.json
)
Personal global settings
This hierarchy ensures that organizational policies are always enforced while still allowing teams and individuals to customize their experience. The same precedence applies whether you run Claude Code from the CLI, the
VS Code extension
, or a
JetBrains IDE
.
For example, if your user settings set
permissions.defaultMode
to
acceptEdits
and a project’s shared settings set it to
default
, the project value applies. The example below covers how array-valued settings such as permission rules combine instead.
Array settings merge across scopes.
When the same array-valued setting (such as
sandbox.filesystem.allowWrite
or
permissions.allow
) appears in multiple scopes, the arrays are
concatenated and deduplicated
, not replaced. This means lower-priority scopes can add entries without overriding those set by higher-priority scopes, and vice versa. For example, if managed settings set
allowWrite
to
["/opt/company-tools"]
and a user adds
["~/.kube"]
, both paths are included in the final configuration.
​
Verify active settings
Run
/status
inside Claude Code to see which settings sources are active. The Status tab includes a
Setting sources
line that lists each layer Claude Code loaded for the current session, such as
User settings
or
Project local settings
. When
managed settings
are in effect, the entry shows the delivery channel in parentheses, for example
Enterprise managed settings (remote)
,
(plist)
,
(HKLM)
,
(HKCU)
, or
(file)
. A layer appears in the list only when that source is loaded with at least one key, so an empty list means no settings sources were found.
The
Setting sources
line confirms which sources are being read. It does not show which layer supplied each individual key. The Config tab in the same dialog is an editor for a fixed set of toggles such as theme and verbose output, not a view of your
settings.json
contents. If a settings file contains errors, such as invalid JSON or a value that fails validation,
/status
reports the issue so you can fix it.
​
Key points about the configuration system
Memory files (
CLAUDE.md
)
: Contain instructions and context that Claude loads at startup
Settings files (JSON)
: Configure permissions, environment variables, and tool behavior
Skills
: Custom prompts that can be invoked with
/skill-name
or loaded by Claude automatically
MCP servers
: Extend Claude Code with additional tools and integrations
Precedence
: Higher-level configurations (Managed) override lower-level ones (User/Project)
Inheritance
: Settings merge across scopes; scalar values from higher-priority scopes override, and arrays concatenate
​
System prompt
Claude Code’s internal system prompt is not published. To add custom instructions, use
CLAUDE.md
files or the
--append-system-prompt
flag.
​
Excluding sensitive files
To prevent Claude Code from accessing files containing sensitive information like API keys, secrets, and environment files, use the
permissions.deny
setting in your
.claude/settings.json
file:
{
"permissions"
: {
"deny"
: [
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
,
"Read(./config/credentials.json)"
,
"Read(./build)"
]
}
}
This replaces the deprecated
ignorePatterns
configuration. Files matching these patterns are excluded from file discovery and search results, and read operations on these files are denied.
​
Subagent configuration
Claude Code supports custom AI subagents that can be configured at both user and project levels. These subagents are stored as Markdown files with YAML frontmatter:
User subagents
:
~/.claude/agents/
- Available across all your projects
Project subagents
:
.claude/agents/
- Specific to your project and can be shared with your team
Subagent files define specialized AI assistants with custom prompts and tool permissions. Learn more about creating and using subagents in the
subagents documentation
.
​
Plugin configuration
Claude Code supports a plugin system that lets you extend functionality with skills, agents, hooks, and MCP servers. Plugins are distributed through marketplaces and can be configured at both user and repository levels.
​
Plugin settings
Plugin-related settings in
settings.json
:
{
"enabledPlugins"
: {
"formatter@acme-tools"
:
true
,
"deployer@acme-tools"
:
true
,
"analyzer@security-plugins"
:
false
},
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/claude-plugins"
}
}
}
}
​
enabledPlugins
Controls which plugins are enabled. Format:
"plugin-name@marketplace-name": true/false
Scopes
:
User settings
(
~/.claude/settings.json
): Personal plugin preferences
Project settings
(
.claude/settings.json
): Project-specific plugins shared with team
Local settings
(
.claude/settings.local.json
): Per-machine overrides (not committed)
Managed settings
(
managed-settings.json
): Organization-wide policy overrides that block installation at all scopes and hide the plugin from the marketplace
Project settings take precedence over user settings, so setting a plugin to
false
in
~/.claude/settings.json
does not disable a plugin that the project’s
.claude/settings.json
enables. To opt out of a project-enabled plugin on your machine, set it to
false
in
.claude/settings.local.json
instead.
Plugins force-enabled by managed settings cannot be disabled this way, since managed settings override local settings.
Example
:
{
"enabledPlugins"
: {
"code-formatter@team-tools"
:
true
,
"deployment-tools@team-tools"
:
true
,
"experimental-features@personal"
:
false
}
}
​
extraKnownMarketplaces
Defines additional marketplaces that should be made available for the repository. Typically used in repository-level settings to ensure team members have access to required plugin sources.
When a repository includes
extraKnownMarketplaces
:
Team members are prompted to install the marketplace when they trust the folder
Team members are then prompted to install plugins from that marketplace
Users can skip unwanted marketplaces or plugins (stored in user settings)
Installation respects trust boundaries and requires explicit consent
Example
:
{
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/claude-plugins"
}
},
"security-plugins"
: {
"source"
: {
"source"
:
"git"
,
"url"
:
"https://git.example.com/security/plugins.git"
}
}
}
}
Marketplace source types
:
github
: GitHub repository (uses
repo
)
git
: Any git URL (uses
url
)
directory
: Local filesystem path (uses
path
, for development only)
hostPattern
: regex pattern to match marketplace hosts (uses
hostPattern
)
settings
: inline marketplace declared directly in settings.json without a separate hosted repository (uses
name
and
plugins
)
Each marketplace entry also accepts an optional
autoUpdate
Boolean. Set
"autoUpdate": true
alongside
source
to make Claude Code refresh that marketplace and update its installed plugins at startup. When omitted, official Anthropic marketplaces default to
true
and all other marketplaces default to
false
. See
Configure auto-updates
.
Use
source: 'settings'
to declare a small set of plugins inline without setting up a hosted marketplace repository. Plugins listed here must reference external sources such as GitHub or npm. You still need to enable each plugin separately in
enabledPlugins
.
{
"extraKnownMarketplaces"
: {
"team-tools"
: {
"source"
: {
"source"
:
"settings"
,
"name"
:
"team-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
}
}
]
}
}
}
}
​
strictKnownMarketplaces
Managed settings only
: Controls which plugin marketplaces users are allowed to add and install plugins from. This setting can only be configured in
managed settings
and provides administrators with strict control over marketplace sources.
Managed settings file locations
:
macOS
:
/Library/Application Support/ClaudeCode/managed-settings.json
Linux and WSL
:
/etc/claude-code/managed-settings.json
Windows
:
C:\Program Files\ClaudeCode\managed-settings.json
Key characteristics
:
Only available in managed settings (
managed-settings.json
)
Cannot be overridden by user or project settings (highest precedence)
Enforced BEFORE network/filesystem operations (blocked sources never execute)
Uses exact matching for source specifications (including
ref
,
path
for git sources), except
hostPattern
and
pathPattern
, which use regex matching
Allowlist behavior
:
undefined
(default): No restrictions - users can add any marketplace
Empty array
[]
: Complete lockdown - users cannot add any new marketplaces
List of sources: Users can only add marketplaces that match exactly
All supported source types
:
The allowlist supports multiple marketplace source types. Most sources use exact matching, while
hostPattern
and
pathPattern
use regex matching against the marketplace host and filesystem path respectively.
GitHub repositories
:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"ref"
:
"main"
,
"path"
:
"marketplace"
}
Fields:
repo
(required),
ref
(optional: branch/tag/SHA),
path
(optional: subdirectory)
Git repositories
:
{
"source"
:
"git"
,
"url"
:
"https://gitlab.example.com/tools/plugins.git"
}
{
"source"
:
"git"
,
"url"
:
"https://bitbucket.org/acme-corp/plugins.git"
,
"ref"
:
"production"
}
{
"source"
:
"git"
,
"url"
:
"ssh://git@git.example.com/plugins.git"
,
"ref"
:
"v3.1"
,
"path"
:
"approved"
}
Fields:
url
(required),
ref
(optional: branch/tag/SHA),
path
(optional: subdirectory)
URL-based marketplaces
:
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
}
{
"source"
:
"url"
,
"url"
:
"https://cdn.example.com/marketplace.json"
,
"headers"
: {
"Authorization"
:
"Bearer ${TOKEN}"
} }
Fields:
url
(required),
headers
(optional: HTTP headers for authenticated access)
URL-based marketplaces only download the
marketplace.json
file. They do not download plugin files from the server. Plugins in URL-based marketplaces must use external sources (GitHub, npm, or git URLs) rather than relative paths. For plugins with relative paths, use a Git-based marketplace instead. See
Troubleshooting
for details.
NPM packages
:
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/claude-plugins"
}
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/approved-marketplace"
}
Fields:
package
(required, supports scoped packages)
File paths
:
{
"source"
:
"file"
,
"path"
:
"/usr/local/share/claude/acme-marketplace.json"
}
{
"source"
:
"file"
,
"path"
:
"/opt/acme-corp/plugins/marketplace.json"
}
Fields:
path
(required: absolute path to marketplace.json file)
Directory paths
:
{
"source"
:
"directory"
,
"path"
:
"/usr/local/share/claude/acme-plugins"
}
{
"source"
:
"directory"
,
"path"
:
"/opt/acme-corp/approved-marketplaces"
}
Fields:
path
(required: absolute path to directory containing
.claude-plugin/marketplace.json
)
Host pattern matching
:
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^gitlab
\\
.internal
\\
.example
\\
.com$"
}
Fields:
hostPattern
(required: regex pattern to match against the marketplace host)
Use host pattern matching when you want to allow all marketplaces from a specific host without enumerating each repository individually. This is useful for organizations with internal GitHub Enterprise or GitLab servers where developers create their own marketplaces.
Host extraction by source type:
github
: always matches against
github.com
git
: extracts hostname from the URL (supports both HTTPS and SSH formats)
url
: extracts hostname from the URL
npm
,
file
,
directory
: not supported for host pattern matching
Path pattern matching
:
{
"source"
:
"pathPattern"
,
"pathPattern"
:
"^/opt/approved/"
}
{
"source"
:
"pathPattern"
,
"pathPattern"
:
".*"
}
Fields:
pathPattern
(required: regex pattern matched against the
path
field of
file
and
directory
sources)
Use path pattern matching to allow filesystem-based marketplaces alongside
hostPattern
restrictions for network sources. Set
".*"
to allow all local paths, or a narrower pattern to restrict to specific directories.
Configuration examples
:
Example: allow specific marketplaces only:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
},
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
},
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
},
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/compliance-plugins"
}
]
}
Example - Disable all marketplace additions:
{
"strictKnownMarketplaces"
: []
}
Example: allow all marketplaces from an internal git server:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
Exact matching requirements
:
Marketplace sources must match
exactly
for a user’s addition to be allowed. For git-based sources (
github
and
git
), this includes all optional fields:
The
repo
or
url
must match exactly
The
ref
field must match exactly (or both be undefined)
The
path
field must match exactly (or both be undefined)
Examples of sources that
do NOT match
:
// These are DIFFERENT sources:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"ref"
:
"main"
}
// These are also DIFFERENT:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"path"
:
"marketplace"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
Comparison with
extraKnownMarketplaces
:
Aspect
strictKnownMarketplaces
extraKnownMarketplaces
Purpose
Organizational policy enforcement
Team convenience
Settings file
managed-settings.json
only
Any settings file
Behavior
Blocks non-allowlisted additions
Auto-installs missing marketplaces
When enforced
Before network/filesystem operations
After user trust prompt
Can be overridden
No (highest precedence)
Yes (by higher precedence settings)
Source format
Direct source object
Named marketplace with nested source
Use case
Compliance, security restrictions
Onboarding, standardization
Format difference
:
strictKnownMarketplaces
uses direct source objects:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
]
}
extraKnownMarketplaces
requires named marketplaces:
{
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
}
}
}
Using both together
:
strictKnownMarketplaces
is a policy gate: it controls what users may add but does not register any marketplaces. To both restrict and pre-register a marketplace for all users, set both in
managed-settings.json
:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
],
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
}
}
}
With only
strictKnownMarketplaces
set, users can still add the allowed marketplace manually via
/plugin marketplace add
, but it is not available automatically.
Important notes
:
Restrictions are checked BEFORE any network requests or filesystem operations
When blocked, users see clear error messages indicating the source is blocked by managed policy
The restriction is enforced on marketplace add and on plugin install, update, refresh, and auto-update. A marketplace added before the policy was set cannot be used to install or update plugins once its source no longer matches the allowlist
Managed settings have the highest precedence and cannot be overridden
See
Managed marketplace restrictions
for user-facing documentation.
​
Managing plugins
Use the
/plugin
command to manage plugins interactively:
Browse available plugins from marketplaces
Install/uninstall plugins
Enable/disable plugins
View plugin details (skills, agents, hooks provided)
Add/remove marketplaces
Learn more about the plugin system in the
plugins documentation
.
​
Environment variables
Environment variables let you control Claude Code behavior without editing settings files. Any variable can also be configured in
settings.json
under the
env
key to apply it to every session or roll it out to your team.
See the
environment variables reference
for the full list.
​
Tools available to Claude
Claude Code has access to a set of tools for reading, editing, searching, running commands, and orchestrating subagents. Tool names are the exact strings you use in permission rules and hook matchers.
See the
tools reference
for the full list and Bash tool behavior details.
​
See also
Permissions
: permission system, rule syntax, tool-specific patterns, and managed policies
Authentication
: set up user access to Claude Code
Debug your configuration
: diagnose why a setting, hook, or MCP server isn’t taking effect
Troubleshoot installation and login
: installation, authentication, and platform issues
Was this page helpful?
Yes
No
Permissions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/settings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Claude Code settings
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use thi...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Settings and permissions
Claude Code settings
Settings and permissions
Settings
Permissions
Sandboxing
Model and responses
Model configuration
Speed up responses with fast mode
Output styles
Interface
Terminal configuration
Fullscreen rendering
Voice dictation
Customize status line
Customize keyboard shortcuts
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code offers a variety of settings to configure its behavior to meet your needs. You can configure Claude Code by running the
/config
command when using the interactive REPL, which opens a tabbed Settings interface where you can view status information and modify configuration options.
​
Configuration scopes
Claude Code uses a
scope system
to determine where configurations apply and who they’re shared with. Understanding scopes helps you decide how to configure Claude Code for personal use, team collaboration, or enterprise deployment.
​
Available scopes
Scope
Location
Who it affects
Shared with team?
Managed
Server-managed settings, plist / registry, or system-level
managed-settings.json
All users on the machine
Yes (deployed by IT)
User
~/.claude/
directory
You, across all projects
No
Project
.claude/
in repository
All collaborators on this repository
Yes (committed to git)
Local
.claude/settings.local.json
You, in this repository only
No (gitignored)
​
When to use each scope
Managed scope
is for:
Security policies that must be enforced organization-wide
Compliance requirements that can’t be overridden
Standardized configurations deployed by IT/DevOps
User scope
is best for:
Personal preferences you want everywhere (themes, editor settings)
Tools and plugins you use across all projects
API keys and authentication (stored securely)
Project scope
is best for:
Team-shared settings (permissions, hooks, MCP servers)
Plugins the whole team should have
Standardizing tooling across collaborators
Local scope
is best for:
Personal overrides for a specific project
Testing configurations before sharing with the team
Machine-specific settings that won’t work for others
​
How scopes interact
When the same setting appears in multiple scopes, Claude Code applies them in priority order:
Managed
(highest) - can’t be overridden by anything
Command line arguments
- temporary session overrides
Local
- overrides project and user settings
Project
- overrides user settings
User
(lowest) - applies when nothing else specifies the setting
For example, if your user settings set
spinnerTipsEnabled
to
true
and project settings set it to
false
, the project value applies. Permission rules behave differently because they merge across scopes rather than override. See
Settings precedence
.
​
What uses scopes
Scopes apply to many Claude Code features:
Feature
User location
Project location
Local location
Settings
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
Subagents
~/.claude/agents/
.claude/agents/
None
MCP servers
~/.claude.json
.mcp.json
~/.claude.json
(per-project)
Plugins
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
CLAUDE.md
~/.claude/CLAUDE.md
CLAUDE.md
or
.claude/CLAUDE.md
CLAUDE.local.md
On Windows, paths shown as
~/.claude
resolve to
%USERPROFILE%\.claude
.
​
Settings files
The
settings.json
file is the official mechanism for configuring Claude
Code through hierarchical settings:
User settings
are defined in
~/.claude/settings.json
and apply to all
projects.
Project settings
are saved in your project directory:
.claude/settings.json
for settings that are checked into source control and shared with your team
.claude/settings.local.json
for settings that are not checked in, useful for personal preferences and experimentation. Claude Code will configure git to ignore
.claude/settings.local.json
when it is created.
Managed settings
: For organizations that need centralized control, Claude Code supports multiple delivery mechanisms for managed settings. All use the same JSON format and cannot be overridden by user or project settings:
Server-managed settings
: delivered from Anthropic’s servers via the Claude.ai admin console. See
server-managed settings
.
MDM/OS-level policies
: delivered through native device management on macOS and Windows:
macOS:
com.anthropic.claudecode
managed preferences domain. The plist’s top-level keys mirror
managed-settings.json
, with nested settings as dictionaries and arrays as plist arrays. Deploy via configuration profiles in Jamf, Iru (Kandji), or similar MDM tools.
Windows:
HKLM\SOFTWARE\Policies\ClaudeCode
registry key with a
Settings
value (REG_SZ or REG_EXPAND_SZ) containing JSON (deployed via Group Policy or Intune)
Windows (user-level):
HKCU\SOFTWARE\Policies\ClaudeCode
(lowest policy priority, only used when no admin-level source exists)
File-based
:
managed-settings.json
and
managed-mcp.json
deployed to system directories:
macOS:
/Library/Application Support/ClaudeCode/
Linux and WSL:
/etc/claude-code/
Windows:
C:\Program Files\ClaudeCode\
The legacy Windows path
C:\ProgramData\ClaudeCode\managed-settings.json
is no longer supported as of v2.1.75. Administrators who deployed settings to that location must migrate files to
C:\Program Files\ClaudeCode\managed-settings.json
.
File-based managed settings also support a drop-in directory at
managed-settings.d/
in the same system directory alongside
managed-settings.json
. This lets separate teams deploy independent policy fragments without coordinating edits to a single file.
Following the systemd convention,
managed-settings.json
is merged first as the base, then all
*.json
files in the drop-in directory are sorted alphabetically and merged on top. Later files override earlier ones for scalar values; arrays are concatenated and de-duplicated; objects are deep-merged. Hidden files starting with
.
are ignored.
Use numeric prefixes to control merge order, for example
10-telemetry.json
and
20-security.json
.
See
managed settings
and
Managed MCP configuration
for details.
This
repository
includes starter deployment templates for Jamf, Iru (Kandji), Intune, and Group Policy. Use these as starting points and adjust them to fit your needs.
Managed deployments can also restrict
plugin marketplace additions
using
strictKnownMarketplaces
. For more information, see
Managed marketplace restrictions
.
Other configuration
is stored in
~/.claude.json
. This file contains your OAuth session,
MCP server
configurations for user and local scopes, per-project state (allowed tools, trust settings), and various caches. Project-scoped MCP servers are stored separately in
.mcp.json
.
Claude Code automatically creates timestamped backups of configuration files and retains the five most recent backups to prevent data loss.
Example settings.json
{
"$schema"
:
"https://json.schemastore.org/claude-code-settings.json"
,
"permissions"
: {
"allow"
: [
"Bash(npm run lint)"
,
"Bash(npm run test *)"
,
"Read(~/.zshrc)"
],
"deny"
: [
"Bash(curl *)"
,
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
]
},
"env"
: {
"CLAUDE_CODE_ENABLE_TELEMETRY"
:
"1"
,
"OTEL_METRICS_EXPORTER"
:
"otlp"
},
"companyAnnouncements"
: [
"Welcome to Acme Corp! Review our code guidelines at docs.acme.com"
,
"Reminder: Code reviews required for all PRs"
,
"New security policy in effect"
]
}
The
$schema
line in the example above points to the
official JSON schema
for Claude Code settings. Adding it to your
settings.json
enables autocomplete and inline validation in VS Code, Cursor, and any other editor that supports JSON schema validation.
The published schema is updated periodically and may not include settings added in the most recent CLI releases, so a validation warning on a recently documented field does not necessarily mean your configuration is invalid.
​
Available settings
settings.json
supports a number of options:
Key
Description
Example
agent
Run the main thread as a named subagent. Applies that subagent’s system prompt, tool restrictions, and model. See
Invoke subagents explicitly
"code-reviewer"
allowedChannelPlugins
(Managed settings only) Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Undefined = fall back to the default, empty array = block all channel plugins. Requires
channelsEnabled: true
. See
Restrict which channel plugins can run
[{ "marketplace": "claude-plugins-official", "plugin": "telegram" }]
allowedHttpHookUrls
Allowlist of URL patterns that HTTP hooks may target. Supports
*
as a wildcard. When set, hooks with non-matching URLs are blocked. Undefined = no restriction, empty array = block all HTTP hooks. Arrays merge across settings sources. See
Hook configuration
["https://hooks.example.com/*"]
allowedMcpServers
When set in managed-settings.json, allowlist of MCP servers users can configure. Undefined = no restrictions, empty array = lockdown. Applies to all scopes. Denylist takes precedence. See
Managed MCP configuration
[{ "serverName": "github" }]
allowManagedHooksOnly
(Managed settings only) Only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. User, project, and all other plugin hooks are blocked. See
Hook configuration
true
allowManagedMcpServersOnly
(Managed settings only) Only
allowedMcpServers
from managed settings are respected.
deniedMcpServers
still merges from all sources. Users can still add MCP servers, but only the admin-defined allowlist applies. See
Managed MCP configuration
true
allowManagedPermissionRulesOnly
(Managed settings only) Prevent user and project settings from defining
allow
,
ask
, or
deny
permission rules. Only rules in managed settings apply. See
Managed-only settings
true
alwaysThinkingEnabled
Enable
extended thinking
by default for all sessions. Typically configured via the
/config
command rather than editing directly. To force thinking off regardless of this setting, set
CLAUDE_CODE_DISABLE_THINKING
in
env
true
apiKeyHelper
Custom script, to be executed in
/bin/sh
, to generate an auth value. This value will be sent as
X-Api-Key
and
Authorization: Bearer
headers for model requests. Set the refresh interval with
CLAUDE_CODE_API_KEY_HELPER_TTL_MS
/bin/generate_temp_api_key.sh
attribution
Customize attribution for git commits and pull requests. See
Attribution settings
{"commit": "🤖 Generated with Claude Code", "pr": ""}
autoMemoryDirectory
Custom directory for
auto memory
storage. Accepts an absolute path or a
~/
-prefixed path. Accepted from policy and user settings, and from the
--settings
flag. Not accepted from project or local settings, since a cloned repository could supply either file to redirect memory writes to sensitive locations
"~/my-memory-dir"
autoMemoryEnabled
Enable
auto memory
. When
false
, Claude does not read from or write to the auto memory directory. Default:
true
. You can also toggle this with
/memory
during a session. To disable via environment variable, set
CLAUDE_CODE_DISABLE_AUTO_MEMORY
in
env
false
autoMode
Customize what the
auto mode
classifier blocks and allows. Contains
environment
,
allow
,
soft_deny
, and
hard_deny
arrays of prose rules. Include the literal string
"$defaults"
in an array to inherit the built-in rules at that position. See
Configure auto mode
. Not read from shared project settings
{"soft_deny": ["$defaults", "Never run terraform apply"]}
autoScrollEnabled
In
fullscreen rendering
, follow new output to the bottom of the conversation. Default:
true
. Appears in
/config
as
Auto-scroll
. Permission prompts still scroll into view when this is off
false
autoUpdatesChannel
Release channel to follow for updates. Use
"stable"
for a version that is typically about one week old and skips versions with major regressions, or
"latest"
(default) for the most recent release. To disable auto-updates entirely, set
DISABLE_AUTOUPDATER
in
env
"stable"
availableModels
Restrict which models users can select via
/model
,
--model
, or
ANTHROPIC_MODEL
. Does not affect the Default option. See
Restrict model selection
["sonnet", "haiku"]
awaySummaryEnabled
Show a one-line session recap when you return to the terminal after a few minutes away. Set to
false
or turn off Session recap in
/config
to disable. Same as
CLAUDE_CODE_ENABLE_AWAY_SUMMARY
true
awsAuthRefresh
Custom script that modifies the
.aws
directory (see
advanced credential configuration
)
aws sso login --profile myprofile
awsCredentialExport
Custom script that outputs JSON with AWS credentials (see
advanced credential configuration
)
/bin/generate_aws_grant.sh
blockedMarketplaces
(Managed settings only) Blocklist of marketplace sources. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. Blocked sources are checked before downloading, so they never touch the filesystem. See
Managed marketplace restrictions
[{ "source": "github", "repo": "untrusted/plugins" }]
channelsEnabled
(Managed settings only) Allow
channels
for the organization. On claude.ai Team and Enterprise plans, channels are blocked when this is unset or
false
. For
Anthropic Console
accounts using API key authentication, channels are allowed by default unless your organization deploys managed settings, in which case this key must be set to
true
true
claudeMd
(Managed settings only) CLAUDE.md-style instructions injected as organization-managed memory. Only honored when set in managed or policy settings and ignored in user, project, and local settings. See
organization-wide CLAUDE.md
"Always run make lint before committing."
claudeMdExcludes
Glob patterns or absolute paths of
CLAUDE.md
files to skip when loading
memory
. Patterns match against absolute file paths. Only applies to user, project, and local memory; managed policy files cannot be excluded
["**/vendor/**/CLAUDE.md"]
cleanupPeriodDays
Session files older than this period are deleted at startup (default: 30 days, minimum 1). Setting to
0
is rejected with a validation error. Also controls the age cutoff for automatic removal of
orphaned subagent worktrees
at startup. To disable transcript writes entirely, set the
CLAUDE_CODE_SKIP_PROMPT_HISTORY
environment variable, or in non-interactive mode (
-p
) use the
--no-session-persistence
flag or the
persistSession: false
SDK option.
20
companyAnnouncements
Announcement to display to users at startup. If multiple announcements are provided, they will be cycled through at random.
["Welcome to Acme Corp! Review our code guidelines at docs.acme.com"]
defaultShell
Default shell for input-box
!
commands. Accepts
"bash"
(default) or
"powershell"
. Setting
"powershell"
routes interactive
!
commands through PowerShell on Windows. Requires
CLAUDE_CODE_USE_POWERSHELL_TOOL=1
. See
PowerShell tool
"powershell"
deniedMcpServers
When set in managed-settings.json, denylist of MCP servers that are explicitly blocked. Applies to all scopes including managed servers. Denylist takes precedence over allowlist. See
Managed MCP configuration
[{ "serverName": "filesystem" }]
disableAgentView
Set to
true
to turn off
background agents and agent view
:
claude agents
,
--bg
,
/background
, and the on-demand supervisor. Typically set in
managed settings
. Equivalent to setting
CLAUDE_CODE_DISABLE_AGENT_VIEW
to
1
true
disableAllHooks
Disable all
hooks
and any custom
status line
true
disableAutoMode
Set to
"disable"
to prevent
auto mode
from being activated. Removes
auto
from the
Shift+Tab
cycle and rejects
--permission-mode auto
at startup. Most useful in
managed settings
where users cannot override it
"disable"
disableDeepLinkRegistration
Set to
"disable"
to prevent Claude Code from registering the
claude-cli://
protocol handler with the operating system on startup.
Deep links
let external tools open a Claude Code session with a pre-filled prompt. Useful in environments where protocol handler registration is restricted or managed separately
"disable"
disabledMcpjsonServers
List of specific MCP servers from
.mcp.json
files to reject
["filesystem"]
disableRemoteControl
Disable
Remote Control
: blocks
claude remote-control
, the
--remote-control
flag, auto-start, and the in-session toggle. Typically placed in
managed settings
for per-device MDM enforcement, but works from any scope. Requires Claude Code v2.1.128 or later
true
disableSkillShellExecution
Disable inline shell execution for
!`...`
and
```!
blocks in
skills
and custom commands from user, project, plugin, or additional-directory sources. Commands are replaced with
[shell command execution disabled by policy]
instead of being run. Bundled and managed skills are not affected. Most useful in
managed settings
where users cannot override it
true
editorMode
Key binding mode for the input prompt:
"normal"
or
"vim"
. Default:
"normal"
. Appears in
/config
as
Editor mode
"vim"
effortLevel
Persist the
effort level
across sessions. Accepts
"low"
,
"medium"
,
"high"
, or
"xhigh"
. Written automatically when you run
/effort
with one of those values.
--effort
and
CLAUDE_CODE_EFFORT_LEVEL
override this for one session. See
Adjust effort level
for supported models
"xhigh"
enableAllProjectMcpServers
Automatically approve all MCP servers defined in project
.mcp.json
files
true
enabledMcpjsonServers
List of specific MCP servers from
.mcp.json
files to approve
["memory", "github"]
env
Environment variables that will be applied to every session
{"FOO": "bar"}
fastModePerSessionOptIn
When
true
, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with
/fast
. The user’s fast mode preference is still saved. See
Require per-session opt-in
true
feedbackSurveyRate
Probability (0–1) that the
session quality survey
appears when eligible. Set to
0
to suppress entirely, or set
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
in
env
. Useful when using Bedrock, Vertex, or Foundry where the default sample rate does not apply
0.05
fileSuggestion
Configure a custom script for
@
file autocomplete. See
File suggestion settings
{"type": "command", "command": "~/.claude/file-suggestion.sh"}
forceLoginMethod
Use
claudeai
to restrict login to Claude.ai accounts,
console
to restrict login to Claude Console (API usage billing) accounts
claudeai
forceLoginOrgUUID
Require login to belong to a specific organization. Accepts a single UUID string, which also pre-selects that organization during login, or an array of UUIDs where any listed organization is accepted without pre-selection. When set in managed settings, login fails if the authenticated account does not belong to a listed organization; an empty array fails closed and blocks login with a misconfiguration message
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
or
["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]
forceRemoteSettingsRefresh
(Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits rather than continuing with cached or no settings. When not set, startup continues without waiting for remote settings. See
fail-closed enforcement
true
gcpAuthRefresh
Custom script that refreshes GCP Application Default Credentials when they expire or cannot be loaded. See
advanced credential configuration
gcloud auth application-default login
hooks
Configure custom commands to run at lifecycle events. See
hooks documentation
for format
See
hooks
httpHookAllowedEnvVars
Allowlist of environment variable names HTTP hooks may interpolate into headers. When set, each hook’s effective
allowedEnvVars
is the intersection with this list. Undefined = no restriction. Arrays merge across settings sources. See
Hook configuration
["MY_TOKEN", "HOOK_SECRET"]
includeCoAuthoredBy
Deprecated
: Use
attribution
instead. Whether to include the
co-authored-by Claude
byline in git commits and pull requests (default:
true
)
false
includeGitInstructions
Include built-in commit and PR workflow instructions and the git status snapshot in Claude’s system prompt (default:
true
). Set to
false
to remove both, for example when using your own git workflow skills. The
CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS
environment variable takes precedence over this setting when set
false
language
Configure Claude’s preferred response language (e.g.,
"japanese"
,
"spanish"
,
"french"
). Claude will respond in this language by default. Also sets the
voice dictation
language
"japanese"
maxSkillDescriptionChars
Per-skill character cap on the combined
description
and
when_to_use
text in the
skill listing
Claude sees each turn (default:
1536
). Text longer than this is truncated. Raise to keep long descriptions intact at the cost of more context per turn; lower to fit more skills under
skillListingBudgetFraction
. Requires Claude Code v2.1.105 or later
2048
minimumVersion
Floor that prevents background auto-updates and
claude update
from installing a version below this one. Switching from the
"latest"
channel to
"stable"
via
/config
prompts you to stay on the current version or allow the downgrade. Choosing to stay sets this value. Also useful in
managed settings
to pin an organization-wide minimum
"2.1.100"
model
Override the default model to use for Claude Code.
--model
and
ANTHROPIC_MODEL
override this for one session
"claude-sonnet-4-6"
modelOverrides
Map Anthropic model IDs to provider-specific model IDs such as Bedrock inference profile ARNs. Each model picker entry uses its mapped value when calling the provider API. See
Override model IDs per version
{"claude-opus-4-6": "arn:aws:bedrock:..."}
otelHeadersHelper
Script to generate dynamic OpenTelemetry headers. Runs at startup and periodically. Set the refresh interval with
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
. See
Dynamic headers
/bin/generate_otel_headers.sh
outputStyle
Configure an output style to adjust the system prompt. See
output styles documentation
"Explanatory"
parentSettingsBehavior
(Managed settings only) Controls whether managed settings supplied programmatically by an embedding host process, such as the Agent SDK or an IDE extension, apply when an admin-deployed managed tier is also present.
"first-wins"
: the parent-supplied settings are dropped and only the admin tier applies.
"merge"
: the parent-supplied settings apply under the admin tier, filtered so they can tighten policy but not loosen it. Has no effect when no admin tier is deployed. Default:
"first-wins"
. Requires Claude Code v2.1.133 or later
"merge"
permissions
See table below for structure of permissions.
plansDirectory
Customize where plan files are stored. Path is relative to project root. Default:
~/.claude/plans
"./plans"
pluginTrustMessage
(Managed settings only) Custom message appended to the plugin trust warning shown before installation. Use this to add organization-specific context, for example to confirm that plugins from your internal marketplace are vetted.
"All plugins from our marketplace are approved by IT"
policyHelper
Admin-deployed executable that computes managed settings dynamically at startup. Only honored from MDM or a system
managed-settings.json
file. See
Compute managed settings with a policy helper
. Requires Claude Code v2.1.136 or later
{"path": "/usr/local/bin/claude-policy"}
preferredNotifChannel
Method for task-complete and permission-prompt notifications:
"auto"
,
"terminal_bell"
,
"iterm2"
,
"iterm2_with_bell"
,
"kitty"
,
"ghostty"
, or
"notifications_disabled"
. Default:
"auto"
, which sends a desktop notification in iTerm2, Ghostty, and Kitty and does nothing in other terminals. Set
"terminal_bell"
to ring the bell character in any terminal. Appears in
/config
as
Notifications
. See
Get a terminal bell or notification
"terminal_bell"
prefersReducedMotion
Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility
true
prUrlTemplate
URL template for the PR badge shown in the footer and in tool-result summaries. Substitutes
{host}
,
{owner}
,
{repo}
,
{number}
, and
{url}
from the
gh
-reported PR URL. Use to point PR links at an internal code-review tool instead of
github.com
. Does not affect
#123
autolinks in Claude’s prose
"https://reviews.example.com/{owner}/{repo}/pull/{number}"
respectGitignore
Control whether the
@
file picker respects
.gitignore
patterns. When
true
(default), files matching
.gitignore
patterns are excluded from suggestions
false
showClearContextOnPlanAccept
Show the “clear context” option on the plan accept screen. Defaults to
false
. Set to
true
to restore the option
true
showThinkingSummaries
Show
extended thinking
summaries in interactive sessions. When unset or
false
(default in interactive mode), thinking blocks are redacted by the API and shown as a collapsed stub. Redaction only changes what you see, not what the model generates: to reduce thinking spend,
lower the budget or disable thinking
instead. Non-interactive mode (
-p
) and SDK callers always receive summaries regardless of this setting
true
showTurnDuration
Show turn duration messages after responses, e.g. “Cooked for 1m 6s”. Default:
true
. Appears in
/config
as
Show turn duration
false
skillListingBudgetFraction
Fraction of the model’s context window reserved for the
skill listing
Claude sees each turn (default:
0.01
= 1%). When the listing exceeds the budget, descriptions for the least-used skills are collapsed to bare names so Claude can still invoke them but won’t see why. Raise to keep more descriptions visible at the cost of more context per turn.
/doctor
shows the current truncation count and which skills are affected. Requires Claude Code v2.1.105 or later
0.02
skillOverrides
Per-skill visibility overrides keyed by skill name. Value is
"on"
,
"name-only"
,
"user-invocable-only"
, or
"off"
. Lets you hide or collapse a skill without editing its SKILL.md. Does not apply to plugin skills, which are managed through
/plugin
. The
/skills
menu writes these to
.claude/settings.local.json
. See
Override skill visibility from settings
. Requires Claude Code v2.1.129 or later
{"legacy-context": "name-only", "deploy": "off"}
skipWebFetchPreflight
Skip the
WebFetch domain safety check
that sends each requested hostname to
api.anthropic.com
before fetching. Set to
true
in environments that block traffic to Anthropic, such as Bedrock, Vertex AI, or Foundry deployments with restrictive egress. When skipped, WebFetch attempts any URL without consulting the blocklist
true
spinnerTipsEnabled
Show tips in the spinner while Claude is working. Set to
false
to disable tips (default:
true
)
false
spinnerTipsOverride
Override spinner tips with custom strings.
tips
: array of tip strings.
excludeDefault
: if
true
, only show custom tips; if
false
or absent, custom tips are merged with built-in tips
{ "excludeDefault": true, "tips": ["Use our internal tool X"] }
spinnerVerbs
Customize the action verbs shown in the spinner and turn duration messages. Set
mode
to
"replace"
to use only your verbs, or
"append"
to add them to the defaults
{"mode": "append", "verbs": ["Pondering", "Crafting"]}
sshConfigs
SSH connections to show in the
Desktop
environment dropdown. Each entry requires
id
,
name
, and
sshHost
;
sshPort
,
sshIdentityFile
, and
startDirectory
are optional. When set in managed settings, connections are read-only for users. Read from managed and user settings only
[{"id": "dev-vm", "name": "Dev VM", "sshHost": "user@dev.example.com"}]
statusLine
Configure a custom status line to display context. See
statusLine
documentation
{"type": "command", "command": "~/.claude/statusline.sh"}
strictKnownMarketplaces
(Managed settings only) Allowlist of plugin marketplace sources. Undefined = no restrictions, empty array = lockdown. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. See
Managed marketplace restrictions
[{ "source": "github", "repo": "acme-corp/plugins" }]
syntaxHighlightingDisabled
Disable syntax highlighting in diffs, code blocks, and file previews
true
teammateMode
How
agent team
teammates display:
auto
(picks split panes in tmux or iTerm2, in-process otherwise),
in-process
, or
tmux
.
--teammate-mode
overrides this for one session. See
choose a display mode
"in-process"
terminalProgressBarEnabled
Show the terminal progress bar in supported terminals: ConEmu, Ghostty 1.2.0+, and iTerm2 3.6.6+. Default:
true
. Appears in
/config
as
Terminal progress bar
false
tui
Terminal UI renderer. Use
"fullscreen"
for the flicker-free
alt-screen renderer
with virtualized scrollback. Use
"default"
for the classic main-screen renderer. Set via
/tui
. You can also set the
CLAUDE_CODE_NO_FLICKER
environment variable
"fullscreen"
useAutoModeDuringPlan
Whether plan mode uses auto mode semantics when auto mode is available. Default:
true
. Not read from shared project settings. Appears in
/config
as “Use auto mode during plan”
false
viewMode
Default transcript view mode on startup:
"default"
,
"verbose"
, or
"focus"
. Overrides the sticky
/focus
selection when set. The
--verbose
flag overrides this for one session
"verbose"
voice
Voice dictation
settings:
enabled
turns dictation on,
mode
selects
"hold"
or
"tap"
, and
autoSubmit
sends the prompt on key release in hold mode. Written automatically when you run
/voice
. Requires a Claude.ai account
{ "enabled": true, "mode": "tap" }
voiceEnabled
Legacy alias for
voice.enabled
. Prefer the
voice
object
true
wslInheritsWindowsSettings
(Windows managed settings only) When
true
, Claude Code on WSL reads managed settings from the Windows policy chain in addition to
/etc/claude-code
, with Windows sources taking priority. Only honored when set in the HKLM registry key or
C:\Program Files\ClaudeCode\managed-settings.json
, both of which require Windows admin to write. For HKCU policy to also apply on WSL, the flag must additionally be set in HKCU itself. Has no effect on native Windows
true
​
Global config settings
These settings are stored in
~/.claude.json
rather than
settings.json
. Adding them to
settings.json
will trigger a schema validation error.
Versions before v2.1.119 also store
autoScrollEnabled
,
editorMode
,
showTurnDuration
,
teammateMode
, and
terminalProgressBarEnabled
here instead of in
settings.json
.
Key
Description
Example
autoConnectIde
Automatically connect to a running IDE when Claude Code starts from an external terminal. Default:
false
. Appears in
/config
as
Auto-connect to IDE (external terminal)
when running outside a VS Code or JetBrains terminal. The
CLAUDE_CODE_AUTO_CONNECT_IDE
environment variable overrides this when set
true
autoInstallIdeExtension
Automatically install the Claude Code IDE extension when running from a VS Code terminal. Default:
true
. Appears in
/config
as
Auto-install IDE extension
when running inside a VS Code or JetBrains terminal. You can also set the
CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL
environment variable
false
externalEditorContext
Prepend Claude’s previous response as
#
-commented context when you open the external editor with
Ctrl+G
. Default:
false
. Appears in
/config
as
Show last response in external editor
true
teammateDefaultModel
Default model for
agent team
teammates when the spawn prompt doesn’t specify one. Set to a model alias such as
"sonnet"
, or
null
to inherit the lead’s current
/model
selection. Appears in
/config
as
Default teammate model
"sonnet"
​
Worktree settings
Configure how
--worktree
creates and manages git worktrees.
Key
Description
Example
worktree.baseRef
Which ref new worktrees branch from.
"fresh"
(default) branches from
origin/<default-branch>
for a clean tree matching the remote.
"head"
branches from your current local
HEAD
, so unpushed commits and feature-branch state are present in the worktree. Applies to
--worktree
, the
EnterWorktree
tool, and subagent isolation
"head"
worktree.symlinkDirectories
Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. No directories are symlinked by default
["node_modules", ".cache"]
worktree.sparsePaths
Directories to check out in each worktree via git sparse-checkout. Only the listed directories plus root-level files are written to disk, which is faster in large monorepos
["packages/my-app", "shared/utils"]
To copy gitignored files like
.env
into new worktrees, use a
.worktreeinclude
file
in your project root instead of a setting.
​
Permission settings
Keys
Description
Example
allow
Array of permission rules to allow tool use. See
Permission rule syntax
below for pattern matching details
[ "Bash(git diff *)" ]
ask
Array of permission rules to ask for confirmation upon tool use. See
Permission rule syntax
below
[ "Bash(git push *)" ]
deny
Array of permission rules to deny tool use. Use this to exclude sensitive files from Claude Code access. See
Permission rule syntax
and
Bash permission limitations
[ "WebFetch", "Bash(curl *)", "Read(./.env)", "Read(./secrets/**)" ]
additionalDirectories
Additional
working directories
for file access. Most
.claude/
configuration is
not discovered
from these directories
[ "../docs/" ]
defaultMode
Default
permission mode
when opening Claude Code. Valid values:
default
,
acceptEdits
,
plan
,
auto
,
dontAsk
,
bypassPermissions
. The
--permission-mode
CLI flag overrides this setting for a single session
"acceptEdits"
disableBypassPermissionsMode
Set to
"disable"
to prevent
bypassPermissions
mode from being activated. This disables the
--dangerously-skip-permissions
command-line flag. Typically placed in
managed settings
to enforce organizational policy, but works from any scope
"disable"
skipDangerousModePermissionPrompt
Skip the confirmation prompt shown before entering bypass permissions mode via
--dangerously-skip-permissions
or
defaultMode: "bypassPermissions"
. Ignored when set in project settings (
.claude/settings.json
) to prevent untrusted repositories from auto-bypassing the prompt
true
​
Permission rule syntax
Permission rules follow the format
Tool
or
Tool(specifier)
. Rules are evaluated in order: deny rules first, then ask, then allow. The first matching rule wins.
Quick examples:
Rule
Effect
Bash
Matches all Bash commands
Bash(npm run *)
Matches commands starting with
npm run
Read(./.env)
Matches reading the
.env
file
WebFetch(domain:example.com)
Matches fetch requests to example.com
For the complete rule syntax reference, including wildcard behavior, tool-specific patterns for Read, Edit, WebFetch, MCP, and Agent rules, and security limitations of Bash patterns, see
Permission rule syntax
.
​
Sandbox settings
Configure advanced sandboxing behavior. Sandboxing isolates bash commands from your filesystem and network. See
Sandboxing
for details.
Keys
Description
Example
enabled
Enable bash sandboxing (macOS, Linux, and WSL2). Default: false
true
failIfUnavailable
Exit with an error at startup if
sandbox.enabled
is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed settings deployments that require sandboxing as a hard gate
true
autoAllowBashIfSandboxed
Auto-approve bash commands when sandboxed. Default: true
true
excludedCommands
Commands that should run outside of the sandbox
["docker *"]
allowUnsandboxedCommands
Allow commands to run outside the sandbox via the
dangerouslyDisableSandbox
parameter. When set to
false
, the
dangerouslyDisableSandbox
escape hatch is completely disabled and all commands must run sandboxed (or be in
excludedCommands
). Useful for enterprise policies that require strict sandboxing. Default: true
false
filesystem.allowWrite
Additional paths where sandboxed commands can write. Arrays are merged across all settings scopes: user, project, and managed paths are combined, not replaced. Also merged with paths from
Edit(...)
allow permission rules. See
path prefixes
below.
["/tmp/build", "~/.kube"]
filesystem.denyWrite
Paths where sandboxed commands cannot write. Arrays are merged across all settings scopes. Also merged with paths from
Edit(...)
deny permission rules.
["/etc", "/usr/local/bin"]
filesystem.denyRead
Paths where sandboxed commands cannot read. Arrays are merged across all settings scopes. Also merged with paths from
Read(...)
deny permission rules.
["~/.aws/credentials"]
filesystem.allowRead
Paths to re-allow reading within
denyRead
regions. Takes precedence over
denyRead
. Arrays are merged across all settings scopes. Use this to create workspace-only read access patterns.
["."]
filesystem.allowManagedReadPathsOnly
(Managed settings only) Only
filesystem.allowRead
paths from managed settings are respected.
denyRead
still merges from all sources. Default: false
true
network.allowUnixSockets
(macOS only) Unix socket paths accessible in sandbox. Ignored on Linux and WSL2, where the seccomp filter cannot inspect socket paths; use
allowAllUnixSockets
instead.
["~/.ssh/agent-socket"]
network.allowAllUnixSockets
Allow all Unix socket connections in sandbox. On Linux and WSL2 this is the only way to permit Unix sockets, since it skips the seccomp filter that otherwise blocks
socket(AF_UNIX, ...)
calls. Default: false
true
network.allowLocalBinding
Allow binding to localhost ports (macOS only). Default: false
true
network.allowMachLookup
Additional XPC/Mach service names the sandbox may look up (macOS only). Supports a single trailing
*
for prefix matching. Needed for tools that communicate via XPC such as the iOS Simulator or Playwright.
["com.apple.coresimulator.*"]
network.allowedDomains
Array of domains to allow for outbound network traffic. Supports wildcards (e.g.,
*.example.com
).
["github.com", "*.npmjs.org"]
network.deniedDomains
Array of domains to block for outbound network traffic. Supports the same wildcard syntax as
allowedDomains
. Takes precedence over
allowedDomains
when both match. Merged from all settings sources regardless of
allowManagedDomainsOnly
.
["sensitive.cloud.example.com"]
network.allowManagedDomainsOnly
(Managed settings only) Only
allowedDomains
and
WebFetch(domain:...)
allow rules from managed settings are respected. Domains from user, project, and local settings are ignored. Non-allowed domains are blocked automatically without prompting the user. Denied domains are still respected from all sources. Default: false
true
network.httpProxyPort
HTTP proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy.
8080
network.socksProxyPort
SOCKS5 proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy.
8081
enableWeakerNestedSandbox
Enable weaker sandbox for unprivileged Docker environments (Linux and WSL2 only).
Reduces security.
Default: false
true
enableWeakerNetworkIsolation
(macOS only) Allow access to the system TLS trust service (
com.apple.trustd.agent
) in the sandbox. Required for Go-based tools like
gh
,
gcloud
, and
terraform
to verify TLS certificates when using
httpProxyPort
with a MITM proxy and custom CA.
Reduces security
by opening a potential data exfiltration path. Default: false
true
bwrapPath
(Managed settings only, Linux/WSL2) Absolute path to the bubblewrap (
bwrap
) binary. Overrides automatic detection via
PATH
. Only honored from
managed settings
, not from user or project settings. Useful when
bwrap
is installed at a non-standard location in managed environments.
/opt/admin/bwrap
socatPath
(Managed settings only, Linux/WSL2) Absolute path to the
socat
binary used for the sandbox network proxy. Overrides automatic detection via
PATH
. Only honored from managed settings.
/opt/admin/socat
​
Sandbox path prefixes
Paths in
filesystem.allowWrite
,
filesystem.denyWrite
,
filesystem.denyRead
, and
filesystem.allowRead
support these prefixes:
Prefix
Meaning
Example
/
Absolute path from filesystem root
/tmp/build
stays
/tmp/build
~/
Relative to home directory
~/.kube
becomes
$HOME/.kube
./
or no prefix
Relative to the project root for project settings, or to
~/.claude
for user settings
./output
in
.claude/settings.json
resolves to
<project-root>/output
The older
//path
prefix for absolute paths still works. If you previously used single-slash
/path
expecting project-relative resolution, switch to
./path
. This syntax differs from
Read and Edit permission rules
, which use
//path
for absolute and
/path
for project-relative. Sandbox filesystem paths use standard conventions:
/tmp/build
is an absolute path.
Configuration example:
{
"sandbox"
: {
"enabled"
:
true
,
"autoAllowBashIfSandboxed"
:
true
,
"excludedCommands"
: [
"docker *"
],
"filesystem"
: {
"allowWrite"
: [
"/tmp/build"
,
"~/.kube"
],
"denyRead"
: [
"~/.aws/credentials"
]
},
"network"
: {
"allowedDomains"
: [
"github.com"
,
"*.npmjs.org"
,
"registry.yarnpkg.com"
],
"deniedDomains"
: [
"uploads.github.com"
],
"allowUnixSockets"
: [
"/var/run/docker.sock"
],
"allowLocalBinding"
:
true
}
}
}
Filesystem and network restrictions
can be configured in two ways that are merged together:
sandbox.filesystem
settings
(shown above): Control paths at the OS-level sandbox boundary. These restrictions apply to all subprocess commands (e.g.,
kubectl
,
terraform
,
npm
), not just Claude’s file tools.
Permission rules
: Use
Edit
allow/deny rules to control Claude’s file tool access,
Read
deny rules to block reads, and
WebFetch
allow/deny rules to control network domains. Paths from these rules are also merged into the sandbox configuration.
​
Attribution settings
Claude Code adds attribution to git commits and pull requests. These are configured separately:
Commits use
git trailers
(like
Co-Authored-By
) by default,  which can be customized or disabled
Pull request descriptions are plain text
Keys
Description
commit
Attribution for git commits, including any trailers. Empty string hides commit attribution
pr
Attribution for pull request descriptions. Empty string hides pull request attribution
Default commit attribution:
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default pull request attribution:
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Example:
{
"attribution"
: {
"commit"
:
"Generated with AI
\n\n
Co-Authored-By: AI <ai@example.com>"
,
"pr"
:
""
}
}
The
attribution
setting takes precedence over the deprecated
includeCoAuthoredBy
setting. To hide all attribution, set
commit
and
pr
to empty strings.
​
File suggestion settings
Configure a custom command for
@
file path autocomplete. The built-in file suggestion uses fast filesystem traversal, but large monorepos may benefit from project-specific indexing such as a pre-built file index or custom tooling.
{
"fileSuggestion"
: {
"type"
:
"command"
,
"command"
:
"~/.claude/file-suggestion.sh"
}
}
The command runs with the same environment variables as
hooks
, including
CLAUDE_PROJECT_DIR
. It receives JSON via stdin with a
query
field:
{
"query"
:
"src/comp"
}
Output newline-separated file paths to stdout (currently limited to 15):
src/components/Button.tsx
src/components/Modal.tsx
src/components/Form.tsx
Example:
#!/bin/bash
query
=
$(
cat
|
jq
-r
'.query'
)
your-repo-file-index
--query
"
$query
"
|
head
-20
​
Hook configuration
These settings control which hooks are allowed to run and what HTTP hooks can access. The
allowManagedHooksOnly
setting can only be configured in
managed settings
. The URL and env var allowlists can be set at any settings level and merge across sources.
Behavior when
allowManagedHooksOnly
is
true
:
Managed hooks and SDK hooks are loaded
Hooks from plugins force-enabled in managed settings
enabledPlugins
are loaded. This lets administrators distribute vetted hooks through an organization marketplace while blocking everything else. Trust is granted by full
plugin@marketplace
ID, so a plugin with the same name from a different marketplace stays blocked
User hooks, project hooks, and all other plugin hooks are blocked
Restrict HTTP hook URLs:
Limit which URLs HTTP hooks can target. Supports
*
as a wildcard for matching. When the array is defined, HTTP hooks targeting non-matching URLs are silently blocked. Hostname matching is case-insensitive and ignores a trailing FQDN dot, matching DNS semantics.
{
"allowedHttpHookUrls"
: [
"https://hooks.example.com/*"
,
"http://localhost:*"
]
}
Restrict HTTP hook environment variables:
Limit which environment variable names HTTP hooks can interpolate into header values. Each hook’s effective
allowedEnvVars
is the intersection of its own list and this setting.
{
"httpHookAllowedEnvVars"
: [
"MY_TOKEN"
,
"HOOK_SECRET"
]
}
​
Compute managed settings with a policy helper
The
policyHelper
setting points at an executable that computes managed settings at startup, so admins can derive policy from device posture, identity, or a remote service instead of a static file. Configure it from MDM or a system
managed-settings.json
file. Claude Code ignores
policyHelper
when it appears in any other scope, including user settings, project settings, the HKCU registry hive, and
server-managed settings
.
The setting accepts these keys:
Key
Type
Description
path
string
Absolute path to the helper executable
timeoutMs
number
How long to wait for the helper before treating the run as failed
refreshIntervalMs
number
How often to re-run the helper in the background. Set to
0
to disable refresh, or to at least
60000
The helper writes a JSON envelope to stdout. Put the settings under a
managedSettings
key rather than at the top level, since a bare settings object parses with
managedSettings
undefined and applies nothing:
{
"managedSettings"
: {
"permissions"
: {
"deny"
: [
"Read(//etc/secrets/**)"
] }
},
"claudeMd"
:
"# Organization context
\n
..."
,
"appendSystemPrompt"
:
"Always cite the internal style guide."
}
When the helper emits
managedSettings
, that object replaces the file-based managed settings for the run. When the helper exits non-zero at startup, Claude Code prints the error and refuses to start, so a helper that needs outage resilience should serve from its own cache and exit
0
.
​
Settings precedence
Settings apply in order of precedence. From highest to lowest:
Managed settings
(
server-managed
,
MDM/OS-level policies
, or
managed settings
)
Policies deployed by IT through server delivery, MDM configuration profiles, registry policies, or managed settings files
Cannot be overridden by any other level, including command line arguments
Within the managed tier, precedence is: server-managed > MDM/OS-level policies > file-based (
managed-settings.d/*.json
+
managed-settings.json
) > HKCU registry (Windows only). Only one managed source is used; sources do not merge across tiers. Within the file-based tier, drop-in files and the base file are merged together.
Embedding hosts such as Claude Desktop can supply policy via the SDK
managedSettings
option. By default this is ignored when any managed-settings tier is present. Administrators can opt in by setting
parentSettingsBehavior
to
"merge"
. The embedder’s values are filtered so they can tighten managed policy but not loosen it.
Command line arguments
Temporary overrides for a specific session. JSON passed via
--settings <file-or-json>
merges with file-based settings using the same rules as the other layers: a key set here overrides the same key in local, project, or user settings, and omitting a key leaves the lower-layer value in place
Local project settings
(
.claude/settings.local.json
)
Personal project-specific settings
Shared project settings
(
.claude/settings.json
)
Team-shared project settings in source control
User settings
(
~/.claude/settings.json
)
Personal global settings
This hierarchy ensures that organizational policies are always enforced while still allowing teams and individuals to customize their experience. The same precedence applies whether you run Claude Code from the CLI, the
VS Code extension
, or a
JetBrains IDE
.
For example, if your user settings set
permissions.defaultMode
to
acceptEdits
and a project’s shared settings set it to
default
, the project value applies. The example below covers how array-valued settings such as permission rules combine instead.
Array settings merge across scopes.
When the same array-valued setting (such as
sandbox.filesystem.allowWrite
or
permissions.allow
) appears in multiple scopes, the arrays are
concatenated and deduplicated
, not replaced. This means lower-priority scopes can add entries without overriding those set by higher-priority scopes, and vice versa. For example, if managed settings set
allowWrite
to
["/opt/company-tools"]
and a user adds
["~/.kube"]
, both paths are included in the final configuration.
​
Verify active settings
Run
/status
inside Claude Code to see which settings sources are active. The Status tab includes a
Setting sources
line that lists each layer Claude Code loaded for the current session, such as
User settings
or
Project local settings
. When
managed settings
are in effect, the entry shows the delivery channel in parentheses, for example
Enterprise managed settings (remote)
,
(plist)
,
(HKLM)
,
(HKCU)
, or
(file)
. A layer appears in the list only when that source is loaded with at least one key, so an empty list means no settings sources were found.
The
Setting sources
line confirms which sources are being read. It does not show which layer supplied each individual key. The Config tab in the same dialog is an editor for a fixed set of toggles such as theme and verbose output, not a view of your
settings.json
contents. If a settings file contains errors, such as invalid JSON or a value that fails validation,
/status
reports the issue so you can fix it.
​
Key points about the configuration system
Memory files (
CLAUDE.md
)
: Contain instructions and context that Claude loads at startup
Settings files (JSON)
: Configure permissions, environment variables, and tool behavior
Skills
: Custom prompts that can be invoked with
/skill-name
or loaded by Claude automatically
MCP servers
: Extend Claude Code with additional tools and integrations
Precedence
: Higher-level configurations (Managed) override lower-level ones (User/Project)
Inheritance
: Settings merge across scopes; scalar values from higher-priority scopes override, and arrays concatenate
​
System prompt
Claude Code’s internal system prompt is not published. To add custom instructions, use
CLAUDE.md
files or the
--append-system-prompt
flag.
​
Excluding sensitive files
To prevent Claude Code from accessing files containing sensitive information like API keys, secrets, and environment files, use the
permissions.deny
setting in your
.claude/settings.json
file:
{
"permissions"
: {
"deny"
: [
"Read(./.env)"
,
"Read(./.env.*)"
,
"Read(./secrets/**)"
,
"Read(./config/credentials.json)"
,
"Read(./build)"
]
}
}
This replaces the deprecated
ignorePatterns
configuration. Files matching these patterns are excluded from file discovery and search results, and read operations on these files are denied.
​
Subagent configuration
Claude Code supports custom AI subagents that can be configured at both user and project levels. These subagents are stored as Markdown files with YAML frontmatter:
User subagents
:
~/.claude/agents/
- Available across all your projects
Project subagents
:
.claude/agents/
- Specific to your project and can be shared with your team
Subagent files define specialized AI assistants with custom prompts and tool permissions. Learn more about creating and using subagents in the
subagents documentation
.
​
Plugin configuration
Claude Code supports a plugin system that lets you extend functionality with skills, agents, hooks, and MCP servers. Plugins are distributed through marketplaces and can be configured at both user and repository levels.
​
Plugin settings
Plugin-related settings in
settings.json
:
{
"enabledPlugins"
: {
"formatter@acme-tools"
:
true
,
"deployer@acme-tools"
:
true
,
"analyzer@security-plugins"
:
false
},
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/claude-plugins"
}
}
}
}
​
enabledPlugins
Controls which plugins are enabled. Format:
"plugin-name@marketplace-name": true/false
Scopes
:
User settings
(
~/.claude/settings.json
): Personal plugin preferences
Project settings
(
.claude/settings.json
): Project-specific plugins shared with team
Local settings
(
.claude/settings.local.json
): Per-machine overrides (not committed)
Managed settings
(
managed-settings.json
): Organization-wide policy overrides that block installation at all scopes and hide the plugin from the marketplace
Project settings take precedence over user settings, so setting a plugin to
false
in
~/.claude/settings.json
does not disable a plugin that the project’s
.claude/settings.json
enables. To opt out of a project-enabled plugin on your machine, set it to
false
in
.claude/settings.local.json
instead.
Plugins force-enabled by managed settings cannot be disabled this way, since managed settings override local settings.
Example
:
{
"enabledPlugins"
: {
"code-formatter@team-tools"
:
true
,
"deployment-tools@team-tools"
:
true
,
"experimental-features@personal"
:
false
}
}
​
extraKnownMarketplaces
Defines additional marketplaces that should be made available for the repository. Typically used in repository-level settings to ensure team members have access to required plugin sources.
When a repository includes
extraKnownMarketplaces
:
Team members are prompted to install the marketplace when they trust the folder
Team members are then prompted to install plugins from that marketplace
Users can skip unwanted marketplaces or plugins (stored in user settings)
Installation respects trust boundaries and requires explicit consent
Example
:
{
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/claude-plugins"
}
},
"security-plugins"
: {
"source"
: {
"source"
:
"git"
,
"url"
:
"https://git.example.com/security/plugins.git"
}
}
}
}
Marketplace source types
:
github
: GitHub repository (uses
repo
)
git
: Any git URL (uses
url
)
directory
: Local filesystem path (uses
path
, for development only)
hostPattern
: regex pattern to match marketplace hosts (uses
hostPattern
)
settings
: inline marketplace declared directly in settings.json without a separate hosted repository (uses
name
and
plugins
)
Each marketplace entry also accepts an optional
autoUpdate
Boolean. Set
"autoUpdate": true
alongside
source
to make Claude Code refresh that marketplace and update its installed plugins at startup. When omitted, official Anthropic marketplaces default to
true
and all other marketplaces default to
false
. See
Configure auto-updates
.
Use
source: 'settings'
to declare a small set of plugins inline without setting up a hosted marketplace repository. Plugins listed here must reference external sources such as GitHub or npm. You still need to enable each plugin separately in
enabledPlugins
.
{
"extraKnownMarketplaces"
: {
"team-tools"
: {
"source"
: {
"source"
:
"settings"
,
"name"
:
"team-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
}
}
]
}
}
}
}
​
strictKnownMarketplaces
Managed settings only
: Controls which plugin marketplaces users are allowed to add and install plugins from. This setting can only be configured in
managed settings
and provides administrators with strict control over marketplace sources.
Managed settings file locations
:
macOS
:
/Library/Application Support/ClaudeCode/managed-settings.json
Linux and WSL
:
/etc/claude-code/managed-settings.json
Windows
:
C:\Program Files\ClaudeCode\managed-settings.json
Key characteristics
:
Only available in managed settings (
managed-settings.json
)
Cannot be overridden by user or project settings (highest precedence)
Enforced BEFORE network/filesystem operations (blocked sources never execute)
Uses exact matching for source specifications (including
ref
,
path
for git sources), except
hostPattern
and
pathPattern
, which use regex matching
Allowlist behavior
:
undefined
(default): No restrictions - users can add any marketplace
Empty array
[]
: Complete lockdown - users cannot add any new marketplaces
List of sources: Users can only add marketplaces that match exactly
All supported source types
:
The allowlist supports multiple marketplace source types. Most sources use exact matching, while
hostPattern
and
pathPattern
use regex matching against the marketplace host and filesystem path respectively.
GitHub repositories
:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"ref"
:
"main"
,
"path"
:
"marketplace"
}
Fields:
repo
(required),
ref
(optional: branch/tag/SHA),
path
(optional: subdirectory)
Git repositories
:
{
"source"
:
"git"
,
"url"
:
"https://gitlab.example.com/tools/plugins.git"
}
{
"source"
:
"git"
,
"url"
:
"https://bitbucket.org/acme-corp/plugins.git"
,
"ref"
:
"production"
}
{
"source"
:
"git"
,
"url"
:
"ssh://git@git.example.com/plugins.git"
,
"ref"
:
"v3.1"
,
"path"
:
"approved"
}
Fields:
url
(required),
ref
(optional: branch/tag/SHA),
path
(optional: subdirectory)
URL-based marketplaces
:
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
}
{
"source"
:
"url"
,
"url"
:
"https://cdn.example.com/marketplace.json"
,
"headers"
: {
"Authorization"
:
"Bearer ${TOKEN}"
} }
Fields:
url
(required),
headers
(optional: HTTP headers for authenticated access)
URL-based marketplaces only download the
marketplace.json
file. They do not download plugin files from the server. Plugins in URL-based marketplaces must use external sources (GitHub, npm, or git URLs) rather than relative paths. For plugins with relative paths, use a Git-based marketplace instead. See
Troubleshooting
for details.
NPM packages
:
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/claude-plugins"
}
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/approved-marketplace"
}
Fields:
package
(required, supports scoped packages)
File paths
:
{
"source"
:
"file"
,
"path"
:
"/usr/local/share/claude/acme-marketplace.json"
}
{
"source"
:
"file"
,
"path"
:
"/opt/acme-corp/plugins/marketplace.json"
}
Fields:
path
(required: absolute path to marketplace.json file)
Directory paths
:
{
"source"
:
"directory"
,
"path"
:
"/usr/local/share/claude/acme-plugins"
}
{
"source"
:
"directory"
,
"path"
:
"/opt/acme-corp/approved-marketplaces"
}
Fields:
path
(required: absolute path to directory containing
.claude-plugin/marketplace.json
)
Host pattern matching
:
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^gitlab
\\
.internal
\\
.example
\\
.com$"
}
Fields:
hostPattern
(required: regex pattern to match against the marketplace host)
Use host pattern matching when you want to allow all marketplaces from a specific host without enumerating each repository individually. This is useful for organizations with internal GitHub Enterprise or GitLab servers where developers create their own marketplaces.
Host extraction by source type:
github
: always matches against
github.com
git
: extracts hostname from the URL (supports both HTTPS and SSH formats)
url
: extracts hostname from the URL
npm
,
file
,
directory
: not supported for host pattern matching
Path pattern matching
:
{
"source"
:
"pathPattern"
,
"pathPattern"
:
"^/opt/approved/"
}
{
"source"
:
"pathPattern"
,
"pathPattern"
:
".*"
}
Fields:
pathPattern
(required: regex pattern matched against the
path
field of
file
and
directory
sources)
Use path pattern matching to allow filesystem-based marketplaces alongside
hostPattern
restrictions for network sources. Set
".*"
to allow all local paths, or a narrower pattern to restrict to specific directories.
Configuration examples
:
Example: allow specific marketplaces only:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
},
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
},
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
},
{
"source"
:
"npm"
,
"package"
:
"@acme-corp/compliance-plugins"
}
]
}
Example - Disable all marketplace additions:
{
"strictKnownMarketplaces"
: []
}
Example: allow all marketplaces from an internal git server:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
Exact matching requirements
:
Marketplace sources must match
exactly
for a user’s addition to be allowed. For git-based sources (
github
and
git
), this includes all optional fields:
The
repo
or
url
must match exactly
The
ref
field must match exactly (or both be undefined)
The
path
field must match exactly (or both be undefined)
Examples of sources that
do NOT match
:
// These are DIFFERENT sources:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"ref"
:
"main"
}
// These are also DIFFERENT:
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
,
"path"
:
"marketplace"
}
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
Comparison with
extraKnownMarketplaces
:
Aspect
strictKnownMarketplaces
extraKnownMarketplaces
Purpose
Organizational policy enforcement
Team convenience
Settings file
managed-settings.json
only
Any settings file
Behavior
Blocks non-allowlisted additions
Auto-installs missing marketplaces
When enforced
Before network/filesystem operations
After user trust prompt
Can be overridden
No (highest precedence)
Yes (by higher precedence settings)
Source format
Direct source object
Named marketplace with nested source
Use case
Compliance, security restrictions
Onboarding, standardization
Format difference
:
strictKnownMarketplaces
uses direct source objects:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
]
}
extraKnownMarketplaces
requires named marketplaces:
{
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
}
}
}
Using both together
:
strictKnownMarketplaces
is a policy gate: it controls what users may add but does not register any marketplaces. To both restrict and pre-register a marketplace for all users, set both in
managed-settings.json
:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
],
"extraKnownMarketplaces"
: {
"acme-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/plugins"
}
}
}
}
With only
strictKnownMarketplaces
set, users can still add the allowed marketplace manually via
/plugin marketplace add
, but it is not available automatically.
Important notes
:
Restrictions are checked BEFORE any network requests or filesystem operations
When blocked, users see clear error messages indicating the source is blocked by managed policy
The restriction is enforced on marketplace add and on plugin install, update, refresh, and auto-update. A marketplace added before the policy was set cannot be used to install or update plugins once its source no longer matches the allowlist
Managed settings have the highest precedence and cannot be overridden
See
Managed marketplace restrictions
for user-facing documentation.
​
Managing plugins
Use the
/plugin
command to manage plugins interactively:
Browse available plugins from marketplaces
Install/uninstall plugins
Enable/disable plugins
View plugin details (skills, agents, hooks provided)
Add/remove marketplaces
Learn more about the plugin system in the
plugins documentation
.
​
Environment variables
Environment variables let you control Claude Code behavior without editing settings files. Any variable can also be configured in
settings.json
under the
env
key to apply it to every session or roll it out to your team.
See the
environment variables reference
for the full list.
​
Tools available to Claude
Claude Code has access to a set of tools for reading, editing, searching, running commands, and orchestrating subagents. Tool names are the exact strings you use in permission rules and hook matchers.
See the
tools reference
for the full list and Bash tool behavior details.
​
See also
Permissions
: permission system, rule syntax, tool-specific patterns, and managed policies
Authentication
: set up user access to Claude Code
Debug your configuration
: diagnose why a setting, hook, or MCP server isn’t taking effect
Troubleshoot installation and login
: installation, authentication, and platform issues
Was this page helpful?
Yes
No
Permissions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/settings" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Slash Commands in the SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/slash-commands</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/slash-commands</guid>
  <pubDate>Mon, 05 Feb 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Slash Commands in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the S...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Slash Commands in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
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:
TypeScript
Python
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
);
// Example output: ["/compact", "/context", "/usage"]
}
}
​
Sending Slash Commands
Send slash commands by including them in your prompt string, just like regular text:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Send a slash command
for
await
(
const
message
of
query
({
prompt:
"/compact"
,
options:
{
maxTurns:
1
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
"Command executed:"
,
message
.
result
);
}
}
​
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:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"/compact"
,
options:
{
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
);
}
}
​
Clearing the conversation
The interactive
/clear
command is not available in the SDK. Each
query()
call already starts a fresh conversation, so to clear context, end the current
query()
and start a new one. The previous conversation stays on disk and can be returned to by passing its session ID to the
resume
option
.
​
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. Custom commands are defined as markdown files in specific directories, similar to how subagents are configured.
The
.claude/commands/
directory is the legacy format. The recommended format is
.claude/skills/<name>/SKILL.md
, which supports the same slash-command invocation (
/name
) plus autonomous invocation by Claude. See
Skills
for the current format. The CLI continues to support both formats, and the examples below remain accurate for
.claude/commands/
.
​
File Locations
Custom slash commands are stored in designated directories based on their scope:
Project commands
:
.claude/commands/
- Available only in the current project (legacy; prefer
.claude/skills/
)
Personal commands
:
~/.claude/commands/
- Available across all your projects (legacy; 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
.claude/commands/refactor.md
:
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
:
---
allowed-tools
:
Read, Grep, Glob
description
:
Run security vulnerability scan
model
:
claude-opus-4-7
---
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:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Use a custom command
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
);
}
}
// 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"
) {
// Will include both built-in and custom commands
console
.
log
(
"Available commands:"
,
message
.
slash_commands
);
// Example: ["/compact", "/context", "/usage", "/refactor", "/security-check"]
}
}
​
Advanced Features
​
Arguments and Placeholders
Custom commands support dynamic arguments using placeholders:
Create
.claude/commands/fix-issue.md
:
---
argument-hint
: [
issue-number
] [
priority
]
description
:
Fix a GitHub issue
---
Fix issue #$1 with priority $2.
Check the issue description and implement the necessary changes.
Use in SDK:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Pass arguments to custom command
for
await
(
const
message
of
query
({
prompt:
"/fix-issue 123 high"
,
options:
{
maxTurns:
5
}
})) {
// Command will process with $1="123" and $2="high"
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
"Issue fixed:"
,
message
.
result
);
}
}
​
Bash Command Execution
Custom commands can execute bash commands and include their output:
Create
.claude/commands/git-commit.md
:
---
allowed-tools
:
Bash(git add *), Bash(git status *), Bash(git commit *)
description
:
Create a git commit
---
## Context
-
Current status: !
`git status`
-
Current diff: !
`git diff HEAD`
## Task
Create a git commit with appropriate message based on the changes.
​
File References
Include file contents using the
@
prefix:
Create
.claude/commands/review-config.md
:
---
description
:
Review configuration files
---
Review the following configuration files for issues:
-
Package config: @package.json
-
TypeScript config: @tsconfig.json
-
Environment config: @.env
Check for security issues, outdated dependencies, and misconfigurations.
​
Organization with Namespacing
Organize commands in subdirectories for better structure:
.claude/commands/
├──
frontend/
│
├──
component.md
# Creates /component (project:frontend)
│
└──
style-check.md
# Creates /style-check (project:frontend)
├──
backend/
│
├──
api-test.md
# Creates /api-test (project:backend)
│
└──
db-migrate.md
# Creates /db-migrate (project:backend)
└──
review.md
# Creates /review (project)
The subdirectory appears in the command description but doesn’t affect the command name itself.
​
Practical Examples
​
Code Review Command
Create
.claude/commands/code-review.md
:
---
allowed-tools
:
Read, Grep, Glob, Bash(git diff *)
description
:
Comprehensive code review
---
## Changed Files
!
`git diff --name-only HEAD~1`
## Detailed Changes
!
`git diff HEAD~1`
## Review Checklist
Review the above changes for:
1.
Code quality and readability
2.
Security vulnerabilities
3.
Performance implications
4.
Test coverage
5.
Documentation completeness
Provide specific, actionable feedback organized by priority.
​
Test Runner Command
Create
.claude/commands/test.md
:
---
allowed-tools
:
Bash, Read, Edit
argument-hint
: [
test-pattern
]
description
:
Run tests with optional pattern
---
Run tests matching pattern: $ARGUMENTS
1.
Detect the test framework (Jest, pytest, etc.)
2.
Run tests with the provided pattern
3.
If tests fail, analyze and fix them
4.
Re-run to verify fixes
Use these commands through the SDK:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Run code review
for
await
(
const
message
of
query
({
prompt:
"/code-review"
,
options:
{
maxTurns:
3
}
})) {
// Process review feedback
}
// Run specific tests
for
await
(
const
message
of
query
({
prompt:
"/test auth"
,
options:
{
maxTurns:
5
}
})) {
// Handle test results
}
​
See Also
Slash Commands
- Complete slash command documentation
Subagents in the SDK
- Similar filesystem-based configuration for subagents
TypeScript SDK reference
- Complete API documentation
SDK overview
- General SDK concepts
CLI reference
- Command-line interface
Was this page helpful?
Yes
No
Modifying system prompts
Agent Skills in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/slash-commands" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Slash Commands in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the S...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Customize behavior
Slash Commands in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
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:
TypeScript
Python
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
);
// Example output: ["/compact", "/context", "/usage"]
}
}
​
Sending Slash Commands
Send slash commands by including them in your prompt string, just like regular text:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Send a slash command
for
await
(
const
message
of
query
({
prompt:
"/compact"
,
options:
{
maxTurns:
1
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
"Command executed:"
,
message
.
result
);
}
}
​
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:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"/compact"
,
options:
{
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
);
}
}
​
Clearing the conversation
The interactive
/clear
command is not available in the SDK. Each
query()
call already starts a fresh conversation, so to clear context, end the current
query()
and start a new one. The previous conversation stays on disk and can be returned to by passing its session ID to the
resume
option
.
​
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. Custom commands are defined as markdown files in specific directories, similar to how subagents are configured.
The
.claude/commands/
directory is the legacy format. The recommended format is
.claude/skills/<name>/SKILL.md
, which supports the same slash-command invocation (
/name
) plus autonomous invocation by Claude. See
Skills
for the current format. The CLI continues to support both formats, and the examples below remain accurate for
.claude/commands/
.
​
File Locations
Custom slash commands are stored in designated directories based on their scope:
Project commands
:
.claude/commands/
- Available only in the current project (legacy; prefer
.claude/skills/
)
Personal commands
:
~/.claude/commands/
- Available across all your projects (legacy; 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
.claude/commands/refactor.md
:
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
:
---
allowed-tools
:
Read, Grep, Glob
description
:
Run security vulnerability scan
model
:
claude-opus-4-7
---
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:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Use a custom command
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
);
}
}
// 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"
) {
// Will include both built-in and custom commands
console
.
log
(
"Available commands:"
,
message
.
slash_commands
);
// Example: ["/compact", "/context", "/usage", "/refactor", "/security-check"]
}
}
​
Advanced Features
​
Arguments and Placeholders
Custom commands support dynamic arguments using placeholders:
Create
.claude/commands/fix-issue.md
:
---
argument-hint
: [
issue-number
] [
priority
]
description
:
Fix a GitHub issue
---
Fix issue #$1 with priority $2.
Check the issue description and implement the necessary changes.
Use in SDK:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Pass arguments to custom command
for
await
(
const
message
of
query
({
prompt:
"/fix-issue 123 high"
,
options:
{
maxTurns:
5
}
})) {
// Command will process with $1="123" and $2="high"
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
"Issue fixed:"
,
message
.
result
);
}
}
​
Bash Command Execution
Custom commands can execute bash commands and include their output:
Create
.claude/commands/git-commit.md
:
---
allowed-tools
:
Bash(git add *), Bash(git status *), Bash(git commit *)
description
:
Create a git commit
---
## Context
-
Current status: !
`git status`
-
Current diff: !
`git diff HEAD`
## Task
Create a git commit with appropriate message based on the changes.
​
File References
Include file contents using the
@
prefix:
Create
.claude/commands/review-config.md
:
---
description
:
Review configuration files
---
Review the following configuration files for issues:
-
Package config: @package.json
-
TypeScript config: @tsconfig.json
-
Environment config: @.env
Check for security issues, outdated dependencies, and misconfigurations.
​
Organization with Namespacing
Organize commands in subdirectories for better structure:
.claude/commands/
├──
frontend/
│
├──
component.md
# Creates /component (project:frontend)
│
└──
style-check.md
# Creates /style-check (project:frontend)
├──
backend/
│
├──
api-test.md
# Creates /api-test (project:backend)
│
└──
db-migrate.md
# Creates /db-migrate (project:backend)
└──
review.md
# Creates /review (project)
The subdirectory appears in the command description but doesn’t affect the command name itself.
​
Practical Examples
​
Code Review Command
Create
.claude/commands/code-review.md
:
---
allowed-tools
:
Read, Grep, Glob, Bash(git diff *)
description
:
Comprehensive code review
---
## Changed Files
!
`git diff --name-only HEAD~1`
## Detailed Changes
!
`git diff HEAD~1`
## Review Checklist
Review the above changes for:
1.
Code quality and readability
2.
Security vulnerabilities
3.
Performance implications
4.
Test coverage
5.
Documentation completeness
Provide specific, actionable feedback organized by priority.
​
Test Runner Command
Create
.claude/commands/test.md
:
---
allowed-tools
:
Bash, Read, Edit
argument-hint
: [
test-pattern
]
description
:
Run tests with optional pattern
---
Run tests matching pattern: $ARGUMENTS
1.
Detect the test framework (Jest, pytest, etc.)
2.
Run tests with the provided pattern
3.
If tests fail, analyze and fix them
4.
Re-run to verify fixes
Use these commands through the SDK:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Run code review
for
await
(
const
message
of
query
({
prompt:
"/code-review"
,
options:
{
maxTurns:
3
}
})) {
// Process review feedback
}
// Run specific tests
for
await
(
const
message
of
query
({
prompt:
"/test auth"
,
options:
{
maxTurns:
5
}
})) {
// Handle test results
}
​
See Also
Slash Commands
- Complete slash command documentation
Subagents in the SDK
- Similar filesystem-based configuration for subagents
TypeScript SDK reference
- Complete API documentation
SDK overview
- General SDK concepts
CLI reference
- Command-line interface
Was this page helpful?
Yes
No
Modifying system prompts
Agent Skills in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/slash-commands" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Champion kit</title>
  <link>https://code.claude.com/docs/en/champion-kit</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/champion-kit</guid>
  <pubDate>Mon, 05 Feb 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Champion kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependen...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Champion kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page is for individual engineers who are already using Claude Code and want to help their team adopt it. It covers what to share, how to answer the questions you will get, a thirty-day playbook, and responses to common concerns.
Adoption of a developer tool rarely happens because of a rollout announcement. It happens because someone on the team begins using the tool well, talks about it openly, and makes it easy for others to follow. The work you do as a champion has a disproportionate effect: every example you share shortens the learning curve for the engineers who come after you, and every question you answer in public turns one person’s experience into something the whole team can build on. You are acting as a multiplier for your team, not a help desk, and this guide is structured to keep the role sustainable on those terms.
​
The champion role
The role consists of three behaviors that reinforce one another.
Behavior
What it looks like in practice
Why it matters
Share what you discover
Post the prompts, screenshots, and small wins from your own work in the places your team already reads, such as an engineering channel, a standup thread, or a pull-request description.
Examples drawn from your own codebase are more persuasive than any external documentation, because colleagues can see exactly how the tool applies to the problems they share with you.
Be the person people ask
When a colleague asks how you accomplished something, respond with the actual prompt you used so they can apply it directly to their own task.
A concrete, runnable example removes the gap between curiosity and a first successful use, which is where most adoption efforts stall.
Grow the circle
Establish a small number of lightweight, recurring habits, such as a dedicated channel or a weekly thread, so that momentum continues even when your attention is elsewhere.
Adoption that depends on a single person is fragile. Adoption that is carried by shared habits continues to compound on its own.
Most of this fits naturally inside the work you are already doing. The difference is a small amount of additional intention about where your discoveries are posted and how your answers travel.
​
What this should cost you
Set expectations with yourself and with your lead. The activities below are intended to fit inside a normal working week, and the role should remain a multiplier on your existing work rather than an additional support responsibility.
Activity
Time per week
Guidance
Posting wins and prompts
About 15 minutes
Capture these in the moment with a screenshot and one or two sentences; avoid turning them into formal write-ups.
Answering questions in a shared channel
About 20 minutes
Answer publicly once, then link back to that answer when the question recurs.
Hosting a weekly show-and-tell thread
About 5 minutes
You post the opening prompt; the team supplies the content.
Optional pairing or walkthroughs
0 to 30 minutes
Reserve this for colleagues who are genuinely blocked, and offer the
Quickstart
link before scheduling time.
​
Share what you discover
Your own experience is the most persuasive material your colleagues will encounter, because it is specific to the codebase, workflows, and problems you all share. Documentation tells people what is possible; your posts show them what is actually working in your environment.
​
What is worth sharing
The most useful posts describe a technique a colleague can reuse tomorrow rather than an outcome that is already complete. Techniques compound as they spread through a team; status updates do not.
Examples of reusable techniques:
“I learned that @-mentioning a directory works. Pointing it at
@src/components/
and asking which were missing tests surfaced two I had overlooked.”
“Plan mode (
Shift+Tab
) shows exactly which files will be touched before any edit is made, which is why I am comfortable using it on shared code.”
“I configured a Stop hook so I receive a desktop notification when a long task completes. Configuration is in the thread.”
“Running
/init
generates a
CLAUDE.md
from the repository so the assistant stops re-asking about our conventions.”
​
Where to share it
Post wherever your team already reads. The goal is to place examples in the path of normal work rather than to create a destination.
Location
Best suited for
Recommended format
A
#claude-code
or general engineering channel
Discoveries, prompts, and “today I learned” moments
A screenshot accompanied by one or two sentences of context
Pull-request descriptions
Demonstrating the approach on real code that reviewers are already reading
A single line such as “Claude and I did this refactor; happy to walk through the approach.”
Standups or weekly written updates
Normalizing usage with leads and skip-level managers
One sentence describing one concrete outcome
Team wiki or internal documentation
Durable patterns, custom skills, and
CLAUDE.md
examples
A short page, linked from the channel topic so it remains discoverable
​
The format that works
A screenshot accompanied by a single line of context, or a brief before-and-after description, is generally the right level of detail. Keep each post short enough that someone scrolling past still absorbs the point. A long write-up tends to be saved for later and forgotten, whereas a short post with a screenshot tends to be copied and tried.
The example posts below illustrate tone and length; adapt them rather than copying verbatim.
Learned today that @-mentioning a directory works. I pointed it at
@src/components/ and asked which components were missing tests, and it
surfaced two I had forgotten about.
I configured a Stop hook so I receive a desktop notification when a long
task completes. I started a refactor, stepped away, and was notified when
it finished. Configuration is in the thread.
Plan mode is the reason I am comfortable using this on code that matters.
Press Shift+Tab until you see "plan"; it lays out exactly which files it
intends to touch before changing anything.
​
Be the person people ask
Once you have shared a few examples, questions will follow. This is where the champion role has the greatest leverage, because a good answer to one person frequently unblocks several others who are watching the same channel.
​
Answer with a prompt rather than an explanation
When a colleague asks how you accomplished something, the most useful response is the prompt you actually used. They will learn more from running that prompt against their own problem than from any description you could write, and it gives them something they can act on immediately.
Colleague: How did you get it to find that race condition?
Champion: I asked, "The test in @tests/scheduler.test.ts is flaky, figure
out why," and it traced two unjoined promises in the scheduler. Try the
same phrasing on your test.
​
Point at the feature rather than the documentation
A response such as “Try plan mode, press
Shift+Tab
until you see it” is more useful in the moment than a link to the documentation. If the person needs more depth later they will find it on their own; right now they need the single thing that unblocks them.
​
Questions you are likely to hear
Question
Suggested response
Follow-up resource
”What should I try it on first?”
Recommend a real but contained task, ideally a bug or chore the person has been postponing because it is tedious rather than difficult.
Common workflows
”How do I trust it with my code?”
Introduce plan mode: pressing
Shift+Tab
cycles into it, Claude proposes exactly what it intends to change, and nothing is modified until the user approves.
Permissions
”Is the setup worth the effort?”
Installation takes roughly two minutes, runs in the terminal, and requires no IDE extension. Running
/init
once is sufficient to begin working.
Quickstart
”It produced an incorrect result.”
Encourage them to provide the failure back to Claude. Pasting the error message or failing test is far more effective than rephrasing the original request.
Common workflows
”It does not understand our codebase conventions.”
Suggest running
/init
to generate a
CLAUDE.md
file, then adding the team’s conventions, test commands, and any directories that should be avoided.
Memory
”Is this just autocomplete?”
Offer a brief demonstration in which Claude explains an unfamiliar file, traces a bug across services, or drafts a migration plan. These tasks require reasoning across the repository rather than completing a single line.
A two-minute live demonstration
”What about security and data handling?”
Refer this question to your administrator. Your organization’s deployment and data-handling policy is already configured, and champions should not improvise this answer.
Security
·
Data usage
​
Grow the circle
The objective is not to build a program or to own a rollout. It is to establish a small number of lightweight habits that allow momentum to continue after you have stopped actively driving it. When questions in the channel are being answered by people other than you, the role has done its job.
​
Patterns that tend to work
Pattern
How to run it
Effort required
A dedicated channel
Create a
#claude-code
channel (or a recurring thread in an existing one), pin the
Quickstart
link and one strong example, and answer questions publicly so each answer benefits everyone watching.
About five minutes to set up, then ambient
A weekly show-and-tell thread
Each Friday, post “What did Claude help you with this week?” No preparation, slides, or meeting are required; screenshots and short descriptions are sufficient.
About two minutes per week
Share a custom skill
Post your most useful
.claude/skills/<name>/SKILL.md
file, for example a
/ship
skill that runs tests and lint before committing, with a one-line description. Because skills are plain Markdown, colleagues can adopt them immediately.
About five minutes per skill
Generate a setup guide from your own usage
Run
/team-onboarding
in a project you have spent real time in. Claude scans your recent sessions, commands, and MCP servers, then produces a guide a new teammate can paste as their first message to replay your setup. Pin it in the channel.
About two minutes
Pair on a first task
Offer a single fifteen-minute pairing session to anyone getting started. One successful outcome on their own code is more persuasive than any presentation.
About fifteen minutes per person
Identify the next champion
The colleague who asks you the most questions is usually ready to take on this role. Forward them this page and divide the channel responsibilities between you.
Negligible
​
Thirty-day playbook
If a loose plan is helpful, the sequence below reflects what tends to work across most teams. Adjust freely to fit your context.
1
Week 1: Seed the channel
Create the channel, pin the
Quickstart
, and post two or three of your own examples with the prompts included.
Signal that it is working:
a few colleagues react or reply, and at least one question is asked in the channel.
2
Week 2: Start the rhythm
Start the weekly show-and-tell thread, answer every question publicly, and share one custom skill or
CLAUDE.md
snippet.
Signal that it is working:
someone other than you posts an example of their own.
3
Week 3: Pair and consolidate
Offer two or three short pairing sessions and consolidate the most common questions and answers into a pinned FAQ message.
Signal that it is working:
you see repeat usage, with the same colleagues returning rather than trying once and stopping.
4
Week 4: Hand off
Identify a second champion and share a brief summary of what is working and what is not with your lead or administrator.
Signal that it is working:
questions in the channel are being answered by people other than you.
​
When someone wants to go deeper
You are the warm introduction rather than the onboarding program. When a colleague moves past “should I try this” into “how do I become effective with it,” point them to the
Quickstart
and
Common workflows
pages. They contain short sections covering the features that are genuinely useful but difficult to discover on your own.
​
Respond to common concerns
Healthy skepticism is expected; engineers should be cautious about tools that touch their code. The most effective response is rarely to argue the general case. Instead, acknowledge the concern, offer a brief reframe, and propose one concrete demonstration on the person’s own code. Most concerns are resolved by a single successful experience.
Concern
Suggested response
Evidence to offer
”I am faster without it.”
That is likely true for code the person writes routinely. Suggest trying it on the work they tend to avoid: legacy files, unfamiliar services, or test scaffolding, where the leverage is highest.
Time one tedious task both ways and compare.
”I do not trust AI to touch production code.”
Agree that no change should land unread. Plan mode combined with normal diff review means nothing is applied that the engineer has not inspected, the same standard as any pull request.
Demonstrate plan mode on a real file.
”It will make junior engineers weaker.”
Used well, it is an effective explainer. Encourage junior engineers to ask Claude to explain a file and its call sites before asking it to change anything.
Run “Explain @file and where it is called from” together.
”I tried it once and it hallucinated.”
This is usually a context problem rather than a model problem. @-mentioning the relevant files, running
/init
, and providing the actual error output typically resolves it.
Re-run their original prompt with proper
@
-context.
”We do not have time to learn another tool.”
Claude Code is a terminal command rather than a platform. If it does not return value within the first session, it is reasonable to set it aside.
A two-minute install followed by one real bug.
​
Quick-reference sheet
The techniques below are the ones that most reliably move someone from a first trial to daily use. Pin this table in a channel or share it on its own.
Technique
How to apply it
Provide the right context
Use
@file
or
@directory/
references, or paste the error or log output directly. Supplying relevant context is more effective than elaborate prompting.
Review the plan before the edit
Press
Shift+Tab
to enter plan mode. Claude will describe the intended changes for your approval before executing them.
Teach it your repository
Run
/init
to generate a
CLAUDE.md
file, then add your conventions, test commands, and any directories that should not be modified. See
Memory
.
Reuse a workflow
Save a
SKILL.md
file in
.claude/skills/<name>/
to create a
/name
skill that the entire team can use. See
Skills
.
Stay informed during long tasks
Configure a Stop hook to receive a desktop notification when a long-running task completes. See
Hooks
.
Recover from an incorrect result
Rather than rephrasing the request, paste the failing test or stack trace back to Claude and ask it to address that specific failure.
Keep edits surgical
Ask for a diff, or specify “only change X.” Claude respects scope when scope is stated.
Claude Code is updated frequently. Verify version-specific details against the
documentation home page
before distributing this material internally.
Was this page helpful?
Yes
No
Communications kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/champion-kit" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Champion kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependen...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Adoption
Champion kit
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This page is for individual engineers who are already using Claude Code and want to help their team adopt it. It covers what to share, how to answer the questions you will get, a thirty-day playbook, and responses to common concerns.
Adoption of a developer tool rarely happens because of a rollout announcement. It happens because someone on the team begins using the tool well, talks about it openly, and makes it easy for others to follow. The work you do as a champion has a disproportionate effect: every example you share shortens the learning curve for the engineers who come after you, and every question you answer in public turns one person’s experience into something the whole team can build on. You are acting as a multiplier for your team, not a help desk, and this guide is structured to keep the role sustainable on those terms.
​
The champion role
The role consists of three behaviors that reinforce one another.
Behavior
What it looks like in practice
Why it matters
Share what you discover
Post the prompts, screenshots, and small wins from your own work in the places your team already reads, such as an engineering channel, a standup thread, or a pull-request description.
Examples drawn from your own codebase are more persuasive than any external documentation, because colleagues can see exactly how the tool applies to the problems they share with you.
Be the person people ask
When a colleague asks how you accomplished something, respond with the actual prompt you used so they can apply it directly to their own task.
A concrete, runnable example removes the gap between curiosity and a first successful use, which is where most adoption efforts stall.
Grow the circle
Establish a small number of lightweight, recurring habits, such as a dedicated channel or a weekly thread, so that momentum continues even when your attention is elsewhere.
Adoption that depends on a single person is fragile. Adoption that is carried by shared habits continues to compound on its own.
Most of this fits naturally inside the work you are already doing. The difference is a small amount of additional intention about where your discoveries are posted and how your answers travel.
​
What this should cost you
Set expectations with yourself and with your lead. The activities below are intended to fit inside a normal working week, and the role should remain a multiplier on your existing work rather than an additional support responsibility.
Activity
Time per week
Guidance
Posting wins and prompts
About 15 minutes
Capture these in the moment with a screenshot and one or two sentences; avoid turning them into formal write-ups.
Answering questions in a shared channel
About 20 minutes
Answer publicly once, then link back to that answer when the question recurs.
Hosting a weekly show-and-tell thread
About 5 minutes
You post the opening prompt; the team supplies the content.
Optional pairing or walkthroughs
0 to 30 minutes
Reserve this for colleagues who are genuinely blocked, and offer the
Quickstart
link before scheduling time.
​
Share what you discover
Your own experience is the most persuasive material your colleagues will encounter, because it is specific to the codebase, workflows, and problems you all share. Documentation tells people what is possible; your posts show them what is actually working in your environment.
​
What is worth sharing
The most useful posts describe a technique a colleague can reuse tomorrow rather than an outcome that is already complete. Techniques compound as they spread through a team; status updates do not.
Examples of reusable techniques:
“I learned that @-mentioning a directory works. Pointing it at
@src/components/
and asking which were missing tests surfaced two I had overlooked.”
“Plan mode (
Shift+Tab
) shows exactly which files will be touched before any edit is made, which is why I am comfortable using it on shared code.”
“I configured a Stop hook so I receive a desktop notification when a long task completes. Configuration is in the thread.”
“Running
/init
generates a
CLAUDE.md
from the repository so the assistant stops re-asking about our conventions.”
​
Where to share it
Post wherever your team already reads. The goal is to place examples in the path of normal work rather than to create a destination.
Location
Best suited for
Recommended format
A
#claude-code
or general engineering channel
Discoveries, prompts, and “today I learned” moments
A screenshot accompanied by one or two sentences of context
Pull-request descriptions
Demonstrating the approach on real code that reviewers are already reading
A single line such as “Claude and I did this refactor; happy to walk through the approach.”
Standups or weekly written updates
Normalizing usage with leads and skip-level managers
One sentence describing one concrete outcome
Team wiki or internal documentation
Durable patterns, custom skills, and
CLAUDE.md
examples
A short page, linked from the channel topic so it remains discoverable
​
The format that works
A screenshot accompanied by a single line of context, or a brief before-and-after description, is generally the right level of detail. Keep each post short enough that someone scrolling past still absorbs the point. A long write-up tends to be saved for later and forgotten, whereas a short post with a screenshot tends to be copied and tried.
The example posts below illustrate tone and length; adapt them rather than copying verbatim.
Learned today that @-mentioning a directory works. I pointed it at
@src/components/ and asked which components were missing tests, and it
surfaced two I had forgotten about.
I configured a Stop hook so I receive a desktop notification when a long
task completes. I started a refactor, stepped away, and was notified when
it finished. Configuration is in the thread.
Plan mode is the reason I am comfortable using this on code that matters.
Press Shift+Tab until you see "plan"; it lays out exactly which files it
intends to touch before changing anything.
​
Be the person people ask
Once you have shared a few examples, questions will follow. This is where the champion role has the greatest leverage, because a good answer to one person frequently unblocks several others who are watching the same channel.
​
Answer with a prompt rather than an explanation
When a colleague asks how you accomplished something, the most useful response is the prompt you actually used. They will learn more from running that prompt against their own problem than from any description you could write, and it gives them something they can act on immediately.
Colleague: How did you get it to find that race condition?
Champion: I asked, "The test in @tests/scheduler.test.ts is flaky, figure
out why," and it traced two unjoined promises in the scheduler. Try the
same phrasing on your test.
​
Point at the feature rather than the documentation
A response such as “Try plan mode, press
Shift+Tab
until you see it” is more useful in the moment than a link to the documentation. If the person needs more depth later they will find it on their own; right now they need the single thing that unblocks them.
​
Questions you are likely to hear
Question
Suggested response
Follow-up resource
”What should I try it on first?”
Recommend a real but contained task, ideally a bug or chore the person has been postponing because it is tedious rather than difficult.
Common workflows
”How do I trust it with my code?”
Introduce plan mode: pressing
Shift+Tab
cycles into it, Claude proposes exactly what it intends to change, and nothing is modified until the user approves.
Permissions
”Is the setup worth the effort?”
Installation takes roughly two minutes, runs in the terminal, and requires no IDE extension. Running
/init
once is sufficient to begin working.
Quickstart
”It produced an incorrect result.”
Encourage them to provide the failure back to Claude. Pasting the error message or failing test is far more effective than rephrasing the original request.
Common workflows
”It does not understand our codebase conventions.”
Suggest running
/init
to generate a
CLAUDE.md
file, then adding the team’s conventions, test commands, and any directories that should be avoided.
Memory
”Is this just autocomplete?”
Offer a brief demonstration in which Claude explains an unfamiliar file, traces a bug across services, or drafts a migration plan. These tasks require reasoning across the repository rather than completing a single line.
A two-minute live demonstration
”What about security and data handling?”
Refer this question to your administrator. Your organization’s deployment and data-handling policy is already configured, and champions should not improvise this answer.
Security
·
Data usage
​
Grow the circle
The objective is not to build a program or to own a rollout. It is to establish a small number of lightweight habits that allow momentum to continue after you have stopped actively driving it. When questions in the channel are being answered by people other than you, the role has done its job.
​
Patterns that tend to work
Pattern
How to run it
Effort required
A dedicated channel
Create a
#claude-code
channel (or a recurring thread in an existing one), pin the
Quickstart
link and one strong example, and answer questions publicly so each answer benefits everyone watching.
About five minutes to set up, then ambient
A weekly show-and-tell thread
Each Friday, post “What did Claude help you with this week?” No preparation, slides, or meeting are required; screenshots and short descriptions are sufficient.
About two minutes per week
Share a custom skill
Post your most useful
.claude/skills/<name>/SKILL.md
file, for example a
/ship
skill that runs tests and lint before committing, with a one-line description. Because skills are plain Markdown, colleagues can adopt them immediately.
About five minutes per skill
Generate a setup guide from your own usage
Run
/team-onboarding
in a project you have spent real time in. Claude scans your recent sessions, commands, and MCP servers, then produces a guide a new teammate can paste as their first message to replay your setup. Pin it in the channel.
About two minutes
Pair on a first task
Offer a single fifteen-minute pairing session to anyone getting started. One successful outcome on their own code is more persuasive than any presentation.
About fifteen minutes per person
Identify the next champion
The colleague who asks you the most questions is usually ready to take on this role. Forward them this page and divide the channel responsibilities between you.
Negligible
​
Thirty-day playbook
If a loose plan is helpful, the sequence below reflects what tends to work across most teams. Adjust freely to fit your context.
1
Week 1: Seed the channel
Create the channel, pin the
Quickstart
, and post two or three of your own examples with the prompts included.
Signal that it is working:
a few colleagues react or reply, and at least one question is asked in the channel.
2
Week 2: Start the rhythm
Start the weekly show-and-tell thread, answer every question publicly, and share one custom skill or
CLAUDE.md
snippet.
Signal that it is working:
someone other than you posts an example of their own.
3
Week 3: Pair and consolidate
Offer two or three short pairing sessions and consolidate the most common questions and answers into a pinned FAQ message.
Signal that it is working:
you see repeat usage, with the same colleagues returning rather than trying once and stopping.
4
Week 4: Hand off
Identify a second champion and share a brief summary of what is working and what is not with your lead or administrator.
Signal that it is working:
questions in the channel are being answered by people other than you.
​
When someone wants to go deeper
You are the warm introduction rather than the onboarding program. When a colleague moves past “should I try this” into “how do I become effective with it,” point them to the
Quickstart
and
Common workflows
pages. They contain short sections covering the features that are genuinely useful but difficult to discover on your own.
​
Respond to common concerns
Healthy skepticism is expected; engineers should be cautious about tools that touch their code. The most effective response is rarely to argue the general case. Instead, acknowledge the concern, offer a brief reframe, and propose one concrete demonstration on the person’s own code. Most concerns are resolved by a single successful experience.
Concern
Suggested response
Evidence to offer
”I am faster without it.”
That is likely true for code the person writes routinely. Suggest trying it on the work they tend to avoid: legacy files, unfamiliar services, or test scaffolding, where the leverage is highest.
Time one tedious task both ways and compare.
”I do not trust AI to touch production code.”
Agree that no change should land unread. Plan mode combined with normal diff review means nothing is applied that the engineer has not inspected, the same standard as any pull request.
Demonstrate plan mode on a real file.
”It will make junior engineers weaker.”
Used well, it is an effective explainer. Encourage junior engineers to ask Claude to explain a file and its call sites before asking it to change anything.
Run “Explain @file and where it is called from” together.
”I tried it once and it hallucinated.”
This is usually a context problem rather than a model problem. @-mentioning the relevant files, running
/init
, and providing the actual error output typically resolves it.
Re-run their original prompt with proper
@
-context.
”We do not have time to learn another tool.”
Claude Code is a terminal command rather than a platform. If it does not return value within the first session, it is reasonable to set it aside.
A two-minute install followed by one real bug.
​
Quick-reference sheet
The techniques below are the ones that most reliably move someone from a first trial to daily use. Pin this table in a channel or share it on its own.
Technique
How to apply it
Provide the right context
Use
@file
or
@directory/
references, or paste the error or log output directly. Supplying relevant context is more effective than elaborate prompting.
Review the plan before the edit
Press
Shift+Tab
to enter plan mode. Claude will describe the intended changes for your approval before executing them.
Teach it your repository
Run
/init
to generate a
CLAUDE.md
file, then add your conventions, test commands, and any directories that should not be modified. See
Memory
.
Reuse a workflow
Save a
SKILL.md
file in
.claude/skills/<name>/
to create a
/name
skill that the entire team can use. See
Skills
.
Stay informed during long tasks
Configure a Stop hook to receive a desktop notification when a long-running task completes. See
Hooks
.
Recover from an incorrect result
Rather than rephrasing the request, paste the failing test or stack trace back to Claude and ask it to address that specific failure.
Keep edits surgical
Ask for a diff, or specify “only change X.” Claude respects scope when scope is stated.
Claude Code is updated frequently. Verify version-specific details against the
documentation home page
before distributing this material internally.
Was this page helpful?
Yes
No
Communications kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/champion-kit" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Zero data retention</title>
  <link>https://code.claude.com/docs/en/zero-data-retention</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/zero-data-retention</guid>
  <pubDate>Mon, 05 Feb 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Zero data retention
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Zero data retention
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Zero Data Retention (ZDR) is available for Claude Code when used through Claude for Enterprise. When ZDR is enabled, prompts and model responses generated during Claude Code sessions are processed in real time and not stored by Anthropic after the response is returned, except where needed to comply with law or combat misuse.
ZDR on Claude for Enterprise gives enterprise customers the ability to use Claude Code with zero data retention and access administrative capabilities:
Cost controls per user
Analytics
dashboard
Server-managed settings
Audit logs
ZDR for Claude Code on Claude for Enterprise applies only to Anthropic’s direct platform. For Claude deployments on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry, refer to those platforms’ data retention policies.
​
ZDR scope
ZDR covers Claude Code inference on Claude for Enterprise.
ZDR is enabled on a per-organization basis. Each new organization requires ZDR to be enabled separately by your Anthropic account team. ZDR does not automatically apply to new organizations created under the same account. Contact your account team to enable ZDR for any new organizations.
​
What ZDR covers
ZDR covers model inference calls made through Claude Code on Claude for Enterprise. When you use Claude Code in your terminal, the prompts you send and the responses Claude generates are not retained by Anthropic. This applies regardless of which Claude model is used.
​
What ZDR does not cover
ZDR does not extend to the following, even for organizations with ZDR enabled. These features follow
standard data retention policies
:
Feature
Details
Chat on claude.ai
Chat conversations through the Claude for Enterprise web interface are not covered by ZDR.
Cowork
Cowork sessions are not covered by ZDR.
Claude Code Analytics
Does not store prompts or model responses, but collects productivity metadata such as account emails and usage statistics. Contribution metrics are not available for ZDR organizations; the
analytics dashboard
shows usage metrics only.
User and seat management
Administrative data such as account emails and seat assignments is retained under standard policies.
Third-party integrations
Data processed by third-party tools, MCP servers, or other external integrations is not covered by ZDR. Review those services’ data handling practices independently.
​
Features disabled under ZDR
When ZDR is enabled for a Claude Code organization on Claude for Enterprise, certain features that require storing prompts or completions are automatically disabled at the backend level:
Feature
Reason
Claude Code on the Web
Requires server-side storage of conversation history.
Remote sessions
from the Desktop app
Requires persistent session data that includes prompts and completions.
Feedback submission (
/feedback
)
Submitting feedback sends conversation data to Anthropic.
These features are blocked in the backend regardless of client-side display. If you see a disabled feature in the Claude Code terminal during startup, attempting to use it returns an error indicating the organization’s policies do not allow that action.
Future features may also be disabled if they require storing prompts or completions.
​
Data retention for policy violations
Even with ZDR enabled, Anthropic may retain data where required by law or to address Usage Policy violations. If a session is flagged for a policy violation, Anthropic may retain the associated inputs and outputs for up to 2 years, consistent with Anthropic’s standard ZDR policy.
​
Request ZDR
To request ZDR for Claude Code on Claude for Enterprise,
contact sales
or your Anthropic account team. Your account team will submit the request internally, and Anthropic will review and enable ZDR on your organization after confirming eligibility. All enablement actions are audit-logged.
If you are currently using ZDR for Claude Code via pay-as-you-go API keys, you can transition to Claude for Enterprise to gain access to administrative features while maintaining ZDR for Claude Code. Contact your account team to coordinate the migration.
Was this page helpful?
Yes
No
Data usage
Communications kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/zero-data-retention" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Zero data retention
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Security and data
Zero data retention
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Zero Data Retention (ZDR) is available for Claude Code when used through Claude for Enterprise. When ZDR is enabled, prompts and model responses generated during Claude Code sessions are processed in real time and not stored by Anthropic after the response is returned, except where needed to comply with law or combat misuse.
ZDR on Claude for Enterprise gives enterprise customers the ability to use Claude Code with zero data retention and access administrative capabilities:
Cost controls per user
Analytics
dashboard
Server-managed settings
Audit logs
ZDR for Claude Code on Claude for Enterprise applies only to Anthropic’s direct platform. For Claude deployments on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry, refer to those platforms’ data retention policies.
​
ZDR scope
ZDR covers Claude Code inference on Claude for Enterprise.
ZDR is enabled on a per-organization basis. Each new organization requires ZDR to be enabled separately by your Anthropic account team. ZDR does not automatically apply to new organizations created under the same account. Contact your account team to enable ZDR for any new organizations.
​
What ZDR covers
ZDR covers model inference calls made through Claude Code on Claude for Enterprise. When you use Claude Code in your terminal, the prompts you send and the responses Claude generates are not retained by Anthropic. This applies regardless of which Claude model is used.
​
What ZDR does not cover
ZDR does not extend to the following, even for organizations with ZDR enabled. These features follow
standard data retention policies
:
Feature
Details
Chat on claude.ai
Chat conversations through the Claude for Enterprise web interface are not covered by ZDR.
Cowork
Cowork sessions are not covered by ZDR.
Claude Code Analytics
Does not store prompts or model responses, but collects productivity metadata such as account emails and usage statistics. Contribution metrics are not available for ZDR organizations; the
analytics dashboard
shows usage metrics only.
User and seat management
Administrative data such as account emails and seat assignments is retained under standard policies.
Third-party integrations
Data processed by third-party tools, MCP servers, or other external integrations is not covered by ZDR. Review those services’ data handling practices independently.
​
Features disabled under ZDR
When ZDR is enabled for a Claude Code organization on Claude for Enterprise, certain features that require storing prompts or completions are automatically disabled at the backend level:
Feature
Reason
Claude Code on the Web
Requires server-side storage of conversation history.
Remote sessions
from the Desktop app
Requires persistent session data that includes prompts and completions.
Feedback submission (
/feedback
)
Submitting feedback sends conversation data to Anthropic.
These features are blocked in the backend regardless of client-side display. If you see a disabled feature in the Claude Code terminal during startup, attempting to use it returns an error indicating the organization’s policies do not allow that action.
Future features may also be disabled if they require storing prompts or completions.
​
Data retention for policy violations
Even with ZDR enabled, Anthropic may retain data where required by law or to address Usage Policy violations. If a session is flagged for a policy violation, Anthropic may retain the associated inputs and outputs for up to 2 years, consistent with Anthropic’s standard ZDR policy.
​
Request ZDR
To request ZDR for Claude Code on Claude for Enterprise,
contact sales
or your Anthropic account team. Your account team will submit the request internally, and Anthropic will review and enable ZDR on your organization after confirming eligibility. All enablement actions are audit-logged.
If you are currently using ZDR for Claude Code via pay-as-you-go API keys, you can transition to Claude for Enterprise to gain access to administrative features while maintaining ZDR for Claude Code. Contact your account team to coordinate the migration.
Was this page helpful?
Yes
No
Data usage
Communications kit
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/zero-data-retention" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Use Claude Code on the web</title>
  <link>https://code.claude.com/docs/en/claude-code-on-the-web</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/claude-code-on-the-web</guid>
  <pubDate>Sun, 04 Feb 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Use Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Use Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.
Claude Code on the web runs tasks on Anthropic-managed cloud infrastructure at
claude.ai/code
. Sessions persist even if you close your browser, and you can monitor them from the Claude mobile app.
New to Claude Code on the web? Start with
Get started
to connect your GitHub account and submit your first task.
This page covers:
GitHub authentication options
: two ways to connect GitHub
The cloud environment
: what config carries over, what tools are installed, and how to configure environments
Setup scripts
and dependency management
Network access
: levels, proxies, and the default allowlist
Move tasks between web and terminal
with
--remote
and
--teleport
Work with sessions
: reviewing, sharing, archiving, deleting
Auto-fix pull requests
: respond automatically to CI failures and review comments
Security and isolation
: how sessions are isolated
Limitations
: rate limits and platform restrictions
​
GitHub authentication options
Cloud sessions need access to your GitHub repositories to clone code and push branches. You can grant access in two ways:
Method
How it works
Best for
GitHub App
Authorize the Claude GitHub App during
web onboarding
.
Browser onboarding; teams that want
Auto-fix
/web-setup
Run
/web-setup
in your terminal to sync your local
gh
CLI token to your Claude account.
Individual developers who already use
gh
With either method, a cloud session can access any repository the connecting GitHub account can see, not just the repositories the Claude GitHub App is installed on. App installation enables PR webhooks for
Auto-fix
; it is not a session-level access control. To restrict which repositories your team can reach from cloud sessions, restrict access on GitHub itself, for example by limiting team or repository membership for the connected GitHub accounts.
Either method works.
/schedule
checks for either form of access and prompts you to run
/web-setup
if neither is configured. See
Connect from your terminal
for the
/web-setup
walkthrough.
The GitHub App is required for
Auto-fix
, which uses the App to receive PR webhooks. If you connect with
/web-setup
and later want Auto-fix, install the App on those repositories.
Team and Enterprise admins can disable
/web-setup
with the Quick web setup toggle at
claude.ai/admin-settings/claude-code
.
Organizations with
Zero Data Retention
enabled cannot use
/web-setup
or other cloud session features.
​
The cloud environment
Each session runs in a fresh Anthropic-managed VM with your repository cloned. This section covers what’s available when a session starts and how to customize it.
​
What’s available in cloud sessions
Cloud sessions start from a fresh clone of your repository. Anything committed to the repo is available. Anything you’ve installed or configured only on your own machine is not.
Available in cloud sessions
Why
Your repo’s
CLAUDE.md
Yes
Part of the clone
Your repo’s
.claude/settings.json
hooks
Yes
Part of the clone
Your repo’s
.mcp.json
MCP servers
Yes
Part of the clone
Your repo’s
.claude/rules/
Yes
Part of the clone
Your repo’s
.claude/skills/
,
.claude/agents/
,
.claude/commands/
Yes
Part of the clone
Plugins declared in
.claude/settings.json
Yes
Installed at session start from the
marketplace
you declared. Requires network access to reach the marketplace source
Your user
~/.claude/CLAUDE.md
No
Lives on your machine, not in the repo
Plugins enabled only in your user settings
No
User-scoped
enabledPlugins
lives in
~/.claude/settings.json
. Declare them in the repo’s
.claude/settings.json
instead
MCP servers you added with
claude mcp add
No
Those write to your local user config, not the repo. Declare the server in
.mcp.json
instead
Static API tokens and credentials
No
No dedicated secrets store exists yet. See below
Interactive auth like AWS SSO
No
Not supported. SSO requires browser-based login that can’t run in a cloud session
To make configuration available in cloud sessions, commit it to the repo. A dedicated secrets store is not yet available. Both environment variables and setup scripts are stored in the environment configuration, visible to anyone who can edit that environment. If you need secrets in a cloud session, add them as environment variables with that visibility in mind.
​
Installed tools
Cloud sessions come with common language runtimes, build tools, and databases pre-installed. The table below summarizes what’s included by category.
Category
Included
Python
Python 3.x with pip, poetry, uv, black, mypy, pytest, ruff
Node.js
20, 21, and 22 via nvm, with npm, yarn, pnpm, bun¹, eslint, prettier, chromedriver
Ruby
3.1, 3.2, 3.3 with gem, bundler, rbenv
PHP
8.4 with Composer
Java
OpenJDK 21 with Maven and Gradle
Go
latest stable with module support
Rust
rustc and cargo
C/C++
GCC, Clang, cmake, ninja, conan
Docker
docker, dockerd, docker compose
Databases
PostgreSQL 16, Redis 7.0
Utilities
git, jq, yq, ripgrep, tmux, vim, nano
¹ Bun is installed but has known
proxy compatibility issues
for package fetching.
For exact versions, ask Claude to run
check-tools
in a cloud session. This command only exists in cloud sessions.
​
Work with GitHub issues and pull requests
Cloud sessions include built-in GitHub tools that let Claude read issues, list pull requests, fetch diffs, and post comments without any setup. These tools authenticate through the
GitHub proxy
using whichever method you configured under
GitHub authentication options
, so your token never enters the container.
The
gh
CLI is not pre-installed. If you need a
gh
command the built-in tools don’t cover, like
gh release
or
gh workflow run
, install and authenticate it yourself:
1
Install gh in your setup script
Add
apt update && apt install -y gh
to your
setup script
.
2
Provide a token
Add a
GH_TOKEN
environment variable to your
environment settings
with a GitHub personal access token.
gh
reads
GH_TOKEN
automatically, so no
gh auth login
step is needed.
​
Link artifacts back to the session
Each cloud session has a transcript URL on claude.ai, and the session can read its own ID from the
CLAUDE_CODE_REMOTE_SESSION_ID
environment variable. Use this to put a traceable link in PR bodies, commit messages, Slack posts, or generated reports so a reviewer can open the run that produced them.
The variable’s value uses a
cse_
prefix, while the transcript URL path takes the same ID with a
session_
prefix. Substitute the prefix when building the link. The following command prints the URL:
echo
"https://claude.ai/code/${
CLAUDE_CODE_REMOTE_SESSION_ID
/#
cse_
/
session_
}"
​
Run tests, start services, and add packages
Claude runs tests as part of working on a task. Ask for it in your prompt, like “fix the failing tests in
tests/
” or “run pytest after each change.” Test runners like pytest, jest, and cargo test work out of the box since they’re pre-installed.
PostgreSQL and Redis are pre-installed but not running by default. Ask Claude to start each one during the session:
service
postgresql
start
service
redis-server
start
Docker is available for running containerized services. Ask Claude to run
docker compose up
to start your project’s services. Network access to pull images follows your environment’s
access level
, and the
Trusted defaults
include Docker Hub and other common registries.
If your images are large or slow to pull, add
docker compose pull
or
docker compose build
to your
setup script
. The pulled images are saved in the
cached environment
, so each new session has them on disk. The cache stores files only, not running processes, so Claude still starts the containers each session.
To add packages that aren’t pre-installed, use a
setup script
. The script’s output is
cached
, so packages you install there are available at the start of every session without reinstalling each time. You can also ask Claude to install packages mid-session, but those installs don’t carry over to other sessions.
​
Resource limits
Cloud sessions run with approximate resource ceilings that may change over time:
4 vCPUs
16 GB of RAM
30 GB of disk
Tasks requiring significantly more memory, such as large build jobs or memory-intensive tests, may fail or be terminated. For workloads beyond these limits, use
Remote Control
to run Claude Code on your own hardware.
​
Configure your environment
Environments control
network access
, environment variables, and the
setup script
that runs before a session starts. See
Installed tools
for what’s available without any configuration. You can manage environments from the web interface or the terminal:
Action
How
Add an environment
Select the current environment to open the selector, then select
Add environment
. The dialog includes name, network access level, environment variables, and setup script.
Edit an environment
Select the cloud icon showing the current environment’s name to open the selector, hover over an environment, and click the settings icon that appears on the right.
Archive an environment
Open the environment for editing and select
Archive
. Archived environments are hidden from the selector but existing sessions keep running.
Set the default for
--remote
Run
/remote-env
in your terminal. If you have a single environment, this command shows your current configuration.
/remote-env
only selects the default; add, edit, and archive environments from the web interface.
Environment variables use
.env
format with one
KEY=value
pair per line. Don’t wrap values in quotes, since quotes are stored as part of the value.
NODE_ENV=development
LOG_LEVEL=debug
DATABASE_URL=postgres://localhost:5432/myapp
​
Setup scripts
A setup script is a Bash script that runs when a new cloud session starts, before Claude Code launches. Use setup scripts to install dependencies, configure tools, or fetch anything the session needs that isn’t pre-installed.
Scripts run as root on Ubuntu 24.04, so
apt install
and most language package managers work.
To add a setup script, open the environment settings dialog and enter your script in the
Setup script
field.
This example installs the
gh
CLI, which isn’t pre-installed:
#!/bin/bash
apt
update
&&
apt
install
-y
gh
If the script exits non-zero, the session fails to start. Append
|| true
to non-critical commands to avoid blocking the session on an intermittent install failure.
Keep the script’s total runtime under roughly five minutes so the
environment cache
can build. Run independent installs in parallel with
&
and
wait
. If a single download won’t fit in the five-minute limit, move it to a
SessionStart hook
that launches it in the background.
Setup scripts that install packages need network access to reach registries. The default
Trusted
network access allows connections to
common package registries
including npm, PyPI, RubyGems, and crates.io. Scripts will fail to install packages if your environment uses
None
network access.
​
Environment caching
The setup script runs the first time you start a session in an environment. After it completes, Anthropic snapshots the filesystem and reuses that snapshot as the starting point for later sessions. New sessions start with your dependencies, tools, and Docker images already on disk, and the setup script step is skipped. This keeps startup fast even when the script installs large toolchains or pulls container images.
The cache captures files, not running processes. Anything the setup script writes to disk carries over. Services or containers it starts do not, so start those per session by asking Claude or with a
SessionStart hook
.
The setup script runs again to rebuild the cache when you change the environment’s setup script or allowed network hosts, and when the cache reaches its expiry after roughly seven days. Resuming an existing session never re-runs the setup script.
You don’t need to enable caching or manage snapshots yourself.
​
Setup scripts vs. SessionStart hooks
Use a setup script to install things the cloud needs but your laptop already has, like a language runtime or CLI tool. Use a
SessionStart hook
for project setup that should run everywhere, cloud and local, like
npm install
.
Both run at the start of a session, but they belong to different places:
Setup scripts
SessionStart hooks
Attached to
The cloud environment
Your repository
Configured in
Cloud environment UI
.claude/settings.json
in your repo
Runs
Before Claude Code launches, when no
cached environment
is available
After Claude Code launches, on every session including resumed
Scope
Cloud environments only
Both local and cloud
SessionStart hooks can also be defined in your user-level
~/.claude/settings.json
locally, but user-level settings don’t carry over to cloud sessions. In the cloud, only hooks committed to the repo run.
​
Install dependencies with a SessionStart hook
To install dependencies only in cloud sessions, add a SessionStart hook to your repo’s
.claude/settings.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"matcher"
:
"startup|resume"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/scripts/install_pkgs.sh"
}
]
}
]
}
}
Create the script at
scripts/install_pkgs.sh
and make it executable with
chmod +x
. The
CLAUDE_CODE_REMOTE
environment variable is set to
true
in cloud sessions, so you can use it to skip local execution:
#!/bin/bash
if
[
"
$CLAUDE_CODE_REMOTE
"
!=
"true"
];
then
exit
0
fi
npm
install
pip
install
-r
requirements.txt
exit
0
SessionStart hooks have some limitations in cloud sessions:
No cloud-only scoping
: hooks run in both local and cloud sessions. To skip local execution, check the
CLAUDE_CODE_REMOTE
environment variable as shown above.
Requires network access
: install commands need to reach package registries. If your environment uses
None
network access, these hooks fail. The
default allowlist
under
Trusted
covers npm, PyPI, RubyGems, and crates.io.
Proxy compatibility
: all outbound traffic passes through a
security proxy
. Some package managers don’t work correctly with this proxy. Bun is a known example.
Adds startup latency
: hooks run each time a session starts or resumes, unlike setup scripts which benefit from
environment caching
. Keep install scripts fast by checking whether dependencies are already present before reinstalling.
To persist environment variables for subsequent Bash commands, write to the file at
$CLAUDE_ENV_FILE
. See
SessionStart hooks
for details.
Replacing the base image with your own Docker image is not yet supported. Use a setup script to install what you need on top of the
provided image
, or run your image as a container alongside Claude with
docker compose
.
​
Network access
Network access controls outbound connections from the cloud environment. Each environment specifies one access level, and you can extend it with custom allowed domains. The default is
Trusted
, which allows package registries and other
allowlisted domains
.
To change an environment’s network access,
open it for editing
and use the
Network access
selector in the dialog. There is no separate Environments page. The cloud icon appears wherever you start a cloud session or configure a
routine
.
MCP connector traffic is routed through Anthropic’s servers, so the connectors you enable on a session or routine work without adding their hosts to
Allowed domains
. Connectors are configured per session or per routine; remove any you don’t need to limit which tools Claude can reach. This relies on the same Anthropic-bound channel noted under
Security and isolation
.
​
Access levels
Choose an access level when you create or edit an environment:
Level
Outbound connections
None
No outbound network access
Trusted
Allowlisted domains
only: package registries, GitHub, cloud SDKs
Full
Any domain
Custom
Your own allowlist, optionally including the defaults
GitHub operations use a
separate proxy
that is independent of this setting.
​
Allow specific domains
To allow domains that aren’t in the Trusted list, select
Custom
in the environment’s network access settings. An
Allowed domains
field appears. Enter one domain per line:
api.example.com
*.internal.example.com
registry.example.com
Use
*.
for wildcard subdomain matching. Check
Also include default list of common package managers
to keep the
Trusted domains
alongside your custom entries, or leave it unchecked to allow only what you list.
​
GitHub proxy
For security, all GitHub operations go through a dedicated proxy service that transparently handles all git interactions. Inside the sandbox, the git client authenticates using a custom-built scoped credential. This proxy:
Manages GitHub authentication securely: the git client uses a scoped credential inside the sandbox, which the proxy verifies and translates to your actual GitHub authentication token
Restricts git push operations to the current working branch for safety
Enables cloning, fetching, and PR operations while maintaining security boundaries
​
Security proxy
Environments run behind an HTTP/HTTPS network proxy for security and abuse prevention purposes. All outbound internet traffic passes through this proxy, which provides:
Protection against malicious requests
Rate limiting and abuse prevention
Content filtering for enhanced security
​
Default allowed domains
When using
Trusted
network access, the following domains are allowed by default. Domains marked with
*
indicate wildcard subdomain matching, so
*.gcr.io
allows any subdomain of
gcr.io
.
Anthropic services
api.anthropic.com
statsig.anthropic.com
docs.claude.com
platform.claude.com
code.claude.com
claude.ai
Version control
github.com
www.github.com
api.github.com
npm.pkg.github.com
raw.githubusercontent.com
pkg-npm.githubusercontent.com
objects.githubusercontent.com
release-assets.githubusercontent.com
codeload.github.com
avatars.githubusercontent.com
camo.githubusercontent.com
gist.github.com
gitlab.com
www.gitlab.com
registry.gitlab.com
bitbucket.org
www.bitbucket.org
api.bitbucket.org
Container registries
registry-1.docker.io
auth.docker.io
index.docker.io
hub.docker.com
www.docker.com
production.cloudflare.docker.com
download.docker.com
gcr.io
*.gcr.io
ghcr.io
mcr.microsoft.com
*.data.mcr.microsoft.com
public.ecr.aws
Cloud platforms
cloud.google.com
accounts.google.com
gcloud.google.com
*.googleapis.com
storage.googleapis.com
compute.googleapis.com
container.googleapis.com
azure.com
portal.azure.com
microsoft.com
www.microsoft.com
*.microsoftonline.com
packages.microsoft.com
dotnet.microsoft.com
dot.net
visualstudio.com
dev.azure.com
*.amazonaws.com
*.api.aws
oracle.com
www.oracle.com
java.com
www.java.com
java.net
www.java.net
download.oracle.com
yum.oracle.com
JavaScript and Node package managers
registry.npmjs.org
www.npmjs.com
www.npmjs.org
npmjs.com
npmjs.org
yarnpkg.com
registry.yarnpkg.com
Python package managers
pypi.org
www.pypi.org
files.pythonhosted.org
pythonhosted.org
test.pypi.org
pypi.python.org
pypa.io
www.pypa.io
Ruby package managers
rubygems.org
www.rubygems.org
api.rubygems.org
index.rubygems.org
ruby-lang.org
www.ruby-lang.org
rubyforge.org
www.rubyforge.org
rubyonrails.org
www.rubyonrails.org
rvm.io
get.rvm.io
Rust package managers
crates.io
www.crates.io
index.crates.io
static.crates.io
rustup.rs
static.rust-lang.org
www.rust-lang.org
Go package managers
proxy.golang.org
sum.golang.org
index.golang.org
golang.org
www.golang.org
goproxy.io
pkg.go.dev
JVM package managers
maven.org
repo.maven.org
central.maven.org
repo1.maven.org
repo.maven.apache.org
jcenter.bintray.com
gradle.org
www.gradle.org
services.gradle.org
plugins.gradle.org
kotlinlang.org
www.kotlinlang.org
spring.io
repo.spring.io
Other package managers
packagist.org (PHP Composer)
www.packagist.org
repo.packagist.org
nuget.org (.NET NuGet)
www.nuget.org
api.nuget.org
pub.dev (Dart/Flutter)
api.pub.dev
hex.pm (Elixir/Erlang)
www.hex.pm
cpan.org (Perl CPAN)
www.cpan.org
metacpan.org
www.metacpan.org
api.metacpan.org
cocoapods.org (iOS/macOS)
www.cocoapods.org
cdn.cocoapods.org
haskell.org
www.haskell.org
hackage.haskell.org
swift.org
www.swift.org
Linux distributions
archive.ubuntu.com
security.ubuntu.com
ubuntu.com
www.ubuntu.com
*.ubuntu.com
ppa.launchpad.net
launchpad.net
www.launchpad.net
*.nixos.org
Development tools and platforms
dl.k8s.io (Kubernetes)
pkgs.k8s.io
k8s.io
www.k8s.io
releases.hashicorp.com (HashiCorp)
apt.releases.hashicorp.com
rpm.releases.hashicorp.com
archive.releases.hashicorp.com
hashicorp.com
www.hashicorp.com
repo.anaconda.com (Anaconda/Conda)
conda.anaconda.org
anaconda.org
www.anaconda.com
anaconda.com
continuum.io
apache.org (Apache)
www.apache.org
archive.apache.org
downloads.apache.org
eclipse.org (Eclipse)
www.eclipse.org
download.eclipse.org
nodejs.org (Node.js)
www.nodejs.org
developer.apple.com
developer.android.com
pkg.stainless.com
binaries.prisma.sh
Cloud services and monitoring
statsig.com
www.statsig.com
api.statsig.com
sentry.io
*.sentry.io
downloads.sentry-cdn.com
http-intake.logs.datadoghq.com
*.datadoghq.com
*.datadoghq.eu
api.honeycomb.io
Content delivery and mirrors
sourceforge.net
*.sourceforge.net
packagecloud.io
*.packagecloud.io
fonts.googleapis.com
fonts.gstatic.com
Schema and configuration
json-schema.org
www.json-schema.org
json.schemastore.org
www.schemastore.org
Model Context Protocol
*.modelcontextprotocol.io
​
Move tasks between web and terminal
These workflows require the
Claude Code CLI
signed in to the same claude.ai account. You can start new cloud sessions from your terminal, or pull cloud sessions into your terminal to continue locally. Cloud sessions persist even if you close your laptop, and you can monitor them from anywhere including the Claude mobile app.
From the CLI, session handoff is one-way: you can pull cloud sessions into your terminal with
--teleport
, but you can’t push an existing terminal session to the web. The
--remote
flag creates a new cloud session for your current repository. The
Desktop app
provides a Continue in menu that can send a local session to the web.
​
From terminal to web
Start a cloud session from the command line with the
--remote
flag:
claude
--remote
"Fix the authentication bug in src/auth/login.ts"
This creates a new cloud session on claude.ai. The session clones your current directory’s GitHub remote at your current branch, so push first if you have local commits, since the VM clones from GitHub rather than your machine.
--remote
works with a single repository at a time. The task runs in the cloud while you continue working locally.
--remote
creates cloud sessions.
--remote-control
is unrelated: it exposes a local CLI session for monitoring from the web. See
Remote Control
.
Use
/tasks
in the Claude Code CLI to check progress, or open the session on claude.ai or the Claude mobile app to interact directly. From there you can steer Claude, provide feedback, or answer questions just like any other conversation.
​
Tips for cloud tasks
Plan locally, execute remotely
: for complex tasks, start Claude in plan mode to collaborate on the approach, then send work to the cloud:
claude
--permission-mode
plan
In plan mode, Claude reads files, runs commands to explore, and proposes a plan without editing source code. Once you’re satisfied, save the plan to the repo, commit, and push so the cloud VM can clone it. Then start a cloud session for autonomous execution:
claude
--remote
"Execute the migration plan in docs/migration-plan.md"
This pattern gives you control over the strategy while letting Claude execute autonomously in the cloud.
Plan in the cloud with ultraplan
: to draft and review the plan itself in a web session, use
ultraplan
. Claude generates the plan on Claude Code on the web while you keep working, then you comment on sections in your browser and choose to execute remotely or send the plan back to your terminal.
Run tasks in parallel
: each
--remote
command creates its own cloud session that runs independently. You can start multiple tasks and they’ll all run simultaneously in separate sessions:
claude
--remote
"Fix the flaky test in auth.spec.ts"
claude
--remote
"Update the API documentation"
claude
--remote
"Refactor the logger to use structured output"
Monitor all sessions with
/tasks
in the Claude Code CLI. When a session completes, you can create a PR from the web interface or
teleport
the session to your terminal to continue working.
​
Send local repositories without GitHub
When you run
claude --remote
from a repository that isn’t connected to GitHub, Claude Code bundles your local repository and uploads it directly to the cloud session. The bundle includes your full repository history across all branches, plus any uncommitted changes to tracked files.
This fallback activates automatically when GitHub access isn’t available. To force it even when GitHub is connected, set
CCR_FORCE_BUNDLE=1
:
CCR_FORCE_BUNDLE
=
1
claude
--remote
"Run the test suite and fix any failures"
Bundled repositories must meet these limits:
The directory must be a git repository with at least one commit
The bundled repository must be under 100 MB. Larger repositories fall back to bundling only the current branch, then to a single squashed snapshot of the working tree, and fail only if the snapshot is still too large
Untracked files are not included; run
git add
on files you want the cloud session to see
Sessions created from a bundle can’t push back to a remote unless you also have
GitHub authentication
configured
​
From web to terminal
Pull a cloud session into your terminal using any of these:
Using
--teleport
: from the command line, run
claude --teleport
for an interactive session picker, or
claude --teleport <session-id>
to resume a specific session directly. If you have uncommitted changes, you’ll be prompted to stash them first.
Using
/teleport
: inside an existing CLI session, run
/teleport
(or
/tp
) to open the same session picker without restarting Claude Code.
From
/tasks
: run
/tasks
to see your background sessions, then press
t
to teleport into one
From the web interface
: select
Open in CLI
to copy a command you can paste into your terminal
When you teleport a session, Claude verifies you’re in the correct repository, fetches and checks out the branch from the cloud session, and loads the full conversation history into your terminal.
--teleport
is distinct from
--resume
.
--resume
reopens a conversation from this machine’s local history and doesn’t list cloud sessions;
--teleport
pulls a cloud session and its branch.
​
Teleport requirements
Teleport checks these requirements before resuming a session. If any requirement isn’t met, you’ll see an error or be prompted to resolve the issue.
Requirement
Details
Clean git state
Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed.
Correct repository
You must run
--teleport
from a checkout of the same repository, not a fork.
Branch available
The branch from the cloud session must have been pushed to the remote. Teleport automatically fetches and checks it out.
Same account
You must be authenticated to the same claude.ai account used in the cloud session.
​
--teleport
is unavailable
Teleport requires claude.ai subscription authentication. If you’re authenticated via API key, Bedrock, Vertex AI, or Microsoft Foundry, run
/login
to sign in with your claude.ai account instead. If you’re already signed in via claude.ai and
--teleport
is still unavailable, your organization may have disabled cloud sessions.
​
Work with sessions
Sessions appear in the sidebar at claude.ai/code. From there you can review changes, share with teammates, archive finished work, or delete sessions permanently.
​
Manage context
Cloud sessions support
built-in commands
that produce text output. Commands that open an interactive terminal picker, like
/model
or
/config
, are not available.
For context management specifically:
Command
Works in cloud sessions
Notes
/compact
Yes
Summarizes the conversation to free up context. Accepts optional focus instructions like
/compact keep the test output
/context
Yes
Shows what’s currently in the context window
/clear
No
Start a new session from the sidebar instead
Auto-compaction runs automatically when the context window approaches capacity, the same as in the CLI. To trigger it earlier, set
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
in your
environment variables
. For example,
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=70
compacts at 70% capacity instead of the default ~95%. To change the effective window size for compaction calculations, use
CLAUDE_CODE_AUTO_COMPACT_WINDOW
.
Subagents
work the same way they do locally. Claude can spawn them with the Task tool to offload research or parallel work into a separate context window, keeping the main conversation lighter. Subagents defined in your repo’s
.claude/agents/
are picked up automatically.
Agent teams
are off by default but can be enabled by adding
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
to your
environment variables
.
​
Review changes
Each session shows a diff indicator with lines added and removed, like
+42 -18
. Select it to open the diff view, leave inline comments on specific lines, and send them to Claude with your next message. See
Review and iterate
for the full walkthrough including PR creation. To have Claude monitor the PR for CI failures and review comments automatically, see
Auto-fix pull requests
.
​
Share sessions
To share a session, toggle its visibility according to the account types below. After that, share the session link as-is. Recipients see the latest state when they open the link, but their view doesn’t update in real time.
​
Share from an Enterprise or Team account
For Enterprise and Team accounts, the two visibility options are
Private
and
Team
. Team visibility makes the session visible to other members of your claude.ai organization. Repository access verification is enabled by default, based on the GitHub account connected to the recipient’s account. Your account’s display name is visible to all recipients with access.
Claude in Slack
sessions are automatically shared with Team visibility.
​
Share from a Max or Pro account
For Max and Pro accounts, the two visibility options are
Private
and
Public
. Public visibility makes the session visible to any user logged into claude.ai.
Check your session for sensitive content before sharing. Sessions may contain code and credentials from private GitHub repositories. Repository access verification is not enabled by default.
To require recipients to have repository access, or to hide your name from shared sessions, go to Settings > Claude Code > Sharing settings.
​
Archive sessions
You can archive sessions to keep your session list organized. Archived sessions are hidden from the default session list but can be viewed by filtering for archived sessions.
To archive a session, hover over the session in the sidebar and select the archive icon.
​
Delete sessions
Deleting a session permanently removes the session and its data. This action cannot be undone. You can delete a session in two ways:
From the sidebar
: filter for archived sessions, then hover over the session you want to delete and select the delete icon
From the session menu
: open a session, select the dropdown next to the session title, and select
Delete
You will be asked to confirm before a session is deleted.
​
Auto-fix pull requests
Claude can watch a pull request and automatically respond to CI failures and review comments. Claude subscribes to GitHub activity on the PR, and when a check fails or a reviewer leaves a comment, Claude investigates and pushes a fix if one is clear.
Auto-fix requires the Claude GitHub App to be installed on your repository. If you haven’t already, install it from the
GitHub App page
or when prompted during
setup
.
There are a few ways to turn on auto-fix depending on where the PR came from and what device you’re using:
PRs created in Claude Code on the web
: open the CI status bar and select
Auto-fix
From your terminal
: run
/autofix-pr
while on the PR’s branch. Claude Code detects the open PR with
gh
, spawns a web session, and turns on auto-fix in one step
From the mobile app
: tell Claude to auto-fix the PR, for example “watch this PR and fix any CI failures or review comments”
Any existing PR
: paste the PR URL into a session and tell Claude to auto-fix it
Auto-fix is a per-PR toggle. To stop monitoring, open the CI status bar in the web session and clear the
Auto-fix
toggle, or tell Claude to stop watching the PR.
​
How Claude responds to PR activity
When auto-fix is active, Claude receives GitHub events for the PR including new review comments and CI check failures. For each event, Claude investigates and decides how to proceed:
Clear fixes
: if Claude is confident in a fix and it doesn’t conflict with earlier instructions, Claude makes the change, pushes it, and explains what was done in the session
Ambiguous requests
: if a reviewer’s comment could be interpreted multiple ways or involves something architecturally significant, Claude asks you before acting
Duplicate or no-action events
: if an event is a duplicate or requires no change, Claude notes it in the session and moves on
Claude may reply to review comment threads on GitHub as part of resolving them. These replies are posted using your GitHub account, so they appear under your username, but each reply is labeled as coming from Claude Code so reviewers know it was written by the agent and not by you directly.
If your repository uses comment-triggered automation such as Atlantis, Terraform Cloud, or custom GitHub Actions that run on
issue_comment
events, be aware that Claude can reply on your behalf, which can trigger those workflows. Review your repository’s automation before enabling auto-fix, and consider disabling auto-fix for repositories where a PR comment can deploy infrastructure or run privileged operations.
​
Security and isolation
Each cloud session is separated from your machine and from other sessions through several layers:
Isolated virtual machines
: each session runs in an isolated, Anthropic-managed VM
Network access controls
: network access is limited by default, and can be disabled. When running with network access disabled, Claude Code can still communicate with the Anthropic API, which may allow data to exit the VM.
Credential protection
: sensitive credentials such as git credentials or signing keys are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials.
Secure analysis
: code is analyzed and modified within isolated VMs before creating PRs
​
Troubleshooting
For runtime API errors that appear in the conversation such as
API Error: 500
,
529 Overloaded
,
429
, or
Prompt is too long
, see the
Error reference
. Those errors and their fixes are shared with the CLI and Desktop app. The sections below cover issues specific to cloud sessions.
​
Session creation failed
If a new session fails to start with
Session creation failed
or stalls at provisioning, Claude Code could not allocate a cloud environment.
Check
status.claude.com
for cloud session incidents
Retry after a minute, as capacity is provisioned on demand
Confirm your repository is reachable. The connecting GitHub account must have access to the repository on GitHub, either through the Claude GitHub App authorization or a
gh
token synced via
/web-setup
— installing the App on the repository is not required. See
GitHub authentication options
.
​
Remote Control session expired or access denied
--teleport
connects through the same Remote Control session infrastructure that cloud sessions use, so authentication and session-expiry errors surface with Remote Control wording. You may see
Remote Control session expired
or
Access denied
. The connection token is short-lived and scoped to your account.
Run
/login
locally to refresh your credentials, then reconnect
Confirm you are signed in to the same account that owns the session
If you see
Remote Control may not be available for this organization
, your admin has not enabled remote sessions for your plan
​
Environment expired
Cloud sessions stop after a period of inactivity and the underlying environment is reclaimed. From a local terminal, this surfaces as
Could not resume session ... its environment has expired. Creating a fresh session instead.
On the web, the session is marked expired in the session list.
Reopen the session from
claude.ai/code
to provision a fresh environment with your conversation history restored.
​
Limitations
Before relying on cloud sessions for a workflow, account for these constraints:
Rate limits
: Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel consumes more rate limits proportionately. There is no separate compute charge for the cloud VM.
Repository authentication
: you can only move sessions from web to local when you are authenticated to the same account
Platform restrictions
: repository cloning and pull request creation require GitHub. Self-hosted
GitHub Enterprise Server
instances are supported for Team and Enterprise plans. GitLab, Bitbucket, and other non-GitHub repositories can be sent to cloud sessions as a
local bundle
, but the session can’t push results back to the remote
Organization IP allowlist
: cloud sessions call the Anthropic API from Anthropic-managed infrastructure, not your network. If your organization has
IP allowlisting
enabled, every cloud session fails with an authentication error. The same applies to
Code Review
and
Routines
. Contact
Anthropic support
to exempt Anthropic-hosted services from your organization’s IP allowlist.
​
Related resources
Ultraplan
: draft a plan in a cloud session and review it in your browser
Ultrareview
: run a deep multi-agent code review in a cloud sandbox
Routines
: automate work on a schedule, via API call, or in response to GitHub events
Hooks configuration
: run scripts at session lifecycle events
Settings reference
: all configuration options
Security
: isolation guarantees and data handling
Data usage
: what Anthropic retains from cloud sessions
Was this page helpful?
Yes
No
Get started
Routines
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-code-on-the-web" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Use Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in th...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Use Claude Code on the web
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.
Claude Code on the web runs tasks on Anthropic-managed cloud infrastructure at
claude.ai/code
. Sessions persist even if you close your browser, and you can monitor them from the Claude mobile app.
New to Claude Code on the web? Start with
Get started
to connect your GitHub account and submit your first task.
This page covers:
GitHub authentication options
: two ways to connect GitHub
The cloud environment
: what config carries over, what tools are installed, and how to configure environments
Setup scripts
and dependency management
Network access
: levels, proxies, and the default allowlist
Move tasks between web and terminal
with
--remote
and
--teleport
Work with sessions
: reviewing, sharing, archiving, deleting
Auto-fix pull requests
: respond automatically to CI failures and review comments
Security and isolation
: how sessions are isolated
Limitations
: rate limits and platform restrictions
​
GitHub authentication options
Cloud sessions need access to your GitHub repositories to clone code and push branches. You can grant access in two ways:
Method
How it works
Best for
GitHub App
Authorize the Claude GitHub App during
web onboarding
.
Browser onboarding; teams that want
Auto-fix
/web-setup
Run
/web-setup
in your terminal to sync your local
gh
CLI token to your Claude account.
Individual developers who already use
gh
With either method, a cloud session can access any repository the connecting GitHub account can see, not just the repositories the Claude GitHub App is installed on. App installation enables PR webhooks for
Auto-fix
; it is not a session-level access control. To restrict which repositories your team can reach from cloud sessions, restrict access on GitHub itself, for example by limiting team or repository membership for the connected GitHub accounts.
Either method works.
/schedule
checks for either form of access and prompts you to run
/web-setup
if neither is configured. See
Connect from your terminal
for the
/web-setup
walkthrough.
The GitHub App is required for
Auto-fix
, which uses the App to receive PR webhooks. If you connect with
/web-setup
and later want Auto-fix, install the App on those repositories.
Team and Enterprise admins can disable
/web-setup
with the Quick web setup toggle at
claude.ai/admin-settings/claude-code
.
Organizations with
Zero Data Retention
enabled cannot use
/web-setup
or other cloud session features.
​
The cloud environment
Each session runs in a fresh Anthropic-managed VM with your repository cloned. This section covers what’s available when a session starts and how to customize it.
​
What’s available in cloud sessions
Cloud sessions start from a fresh clone of your repository. Anything committed to the repo is available. Anything you’ve installed or configured only on your own machine is not.
Available in cloud sessions
Why
Your repo’s
CLAUDE.md
Yes
Part of the clone
Your repo’s
.claude/settings.json
hooks
Yes
Part of the clone
Your repo’s
.mcp.json
MCP servers
Yes
Part of the clone
Your repo’s
.claude/rules/
Yes
Part of the clone
Your repo’s
.claude/skills/
,
.claude/agents/
,
.claude/commands/
Yes
Part of the clone
Plugins declared in
.claude/settings.json
Yes
Installed at session start from the
marketplace
you declared. Requires network access to reach the marketplace source
Your user
~/.claude/CLAUDE.md
No
Lives on your machine, not in the repo
Plugins enabled only in your user settings
No
User-scoped
enabledPlugins
lives in
~/.claude/settings.json
. Declare them in the repo’s
.claude/settings.json
instead
MCP servers you added with
claude mcp add
No
Those write to your local user config, not the repo. Declare the server in
.mcp.json
instead
Static API tokens and credentials
No
No dedicated secrets store exists yet. See below
Interactive auth like AWS SSO
No
Not supported. SSO requires browser-based login that can’t run in a cloud session
To make configuration available in cloud sessions, commit it to the repo. A dedicated secrets store is not yet available. Both environment variables and setup scripts are stored in the environment configuration, visible to anyone who can edit that environment. If you need secrets in a cloud session, add them as environment variables with that visibility in mind.
​
Installed tools
Cloud sessions come with common language runtimes, build tools, and databases pre-installed. The table below summarizes what’s included by category.
Category
Included
Python
Python 3.x with pip, poetry, uv, black, mypy, pytest, ruff
Node.js
20, 21, and 22 via nvm, with npm, yarn, pnpm, bun¹, eslint, prettier, chromedriver
Ruby
3.1, 3.2, 3.3 with gem, bundler, rbenv
PHP
8.4 with Composer
Java
OpenJDK 21 with Maven and Gradle
Go
latest stable with module support
Rust
rustc and cargo
C/C++
GCC, Clang, cmake, ninja, conan
Docker
docker, dockerd, docker compose
Databases
PostgreSQL 16, Redis 7.0
Utilities
git, jq, yq, ripgrep, tmux, vim, nano
¹ Bun is installed but has known
proxy compatibility issues
for package fetching.
For exact versions, ask Claude to run
check-tools
in a cloud session. This command only exists in cloud sessions.
​
Work with GitHub issues and pull requests
Cloud sessions include built-in GitHub tools that let Claude read issues, list pull requests, fetch diffs, and post comments without any setup. These tools authenticate through the
GitHub proxy
using whichever method you configured under
GitHub authentication options
, so your token never enters the container.
The
gh
CLI is not pre-installed. If you need a
gh
command the built-in tools don’t cover, like
gh release
or
gh workflow run
, install and authenticate it yourself:
1
Install gh in your setup script
Add
apt update && apt install -y gh
to your
setup script
.
2
Provide a token
Add a
GH_TOKEN
environment variable to your
environment settings
with a GitHub personal access token.
gh
reads
GH_TOKEN
automatically, so no
gh auth login
step is needed.
​
Link artifacts back to the session
Each cloud session has a transcript URL on claude.ai, and the session can read its own ID from the
CLAUDE_CODE_REMOTE_SESSION_ID
environment variable. Use this to put a traceable link in PR bodies, commit messages, Slack posts, or generated reports so a reviewer can open the run that produced them.
The variable’s value uses a
cse_
prefix, while the transcript URL path takes the same ID with a
session_
prefix. Substitute the prefix when building the link. The following command prints the URL:
echo
"https://claude.ai/code/${
CLAUDE_CODE_REMOTE_SESSION_ID
/#
cse_
/
session_
}"
​
Run tests, start services, and add packages
Claude runs tests as part of working on a task. Ask for it in your prompt, like “fix the failing tests in
tests/
” or “run pytest after each change.” Test runners like pytest, jest, and cargo test work out of the box since they’re pre-installed.
PostgreSQL and Redis are pre-installed but not running by default. Ask Claude to start each one during the session:
service
postgresql
start
service
redis-server
start
Docker is available for running containerized services. Ask Claude to run
docker compose up
to start your project’s services. Network access to pull images follows your environment’s
access level
, and the
Trusted defaults
include Docker Hub and other common registries.
If your images are large or slow to pull, add
docker compose pull
or
docker compose build
to your
setup script
. The pulled images are saved in the
cached environment
, so each new session has them on disk. The cache stores files only, not running processes, so Claude still starts the containers each session.
To add packages that aren’t pre-installed, use a
setup script
. The script’s output is
cached
, so packages you install there are available at the start of every session without reinstalling each time. You can also ask Claude to install packages mid-session, but those installs don’t carry over to other sessions.
​
Resource limits
Cloud sessions run with approximate resource ceilings that may change over time:
4 vCPUs
16 GB of RAM
30 GB of disk
Tasks requiring significantly more memory, such as large build jobs or memory-intensive tests, may fail or be terminated. For workloads beyond these limits, use
Remote Control
to run Claude Code on your own hardware.
​
Configure your environment
Environments control
network access
, environment variables, and the
setup script
that runs before a session starts. See
Installed tools
for what’s available without any configuration. You can manage environments from the web interface or the terminal:
Action
How
Add an environment
Select the current environment to open the selector, then select
Add environment
. The dialog includes name, network access level, environment variables, and setup script.
Edit an environment
Select the cloud icon showing the current environment’s name to open the selector, hover over an environment, and click the settings icon that appears on the right.
Archive an environment
Open the environment for editing and select
Archive
. Archived environments are hidden from the selector but existing sessions keep running.
Set the default for
--remote
Run
/remote-env
in your terminal. If you have a single environment, this command shows your current configuration.
/remote-env
only selects the default; add, edit, and archive environments from the web interface.
Environment variables use
.env
format with one
KEY=value
pair per line. Don’t wrap values in quotes, since quotes are stored as part of the value.
NODE_ENV=development
LOG_LEVEL=debug
DATABASE_URL=postgres://localhost:5432/myapp
​
Setup scripts
A setup script is a Bash script that runs when a new cloud session starts, before Claude Code launches. Use setup scripts to install dependencies, configure tools, or fetch anything the session needs that isn’t pre-installed.
Scripts run as root on Ubuntu 24.04, so
apt install
and most language package managers work.
To add a setup script, open the environment settings dialog and enter your script in the
Setup script
field.
This example installs the
gh
CLI, which isn’t pre-installed:
#!/bin/bash
apt
update
&&
apt
install
-y
gh
If the script exits non-zero, the session fails to start. Append
|| true
to non-critical commands to avoid blocking the session on an intermittent install failure.
Keep the script’s total runtime under roughly five minutes so the
environment cache
can build. Run independent installs in parallel with
&
and
wait
. If a single download won’t fit in the five-minute limit, move it to a
SessionStart hook
that launches it in the background.
Setup scripts that install packages need network access to reach registries. The default
Trusted
network access allows connections to
common package registries
including npm, PyPI, RubyGems, and crates.io. Scripts will fail to install packages if your environment uses
None
network access.
​
Environment caching
The setup script runs the first time you start a session in an environment. After it completes, Anthropic snapshots the filesystem and reuses that snapshot as the starting point for later sessions. New sessions start with your dependencies, tools, and Docker images already on disk, and the setup script step is skipped. This keeps startup fast even when the script installs large toolchains or pulls container images.
The cache captures files, not running processes. Anything the setup script writes to disk carries over. Services or containers it starts do not, so start those per session by asking Claude or with a
SessionStart hook
.
The setup script runs again to rebuild the cache when you change the environment’s setup script or allowed network hosts, and when the cache reaches its expiry after roughly seven days. Resuming an existing session never re-runs the setup script.
You don’t need to enable caching or manage snapshots yourself.
​
Setup scripts vs. SessionStart hooks
Use a setup script to install things the cloud needs but your laptop already has, like a language runtime or CLI tool. Use a
SessionStart hook
for project setup that should run everywhere, cloud and local, like
npm install
.
Both run at the start of a session, but they belong to different places:
Setup scripts
SessionStart hooks
Attached to
The cloud environment
Your repository
Configured in
Cloud environment UI
.claude/settings.json
in your repo
Runs
Before Claude Code launches, when no
cached environment
is available
After Claude Code launches, on every session including resumed
Scope
Cloud environments only
Both local and cloud
SessionStart hooks can also be defined in your user-level
~/.claude/settings.json
locally, but user-level settings don’t carry over to cloud sessions. In the cloud, only hooks committed to the repo run.
​
Install dependencies with a SessionStart hook
To install dependencies only in cloud sessions, add a SessionStart hook to your repo’s
.claude/settings.json
:
{
"hooks"
: {
"SessionStart"
: [
{
"matcher"
:
"startup|resume"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"
\"
$CLAUDE_PROJECT_DIR
\"
/scripts/install_pkgs.sh"
}
]
}
]
}
}
Create the script at
scripts/install_pkgs.sh
and make it executable with
chmod +x
. The
CLAUDE_CODE_REMOTE
environment variable is set to
true
in cloud sessions, so you can use it to skip local execution:
#!/bin/bash
if
[
"
$CLAUDE_CODE_REMOTE
"
!=
"true"
];
then
exit
0
fi
npm
install
pip
install
-r
requirements.txt
exit
0
SessionStart hooks have some limitations in cloud sessions:
No cloud-only scoping
: hooks run in both local and cloud sessions. To skip local execution, check the
CLAUDE_CODE_REMOTE
environment variable as shown above.
Requires network access
: install commands need to reach package registries. If your environment uses
None
network access, these hooks fail. The
default allowlist
under
Trusted
covers npm, PyPI, RubyGems, and crates.io.
Proxy compatibility
: all outbound traffic passes through a
security proxy
. Some package managers don’t work correctly with this proxy. Bun is a known example.
Adds startup latency
: hooks run each time a session starts or resumes, unlike setup scripts which benefit from
environment caching
. Keep install scripts fast by checking whether dependencies are already present before reinstalling.
To persist environment variables for subsequent Bash commands, write to the file at
$CLAUDE_ENV_FILE
. See
SessionStart hooks
for details.
Replacing the base image with your own Docker image is not yet supported. Use a setup script to install what you need on top of the
provided image
, or run your image as a container alongside Claude with
docker compose
.
​
Network access
Network access controls outbound connections from the cloud environment. Each environment specifies one access level, and you can extend it with custom allowed domains. The default is
Trusted
, which allows package registries and other
allowlisted domains
.
To change an environment’s network access,
open it for editing
and use the
Network access
selector in the dialog. There is no separate Environments page. The cloud icon appears wherever you start a cloud session or configure a
routine
.
MCP connector traffic is routed through Anthropic’s servers, so the connectors you enable on a session or routine work without adding their hosts to
Allowed domains
. Connectors are configured per session or per routine; remove any you don’t need to limit which tools Claude can reach. This relies on the same Anthropic-bound channel noted under
Security and isolation
.
​
Access levels
Choose an access level when you create or edit an environment:
Level
Outbound connections
None
No outbound network access
Trusted
Allowlisted domains
only: package registries, GitHub, cloud SDKs
Full
Any domain
Custom
Your own allowlist, optionally including the defaults
GitHub operations use a
separate proxy
that is independent of this setting.
​
Allow specific domains
To allow domains that aren’t in the Trusted list, select
Custom
in the environment’s network access settings. An
Allowed domains
field appears. Enter one domain per line:
api.example.com
*.internal.example.com
registry.example.com
Use
*.
for wildcard subdomain matching. Check
Also include default list of common package managers
to keep the
Trusted domains
alongside your custom entries, or leave it unchecked to allow only what you list.
​
GitHub proxy
For security, all GitHub operations go through a dedicated proxy service that transparently handles all git interactions. Inside the sandbox, the git client authenticates using a custom-built scoped credential. This proxy:
Manages GitHub authentication securely: the git client uses a scoped credential inside the sandbox, which the proxy verifies and translates to your actual GitHub authentication token
Restricts git push operations to the current working branch for safety
Enables cloning, fetching, and PR operations while maintaining security boundaries
​
Security proxy
Environments run behind an HTTP/HTTPS network proxy for security and abuse prevention purposes. All outbound internet traffic passes through this proxy, which provides:
Protection against malicious requests
Rate limiting and abuse prevention
Content filtering for enhanced security
​
Default allowed domains
When using
Trusted
network access, the following domains are allowed by default. Domains marked with
*
indicate wildcard subdomain matching, so
*.gcr.io
allows any subdomain of
gcr.io
.
Anthropic services
api.anthropic.com
statsig.anthropic.com
docs.claude.com
platform.claude.com
code.claude.com
claude.ai
Version control
github.com
www.github.com
api.github.com
npm.pkg.github.com
raw.githubusercontent.com
pkg-npm.githubusercontent.com
objects.githubusercontent.com
release-assets.githubusercontent.com
codeload.github.com
avatars.githubusercontent.com
camo.githubusercontent.com
gist.github.com
gitlab.com
www.gitlab.com
registry.gitlab.com
bitbucket.org
www.bitbucket.org
api.bitbucket.org
Container registries
registry-1.docker.io
auth.docker.io
index.docker.io
hub.docker.com
www.docker.com
production.cloudflare.docker.com
download.docker.com
gcr.io
*.gcr.io
ghcr.io
mcr.microsoft.com
*.data.mcr.microsoft.com
public.ecr.aws
Cloud platforms
cloud.google.com
accounts.google.com
gcloud.google.com
*.googleapis.com
storage.googleapis.com
compute.googleapis.com
container.googleapis.com
azure.com
portal.azure.com
microsoft.com
www.microsoft.com
*.microsoftonline.com
packages.microsoft.com
dotnet.microsoft.com
dot.net
visualstudio.com
dev.azure.com
*.amazonaws.com
*.api.aws
oracle.com
www.oracle.com
java.com
www.java.com
java.net
www.java.net
download.oracle.com
yum.oracle.com
JavaScript and Node package managers
registry.npmjs.org
www.npmjs.com
www.npmjs.org
npmjs.com
npmjs.org
yarnpkg.com
registry.yarnpkg.com
Python package managers
pypi.org
www.pypi.org
files.pythonhosted.org
pythonhosted.org
test.pypi.org
pypi.python.org
pypa.io
www.pypa.io
Ruby package managers
rubygems.org
www.rubygems.org
api.rubygems.org
index.rubygems.org
ruby-lang.org
www.ruby-lang.org
rubyforge.org
www.rubyforge.org
rubyonrails.org
www.rubyonrails.org
rvm.io
get.rvm.io
Rust package managers
crates.io
www.crates.io
index.crates.io
static.crates.io
rustup.rs
static.rust-lang.org
www.rust-lang.org
Go package managers
proxy.golang.org
sum.golang.org
index.golang.org
golang.org
www.golang.org
goproxy.io
pkg.go.dev
JVM package managers
maven.org
repo.maven.org
central.maven.org
repo1.maven.org
repo.maven.apache.org
jcenter.bintray.com
gradle.org
www.gradle.org
services.gradle.org
plugins.gradle.org
kotlinlang.org
www.kotlinlang.org
spring.io
repo.spring.io
Other package managers
packagist.org (PHP Composer)
www.packagist.org
repo.packagist.org
nuget.org (.NET NuGet)
www.nuget.org
api.nuget.org
pub.dev (Dart/Flutter)
api.pub.dev
hex.pm (Elixir/Erlang)
www.hex.pm
cpan.org (Perl CPAN)
www.cpan.org
metacpan.org
www.metacpan.org
api.metacpan.org
cocoapods.org (iOS/macOS)
www.cocoapods.org
cdn.cocoapods.org
haskell.org
www.haskell.org
hackage.haskell.org
swift.org
www.swift.org
Linux distributions
archive.ubuntu.com
security.ubuntu.com
ubuntu.com
www.ubuntu.com
*.ubuntu.com
ppa.launchpad.net
launchpad.net
www.launchpad.net
*.nixos.org
Development tools and platforms
dl.k8s.io (Kubernetes)
pkgs.k8s.io
k8s.io
www.k8s.io
releases.hashicorp.com (HashiCorp)
apt.releases.hashicorp.com
rpm.releases.hashicorp.com
archive.releases.hashicorp.com
hashicorp.com
www.hashicorp.com
repo.anaconda.com (Anaconda/Conda)
conda.anaconda.org
anaconda.org
www.anaconda.com
anaconda.com
continuum.io
apache.org (Apache)
www.apache.org
archive.apache.org
downloads.apache.org
eclipse.org (Eclipse)
www.eclipse.org
download.eclipse.org
nodejs.org (Node.js)
www.nodejs.org
developer.apple.com
developer.android.com
pkg.stainless.com
binaries.prisma.sh
Cloud services and monitoring
statsig.com
www.statsig.com
api.statsig.com
sentry.io
*.sentry.io
downloads.sentry-cdn.com
http-intake.logs.datadoghq.com
*.datadoghq.com
*.datadoghq.eu
api.honeycomb.io
Content delivery and mirrors
sourceforge.net
*.sourceforge.net
packagecloud.io
*.packagecloud.io
fonts.googleapis.com
fonts.gstatic.com
Schema and configuration
json-schema.org
www.json-schema.org
json.schemastore.org
www.schemastore.org
Model Context Protocol
*.modelcontextprotocol.io
​
Move tasks between web and terminal
These workflows require the
Claude Code CLI
signed in to the same claude.ai account. You can start new cloud sessions from your terminal, or pull cloud sessions into your terminal to continue locally. Cloud sessions persist even if you close your laptop, and you can monitor them from anywhere including the Claude mobile app.
From the CLI, session handoff is one-way: you can pull cloud sessions into your terminal with
--teleport
, but you can’t push an existing terminal session to the web. The
--remote
flag creates a new cloud session for your current repository. The
Desktop app
provides a Continue in menu that can send a local session to the web.
​
From terminal to web
Start a cloud session from the command line with the
--remote
flag:
claude
--remote
"Fix the authentication bug in src/auth/login.ts"
This creates a new cloud session on claude.ai. The session clones your current directory’s GitHub remote at your current branch, so push first if you have local commits, since the VM clones from GitHub rather than your machine.
--remote
works with a single repository at a time. The task runs in the cloud while you continue working locally.
--remote
creates cloud sessions.
--remote-control
is unrelated: it exposes a local CLI session for monitoring from the web. See
Remote Control
.
Use
/tasks
in the Claude Code CLI to check progress, or open the session on claude.ai or the Claude mobile app to interact directly. From there you can steer Claude, provide feedback, or answer questions just like any other conversation.
​
Tips for cloud tasks
Plan locally, execute remotely
: for complex tasks, start Claude in plan mode to collaborate on the approach, then send work to the cloud:
claude
--permission-mode
plan
In plan mode, Claude reads files, runs commands to explore, and proposes a plan without editing source code. Once you’re satisfied, save the plan to the repo, commit, and push so the cloud VM can clone it. Then start a cloud session for autonomous execution:
claude
--remote
"Execute the migration plan in docs/migration-plan.md"
This pattern gives you control over the strategy while letting Claude execute autonomously in the cloud.
Plan in the cloud with ultraplan
: to draft and review the plan itself in a web session, use
ultraplan
. Claude generates the plan on Claude Code on the web while you keep working, then you comment on sections in your browser and choose to execute remotely or send the plan back to your terminal.
Run tasks in parallel
: each
--remote
command creates its own cloud session that runs independently. You can start multiple tasks and they’ll all run simultaneously in separate sessions:
claude
--remote
"Fix the flaky test in auth.spec.ts"
claude
--remote
"Update the API documentation"
claude
--remote
"Refactor the logger to use structured output"
Monitor all sessions with
/tasks
in the Claude Code CLI. When a session completes, you can create a PR from the web interface or
teleport
the session to your terminal to continue working.
​
Send local repositories without GitHub
When you run
claude --remote
from a repository that isn’t connected to GitHub, Claude Code bundles your local repository and uploads it directly to the cloud session. The bundle includes your full repository history across all branches, plus any uncommitted changes to tracked files.
This fallback activates automatically when GitHub access isn’t available. To force it even when GitHub is connected, set
CCR_FORCE_BUNDLE=1
:
CCR_FORCE_BUNDLE
=
1
claude
--remote
"Run the test suite and fix any failures"
Bundled repositories must meet these limits:
The directory must be a git repository with at least one commit
The bundled repository must be under 100 MB. Larger repositories fall back to bundling only the current branch, then to a single squashed snapshot of the working tree, and fail only if the snapshot is still too large
Untracked files are not included; run
git add
on files you want the cloud session to see
Sessions created from a bundle can’t push back to a remote unless you also have
GitHub authentication
configured
​
From web to terminal
Pull a cloud session into your terminal using any of these:
Using
--teleport
: from the command line, run
claude --teleport
for an interactive session picker, or
claude --teleport <session-id>
to resume a specific session directly. If you have uncommitted changes, you’ll be prompted to stash them first.
Using
/teleport
: inside an existing CLI session, run
/teleport
(or
/tp
) to open the same session picker without restarting Claude Code.
From
/tasks
: run
/tasks
to see your background sessions, then press
t
to teleport into one
From the web interface
: select
Open in CLI
to copy a command you can paste into your terminal
When you teleport a session, Claude verifies you’re in the correct repository, fetches and checks out the branch from the cloud session, and loads the full conversation history into your terminal.
--teleport
is distinct from
--resume
.
--resume
reopens a conversation from this machine’s local history and doesn’t list cloud sessions;
--teleport
pulls a cloud session and its branch.
​
Teleport requirements
Teleport checks these requirements before resuming a session. If any requirement isn’t met, you’ll see an error or be prompted to resolve the issue.
Requirement
Details
Clean git state
Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed.
Correct repository
You must run
--teleport
from a checkout of the same repository, not a fork.
Branch available
The branch from the cloud session must have been pushed to the remote. Teleport automatically fetches and checks it out.
Same account
You must be authenticated to the same claude.ai account used in the cloud session.
​
--teleport
is unavailable
Teleport requires claude.ai subscription authentication. If you’re authenticated via API key, Bedrock, Vertex AI, or Microsoft Foundry, run
/login
to sign in with your claude.ai account instead. If you’re already signed in via claude.ai and
--teleport
is still unavailable, your organization may have disabled cloud sessions.
​
Work with sessions
Sessions appear in the sidebar at claude.ai/code. From there you can review changes, share with teammates, archive finished work, or delete sessions permanently.
​
Manage context
Cloud sessions support
built-in commands
that produce text output. Commands that open an interactive terminal picker, like
/model
or
/config
, are not available.
For context management specifically:
Command
Works in cloud sessions
Notes
/compact
Yes
Summarizes the conversation to free up context. Accepts optional focus instructions like
/compact keep the test output
/context
Yes
Shows what’s currently in the context window
/clear
No
Start a new session from the sidebar instead
Auto-compaction runs automatically when the context window approaches capacity, the same as in the CLI. To trigger it earlier, set
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
in your
environment variables
. For example,
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=70
compacts at 70% capacity instead of the default ~95%. To change the effective window size for compaction calculations, use
CLAUDE_CODE_AUTO_COMPACT_WINDOW
.
Subagents
work the same way they do locally. Claude can spawn them with the Task tool to offload research or parallel work into a separate context window, keeping the main conversation lighter. Subagents defined in your repo’s
.claude/agents/
are picked up automatically.
Agent teams
are off by default but can be enabled by adding
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
to your
environment variables
.
​
Review changes
Each session shows a diff indicator with lines added and removed, like
+42 -18
. Select it to open the diff view, leave inline comments on specific lines, and send them to Claude with your next message. See
Review and iterate
for the full walkthrough including PR creation. To have Claude monitor the PR for CI failures and review comments automatically, see
Auto-fix pull requests
.
​
Share sessions
To share a session, toggle its visibility according to the account types below. After that, share the session link as-is. Recipients see the latest state when they open the link, but their view doesn’t update in real time.
​
Share from an Enterprise or Team account
For Enterprise and Team accounts, the two visibility options are
Private
and
Team
. Team visibility makes the session visible to other members of your claude.ai organization. Repository access verification is enabled by default, based on the GitHub account connected to the recipient’s account. Your account’s display name is visible to all recipients with access.
Claude in Slack
sessions are automatically shared with Team visibility.
​
Share from a Max or Pro account
For Max and Pro accounts, the two visibility options are
Private
and
Public
. Public visibility makes the session visible to any user logged into claude.ai.
Check your session for sensitive content before sharing. Sessions may contain code and credentials from private GitHub repositories. Repository access verification is not enabled by default.
To require recipients to have repository access, or to hide your name from shared sessions, go to Settings > Claude Code > Sharing settings.
​
Archive sessions
You can archive sessions to keep your session list organized. Archived sessions are hidden from the default session list but can be viewed by filtering for archived sessions.
To archive a session, hover over the session in the sidebar and select the archive icon.
​
Delete sessions
Deleting a session permanently removes the session and its data. This action cannot be undone. You can delete a session in two ways:
From the sidebar
: filter for archived sessions, then hover over the session you want to delete and select the delete icon
From the session menu
: open a session, select the dropdown next to the session title, and select
Delete
You will be asked to confirm before a session is deleted.
​
Auto-fix pull requests
Claude can watch a pull request and automatically respond to CI failures and review comments. Claude subscribes to GitHub activity on the PR, and when a check fails or a reviewer leaves a comment, Claude investigates and pushes a fix if one is clear.
Auto-fix requires the Claude GitHub App to be installed on your repository. If you haven’t already, install it from the
GitHub App page
or when prompted during
setup
.
There are a few ways to turn on auto-fix depending on where the PR came from and what device you’re using:
PRs created in Claude Code on the web
: open the CI status bar and select
Auto-fix
From your terminal
: run
/autofix-pr
while on the PR’s branch. Claude Code detects the open PR with
gh
, spawns a web session, and turns on auto-fix in one step
From the mobile app
: tell Claude to auto-fix the PR, for example “watch this PR and fix any CI failures or review comments”
Any existing PR
: paste the PR URL into a session and tell Claude to auto-fix it
Auto-fix is a per-PR toggle. To stop monitoring, open the CI status bar in the web session and clear the
Auto-fix
toggle, or tell Claude to stop watching the PR.
​
How Claude responds to PR activity
When auto-fix is active, Claude receives GitHub events for the PR including new review comments and CI check failures. For each event, Claude investigates and decides how to proceed:
Clear fixes
: if Claude is confident in a fix and it doesn’t conflict with earlier instructions, Claude makes the change, pushes it, and explains what was done in the session
Ambiguous requests
: if a reviewer’s comment could be interpreted multiple ways or involves something architecturally significant, Claude asks you before acting
Duplicate or no-action events
: if an event is a duplicate or requires no change, Claude notes it in the session and moves on
Claude may reply to review comment threads on GitHub as part of resolving them. These replies are posted using your GitHub account, so they appear under your username, but each reply is labeled as coming from Claude Code so reviewers know it was written by the agent and not by you directly.
If your repository uses comment-triggered automation such as Atlantis, Terraform Cloud, or custom GitHub Actions that run on
issue_comment
events, be aware that Claude can reply on your behalf, which can trigger those workflows. Review your repository’s automation before enabling auto-fix, and consider disabling auto-fix for repositories where a PR comment can deploy infrastructure or run privileged operations.
​
Security and isolation
Each cloud session is separated from your machine and from other sessions through several layers:
Isolated virtual machines
: each session runs in an isolated, Anthropic-managed VM
Network access controls
: network access is limited by default, and can be disabled. When running with network access disabled, Claude Code can still communicate with the Anthropic API, which may allow data to exit the VM.
Credential protection
: sensitive credentials such as git credentials or signing keys are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials.
Secure analysis
: code is analyzed and modified within isolated VMs before creating PRs
​
Troubleshooting
For runtime API errors that appear in the conversation such as
API Error: 500
,
529 Overloaded
,
429
, or
Prompt is too long
, see the
Error reference
. Those errors and their fixes are shared with the CLI and Desktop app. The sections below cover issues specific to cloud sessions.
​
Session creation failed
If a new session fails to start with
Session creation failed
or stalls at provisioning, Claude Code could not allocate a cloud environment.
Check
status.claude.com
for cloud session incidents
Retry after a minute, as capacity is provisioned on demand
Confirm your repository is reachable. The connecting GitHub account must have access to the repository on GitHub, either through the Claude GitHub App authorization or a
gh
token synced via
/web-setup
— installing the App on the repository is not required. See
GitHub authentication options
.
​
Remote Control session expired or access denied
--teleport
connects through the same Remote Control session infrastructure that cloud sessions use, so authentication and session-expiry errors surface with Remote Control wording. You may see
Remote Control session expired
or
Access denied
. The connection token is short-lived and scoped to your account.
Run
/login
locally to refresh your credentials, then reconnect
Confirm you are signed in to the same account that owns the session
If you see
Remote Control may not be available for this organization
, your admin has not enabled remote sessions for your plan
​
Environment expired
Cloud sessions stop after a period of inactivity and the underlying environment is reclaimed. From a local terminal, this surfaces as
Could not resume session ... its environment has expired. Creating a fresh session instead.
On the web, the session is marked expired in the session list.
Reopen the session from
claude.ai/code
to provision a fresh environment with your conversation history restored.
​
Limitations
Before relying on cloud sessions for a workflow, account for these constraints:
Rate limits
: Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel consumes more rate limits proportionately. There is no separate compute charge for the cloud VM.
Repository authentication
: you can only move sessions from web to local when you are authenticated to the same account
Platform restrictions
: repository cloning and pull request creation require GitHub. Self-hosted
GitHub Enterprise Server
instances are supported for Team and Enterprise plans. GitLab, Bitbucket, and other non-GitHub repositories can be sent to cloud sessions as a
local bundle
, but the session can’t push results back to the remote
Organization IP allowlist
: cloud sessions call the Anthropic API from Anthropic-managed infrastructure, not your network. If your organization has
IP allowlisting
enabled, every cloud session fails with an authentication error. The same applies to
Code Review
and
Routines
. Contact
Anthropic support
to exempt Anthropic-hosted services from your organization’s IP allowlist.
​
Related resources
Ultraplan
: draft a plan in a cloud session and review it in your browser
Ultrareview
: run a deep multi-agent code review in a cloud sandbox
Routines
: automate work on a schedule, via API call, or in response to GitHub events
Hooks configuration
: run scripts at session lifecycle events
Settings reference
: all configuration options
Security
: isolation guarantees and data handling
Data usage
: what Anthropic retains from cloud sessions
Was this page helpful?
Yes
No
Get started
Routines
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/claude-code-on-the-web" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>How the agent loop works</title>
  <link>https://code.claude.com/docs/en/agent-sdk/agent-loop</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/agent-loop</guid>
  <pubDate>Sat, 03 Feb 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How the agent loop works
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cus...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How the agent loop works
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Agent SDK lets you embed Claude Code’s autonomous agent loop in your own applications. The SDK is a standalone package that gives you programmatic control over tools, permissions, cost limits, and output. You don’t need the Claude Code CLI installed to use it.
When you start an agent, the SDK runs the same
execution loop that powers Claude Code
: Claude evaluates your prompt, calls tools to take action, receives the results, and repeats until the task is complete. This page explains what happens inside that loop so you can build, debug, and optimize your agents effectively.
​
The loop at a glance
Every agent session follows the same cycle:
Receive prompt.
Claude receives your prompt, along with the system prompt, tool definitions, and conversation history. The SDK yields a
SystemMessage
with subtype
"init"
containing session metadata.
Evaluate and respond.
Claude evaluates the current state and determines how to proceed. It may respond with text, request one or more tool calls, or both. The SDK yields an
AssistantMessage
containing the text and any tool call requests.
Execute tools.
The SDK runs each requested tool and collects the results. Each set of tool results feeds back to Claude for the next decision. You can use
hooks
to intercept, modify, or block tool calls before they run.
Repeat.
Steps 2 and 3 repeat as a cycle. Each full cycle is one turn. Claude continues calling tools and processing results until it produces a response with no tool calls.
Return result.
The SDK yields a final
AssistantMessage
with the text response (no tool calls), followed by a
ResultMessage
with the final text, token usage, cost, and session ID.
A quick question (“what files are here?”) might take one or two turns of calling
Glob
and responding with the results. A complex task (“refactor the auth module and update the tests”) can chain dozens of tool calls across many turns, reading files, editing code, and running tests, with Claude adjusting its approach based on each result.
​
Turns and messages
A turn is one round trip inside the loop: Claude produces output that includes tool calls, the SDK executes those tools, and the results feed back to Claude automatically. This happens without yielding control back to your code. Turns continue until Claude produces output with no tool calls, at which point the loop ends and the final result is delivered.
Consider what a full session might look like for the prompt “Fix the failing tests in auth.ts”.
First, the SDK sends your prompt to Claude and yields a
SystemMessage
with the session metadata. Then the loop begins:
Turn 1:
Claude calls
Bash
to run
npm test
. The SDK yields an
AssistantMessage
with the tool call, executes the command, then yields a
UserMessage
with the output (three failures).
Turn 2:
Claude calls
Read
on
auth.ts
and
auth.test.ts
. The SDK returns the file contents and yields an
AssistantMessage
.
Turn 3:
Claude calls
Edit
to fix
auth.ts
, then calls
Bash
to re-run
npm test
. All three tests pass. The SDK yields an
AssistantMessage
.
Final turn:
Claude produces a text-only response with no tool calls: “Fixed the auth bug, all three tests pass now.” The SDK yields a final
AssistantMessage
with this text, then a
ResultMessage
with the same text plus cost and usage.
That was four turns: three with tool calls, one final text-only response.
You can cap the loop with
max_turns
/
maxTurns
, which counts tool-use turns only. For example,
max_turns=2
in the loop above would have stopped before the edit step. You can also use
max_budget_usd
/
maxBudgetUsd
to cap turns based on a spend threshold.
Without limits, the loop runs until Claude finishes on its own, which is fine for well-scoped tasks but can run long on open-ended prompts (“improve this codebase”). Setting a budget is a good default for production agents. See
Turns and budget
below for the option reference.
​
Message types
As the loop runs, the SDK yields a stream of messages. Each message carries a type that tells you what stage of the loop it came from. The five core types are:
SystemMessage
:
session lifecycle events. The
subtype
field distinguishes them:
"init"
is the first message (session metadata), and
"compact_boundary"
fires after
compaction
. In TypeScript, the compact boundary is its own
SDKCompactBoundaryMessage
type rather than a subtype of
SDKSystemMessage
.
AssistantMessage
:
emitted after each Claude response, including the final text-only one. Contains text content blocks and tool call blocks from that turn.
UserMessage
:
emitted after each tool execution with the tool result content sent back to Claude. Also emitted for any user inputs you stream mid-loop.
StreamEvent
:
only emitted when partial messages are enabled. Contains raw API streaming events (text deltas, tool input chunks). See
Stream responses
.
ResultMessage
:
marks the end of the agent loop. Contains the final text result, token usage, cost, and session ID. Check the
subtype
field to determine whether the task succeeded or hit a limit. A small number of trailing system events, such as
prompt_suggestion
, can arrive after it, so iterate the stream to completion rather than breaking on the result. See
Handle the result
.
These five types cover the full agent loop lifecycle in both SDKs. The TypeScript SDK also yields additional observability events (hook events, tool progress, rate limits, task notifications) that provide extra detail but are not required to drive the loop. See the
Python message types reference
and
TypeScript message types reference
for the complete lists.
​
Handle messages
Which messages you handle depends on what you’re building:
Final results only:
handle
ResultMessage
to get the output, cost, and whether the task succeeded or hit a limit.
Progress updates:
handle
AssistantMessage
to see what Claude is doing each turn, including which tools it called.
Live streaming:
enable partial messages (
include_partial_messages
in Python,
includePartialMessages
in TypeScript) to get
StreamEvent
messages in real time. See
Stream responses in real-time
.
How you check message types depends on the SDK:
Python:
check message types with
isinstance()
against classes imported from
claude_agent_sdk
(for example,
isinstance(message, ResultMessage)
).
TypeScript:
check the
type
string field (for example,
message.type === "result"
).
AssistantMessage
and
UserMessage
wrap the raw API message in a
.message
field, so content blocks are at
message.message.content
, not
message.content
.
Example: Check message types and handle results
Python
TypeScript
from
claude_agent_sdk
import
query, AssistantMessage, ResultMessage
async
for
message
in
query(
prompt
=
"Summarize this project"
):
if
isinstance
(message, AssistantMessage):
print
(
f
"Turn completed:
{
len
(message.content)
}
content blocks"
)
if
isinstance
(message, ResultMessage):
if
message.subtype
==
"success"
:
print
(message.result)
else
:
print
(
f
"Stopped:
{
message.subtype
}
"
)
​
Tool execution
Tools give your agent the ability to take action. Without tools, Claude can only respond with text. With tools, Claude can read files, run commands, search code, and interact with external services.
​
Built-in tools
The SDK includes the same tools that power Claude Code:
Category
Tools
What they do
File operations
Read
,
Edit
,
Write
Read, modify, and create files
Search
Glob
,
Grep
Find files by pattern, search content with regex
Execution
Bash
Run shell commands, scripts, git operations
Web
WebSearch
,
WebFetch
Search the web, fetch and parse pages
Discovery
ToolSearch
Dynamically find and load tools on-demand instead of preloading all of them
Orchestration
Agent
,
Skill
,
AskUserQuestion
,
TodoWrite
Spawn subagents, invoke skills, ask the user, track tasks
Beyond built-in tools, you can:
Connect external services
with
MCP servers
(databases, browsers, APIs)
Define custom tools
with
custom tool handlers
Load project skills
via
setting sources
for reusable workflows
​
Tool permissions
Claude determines which tools to call based on the task, but you control whether those calls are allowed to execute. You can auto-approve specific tools, block others entirely, or require approval for everything. Three options work together to determine what runs:
allowed_tools
/
allowedTools
auto-approves listed tools. A read-only agent with
["Read", "Glob", "Grep"]
in its allowed tools list runs those tools without prompting. Tools not listed are still available but require permission.
disallowed_tools
/
disallowedTools
blocks listed tools, regardless of other settings. See
Permissions
for the order that rules are checked before a tool runs.
permission_mode
/
permissionMode
controls what happens to tools that aren’t covered by allow or deny rules. See
Permission mode
for available modes.
You can also scope individual tools with rules like
"Bash(npm *)"
to allow only specific commands. See
Permissions
for the full rule syntax.
When a tool is denied, Claude receives a rejection message as the tool result and typically attempts a different approach or reports that it couldn’t proceed.
​
Parallel tool execution
When Claude requests multiple tool calls in a single turn, both SDKs can run them concurrently or sequentially depending on the tool. Read-only tools (like
Read
,
Glob
,
Grep
, and MCP tools marked as read-only) can run concurrently. Tools that modify state (like
Edit
,
Write
, and
Bash
) run sequentially to avoid conflicts.
Custom tools default to sequential execution. To enable parallel execution for a custom tool, set
readOnlyHint
in its annotations. Both the
TypeScript
and
Python
SDKs use this field name from the MCP SDK.
​
Control how the loop runs
You can limit how many turns the loop takes, how much it costs, how deeply Claude reasons, and whether tools require approval before running. All of these are fields on
ClaudeAgentOptions
(Python) /
Options
(TypeScript).
​
Turns and budget
Option
What it controls
Default
Max turns (
max_turns
/
maxTurns
)
Maximum tool-use round trips
No limit
Max budget (
max_budget_usd
/
maxBudgetUsd
)
Maximum cost before stopping
No limit
When either limit is hit, the SDK returns a
ResultMessage
with a corresponding error subtype (
error_max_turns
or
error_max_budget_usd
). See
Handle the result
for how to check these subtypes and
ClaudeAgentOptions
/
Options
for syntax.
​
Effort level
The
effort
option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See
Effort
for which models support it.
Level
Behavior
Good for
"low"
Minimal reasoning, fast responses
File lookups, listing directories
"medium"
Balanced reasoning
Routine edits, standard tasks
"high"
Thorough analysis
Refactors, debugging
"xhigh"
Extended reasoning depth
Coding and agentic tasks; recommended on Opus 4.7
"max"
Maximum reasoning depth
Multi-step problems requiring deep analysis
If you don’t set
effort
, the Python SDK leaves the parameter unset and defers to the model’s default behavior. The TypeScript SDK defaults to
"high"
.
effort
trades latency and token cost for reasoning depth within each response.
Extended thinking
is a separate feature that produces visible chain-of-thought blocks in the output. They are independent: you can set
effort: "low"
with extended thinking enabled, or
effort: "max"
without it.
Use lower effort for agents doing simple, well-scoped tasks (like listing files or running a single grep) to reduce cost and latency. Set
effort
in the top-level
query()
options for the whole session, or per subagent with the
effort
field on
AgentDefinition
to override the session level.
​
Permission mode
The permission mode option (
permission_mode
in Python,
permissionMode
in TypeScript) controls whether the agent asks for approval before using tools:
Mode
Behavior
"default"
Tools not covered by allow rules trigger your approval callback; no callback means deny
"acceptEdits"
Auto-approves file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.); other Bash commands follow default rules
"plan"
Read-only tools run; Claude explores and produces a plan without editing your source files
"dontAsk"
Never prompts. Tools pre-approved by
permission rules
run, everything else is denied
"auto"
(TypeScript only)
Uses a model classifier to approve or deny each tool call. See
Auto mode
for availability and behavior
"bypassPermissions"
Runs all allowed tools without asking. Cannot be used when running as root on Unix. Use only in isolated environments where the agent’s actions cannot affect systems you care about
For interactive applications, use
"default"
with a tool approval callback to surface approval prompts. For autonomous agents on a dev machine,
"acceptEdits"
auto-approves file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.) while still gating other
Bash
commands behind allow rules. Reserve
"bypassPermissions"
for CI, containers, or other isolated environments. See
Permissions
for full details.
​
Model
If you don’t set
model
, the SDK uses Claude Code’s default, which depends on your authentication method and subscription. Set it explicitly (for example,
model="claude-sonnet-4-6"
) to pin a specific model or to use a smaller model for faster, cheaper agents. See
models
for available IDs.
​
The context window
The context window is the total amount of information available to Claude during a session. It does not reset between turns within a session. Everything accumulates: the system prompt, tool definitions, conversation history, tool inputs, and tool outputs. Content that stays the same across turns (system prompt, tool definitions, CLAUDE.md) is automatically
prompt cached
, which reduces cost and latency for repeated prefixes.
​
What consumes context
Here’s how each component affects context in the SDK:
Source
When it loads
Impact
System prompt
Every request
Small fixed cost, always present
CLAUDE.md files
Session start, via
settingSources
Full content in every request (but prompt-cached, so only the first request pays full cost)
Tool definitions
Every request; MCP schemas deferred by default
Built-in tool schemas load every request.
Tool search
defers MCP tool schemas by default, falling back to upfront loading on Vertex AI or a non-first-party
ANTHROPIC_BASE_URL
. See
Configure tool search
for the full matrix
Conversation history
Accumulates over turns
Grows with each turn: prompts, responses, tool inputs, tool outputs
Skill descriptions
Session start, via setting sources
Short summaries; full content loads only when invoked
Large tool outputs consume significant context. Reading a big file or running a command with verbose output can use thousands of tokens in a single turn. Context accumulates across turns, so longer sessions with many tool calls build up significantly more context than short ones.
​
Automatic compaction
When the context window approaches its limit, the SDK automatically compacts the conversation: it summarizes older history to free space, keeping your most recent exchanges and key decisions intact. The SDK emits a message with
type: "system"
and
subtype: "compact_boundary"
in the stream when this happens (in Python this is a
SystemMessage
; in TypeScript it is a separate
SDKCompactBoundaryMessage
type).
Compaction replaces older messages with a summary, so specific instructions from early in the conversation may not be preserved. Persistent rules belong in CLAUDE.md (loaded via
settingSources
) rather than in the initial prompt, because CLAUDE.md content is re-injected on every request.
You can customize compaction behavior in several ways:
Summarization instructions in CLAUDE.md:
The compactor reads your CLAUDE.md like any other context, so you can include a section telling it what to preserve when summarizing. The section header is free-form (not a magic string); the compactor matches on intent.
PreCompact
hook:
Run custom logic before compaction occurs, for example to archive the full transcript. The hook receives a
trigger
field (
manual
or
auto
). See
hooks
.
Manual compaction:
Send
/compact
as a prompt string to trigger compaction on demand. (Slash commands sent this way are SDK inputs, not CLI-only shortcuts. See
slash commands in the SDK
.)
Example: Summarization instructions in CLAUDE.md
Add a section to your project’s CLAUDE.md telling the compactor what to preserve. The header name isn’t special; use any clear label.
CLAUDE.md
# Summary instructions
When summarizing this conversation, always preserve:
-
The current task objective and acceptance criteria
-
File paths that have been read or modified
-
Test results and error messages
-
Decisions made and the reasoning behind them
​
Keep context efficient
A few strategies for long-running agents:
Use subagents for subtasks.
Each subagent starts with a fresh conversation (no prior message history, though it does load its own system prompt and project-level context like CLAUDE.md). It does not see the parent’s turns, and only its final response returns to the parent as a tool result. The main agent’s context grows by that summary, not by the full subtask transcript. See
What subagents inherit
for details.
Be selective with tools.
Every tool definition takes context space. Use the
tools
field on
AgentDefinition
to scope subagents to the minimum set they need.
Watch MCP server costs.
MCP tool search
defers MCP tool schemas by default and loads them on demand. When tool search is off, on Vertex AI, or behind a non-first-party
ANTHROPIC_BASE_URL
, each MCP server adds all its tool schemas to every request, so a few servers with many tools can consume significant context before the agent does any work.
Use lower effort for routine tasks.
Set
effort
to
"low"
for agents that only need to read files or list directories. This reduces token usage and cost.
For a detailed breakdown of per-feature context costs, see
Understand context costs
.
​
Sessions and continuity
Each interaction with the SDK creates or continues a session. Capture the session ID from
ResultMessage.session_id
(available in both SDKs) to resume later. The TypeScript SDK also exposes it as a direct field on the init
SystemMessage
; in Python it’s nested in
SystemMessage.data
.
When you resume, the full context from previous turns is restored: files that were read, analysis that was performed, and actions that were taken. You can also fork a session to branch into a different approach without modifying the original.
See
Session management
for the full guide on resume, continue, and fork patterns.
In Python,
ClaudeSDKClient
handles session IDs automatically across multiple calls. See the
Python SDK reference
for details.
​
Handle the result
When the loop ends, the
ResultMessage
tells you what happened and gives you the output. The
subtype
field (available in both SDKs) is the primary way to check termination state.
Result subtype
What happened
result
field available?
success
Claude finished the task normally
Yes
error_max_turns
Hit the
maxTurns
limit before finishing
No
error_max_budget_usd
Hit the
maxBudgetUsd
limit before finishing
No
error_during_execution
An error interrupted the loop (for example, an API failure or cancelled request)
No
error_max_structured_output_retries
Structured output validation failed after the configured retry limit
No
The
result
field (the final text output) is only present on the
success
variant, so always check the subtype before reading it. All result subtypes carry
total_cost_usd
,
usage
,
num_turns
, and
session_id
so you can track cost and resume even after errors. In Python,
total_cost_usd
and
usage
are typed as optional and may be
None
on some error paths, so guard before formatting them. See
Tracking costs and usage
for details on interpreting the
usage
fields.
The result also includes a
stop_reason
field (
string | null
in TypeScript,
str | None
in Python) indicating why the model stopped generating on its final turn. Common values are
end_turn
(model finished normally),
max_tokens
(hit the output token limit), and
refusal
(the model declined the request). On error result subtypes,
stop_reason
carries the value from the last assistant response before the loop ended. To detect refusals, check
stop_reason === "refusal"
(TypeScript) or
stop_reason == "refusal"
(Python). See
SDKResultMessage
(TypeScript) or
ResultMessage
(Python) for the full type.
​
Hooks
Hooks
are callbacks that fire at specific points in the loop: before a tool runs, after it returns, when the agent finishes, and so on. Some commonly used hooks are:
Hook
When it fires
Common uses
PreToolUse
Before a tool executes
Validate inputs, block dangerous commands
PostToolUse
After a tool returns
Audit outputs, trigger side effects
UserPromptSubmit
When a prompt is sent
Inject additional context into prompts
Stop
When the agent finishes
Validate the result, save session state
SubagentStart
/
SubagentStop
When a subagent spawns or completes
Track and aggregate parallel task results
PreCompact
Before context compaction
Archive full transcript before summarizing
Hooks run in your application process, not inside the agent’s context window, so they don’t consume context. Hooks can also short-circuit the loop: a
PreToolUse
hook that rejects a tool call prevents it from executing, and Claude receives the rejection message instead.
Both SDKs support all the events above. The TypeScript SDK includes additional events that Python does not yet support. See
Control execution with hooks
for the complete event list, per-SDK availability, and the full callback API.
​
Put it all together
This example combines the key concepts from this page into a single agent that fixes failing tests. It configures the agent with allowed tools (auto-approved so the agent runs autonomously), project settings, and safety limits on turns and reasoning effort. As the loop runs, it captures the session ID for potential resumption, handles the final result, and prints the total cost.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
run_agent
():
session_id
=
None
async
for
message
in
query(
prompt
=
"Find and fix the bug causing test failures in the auth module"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
,
"Glob"
,
"Grep"
,
],
# Listing tools here auto-approves them (no prompting)
setting_sources
=
[
"project"
],
# Load CLAUDE.md, skills, hooks from current directory
max_turns
=
30
,
# Prevent runaway sessions
effort
=
"high"
,
# Thorough reasoning for complex debugging
),
):
# Handle the final result
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
# Save for potential resumption
if
message.subtype
==
"success"
:
print
(
f
"Done:
{
message.result
}
"
)
elif
message.subtype
==
"error_max_turns"
:
# Agent ran out of turns. Resume with a higher limit.
print
(
f
"Hit turn limit. Resume session
{
session_id
}
to continue."
)
elif
message.subtype
==
"error_max_budget_usd"
:
print
(
"Hit budget limit."
)
else
:
print
(
f
"Stopped:
{
message.subtype
}
"
)
if
message.total_cost_usd
is
not
None
:
print
(
f
"Cost: $
{
message.total_cost_usd
:.4f}
"
)
asyncio.run(run_agent())
​
Next steps
Now that you understand the loop, here’s where to go depending on what you’re building:
Haven’t run an agent yet?
Start with the
quickstart
to get the SDK installed and see a full example running end to end.
Ready to hook into your project?
Load CLAUDE.md, skills, and filesystem hooks
so the agent follows your project conventions automatically.
Building an interactive UI?
Enable
streaming
to show live text and tool calls as the loop runs.
Need tighter control over what the agent can do?
Lock down tool access with
permissions
, and use
hooks
to audit, block, or transform tool calls before they execute.
Running long or expensive tasks?
Offload isolated work to
subagents
to keep your main context lean.
For the broader conceptual picture of the agentic loop (not SDK-specific), see
How Claude Code works
.
Was this page helpful?
Yes
No
Quickstart
Use Claude Code features
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/agent-loop" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How the agent loop works
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cus...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Core concepts
How the agent loop works
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Agent SDK lets you embed Claude Code’s autonomous agent loop in your own applications. The SDK is a standalone package that gives you programmatic control over tools, permissions, cost limits, and output. You don’t need the Claude Code CLI installed to use it.
When you start an agent, the SDK runs the same
execution loop that powers Claude Code
: Claude evaluates your prompt, calls tools to take action, receives the results, and repeats until the task is complete. This page explains what happens inside that loop so you can build, debug, and optimize your agents effectively.
​
The loop at a glance
Every agent session follows the same cycle:
Receive prompt.
Claude receives your prompt, along with the system prompt, tool definitions, and conversation history. The SDK yields a
SystemMessage
with subtype
"init"
containing session metadata.
Evaluate and respond.
Claude evaluates the current state and determines how to proceed. It may respond with text, request one or more tool calls, or both. The SDK yields an
AssistantMessage
containing the text and any tool call requests.
Execute tools.
The SDK runs each requested tool and collects the results. Each set of tool results feeds back to Claude for the next decision. You can use
hooks
to intercept, modify, or block tool calls before they run.
Repeat.
Steps 2 and 3 repeat as a cycle. Each full cycle is one turn. Claude continues calling tools and processing results until it produces a response with no tool calls.
Return result.
The SDK yields a final
AssistantMessage
with the text response (no tool calls), followed by a
ResultMessage
with the final text, token usage, cost, and session ID.
A quick question (“what files are here?”) might take one or two turns of calling
Glob
and responding with the results. A complex task (“refactor the auth module and update the tests”) can chain dozens of tool calls across many turns, reading files, editing code, and running tests, with Claude adjusting its approach based on each result.
​
Turns and messages
A turn is one round trip inside the loop: Claude produces output that includes tool calls, the SDK executes those tools, and the results feed back to Claude automatically. This happens without yielding control back to your code. Turns continue until Claude produces output with no tool calls, at which point the loop ends and the final result is delivered.
Consider what a full session might look like for the prompt “Fix the failing tests in auth.ts”.
First, the SDK sends your prompt to Claude and yields a
SystemMessage
with the session metadata. Then the loop begins:
Turn 1:
Claude calls
Bash
to run
npm test
. The SDK yields an
AssistantMessage
with the tool call, executes the command, then yields a
UserMessage
with the output (three failures).
Turn 2:
Claude calls
Read
on
auth.ts
and
auth.test.ts
. The SDK returns the file contents and yields an
AssistantMessage
.
Turn 3:
Claude calls
Edit
to fix
auth.ts
, then calls
Bash
to re-run
npm test
. All three tests pass. The SDK yields an
AssistantMessage
.
Final turn:
Claude produces a text-only response with no tool calls: “Fixed the auth bug, all three tests pass now.” The SDK yields a final
AssistantMessage
with this text, then a
ResultMessage
with the same text plus cost and usage.
That was four turns: three with tool calls, one final text-only response.
You can cap the loop with
max_turns
/
maxTurns
, which counts tool-use turns only. For example,
max_turns=2
in the loop above would have stopped before the edit step. You can also use
max_budget_usd
/
maxBudgetUsd
to cap turns based on a spend threshold.
Without limits, the loop runs until Claude finishes on its own, which is fine for well-scoped tasks but can run long on open-ended prompts (“improve this codebase”). Setting a budget is a good default for production agents. See
Turns and budget
below for the option reference.
​
Message types
As the loop runs, the SDK yields a stream of messages. Each message carries a type that tells you what stage of the loop it came from. The five core types are:
SystemMessage
:
session lifecycle events. The
subtype
field distinguishes them:
"init"
is the first message (session metadata), and
"compact_boundary"
fires after
compaction
. In TypeScript, the compact boundary is its own
SDKCompactBoundaryMessage
type rather than a subtype of
SDKSystemMessage
.
AssistantMessage
:
emitted after each Claude response, including the final text-only one. Contains text content blocks and tool call blocks from that turn.
UserMessage
:
emitted after each tool execution with the tool result content sent back to Claude. Also emitted for any user inputs you stream mid-loop.
StreamEvent
:
only emitted when partial messages are enabled. Contains raw API streaming events (text deltas, tool input chunks). See
Stream responses
.
ResultMessage
:
marks the end of the agent loop. Contains the final text result, token usage, cost, and session ID. Check the
subtype
field to determine whether the task succeeded or hit a limit. A small number of trailing system events, such as
prompt_suggestion
, can arrive after it, so iterate the stream to completion rather than breaking on the result. See
Handle the result
.
These five types cover the full agent loop lifecycle in both SDKs. The TypeScript SDK also yields additional observability events (hook events, tool progress, rate limits, task notifications) that provide extra detail but are not required to drive the loop. See the
Python message types reference
and
TypeScript message types reference
for the complete lists.
​
Handle messages
Which messages you handle depends on what you’re building:
Final results only:
handle
ResultMessage
to get the output, cost, and whether the task succeeded or hit a limit.
Progress updates:
handle
AssistantMessage
to see what Claude is doing each turn, including which tools it called.
Live streaming:
enable partial messages (
include_partial_messages
in Python,
includePartialMessages
in TypeScript) to get
StreamEvent
messages in real time. See
Stream responses in real-time
.
How you check message types depends on the SDK:
Python:
check message types with
isinstance()
against classes imported from
claude_agent_sdk
(for example,
isinstance(message, ResultMessage)
).
TypeScript:
check the
type
string field (for example,
message.type === "result"
).
AssistantMessage
and
UserMessage
wrap the raw API message in a
.message
field, so content blocks are at
message.message.content
, not
message.content
.
Example: Check message types and handle results
Python
TypeScript
from
claude_agent_sdk
import
query, AssistantMessage, ResultMessage
async
for
message
in
query(
prompt
=
"Summarize this project"
):
if
isinstance
(message, AssistantMessage):
print
(
f
"Turn completed:
{
len
(message.content)
}
content blocks"
)
if
isinstance
(message, ResultMessage):
if
message.subtype
==
"success"
:
print
(message.result)
else
:
print
(
f
"Stopped:
{
message.subtype
}
"
)
​
Tool execution
Tools give your agent the ability to take action. Without tools, Claude can only respond with text. With tools, Claude can read files, run commands, search code, and interact with external services.
​
Built-in tools
The SDK includes the same tools that power Claude Code:
Category
Tools
What they do
File operations
Read
,
Edit
,
Write
Read, modify, and create files
Search
Glob
,
Grep
Find files by pattern, search content with regex
Execution
Bash
Run shell commands, scripts, git operations
Web
WebSearch
,
WebFetch
Search the web, fetch and parse pages
Discovery
ToolSearch
Dynamically find and load tools on-demand instead of preloading all of them
Orchestration
Agent
,
Skill
,
AskUserQuestion
,
TodoWrite
Spawn subagents, invoke skills, ask the user, track tasks
Beyond built-in tools, you can:
Connect external services
with
MCP servers
(databases, browsers, APIs)
Define custom tools
with
custom tool handlers
Load project skills
via
setting sources
for reusable workflows
​
Tool permissions
Claude determines which tools to call based on the task, but you control whether those calls are allowed to execute. You can auto-approve specific tools, block others entirely, or require approval for everything. Three options work together to determine what runs:
allowed_tools
/
allowedTools
auto-approves listed tools. A read-only agent with
["Read", "Glob", "Grep"]
in its allowed tools list runs those tools without prompting. Tools not listed are still available but require permission.
disallowed_tools
/
disallowedTools
blocks listed tools, regardless of other settings. See
Permissions
for the order that rules are checked before a tool runs.
permission_mode
/
permissionMode
controls what happens to tools that aren’t covered by allow or deny rules. See
Permission mode
for available modes.
You can also scope individual tools with rules like
"Bash(npm *)"
to allow only specific commands. See
Permissions
for the full rule syntax.
When a tool is denied, Claude receives a rejection message as the tool result and typically attempts a different approach or reports that it couldn’t proceed.
​
Parallel tool execution
When Claude requests multiple tool calls in a single turn, both SDKs can run them concurrently or sequentially depending on the tool. Read-only tools (like
Read
,
Glob
,
Grep
, and MCP tools marked as read-only) can run concurrently. Tools that modify state (like
Edit
,
Write
, and
Bash
) run sequentially to avoid conflicts.
Custom tools default to sequential execution. To enable parallel execution for a custom tool, set
readOnlyHint
in its annotations. Both the
TypeScript
and
Python
SDKs use this field name from the MCP SDK.
​
Control how the loop runs
You can limit how many turns the loop takes, how much it costs, how deeply Claude reasons, and whether tools require approval before running. All of these are fields on
ClaudeAgentOptions
(Python) /
Options
(TypeScript).
​
Turns and budget
Option
What it controls
Default
Max turns (
max_turns
/
maxTurns
)
Maximum tool-use round trips
No limit
Max budget (
max_budget_usd
/
maxBudgetUsd
)
Maximum cost before stopping
No limit
When either limit is hit, the SDK returns a
ResultMessage
with a corresponding error subtype (
error_max_turns
or
error_max_budget_usd
). See
Handle the result
for how to check these subtypes and
ClaudeAgentOptions
/
Options
for syntax.
​
Effort level
The
effort
option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See
Effort
for which models support it.
Level
Behavior
Good for
"low"
Minimal reasoning, fast responses
File lookups, listing directories
"medium"
Balanced reasoning
Routine edits, standard tasks
"high"
Thorough analysis
Refactors, debugging
"xhigh"
Extended reasoning depth
Coding and agentic tasks; recommended on Opus 4.7
"max"
Maximum reasoning depth
Multi-step problems requiring deep analysis
If you don’t set
effort
, the Python SDK leaves the parameter unset and defers to the model’s default behavior. The TypeScript SDK defaults to
"high"
.
effort
trades latency and token cost for reasoning depth within each response.
Extended thinking
is a separate feature that produces visible chain-of-thought blocks in the output. They are independent: you can set
effort: "low"
with extended thinking enabled, or
effort: "max"
without it.
Use lower effort for agents doing simple, well-scoped tasks (like listing files or running a single grep) to reduce cost and latency. Set
effort
in the top-level
query()
options for the whole session, or per subagent with the
effort
field on
AgentDefinition
to override the session level.
​
Permission mode
The permission mode option (
permission_mode
in Python,
permissionMode
in TypeScript) controls whether the agent asks for approval before using tools:
Mode
Behavior
"default"
Tools not covered by allow rules trigger your approval callback; no callback means deny
"acceptEdits"
Auto-approves file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.); other Bash commands follow default rules
"plan"
Read-only tools run; Claude explores and produces a plan without editing your source files
"dontAsk"
Never prompts. Tools pre-approved by
permission rules
run, everything else is denied
"auto"
(TypeScript only)
Uses a model classifier to approve or deny each tool call. See
Auto mode
for availability and behavior
"bypassPermissions"
Runs all allowed tools without asking. Cannot be used when running as root on Unix. Use only in isolated environments where the agent’s actions cannot affect systems you care about
For interactive applications, use
"default"
with a tool approval callback to surface approval prompts. For autonomous agents on a dev machine,
"acceptEdits"
auto-approves file edits and common filesystem commands (
mkdir
,
touch
,
mv
,
cp
, etc.) while still gating other
Bash
commands behind allow rules. Reserve
"bypassPermissions"
for CI, containers, or other isolated environments. See
Permissions
for full details.
​
Model
If you don’t set
model
, the SDK uses Claude Code’s default, which depends on your authentication method and subscription. Set it explicitly (for example,
model="claude-sonnet-4-6"
) to pin a specific model or to use a smaller model for faster, cheaper agents. See
models
for available IDs.
​
The context window
The context window is the total amount of information available to Claude during a session. It does not reset between turns within a session. Everything accumulates: the system prompt, tool definitions, conversation history, tool inputs, and tool outputs. Content that stays the same across turns (system prompt, tool definitions, CLAUDE.md) is automatically
prompt cached
, which reduces cost and latency for repeated prefixes.
​
What consumes context
Here’s how each component affects context in the SDK:
Source
When it loads
Impact
System prompt
Every request
Small fixed cost, always present
CLAUDE.md files
Session start, via
settingSources
Full content in every request (but prompt-cached, so only the first request pays full cost)
Tool definitions
Every request; MCP schemas deferred by default
Built-in tool schemas load every request.
Tool search
defers MCP tool schemas by default, falling back to upfront loading on Vertex AI or a non-first-party
ANTHROPIC_BASE_URL
. See
Configure tool search
for the full matrix
Conversation history
Accumulates over turns
Grows with each turn: prompts, responses, tool inputs, tool outputs
Skill descriptions
Session start, via setting sources
Short summaries; full content loads only when invoked
Large tool outputs consume significant context. Reading a big file or running a command with verbose output can use thousands of tokens in a single turn. Context accumulates across turns, so longer sessions with many tool calls build up significantly more context than short ones.
​
Automatic compaction
When the context window approaches its limit, the SDK automatically compacts the conversation: it summarizes older history to free space, keeping your most recent exchanges and key decisions intact. The SDK emits a message with
type: "system"
and
subtype: "compact_boundary"
in the stream when this happens (in Python this is a
SystemMessage
; in TypeScript it is a separate
SDKCompactBoundaryMessage
type).
Compaction replaces older messages with a summary, so specific instructions from early in the conversation may not be preserved. Persistent rules belong in CLAUDE.md (loaded via
settingSources
) rather than in the initial prompt, because CLAUDE.md content is re-injected on every request.
You can customize compaction behavior in several ways:
Summarization instructions in CLAUDE.md:
The compactor reads your CLAUDE.md like any other context, so you can include a section telling it what to preserve when summarizing. The section header is free-form (not a magic string); the compactor matches on intent.
PreCompact
hook:
Run custom logic before compaction occurs, for example to archive the full transcript. The hook receives a
trigger
field (
manual
or
auto
). See
hooks
.
Manual compaction:
Send
/compact
as a prompt string to trigger compaction on demand. (Slash commands sent this way are SDK inputs, not CLI-only shortcuts. See
slash commands in the SDK
.)
Example: Summarization instructions in CLAUDE.md
Add a section to your project’s CLAUDE.md telling the compactor what to preserve. The header name isn’t special; use any clear label.
CLAUDE.md
# Summary instructions
When summarizing this conversation, always preserve:
-
The current task objective and acceptance criteria
-
File paths that have been read or modified
-
Test results and error messages
-
Decisions made and the reasoning behind them
​
Keep context efficient
A few strategies for long-running agents:
Use subagents for subtasks.
Each subagent starts with a fresh conversation (no prior message history, though it does load its own system prompt and project-level context like CLAUDE.md). It does not see the parent’s turns, and only its final response returns to the parent as a tool result. The main agent’s context grows by that summary, not by the full subtask transcript. See
What subagents inherit
for details.
Be selective with tools.
Every tool definition takes context space. Use the
tools
field on
AgentDefinition
to scope subagents to the minimum set they need.
Watch MCP server costs.
MCP tool search
defers MCP tool schemas by default and loads them on demand. When tool search is off, on Vertex AI, or behind a non-first-party
ANTHROPIC_BASE_URL
, each MCP server adds all its tool schemas to every request, so a few servers with many tools can consume significant context before the agent does any work.
Use lower effort for routine tasks.
Set
effort
to
"low"
for agents that only need to read files or list directories. This reduces token usage and cost.
For a detailed breakdown of per-feature context costs, see
Understand context costs
.
​
Sessions and continuity
Each interaction with the SDK creates or continues a session. Capture the session ID from
ResultMessage.session_id
(available in both SDKs) to resume later. The TypeScript SDK also exposes it as a direct field on the init
SystemMessage
; in Python it’s nested in
SystemMessage.data
.
When you resume, the full context from previous turns is restored: files that were read, analysis that was performed, and actions that were taken. You can also fork a session to branch into a different approach without modifying the original.
See
Session management
for the full guide on resume, continue, and fork patterns.
In Python,
ClaudeSDKClient
handles session IDs automatically across multiple calls. See the
Python SDK reference
for details.
​
Handle the result
When the loop ends, the
ResultMessage
tells you what happened and gives you the output. The
subtype
field (available in both SDKs) is the primary way to check termination state.
Result subtype
What happened
result
field available?
success
Claude finished the task normally
Yes
error_max_turns
Hit the
maxTurns
limit before finishing
No
error_max_budget_usd
Hit the
maxBudgetUsd
limit before finishing
No
error_during_execution
An error interrupted the loop (for example, an API failure or cancelled request)
No
error_max_structured_output_retries
Structured output validation failed after the configured retry limit
No
The
result
field (the final text output) is only present on the
success
variant, so always check the subtype before reading it. All result subtypes carry
total_cost_usd
,
usage
,
num_turns
, and
session_id
so you can track cost and resume even after errors. In Python,
total_cost_usd
and
usage
are typed as optional and may be
None
on some error paths, so guard before formatting them. See
Tracking costs and usage
for details on interpreting the
usage
fields.
The result also includes a
stop_reason
field (
string | null
in TypeScript,
str | None
in Python) indicating why the model stopped generating on its final turn. Common values are
end_turn
(model finished normally),
max_tokens
(hit the output token limit), and
refusal
(the model declined the request). On error result subtypes,
stop_reason
carries the value from the last assistant response before the loop ended. To detect refusals, check
stop_reason === "refusal"
(TypeScript) or
stop_reason == "refusal"
(Python). See
SDKResultMessage
(TypeScript) or
ResultMessage
(Python) for the full type.
​
Hooks
Hooks
are callbacks that fire at specific points in the loop: before a tool runs, after it returns, when the agent finishes, and so on. Some commonly used hooks are:
Hook
When it fires
Common uses
PreToolUse
Before a tool executes
Validate inputs, block dangerous commands
PostToolUse
After a tool returns
Audit outputs, trigger side effects
UserPromptSubmit
When a prompt is sent
Inject additional context into prompts
Stop
When the agent finishes
Validate the result, save session state
SubagentStart
/
SubagentStop
When a subagent spawns or completes
Track and aggregate parallel task results
PreCompact
Before context compaction
Archive full transcript before summarizing
Hooks run in your application process, not inside the agent’s context window, so they don’t consume context. Hooks can also short-circuit the loop: a
PreToolUse
hook that rejects a tool call prevents it from executing, and Claude receives the rejection message instead.
Both SDKs support all the events above. The TypeScript SDK includes additional events that Python does not yet support. See
Control execution with hooks
for the complete event list, per-SDK availability, and the full callback API.
​
Put it all together
This example combines the key concepts from this page into a single agent that fixes failing tests. It configures the agent with allowed tools (auto-approved so the agent runs autonomously), project settings, and safety limits on turns and reasoning effort. As the loop runs, it captures the session ID for potential resumption, handles the final result, and prints the total cost.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
async
def
run_agent
():
session_id
=
None
async
for
message
in
query(
prompt
=
"Find and fix the bug causing test failures in the auth module"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Edit"
,
"Bash"
,
"Glob"
,
"Grep"
,
],
# Listing tools here auto-approves them (no prompting)
setting_sources
=
[
"project"
],
# Load CLAUDE.md, skills, hooks from current directory
max_turns
=
30
,
# Prevent runaway sessions
effort
=
"high"
,
# Thorough reasoning for complex debugging
),
):
# Handle the final result
if
isinstance
(message, ResultMessage):
session_id
=
message.session_id
# Save for potential resumption
if
message.subtype
==
"success"
:
print
(
f
"Done:
{
message.result
}
"
)
elif
message.subtype
==
"error_max_turns"
:
# Agent ran out of turns. Resume with a higher limit.
print
(
f
"Hit turn limit. Resume session
{
session_id
}
to continue."
)
elif
message.subtype
==
"error_max_budget_usd"
:
print
(
"Hit budget limit."
)
else
:
print
(
f
"Stopped:
{
message.subtype
}
"
)
if
message.total_cost_usd
is
not
None
:
print
(
f
"Cost: $
{
message.total_cost_usd
:.4f}
"
)
asyncio.run(run_agent())
​
Next steps
Now that you understand the loop, here’s where to go depending on what you’re building:
Haven’t run an agent yet?
Start with the
quickstart
to get the SDK installed and see a full example running end to end.
Ready to hook into your project?
Load CLAUDE.md, skills, and filesystem hooks
so the agent follows your project conventions automatically.
Building an interactive UI?
Enable
streaming
to show live text and tool calls as the loop runs.
Need tighter control over what the agent can do?
Lock down tool access with
permissions
, and use
hooks
to audit, block, or transform tool calls before they execute.
Running long or expensive tasks?
Offload isolated work to
subagents
to keep your main context lean.
For the broader conceptual picture of the agentic loop (not SDK-specific), see
How Claude Code works
.
Was this page helpful?
Yes
No
Quickstart
Use Claude Code features
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/agent-loop" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Week 19 · May 4–8, 2026</title>
  <link>https://code.claude.com/docs/en/whats-new/2026-w19</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/whats-new/2026-w19</guid>
  <pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 19 · May 4–8, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.128 → v2.1.136
2 features · M...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 19 · May 4–8, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.128 → v2.1.136
2 features · May 4–8
Plugins from .zip archives and URLs
--plugin-dir
now accepts a
.zip
plugin archive in addition to a directory, and the new
--plugin-url
flag fetches a plugin archive from a URL for the current session. Useful for trying a plugin before adding it to a marketplace, or for shipping internal plugins from an artifact store.
Load a plugin straight from a URL:
terminal
claude
--plugin-url
https://example.com/my-plugin.zip
Plugins guide
History search across all your projects
v2.1.129
Ctrl+R
reverse-search now defaults to all prompts across every project, restoring the behavior from before v2.1.124. Press
Ctrl+S
while searching to narrow back to the current project or session. Handy when you remember a command you ran in another repo last week and don’t want to go digging for it.
Interactive mode: command history
Other wins
New
worktree.baseRef
setting (
fresh
|
head
) controls whether
—worktree
, the
EnterWorktree
tool, and agent-isolation worktrees branch from the remote default branch or local
HEAD
; the default
fresh
keeps unpushed commits out of new worktrees
New
settings.autoMode.hard_deny
rules block matching actions unconditionally in auto mode, regardless of allow exceptions, for actions that should never run automatically even when broader allow rules apply
Hooks now receive the active effort level via the
effort.level
JSON input field and the
$CLAUDE_EFFORT
environment variable, and Bash tool commands can read
$CLAUDE_EFFORT
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1
opts out of the fullscreen alternate-screen renderer and keeps the conversation in the terminal’s native scrollback
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
lets Homebrew or WinGet installations run the upgrade in the background and prompt to restart
CLAUDE_CODE_SESSION_ID
is now in the Bash tool subprocess environment, matching the
session_id
passed to hooks
/mcp
now shows the tool count for connected servers and flags servers that connected with 0 tools
—channels
now works with console (API key) authentication
Subprocesses such as Bash, hooks, MCP, and LSP no longer inherit
OTEL_*
environment variables, so OTEL-instrumented apps run via the Bash tool no longer pick up the CLI’s own OTLP endpoint
Sub-agent progress summaries now hit the prompt cache, cutting
cache_creation
token cost by roughly 3x
Several OAuth and credential reliability fixes: parallel sessions no longer dead-end at 401 after a refresh-token race, MCP OAuth refresh tokens are no longer lost when multiple servers refresh concurrently, and a rare login loop from a concurrent credential write is fixed
New
parentSettingsBehavior
admin key lets admins opt SDK
managedSettings
into the policy merge
Full changelog for v2.1.128–v2.1.136 →
Was this page helpful?
Yes
No
What's new
Week 18 · Apr 27 – May 1
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w19" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What&apos;s New
Week 19 · May 4–8, 2026
What&apos;s New
What&apos;s new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.128 → v2.1.136
2 features · M...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
What's New
Week 19 · May 4–8, 2026
What's New
What's new
Week 19 · May 4–8
Week 18 · Apr 27 – May 1
Week 17 · Apr 20–24
Week 16 · Apr 13–17
Week 15 · Apr 6–10
Week 14 · Mar 30 – Apr 3
Week 13 · Mar 23–27
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Releases
v2.1.128 → v2.1.136
2 features · May 4–8
Plugins from .zip archives and URLs
--plugin-dir
now accepts a
.zip
plugin archive in addition to a directory, and the new
--plugin-url
flag fetches a plugin archive from a URL for the current session. Useful for trying a plugin before adding it to a marketplace, or for shipping internal plugins from an artifact store.
Load a plugin straight from a URL:
terminal
claude
--plugin-url
https://example.com/my-plugin.zip
Plugins guide
History search across all your projects
v2.1.129
Ctrl+R
reverse-search now defaults to all prompts across every project, restoring the behavior from before v2.1.124. Press
Ctrl+S
while searching to narrow back to the current project or session. Handy when you remember a command you ran in another repo last week and don’t want to go digging for it.
Interactive mode: command history
Other wins
New
worktree.baseRef
setting (
fresh
|
head
) controls whether
—worktree
, the
EnterWorktree
tool, and agent-isolation worktrees branch from the remote default branch or local
HEAD
; the default
fresh
keeps unpushed commits out of new worktrees
New
settings.autoMode.hard_deny
rules block matching actions unconditionally in auto mode, regardless of allow exceptions, for actions that should never run automatically even when broader allow rules apply
Hooks now receive the active effort level via the
effort.level
JSON input field and the
$CLAUDE_EFFORT
environment variable, and Bash tool commands can read
$CLAUDE_EFFORT
CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1
opts out of the fullscreen alternate-screen renderer and keeps the conversation in the terminal’s native scrollback
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
lets Homebrew or WinGet installations run the upgrade in the background and prompt to restart
CLAUDE_CODE_SESSION_ID
is now in the Bash tool subprocess environment, matching the
session_id
passed to hooks
/mcp
now shows the tool count for connected servers and flags servers that connected with 0 tools
—channels
now works with console (API key) authentication
Subprocesses such as Bash, hooks, MCP, and LSP no longer inherit
OTEL_*
environment variables, so OTEL-instrumented apps run via the Bash tool no longer pick up the CLI’s own OTLP endpoint
Sub-agent progress summaries now hit the prompt cache, cutting
cache_creation
token cost by roughly 3x
Several OAuth and credential reliability fixes: parallel sessions no longer dead-end at 401 after a refresh-token race, MCP OAuth refresh tokens are no longer lost when multiple servers refresh concurrently, and a rare login loop from a concurrent credential write is fixed
New
parentSettingsBehavior
admin key lets admins opt SDK
managedSettings
into the policy merge
Full changelog for v2.1.128–v2.1.136 →
Was this page helpful?
Yes
No
What's new
Week 18 · Apr 27 – May 1
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/whats-new/2026-w19" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Enterprise deployment overview</title>
  <link>https://code.claude.com/docs/en/third-party-integrations</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/third-party-integrations</guid>
  <pubDate>Wed, 31 Jan 2024 00:00:00 +0000</pubDate>
  <category>Integrations</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise deployment overview
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketp...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise deployment overview
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Organizations can deploy Claude Code through Anthropic directly or through a cloud provider. This page helps you choose the right configuration.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Compare deployment options
For most organizations, Claude for Teams or Claude for Enterprise provides the best experience. Team members get access to both Claude Code and Claude on the web with a single subscription, centralized billing, and no infrastructure setup required.
Claude for Teams
is self-service and includes collaboration features, admin tools, and billing management. Best for smaller teams that need to get started quickly.
Claude for Enterprise
adds SSO and domain capture, role-based permissions, compliance API access, and managed policy settings for deploying organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.
Learn more about
Team plans
and
Enterprise plans
.
If your organization has specific infrastructure requirements, compare the options below:
Feature
Claude for Teams/Enterprise
Anthropic Console
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Best for
Most organizations (recommended)
Individual developers
AWS-native deployments
AWS Marketplace billing with Claude API features
GCP-native deployments
Azure-native deployments
Billing
Teams:
$150/seat (Premium) with PAYG available
Enterprise:
Contact Sales
PAYG
PAYG through AWS
PAYG through AWS Marketplace
PAYG through GCP
PAYG through Azure
Regions
Supported
countries
Supported
countries
Multiple AWS
regions
Multiple AWS regions
Multiple GCP
regions
Multiple Azure
regions
Prompt caching
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Authentication
Claude.ai SSO or email
API key
API key or AWS credentials
API key or AWS credentials
GCP credentials
API key or Microsoft Entra ID
Cost tracking
Usage dashboard
Usage dashboard
AWS Cost Explorer
AWS Cost Explorer
GCP Billing
Azure Cost Management
Includes Claude on web
Yes
No
No
No
No
No
Enterprise features
Team management, SSO, usage monitoring
None
IAM policies, CloudTrail
IAM policies, CloudTrail
IAM roles, Cloud Audit Logs
RBAC policies, Azure Monitor
Select a deployment option to view setup instructions:
Claude for Teams or Enterprise
Anthropic Console
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
​
Configure proxies and gateways
Most organizations can use a cloud provider directly without additional configuration. However, you may need to configure a corporate proxy or LLM gateway if your organization has specific network or management requirements. These are different configurations that can be used together:
Corporate proxy
: Routes traffic through an HTTP/HTTPS proxy. Use this if your organization requires all outbound traffic to pass through a proxy server for security monitoring, compliance, or network policy enforcement. Configure with the
HTTPS_PROXY
or
HTTP_PROXY
environment variables. Learn more in
Enterprise network configuration
.
LLM Gateway
: A service that sits between Claude Code and the cloud provider to handle authentication and routing. Use this if you need centralized usage tracking across teams, custom rate limiting or budgets, or centralized authentication management. Configure with the
ANTHROPIC_BASE_URL
,
ANTHROPIC_BEDROCK_BASE_URL
,
ANTHROPIC_AWS_BASE_URL
, or
ANTHROPIC_VERTEX_BASE_URL
environment variables. Learn more in
LLM gateway configuration
.
The following examples show the environment variables to set in your shell or shell profile (
.bashrc
,
.zshrc
). See
Settings
for other configuration methods.
​
Amazon Bedrock
Corporate proxy
LLM Gateway
Route Bedrock traffic through your corporate proxy by setting the following
environment variables
:
# Enable Bedrock
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
AWS_REGION
=
us-east-1
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Bedrock traffic through your LLM gateway by setting the following
environment variables
:
# Enable Bedrock
export
CLAUDE_CODE_USE_BEDROCK
=
1
# Configure LLM gateway
export
ANTHROPIC_BEDROCK_BASE_URL
=
'https://your-llm-gateway.com/bedrock'
export
CLAUDE_CODE_SKIP_BEDROCK_AUTH
=
1
# If gateway handles AWS auth
​
Microsoft Foundry
Corporate proxy
LLM Gateway
Route Foundry traffic through your corporate proxy by setting the following
environment variables
:
# Enable Microsoft Foundry
export
CLAUDE_CODE_USE_FOUNDRY
=
1
export
ANTHROPIC_FOUNDRY_RESOURCE
=
your-resource
export
ANTHROPIC_FOUNDRY_API_KEY
=
your-api-key
# Or omit for Entra ID auth
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Foundry traffic through your LLM gateway by setting the following
environment variables
:
# Enable Microsoft Foundry
export
CLAUDE_CODE_USE_FOUNDRY
=
1
# Configure LLM gateway
export
ANTHROPIC_FOUNDRY_BASE_URL
=
'https://your-llm-gateway.com'
export
CLAUDE_CODE_SKIP_FOUNDRY_AUTH
=
1
# If gateway handles Azure auth
​
Google Vertex AI
Corporate proxy
LLM Gateway
Route Vertex AI traffic through your corporate proxy by setting the following
environment variables
:
# Enable Vertex
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
us-east5
export
ANTHROPIC_VERTEX_PROJECT_ID
=
your-project-id
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Vertex AI traffic through your LLM gateway by setting the following
environment variables
:
# Enable Vertex
export
CLAUDE_CODE_USE_VERTEX
=
1
# Configure LLM gateway
export
ANTHROPIC_VERTEX_BASE_URL
=
'https://your-llm-gateway.com/vertex'
export
CLAUDE_CODE_SKIP_VERTEX_AUTH
=
1
# If gateway handles GCP auth
Use
/status
in Claude Code to verify your proxy and gateway configuration is applied correctly.
​
Best practices for organizations
​
Invest in documentation and memory
We strongly recommend investing in documentation so that Claude Code understands your codebase. Organizations can deploy CLAUDE.md files at multiple levels:
Organization-wide
: Deploy to system directories like
/Library/Application Support/ClaudeCode/CLAUDE.md
(macOS) for company-wide standards
Repository-level
: Create
CLAUDE.md
files in repository roots containing project architecture, build commands, and contribution guidelines. Check these into source control so all users benefit
Learn more in
Memory and CLAUDE.md files
.
​
Simplify deployment
If you have a custom development environment, we find that creating a “one click” way to install Claude Code is key to growing adoption across an organization.
​
Start with guided usage
Encourage new users to try Claude Code for codebase Q&A, or on smaller bug fixes or feature requests. Ask Claude Code to make a plan. Check Claude’s suggestions and give feedback if it’s off-track. Over time, as users understand this new paradigm better, then they’ll be more effective at letting Claude Code run more agentically.
​
Pin model versions for cloud providers
If you deploy through
Bedrock
,
Vertex AI
,
Foundry
, or
Claude Platform on AWS
, pin specific model versions using
ANTHROPIC_DEFAULT_OPUS_MODEL
,
ANTHROPIC_DEFAULT_SONNET_MODEL
, and
ANTHROPIC_DEFAULT_HAIKU_MODEL
. Without pinning, model aliases resolve to the latest version, which may not yet be enabled in your account when Anthropic releases an update. Pinning lets you control when your users move to a new model. See
Model configuration
for what each provider does when the latest version is unavailable.
​
Configure security policies
Security teams can configure managed permissions for what Claude Code is and is not allowed to do, which cannot be overwritten by local configuration.
Learn more
.
​
Leverage MCP for integrations
MCP is a great way to give Claude Code more information, such as connecting to ticket management systems or error logs. We recommend that one central team configures MCP servers and checks a
.mcp.json
configuration into the codebase so that all users benefit.
Learn more
.
At Anthropic, we trust Claude Code to power development across every Anthropic codebase. We hope you enjoy using Claude Code as much as we do.
​
Next steps
Once you’ve chosen a deployment option and configured access for your team:
Roll out to your team
: Share installation instructions and have team members
install Claude Code
and authenticate with their credentials.
Set up shared configuration
: Create a
CLAUDE.md file
in your repositories to help Claude Code understand your codebase and coding standards.
Configure permissions
: Review
security settings
to define what Claude Code can and cannot do in your environment.
Was this page helpful?
Yes
No
Auto mode
Amazon Bedrock
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/third-party-integrations" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise deployment overview
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketp...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Enterprise deployment overview
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Organizations can deploy Claude Code through Anthropic directly or through a cloud provider. This page helps you choose the right configuration.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Compare deployment options
For most organizations, Claude for Teams or Claude for Enterprise provides the best experience. Team members get access to both Claude Code and Claude on the web with a single subscription, centralized billing, and no infrastructure setup required.
Claude for Teams
is self-service and includes collaboration features, admin tools, and billing management. Best for smaller teams that need to get started quickly.
Claude for Enterprise
adds SSO and domain capture, role-based permissions, compliance API access, and managed policy settings for deploying organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.
Learn more about
Team plans
and
Enterprise plans
.
If your organization has specific infrastructure requirements, compare the options below:
Feature
Claude for Teams/Enterprise
Anthropic Console
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Best for
Most organizations (recommended)
Individual developers
AWS-native deployments
AWS Marketplace billing with Claude API features
GCP-native deployments
Azure-native deployments
Billing
Teams:
$150/seat (Premium) with PAYG available
Enterprise:
Contact Sales
PAYG
PAYG through AWS
PAYG through AWS Marketplace
PAYG through GCP
PAYG through Azure
Regions
Supported
countries
Supported
countries
Multiple AWS
regions
Multiple AWS regions
Multiple GCP
regions
Multiple Azure
regions
Prompt caching
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Enabled by default
Authentication
Claude.ai SSO or email
API key
API key or AWS credentials
API key or AWS credentials
GCP credentials
API key or Microsoft Entra ID
Cost tracking
Usage dashboard
Usage dashboard
AWS Cost Explorer
AWS Cost Explorer
GCP Billing
Azure Cost Management
Includes Claude on web
Yes
No
No
No
No
No
Enterprise features
Team management, SSO, usage monitoring
None
IAM policies, CloudTrail
IAM policies, CloudTrail
IAM roles, Cloud Audit Logs
RBAC policies, Azure Monitor
Select a deployment option to view setup instructions:
Claude for Teams or Enterprise
Anthropic Console
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
​
Configure proxies and gateways
Most organizations can use a cloud provider directly without additional configuration. However, you may need to configure a corporate proxy or LLM gateway if your organization has specific network or management requirements. These are different configurations that can be used together:
Corporate proxy
: Routes traffic through an HTTP/HTTPS proxy. Use this if your organization requires all outbound traffic to pass through a proxy server for security monitoring, compliance, or network policy enforcement. Configure with the
HTTPS_PROXY
or
HTTP_PROXY
environment variables. Learn more in
Enterprise network configuration
.
LLM Gateway
: A service that sits between Claude Code and the cloud provider to handle authentication and routing. Use this if you need centralized usage tracking across teams, custom rate limiting or budgets, or centralized authentication management. Configure with the
ANTHROPIC_BASE_URL
,
ANTHROPIC_BEDROCK_BASE_URL
,
ANTHROPIC_AWS_BASE_URL
, or
ANTHROPIC_VERTEX_BASE_URL
environment variables. Learn more in
LLM gateway configuration
.
The following examples show the environment variables to set in your shell or shell profile (
.bashrc
,
.zshrc
). See
Settings
for other configuration methods.
​
Amazon Bedrock
Corporate proxy
LLM Gateway
Route Bedrock traffic through your corporate proxy by setting the following
environment variables
:
# Enable Bedrock
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
AWS_REGION
=
us-east-1
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Bedrock traffic through your LLM gateway by setting the following
environment variables
:
# Enable Bedrock
export
CLAUDE_CODE_USE_BEDROCK
=
1
# Configure LLM gateway
export
ANTHROPIC_BEDROCK_BASE_URL
=
'https://your-llm-gateway.com/bedrock'
export
CLAUDE_CODE_SKIP_BEDROCK_AUTH
=
1
# If gateway handles AWS auth
​
Microsoft Foundry
Corporate proxy
LLM Gateway
Route Foundry traffic through your corporate proxy by setting the following
environment variables
:
# Enable Microsoft Foundry
export
CLAUDE_CODE_USE_FOUNDRY
=
1
export
ANTHROPIC_FOUNDRY_RESOURCE
=
your-resource
export
ANTHROPIC_FOUNDRY_API_KEY
=
your-api-key
# Or omit for Entra ID auth
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Foundry traffic through your LLM gateway by setting the following
environment variables
:
# Enable Microsoft Foundry
export
CLAUDE_CODE_USE_FOUNDRY
=
1
# Configure LLM gateway
export
ANTHROPIC_FOUNDRY_BASE_URL
=
'https://your-llm-gateway.com'
export
CLAUDE_CODE_SKIP_FOUNDRY_AUTH
=
1
# If gateway handles Azure auth
​
Google Vertex AI
Corporate proxy
LLM Gateway
Route Vertex AI traffic through your corporate proxy by setting the following
environment variables
:
# Enable Vertex
export
CLAUDE_CODE_USE_VERTEX
=
1
export
CLOUD_ML_REGION
=
us-east5
export
ANTHROPIC_VERTEX_PROJECT_ID
=
your-project-id
# Configure corporate proxy
export
HTTPS_PROXY
=
'https://proxy.example.com:8080'
Route Vertex AI traffic through your LLM gateway by setting the following
environment variables
:
# Enable Vertex
export
CLAUDE_CODE_USE_VERTEX
=
1
# Configure LLM gateway
export
ANTHROPIC_VERTEX_BASE_URL
=
'https://your-llm-gateway.com/vertex'
export
CLAUDE_CODE_SKIP_VERTEX_AUTH
=
1
# If gateway handles GCP auth
Use
/status
in Claude Code to verify your proxy and gateway configuration is applied correctly.
​
Best practices for organizations
​
Invest in documentation and memory
We strongly recommend investing in documentation so that Claude Code understands your codebase. Organizations can deploy CLAUDE.md files at multiple levels:
Organization-wide
: Deploy to system directories like
/Library/Application Support/ClaudeCode/CLAUDE.md
(macOS) for company-wide standards
Repository-level
: Create
CLAUDE.md
files in repository roots containing project architecture, build commands, and contribution guidelines. Check these into source control so all users benefit
Learn more in
Memory and CLAUDE.md files
.
​
Simplify deployment
If you have a custom development environment, we find that creating a “one click” way to install Claude Code is key to growing adoption across an organization.
​
Start with guided usage
Encourage new users to try Claude Code for codebase Q&A, or on smaller bug fixes or feature requests. Ask Claude Code to make a plan. Check Claude’s suggestions and give feedback if it’s off-track. Over time, as users understand this new paradigm better, then they’ll be more effective at letting Claude Code run more agentically.
​
Pin model versions for cloud providers
If you deploy through
Bedrock
,
Vertex AI
,
Foundry
, or
Claude Platform on AWS
, pin specific model versions using
ANTHROPIC_DEFAULT_OPUS_MODEL
,
ANTHROPIC_DEFAULT_SONNET_MODEL
, and
ANTHROPIC_DEFAULT_HAIKU_MODEL
. Without pinning, model aliases resolve to the latest version, which may not yet be enabled in your account when Anthropic releases an update. Pinning lets you control when your users move to a new model. See
Model configuration
for what each provider does when the latest version is unavailable.
​
Configure security policies
Security teams can configure managed permissions for what Claude Code is and is not allowed to do, which cannot be overwritten by local configuration.
Learn more
.
​
Leverage MCP for integrations
MCP is a great way to give Claude Code more information, such as connecting to ticket management systems or error logs. We recommend that one central team configures MCP servers and checks a
.mcp.json
configuration into the codebase so that all users benefit.
Learn more
.
At Anthropic, we trust Claude Code to power development across every Anthropic codebase. We hope you enjoy using Claude Code as much as we do.
​
Next steps
Once you’ve chosen a deployment option and configured access for your team:
Roll out to your team
: Share installation instructions and have team members
install Claude Code
and authenticate with their credentials.
Set up shared configuration
: Create a
CLAUDE.md file
in your repositories to help Claude Code understand your codebase and coding standards.
Configure permissions
: Review
security settings
to define what Claude Code can and cannot do in your environment.
Was this page helpful?
Yes
No
Auto mode
Amazon Bedrock
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/third-party-integrations" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Run agents in parallel</title>
  <link>https://code.claude.com/docs/en/agents</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agents</guid>
  <pubDate>Mon, 29 Jan 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run agents in parallel
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run agents in parallel
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents
,
agent view
,
agent teams
, and
worktrees
each parallelize work in a different way. The right one depends on whether you want to stay in each conversation yourself, hand tasks off and check back later, or have Claude coordinate a group of workers for you.
Approach
What it gives you
Use it when
Subagents
Delegated workers inside one session that do a side task in their own context and return a summary
A side task would flood your main conversation with search results, logs, or file contents you won’t reference again
Agent view
One screen to dispatch and monitor sessions running in the background, opened with
claude agents
. Research preview
You have several independent tasks and want to hand them off, check status at a glance, and step in only when one needs you
Agent teams
Multiple coordinated sessions with a shared task list and inter-agent messaging, managed by a lead. Experimental and disabled by default
You want Claude to split a project into pieces, assign them, and keep the workers in sync
Worktrees
Separate git checkouts so parallel sessions never touch each other’s files
You’re running several sessions yourself, or your subagents edit overlapping files
/batch
A planned split of one large change into 5 to 30 worktree-isolated subagents that each open a pull request
A repo-wide migration or mechanical refactor you can describe in one instruction
In every approach the workers are Claude sessions. To involve a different tool, expose it to Claude as an
MCP server
.
You can combine these approaches. Agent view automatically moves each dispatched session into its own worktree when it needs to edit files, and a session you’re working in can spawn subagents that each get their own worktree.
Running several sessions or subagents at once multiplies token usage. See
Costs
for usage and rate-limit details.
​
Choose an approach
The right approach depends on who coordinates the work, whether the workers need to communicate, and whether they edit the same files:
Who coordinates the work?
If you want Claude to delegate and collect results inside one conversation, use
subagents
. If you’re handing off independent tasks and checking back on them, use
agent view
. If you want Claude to plan, assign, and supervise a group of workers, use
agent teams
, which are experimental and disabled by default.
Do the workers need to talk to each other?
Subagents report results back to the conversation that spawned them, and agent view sessions report only to you. Teammates in an agent team share a task list and message each other directly.
Do the tasks touch the same files?
Isolate the work with
worktrees
. Subagents and sessions you run yourself can each use a separate worktree. Agent teams don’t isolate teammates in worktrees, so
partition the work
so each teammate owns a different set of files.
​
Check on running work
The command for checking on running work depends on which approach you used:
For background sessions,
claude agents
opens
agent view
: one screen showing every session, its state, and which ones need your input.
For subagents in the current session,
/agents
opens a panel with a
Running
tab listing live subagents and a
Library
tab where you
create and edit custom subagents
. Despite the similar name, this is separate from
claude agents
.
For anything running in the background of the current session,
/tasks
lists each item and lets you check on, attach to, or stop it.
For a desktop view of all your sessions, see
parallel sessions in the desktop app
.
​
Learn more
Each guide below covers setup and configuration for one approach:
Create custom subagents
: define reusable specialists and control which tools they can use.
Manage agents with agent view
: dispatch sessions, watch their state, and attach when one needs you.
Orchestrate agent teams
: set up a lead and teammates, assign tasks, and review their work.
Run parallel sessions with worktrees
: start Claude in an isolated checkout, control what gets copied in, and clean up afterward.
Was this page helpful?
Yes
No
Create custom subagents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run agents in parallel
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions ...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Agents and parallel work
Run agents in parallel
Agents and parallel work
Overview
Create custom subagents
Agent view
Run agent teams
Isolate sessions with worktrees
Tools and plugins
Model Context Protocol (MCP)
Discover and install prebuilt plugins
Create plugins
Extend Claude with skills
Automation
Automate with hooks
Push external events to Claude
Run prompts on a schedule
Goals
Programmatic usage
Launch sessions from links
Troubleshooting
Troubleshoot installation and login
Troubleshoot performance and stability
Debug configuration
Error reference
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents
,
agent view
,
agent teams
, and
worktrees
each parallelize work in a different way. The right one depends on whether you want to stay in each conversation yourself, hand tasks off and check back later, or have Claude coordinate a group of workers for you.
Approach
What it gives you
Use it when
Subagents
Delegated workers inside one session that do a side task in their own context and return a summary
A side task would flood your main conversation with search results, logs, or file contents you won’t reference again
Agent view
One screen to dispatch and monitor sessions running in the background, opened with
claude agents
. Research preview
You have several independent tasks and want to hand them off, check status at a glance, and step in only when one needs you
Agent teams
Multiple coordinated sessions with a shared task list and inter-agent messaging, managed by a lead. Experimental and disabled by default
You want Claude to split a project into pieces, assign them, and keep the workers in sync
Worktrees
Separate git checkouts so parallel sessions never touch each other’s files
You’re running several sessions yourself, or your subagents edit overlapping files
/batch
A planned split of one large change into 5 to 30 worktree-isolated subagents that each open a pull request
A repo-wide migration or mechanical refactor you can describe in one instruction
In every approach the workers are Claude sessions. To involve a different tool, expose it to Claude as an
MCP server
.
You can combine these approaches. Agent view automatically moves each dispatched session into its own worktree when it needs to edit files, and a session you’re working in can spawn subagents that each get their own worktree.
Running several sessions or subagents at once multiplies token usage. See
Costs
for usage and rate-limit details.
​
Choose an approach
The right approach depends on who coordinates the work, whether the workers need to communicate, and whether they edit the same files:
Who coordinates the work?
If you want Claude to delegate and collect results inside one conversation, use
subagents
. If you’re handing off independent tasks and checking back on them, use
agent view
. If you want Claude to plan, assign, and supervise a group of workers, use
agent teams
, which are experimental and disabled by default.
Do the workers need to talk to each other?
Subagents report results back to the conversation that spawned them, and agent view sessions report only to you. Teammates in an agent team share a task list and message each other directly.
Do the tasks touch the same files?
Isolate the work with
worktrees
. Subagents and sessions you run yourself can each use a separate worktree. Agent teams don’t isolate teammates in worktrees, so
partition the work
so each teammate owns a different set of files.
​
Check on running work
The command for checking on running work depends on which approach you used:
For background sessions,
claude agents
opens
agent view
: one screen showing every session, its state, and which ones need your input.
For subagents in the current session,
/agents
opens a panel with a
Running
tab listing live subagents and a
Library
tab where you
create and edit custom subagents
. Despite the similar name, this is separate from
claude agents
.
For anything running in the background of the current session,
/tasks
lists each item and lets you check on, attach to, or stop it.
For a desktop view of all your sessions, see
parallel sessions in the desktop app
.
​
Learn more
Each guide below covers setup and configuration for one approach:
Create custom subagents
: define reusable specialists and control which tools they can use.
Manage agents with agent view
: dispatch sessions, watch their state, and attach when one needs you.
Orchestrate agent teams
: set up a lead and teammates, assign tasks, and review their work.
Run parallel sessions with worktrees
: start Claude in an isolated checkout, control what gets copied in, and clean up afterward.
Was this page helpful?
Yes
No
Create custom subagents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Let Claude use your computer from the CLI</title>
  <link>https://code.claude.com/docs/en/computer-use</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/computer-use</guid>
  <pubDate>Fri, 26 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Let Claude use your computer from the CLI
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Let Claude use your computer from the CLI
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Computer use is a research preview on macOS that requires a Pro or Max plan. It is not available on Team or Enterprise plans. It requires Claude Code v2.1.85 or later and an interactive session, so it is not available in non-interactive mode with the
-p
flag.
Computer use lets Claude open apps, control your screen, and work on your machine the way you would. From the CLI, Claude can compile a Swift app, launch it, click through every button, and screenshot the result, all in the same conversation where it wrote the code.
This page covers how computer use works in the CLI. For the Desktop app on macOS or Windows, see
computer use in Desktop
.
​
What you can do with computer use
Computer use handles tasks that require a GUI: anything you’d normally have to leave the terminal and do by hand.
Build and validate native apps
: ask Claude to build a macOS menu bar app. Claude writes the Swift, compiles it, launches it, and clicks through every control to verify it works before you ever open it.
End-to-end UI testing
: point Claude at a local Electron app and say “test the onboarding flow.” Claude opens the app, clicks through signup, and screenshots each step. No Playwright config, no test harness.
Debug visual and layout issues
: tell Claude “the modal is clipping on small windows.” Claude resizes the window, reproduces the bug, screenshots it, patches the CSS, and verifies the fix. Claude sees what you see.
Drive GUI-only tools
: interact with design tools, hardware control panels, the iOS Simulator, or proprietary apps that have no CLI or API.
​
When computer use applies
Claude has several ways to interact with an app or service. Computer use is the broadest and slowest, so Claude tries the most precise tool first:
If you have an
MCP server
for the service, Claude uses that.
If the task is a shell command, Claude uses Bash.
If the task is browser work and you have
Claude in Chrome
set up, Claude uses that.
If none of those apply, Claude uses computer use.
Screen control is reserved for things nothing else can reach: native apps, simulators, and tools without an API.
​
Enable computer use
Computer use is available as a built-in MCP server called
computer-use
. It’s off by default until you enable it.
1
Open the MCP menu
In an interactive Claude Code session, run:
/mcp
Find
computer-use
in the server list. It shows as disabled.
2
Enable the server
Select
computer-use
and choose
Enable
. The setting persists per project, so you only do this once for each project where you want computer use.
3
Grant macOS permissions
The first time Claude tries to use your computer, you’ll see a prompt to grant two macOS permissions:
Accessibility
: lets Claude click, type, and scroll
Screen Recording
: lets Claude see what’s on your screen
The prompt includes links to open the relevant System Settings pane. Grant both, then select
Try again
in the prompt. macOS may require you to restart Claude Code after granting Screen Recording.
After setup, ask Claude to do something that needs the GUI:
Build the app target, launch it, and click through each tab to make
sure nothing crashes. Screenshot any error states you find.
​
Approve apps per session
Enabling the
computer-use
server doesn’t grant Claude access to every app on your machine. The first time Claude needs a specific app in a session, a prompt appears in your terminal showing:
Which apps Claude wants to control
Any extra permissions requested, such as clipboard access
How many other apps will be hidden while Claude works
Choose
Allow for this session
or
Deny
. Approvals last for the current session. You can approve multiple apps at once when Claude requests them together.
Apps with broad reach show an extra warning in the prompt so you know what approving them grants:
Warning
Applies to
Equivalent to shell access
Terminal, iTerm, VS Code, Warp, and other terminals and IDEs
Can read or write any file
Finder
Can change system settings
System Settings
These apps aren’t blocked. The warning lets you decide whether the task warrants that level of access.
Claude’s level of control also varies by app category: browsers and trading platforms are view-only, terminals and IDEs are click-only, and everything else gets full control. See
app permissions in Desktop
for the complete tier breakdown.
​
How Claude works on your screen
Understanding the flow helps you anticipate what Claude will do and how to intervene.
​
One session at a time
Computer use holds a machine-wide lock while active. If another Claude Code session is already using your computer, new attempts fail with a message telling you which session holds the lock. Finish or exit that session first.
​
Apps are hidden while Claude works
When Claude starts controlling your screen, other visible apps are hidden so Claude interacts with only the approved apps. Your terminal window stays visible and is excluded from screenshots, so you can watch the session and Claude never sees its own output.
When Claude finishes the turn, hidden apps are restored automatically.
​
Screenshots are downscaled automatically
Claude Code downscales every screenshot before sending it to the model. You don’t need to lower your display resolution or resize windows on Retina or other high-resolution displays. A 16-inch MacBook Pro at native Retina resolution captures at 3456×2234 and downscales to roughly 1372×887, preserving aspect ratio.
There is no setting to change the target size. If on-screen text or controls are too small for Claude to read after downscaling, increase their size in the app rather than changing your display resolution.
​
Stop at any time
When Claude acquires the lock, a macOS notification appears: “Claude is using your computer · press Esc to stop.” Press
Esc
anywhere to abort the current action immediately, or press
Ctrl+C
in the terminal. Either way, Claude releases the lock, unhides your apps, and returns control to you.
A second notification appears when Claude is done.
​
Safety and the trust boundary
Unlike the
sandboxed Bash tool
, computer use runs on your actual desktop with access to the apps you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the
computer use safety guide
for best practices.
The built-in guardrails reduce risk without requiring configuration:
Per-app approval
: Claude can only control apps you’ve approved in the current session.
Sentinel warnings
: apps that grant shell, filesystem, or system settings access are flagged before you approve.
Terminal excluded from screenshots
: Claude never sees your terminal window, so on-screen prompts in your session can’t feed back into the model.
Global escape
: the
Esc
key aborts computer use from anywhere, and the key press is consumed so prompt injection can’t use it to dismiss dialogs.
Lock file
: only one session can control your machine at a time.
​
Example workflows
These examples show common ways to combine computer use with coding tasks.
​
Validate a native build
After making changes to a macOS or iOS app, have Claude compile and verify in one pass:
Build the MenuBarStats target, launch it, open the preferences window,
and verify the interval slider updates the label. Screenshot the
preferences window when you're done.
Claude runs
xcodebuild
, launches the app, interacts with the UI, and reports what it finds.
​
Reproduce a layout bug
When a visual bug only appears at certain window sizes, let Claude find it:
The settings modal clips its footer on narrow windows. Resize the app
window down until you can reproduce it, screenshot the clipped state,
then check the CSS for the modal container.
Claude resizes the window, captures the broken state, and reads the relevant stylesheets.
​
Test a simulator flow
Drive the iOS Simulator without writing XCTest:
Open the iOS Simulator, launch the app, tap through the onboarding
screens, and tell me if any screen takes more than a second to load.
Claude controls the simulator the same way you would with a mouse.
​
Differences from the Desktop app
The CLI and Desktop surfaces share the same computer use engine, with a few differences:
Feature
Desktop
CLI
Platforms
macOS and Windows
macOS only
Enable
Toggle in
Settings > General
(under
Desktop app
)
Enable
computer-use
in
/mcp
Denied apps list
Configurable in Settings
Not yet available
Auto-unhide toggle
Optional
Always on
Dispatch integration
Dispatch-spawned sessions can use computer use
Not applicable
​
Troubleshooting
​
”Computer use is in use by another Claude session”
Another Claude Code session holds the lock. Finish the task in that session or exit it. If the other session crashed, the lock is released automatically when Claude detects the process is no longer running.
​
macOS permissions prompt keeps reappearing
macOS sometimes requires a restart of the requesting process after you grant Screen Recording. Quit Claude Code completely and start a new session. If the prompt persists, open
System Settings > Privacy & Security > Screen Recording
and confirm your terminal app is listed and enabled.
​
computer-use
doesn’t appear in
/mcp
The server only appears on eligible setups. Check that:
You’re on macOS. Computer use in the CLI is not available on Linux or Windows. On Windows, use
computer use in Desktop
instead.
You’re running Claude Code v2.1.85 or later. Run
claude --version
to check.
You’re on a Pro or Max plan. Run
/status
to confirm your subscription.
You’re authenticated through claude.ai. Computer use is not available with third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.
You’re in an interactive session. Computer use is not available in non-interactive mode with the
-p
flag.
​
See also
Computer use in Desktop
: the same capability with a graphical settings page
Claude in Chrome
: browser automation for web-based tasks
MCP
: connect Claude to structured tools and APIs
Sandboxing
: how Claude’s Bash tool isolates filesystem and network access
Computer use safety guide
: best practices for safe computer use
Was this page helpful?
Yes
No
Chrome extension (beta)
Visual Studio Code
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/computer-use" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Let Claude use your computer from the CLI
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Let Claude use your computer from the CLI
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Computer use is a research preview on macOS that requires a Pro or Max plan. It is not available on Team or Enterprise plans. It requires Claude Code v2.1.85 or later and an interactive session, so it is not available in non-interactive mode with the
-p
flag.
Computer use lets Claude open apps, control your screen, and work on your machine the way you would. From the CLI, Claude can compile a Swift app, launch it, click through every button, and screenshot the result, all in the same conversation where it wrote the code.
This page covers how computer use works in the CLI. For the Desktop app on macOS or Windows, see
computer use in Desktop
.
​
What you can do with computer use
Computer use handles tasks that require a GUI: anything you’d normally have to leave the terminal and do by hand.
Build and validate native apps
: ask Claude to build a macOS menu bar app. Claude writes the Swift, compiles it, launches it, and clicks through every control to verify it works before you ever open it.
End-to-end UI testing
: point Claude at a local Electron app and say “test the onboarding flow.” Claude opens the app, clicks through signup, and screenshots each step. No Playwright config, no test harness.
Debug visual and layout issues
: tell Claude “the modal is clipping on small windows.” Claude resizes the window, reproduces the bug, screenshots it, patches the CSS, and verifies the fix. Claude sees what you see.
Drive GUI-only tools
: interact with design tools, hardware control panels, the iOS Simulator, or proprietary apps that have no CLI or API.
​
When computer use applies
Claude has several ways to interact with an app or service. Computer use is the broadest and slowest, so Claude tries the most precise tool first:
If you have an
MCP server
for the service, Claude uses that.
If the task is a shell command, Claude uses Bash.
If the task is browser work and you have
Claude in Chrome
set up, Claude uses that.
If none of those apply, Claude uses computer use.
Screen control is reserved for things nothing else can reach: native apps, simulators, and tools without an API.
​
Enable computer use
Computer use is available as a built-in MCP server called
computer-use
. It’s off by default until you enable it.
1
Open the MCP menu
In an interactive Claude Code session, run:
/mcp
Find
computer-use
in the server list. It shows as disabled.
2
Enable the server
Select
computer-use
and choose
Enable
. The setting persists per project, so you only do this once for each project where you want computer use.
3
Grant macOS permissions
The first time Claude tries to use your computer, you’ll see a prompt to grant two macOS permissions:
Accessibility
: lets Claude click, type, and scroll
Screen Recording
: lets Claude see what’s on your screen
The prompt includes links to open the relevant System Settings pane. Grant both, then select
Try again
in the prompt. macOS may require you to restart Claude Code after granting Screen Recording.
After setup, ask Claude to do something that needs the GUI:
Build the app target, launch it, and click through each tab to make
sure nothing crashes. Screenshot any error states you find.
​
Approve apps per session
Enabling the
computer-use
server doesn’t grant Claude access to every app on your machine. The first time Claude needs a specific app in a session, a prompt appears in your terminal showing:
Which apps Claude wants to control
Any extra permissions requested, such as clipboard access
How many other apps will be hidden while Claude works
Choose
Allow for this session
or
Deny
. Approvals last for the current session. You can approve multiple apps at once when Claude requests them together.
Apps with broad reach show an extra warning in the prompt so you know what approving them grants:
Warning
Applies to
Equivalent to shell access
Terminal, iTerm, VS Code, Warp, and other terminals and IDEs
Can read or write any file
Finder
Can change system settings
System Settings
These apps aren’t blocked. The warning lets you decide whether the task warrants that level of access.
Claude’s level of control also varies by app category: browsers and trading platforms are view-only, terminals and IDEs are click-only, and everything else gets full control. See
app permissions in Desktop
for the complete tier breakdown.
​
How Claude works on your screen
Understanding the flow helps you anticipate what Claude will do and how to intervene.
​
One session at a time
Computer use holds a machine-wide lock while active. If another Claude Code session is already using your computer, new attempts fail with a message telling you which session holds the lock. Finish or exit that session first.
​
Apps are hidden while Claude works
When Claude starts controlling your screen, other visible apps are hidden so Claude interacts with only the approved apps. Your terminal window stays visible and is excluded from screenshots, so you can watch the session and Claude never sees its own output.
When Claude finishes the turn, hidden apps are restored automatically.
​
Screenshots are downscaled automatically
Claude Code downscales every screenshot before sending it to the model. You don’t need to lower your display resolution or resize windows on Retina or other high-resolution displays. A 16-inch MacBook Pro at native Retina resolution captures at 3456×2234 and downscales to roughly 1372×887, preserving aspect ratio.
There is no setting to change the target size. If on-screen text or controls are too small for Claude to read after downscaling, increase their size in the app rather than changing your display resolution.
​
Stop at any time
When Claude acquires the lock, a macOS notification appears: “Claude is using your computer · press Esc to stop.” Press
Esc
anywhere to abort the current action immediately, or press
Ctrl+C
in the terminal. Either way, Claude releases the lock, unhides your apps, and returns control to you.
A second notification appears when Claude is done.
​
Safety and the trust boundary
Unlike the
sandboxed Bash tool
, computer use runs on your actual desktop with access to the apps you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the
computer use safety guide
for best practices.
The built-in guardrails reduce risk without requiring configuration:
Per-app approval
: Claude can only control apps you’ve approved in the current session.
Sentinel warnings
: apps that grant shell, filesystem, or system settings access are flagged before you approve.
Terminal excluded from screenshots
: Claude never sees your terminal window, so on-screen prompts in your session can’t feed back into the model.
Global escape
: the
Esc
key aborts computer use from anywhere, and the key press is consumed so prompt injection can’t use it to dismiss dialogs.
Lock file
: only one session can control your machine at a time.
​
Example workflows
These examples show common ways to combine computer use with coding tasks.
​
Validate a native build
After making changes to a macOS or iOS app, have Claude compile and verify in one pass:
Build the MenuBarStats target, launch it, open the preferences window,
and verify the interval slider updates the label. Screenshot the
preferences window when you're done.
Claude runs
xcodebuild
, launches the app, interacts with the UI, and reports what it finds.
​
Reproduce a layout bug
When a visual bug only appears at certain window sizes, let Claude find it:
The settings modal clips its footer on narrow windows. Resize the app
window down until you can reproduce it, screenshot the clipped state,
then check the CSS for the modal container.
Claude resizes the window, captures the broken state, and reads the relevant stylesheets.
​
Test a simulator flow
Drive the iOS Simulator without writing XCTest:
Open the iOS Simulator, launch the app, tap through the onboarding
screens, and tell me if any screen takes more than a second to load.
Claude controls the simulator the same way you would with a mouse.
​
Differences from the Desktop app
The CLI and Desktop surfaces share the same computer use engine, with a few differences:
Feature
Desktop
CLI
Platforms
macOS and Windows
macOS only
Enable
Toggle in
Settings > General
(under
Desktop app
)
Enable
computer-use
in
/mcp
Denied apps list
Configurable in Settings
Not yet available
Auto-unhide toggle
Optional
Always on
Dispatch integration
Dispatch-spawned sessions can use computer use
Not applicable
​
Troubleshooting
​
”Computer use is in use by another Claude session”
Another Claude Code session holds the lock. Finish the task in that session or exit it. If the other session crashed, the lock is released automatically when Claude detects the process is no longer running.
​
macOS permissions prompt keeps reappearing
macOS sometimes requires a restart of the requesting process after you grant Screen Recording. Quit Claude Code completely and start a new session. If the prompt persists, open
System Settings > Privacy & Security > Screen Recording
and confirm your terminal app is listed and enabled.
​
computer-use
doesn’t appear in
/mcp
The server only appears on eligible setups. Check that:
You’re on macOS. Computer use in the CLI is not available on Linux or Windows. On Windows, use
computer use in Desktop
instead.
You’re running Claude Code v2.1.85 or later. Run
claude --version
to check.
You’re on a Pro or Max plan. Run
/status
to confirm your subscription.
You’re authenticated through claude.ai. Computer use is not available with third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.
You’re in an interactive session. Computer use is not available in non-interactive mode with the
-p
flag.
​
See also
Computer use in Desktop
: the same capability with a graphical settings page
Claude in Chrome
: browser automation for web-based tasks
MCP
: connect Claude to structured tools and APIs
Sandboxing
: how Claude’s Bash tool isolates filesystem and network access
Computer use safety guide
: best practices for safe computer use
Was this page helpful?
Yes
No
Chrome extension (beta)
Visual Studio Code
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/computer-use" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Subagents in the SDK</title>
  <link>https://code.claude.com/docs/en/agent-sdk/subagents</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/subagents</guid>
  <pubDate>Tue, 23 Jan 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Subagents in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cus...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Subagents in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents are separate agent instances that your main agent can spawn to handle focused subtasks.
Use subagents to isolate context for focused subtasks, run multiple analyses in parallel, and apply specialized instructions without bloating the main agent’s prompt.
This guide explains how to define and use subagents in the SDK using the
agents
parameter.
​
Overview
You can create subagents in three ways:
Programmatically
: use the
agents
parameter in your
query()
options (
TypeScript
,
Python
)
Filesystem-based
: define agents as markdown files in
.claude/agents/
directories (see
defining subagents as files
)
Built-in general-purpose
: Claude can invoke the built-in
general-purpose
subagent at any time via the Agent tool without you defining anything
This guide focuses on the programmatic approach, which is recommended for SDK applications.
When you define subagents, Claude determines whether to invoke them based on each subagent’s
description
field. Write clear descriptions that explain when the subagent should be used, and Claude will automatically delegate appropriate tasks. You can also explicitly request a subagent by name in your prompt (for example, “Use the code-reviewer agent to…”).
​
Benefits of using subagents
​
Context isolation
Each subagent runs in its own fresh conversation. Intermediate tool calls and results stay inside the subagent; only its final message returns to the parent. See
What subagents inherit
for exactly what’s in the subagent’s context.
Example:
a
research-assistant
subagent can explore dozens of files without any of that content accumulating in the main conversation. The parent receives a concise summary, not every file the subagent read.
​
Parallelization
Multiple subagents can run concurrently, dramatically speeding up complex workflows.
Example:
during a code review, you can run
style-checker
,
security-scanner
, and
test-coverage
subagents simultaneously, reducing review time from minutes to seconds.
​
Specialized instructions and knowledge
Each subagent can have tailored system prompts with specific expertise, best practices, and constraints.
Example:
a
database-migration
subagent can have detailed knowledge about SQL best practices, rollback strategies, and data integrity checks that would be unnecessary noise in the main agent’s instructions.
​
Tool restrictions
Subagents can be limited to specific tools, reducing the risk of unintended actions.
Example:
a
doc-reviewer
subagent might only have access to Read and Grep tools, ensuring it can analyze but never accidentally modify your documentation files.
​
Creating subagents
​
Programmatic definition (recommended)
Define subagents directly in your code using the
agents
parameter. This example creates two subagents: a code reviewer with read-only access and a test runner that can execute commands. The
Agent
tool must be included in
allowedTools
since Claude invokes subagents through the Agent tool.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Review the authentication module for security issues"
,
options
=
ClaudeAgentOptions(
# Agent tool is required for subagent invocation
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
# description tells Claude when to use this subagent
description
=
"Expert code review specialist. Use for quality, security, and maintainability reviews."
,
# prompt defines the subagent's behavior and expertise
prompt
=
"""You are a code review specialist with expertise in security, performance, and best practices.
When reviewing code:
- Identify security vulnerabilities
- Check for performance issues
- Verify adherence to coding standards
- Suggest specific improvements
Be thorough but concise in your feedback."""
,
# tools restricts what the subagent can do (read-only here)
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
# model overrides the default model for this subagent
model
=
"sonnet"
,
),
"test-runner"
: AgentDefinition(
description
=
"Runs and analyzes test suites. Use for test execution and coverage analysis."
,
prompt
=
"""You are a test execution specialist. Run tests and provide clear analysis of results.
Focus on:
- Running test commands
- Analyzing test output
- Identifying failing tests
- Suggesting fixes for failures"""
,
# Bash access lets this subagent run test commands
tools
=
[
"Bash"
,
"Read"
,
"Grep"
],
),
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
AgentDefinition configuration
Field
Type
Required
Description
description
string
Yes
Natural language description of when to use this agent
prompt
string
Yes
The agent’s system prompt defining its role and behavior
tools
string[]
No
Array of allowed tool names. If omitted, inherits all tools
disallowedTools
string[]
No
Array of tool names to remove from the agent’s tool set
model
string
No
Model override for this agent. Accepts an alias such as
'sonnet'
,
'opus'
,
'haiku'
,
'inherit'
, or a full model ID. Defaults to main model if omitted
skills
string[]
No
List of skill names to preload into the agent’s context at startup. Unlisted skills remain invocable through the Skill tool
memory
'user' | 'project' | 'local'
No
Memory source for this agent
mcpServers
(string | object)[]
No
MCP servers available to this agent, by name or inline config
maxTurns
number
No
Maximum number of agentic turns before the agent stops
background
boolean
No
Run this agent as a non-blocking background task when invoked
effort
'low' | 'medium' | 'high' | 'xhigh' | 'max' | number
No
Reasoning effort level for this agent
permissionMode
PermissionMode
No
Permission mode for tool execution within this agent
In the Python SDK, these field names use camelCase to match the wire format. See the
AgentDefinition
reference
for details.
Subagents cannot spawn their own subagents. Don’t include
Agent
in a subagent’s
tools
array.
​
Filesystem-based definition (alternative)
You can also define subagents as markdown files in
.claude/agents/
directories. See the
Claude Code subagents documentation
for details on this approach. Programmatically defined agents take precedence over filesystem-based agents with the same name.
Even without defining custom subagents, Claude can spawn the built-in
general-purpose
subagent when
Agent
is in your
allowedTools
. This is useful for delegating research or exploration tasks without creating specialized agents.
​
What subagents inherit
A subagent’s context window starts fresh (no parent conversation) but isn’t empty. The only channel from parent to subagent is the Agent tool’s prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt.
The subagent receives
The subagent does not receive
Its own system prompt (
AgentDefinition.prompt
) and the Agent tool’s prompt
The parent’s conversation history or tool results
Project CLAUDE.md (loaded via
settingSources
)
Preloaded skill content, unless listed in
AgentDefinition.skills
Tool definitions (inherited from parent, or the subset in
tools
)
The parent’s system prompt
The parent receives the subagent’s final message verbatim as the Agent tool result, but may summarize it in its own response. To preserve subagent output verbatim in the user-facing response, include an instruction to do so in the prompt or
systemPrompt
option you pass to the
main
query()
call.
​
Invoking subagents
​
Automatic invocation
Claude automatically decides when to invoke subagents based on the task and each subagent’s
description
. For example, if you define a
performance-optimizer
subagent with the description “Performance optimization specialist for query tuning”, Claude will invoke it when your prompt mentions optimizing queries.
Write clear, specific descriptions so Claude can match tasks to the right subagent.
​
Explicit invocation
To guarantee Claude uses a specific subagent, mention it by name in your prompt:
"Use the code-reviewer agent to check the authentication module"
This bypasses automatic matching and directly invokes the named subagent.
​
Dynamic agent configuration
You can create agent definitions dynamically based on runtime conditions. This example creates a security reviewer with different strictness levels, using a more powerful model for strict reviews.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
# Factory function that returns an AgentDefinition
# This pattern lets you customize agents based on runtime conditions
def
create_security_agent
(
security_level
:
str
) -> AgentDefinition:
is_strict
=
security_level
==
"strict"
return
AgentDefinition(
description
=
"Security code reviewer"
,
# Customize the prompt based on strictness level
prompt
=
f
"You are a
{
'strict'
if
is_strict
else
'balanced'
}
security reviewer..."
,
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
# Key insight: use a more capable model for high-stakes reviews
model
=
"opus"
if
is_strict
else
"sonnet"
,
)
async
def
main
():
# The agent is created at query time, so each request can use different settings
async
for
message
in
query(
prompt
=
"Review this PR for security issues"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
# Call the factory with your desired configuration
"security-reviewer"
: create_security_agent(
"strict"
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Detecting subagent invocation
Subagents are invoked via the Agent tool. To detect when a subagent is invoked, check for
tool_use
blocks where
name
is
"Agent"
. Messages from within a subagent’s context include a
parent_tool_use_id
field.
The tool name was renamed from
"Task"
to
"Agent"
in Claude Code v2.1.63. Current SDK releases emit
"Agent"
in
tool_use
blocks but still use
"Task"
in the
system:init
tools list and in
result.permission_denials[].tool_name
. Checking both values in
block.name
ensures compatibility across SDK versions.
This example iterates through streamed messages, logging when a subagent is invoked and when subsequent messages originate from within that subagent’s execution context.
The message structure differs between SDKs. In Python, content blocks are accessed directly via
message.content
. In TypeScript,
SDKAssistantMessage
wraps the Claude API message, so content is accessed via
message.message.content
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition, ToolUseBlock
async
def
main
():
async
for
message
in
query(
prompt
=
"Use the code-reviewer agent to review this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
description
=
"Expert code reviewer."
,
prompt
=
"Analyze code quality and suggest improvements."
,
tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
)
},
),
):
# Check for subagent invocation. Match both names: older SDK
# versions emitted "Task", current versions emit "Agent".
if
hasattr
(message,
"content"
)
and
message.content:
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock)
and
block.name
in
(
"Task"
,
"Agent"
,
):
print
(
f
"Subagent invoked:
{
block.input.get(
'subagent_type'
)
}
"
)
# Check if this message is from within a subagent's context
if
hasattr
(message,
"parent_tool_use_id"
)
and
message.parent_tool_use_id:
print
(
"  (running inside subagent)"
)
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Resuming subagents
Subagents can be resumed to continue where they left off. Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.
When a subagent completes, Claude receives its agent ID in the Agent tool result. To resume a subagent programmatically:
Capture the session ID
: Extract
session_id
from messages during the first query
Extract the agent ID
: Parse
agentId
from the message content
Resume the session
: Pass
resume: sessionId
in the second query’s options, and include the agent ID in your prompt
You must resume the same session to access the subagent’s transcript. Each
query()
call starts a new session by default, so pass
resume: sessionId
to continue in the same session.
If you’re using a custom agent (not a built-in one), you also need to pass the same agent definition in the
agents
parameter for both queries.
The example below demonstrates this flow: the first query runs a subagent and captures the session ID and agent ID, then the second query resumes the session to ask a follow-up question that requires context from the first analysis.
TypeScript
Python
import
{
query
,
type
SDKMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Helper to extract agentId from message content
// Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)
function
extractAgentId
(
message
:
SDKMessage
)
:
string
|
undefined
{
if
(
message
.
type
!==
"assistant"
&&
message
.
type
!==
"user"
)
return
undefined
;
// Stringify the content so we can search it without traversing nested blocks
const
content
=
JSON
.
stringify
(
message
.
message
.
content
);
const
match
=
content
.
match
(
/agentId:
\s
*
(
[
a-f0-9-
]
+
)
/
);
return
match
?.[
1
];
}
let
agentId
:
string
|
undefined
;
let
sessionId
:
string
|
undefined
;
// First invocation - use the Explore agent to find API endpoints
for
await
(
const
message
of
query
({
prompt:
"Use the Explore agent to find all API endpoints in this codebase"
,
options:
{
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
] }
})) {
// Capture session_id from ResultMessage (needed to resume this session)
if
(
"session_id"
in
message
)
sessionId
=
message
.
session_id
;
// Search message content for the agentId (appears in Agent tool results)
const
extractedId
=
extractAgentId
(
message
);
if
(
extractedId
)
agentId
=
extractedId
;
// Print the final result
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
// Second invocation - resume and ask follow-up
if
(
agentId
&&
sessionId
) {
for
await
(
const
message
of
query
({
prompt:
`Resume agent
${
agentId
}
and list the top 3 most complex endpoints`
,
options:
{
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
resume:
sessionId
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
}
Subagent transcripts persist independently of the main conversation:
Main conversation compaction
: When the main conversation compacts, subagent transcripts are unaffected. They’re stored in separate files.
Session persistence
: Subagent transcripts persist within their session. You can resume a subagent after restarting Claude Code by resuming the same session.
Automatic cleanup
: Transcripts are cleaned up based on the
cleanupPeriodDays
setting (default: 30 days).
​
Tool restrictions
Subagents can have restricted tool access via the
tools
field:
Omit the field
: agent inherits all available tools (default)
Specify tools
: agent can only use listed tools
This example creates a read-only analysis agent that can examine code but cannot modify files or run commands.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Analyze the architecture of this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
"code-analyzer"
: AgentDefinition(
description
=
"Static code analysis and architecture review"
,
prompt
=
"""You are a code architecture analyst. Analyze code structure,
identify patterns, and suggest improvements without making changes."""
,
# Read-only tools: no Edit, Write, or Bash access
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Common tool combinations
Use case
Tools
Description
Read-only analysis
Read
,
Grep
,
Glob
Can examine code but not modify or execute
Test execution
Bash
,
Read
,
Grep
Can run commands and analyze output
Code modification
Read
,
Edit
,
Write
,
Grep
,
Glob
Full read/write access without command execution
Full access
All tools
Inherits all tools from parent (omit
tools
field)
​
Troubleshooting
​
Claude not delegating to subagents
If Claude completes tasks directly instead of delegating to your subagent:
Include the Agent tool
: subagents are invoked via the Agent tool, so it must be in
allowedTools
Use explicit prompting
: mention the subagent by name in your prompt (for example, “Use the code-reviewer agent to…”)
Write a clear description
: explain exactly when the subagent should be used so Claude can match tasks appropriately
​
Filesystem-based agents not loading
Agents defined in
.claude/agents/
are loaded at startup only. If you create a new agent file while Claude Code is running, restart the session to load it.
​
Windows: long prompt failures
On Windows, subagents with very long prompts may fail due to command line length limits (8191 chars). Keep prompts concise or use filesystem-based agents for complex instructions.
​
Related documentation
Claude Code subagents
: comprehensive subagent documentation including filesystem-based definitions
SDK overview
: getting started with the Claude Agent SDK
Was this page helpful?
Yes
No
Scale to many tools with tool search
Modifying system prompts
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/subagents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Subagents in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Cus...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Subagents in the SDK
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Subagents are separate agent instances that your main agent can spawn to handle focused subtasks.
Use subagents to isolate context for focused subtasks, run multiple analyses in parallel, and apply specialized instructions without bloating the main agent’s prompt.
This guide explains how to define and use subagents in the SDK using the
agents
parameter.
​
Overview
You can create subagents in three ways:
Programmatically
: use the
agents
parameter in your
query()
options (
TypeScript
,
Python
)
Filesystem-based
: define agents as markdown files in
.claude/agents/
directories (see
defining subagents as files
)
Built-in general-purpose
: Claude can invoke the built-in
general-purpose
subagent at any time via the Agent tool without you defining anything
This guide focuses on the programmatic approach, which is recommended for SDK applications.
When you define subagents, Claude determines whether to invoke them based on each subagent’s
description
field. Write clear descriptions that explain when the subagent should be used, and Claude will automatically delegate appropriate tasks. You can also explicitly request a subagent by name in your prompt (for example, “Use the code-reviewer agent to…”).
​
Benefits of using subagents
​
Context isolation
Each subagent runs in its own fresh conversation. Intermediate tool calls and results stay inside the subagent; only its final message returns to the parent. See
What subagents inherit
for exactly what’s in the subagent’s context.
Example:
a
research-assistant
subagent can explore dozens of files without any of that content accumulating in the main conversation. The parent receives a concise summary, not every file the subagent read.
​
Parallelization
Multiple subagents can run concurrently, dramatically speeding up complex workflows.
Example:
during a code review, you can run
style-checker
,
security-scanner
, and
test-coverage
subagents simultaneously, reducing review time from minutes to seconds.
​
Specialized instructions and knowledge
Each subagent can have tailored system prompts with specific expertise, best practices, and constraints.
Example:
a
database-migration
subagent can have detailed knowledge about SQL best practices, rollback strategies, and data integrity checks that would be unnecessary noise in the main agent’s instructions.
​
Tool restrictions
Subagents can be limited to specific tools, reducing the risk of unintended actions.
Example:
a
doc-reviewer
subagent might only have access to Read and Grep tools, ensuring it can analyze but never accidentally modify your documentation files.
​
Creating subagents
​
Programmatic definition (recommended)
Define subagents directly in your code using the
agents
parameter. This example creates two subagents: a code reviewer with read-only access and a test runner that can execute commands. The
Agent
tool must be included in
allowedTools
since Claude invokes subagents through the Agent tool.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Review the authentication module for security issues"
,
options
=
ClaudeAgentOptions(
# Agent tool is required for subagent invocation
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
# description tells Claude when to use this subagent
description
=
"Expert code review specialist. Use for quality, security, and maintainability reviews."
,
# prompt defines the subagent's behavior and expertise
prompt
=
"""You are a code review specialist with expertise in security, performance, and best practices.
When reviewing code:
- Identify security vulnerabilities
- Check for performance issues
- Verify adherence to coding standards
- Suggest specific improvements
Be thorough but concise in your feedback."""
,
# tools restricts what the subagent can do (read-only here)
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
# model overrides the default model for this subagent
model
=
"sonnet"
,
),
"test-runner"
: AgentDefinition(
description
=
"Runs and analyzes test suites. Use for test execution and coverage analysis."
,
prompt
=
"""You are a test execution specialist. Run tests and provide clear analysis of results.
Focus on:
- Running test commands
- Analyzing test output
- Identifying failing tests
- Suggesting fixes for failures"""
,
# Bash access lets this subagent run test commands
tools
=
[
"Bash"
,
"Read"
,
"Grep"
],
),
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
AgentDefinition configuration
Field
Type
Required
Description
description
string
Yes
Natural language description of when to use this agent
prompt
string
Yes
The agent’s system prompt defining its role and behavior
tools
string[]
No
Array of allowed tool names. If omitted, inherits all tools
disallowedTools
string[]
No
Array of tool names to remove from the agent’s tool set
model
string
No
Model override for this agent. Accepts an alias such as
'sonnet'
,
'opus'
,
'haiku'
,
'inherit'
, or a full model ID. Defaults to main model if omitted
skills
string[]
No
List of skill names to preload into the agent’s context at startup. Unlisted skills remain invocable through the Skill tool
memory
'user' | 'project' | 'local'
No
Memory source for this agent
mcpServers
(string | object)[]
No
MCP servers available to this agent, by name or inline config
maxTurns
number
No
Maximum number of agentic turns before the agent stops
background
boolean
No
Run this agent as a non-blocking background task when invoked
effort
'low' | 'medium' | 'high' | 'xhigh' | 'max' | number
No
Reasoning effort level for this agent
permissionMode
PermissionMode
No
Permission mode for tool execution within this agent
In the Python SDK, these field names use camelCase to match the wire format. See the
AgentDefinition
reference
for details.
Subagents cannot spawn their own subagents. Don’t include
Agent
in a subagent’s
tools
array.
​
Filesystem-based definition (alternative)
You can also define subagents as markdown files in
.claude/agents/
directories. See the
Claude Code subagents documentation
for details on this approach. Programmatically defined agents take precedence over filesystem-based agents with the same name.
Even without defining custom subagents, Claude can spawn the built-in
general-purpose
subagent when
Agent
is in your
allowedTools
. This is useful for delegating research or exploration tasks without creating specialized agents.
​
What subagents inherit
A subagent’s context window starts fresh (no parent conversation) but isn’t empty. The only channel from parent to subagent is the Agent tool’s prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt.
The subagent receives
The subagent does not receive
Its own system prompt (
AgentDefinition.prompt
) and the Agent tool’s prompt
The parent’s conversation history or tool results
Project CLAUDE.md (loaded via
settingSources
)
Preloaded skill content, unless listed in
AgentDefinition.skills
Tool definitions (inherited from parent, or the subset in
tools
)
The parent’s system prompt
The parent receives the subagent’s final message verbatim as the Agent tool result, but may summarize it in its own response. To preserve subagent output verbatim in the user-facing response, include an instruction to do so in the prompt or
systemPrompt
option you pass to the
main
query()
call.
​
Invoking subagents
​
Automatic invocation
Claude automatically decides when to invoke subagents based on the task and each subagent’s
description
. For example, if you define a
performance-optimizer
subagent with the description “Performance optimization specialist for query tuning”, Claude will invoke it when your prompt mentions optimizing queries.
Write clear, specific descriptions so Claude can match tasks to the right subagent.
​
Explicit invocation
To guarantee Claude uses a specific subagent, mention it by name in your prompt:
"Use the code-reviewer agent to check the authentication module"
This bypasses automatic matching and directly invokes the named subagent.
​
Dynamic agent configuration
You can create agent definitions dynamically based on runtime conditions. This example creates a security reviewer with different strictness levels, using a more powerful model for strict reviews.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
# Factory function that returns an AgentDefinition
# This pattern lets you customize agents based on runtime conditions
def
create_security_agent
(
security_level
:
str
) -> AgentDefinition:
is_strict
=
security_level
==
"strict"
return
AgentDefinition(
description
=
"Security code reviewer"
,
# Customize the prompt based on strictness level
prompt
=
f
"You are a
{
'strict'
if
is_strict
else
'balanced'
}
security reviewer..."
,
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
# Key insight: use a more capable model for high-stakes reviews
model
=
"opus"
if
is_strict
else
"sonnet"
,
)
async
def
main
():
# The agent is created at query time, so each request can use different settings
async
for
message
in
query(
prompt
=
"Review this PR for security issues"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
# Call the factory with your desired configuration
"security-reviewer"
: create_security_agent(
"strict"
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Detecting subagent invocation
Subagents are invoked via the Agent tool. To detect when a subagent is invoked, check for
tool_use
blocks where
name
is
"Agent"
. Messages from within a subagent’s context include a
parent_tool_use_id
field.
The tool name was renamed from
"Task"
to
"Agent"
in Claude Code v2.1.63. Current SDK releases emit
"Agent"
in
tool_use
blocks but still use
"Task"
in the
system:init
tools list and in
result.permission_denials[].tool_name
. Checking both values in
block.name
ensures compatibility across SDK versions.
This example iterates through streamed messages, logging when a subagent is invoked and when subsequent messages originate from within that subagent’s execution context.
The message structure differs between SDKs. In Python, content blocks are accessed directly via
message.content
. In TypeScript,
SDKAssistantMessage
wraps the Claude API message, so content is accessed via
message.message.content
.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition, ToolUseBlock
async
def
main
():
async
for
message
in
query(
prompt
=
"Use the code-reviewer agent to review this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Glob"
,
"Grep"
,
"Agent"
],
agents
=
{
"code-reviewer"
: AgentDefinition(
description
=
"Expert code reviewer."
,
prompt
=
"Analyze code quality and suggest improvements."
,
tools
=
[
"Read"
,
"Glob"
,
"Grep"
],
)
},
),
):
# Check for subagent invocation. Match both names: older SDK
# versions emitted "Task", current versions emit "Agent".
if
hasattr
(message,
"content"
)
and
message.content:
for
block
in
message.content:
if
isinstance
(block, ToolUseBlock)
and
block.name
in
(
"Task"
,
"Agent"
,
):
print
(
f
"Subagent invoked:
{
block.input.get(
'subagent_type'
)
}
"
)
# Check if this message is from within a subagent's context
if
hasattr
(message,
"parent_tool_use_id"
)
and
message.parent_tool_use_id:
print
(
"  (running inside subagent)"
)
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Resuming subagents
Subagents can be resumed to continue where they left off. Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.
When a subagent completes, Claude receives its agent ID in the Agent tool result. To resume a subagent programmatically:
Capture the session ID
: Extract
session_id
from messages during the first query
Extract the agent ID
: Parse
agentId
from the message content
Resume the session
: Pass
resume: sessionId
in the second query’s options, and include the agent ID in your prompt
You must resume the same session to access the subagent’s transcript. Each
query()
call starts a new session by default, so pass
resume: sessionId
to continue in the same session.
If you’re using a custom agent (not a built-in one), you also need to pass the same agent definition in the
agents
parameter for both queries.
The example below demonstrates this flow: the first query runs a subagent and captures the session ID and agent ID, then the second query resumes the session to ask a follow-up question that requires context from the first analysis.
TypeScript
Python
import
{
query
,
type
SDKMessage
}
from
"@anthropic-ai/claude-agent-sdk"
;
// Helper to extract agentId from message content
// Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)
function
extractAgentId
(
message
:
SDKMessage
)
:
string
|
undefined
{
if
(
message
.
type
!==
"assistant"
&&
message
.
type
!==
"user"
)
return
undefined
;
// Stringify the content so we can search it without traversing nested blocks
const
content
=
JSON
.
stringify
(
message
.
message
.
content
);
const
match
=
content
.
match
(
/agentId:
\s
*
(
[
a-f0-9-
]
+
)
/
);
return
match
?.[
1
];
}
let
agentId
:
string
|
undefined
;
let
sessionId
:
string
|
undefined
;
// First invocation - use the Explore agent to find API endpoints
for
await
(
const
message
of
query
({
prompt:
"Use the Explore agent to find all API endpoints in this codebase"
,
options:
{
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
] }
})) {
// Capture session_id from ResultMessage (needed to resume this session)
if
(
"session_id"
in
message
)
sessionId
=
message
.
session_id
;
// Search message content for the agentId (appears in Agent tool results)
const
extractedId
=
extractAgentId
(
message
);
if
(
extractedId
)
agentId
=
extractedId
;
// Print the final result
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
// Second invocation - resume and ask follow-up
if
(
agentId
&&
sessionId
) {
for
await
(
const
message
of
query
({
prompt:
`Resume agent
${
agentId
}
and list the top 3 most complex endpoints`
,
options:
{
allowedTools:
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
resume:
sessionId
}
})) {
if
(
"result"
in
message
)
console
.
log
(
message
.
result
);
}
}
Subagent transcripts persist independently of the main conversation:
Main conversation compaction
: When the main conversation compacts, subagent transcripts are unaffected. They’re stored in separate files.
Session persistence
: Subagent transcripts persist within their session. You can resume a subagent after restarting Claude Code by resuming the same session.
Automatic cleanup
: Transcripts are cleaned up based on the
cleanupPeriodDays
setting (default: 30 days).
​
Tool restrictions
Subagents can have restricted tool access via the
tools
field:
Omit the field
: agent inherits all available tools (default)
Specify tools
: agent can only use listed tools
This example creates a read-only analysis agent that can examine code but cannot modify files or run commands.
Python
TypeScript
import
asyncio
from
claude_agent_sdk
import
query, ClaudeAgentOptions, AgentDefinition
async
def
main
():
async
for
message
in
query(
prompt
=
"Analyze the architecture of this codebase"
,
options
=
ClaudeAgentOptions(
allowed_tools
=
[
"Read"
,
"Grep"
,
"Glob"
,
"Agent"
],
agents
=
{
"code-analyzer"
: AgentDefinition(
description
=
"Static code analysis and architecture review"
,
prompt
=
"""You are a code architecture analyst. Analyze code structure,
identify patterns, and suggest improvements without making changes."""
,
# Read-only tools: no Edit, Write, or Bash access
tools
=
[
"Read"
,
"Grep"
,
"Glob"
],
)
},
),
):
if
hasattr
(message,
"result"
):
print
(message.result)
asyncio.run(main())
​
Common tool combinations
Use case
Tools
Description
Read-only analysis
Read
,
Grep
,
Glob
Can examine code but not modify or execute
Test execution
Bash
,
Read
,
Grep
Can run commands and analyze output
Code modification
Read
,
Edit
,
Write
,
Grep
,
Glob
Full read/write access without command execution
Full access
All tools
Inherits all tools from parent (omit
tools
field)
​
Troubleshooting
​
Claude not delegating to subagents
If Claude completes tasks directly instead of delegating to your subagent:
Include the Agent tool
: subagents are invoked via the Agent tool, so it must be in
allowedTools
Use explicit prompting
: mention the subagent by name in your prompt (for example, “Use the code-reviewer agent to…”)
Write a clear description
: explain exactly when the subagent should be used so Claude can match tasks appropriately
​
Filesystem-based agents not loading
Agents defined in
.claude/agents/
are loaded at startup only. If you create a new agent file while Claude Code is running, restart the session to load it.
​
Windows: long prompt failures
On Windows, subagents with very long prompts may fail due to command line length limits (8191 chars). Keep prompts concise or use filesystem-based agents for complex instructions.
​
Related documentation
Claude Code subagents
: comprehensive subagent documentation including filesystem-based definitions
SDK overview
: getting started with the Claude Agent SDK
Was this page helpful?
Yes
No
Scale to many tools with tool search
Modifying system prompts
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/subagents" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Claude Code on Amazon Bedrock</title>
  <link>https://code.claude.com/docs/en/amazon-bedrock</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/amazon-bedrock</guid>
  <pubDate>Fri, 19 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Amazon Bedrock
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketpl...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Amazon Bedrock
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Bedrock, ensure you have:
An AWS account with Bedrock access enabled
Access to desired Claude models (for example, Claude Sonnet 4.6) in Bedrock
AWS CLI installed and configured (optional - only needed if you don’t have another mechanism for getting credentials)
Appropriate IAM permissions
To sign in with your own Bedrock credentials, follow
Sign in with Bedrock
below. To deploy Claude Code across a team, use the
manual setup
steps and
pin your model versions
before rolling out.
​
Sign in with Bedrock
If you have AWS credentials and want to start using Claude Code through Bedrock, the login wizard walks you through it. You complete the AWS-side prerequisites once per account; the wizard handles the Claude Code side.
1
Enable Anthropic models in your AWS account
In the
Amazon Bedrock console
, open the Model catalog, select an Anthropic model, and submit the use case form. Access is granted immediately after submission. See
Submit use case details
for AWS Organizations and
IAM configuration
for the permissions your role needs.
2
Start Claude Code and choose Bedrock
Run
claude
. At the login prompt, select
3rd-party platform
, then
Amazon Bedrock
.
3
Follow the wizard prompts
Choose how you authenticate to AWS: an AWS profile detected from your
~/.aws
directory, a Bedrock API key, an access key and secret, or credentials already in your environment. The wizard picks up your region, verifies which Claude models your account can invoke, and lets you pin them. It saves the result to the
env
block of your
user settings file
, so you don’t need to export environment variables yourself.
After you’ve signed in, run
/setup-bedrock
any time to reopen the wizard and change your credentials, region, or model pins.
​
Set up manually
To configure Bedrock through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.
​
1. Submit use case details
First-time users of Anthropic models are required to submit use case details before invoking a model. This is done once per AWS account.
Ensure you have the right IAM permissions described below
Navigate to the
Amazon Bedrock console
Select an Anthropic model from the
Model catalog
Complete the use case form. Access is granted immediately after submission.
If you use AWS Organizations, you can submit the form once from the management account using the
PutUseCaseForModelAccess
API
. This call requires the
bedrock:PutUseCaseForModelAccess
IAM permission. Approval extends to child accounts automatically.
​
2. Configure AWS credentials
Claude Code uses the default AWS SDK credential chain. Set up your credentials using one of these methods:
Option A: AWS CLI configuration
aws
configure
Option B: Environment variables (access key)
export
AWS_ACCESS_KEY_ID
=
your-access-key-id
export
AWS_SECRET_ACCESS_KEY
=
your-secret-access-key
export
AWS_SESSION_TOKEN
=
your-session-token
Option C: Environment variables (SSO profile)
aws
sso
login
--profile=
<
your-profile-name
>
export
AWS_PROFILE
=
your-profile-name
Option D: AWS Management Console credentials
aws
login
Learn more
about
aws login
.
Option E: Bedrock API keys
export
AWS_BEARER_TOKEN_BEDROCK
=
your-bedrock-api-key
Bedrock API keys provide a simpler authentication method without needing full AWS credentials.
Learn more about Bedrock API keys
.
​
Advanced credential configuration
Claude Code supports automatic credential refresh for AWS SSO and corporate identity providers. Add these settings to your Claude Code settings file (see
Settings
for file locations).
These two settings have different trigger conditions:
awsAuthRefresh
: runs only when Claude Code detects that your AWS credentials are expired, either locally based on their timestamp or when Bedrock returns a credential error, then retries the request with refreshed credentials.
awsCredentialExport
: runs at session start and on each credential reload, even when the credentials in your AWS default credential provider chain are still valid. Use this when your Bedrock account requires cross-account credentials that differ from the ones the default provider chain would resolve.
Example configuration
{
"awsAuthRefresh"
:
"aws sso login --profile myprofile"
,
"env"
: {
"AWS_PROFILE"
:
"myprofile"
}
}
Configuration settings explained
awsAuthRefresh
: Use this for commands that modify the
.aws
directory, such as updating credentials, SSO cache, or config files. The command’s output is displayed to the user, but interactive input isn’t supported. This works well for browser-based SSO flows where the CLI displays a URL or code and you complete authentication in the browser.
awsCredentialExport
: Only use this if you can’t modify
.aws
and must directly return credentials. This command runs whenever credentials need to be refreshed, not only when credentials are expired. Output is captured silently and not shown to the user. The command must output JSON in this format:
{
"Credentials"
: {
"AccessKeyId"
:
"value"
,
"SecretAccessKey"
:
"value"
,
"SessionToken"
:
"value"
}
}
​
3. Configure Claude Code
Set the following environment variables to enable Bedrock:
# Enable Bedrock integration
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
AWS_REGION
=
us-east-1
# or your preferred region
# Optional: Override the AWS region for the small/fast model (Bedrock and Mantle).
# On Bedrock, has no effect without ANTHROPIC_DEFAULT_HAIKU_MODEL
# or the deprecated ANTHROPIC_SMALL_FAST_MODEL set.
export
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
=
us-west-2
# Optional: Override the Bedrock endpoint URL for custom endpoints or gateways
# export ANTHROPIC_BEDROCK_BASE_URL=https://bedrock-runtime.us-east-1.amazonaws.com
When enabling Bedrock for Claude Code, keep the following in mind:
AWS_REGION
is a required environment variable. Claude Code does not read from the
.aws
config file for this setting.
When using Bedrock, the
/login
and
/logout
commands are disabled since authentication is handled through AWS credentials.
You can use settings files for environment variables like
AWS_PROFILE
that you don’t want to leak to other processes. See
Settings
for more information.
​
4. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as
sonnet
and
opus
resolve to the latest version, which may not yet be available in your Bedrock account when Anthropic releases an update. Claude Code
falls back
to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Bedrock model IDs.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Bedrock resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'us.anthropic.claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'us.anthropic.claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'us.anthropic.claude-haiku-4-5-20251001-v1:0'
These variables use cross-region inference profile IDs (with the
us.
prefix). If you use a different region prefix or application inference profiles, adjust accordingly. For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Claude Code uses these default models when no pinning variables are set:
Model type
Default value
Primary model
us.anthropic.claude-sonnet-4-5-20250929-v1:0
Small/fast model
Same as primary model
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Bedrock, Claude Code defaults this to the primary model because Haiku may not be enabled in every account or region. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a model ID that is available in your account.
To customize models further, use one of these methods:
# Using inference profile ID
export
ANTHROPIC_MODEL
=
'us.anthropic.claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'us.anthropic.claude-haiku-4-5-20251001-v1:0'
# Using application inference profile ARN
export
ANTHROPIC_MODEL
=
'arn:aws:bedrock:us-east-2:your-account-id:application-inference-profile/your-model-id'
# Optional: Disable prompt caching if needed
export
DISABLE_PROMPT_CACHING
=
1
# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default
export
ENABLE_PROMPT_CACHING_1H
=
1
Prompt caching
may not be available in all regions. Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes.
​
Map each model version to an inference profile
The
ANTHROPIC_DEFAULT_*_MODEL
environment variables configure one inference profile per model family. If your organization needs to expose several versions of the same family in the
/model
picker, each routed to its own application inference profile ARN, use the
modelOverrides
setting in your
settings file
instead.
This example maps four Opus versions to distinct ARNs so users can switch between them without bypassing your organization’s inference profiles:
{
"modelOverrides"
: {
"claude-opus-4-7"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-47-prod"
,
"claude-opus-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod"
,
"claude-opus-4-5-20251101"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-45-prod"
,
"claude-opus-4-1-20250805"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-41-prod"
}
}
When a user selects one of these versions in
/model
, Claude Code calls Bedrock with the mapped ARN. Versions without an override fall back to the built-in Bedrock model ID or any matching inference profile discovered at startup. See
Override model IDs per version
for details on how overrides interact with
availableModels
and other model settings.
​
Startup model checks
When Claude Code starts with Bedrock configured, it verifies that the models it intends to use are accessible in your account. This check requires Claude Code v2.1.94 or later.
If you have pinned a model version that is older than the current Claude Code default, and your account can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your
user settings file
and restarts Claude Code. Declining is remembered until the next default version change. Pins that point to an
application inference profile ARN
are skipped, since those are managed by your administrator.
If you have not pinned a model and the current default is unavailable in your account, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in your Bedrock account or
pin a version
to make the choice permanent.
​
IAM configuration
Create an IAM policy with the required permissions for Claude Code:
{
"Version"
:
"2012-10-17"
,
"Statement"
: [
{
"Sid"
:
"AllowModelAndInferenceProfileAccess"
,
"Effect"
:
"Allow"
,
"Action"
: [
"bedrock:InvokeModel"
,
"bedrock:InvokeModelWithResponseStream"
,
"bedrock:ListInferenceProfiles"
,
"bedrock:GetInferenceProfile"
],
"Resource"
: [
"arn:aws:bedrock:*:*:inference-profile/*"
,
"arn:aws:bedrock:*:*:application-inference-profile/*"
,
"arn:aws:bedrock:*:*:foundation-model/*"
]
},
{
"Sid"
:
"AllowMarketplaceSubscription"
,
"Effect"
:
"Allow"
,
"Action"
: [
"aws-marketplace:ViewSubscriptions"
,
"aws-marketplace:Subscribe"
],
"Resource"
:
"*"
,
"Condition"
: {
"StringEquals"
: {
"aws:CalledViaLast"
:
"bedrock.amazonaws.com"
}
}
}
]
}
For more restrictive permissions, you can limit the Resource to specific inference profile ARNs.
bedrock:GetInferenceProfile
lets Claude Code resolve an
application inference profile ARN
to its backing foundation model, which is used to select the correct request shape for that model.
If the token is missing this permission, Claude Code recovers automatically by retrying once with the alternate shape, so requests still succeed but each new model adds an extra round-trip. Granting the permission avoids the retry. This applies most often to
AWS_BEARER_TOKEN_BEDROCK
deployments, where the token’s policy is typically narrower than a full IAM role.
For details, see
Bedrock IAM documentation
.
Create a dedicated AWS account for Claude Code to simplify cost tracking and access control.
​
1M token context window
Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the
1M token context window
on Amazon Bedrock. Claude Code automatically enables the extended context window when you select a 1M model variant.
The
setup wizard
offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append
[1m]
to the model ID. See
Pin models for third-party deployments
for details.
​
Service tiers
Amazon Bedrock service tiers
let you trade off cost against latency. Set
ANTHROPIC_BEDROCK_SERVICE_TIER
to
default
,
flex
, or
priority
:
export
ANTHROPIC_BEDROCK_SERVICE_TIER
=
priority
Claude Code sends this as the
X-Amzn-Bedrock-Service-Tier
header on each request. Tier availability varies by model and region. Reserved capacity uses a
provisioned throughput
ARN as the model ID instead of this setting.
​
AWS Guardrails
Amazon Bedrock Guardrails
let you implement content filtering for Claude Code. Create a Guardrail in the
Amazon Bedrock console
, publish a version, then add the Guardrail headers to your
settings file
. Enable Cross-Region inference on your Guardrail if you’re using cross-region inference profiles.
Example configuration:
{
"env"
: {
"ANTHROPIC_CUSTOM_HEADERS"
:
"X-Amzn-Bedrock-GuardrailIdentifier: your-guardrail-id
\n
X-Amzn-Bedrock-GuardrailVersion: 1"
}
}
​
Use the Mantle endpoint
Mantle is an Amazon Bedrock endpoint that serves Claude models through the native Anthropic API shape rather than the Bedrock Invoke API. It uses the same AWS credentials, IAM permissions, and
awsAuthRefresh
configuration described earlier on this page.
Mantle requires Claude Code v2.1.94 or later. Run
claude --version
to check.
​
Enable Mantle
With AWS credentials already configured, set
CLAUDE_CODE_USE_MANTLE
to route requests to the Mantle endpoint:
export
CLAUDE_CODE_USE_MANTLE
=
1
export
AWS_REGION
=
us-east-1
Claude Code constructs the endpoint URL from
AWS_REGION
. To override it for a custom endpoint or gateway, set
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
.
Run
/status
inside Claude Code to confirm. The provider line shows
Amazon Bedrock (Mantle)
when Mantle is active.
​
Select a Mantle model
Mantle uses model IDs prefixed with
anthropic.
and without a version suffix, for example
anthropic.claude-haiku-4-5
. The models available to your account depend on what your organization has been granted; additional model IDs are listed in your onboarding materials from AWS. Contact your AWS account team to request access to allowlisted models.
Set the model with the
--model
flag or with
/model
inside Claude Code:
claude
--model
anthropic.claude-haiku-4-5
​
Run Mantle alongside the Invoke API
The models available to you on Mantle may not include every model you use today. Setting both
CLAUDE_CODE_USE_BEDROCK
and
CLAUDE_CODE_USE_MANTLE
lets Claude Code call both endpoints from the same session. Model IDs that match the Mantle format are routed to Mantle, and all other model IDs go to the Bedrock Invoke API.
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
CLAUDE_CODE_USE_MANTLE
=
1
To surface a Mantle model in the
/model
picker, list its ID in
availableModels
in your
settings file
. This setting also restricts the picker to the listed entries, so include every alias you want to keep available:
{
"availableModels"
: [
"opus"
,
"sonnet"
,
"haiku"
,
"anthropic.claude-haiku-4-5"
]
}
Entries with the
anthropic.
prefix are added as custom picker options and routed to Mantle. Replace
anthropic.claude-haiku-4-5
with the model ID your account has been granted. See
Restrict model selection
for how
availableModels
interacts with other model settings.
When both providers are active,
/status
shows
Amazon Bedrock + Amazon Bedrock (Mantle)
.
​
Route Mantle through a gateway
If your organization routes model traffic through a centralized
LLM gateway
that injects AWS credentials server-side, disable client-side authentication so Claude Code sends requests without SigV4 signatures or
x-api-key
headers:
export
CLAUDE_CODE_USE_MANTLE
=
1
export
CLAUDE_CODE_SKIP_MANTLE_AUTH
=
1
export
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
=
https
://
your-gateway
.
example
.
com
​
Mantle environment variables
These variables are specific to the Mantle endpoint. See
Environment variables
for the full list.
Variable
Purpose
CLAUDE_CODE_USE_MANTLE
Enable the Mantle endpoint. Set to
1
or
true
.
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
Override the default Mantle endpoint URL
CLAUDE_CODE_SKIP_MANTLE_AUTH
Skip client-side authentication for proxy setups
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
Override AWS region for the Haiku-class model (shared with Bedrock)
​
Troubleshooting
​
Authentication loop with SSO and corporate proxies
If browser tabs spawn repeatedly when using AWS SSO, remove the
awsAuthRefresh
setting from your
settings file
. This can occur when corporate VPNs or TLS inspection proxies interrupt the SSO browser flow. Claude Code treats the interrupted connection as an authentication failure, re-runs
awsAuthRefresh
, and loops indefinitely.
If your network environment interferes with automatic browser-based SSO flows, use
aws sso login
manually before starting Claude Code instead of relying on
awsAuthRefresh
.
​
Region issues
If you encounter region issues:
Check model availability:
aws bedrock list-inference-profiles --region your-region
Switch to a supported region:
export AWS_REGION=us-east-1
Consider using inference profiles for cross-region access
If you receive an error “on-demand throughput isn’t supported”:
Specify the model as an
inference profile
ID
Claude Code uses the Bedrock
Invoke API
and does not support the Converse API.
​
Mantle endpoint errors
If
/status
does not show
Amazon Bedrock (Mantle)
after you set
CLAUDE_CODE_USE_MANTLE
, the variable is not reaching the process. Confirm it is exported in the shell where you launched
claude
, or set it in the
env
block of your
settings file
.
A
403
from the Mantle endpoint with valid credentials means your AWS account has not been granted access to the model you requested. Contact your AWS account team to request access.
A
400
that names the model ID means that model is not served on Mantle. Mantle has its own model lineup separate from the standard Bedrock catalog, so inference profile IDs such as
us.anthropic.claude-sonnet-4-6
will not work. Use a Mantle-format ID, or enable
both endpoints
so Claude Code routes each request to the endpoint where the model is available.
​
Additional resources
Bedrock documentation
Bedrock pricing
Bedrock inference profiles
Bedrock token burndown and quotas
Claude Code on Amazon Bedrock: Quick Setup Guide
Claude Code Monitoring Implementation (Bedrock)
Was this page helpful?
Yes
No
Overview
Claude Platform on AWS
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/amazon-bedrock" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Amazon Bedrock
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketpl...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Claude Code on Amazon Bedrock
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Deploying Claude Code across your organization?
Talk to sales about enterprise plans, SSO, and centralized billing.
View plans
Contact sales
​
Prerequisites
Before configuring Claude Code with Bedrock, ensure you have:
An AWS account with Bedrock access enabled
Access to desired Claude models (for example, Claude Sonnet 4.6) in Bedrock
AWS CLI installed and configured (optional - only needed if you don’t have another mechanism for getting credentials)
Appropriate IAM permissions
To sign in with your own Bedrock credentials, follow
Sign in with Bedrock
below. To deploy Claude Code across a team, use the
manual setup
steps and
pin your model versions
before rolling out.
​
Sign in with Bedrock
If you have AWS credentials and want to start using Claude Code through Bedrock, the login wizard walks you through it. You complete the AWS-side prerequisites once per account; the wizard handles the Claude Code side.
1
Enable Anthropic models in your AWS account
In the
Amazon Bedrock console
, open the Model catalog, select an Anthropic model, and submit the use case form. Access is granted immediately after submission. See
Submit use case details
for AWS Organizations and
IAM configuration
for the permissions your role needs.
2
Start Claude Code and choose Bedrock
Run
claude
. At the login prompt, select
3rd-party platform
, then
Amazon Bedrock
.
3
Follow the wizard prompts
Choose how you authenticate to AWS: an AWS profile detected from your
~/.aws
directory, a Bedrock API key, an access key and secret, or credentials already in your environment. The wizard picks up your region, verifies which Claude models your account can invoke, and lets you pin them. It saves the result to the
env
block of your
user settings file
, so you don’t need to export environment variables yourself.
After you’ve signed in, run
/setup-bedrock
any time to reopen the wizard and change your credentials, region, or model pins.
​
Set up manually
To configure Bedrock through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.
​
1. Submit use case details
First-time users of Anthropic models are required to submit use case details before invoking a model. This is done once per AWS account.
Ensure you have the right IAM permissions described below
Navigate to the
Amazon Bedrock console
Select an Anthropic model from the
Model catalog
Complete the use case form. Access is granted immediately after submission.
If you use AWS Organizations, you can submit the form once from the management account using the
PutUseCaseForModelAccess
API
. This call requires the
bedrock:PutUseCaseForModelAccess
IAM permission. Approval extends to child accounts automatically.
​
2. Configure AWS credentials
Claude Code uses the default AWS SDK credential chain. Set up your credentials using one of these methods:
Option A: AWS CLI configuration
aws
configure
Option B: Environment variables (access key)
export
AWS_ACCESS_KEY_ID
=
your-access-key-id
export
AWS_SECRET_ACCESS_KEY
=
your-secret-access-key
export
AWS_SESSION_TOKEN
=
your-session-token
Option C: Environment variables (SSO profile)
aws
sso
login
--profile=
<
your-profile-name
>
export
AWS_PROFILE
=
your-profile-name
Option D: AWS Management Console credentials
aws
login
Learn more
about
aws login
.
Option E: Bedrock API keys
export
AWS_BEARER_TOKEN_BEDROCK
=
your-bedrock-api-key
Bedrock API keys provide a simpler authentication method without needing full AWS credentials.
Learn more about Bedrock API keys
.
​
Advanced credential configuration
Claude Code supports automatic credential refresh for AWS SSO and corporate identity providers. Add these settings to your Claude Code settings file (see
Settings
for file locations).
These two settings have different trigger conditions:
awsAuthRefresh
: runs only when Claude Code detects that your AWS credentials are expired, either locally based on their timestamp or when Bedrock returns a credential error, then retries the request with refreshed credentials.
awsCredentialExport
: runs at session start and on each credential reload, even when the credentials in your AWS default credential provider chain are still valid. Use this when your Bedrock account requires cross-account credentials that differ from the ones the default provider chain would resolve.
Example configuration
{
"awsAuthRefresh"
:
"aws sso login --profile myprofile"
,
"env"
: {
"AWS_PROFILE"
:
"myprofile"
}
}
Configuration settings explained
awsAuthRefresh
: Use this for commands that modify the
.aws
directory, such as updating credentials, SSO cache, or config files. The command’s output is displayed to the user, but interactive input isn’t supported. This works well for browser-based SSO flows where the CLI displays a URL or code and you complete authentication in the browser.
awsCredentialExport
: Only use this if you can’t modify
.aws
and must directly return credentials. This command runs whenever credentials need to be refreshed, not only when credentials are expired. Output is captured silently and not shown to the user. The command must output JSON in this format:
{
"Credentials"
: {
"AccessKeyId"
:
"value"
,
"SecretAccessKey"
:
"value"
,
"SessionToken"
:
"value"
}
}
​
3. Configure Claude Code
Set the following environment variables to enable Bedrock:
# Enable Bedrock integration
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
AWS_REGION
=
us-east-1
# or your preferred region
# Optional: Override the AWS region for the small/fast model (Bedrock and Mantle).
# On Bedrock, has no effect without ANTHROPIC_DEFAULT_HAIKU_MODEL
# or the deprecated ANTHROPIC_SMALL_FAST_MODEL set.
export
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
=
us-west-2
# Optional: Override the Bedrock endpoint URL for custom endpoints or gateways
# export ANTHROPIC_BEDROCK_BASE_URL=https://bedrock-runtime.us-east-1.amazonaws.com
When enabling Bedrock for Claude Code, keep the following in mind:
AWS_REGION
is a required environment variable. Claude Code does not read from the
.aws
config file for this setting.
When using Bedrock, the
/login
and
/logout
commands are disabled since authentication is handled through AWS credentials.
You can use settings files for environment variables like
AWS_PROFILE
that you don’t want to leak to other processes. See
Settings
for more information.
​
4. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as
sonnet
and
opus
resolve to the latest version, which may not yet be available in your Bedrock account when Anthropic releases an update. Claude Code
falls back
to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Bedrock model IDs.
Without
ANTHROPIC_DEFAULT_OPUS_MODEL
, the
opus
alias on Bedrock resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:
export
ANTHROPIC_DEFAULT_OPUS_MODEL
=
'us.anthropic.claude-opus-4-7'
export
ANTHROPIC_DEFAULT_SONNET_MODEL
=
'us.anthropic.claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'us.anthropic.claude-haiku-4-5-20251001-v1:0'
These variables use cross-region inference profile IDs (with the
us.
prefix). If you use a different region prefix or application inference profiles, adjust accordingly. For current and legacy model IDs, see
Models overview
. See
Model configuration
for the full list of environment variables.
Claude Code uses these default models when no pinning variables are set:
Model type
Default value
Primary model
us.anthropic.claude-sonnet-4-5-20250929-v1:0
Small/fast model
Same as primary model
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Bedrock, Claude Code defaults this to the primary model because Haiku may not be enabled in every account or region. To use Haiku for background tasks, set
ANTHROPIC_DEFAULT_HAIKU_MODEL
to a model ID that is available in your account.
To customize models further, use one of these methods:
# Using inference profile ID
export
ANTHROPIC_MODEL
=
'us.anthropic.claude-sonnet-4-6'
export
ANTHROPIC_DEFAULT_HAIKU_MODEL
=
'us.anthropic.claude-haiku-4-5-20251001-v1:0'
# Using application inference profile ARN
export
ANTHROPIC_MODEL
=
'arn:aws:bedrock:us-east-2:your-account-id:application-inference-profile/your-model-id'
# Optional: Disable prompt caching if needed
export
DISABLE_PROMPT_CACHING
=
1
# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default
export
ENABLE_PROMPT_CACHING_1H
=
1
Prompt caching
may not be available in all regions. Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes.
​
Map each model version to an inference profile
The
ANTHROPIC_DEFAULT_*_MODEL
environment variables configure one inference profile per model family. If your organization needs to expose several versions of the same family in the
/model
picker, each routed to its own application inference profile ARN, use the
modelOverrides
setting in your
settings file
instead.
This example maps four Opus versions to distinct ARNs so users can switch between them without bypassing your organization’s inference profiles:
{
"modelOverrides"
: {
"claude-opus-4-7"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-47-prod"
,
"claude-opus-4-6"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod"
,
"claude-opus-4-5-20251101"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-45-prod"
,
"claude-opus-4-1-20250805"
:
"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-41-prod"
}
}
When a user selects one of these versions in
/model
, Claude Code calls Bedrock with the mapped ARN. Versions without an override fall back to the built-in Bedrock model ID or any matching inference profile discovered at startup. See
Override model IDs per version
for details on how overrides interact with
availableModels
and other model settings.
​
Startup model checks
When Claude Code starts with Bedrock configured, it verifies that the models it intends to use are accessible in your account. This check requires Claude Code v2.1.94 or later.
If you have pinned a model version that is older than the current Claude Code default, and your account can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your
user settings file
and restarts Claude Code. Declining is remembered until the next default version change. Pins that point to an
application inference profile ARN
are skipped, since those are managed by your administrator.
If you have not pinned a model and the current default is unavailable in your account, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in your Bedrock account or
pin a version
to make the choice permanent.
​
IAM configuration
Create an IAM policy with the required permissions for Claude Code:
{
"Version"
:
"2012-10-17"
,
"Statement"
: [
{
"Sid"
:
"AllowModelAndInferenceProfileAccess"
,
"Effect"
:
"Allow"
,
"Action"
: [
"bedrock:InvokeModel"
,
"bedrock:InvokeModelWithResponseStream"
,
"bedrock:ListInferenceProfiles"
,
"bedrock:GetInferenceProfile"
],
"Resource"
: [
"arn:aws:bedrock:*:*:inference-profile/*"
,
"arn:aws:bedrock:*:*:application-inference-profile/*"
,
"arn:aws:bedrock:*:*:foundation-model/*"
]
},
{
"Sid"
:
"AllowMarketplaceSubscription"
,
"Effect"
:
"Allow"
,
"Action"
: [
"aws-marketplace:ViewSubscriptions"
,
"aws-marketplace:Subscribe"
],
"Resource"
:
"*"
,
"Condition"
: {
"StringEquals"
: {
"aws:CalledViaLast"
:
"bedrock.amazonaws.com"
}
}
}
]
}
For more restrictive permissions, you can limit the Resource to specific inference profile ARNs.
bedrock:GetInferenceProfile
lets Claude Code resolve an
application inference profile ARN
to its backing foundation model, which is used to select the correct request shape for that model.
If the token is missing this permission, Claude Code recovers automatically by retrying once with the alternate shape, so requests still succeed but each new model adds an extra round-trip. Granting the permission avoids the retry. This applies most often to
AWS_BEARER_TOKEN_BEDROCK
deployments, where the token’s policy is typically narrower than a full IAM role.
For details, see
Bedrock IAM documentation
.
Create a dedicated AWS account for Claude Code to simplify cost tracking and access control.
​
1M token context window
Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the
1M token context window
on Amazon Bedrock. Claude Code automatically enables the extended context window when you select a 1M model variant.
The
setup wizard
offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append
[1m]
to the model ID. See
Pin models for third-party deployments
for details.
​
Service tiers
Amazon Bedrock service tiers
let you trade off cost against latency. Set
ANTHROPIC_BEDROCK_SERVICE_TIER
to
default
,
flex
, or
priority
:
export
ANTHROPIC_BEDROCK_SERVICE_TIER
=
priority
Claude Code sends this as the
X-Amzn-Bedrock-Service-Tier
header on each request. Tier availability varies by model and region. Reserved capacity uses a
provisioned throughput
ARN as the model ID instead of this setting.
​
AWS Guardrails
Amazon Bedrock Guardrails
let you implement content filtering for Claude Code. Create a Guardrail in the
Amazon Bedrock console
, publish a version, then add the Guardrail headers to your
settings file
. Enable Cross-Region inference on your Guardrail if you’re using cross-region inference profiles.
Example configuration:
{
"env"
: {
"ANTHROPIC_CUSTOM_HEADERS"
:
"X-Amzn-Bedrock-GuardrailIdentifier: your-guardrail-id
\n
X-Amzn-Bedrock-GuardrailVersion: 1"
}
}
​
Use the Mantle endpoint
Mantle is an Amazon Bedrock endpoint that serves Claude models through the native Anthropic API shape rather than the Bedrock Invoke API. It uses the same AWS credentials, IAM permissions, and
awsAuthRefresh
configuration described earlier on this page.
Mantle requires Claude Code v2.1.94 or later. Run
claude --version
to check.
​
Enable Mantle
With AWS credentials already configured, set
CLAUDE_CODE_USE_MANTLE
to route requests to the Mantle endpoint:
export
CLAUDE_CODE_USE_MANTLE
=
1
export
AWS_REGION
=
us-east-1
Claude Code constructs the endpoint URL from
AWS_REGION
. To override it for a custom endpoint or gateway, set
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
.
Run
/status
inside Claude Code to confirm. The provider line shows
Amazon Bedrock (Mantle)
when Mantle is active.
​
Select a Mantle model
Mantle uses model IDs prefixed with
anthropic.
and without a version suffix, for example
anthropic.claude-haiku-4-5
. The models available to your account depend on what your organization has been granted; additional model IDs are listed in your onboarding materials from AWS. Contact your AWS account team to request access to allowlisted models.
Set the model with the
--model
flag or with
/model
inside Claude Code:
claude
--model
anthropic.claude-haiku-4-5
​
Run Mantle alongside the Invoke API
The models available to you on Mantle may not include every model you use today. Setting both
CLAUDE_CODE_USE_BEDROCK
and
CLAUDE_CODE_USE_MANTLE
lets Claude Code call both endpoints from the same session. Model IDs that match the Mantle format are routed to Mantle, and all other model IDs go to the Bedrock Invoke API.
export
CLAUDE_CODE_USE_BEDROCK
=
1
export
CLAUDE_CODE_USE_MANTLE
=
1
To surface a Mantle model in the
/model
picker, list its ID in
availableModels
in your
settings file
. This setting also restricts the picker to the listed entries, so include every alias you want to keep available:
{
"availableModels"
: [
"opus"
,
"sonnet"
,
"haiku"
,
"anthropic.claude-haiku-4-5"
]
}
Entries with the
anthropic.
prefix are added as custom picker options and routed to Mantle. Replace
anthropic.claude-haiku-4-5
with the model ID your account has been granted. See
Restrict model selection
for how
availableModels
interacts with other model settings.
When both providers are active,
/status
shows
Amazon Bedrock + Amazon Bedrock (Mantle)
.
​
Route Mantle through a gateway
If your organization routes model traffic through a centralized
LLM gateway
that injects AWS credentials server-side, disable client-side authentication so Claude Code sends requests without SigV4 signatures or
x-api-key
headers:
export
CLAUDE_CODE_USE_MANTLE
=
1
export
CLAUDE_CODE_SKIP_MANTLE_AUTH
=
1
export
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
=
https
://
your-gateway
.
example
.
com
​
Mantle environment variables
These variables are specific to the Mantle endpoint. See
Environment variables
for the full list.
Variable
Purpose
CLAUDE_CODE_USE_MANTLE
Enable the Mantle endpoint. Set to
1
or
true
.
ANTHROPIC_BEDROCK_MANTLE_BASE_URL
Override the default Mantle endpoint URL
CLAUDE_CODE_SKIP_MANTLE_AUTH
Skip client-side authentication for proxy setups
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION
Override AWS region for the Haiku-class model (shared with Bedrock)
​
Troubleshooting
​
Authentication loop with SSO and corporate proxies
If browser tabs spawn repeatedly when using AWS SSO, remove the
awsAuthRefresh
setting from your
settings file
. This can occur when corporate VPNs or TLS inspection proxies interrupt the SSO browser flow. Claude Code treats the interrupted connection as an authentication failure, re-runs
awsAuthRefresh
, and loops indefinitely.
If your network environment interferes with automatic browser-based SSO flows, use
aws sso login
manually before starting Claude Code instead of relying on
awsAuthRefresh
.
​
Region issues
If you encounter region issues:
Check model availability:
aws bedrock list-inference-profiles --region your-region
Switch to a supported region:
export AWS_REGION=us-east-1
Consider using inference profiles for cross-region access
If you receive an error “on-demand throughput isn’t supported”:
Specify the model as an
inference profile
ID
Claude Code uses the Bedrock
Invoke API
and does not support the Converse API.
​
Mantle endpoint errors
If
/status
does not show
Amazon Bedrock (Mantle)
after you set
CLAUDE_CODE_USE_MANTLE
, the variable is not reaching the process. Confirm it is exported in the shell where you launched
claude
, or set it in the
env
block of your
settings file
.
A
403
from the Mantle endpoint with valid credentials means your AWS account has not been granted access to the model you requested. Contact your AWS account team to request access.
A
400
that names the model ID means that model is not served on Mantle. Mantle has its own model lineup separate from the standard Bedrock catalog, so inference profile IDs such as
us.anthropic.claude-sonnet-4-6
will not work. Use a Mantle-format ID, or enable
both endpoints
so Claude Code routes each request to the endpoint where the model is available.
​
Additional resources
Bedrock documentation
Bedrock pricing
Bedrock inference profiles
Bedrock token burndown and quotas
Claude Code on Amazon Bedrock: Quick Setup Guide
Claude Code Monitoring Implementation (Bedrock)
Was this page helpful?
Yes
No
Overview
Claude Platform on AWS
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/amazon-bedrock" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Use Claude Code with Chrome (beta)</title>
  <link>https://code.claude.com/docs/en/chrome</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/chrome</guid>
  <pubDate>Wed, 17 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code with Chrome (beta)
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code with Chrome (beta)
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code integrates with the
Claude in Chrome browser extension
to give you browser automation capabilities from the CLI or the
VS Code extension
. Build your code, then test and debug in the browser without switching contexts.
Claude opens new tabs for browser tasks and shares your browser’s login state, so it can access any site you’re already signed into. Browser actions run in a visible Chrome window in real time. When Claude encounters a login page or CAPTCHA, it pauses and asks you to handle it manually.
Chrome integration is in beta and currently works with Google Chrome and Microsoft Edge. It is not yet supported on Brave, Arc, or other Chromium-based browsers. WSL (Windows Subsystem for Linux) is also not supported.
​
Capabilities
With Chrome connected, you can chain browser actions with coding tasks in a single workflow:
Live debugging
: read console errors and DOM state directly, then fix the code that caused them
Design verification
: build a UI from a Figma mock, then open it in the browser to verify it matches
Web app testing
: test form validation, check for visual regressions, or verify user flows
Authenticated web apps
: interact with Google Docs, Gmail, Notion, or any app you’re logged into without API connectors
Data extraction
: pull structured information from web pages and save it locally
Task automation
: automate repetitive browser tasks like data entry, form filling, or multi-site workflows
Session recording
: record browser interactions as GIFs to document or share what happened
​
Prerequisites
Before using Claude Code with Chrome, you need:
Google Chrome
or
Microsoft Edge
browser
Claude in Chrome extension
version 1.0.36 or higher, available in the Chrome Web Store for both browsers
Claude Code
version 2.0.73 or higher
A direct Anthropic plan (Pro, Max, Team, or Enterprise)
Chrome integration is not available through third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.
​
Get started in the CLI
1
Launch Claude Code with Chrome
Start Claude Code with the
--chrome
flag:
claude
--chrome
You can also enable Chrome from within an existing session by running
/chrome
.
2
Ask Claude to use the browser
This example navigates to a page, interacts with it, and reports what it finds, all from your terminal or editor:
Go to code.claude.com/docs, click on the search box,
type "hooks", and tell me what results appear
Run
/chrome
at any time to check the connection status, manage permissions, or reconnect the extension.
For VS Code, see
browser automation in VS Code
.
​
Enable Chrome by default
To avoid passing
--chrome
each session, run
/chrome
and select “Enabled by default”.
In the
VS Code extension
, Chrome is available whenever the Chrome extension is installed. No additional flag is needed.
Enabling Chrome by default in the CLI increases context usage since browser tools are always loaded. If you notice increased context consumption, disable this setting and use
--chrome
only when needed.
​
Manage site permissions
Site-level permissions are inherited from the Chrome extension. Manage permissions in the Chrome extension settings to control which sites Claude can browse, click, and type on.
​
Example workflows
These examples show common ways to combine browser actions with coding tasks. Run
/mcp
and select
claude-in-chrome
to see the full list of available browser tools.
​
Test a local web application
When developing a web app, ask Claude to verify your changes work correctly:
I just updated the login form validation. Can you open localhost:3000,
try submitting the form with invalid data, and check if the error
messages appear correctly?
Claude navigates to your local server, interacts with the form, and reports what it observes.
​
Debug with console logs
Claude can read console output to help diagnose problems. Tell Claude what patterns to look for rather than asking for all console output, since logs can be verbose:
Open the dashboard page and check the console for any errors when
the page loads.
Claude reads the console messages and can filter for specific patterns or error types.
​
Automate form filling
Speed up repetitive data entry tasks:
I have a spreadsheet of customer contacts in contacts.csv. For each row,
go to the CRM at crm.example.com, click "Add Contact", and fill in the
name, email, and phone fields.
Claude reads your local file, navigates the web interface, and enters the data for each record.
​
Draft content in Google Docs
Use Claude to write directly in your documents without API setup:
Draft a project update based on the recent commits and add it to my
Google Doc at docs.google.com/document/d/abc123
Claude opens the document, clicks into the editor, and types the content. This works with any web app you’re logged into: Gmail, Notion, Sheets, and more.
​
Extract data from web pages
Pull structured information from websites:
Go to the product listings page and extract the name, price, and
availability for each item. Save the results as a CSV file.
Claude navigates to the page, reads the content, and compiles the data into a structured format.
​
Run multi-site workflows
Coordinate tasks across multiple websites:
Check my calendar for meetings tomorrow, then for each meeting with
an external attendee, look up their company website and add a note
about what they do.
Claude works across tabs to gather information and complete the workflow.
​
Record a demo GIF
Create shareable recordings of browser interactions:
Record a GIF showing how to complete the checkout flow, from adding
an item to the cart through to the confirmation page.
Claude records the interaction sequence and saves it as a GIF file.
​
Troubleshooting
​
Extension not detected
If Claude Code shows “Chrome extension not detected”:
Verify the Chrome extension is installed and enabled in
chrome://extensions
Verify Claude Code is up to date by running
claude --version
Check that Chrome is running
Run
/chrome
and select “Reconnect extension” to re-establish the connection
If the issue persists, restart both Claude Code and Chrome
The first time you enable Chrome integration, Claude Code installs a native messaging host configuration file. Chrome reads this file on startup, so if the extension isn’t detected on your first attempt, restart Chrome to pick up the new configuration.
If the connection still fails, verify the host configuration file exists at:
For Chrome:
macOS
:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Linux
:
~/.config/google-chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Windows
: check
HKCU\Software\Google\Chrome\NativeMessagingHosts\
in the Windows Registry
For Edge:
macOS
:
~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Linux
:
~/.config/microsoft-edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Windows
: check
HKCU\Software\Microsoft\Edge\NativeMessagingHosts\
in the Windows Registry
​
Browser not responding
If Claude’s browser commands stop working:
Check if a modal dialog (alert, confirm, prompt) is blocking the page. JavaScript dialogs block browser events and prevent Claude from receiving commands. Dismiss the dialog manually, then tell Claude to continue.
Ask Claude to create a new tab and try again
Restart the Chrome extension by disabling and re-enabling it in
chrome://extensions
​
Connection drops during long sessions
The Chrome extension’s service worker can go idle during extended sessions, which breaks the connection. If browser tools stop working after a period of inactivity, run
/chrome
and select “Reconnect extension”.
​
Windows-specific issues
On Windows, you may encounter:
Named pipe conflicts (EADDRINUSE)
: if another process is using the same named pipe, restart Claude Code. Close any other Claude Code sessions that might be using Chrome.
Native messaging host errors
: if the native messaging host crashes on startup, try reinstalling Claude Code to regenerate the host configuration.
​
Common error messages
These are the most frequently encountered errors and how to resolve them:
Error
Cause
Fix
”Browser extension is not connected”
Native messaging host cannot reach the extension
Restart Chrome and Claude Code, then run
/chrome
to reconnect
”Extension not detected”
Chrome extension is not installed or is disabled
Install or enable the extension in
chrome://extensions
”No tab available”
Claude tried to act before a tab was ready
Ask Claude to create a new tab and retry
”Receiving end does not exist”
Extension service worker went idle
Run
/chrome
and select “Reconnect extension”
​
See also
Computer use
: control native macOS apps when a task can’t be done in a browser
Use Claude Code in VS Code
: browser automation in the VS Code extension
CLI reference
: command-line flags including
--chrome
Common workflows
: more ways to use Claude Code
Data and privacy
: how Claude Code handles your data
Getting started with Claude in Chrome
: full documentation for the Chrome extension, including shortcuts, scheduling, and permissions
Was this page helpful?
Yes
No
Desktop changelog
Computer use (preview)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/chrome" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code with Chrome (beta)
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Platforms and integrations
Use Claude Code with Chrome (beta)
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Claude Code integrates with the
Claude in Chrome browser extension
to give you browser automation capabilities from the CLI or the
VS Code extension
. Build your code, then test and debug in the browser without switching contexts.
Claude opens new tabs for browser tasks and shares your browser’s login state, so it can access any site you’re already signed into. Browser actions run in a visible Chrome window in real time. When Claude encounters a login page or CAPTCHA, it pauses and asks you to handle it manually.
Chrome integration is in beta and currently works with Google Chrome and Microsoft Edge. It is not yet supported on Brave, Arc, or other Chromium-based browsers. WSL (Windows Subsystem for Linux) is also not supported.
​
Capabilities
With Chrome connected, you can chain browser actions with coding tasks in a single workflow:
Live debugging
: read console errors and DOM state directly, then fix the code that caused them
Design verification
: build a UI from a Figma mock, then open it in the browser to verify it matches
Web app testing
: test form validation, check for visual regressions, or verify user flows
Authenticated web apps
: interact with Google Docs, Gmail, Notion, or any app you’re logged into without API connectors
Data extraction
: pull structured information from web pages and save it locally
Task automation
: automate repetitive browser tasks like data entry, form filling, or multi-site workflows
Session recording
: record browser interactions as GIFs to document or share what happened
​
Prerequisites
Before using Claude Code with Chrome, you need:
Google Chrome
or
Microsoft Edge
browser
Claude in Chrome extension
version 1.0.36 or higher, available in the Chrome Web Store for both browsers
Claude Code
version 2.0.73 or higher
A direct Anthropic plan (Pro, Max, Team, or Enterprise)
Chrome integration is not available through third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.
​
Get started in the CLI
1
Launch Claude Code with Chrome
Start Claude Code with the
--chrome
flag:
claude
--chrome
You can also enable Chrome from within an existing session by running
/chrome
.
2
Ask Claude to use the browser
This example navigates to a page, interacts with it, and reports what it finds, all from your terminal or editor:
Go to code.claude.com/docs, click on the search box,
type "hooks", and tell me what results appear
Run
/chrome
at any time to check the connection status, manage permissions, or reconnect the extension.
For VS Code, see
browser automation in VS Code
.
​
Enable Chrome by default
To avoid passing
--chrome
each session, run
/chrome
and select “Enabled by default”.
In the
VS Code extension
, Chrome is available whenever the Chrome extension is installed. No additional flag is needed.
Enabling Chrome by default in the CLI increases context usage since browser tools are always loaded. If you notice increased context consumption, disable this setting and use
--chrome
only when needed.
​
Manage site permissions
Site-level permissions are inherited from the Chrome extension. Manage permissions in the Chrome extension settings to control which sites Claude can browse, click, and type on.
​
Example workflows
These examples show common ways to combine browser actions with coding tasks. Run
/mcp
and select
claude-in-chrome
to see the full list of available browser tools.
​
Test a local web application
When developing a web app, ask Claude to verify your changes work correctly:
I just updated the login form validation. Can you open localhost:3000,
try submitting the form with invalid data, and check if the error
messages appear correctly?
Claude navigates to your local server, interacts with the form, and reports what it observes.
​
Debug with console logs
Claude can read console output to help diagnose problems. Tell Claude what patterns to look for rather than asking for all console output, since logs can be verbose:
Open the dashboard page and check the console for any errors when
the page loads.
Claude reads the console messages and can filter for specific patterns or error types.
​
Automate form filling
Speed up repetitive data entry tasks:
I have a spreadsheet of customer contacts in contacts.csv. For each row,
go to the CRM at crm.example.com, click "Add Contact", and fill in the
name, email, and phone fields.
Claude reads your local file, navigates the web interface, and enters the data for each record.
​
Draft content in Google Docs
Use Claude to write directly in your documents without API setup:
Draft a project update based on the recent commits and add it to my
Google Doc at docs.google.com/document/d/abc123
Claude opens the document, clicks into the editor, and types the content. This works with any web app you’re logged into: Gmail, Notion, Sheets, and more.
​
Extract data from web pages
Pull structured information from websites:
Go to the product listings page and extract the name, price, and
availability for each item. Save the results as a CSV file.
Claude navigates to the page, reads the content, and compiles the data into a structured format.
​
Run multi-site workflows
Coordinate tasks across multiple websites:
Check my calendar for meetings tomorrow, then for each meeting with
an external attendee, look up their company website and add a note
about what they do.
Claude works across tabs to gather information and complete the workflow.
​
Record a demo GIF
Create shareable recordings of browser interactions:
Record a GIF showing how to complete the checkout flow, from adding
an item to the cart through to the confirmation page.
Claude records the interaction sequence and saves it as a GIF file.
​
Troubleshooting
​
Extension not detected
If Claude Code shows “Chrome extension not detected”:
Verify the Chrome extension is installed and enabled in
chrome://extensions
Verify Claude Code is up to date by running
claude --version
Check that Chrome is running
Run
/chrome
and select “Reconnect extension” to re-establish the connection
If the issue persists, restart both Claude Code and Chrome
The first time you enable Chrome integration, Claude Code installs a native messaging host configuration file. Chrome reads this file on startup, so if the extension isn’t detected on your first attempt, restart Chrome to pick up the new configuration.
If the connection still fails, verify the host configuration file exists at:
For Chrome:
macOS
:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Linux
:
~/.config/google-chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Windows
: check
HKCU\Software\Google\Chrome\NativeMessagingHosts\
in the Windows Registry
For Edge:
macOS
:
~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Linux
:
~/.config/microsoft-edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json
Windows
: check
HKCU\Software\Microsoft\Edge\NativeMessagingHosts\
in the Windows Registry
​
Browser not responding
If Claude’s browser commands stop working:
Check if a modal dialog (alert, confirm, prompt) is blocking the page. JavaScript dialogs block browser events and prevent Claude from receiving commands. Dismiss the dialog manually, then tell Claude to continue.
Ask Claude to create a new tab and try again
Restart the Chrome extension by disabling and re-enabling it in
chrome://extensions
​
Connection drops during long sessions
The Chrome extension’s service worker can go idle during extended sessions, which breaks the connection. If browser tools stop working after a period of inactivity, run
/chrome
and select “Reconnect extension”.
​
Windows-specific issues
On Windows, you may encounter:
Named pipe conflicts (EADDRINUSE)
: if another process is using the same named pipe, restart Claude Code. Close any other Claude Code sessions that might be using Chrome.
Native messaging host errors
: if the native messaging host crashes on startup, try reinstalling Claude Code to regenerate the host configuration.
​
Common error messages
These are the most frequently encountered errors and how to resolve them:
Error
Cause
Fix
”Browser extension is not connected”
Native messaging host cannot reach the extension
Restart Chrome and Claude Code, then run
/chrome
to reconnect
”Extension not detected”
Chrome extension is not installed or is disabled
Install or enable the extension in
chrome://extensions
”No tab available”
Claude tried to act before a tab was ready
Ask Claude to create a new tab and retry
”Receiving end does not exist”
Extension service worker went idle
Run
/chrome
and select “Reconnect extension”
​
See also
Computer use
: control native macOS apps when a task can’t be done in a browser
Use Claude Code in VS Code
: browser automation in the VS Code extension
CLI reference
: command-line flags including
--chrome
Common workflows
: more ways to use Claude Code
Data and privacy
: how Claude Code handles your data
Getting started with Claude in Chrome
: full documentation for the Chrome extension, including shortcuts, scheduling, and permissions
Was this page helpful?
Yes
No
Desktop changelog
Computer use (preview)
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/chrome" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Schedule recurring tasks in Claude Code Desktop</title>
  <link>https://code.claude.com/docs/en/desktop-scheduled-tasks</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/desktop-scheduled-tasks</guid>
  <pubDate>Tue, 16 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Schedule recurring tasks in Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on deskt...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Schedule recurring tasks in Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Scheduled tasks start a new session automatically at a time and frequency you choose. Use them for recurring work like daily code reviews, dependency update checks, or morning briefings that pull from your calendar and inbox.
The Desktop app’s
Routines
page lets you create both local scheduled tasks and remote
routines
. A local task runs on your machine with direct access to your files and tools, but only fires while the app is open and your computer is awake. A remote routine runs on Anthropic-managed cloud infrastructure even when your computer is off, and can also fire on API calls or GitHub events. This page covers local scheduled tasks; for remote routines and their trigger options, see
Routines
.
​
Compare scheduling options
Claude Code offers three ways to schedule recurring or one-off work:
Cloud
Desktop
/loop
Runs on
Anthropic cloud
Your machine
Your machine
Requires machine on
No
Yes
Yes
Requires open session
No
No
Yes
Persistent across restarts
Yes
Yes
Restored on
--resume
if unexpired
Access to local files
No (fresh clone)
Yes
Yes
MCP servers
Connectors configured per task
Config files
and connectors
Inherits from session
Permission prompts
No (runs autonomously)
Configurable per task
Inherits from session
Customizable schedule
Via
/schedule
in the CLI
Yes
Yes
Minimum interval
1 hour
1 minute
1 minute
Use
cloud tasks
for work that should run reliably without your machine. Use
Desktop tasks
when you need access to local files and tools. Use
/loop
for quick polling during a session.
By default, scheduled tasks run against whatever state your working directory is in, including uncommitted changes. Enable the worktree toggle when creating the task to give each run its own isolated Git worktree, the same way
parallel sessions
work.
​
Create a scheduled task
Click
Routines
in the sidebar, then click
New routine
and choose
Local
. Configure these fields:
Field
Description
Name
Identifier for the task. Converted to lowercase kebab-case and used as the folder name on disk. Must be unique across your tasks.
Description
Short summary shown in the task list.
Instructions
What Claude should do when the task runs. Write this the same way you’d write any message in the prompt box. The instructions input includes pickers for the permission mode and model, and below it you select the working folder and whether to run in an isolated worktree.
Schedule
How often the task runs. See
schedule options
below.
A folder is required before you can save the task. If you haven’t trusted that folder yet, Desktop prompts you to trust it before saving.
You can also create a task by describing what you want in any session. For example, “set up a daily code review that runs every morning at 9am” creates a recurring task, and “remind me at 3pm tomorrow to check the deploy” creates a one-time task that disables itself after it fires.
​
Schedule options
Pick a preset from the Schedule control:
Manual
: no schedule, only runs when you click
Run now
. Useful for saving a prompt you trigger on demand
Hourly
: runs every hour
Daily
: shows a time picker, defaults to 9:00 AM local time
Weekdays
: same as Daily but skips Saturday and Sunday
Weekly
: shows a time picker and a day picker
For intervals the picker doesn’t offer, such as every 15 minutes, the first of each month, or a single run at a specific future time, ask Claude in any Desktop session to set the schedule. Use plain language; for example, “schedule a task to run all the tests every 6 hours.”
​
How scheduled tasks run
Scheduled tasks run on your machine. Desktop checks the schedule every minute while the app is open and starts a fresh session when a task is due, independent of any manual sessions you have open. Each task gets a small delay of a few minutes after the scheduled time to stagger API traffic. The delay is deterministic: the same task always starts at the same offset.
When a task fires, you get a desktop notification and a new session appears under a
Scheduled
section in the sidebar. Open it to see what Claude did, review changes, or respond to permission prompts. The session works like any other: Claude can edit files, run commands, create commits, and open pull requests.
Tasks only run while the desktop app is running and your computer is awake. If your computer sleeps through a scheduled time, the run is skipped. To prevent idle-sleep, enable
Keep computer awake
in Settings under
Desktop app → General
. Closing the laptop lid still puts it to sleep. For tasks that need to run even when your computer is off, or that should trigger on an API call or GitHub event, create a remote
routine
instead.
​
Missed runs
When the app starts or your computer wakes, Desktop checks whether each task missed any runs in the last seven days. If it did, Desktop starts exactly one catch-up run for the most recently missed time and discards anything older. A daily task that missed six days runs once on wake. Desktop shows a notification when a catch-up run starts.
Keep this in mind when writing prompts. A task scheduled for 9am might run at 11pm if your computer was asleep all day. If timing matters, add guardrails to the prompt itself, for example: “Only review today’s commits. If it’s after 5pm, skip the review and just post a summary of what was missed.”
​
Permissions for scheduled tasks
Each task has its own permission mode, which you set when creating or editing the task. Allow rules from
~/.claude/settings.json
also apply to scheduled task sessions. If a task runs in Ask mode and needs to run a tool it doesn’t have permission for, the run stalls until you approve it. The session stays open in the sidebar so you can answer later.
To avoid stalls, click
Run now
after creating a task, watch for permission prompts, and select “always allow” for each one. Future runs of that task auto-approve the same tools without prompting. You can review and revoke these approvals from the task’s detail page.
​
Manage scheduled tasks
Click a task in the
Routines
list to open its detail page. From here you can:
Run now
: start the task immediately without waiting for the next scheduled time
Status
: toggle between Active and Paused to pause or resume scheduled runs without deleting the task
Edit
: change the instructions, schedule, folder, or other settings
Review history
: see every past run, including skipped runs. Hover a skipped entry to see why: your computer was asleep, the previous run was still in progress, or other scheduled tasks were already running. Click
Show more
to load older entries.
Review allowed permissions
: see and revoke saved tool approvals for this task from the
Always allowed
panel
Delete
: remove the task and archive all sessions it created. An
Also delete files on disk
checkbox appears in the confirmation dialog; check it to also remove the task’s
SKILL.md
file and associated data from
~/.claude/scheduled-tasks/
.
You can also list, create, edit, and pause tasks by asking Claude in any Desktop session. For example, “pause my dependency-audit task” or “show me my scheduled tasks.” To delete a task, use the
Delete
button on its detail page.
A scheduled task can also modify its own schedule or prompt from within a running session using the
update_scheduled_task
MCP tool. This lets a task reschedule itself based on what it finds, for example, rescheduling a code review to run earlier when it detects a release branch has been created.
To edit a task’s prompt on disk, open
~/.claude/scheduled-tasks/<task-name>/SKILL.md
(or under
CLAUDE_CONFIG_DIR
if set). The file uses YAML frontmatter for
name
and
description
, with the prompt as the body. Changes take effect on the next run. Schedule, folder, model, and enabled state are not in this file: change them through the Edit form or ask Claude.
​
Related resources
Routines
: run tasks on Anthropic-managed infrastructure on a schedule, via API call, or in response to GitHub events, even when your computer is off
Run prompts on a schedule
: session-scoped scheduling with
/loop
in the CLI
Claude Code GitHub Actions
: run Claude on a schedule in CI instead of on your machine
Use Claude Code Desktop
: the full Desktop app guide
Was this page helpful?
Yes
No
Reference
Desktop changelog
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-scheduled-tasks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Schedule recurring tasks in Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on deskt...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on desktop
Schedule recurring tasks in Claude Code Desktop
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Claude Code on desktop
Get started
Reference
Scheduled tasks
Desktop changelog
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Scheduled tasks start a new session automatically at a time and frequency you choose. Use them for recurring work like daily code reviews, dependency update checks, or morning briefings that pull from your calendar and inbox.
The Desktop app’s
Routines
page lets you create both local scheduled tasks and remote
routines
. A local task runs on your machine with direct access to your files and tools, but only fires while the app is open and your computer is awake. A remote routine runs on Anthropic-managed cloud infrastructure even when your computer is off, and can also fire on API calls or GitHub events. This page covers local scheduled tasks; for remote routines and their trigger options, see
Routines
.
​
Compare scheduling options
Claude Code offers three ways to schedule recurring or one-off work:
Cloud
Desktop
/loop
Runs on
Anthropic cloud
Your machine
Your machine
Requires machine on
No
Yes
Yes
Requires open session
No
No
Yes
Persistent across restarts
Yes
Yes
Restored on
--resume
if unexpired
Access to local files
No (fresh clone)
Yes
Yes
MCP servers
Connectors configured per task
Config files
and connectors
Inherits from session
Permission prompts
No (runs autonomously)
Configurable per task
Inherits from session
Customizable schedule
Via
/schedule
in the CLI
Yes
Yes
Minimum interval
1 hour
1 minute
1 minute
Use
cloud tasks
for work that should run reliably without your machine. Use
Desktop tasks
when you need access to local files and tools. Use
/loop
for quick polling during a session.
By default, scheduled tasks run against whatever state your working directory is in, including uncommitted changes. Enable the worktree toggle when creating the task to give each run its own isolated Git worktree, the same way
parallel sessions
work.
​
Create a scheduled task
Click
Routines
in the sidebar, then click
New routine
and choose
Local
. Configure these fields:
Field
Description
Name
Identifier for the task. Converted to lowercase kebab-case and used as the folder name on disk. Must be unique across your tasks.
Description
Short summary shown in the task list.
Instructions
What Claude should do when the task runs. Write this the same way you’d write any message in the prompt box. The instructions input includes pickers for the permission mode and model, and below it you select the working folder and whether to run in an isolated worktree.
Schedule
How often the task runs. See
schedule options
below.
A folder is required before you can save the task. If you haven’t trusted that folder yet, Desktop prompts you to trust it before saving.
You can also create a task by describing what you want in any session. For example, “set up a daily code review that runs every morning at 9am” creates a recurring task, and “remind me at 3pm tomorrow to check the deploy” creates a one-time task that disables itself after it fires.
​
Schedule options
Pick a preset from the Schedule control:
Manual
: no schedule, only runs when you click
Run now
. Useful for saving a prompt you trigger on demand
Hourly
: runs every hour
Daily
: shows a time picker, defaults to 9:00 AM local time
Weekdays
: same as Daily but skips Saturday and Sunday
Weekly
: shows a time picker and a day picker
For intervals the picker doesn’t offer, such as every 15 minutes, the first of each month, or a single run at a specific future time, ask Claude in any Desktop session to set the schedule. Use plain language; for example, “schedule a task to run all the tests every 6 hours.”
​
How scheduled tasks run
Scheduled tasks run on your machine. Desktop checks the schedule every minute while the app is open and starts a fresh session when a task is due, independent of any manual sessions you have open. Each task gets a small delay of a few minutes after the scheduled time to stagger API traffic. The delay is deterministic: the same task always starts at the same offset.
When a task fires, you get a desktop notification and a new session appears under a
Scheduled
section in the sidebar. Open it to see what Claude did, review changes, or respond to permission prompts. The session works like any other: Claude can edit files, run commands, create commits, and open pull requests.
Tasks only run while the desktop app is running and your computer is awake. If your computer sleeps through a scheduled time, the run is skipped. To prevent idle-sleep, enable
Keep computer awake
in Settings under
Desktop app → General
. Closing the laptop lid still puts it to sleep. For tasks that need to run even when your computer is off, or that should trigger on an API call or GitHub event, create a remote
routine
instead.
​
Missed runs
When the app starts or your computer wakes, Desktop checks whether each task missed any runs in the last seven days. If it did, Desktop starts exactly one catch-up run for the most recently missed time and discards anything older. A daily task that missed six days runs once on wake. Desktop shows a notification when a catch-up run starts.
Keep this in mind when writing prompts. A task scheduled for 9am might run at 11pm if your computer was asleep all day. If timing matters, add guardrails to the prompt itself, for example: “Only review today’s commits. If it’s after 5pm, skip the review and just post a summary of what was missed.”
​
Permissions for scheduled tasks
Each task has its own permission mode, which you set when creating or editing the task. Allow rules from
~/.claude/settings.json
also apply to scheduled task sessions. If a task runs in Ask mode and needs to run a tool it doesn’t have permission for, the run stalls until you approve it. The session stays open in the sidebar so you can answer later.
To avoid stalls, click
Run now
after creating a task, watch for permission prompts, and select “always allow” for each one. Future runs of that task auto-approve the same tools without prompting. You can review and revoke these approvals from the task’s detail page.
​
Manage scheduled tasks
Click a task in the
Routines
list to open its detail page. From here you can:
Run now
: start the task immediately without waiting for the next scheduled time
Status
: toggle between Active and Paused to pause or resume scheduled runs without deleting the task
Edit
: change the instructions, schedule, folder, or other settings
Review history
: see every past run, including skipped runs. Hover a skipped entry to see why: your computer was asleep, the previous run was still in progress, or other scheduled tasks were already running. Click
Show more
to load older entries.
Review allowed permissions
: see and revoke saved tool approvals for this task from the
Always allowed
panel
Delete
: remove the task and archive all sessions it created. An
Also delete files on disk
checkbox appears in the confirmation dialog; check it to also remove the task’s
SKILL.md
file and associated data from
~/.claude/scheduled-tasks/
.
You can also list, create, edit, and pause tasks by asking Claude in any Desktop session. For example, “pause my dependency-audit task” or “show me my scheduled tasks.” To delete a task, use the
Delete
button on its detail page.
A scheduled task can also modify its own schedule or prompt from within a running session using the
update_scheduled_task
MCP tool. This lets a task reschedule itself based on what it finds, for example, rescheduling a code review to run earlier when it detects a release branch has been created.
To edit a task’s prompt on disk, open
~/.claude/scheduled-tasks/<task-name>/SKILL.md
(or under
CLAUDE_CONFIG_DIR
if set). The file uses YAML frontmatter for
name
and
description
, with the prompt as the body. Changes take effect on the next run. Schedule, folder, model, and enabled state are not in this file: change them through the Edit form or ask Claude.
​
Related resources
Routines
: run tasks on Anthropic-managed infrastructure on a schedule, via API call, or in response to GitHub events, even when your computer is off
Run prompts on a schedule
: session-scoped scheduling with
/loop
in the CLI
Claude Code GitHub Actions
: run Claude on a schedule in CI instead of on your machine
Use Claude Code Desktop
: the full Desktop app guide
Was this page helpful?
Yes
No
Reference
Desktop changelog
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/desktop-scheduled-tasks" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Automate work with routines</title>
  <link>https://code.claude.com/docs/en/routines</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/routines</guid>
  <pubDate>Sun, 14 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Automate work with routines
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Automate work with routines
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Routines are in research preview. Behavior, limits, and the API surface may change.
A routine is a saved Claude Code configuration: a prompt, one or more repositories, and a set of
connectors
, packaged once and run automatically. Routines execute on Anthropic-managed cloud infrastructure, so they keep working when your laptop is closed.
Each routine can have one or more triggers attached to it:
Scheduled
: run on a recurring cadence like hourly, nightly, or weekly, or once at a specific future time
API
: trigger on demand by sending an HTTP POST to a per-routine endpoint with a bearer token
GitHub
: run automatically in response to repository events such as pull requests or releases
A single routine can combine triggers. For example, a PR review routine can run nightly, trigger from a deploy script, and also react to every new PR.
Routines are available on Pro, Max, Team, and Enterprise plans with
Claude Code on the web
enabled. Create and manage them at
claude.ai/code/routines
, or from the CLI with
/schedule
.
Team and Enterprise admins can disable routines for all members with the Routines toggle at
claude.ai/admin-settings/claude-code
. When disabled, existing routines stop running and members cannot create new ones.
This page covers creating a routine, configuring each trigger type, managing runs, and how usage limits apply.
​
Example use cases
Each example pairs a trigger type with the kind of work routines are suited to: unattended, repeatable, and tied to a clear outcome.
Backlog maintenance.
A schedule trigger runs every weeknight against your issue tracker via a connector. The routine reads issues opened since the last run, applies labels, assigns owners based on the area of code referenced, and posts a summary to Slack so the team starts the day with a groomed queue.
Alert triage.
Your monitoring tool calls the routine’s API endpoint when an error threshold is crossed, passing the alert body as
text
. The routine pulls the stack trace, correlates it with recent commits in the repository, and opens a draft pull request with a proposed fix and a link back to the alert. On-call reviews the PR instead of starting from a blank terminal.
Bespoke code review.
A GitHub trigger runs on
pull_request.opened
. The routine applies your team’s own review checklist, leaves inline comments for security, performance, and style issues, and adds a summary comment so human reviewers can focus on design instead of mechanical checks.
Deploy verification.
Your CD pipeline calls the routine’s API endpoint after each production deploy. The routine runs smoke checks against the new build, scans error logs for regressions, and posts a go or no-go to the release channel before the deploy window closes.
Docs drift.
A schedule trigger runs weekly. The routine scans merged PRs since the last run, flags documentation that references changed APIs, and opens update PRs against the docs repository for an editor to review.
Library port.
A GitHub trigger runs on
pull_request.closed
filtered to merged PRs in one SDK repository. The routine ports the change to a parallel SDK in another language and opens a matching PR, keeping the two libraries in step without a human re-implementing each change.
The sections below walk through creating a routine and configuring each of these trigger types.
​
Create a routine
Create a routine from the web at
claude.ai/code/routines
, from the Desktop app, or from the CLI. All three surfaces write to the same cloud account, so a routine you create in one shows up in the others immediately. In the Desktop app, click
Routines
in the sidebar, then
New routine
, and choose
Remote
; choosing
Local
instead creates a
Desktop scheduled task
, which runs on your machine rather than in the cloud.
The creation form sets up the routine’s prompt, repositories, environment, connectors, and triggers.
Routines run autonomously as full Claude Code cloud sessions: there is no permission-mode picker and no approval prompts during a run. The session can run shell commands, use
skills
committed to the cloned repository, and call any connectors you include. What a routine can reach is determined by the repositories you select and their branch-push setting, the
environment’s
network access and variables, and the connectors you include. Scope each of those to what the routine actually needs.
Routines belong to your individual claude.ai account. They are not shared with teammates, and they count against your account’s daily run allowance. Anything a routine does through your connected GitHub identity or connectors appears as you: commits and pull requests carry your GitHub user, and Slack messages, Linear tickets, or other connector actions use your linked accounts for those services.
​
Create from the web
1
Open the creation form
Visit
claude.ai/code/routines
and click
New routine
.
2
Name the routine and write the prompt
Give the routine a descriptive name and write the prompt Claude runs each time. The prompt is the most important part: the routine runs autonomously, so the prompt must be self-contained and explicit about what to do and what success looks like.
The prompt input includes a model selector. Claude uses the selected model on every run.
3
Select repositories
Add one or more GitHub repositories for Claude to work in. Each repository is cloned at the start of a run, starting from the default branch. Claude creates
claude/
-prefixed branches for its changes.
4
Select an environment
Pick a
cloud environment
for the routine. Environments control what the cloud session has access to:
Network access
: set the level of internet access available during each run
Environment variables
: provide API keys, tokens, or other secrets Claude can use
Setup script
: install dependencies and tools the routine needs. The result is
cached
, so the script doesn’t re-run on every session
A
Default
environment is provided with
Trusted
network access, which allows the
default set
of package registries, cloud provider APIs, container registries, and common development domains, but blocks everything else. If your routine needs to reach your own services or a domain outside that list, edit the environment’s
network access
before running. To use a separate environment,
create one
first.
5
Select a trigger
Under
Select a trigger
, choose how the routine starts. You can pick one trigger type or combine several.
Schedule
GitHub event
API
Pick a preset frequency for a recurring run, or schedule a single one-off run at a specific timestamp. See
Add a schedule trigger
for timezone handling, stagger, custom cron intervals, and one-off runs.
Select the repository, the event to react to, and optional filters. See
Add a GitHub trigger
for the full list of supported events and filter fields.
Select
API
here, then save the routine. The URL and token are generated after the routine is saved, since they depend on the routine ID. See
Add an API trigger
to copy the URL and generate a token.
6
Review connectors and permissions
The
Connectors
and
Permissions
tabs at the bottom of the form control what the routine can reach.
Under Connectors, all of your connected
MCP connectors
are included by default. Remove any the routine doesn’t need. Claude can use every tool from an included connector, including writes, without asking for permission during a run.
Under Permissions, enable
Allow unrestricted branch pushes
for any repository where Claude should be able to push to existing branches instead of only
claude/
-prefixed ones.
7
Create the routine
Click
Create
. The routine appears in the list and runs the next time one of its triggers matches. To start a run immediately, click
Run now
on the routine’s detail page.
Each run creates a new session alongside your other sessions, where you can see what Claude did, review changes, and create a pull request.
​
Create from the CLI
Run
/schedule
in any session to create a scheduled routine conversationally. You can also pass a description directly, for a recurring routine like
/schedule daily PR review at 9am
or a one-off like
/schedule clean up feature flag in one week
. Claude walks through the same information the web form collects, then saves the routine to your account.
/schedule
in the CLI creates scheduled routines only. To add an API or GitHub trigger, edit the routine on the web at
claude.ai/code/routines
.
The CLI also supports managing existing routines. Run
/schedule list
to see all routines,
/schedule update
to change one, or
/schedule run
to trigger it immediately.
​
Configure triggers
A routine starts when one of its triggers matches. You can attach any combination of schedule, API, and GitHub triggers to the same routine, and add or remove them at any time from the
Select a trigger
section of the routine’s edit form.
​
Add a schedule trigger
A schedule trigger runs the routine on a recurring cadence, or once at a specific future time. Pick a preset frequency in the
Select a trigger
section: hourly, daily, weekdays, or weekly. Times are entered in your local zone and converted automatically, so the routine runs at that wall-clock time regardless of where the cloud infrastructure is located.
Runs may start a few minutes after the scheduled time due to stagger. The offset is consistent for each routine.
For a custom interval such as every two hours or the first of each month, pick the closest preset in the form, then run
/schedule update
in the CLI to set a specific cron expression. The minimum interval is one hour; expressions that run more frequently are rejected.
​
Schedule a one-off run
A one-off schedule fires the routine a single time at a specific timestamp. Use it to remind yourself later in the week, to open a cleanup PR after a rollout finishes, or to kick off a follow-up task when an upstream change lands. After the routine fires, it auto-disables and the web UI marks it as
Ran
. To run it again, edit the routine and set a new one-off time.
Create a one-off run from the CLI by describing the time in natural language. Claude resolves the phrase against the current time and confirms the absolute timestamp before saving.
/schedule tomorrow at 9am, summarize yesterday's merged PRs
/schedule in 2 weeks, open a cleanup PR that removes the feature flag
The same local-to-UTC conversion as recurring schedules applies to one-off timestamps.
One-off runs do not count against the daily routine run cap. They consume your plan’s regular subscription usage like any other session. See
Usage and limits
for details.
​
Add an API trigger
An API trigger gives a routine a dedicated HTTP endpoint. POSTing to the endpoint with the routine’s bearer token starts a new session and returns a session URL. Use this to wire Claude Code into alerting systems, deploy pipelines, internal tools, or anywhere you can make an authenticated HTTP request.
API triggers are added to an existing routine from the web. The CLI cannot currently create or revoke tokens.
1
Open the routine for editing
Go to
claude.ai/code/routines
, click the routine you want to trigger via API, then click the pencil icon to open
Edit routine
.
2
Add an API trigger
Scroll to the
Select a trigger
section below the
Instructions
box, click
Add another trigger
, and choose
API
.
3
Copy the URL and generate a token
The modal shows the URL for this routine along with a sample curl command. Copy the URL, then click
Generate token
and copy the token immediately. The token is shown once and cannot be retrieved later, so store it somewhere secure such as your alerting tool’s secret store.
4
Call the endpoint
Send the token in the
Authorization: Bearer
header when you POST to the URL. The
Trigger a routine
section below shows a complete example.
Each routine has its own token, scoped to triggering that routine only. To rotate or revoke it, return to the same modal and click
Regenerate
or
Revoke
.
​
Trigger a routine
Send a POST request to the
/fire
endpoint with the bearer token in the
Authorization
header. The request body accepts an optional
text
field for run-specific context such as an alert body or a failing log, passed to the routine alongside its saved prompt. The value is freeform text and is not parsed: if you send JSON or another structured payload, the routine receives it as a literal string.
The example below triggers a routine from a shell:
curl
-X
POST
https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEFGHJKLMNOPQRSTUVW/fire
\
-H
"Authorization: Bearer sk-ant-oat01-xxxxx"
\
-H
"anthropic-beta: experimental-cc-routine-2026-04-01"
\
-H
"anthropic-version: 2023-06-01"
\
-H
"Content-Type: application/json"
\
-d
'{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'
A successful request returns a JSON body with the new session ID and URL:
{
"type"
:
"routine_fire"
,
"claude_code_session_id"
:
"session_01HJKLMNOPQRSTUVWXYZ"
,
"claude_code_session_url"
:
"https://claude.ai/code/session_01HJKLMNOPQRSTUVWXYZ"
}
Open the session URL in a browser to watch the run in real time, review changes, or continue the conversation manually.
The
/fire
endpoint ships under the
experimental-cc-routine-2026-04-01
beta header. Request and response shapes, rate limits, and token semantics may change while the feature is in research preview. Breaking changes ship behind new dated beta header versions, and the two most recent previous header versions continue to work so that callers have time to migrate.
​
API reference
For the full API reference, including all error responses, validation rules, and field limits, see
Trigger a routine via API
in the Claude Platform documentation.
The
/fire
endpoint is available to claude.ai users only and is not part of the Claude Platform API surface.
​
Add a GitHub trigger
A GitHub trigger starts a new session automatically when a matching event occurs on a connected repository. Each matching event starts its own session.
During the research preview, GitHub webhook events are subject to per-routine and per-account hourly caps. Events beyond the limit are dropped until the window resets. See your current limits at
claude.ai/code/routines
.
GitHub triggers are configured from the web UI only.
1
Open the routine for editing
Go to
claude.ai/code/routines
, click the routine, then click the pencil icon to open
Edit routine
.
2
Add a GitHub event trigger
Scroll to the
Select a trigger
section, click
Add another trigger
, and choose
GitHub event
.
3
Install the Claude GitHub App
The Claude GitHub App must be installed on the repository you want to subscribe to. The trigger setup prompts you to install it if it isn’t already.
Running
/web-setup
in the CLI grants repository access for cloning, but it does not install the Claude GitHub App and does not enable webhook delivery. GitHub triggers require installing the Claude GitHub App, which the trigger setup prompts you to do.
4
Configure the trigger
Select the repository, choose an event from the
supported events
list, and optionally add filters. Save the trigger.
​
Supported events
GitHub triggers can subscribe to either of the following event categories. Within each category you can pick a specific action, such as
pull_request.opened
, or react to all actions in the category.
Event
Triggers when
Pull request
A PR is opened, closed, assigned, labeled, synchronized, or otherwise updated
Release
A release is created, published, edited, or deleted
​
Filter pull requests
Use filters to narrow which pull requests start a new session. All filter conditions must match for the routine to trigger. The available filter fields are:
Filter
Matches
Author
PR author’s GitHub username
Title
PR title text
Body
PR description text
Base branch
Branch the PR targets
Head branch
Branch the PR comes from
Labels
Labels applied to the PR
Is draft
Whether the PR is in draft state
Is merged
Whether the PR has been merged
Each filter pairs a field with an operator: equals, contains, starts with, is one of, is not one of, or matches regex.
The
matches regex
operator tests the entire field value, not a substring within it. To match any title containing
hotfix
, write
.*hotfix.*
. Without the surrounding
.*
, the filter matches only a title that is exactly
hotfix
with nothing before or after. For literal substring matching without regex syntax, use the
contains
operator instead.
A few example filter combinations:
Auth module review
: base branch
main
, head branch contains
auth-provider
. Sends any PR that touches authentication to a focused reviewer.
Ready-for-review only
: is draft is
false
. Skips drafts so the routine only runs when the PR is ready for review.
Label-gated backport
: labels include
needs-backport
. Triggers a port-to-another-branch routine only when a maintainer tags the PR.
​
How sessions map to events
Each matching GitHub event starts a new session. Session reuse across events is not available for GitHub-triggered routines, so two PR updates produce two independent sessions.
​
Manage routines
Click a routine in the list to open its detail page. The detail page shows the routine’s repositories, connectors, prompt, schedule, API tokens, GitHub triggers, and a list of past runs.
​
View and interact with runs
Click any run to open it as a full session. From there you can see what Claude did, review changes, create a pull request, or continue the conversation. Each run session works like any other session: use the dropdown menu next to the session title to rename, archive, or delete it.
A green status in the run list means the session started and exited without an infrastructure error. It does not mean the task in your prompt succeeded. Open the run to read the transcript and confirm what Claude actually did. Blocked network requests, missing connector tools, and task-level failures all surface there rather than in the status indicator.
​
Edit and control routines
From the routine detail page you can:
Click
Run now
to start a run immediately without waiting for the next scheduled time.
Use the toggle in the
Repeats
section to pause or resume the schedule. Paused routines keep their configuration but don’t run until you re-enable them.
Click the pencil icon to open
Edit routine
and change the name, prompt, repositories, environment, connectors, or any of the routine’s triggers. The
Select a trigger
section is where you add or remove schedules, API tokens, and GitHub event triggers.
Click the delete icon to remove the routine. Past sessions created by the routine remain in your session list.
​
Repositories and branch permissions
Routines need GitHub access to clone repositories. When you create a routine from the CLI with
/schedule
, Claude checks whether your account has GitHub connected and prompts you to run
/web-setup
if it doesn’t. See
GitHub authentication options
for the two ways to grant access.
Each repository you add is cloned on every run. Claude starts from the repository’s default branch unless your prompt specifies otherwise.
By default, Claude can only push to branches prefixed with
claude/
. This prevents routines from accidentally modifying protected or long-lived branches. To remove this restriction for a specific repository, enable
Allow unrestricted branch pushes
for that repository when creating or editing the routine.
​
Connectors
Routines can use your connected MCP connectors to read from and write to external services during each run. For example, a routine that triages support requests might read from a Slack channel and create issues in Linear.
Connectors are the
claude.ai integrations
on your account. MCP servers you added locally in the CLI with
claude mcp add
are stored on your machine rather than your claude.ai account, so they do not appear in the connectors list. To use one of those servers in a routine, add it as a connector at
claude.ai/customize/connectors
, or declare it in a committed
.mcp.json
so it is part of the cloned repository.
When you create a routine, all of your currently connected connectors are included by default. Remove any that aren’t needed to limit which tools Claude has access to during the run. You can also add connectors directly from the routine form.
To manage or add connectors outside of the routine form, visit
Settings > Connectors
on claude.ai or use
/schedule update
in the CLI.
​
Environments and network access
Each routine runs in a
cloud environment
that controls network access, environment variables, and setup scripts. The routine inherits the environment’s network policy on every run.
The
Default
environment uses
Trusted
network access: the
default allowlist
of package registries, cloud provider APIs, container registries, and common development domains is reachable, but arbitrary domains are not. Outbound requests to other hosts fail with
403
and
x-deny-reason: host_not_allowed
. MCP connector traffic is routed through Anthropic’s servers, so the connectors you add to the routine work without adding their hosts to
Allowed domains
. Remove any connectors you don’t need under
Connectors
.
To allow additional domains:
1
Open the routine for editing
On the routine’s detail page, click the pencil icon to open
Edit routine
.
2
Open the environment selector
Below the
Instructions
box, select the cloud icon showing your environment’s name, such as
Default
.
3
Open the environment settings
Hover over the environment in the list and click the settings icon that appears on the right.
4
Change the network access level
In the
Update cloud environment
dialog, change
Network access
to
Custom
and enter your domains in
Allowed domains
. Check
Also include default list of common package managers
to keep the
default allowlist
alongside your custom domains. Select
Full
instead for unrestricted access.
5
Save
Click
Save changes
. The new policy applies from the next run.
See
Network access
for details on access levels and the default allowlist.
​
Usage and limits
Routines draw down subscription usage the same way interactive sessions do. In addition to the standard subscription limits, routines have a daily cap on how many runs can start per account. See your current consumption and remaining daily routine runs at
claude.ai/code/routines
or
claude.ai/settings/usage
.
When a routine hits the daily cap or your subscription usage limit, organizations with extra usage enabled can keep running routines on metered overage. Without extra usage, additional runs are rejected until the window resets. Enable extra usage from
Settings > Billing
on claude.ai.
One-off runs do not count against the daily routine cap. They draw down your regular subscription usage like any other session, but they are exempt from the per-account daily routine run allowance.
​
Troubleshooting
​
”Routines are disabled by your organization’s policy”
Your Team or Enterprise admin has likely turned off the
Routines
toggle at
claude.ai/admin-settings/claude-code
. This is a server-side organization setting, so it cannot be overridden from your local configuration. Contact your admin to request that routines be enabled for your organization.
​
Related resources
/loop
and in-session scheduling
: schedule local tasks within an open CLI session
Desktop scheduled tasks
: local scheduled tasks that run on your machine with access to local files
Cloud environment
: configure the runtime environment for cloud sessions
MCP connectors
: connect external services like Slack, Linear, and Google Drive
GitHub Actions
: run Claude in your CI pipeline on repository events
Was this page helpful?
Yes
No
Reference
Plan in the cloud
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/routines" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Automate work with routines
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in t...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Claude Code on the web
Automate work with routines
Getting started
Overview
Quickstart
Changelog
Core concepts
How Claude Code works
Extend Claude Code
Explore the .claude directory
Explore the context window
Use Claude Code
Store instructions and memories
Permission modes
Common workflows
Best practices
Platforms and integrations
Overview
Remote Control
Claude Code on the web
Get started
Reference
Routines
Plan in the cloud
Ultrareview
Claude Code on desktop
Chrome extension (beta)
Computer use (preview)
Visual Studio Code
JetBrains IDEs
Code review & CI/CD
Claude Code in Slack
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Routines are in research preview. Behavior, limits, and the API surface may change.
A routine is a saved Claude Code configuration: a prompt, one or more repositories, and a set of
connectors
, packaged once and run automatically. Routines execute on Anthropic-managed cloud infrastructure, so they keep working when your laptop is closed.
Each routine can have one or more triggers attached to it:
Scheduled
: run on a recurring cadence like hourly, nightly, or weekly, or once at a specific future time
API
: trigger on demand by sending an HTTP POST to a per-routine endpoint with a bearer token
GitHub
: run automatically in response to repository events such as pull requests or releases
A single routine can combine triggers. For example, a PR review routine can run nightly, trigger from a deploy script, and also react to every new PR.
Routines are available on Pro, Max, Team, and Enterprise plans with
Claude Code on the web
enabled. Create and manage them at
claude.ai/code/routines
, or from the CLI with
/schedule
.
Team and Enterprise admins can disable routines for all members with the Routines toggle at
claude.ai/admin-settings/claude-code
. When disabled, existing routines stop running and members cannot create new ones.
This page covers creating a routine, configuring each trigger type, managing runs, and how usage limits apply.
​
Example use cases
Each example pairs a trigger type with the kind of work routines are suited to: unattended, repeatable, and tied to a clear outcome.
Backlog maintenance.
A schedule trigger runs every weeknight against your issue tracker via a connector. The routine reads issues opened since the last run, applies labels, assigns owners based on the area of code referenced, and posts a summary to Slack so the team starts the day with a groomed queue.
Alert triage.
Your monitoring tool calls the routine’s API endpoint when an error threshold is crossed, passing the alert body as
text
. The routine pulls the stack trace, correlates it with recent commits in the repository, and opens a draft pull request with a proposed fix and a link back to the alert. On-call reviews the PR instead of starting from a blank terminal.
Bespoke code review.
A GitHub trigger runs on
pull_request.opened
. The routine applies your team’s own review checklist, leaves inline comments for security, performance, and style issues, and adds a summary comment so human reviewers can focus on design instead of mechanical checks.
Deploy verification.
Your CD pipeline calls the routine’s API endpoint after each production deploy. The routine runs smoke checks against the new build, scans error logs for regressions, and posts a go or no-go to the release channel before the deploy window closes.
Docs drift.
A schedule trigger runs weekly. The routine scans merged PRs since the last run, flags documentation that references changed APIs, and opens update PRs against the docs repository for an editor to review.
Library port.
A GitHub trigger runs on
pull_request.closed
filtered to merged PRs in one SDK repository. The routine ports the change to a parallel SDK in another language and opens a matching PR, keeping the two libraries in step without a human re-implementing each change.
The sections below walk through creating a routine and configuring each of these trigger types.
​
Create a routine
Create a routine from the web at
claude.ai/code/routines
, from the Desktop app, or from the CLI. All three surfaces write to the same cloud account, so a routine you create in one shows up in the others immediately. In the Desktop app, click
Routines
in the sidebar, then
New routine
, and choose
Remote
; choosing
Local
instead creates a
Desktop scheduled task
, which runs on your machine rather than in the cloud.
The creation form sets up the routine’s prompt, repositories, environment, connectors, and triggers.
Routines run autonomously as full Claude Code cloud sessions: there is no permission-mode picker and no approval prompts during a run. The session can run shell commands, use
skills
committed to the cloned repository, and call any connectors you include. What a routine can reach is determined by the repositories you select and their branch-push setting, the
environment’s
network access and variables, and the connectors you include. Scope each of those to what the routine actually needs.
Routines belong to your individual claude.ai account. They are not shared with teammates, and they count against your account’s daily run allowance. Anything a routine does through your connected GitHub identity or connectors appears as you: commits and pull requests carry your GitHub user, and Slack messages, Linear tickets, or other connector actions use your linked accounts for those services.
​
Create from the web
1
Open the creation form
Visit
claude.ai/code/routines
and click
New routine
.
2
Name the routine and write the prompt
Give the routine a descriptive name and write the prompt Claude runs each time. The prompt is the most important part: the routine runs autonomously, so the prompt must be self-contained and explicit about what to do and what success looks like.
The prompt input includes a model selector. Claude uses the selected model on every run.
3
Select repositories
Add one or more GitHub repositories for Claude to work in. Each repository is cloned at the start of a run, starting from the default branch. Claude creates
claude/
-prefixed branches for its changes.
4
Select an environment
Pick a
cloud environment
for the routine. Environments control what the cloud session has access to:
Network access
: set the level of internet access available during each run
Environment variables
: provide API keys, tokens, or other secrets Claude can use
Setup script
: install dependencies and tools the routine needs. The result is
cached
, so the script doesn’t re-run on every session
A
Default
environment is provided with
Trusted
network access, which allows the
default set
of package registries, cloud provider APIs, container registries, and common development domains, but blocks everything else. If your routine needs to reach your own services or a domain outside that list, edit the environment’s
network access
before running. To use a separate environment,
create one
first.
5
Select a trigger
Under
Select a trigger
, choose how the routine starts. You can pick one trigger type or combine several.
Schedule
GitHub event
API
Pick a preset frequency for a recurring run, or schedule a single one-off run at a specific timestamp. See
Add a schedule trigger
for timezone handling, stagger, custom cron intervals, and one-off runs.
Select the repository, the event to react to, and optional filters. See
Add a GitHub trigger
for the full list of supported events and filter fields.
Select
API
here, then save the routine. The URL and token are generated after the routine is saved, since they depend on the routine ID. See
Add an API trigger
to copy the URL and generate a token.
6
Review connectors and permissions
The
Connectors
and
Permissions
tabs at the bottom of the form control what the routine can reach.
Under Connectors, all of your connected
MCP connectors
are included by default. Remove any the routine doesn’t need. Claude can use every tool from an included connector, including writes, without asking for permission during a run.
Under Permissions, enable
Allow unrestricted branch pushes
for any repository where Claude should be able to push to existing branches instead of only
claude/
-prefixed ones.
7
Create the routine
Click
Create
. The routine appears in the list and runs the next time one of its triggers matches. To start a run immediately, click
Run now
on the routine’s detail page.
Each run creates a new session alongside your other sessions, where you can see what Claude did, review changes, and create a pull request.
​
Create from the CLI
Run
/schedule
in any session to create a scheduled routine conversationally. You can also pass a description directly, for a recurring routine like
/schedule daily PR review at 9am
or a one-off like
/schedule clean up feature flag in one week
. Claude walks through the same information the web form collects, then saves the routine to your account.
/schedule
in the CLI creates scheduled routines only. To add an API or GitHub trigger, edit the routine on the web at
claude.ai/code/routines
.
The CLI also supports managing existing routines. Run
/schedule list
to see all routines,
/schedule update
to change one, or
/schedule run
to trigger it immediately.
​
Configure triggers
A routine starts when one of its triggers matches. You can attach any combination of schedule, API, and GitHub triggers to the same routine, and add or remove them at any time from the
Select a trigger
section of the routine’s edit form.
​
Add a schedule trigger
A schedule trigger runs the routine on a recurring cadence, or once at a specific future time. Pick a preset frequency in the
Select a trigger
section: hourly, daily, weekdays, or weekly. Times are entered in your local zone and converted automatically, so the routine runs at that wall-clock time regardless of where the cloud infrastructure is located.
Runs may start a few minutes after the scheduled time due to stagger. The offset is consistent for each routine.
For a custom interval such as every two hours or the first of each month, pick the closest preset in the form, then run
/schedule update
in the CLI to set a specific cron expression. The minimum interval is one hour; expressions that run more frequently are rejected.
​
Schedule a one-off run
A one-off schedule fires the routine a single time at a specific timestamp. Use it to remind yourself later in the week, to open a cleanup PR after a rollout finishes, or to kick off a follow-up task when an upstream change lands. After the routine fires, it auto-disables and the web UI marks it as
Ran
. To run it again, edit the routine and set a new one-off time.
Create a one-off run from the CLI by describing the time in natural language. Claude resolves the phrase against the current time and confirms the absolute timestamp before saving.
/schedule tomorrow at 9am, summarize yesterday's merged PRs
/schedule in 2 weeks, open a cleanup PR that removes the feature flag
The same local-to-UTC conversion as recurring schedules applies to one-off timestamps.
One-off runs do not count against the daily routine run cap. They consume your plan’s regular subscription usage like any other session. See
Usage and limits
for details.
​
Add an API trigger
An API trigger gives a routine a dedicated HTTP endpoint. POSTing to the endpoint with the routine’s bearer token starts a new session and returns a session URL. Use this to wire Claude Code into alerting systems, deploy pipelines, internal tools, or anywhere you can make an authenticated HTTP request.
API triggers are added to an existing routine from the web. The CLI cannot currently create or revoke tokens.
1
Open the routine for editing
Go to
claude.ai/code/routines
, click the routine you want to trigger via API, then click the pencil icon to open
Edit routine
.
2
Add an API trigger
Scroll to the
Select a trigger
section below the
Instructions
box, click
Add another trigger
, and choose
API
.
3
Copy the URL and generate a token
The modal shows the URL for this routine along with a sample curl command. Copy the URL, then click
Generate token
and copy the token immediately. The token is shown once and cannot be retrieved later, so store it somewhere secure such as your alerting tool’s secret store.
4
Call the endpoint
Send the token in the
Authorization: Bearer
header when you POST to the URL. The
Trigger a routine
section below shows a complete example.
Each routine has its own token, scoped to triggering that routine only. To rotate or revoke it, return to the same modal and click
Regenerate
or
Revoke
.
​
Trigger a routine
Send a POST request to the
/fire
endpoint with the bearer token in the
Authorization
header. The request body accepts an optional
text
field for run-specific context such as an alert body or a failing log, passed to the routine alongside its saved prompt. The value is freeform text and is not parsed: if you send JSON or another structured payload, the routine receives it as a literal string.
The example below triggers a routine from a shell:
curl
-X
POST
https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEFGHJKLMNOPQRSTUVW/fire
\
-H
"Authorization: Bearer sk-ant-oat01-xxxxx"
\
-H
"anthropic-beta: experimental-cc-routine-2026-04-01"
\
-H
"anthropic-version: 2023-06-01"
\
-H
"Content-Type: application/json"
\
-d
'{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'
A successful request returns a JSON body with the new session ID and URL:
{
"type"
:
"routine_fire"
,
"claude_code_session_id"
:
"session_01HJKLMNOPQRSTUVWXYZ"
,
"claude_code_session_url"
:
"https://claude.ai/code/session_01HJKLMNOPQRSTUVWXYZ"
}
Open the session URL in a browser to watch the run in real time, review changes, or continue the conversation manually.
The
/fire
endpoint ships under the
experimental-cc-routine-2026-04-01
beta header. Request and response shapes, rate limits, and token semantics may change while the feature is in research preview. Breaking changes ship behind new dated beta header versions, and the two most recent previous header versions continue to work so that callers have time to migrate.
​
API reference
For the full API reference, including all error responses, validation rules, and field limits, see
Trigger a routine via API
in the Claude Platform documentation.
The
/fire
endpoint is available to claude.ai users only and is not part of the Claude Platform API surface.
​
Add a GitHub trigger
A GitHub trigger starts a new session automatically when a matching event occurs on a connected repository. Each matching event starts its own session.
During the research preview, GitHub webhook events are subject to per-routine and per-account hourly caps. Events beyond the limit are dropped until the window resets. See your current limits at
claude.ai/code/routines
.
GitHub triggers are configured from the web UI only.
1
Open the routine for editing
Go to
claude.ai/code/routines
, click the routine, then click the pencil icon to open
Edit routine
.
2
Add a GitHub event trigger
Scroll to the
Select a trigger
section, click
Add another trigger
, and choose
GitHub event
.
3
Install the Claude GitHub App
The Claude GitHub App must be installed on the repository you want to subscribe to. The trigger setup prompts you to install it if it isn’t already.
Running
/web-setup
in the CLI grants repository access for cloning, but it does not install the Claude GitHub App and does not enable webhook delivery. GitHub triggers require installing the Claude GitHub App, which the trigger setup prompts you to do.
4
Configure the trigger
Select the repository, choose an event from the
supported events
list, and optionally add filters. Save the trigger.
​
Supported events
GitHub triggers can subscribe to either of the following event categories. Within each category you can pick a specific action, such as
pull_request.opened
, or react to all actions in the category.
Event
Triggers when
Pull request
A PR is opened, closed, assigned, labeled, synchronized, or otherwise updated
Release
A release is created, published, edited, or deleted
​
Filter pull requests
Use filters to narrow which pull requests start a new session. All filter conditions must match for the routine to trigger. The available filter fields are:
Filter
Matches
Author
PR author’s GitHub username
Title
PR title text
Body
PR description text
Base branch
Branch the PR targets
Head branch
Branch the PR comes from
Labels
Labels applied to the PR
Is draft
Whether the PR is in draft state
Is merged
Whether the PR has been merged
Each filter pairs a field with an operator: equals, contains, starts with, is one of, is not one of, or matches regex.
The
matches regex
operator tests the entire field value, not a substring within it. To match any title containing
hotfix
, write
.*hotfix.*
. Without the surrounding
.*
, the filter matches only a title that is exactly
hotfix
with nothing before or after. For literal substring matching without regex syntax, use the
contains
operator instead.
A few example filter combinations:
Auth module review
: base branch
main
, head branch contains
auth-provider
. Sends any PR that touches authentication to a focused reviewer.
Ready-for-review only
: is draft is
false
. Skips drafts so the routine only runs when the PR is ready for review.
Label-gated backport
: labels include
needs-backport
. Triggers a port-to-another-branch routine only when a maintainer tags the PR.
​
How sessions map to events
Each matching GitHub event starts a new session. Session reuse across events is not available for GitHub-triggered routines, so two PR updates produce two independent sessions.
​
Manage routines
Click a routine in the list to open its detail page. The detail page shows the routine’s repositories, connectors, prompt, schedule, API tokens, GitHub triggers, and a list of past runs.
​
View and interact with runs
Click any run to open it as a full session. From there you can see what Claude did, review changes, create a pull request, or continue the conversation. Each run session works like any other session: use the dropdown menu next to the session title to rename, archive, or delete it.
A green status in the run list means the session started and exited without an infrastructure error. It does not mean the task in your prompt succeeded. Open the run to read the transcript and confirm what Claude actually did. Blocked network requests, missing connector tools, and task-level failures all surface there rather than in the status indicator.
​
Edit and control routines
From the routine detail page you can:
Click
Run now
to start a run immediately without waiting for the next scheduled time.
Use the toggle in the
Repeats
section to pause or resume the schedule. Paused routines keep their configuration but don’t run until you re-enable them.
Click the pencil icon to open
Edit routine
and change the name, prompt, repositories, environment, connectors, or any of the routine’s triggers. The
Select a trigger
section is where you add or remove schedules, API tokens, and GitHub event triggers.
Click the delete icon to remove the routine. Past sessions created by the routine remain in your session list.
​
Repositories and branch permissions
Routines need GitHub access to clone repositories. When you create a routine from the CLI with
/schedule
, Claude checks whether your account has GitHub connected and prompts you to run
/web-setup
if it doesn’t. See
GitHub authentication options
for the two ways to grant access.
Each repository you add is cloned on every run. Claude starts from the repository’s default branch unless your prompt specifies otherwise.
By default, Claude can only push to branches prefixed with
claude/
. This prevents routines from accidentally modifying protected or long-lived branches. To remove this restriction for a specific repository, enable
Allow unrestricted branch pushes
for that repository when creating or editing the routine.
​
Connectors
Routines can use your connected MCP connectors to read from and write to external services during each run. For example, a routine that triages support requests might read from a Slack channel and create issues in Linear.
Connectors are the
claude.ai integrations
on your account. MCP servers you added locally in the CLI with
claude mcp add
are stored on your machine rather than your claude.ai account, so they do not appear in the connectors list. To use one of those servers in a routine, add it as a connector at
claude.ai/customize/connectors
, or declare it in a committed
.mcp.json
so it is part of the cloned repository.
When you create a routine, all of your currently connected connectors are included by default. Remove any that aren’t needed to limit which tools Claude has access to during the run. You can also add connectors directly from the routine form.
To manage or add connectors outside of the routine form, visit
Settings > Connectors
on claude.ai or use
/schedule update
in the CLI.
​
Environments and network access
Each routine runs in a
cloud environment
that controls network access, environment variables, and setup scripts. The routine inherits the environment’s network policy on every run.
The
Default
environment uses
Trusted
network access: the
default allowlist
of package registries, cloud provider APIs, container registries, and common development domains is reachable, but arbitrary domains are not. Outbound requests to other hosts fail with
403
and
x-deny-reason: host_not_allowed
. MCP connector traffic is routed through Anthropic’s servers, so the connectors you add to the routine work without adding their hosts to
Allowed domains
. Remove any connectors you don’t need under
Connectors
.
To allow additional domains:
1
Open the routine for editing
On the routine’s detail page, click the pencil icon to open
Edit routine
.
2
Open the environment selector
Below the
Instructions
box, select the cloud icon showing your environment’s name, such as
Default
.
3
Open the environment settings
Hover over the environment in the list and click the settings icon that appears on the right.
4
Change the network access level
In the
Update cloud environment
dialog, change
Network access
to
Custom
and enter your domains in
Allowed domains
. Check
Also include default list of common package managers
to keep the
default allowlist
alongside your custom domains. Select
Full
instead for unrestricted access.
5
Save
Click
Save changes
. The new policy applies from the next run.
See
Network access
for details on access levels and the default allowlist.
​
Usage and limits
Routines draw down subscription usage the same way interactive sessions do. In addition to the standard subscription limits, routines have a daily cap on how many runs can start per account. See your current consumption and remaining daily routine runs at
claude.ai/code/routines
or
claude.ai/settings/usage
.
When a routine hits the daily cap or your subscription usage limit, organizations with extra usage enabled can keep running routines on metered overage. Without extra usage, additional runs are rejected until the window resets. Enable extra usage from
Settings > Billing
on claude.ai.
One-off runs do not count against the daily routine cap. They draw down your regular subscription usage like any other session, but they are exempt from the per-account daily routine run allowance.
​
Troubleshooting
​
”Routines are disabled by your organization’s policy”
Your Team or Enterprise admin has likely turned off the
Routines
toggle at
claude.ai/admin-settings/claude-code
. This is a server-side organization setting, so it cannot be overridden from your local configuration. Contact your admin to request that routines be enabled for your organization.
​
Related resources
/loop
and in-session scheduling
: schedule local tasks within an open CLI session
Desktop scheduled tasks
: local scheduled tasks that run on your machine with access to local files
Cloud environment
: configure the runtime environment for cloud sessions
MCP connectors
: connect external services like Slack, Linear, and Google Drive
GitHub Actions
: run Claude in your CI pipeline on repository events
Was this page helpful?
Yes
No
Reference
Plan in the cloud
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/routines" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Development containers</title>
  <link>https://code.claude.com/docs/en/devcontainer</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/devcontainer</guid>
  <pubDate>Wed, 10 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Development containers
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plu...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Development containers
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
development container
, or dev container, lets you define an identical, isolated environment that every engineer on your team can run. With Claude Code installed in that container, commands Claude runs execute inside it rather than on the host machine, while edits to your project files appear in your local repository as you work.
This page covers
installing Claude Code in a dev container
and the configuration topics that follow. Each topic is self-contained, so jump to the ones that match what you need to set up:
Persist authentication and settings across rebuilds
Enforce organization policy
Restrict network egress
Run without permission prompts
While the dev container provides substantial protections, no system is completely immune to all attacks.
When executed with
--dangerously-skip-permissions
, dev containers do not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in
~/.claude
.
Only use dev containers when developing with trusted repositories, and monitor Claude’s activities.
Avoid mounting host secrets such as
~/.ssh
or cloud credential files into the container; prefer repository-scoped or short-lived tokens.
How dev containers work with your editor
A dev container runs as a Docker container, either on your machine or on a cloud host such as GitHub Codespaces. An editor that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, a JetBrains IDE, or Cursor, connects to that container: you browse and edit files in the editor as usual, but the integrated terminal, language servers, and build tools all run inside the container rather than on your host. Editors without dev container support, such as plain Vim, are not part of this workflow.
Claude Code runs inside the container, so it sees the same files, dependencies, and tools as the rest of your project’s toolchain. In VS Code you can use either the
Claude Code extension panel
or run
claude
in the integrated terminal; both run inside the container and share the same
~/.claude
configuration.
​
Add Claude Code to your dev container
Claude Code installs into any dev container through the
Claude Code Dev Container Feature
.
The settings work with any tool that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, or JetBrains IDEs. The steps below use VS Code as an example.
When you open the container in VS Code or Codespaces, the feature also adds the Claude Code VS Code extension; other editors ignore that part.
New to dev containers? The
VS Code Dev Containers tutorial
walks through installing Docker, the extension, and opening your first container. For a fuller hardened example with a firewall and persistent volumes, see
Try the reference container
.
1
Create or update devcontainer.json
Save the following as
.devcontainer/devcontainer.json
in your repository, or add the
features
block to your existing file.
The version tag at the end, such as
:1.0
, pins the feature’s install script, not the Claude Code release. The feature installs the latest Claude Code, and Claude Code auto-updates itself inside the container by default.
To pin the CLI version or disable auto-update, see
Enforce organization policy
.
.devcontainer/devcontainer.json
{
"image"
:
"mcr.microsoft.com/devcontainers/base:ubuntu"
,
"features"
: {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0"
: {}
}
}
Replace the
image
line with your project’s base image or remove it if your existing file uses a Dockerfile.
2
Rebuild the container
Open the VS Code Command Palette with
Cmd+Shift+P
on Mac or
Ctrl+Shift+P
on Windows and Linux, and run
Dev Containers: Rebuild Container
.
For other tools, follow that tool’s rebuild action: see
rebuilding in GitHub Codespaces
, the
Dev Containers CLI
, or your IDE’s dev container documentation.
3
Sign in to Claude Code
Open a terminal in the rebuilt container and run
claude
, then follow the authentication prompt.
What you see at the authentication prompt depends on your provider:
Anthropic
: sign in through a browser with your Claude or Anthropic Console account
Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
: Claude Code uses your cloud provider credentials, with no browser prompt
For cloud providers, pass credentials into the container as environment variables through
containerEnv
, a Codespaces secret, or your cloud’s workload identity rather than mounting credential files from the host. See
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
for the credential chain Claude Code reads.
See
Choose your API provider
to decide which path fits your organization.
If the browser sign-in completes but the callback never reaches the container, copy the code shown in the browser and paste it at the
Paste code here if prompted
prompt in the terminal. This can happen when the editor’s port forwarding doesn’t route the localhost callback.
​
Persist authentication and settings across rebuilds
By default, the container’s home directory is discarded on rebuild, so engineers must sign in again each time. Claude Code stores its authentication token, user settings, and session history under
~/.claude
. Mount a named volume at that path to keep this state across rebuilds.
The following example mounts a volume at the home directory of the
node
user:
devcontainer.json
"mounts"
: [
"source=claude-code-config,target=/home/node/.claude,type=volume"
]
Replace
/home/node
with the home directory of your container’s
remoteUser
. If you mount the volume somewhere other than
~/.claude
, set
CLAUDE_CONFIG_DIR
to the mount path so Claude Code reads and writes there.
To isolate state per project rather than sharing one volume across all repositories, include the
${devcontainerId}
variable in the source name. The
reference configuration
uses
source=claude-code-config-${devcontainerId}
for this purpose.
In GitHub Codespaces,
~/.claude
persists across stopping and starting a codespace, but is still cleared when you rebuild the container, so the volume mount above applies there too. To carry authentication across codespaces, store
ANTHROPIC_API_KEY
or a
CLAUDE_CODE_OAUTH_TOKEN
from
claude setup-token
as a
Codespaces secret
; Codespaces makes secrets available as environment variables inside the container automatically.
​
Enforce organization policy
A dev container is a convenient place to apply organization policy, because the same image and configuration run on every engineer’s machine.
Claude Code reads
/etc/claude-code/managed-settings.json
on Linux and applies it at the highest precedence in the
settings hierarchy
, so values there override anything an engineer sets in
~/.claude
or the project’s
.claude/
directory. Copy the file into place from your Dockerfile:
Dockerfile
RUN
mkdir -p /etc/claude-code
COPY
managed-settings.json /etc/claude-code/managed-settings.json
Because the Dockerfile lives in the repository, anyone with write access can change or remove this step. For policy that engineers cannot bypass by editing repository files, deliver managed settings through
server-managed settings
or your MDM instead. See
managed settings files
for the available keys and the other delivery paths.
To set
environment variables
that apply to every Claude Code session in the container, add them to
containerEnv
in your
devcontainer.json
. The following example opts out of telemetry and error reporting and prevents Claude Code from auto-updating after install:
devcontainer.json
"containerEnv"
: {
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"
:
"1"
,
"DISABLE_AUTOUPDATER"
:
"1"
}
The Dev Container Feature always installs the latest Claude Code release. To pin a specific Claude Code version for reproducible builds, install it from your Dockerfile with
npm install -g @anthropic-ai/claude-code@X.Y.Z
instead of using the feature, and set
DISABLE_AUTOUPDATER
as shown above.
For the full list of policy controls including permission rules, tool restrictions, and MCP server allowlists, see
Set up Claude Code for your organization
.
To make
MCP servers
available inside the container, define them at
project scope
in a
.mcp.json
file at the repository root so they are checked in alongside your dev container configuration. Install any binaries that local stdio servers depend on in your Dockerfile, and add remote server domains to your network allowlist.
​
Restrict network egress
You can limit the container’s outbound traffic to only the domains Claude Code needs. See
Network access requirements
for the inference and authentication domains, and
Telemetry services
for the optional telemetry and error reporting connections and how to disable them.
The reference container includes an
init-firewall.sh
script that blocks all outbound traffic except the domains Claude Code and your development tools need. Running a firewall inside a container requires extra permissions, so the reference adds the
NET_ADMIN
and
NET_RAW
capabilities through
runArgs
. The firewall script and these capabilities are not required for Claude Code itself: you can leave them out and rely on your own network controls instead.
​
Run without permission prompts
Because the container runs Claude Code as a non-root user and confines command execution to the container, you can pass
--dangerously-skip-permissions
for unattended operation. The CLI rejects this flag when launched as root, so confirm
remoteUser
is set to a non-root account.
Skipping permission prompts removes your opportunity to review tool calls before they run. Claude can still modify any file in the bind-mounted workspace, which appears directly on your host, and reach anything the container’s network policy allows. Pair this flag with the
network egress restrictions
above to limit what a bypassed session can reach.
If you want fewer prompts without disabling safety checks, consider
auto mode
instead, which has a classifier review actions before they run. To prevent engineers from using
--dangerously-skip-permissions
at all, set
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
​
Try the reference container
The
anthropics/claude-code
repository includes an example dev container that combines the CLI, the egress firewall, persistent volumes, and a Zsh-based shell. It is provided as a working example rather than a maintained base image; use it to see how the pieces fit together before applying them to your own configuration.
1
Install prerequisites
Install VS Code and the
Dev Containers extension
.
2
Clone the reference
Clone the
Claude Code repository
and open it in VS Code.
3
Reopen in container
When prompted, click
Reopen in Container
, or run
Dev Containers: Reopen in Container
from the Command Palette.
4
Start Claude Code
Once the container finishes building, open a terminal with
Ctrl+`
and run
claude
to sign in and start your first session.
To use this configuration with your own project, copy the
.devcontainer/
directory into your repository and adjust the Dockerfile for your toolchain, or return to
Add Claude Code to your dev container
to add only the feature to a setup you already have.
The reference configuration consists of three files. None of them are required when you add Claude Code to your own dev container through the feature, but they show one way to combine the pieces.
File
Purpose
devcontainer.json
Volume mounts,
runArgs
capabilities, VS Code extensions, and
containerEnv
Dockerfile
Base image, development tools, and the Claude Code install
init-firewall.sh
Blocks all outbound network traffic except the allowed domains
​
Next steps
Once Claude Code is running in your dev container, the pages below cover the rest of an organization rollout: choosing an authentication path, delivering managed policy outside the repository, monitoring usage, and understanding what Claude Code stores and sends.
Set up Claude Code for your organization
: choose an authentication provider, decide how policy reaches devices, and plan the rollout
Server-managed settings
: deliver managed policy from the Claude.ai admin console so engineers cannot bypass it by editing repository files
Monitor usage and audit activity
: export OpenTelemetry metrics and review what your team is running
Network access requirements
: the full domain allowlist for proxies and firewalls
Telemetry services and opt-out
: what Claude Code sends by default and the environment variables that disable it
Explore the
.claude
directory
: what the volume mount holds, including credentials, settings, and session history
Security model
: how Claude Code’s permission system, sandboxing, and prompt-injection protections fit together
Permission modes
: the full range from plan mode to auto mode to bypass, and when to use each
Was this page helpful?
Yes
No
LLM gateway
Monitoring
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/devcontainer" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Development containers
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plu...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Deployment
Development containers
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
development container
, or dev container, lets you define an identical, isolated environment that every engineer on your team can run. With Claude Code installed in that container, commands Claude runs execute inside it rather than on the host machine, while edits to your project files appear in your local repository as you work.
This page covers
installing Claude Code in a dev container
and the configuration topics that follow. Each topic is self-contained, so jump to the ones that match what you need to set up:
Persist authentication and settings across rebuilds
Enforce organization policy
Restrict network egress
Run without permission prompts
While the dev container provides substantial protections, no system is completely immune to all attacks.
When executed with
--dangerously-skip-permissions
, dev containers do not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in
~/.claude
.
Only use dev containers when developing with trusted repositories, and monitor Claude’s activities.
Avoid mounting host secrets such as
~/.ssh
or cloud credential files into the container; prefer repository-scoped or short-lived tokens.
How dev containers work with your editor
A dev container runs as a Docker container, either on your machine or on a cloud host such as GitHub Codespaces. An editor that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, a JetBrains IDE, or Cursor, connects to that container: you browse and edit files in the editor as usual, but the integrated terminal, language servers, and build tools all run inside the container rather than on your host. Editors without dev container support, such as plain Vim, are not part of this workflow.
Claude Code runs inside the container, so it sees the same files, dependencies, and tools as the rest of your project’s toolchain. In VS Code you can use either the
Claude Code extension panel
or run
claude
in the integrated terminal; both run inside the container and share the same
~/.claude
configuration.
​
Add Claude Code to your dev container
Claude Code installs into any dev container through the
Claude Code Dev Container Feature
.
The settings work with any tool that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, or JetBrains IDEs. The steps below use VS Code as an example.
When you open the container in VS Code or Codespaces, the feature also adds the Claude Code VS Code extension; other editors ignore that part.
New to dev containers? The
VS Code Dev Containers tutorial
walks through installing Docker, the extension, and opening your first container. For a fuller hardened example with a firewall and persistent volumes, see
Try the reference container
.
1
Create or update devcontainer.json
Save the following as
.devcontainer/devcontainer.json
in your repository, or add the
features
block to your existing file.
The version tag at the end, such as
:1.0
, pins the feature’s install script, not the Claude Code release. The feature installs the latest Claude Code, and Claude Code auto-updates itself inside the container by default.
To pin the CLI version or disable auto-update, see
Enforce organization policy
.
.devcontainer/devcontainer.json
{
"image"
:
"mcr.microsoft.com/devcontainers/base:ubuntu"
,
"features"
: {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0"
: {}
}
}
Replace the
image
line with your project’s base image or remove it if your existing file uses a Dockerfile.
2
Rebuild the container
Open the VS Code Command Palette with
Cmd+Shift+P
on Mac or
Ctrl+Shift+P
on Windows and Linux, and run
Dev Containers: Rebuild Container
.
For other tools, follow that tool’s rebuild action: see
rebuilding in GitHub Codespaces
, the
Dev Containers CLI
, or your IDE’s dev container documentation.
3
Sign in to Claude Code
Open a terminal in the rebuilt container and run
claude
, then follow the authentication prompt.
What you see at the authentication prompt depends on your provider:
Anthropic
: sign in through a browser with your Claude or Anthropic Console account
Amazon Bedrock, Google Vertex AI, or Microsoft Foundry
: Claude Code uses your cloud provider credentials, with no browser prompt
For cloud providers, pass credentials into the container as environment variables through
containerEnv
, a Codespaces secret, or your cloud’s workload identity rather than mounting credential files from the host. See
Amazon Bedrock
,
Google Vertex AI
, or
Microsoft Foundry
for the credential chain Claude Code reads.
See
Choose your API provider
to decide which path fits your organization.
If the browser sign-in completes but the callback never reaches the container, copy the code shown in the browser and paste it at the
Paste code here if prompted
prompt in the terminal. This can happen when the editor’s port forwarding doesn’t route the localhost callback.
​
Persist authentication and settings across rebuilds
By default, the container’s home directory is discarded on rebuild, so engineers must sign in again each time. Claude Code stores its authentication token, user settings, and session history under
~/.claude
. Mount a named volume at that path to keep this state across rebuilds.
The following example mounts a volume at the home directory of the
node
user:
devcontainer.json
"mounts"
: [
"source=claude-code-config,target=/home/node/.claude,type=volume"
]
Replace
/home/node
with the home directory of your container’s
remoteUser
. If you mount the volume somewhere other than
~/.claude
, set
CLAUDE_CONFIG_DIR
to the mount path so Claude Code reads and writes there.
To isolate state per project rather than sharing one volume across all repositories, include the
${devcontainerId}
variable in the source name. The
reference configuration
uses
source=claude-code-config-${devcontainerId}
for this purpose.
In GitHub Codespaces,
~/.claude
persists across stopping and starting a codespace, but is still cleared when you rebuild the container, so the volume mount above applies there too. To carry authentication across codespaces, store
ANTHROPIC_API_KEY
or a
CLAUDE_CODE_OAUTH_TOKEN
from
claude setup-token
as a
Codespaces secret
; Codespaces makes secrets available as environment variables inside the container automatically.
​
Enforce organization policy
A dev container is a convenient place to apply organization policy, because the same image and configuration run on every engineer’s machine.
Claude Code reads
/etc/claude-code/managed-settings.json
on Linux and applies it at the highest precedence in the
settings hierarchy
, so values there override anything an engineer sets in
~/.claude
or the project’s
.claude/
directory. Copy the file into place from your Dockerfile:
Dockerfile
RUN
mkdir -p /etc/claude-code
COPY
managed-settings.json /etc/claude-code/managed-settings.json
Because the Dockerfile lives in the repository, anyone with write access can change or remove this step. For policy that engineers cannot bypass by editing repository files, deliver managed settings through
server-managed settings
or your MDM instead. See
managed settings files
for the available keys and the other delivery paths.
To set
environment variables
that apply to every Claude Code session in the container, add them to
containerEnv
in your
devcontainer.json
. The following example opts out of telemetry and error reporting and prevents Claude Code from auto-updating after install:
devcontainer.json
"containerEnv"
: {
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"
:
"1"
,
"DISABLE_AUTOUPDATER"
:
"1"
}
The Dev Container Feature always installs the latest Claude Code release. To pin a specific Claude Code version for reproducible builds, install it from your Dockerfile with
npm install -g @anthropic-ai/claude-code@X.Y.Z
instead of using the feature, and set
DISABLE_AUTOUPDATER
as shown above.
For the full list of policy controls including permission rules, tool restrictions, and MCP server allowlists, see
Set up Claude Code for your organization
.
To make
MCP servers
available inside the container, define them at
project scope
in a
.mcp.json
file at the repository root so they are checked in alongside your dev container configuration. Install any binaries that local stdio servers depend on in your Dockerfile, and add remote server domains to your network allowlist.
​
Restrict network egress
You can limit the container’s outbound traffic to only the domains Claude Code needs. See
Network access requirements
for the inference and authentication domains, and
Telemetry services
for the optional telemetry and error reporting connections and how to disable them.
The reference container includes an
init-firewall.sh
script that blocks all outbound traffic except the domains Claude Code and your development tools need. Running a firewall inside a container requires extra permissions, so the reference adds the
NET_ADMIN
and
NET_RAW
capabilities through
runArgs
. The firewall script and these capabilities are not required for Claude Code itself: you can leave them out and rely on your own network controls instead.
​
Run without permission prompts
Because the container runs Claude Code as a non-root user and confines command execution to the container, you can pass
--dangerously-skip-permissions
for unattended operation. The CLI rejects this flag when launched as root, so confirm
remoteUser
is set to a non-root account.
Skipping permission prompts removes your opportunity to review tool calls before they run. Claude can still modify any file in the bind-mounted workspace, which appears directly on your host, and reach anything the container’s network policy allows. Pair this flag with the
network egress restrictions
above to limit what a bypassed session can reach.
If you want fewer prompts without disabling safety checks, consider
auto mode
instead, which has a classifier review actions before they run. To prevent engineers from using
--dangerously-skip-permissions
at all, set
permissions.disableBypassPermissionsMode
to
"disable"
in
managed settings
.
​
Try the reference container
The
anthropics/claude-code
repository includes an example dev container that combines the CLI, the egress firewall, persistent volumes, and a Zsh-based shell. It is provided as a working example rather than a maintained base image; use it to see how the pieces fit together before applying them to your own configuration.
1
Install prerequisites
Install VS Code and the
Dev Containers extension
.
2
Clone the reference
Clone the
Claude Code repository
and open it in VS Code.
3
Reopen in container
When prompted, click
Reopen in Container
, or run
Dev Containers: Reopen in Container
from the Command Palette.
4
Start Claude Code
Once the container finishes building, open a terminal with
Ctrl+`
and run
claude
to sign in and start your first session.
To use this configuration with your own project, copy the
.devcontainer/
directory into your repository and adjust the Dockerfile for your toolchain, or return to
Add Claude Code to your dev container
to add only the feature to a setup you already have.
The reference configuration consists of three files. None of them are required when you add Claude Code to your own dev container through the feature, but they show one way to combine the pieces.
File
Purpose
devcontainer.json
Volume mounts,
runArgs
capabilities, VS Code extensions, and
containerEnv
Dockerfile
Base image, development tools, and the Claude Code install
init-firewall.sh
Blocks all outbound network traffic except the allowed domains
​
Next steps
Once Claude Code is running in your dev container, the pages below cover the rest of an organization rollout: choosing an authentication path, delivering managed policy outside the repository, monitoring usage, and understanding what Claude Code stores and sends.
Set up Claude Code for your organization
: choose an authentication provider, decide how policy reaches devices, and plan the rollout
Server-managed settings
: deliver managed policy from the Claude.ai admin console so engineers cannot bypass it by editing repository files
Monitor usage and audit activity
: export OpenTelemetry metrics and review what your team is running
Network access requirements
: the full domain allowlist for proxies and firewalls
Telemetry services and opt-out
: what Claude Code sends by default and the environment variables that disable it
Explore the
.claude
directory
: what the volume mount holds, including credentials, settings, and session history
Security model
: how Claude Code’s permission system, sandboxing, and prompt-injection protections fit together
Permission modes
: the full range from plan mode to auto mode to bypass, and when to use each
Was this page helpful?
Yes
No
LLM gateway
Monitoring
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/devcontainer" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Scale to many tools with tool search</title>
  <link>https://code.claude.com/docs/en/agent-sdk/tool-search</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/tool-search</guid>
  <pubDate>Tue, 09 Jan 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Scale to many tools with tool search
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagent...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Scale to many tools with tool search
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Tool search enables your agent to work with hundreds or thousands of tools by dynamically discovering and loading them on demand. Instead of loading all tool definitions into the context window upfront, the agent searches your tool catalog and loads only the tools it needs.
This approach solves two challenges as tool libraries scale:
Context efficiency:
Tool definitions can consume large portions of the context window (50 tools can use 10-20K tokens), leaving less room for actual work.
Tool selection accuracy:
Tool selection accuracy degrades with more than 30-50 tools loaded at once.
Tool search is enabled by default. This page covers
how it works
, how to
configure it
, and how to
optimize tool discovery
.
​
How tool search works
When tool search is active, tool definitions are withheld from the context window. The agent receives a summary of available tools and searches for relevant ones when the task requires a capability not already loaded. The 3-5 most relevant tools are loaded into context, where they stay available for subsequent turns. If the conversation is long enough that the SDK compacts earlier messages to free space, previously discovered tools may be removed, and the agent searches again as needed.
Tool search adds one extra round-trip the first time Claude discovers a tool (the search step), but for large tool sets this is offset by smaller context on every turn. With fewer than ~10 tools, loading everything upfront is typically faster.
For details on the underlying API mechanism, see
Tool search in the API
.
Tool search requires Claude Sonnet 4 or later, or Claude Opus 4 or later. Haiku models do not support tool search.
​
Configure tool search
Tool search is on by default. It is disabled by default on Vertex AI, where it is supported for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later. It is also disabled when
ANTHROPIC_BASE_URL
points to a non-first-party host, since most proxies do not forward
tool_reference
blocks. You can override either default with the
ENABLE_TOOL_SEARCH
environment variable:
Value
Behavior
(unset)
Tool search is on. Tool definitions are deferred and discovered on demand. Falls back to loading upfront on Vertex AI or a non-first-party
ANTHROPIC_BASE_URL
.
true
Tool search is always on. The SDK sends the beta header even on Vertex AI and through proxies. Requests fail on Vertex AI models earlier than Sonnet 4.5 or Opus 4.5, or on proxies that do not support
tool_reference
blocks.
auto
Checks the combined token count of all tool definitions against the model’s context window. If they exceed 10%, tool search activates. If they’re under 10%, all tools are loaded into context normally.
auto:N
Same as
auto
with a custom percentage.
auto:5
activates when tool definitions exceed 5% of the context window. Lower values activate sooner.
false
Tool search is off. All tool definitions are loaded into context on every turn.
Tool search applies to all registered tools, whether they come from remote MCP servers or
custom SDK MCP servers
. When using
auto
, the threshold is based on the combined size of all tool definitions across all servers.
Set the value in the
env
option on
query()
. This example connects to a remote MCP server that exposes many tools, pre-approves all of them with a wildcard, and uses
auto:5
so tool search activates when their definitions exceed 5% of the context window:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Find and run the appropriate database query"
,
options:
{
mcpServers:
{
"enterprise-tools"
:
{
// Connect to a remote MCP server
type:
"http"
,
url:
"https://tools.example.com/mcp"
}
},
allowedTools:
[
"mcp__enterprise-tools__*"
],
// Wildcard pre-approves all tools from this server
env:
{
ENABLE_TOOL_SEARCH:
"auto:5"
// Activate tool search when tools exceed 5% of context
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
Setting
ENABLE_TOOL_SEARCH
to
"false"
disables tool search and loads all tool definitions into context on every turn. This removes the search round-trip, which can be faster when the tool set is small (fewer than ~10 tools) and the definitions fit comfortably in the context window.
​
Optimize tool discovery
The search mechanism matches queries against tool names and descriptions. Names like
search_slack_messages
surface for a wider range of requests than
query_slack
. Descriptions with specific keywords (“Search Slack messages by keyword, channel, or date range”) match more queries than generic ones (“Query Slack”).
You can also add a system prompt section listing available tool categories. This gives the agent context about what kinds of tools are available to search for:
You can search for tools to interact with Slack, GitHub, and Jira.
​
Limits
Maximum tools:
10,000 tools in your catalog
Search results:
Returns 3-5 most relevant tools per search
Model support:
Claude Sonnet 4 and later, Claude Opus 4 and later (no Haiku)
​
Related documentation
Tool search in the API
: Full API documentation for tool search, including custom implementations
Connect MCP servers
: Connect to external tools via MCP servers
Custom tools
: Build your own tools with SDK MCP servers
TypeScript SDK reference
: Full API reference
Python SDK reference
: Full API reference
Was this page helpful?
Yes
No
Connect to external tools with MCP
Subagents in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/tool-search" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Scale to many tools with tool search
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagent...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Extend with tools
Scale to many tools with tool search
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Tool search enables your agent to work with hundreds or thousands of tools by dynamically discovering and loading them on demand. Instead of loading all tool definitions into the context window upfront, the agent searches your tool catalog and loads only the tools it needs.
This approach solves two challenges as tool libraries scale:
Context efficiency:
Tool definitions can consume large portions of the context window (50 tools can use 10-20K tokens), leaving less room for actual work.
Tool selection accuracy:
Tool selection accuracy degrades with more than 30-50 tools loaded at once.
Tool search is enabled by default. This page covers
how it works
, how to
configure it
, and how to
optimize tool discovery
.
​
How tool search works
When tool search is active, tool definitions are withheld from the context window. The agent receives a summary of available tools and searches for relevant ones when the task requires a capability not already loaded. The 3-5 most relevant tools are loaded into context, where they stay available for subsequent turns. If the conversation is long enough that the SDK compacts earlier messages to free space, previously discovered tools may be removed, and the agent searches again as needed.
Tool search adds one extra round-trip the first time Claude discovers a tool (the search step), but for large tool sets this is offset by smaller context on every turn. With fewer than ~10 tools, loading everything upfront is typically faster.
For details on the underlying API mechanism, see
Tool search in the API
.
Tool search requires Claude Sonnet 4 or later, or Claude Opus 4 or later. Haiku models do not support tool search.
​
Configure tool search
Tool search is on by default. It is disabled by default on Vertex AI, where it is supported for Claude Sonnet 4.5 and later and Claude Opus 4.5 and later. It is also disabled when
ANTHROPIC_BASE_URL
points to a non-first-party host, since most proxies do not forward
tool_reference
blocks. You can override either default with the
ENABLE_TOOL_SEARCH
environment variable:
Value
Behavior
(unset)
Tool search is on. Tool definitions are deferred and discovered on demand. Falls back to loading upfront on Vertex AI or a non-first-party
ANTHROPIC_BASE_URL
.
true
Tool search is always on. The SDK sends the beta header even on Vertex AI and through proxies. Requests fail on Vertex AI models earlier than Sonnet 4.5 or Opus 4.5, or on proxies that do not support
tool_reference
blocks.
auto
Checks the combined token count of all tool definitions against the model’s context window. If they exceed 10%, tool search activates. If they’re under 10%, all tools are loaded into context normally.
auto:N
Same as
auto
with a custom percentage.
auto:5
activates when tool definitions exceed 5% of the context window. Lower values activate sooner.
false
Tool search is off. All tool definitions are loaded into context on every turn.
Tool search applies to all registered tools, whether they come from remote MCP servers or
custom SDK MCP servers
. When using
auto
, the threshold is based on the combined size of all tool definitions across all servers.
Set the value in the
env
option on
query()
. This example connects to a remote MCP server that exposes many tools, pre-approves all of them with a wildcard, and uses
auto:5
so tool search activates when their definitions exceed 5% of the context window:
TypeScript
Python
import
{
query
}
from
"@anthropic-ai/claude-agent-sdk"
;
for
await
(
const
message
of
query
({
prompt:
"Find and run the appropriate database query"
,
options:
{
mcpServers:
{
"enterprise-tools"
:
{
// Connect to a remote MCP server
type:
"http"
,
url:
"https://tools.example.com/mcp"
}
},
allowedTools:
[
"mcp__enterprise-tools__*"
],
// Wildcard pre-approves all tools from this server
env:
{
ENABLE_TOOL_SEARCH:
"auto:5"
// Activate tool search when tools exceed 5% of context
}
}
})) {
if
(
message
.
type
===
"result"
&&
message
.
subtype
===
"success"
) {
console
.
log
(
message
.
result
);
}
}
Setting
ENABLE_TOOL_SEARCH
to
"false"
disables tool search and loads all tool definitions into context on every turn. This removes the search round-trip, which can be faster when the tool set is small (fewer than ~10 tools) and the definitions fit comfortably in the context window.
​
Optimize tool discovery
The search mechanism matches queries against tool names and descriptions. Names like
search_slack_messages
surface for a wider range of requests than
query_slack
. Descriptions with specific keywords (“Search Slack messages by keyword, channel, or date range”) match more queries than generic ones (“Query Slack”).
You can also add a system prompt section listing available tool categories. This gives the agent context about what kinds of tools are available to search for:
You can search for tools to interact with Slack, GitHub, and Jira.
​
Limits
Maximum tools:
10,000 tools in your catalog
Search results:
Returns 3-5 most relevant tools per search
Model support:
Claude Sonnet 4 and later, Claude Opus 4 and later (no Haiku)
​
Related documentation
Tool search in the API
: Full API documentation for tool search, including custom implementations
Connect MCP servers
: Connect to external tools via MCP servers
Custom tools
: Build your own tools with SDK MCP servers
TypeScript SDK reference
: Full API reference
Python SDK reference
: Full API reference
Was this page helpful?
Yes
No
Connect to external tools with MCP
Subagents in the SDK
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/tool-search" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Create and distribute a plugin marketplace</title>
  <link>https://code.claude.com/docs/en/plugin-marketplaces</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/plugin-marketplaces</guid>
  <pubDate>Thu, 04 Jan 2024 00:00:00 +0000</pubDate>
  <category>Plugins</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Create and distribute a plugin marketplace
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distri...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Create and distribute a plugin marketplace
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
plugin marketplace
is a catalog that lets you distribute plugins to others. Marketplaces provide centralized discovery, version tracking, automatic updates, and support for multiple source types (git repositories, local paths, and more). This guide shows you how to create your own marketplace to share plugins with your team or community.
Looking to install plugins from an existing marketplace? See
Discover and install prebuilt plugins
.
​
Overview
Creating and distributing a marketplace involves:
Creating plugins
: build one or more plugins with skills, agents, hooks, MCP servers, or LSP servers. This guide assumes you already have plugins to distribute; see
Create plugins
for details on how to create them.
Creating a marketplace file
: define a
marketplace.json
that lists your plugins and where to find them (see
Create the marketplace file
).
Host the marketplace
: push to GitHub, GitLab, or another git host (see
Host and distribute marketplaces
).
Share with users
: users add your marketplace with
/plugin marketplace add
and install individual plugins (see
Discover and install plugins
).
Once your marketplace is live, you can update it by pushing changes to your repository. Users refresh their local copy with
/plugin marketplace update
.
​
Walkthrough: create a local marketplace
This example creates a marketplace with one plugin: a
quality-review
skill for code reviews. You’ll create the directory structure, add a skill, create the plugin manifest and marketplace catalog, then install and test it.
1
Create the directory structure
mkdir
-p
my-marketplace/.claude-plugin
mkdir
-p
my-marketplace/plugins/quality-review-plugin/.claude-plugin
mkdir
-p
my-marketplace/plugins/quality-review-plugin/skills/quality-review
2
Create the skill
Create a
SKILL.md
file that defines what the
quality-review
skill does.
my-marketplace/plugins/quality-review-plugin/skills/quality-review/SKILL.md
---
description
:
Review code for bugs, security, and performance
disable-model-invocation
:
true
---
Review the code I've selected or the recent changes for:
-
Potential bugs or edge cases
-
Security concerns
-
Performance issues
-
Readability improvements
Be concise and actionable.
3
Create the plugin manifest
Create a
plugin.json
file that describes the plugin. The manifest goes in the
.claude-plugin/
directory.
my-marketplace/plugins/quality-review-plugin/.claude-plugin/plugin.json
{
"name"
:
"quality-review-plugin"
,
"description"
:
"Adds a quality-review skill for quick code reviews"
,
"version"
:
"1.0.0"
}
Setting
version
means users only receive updates when you change this field, so bump it on every release. If you omit
version
and host this marketplace in git, every commit automatically counts as a new version. See
Version resolution
to choose the right approach.
4
Create the marketplace file
Create the marketplace catalog that lists your plugin.
my-marketplace/.claude-plugin/marketplace.json
{
"name"
:
"my-plugins"
,
"owner"
: {
"name"
:
"Your Name"
},
"plugins"
: [
{
"name"
:
"quality-review-plugin"
,
"source"
:
"./plugins/quality-review-plugin"
,
"description"
:
"Adds a quality-review skill for quick code reviews"
}
]
}
5
Add and install
Add the marketplace and install the plugin.
/plugin
marketplace
add
./my-marketplace
/plugin
install
quality-review-plugin@my-plugins
6
Try it out
Select some code in your editor and run your new skill. Plugin skills are namespaced with the plugin name.
/quality-review-plugin:quality-review
To learn more about what plugins can do, including hooks, agents, MCP servers, and LSP servers, see
Plugins
.
How plugins are installed
: When users install a plugin, Claude Code copies the plugin directory to a cache location. This means plugins can’t reference files outside their directory using paths like
../shared-utils
, because those files won’t be copied.
If you need to share files across plugins, use symlinks. See
Plugin caching and file resolution
for details.
​
Create the marketplace file
Create
.claude-plugin/marketplace.json
in your repository root. This file defines your marketplace’s name, owner information, and a list of plugins with their sources.
Each plugin entry needs at minimum a
name
and
source
(where to fetch it from). See the
full schema
below for all available fields.
{
"name"
:
"company-tools"
,
"owner"
: {
"name"
:
"DevTools Team"
,
"email"
:
"devtools@example.com"
},
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
:
"./plugins/formatter"
,
"description"
:
"Automatic code formatting on save"
,
"version"
:
"2.1.0"
,
"author"
: {
"name"
:
"DevTools Team"
}
},
{
"name"
:
"deployment-tools"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"company/deploy-plugin"
},
"description"
:
"Deployment automation tools"
}
]
}
​
Marketplace schema
​
Required fields
Field
Type
Description
Example
name
string
Marketplace identifier (kebab-case, no spaces). This is public-facing: users see it when installing plugins (for example,
/plugin install my-tool@your-marketplace
).
"acme-tools"
owner
object
Marketplace maintainer information (
see fields below
)
plugins
array
List of available plugins
See below
Reserved names
: The following marketplace names are reserved for official Anthropic use and cannot be used by third-party marketplaces:
claude-code-marketplace
,
claude-code-plugins
,
claude-plugins-official
,
anthropic-marketplace
,
anthropic-plugins
,
agent-skills
,
knowledge-work-plugins
,
life-sciences
. Names that impersonate official marketplaces (like
official-claude-plugins
or
anthropic-tools-v2
) are also blocked.
​
Owner fields
Field
Type
Required
Description
name
string
Yes
Name of the maintainer or team
email
string
No
Contact email for the maintainer
​
Optional fields
Field
Type
Description
$schema
string
JSON Schema URL for editor autocomplete and validation. Claude Code ignores this field at load time.
description
string
Brief marketplace description
version
string
Marketplace manifest version
metadata.pluginRoot
string
Base directory prepended to relative plugin source paths (for example,
"./plugins"
lets you write
"source": "formatter"
instead of
"source": "./plugins/formatter"
)
allowCrossMarketplaceDependenciesOn
array
Other marketplaces that plugins in this marketplace may depend on. Dependencies from a marketplace not listed here are blocked at install. See
Depend on a plugin from another marketplace
.
description
and
version
are also accepted under
metadata
for backward compatibility.
​
Plugin entries
Each plugin entry in the
plugins
array describes a plugin and where to find it. You can include any field from the
plugin manifest schema
(like
description
,
version
,
author
,
commands
,
hooks
, etc.), plus these marketplace-specific fields:
source
,
category
,
tags
, and
strict
.
​
Required fields
Field
Type
Description
name
string
Plugin identifier (kebab-case, no spaces). This is public-facing: users see it when installing (for example,
/plugin install my-plugin@marketplace
).
source
string|object
Where to fetch the plugin from (see
Plugin sources
below)
​
Optional plugin fields
Standard metadata fields:
Field
Type
Description
description
string
Brief plugin description
version
string
Plugin version. If set (here or in
plugin.json
), the plugin is pinned to this string and users only receive updates when it changes. Omit to fall back to the git commit SHA. See
Version resolution
.
author
object
Plugin author information (
name
required,
email
optional)
homepage
string
Plugin homepage or documentation URL
repository
string
Source code repository URL
license
string
SPDX license identifier (for example, MIT, Apache-2.0)
keywords
array
Tags for plugin discovery and categorization
category
string
Plugin category for organization
tags
array
Tags for searchability
strict
boolean
Controls whether
plugin.json
is the authority for component definitions (default: true). See
Strict mode
below.
Component configuration fields:
Field
Type
Description
skills
string|array
Custom paths to skill directories containing
<name>/SKILL.md
commands
string|array
Custom paths to flat
.md
skill files or directories
agents
string|array
Custom paths to agent files
hooks
string|object
Custom hooks configuration or path to hooks file
mcpServers
string|object
MCP server configurations or path to MCP config
lspServers
string|object
LSP server configurations or path to LSP config
​
Plugin sources
Plugin sources tell Claude Code where to fetch each individual plugin listed in your marketplace. These are set in the
source
field of each plugin entry in
marketplace.json
.
Once a plugin is cloned or copied into the local machine, it is copied into the local versioned plugin cache at
~/.claude/plugins/cache
.
Source
Type
Fields
Notes
Relative path
string
(e.g.
"./my-plugin"
)
none
Local directory within the marketplace repo. Must start with
./
. Resolved relative to the marketplace root, not the
.claude-plugin/
directory
github
object
repo
,
ref?
,
sha?
url
object
url
,
ref?
,
sha?
Git URL source
git-subdir
object
url
,
path
,
ref?
,
sha?
Subdirectory within a git repo. Clones sparsely to minimize bandwidth for monorepos
npm
object
package
,
version?
,
registry?
Installed via
npm install
Marketplace sources vs plugin sources
: These are different concepts that control different things.
Marketplace source
— where to fetch the
marketplace.json
catalog itself. Set when users run
/plugin marketplace add
or in
extraKnownMarketplaces
settings. Supports
ref
(branch/tag) but not
sha
.
Plugin source
— where to fetch an individual plugin listed in the marketplace. Set in the
source
field of each plugin entry inside
marketplace.json
. Supports both
ref
(branch/tag) and
sha
(exact commit).
For example, a marketplace hosted at
acme-corp/plugin-catalog
(marketplace source) can list a plugin fetched from
acme-corp/code-formatter
(plugin source). The marketplace source and plugin source point to different repositories and are pinned independently.
​
Relative paths
For plugins in the same repository, use a path starting with
./
:
{
"name"
:
"my-plugin"
,
"source"
:
"./plugins/my-plugin"
}
Paths resolve relative to the marketplace root, which is the directory containing
.claude-plugin/
. In the example above,
./plugins/my-plugin
points to
<repo>/plugins/my-plugin
, even though
marketplace.json
lives at
<repo>/.claude-plugin/marketplace.json
. Do not use
../
to reference paths outside the marketplace root.
Relative paths only work when users add your marketplace via Git (GitHub, GitLab, or git URL). If users add your marketplace via a direct URL to the
marketplace.json
file, relative paths will not resolve correctly. For URL-based distribution, use GitHub, npm, or git URL sources instead. See
Troubleshooting
for details.
​
GitHub repositories
{
"name"
:
"github-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/plugin-repo"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"github-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/plugin-repo"
,
"ref"
:
"v2.0.0"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
Field
Type
Description
repo
string
Required. GitHub repository in
owner/repo
format
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
Git repositories
{
"name"
:
"git-plugin"
,
"source"
: {
"source"
:
"url"
,
"url"
:
"https://gitlab.com/team/plugin.git"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"git-plugin"
,
"source"
: {
"source"
:
"url"
,
"url"
:
"https://gitlab.com/team/plugin.git"
,
"ref"
:
"main"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
Field
Type
Description
url
string
Required. Full git repository URL (
https://
or
git@
). The
.git
suffix is optional, so Azure DevOps and AWS CodeCommit URLs without the suffix work
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
Git subdirectories
Use
git-subdir
to point to a plugin that lives inside a subdirectory of a git repository. Claude Code uses a sparse, partial clone to fetch only the subdirectory, minimizing bandwidth for large monorepos.
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"git-subdir"
,
"url"
:
"https://github.com/acme-corp/monorepo.git"
,
"path"
:
"tools/claude-plugin"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"git-subdir"
,
"url"
:
"https://github.com/acme-corp/monorepo.git"
,
"path"
:
"tools/claude-plugin"
,
"ref"
:
"v2.0.0"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
The
url
field also accepts a GitHub shorthand (
owner/repo
) or SSH URLs (
git@github.com:owner/repo.git
).
Field
Type
Description
url
string
Required. Git repository URL, GitHub
owner/repo
shorthand, or SSH URL
path
string
Required. Subdirectory path within the repo containing the plugin (for example,
"tools/claude-plugin"
)
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
npm packages
Plugins distributed as npm packages are installed using
npm install
. This works with any package on the public npm registry or a private registry your team hosts.
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
}
}
To pin to a specific version, add the
version
field:
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
,
"version"
:
"2.1.0"
}
}
To install from a private or internal registry, add the
registry
field:
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
,
"version"
:
"^2.0.0"
,
"registry"
:
"https://npm.example.com"
}
}
Field
Type
Description
package
string
Required. Package name or scoped package (for example,
@org/plugin
)
version
string
Optional. Version or version range (for example,
2.1.0
,
^2.0.0
,
~1.5.0
)
registry
string
Optional. Custom npm registry URL. Defaults to the system npm registry (typically npmjs.org)
​
Advanced plugin entries
This example shows a plugin entry using many of the optional fields, including custom paths for commands, agents, hooks, and MCP servers:
{
"name"
:
"enterprise-tools"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"company/enterprise-plugin"
},
"description"
:
"Enterprise workflow automation tools"
,
"version"
:
"2.1.0"
,
"author"
: {
"name"
:
"Enterprise Team"
,
"email"
:
"enterprise@example.com"
},
"homepage"
:
"https://docs.example.com/plugins/enterprise-tools"
,
"repository"
:
"https://github.com/company/enterprise-plugin"
,
"license"
:
"MIT"
,
"keywords"
: [
"enterprise"
,
"workflow"
,
"automation"
],
"category"
:
"productivity"
,
"commands"
: [
"./commands/core/"
,
"./commands/enterprise/"
,
"./commands/experimental/preview.md"
],
"agents"
: [
"./agents/security-reviewer.md"
,
"./agents/compliance-checker.md"
],
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
]
}
]
},
"mcpServers"
: {
"enterprise-db"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
]
}
},
"strict"
:
false
}
Key things to notice:
commands
and
agents
: You can specify multiple directories or individual files. Paths are relative to the plugin root.
${CLAUDE_PLUGIN_ROOT}
: use this variable in hooks and MCP server configs to reference files within the plugin’s installation directory. This is necessary because plugins are copied to a cache location when installed. For dependencies or state that should survive plugin updates, use
${CLAUDE_PLUGIN_DATA}
instead.
strict: false
: Since this is set to false, the plugin doesn’t need its own
plugin.json
. The marketplace entry defines everything. See
Strict mode
below.
​
Strict mode
The
strict
field controls whether
plugin.json
is the authority for component definitions (skills, agents, hooks, MCP servers, output styles).
Value
Behavior
true
(default)
plugin.json
is the authority. The marketplace entry can supplement it with additional components, and both sources are merged.
false
The marketplace entry is the entire definition. If the plugin also has a
plugin.json
that declares components, that’s a conflict and the plugin fails to load.
When to use each mode:
strict: true
: the plugin has its own
plugin.json
and manages its own components. The marketplace entry can add extra skills or hooks on top. This is the default and works for most plugins.
strict: false
: the marketplace operator wants full control. The plugin repo provides raw files, and the marketplace entry defines which of those files are exposed as skills, agents, hooks, etc. Useful when the marketplace restructures or curates a plugin’s components differently than the plugin author intended.
​
Host and distribute marketplaces
​
Host on GitHub (recommended)
GitHub provides the easiest distribution method:
Create a repository
: Set up a new repository for your marketplace
Add marketplace file
: Create
.claude-plugin/marketplace.json
with your plugin definitions
Share with teams
: Users add your marketplace with
/plugin marketplace add owner/repo
Benefits
: Built-in version control, issue tracking, and team collaboration features.
​
Host on other git services
Any git hosting service works, such as GitLab, Bitbucket, and self-hosted servers. Users add with the full repository URL:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git
​
Private repositories
Claude Code supports installing plugins from private repositories. For manual installation and updates, Claude Code uses your existing git credential helpers, so HTTPS access via
gh auth login
, macOS Keychain, or
git-credential-store
works the same as in your terminal. SSH access works as long as the host is already in your
known_hosts
file and the key is loaded in
ssh-agent
, since Claude Code suppresses interactive SSH prompts for the host fingerprint and key passphrase.
Background auto-updates run at startup without credential helpers, since interactive prompts would block Claude Code from starting. To enable auto-updates for private marketplaces, set the appropriate authentication token in your environment:
Provider
Environment variables
Notes
GitHub
GITHUB_TOKEN
or
GH_TOKEN
Personal access token or GitHub App token
GitLab
GITLAB_TOKEN
or
GL_TOKEN
Personal access token or project token
Bitbucket
BITBUCKET_TOKEN
App password or repository access token
Set the token in your shell configuration (for example,
.bashrc
,
.zshrc
) or pass it when running Claude Code:
export
GITHUB_TOKEN
=
ghp_xxxxxxxxxxxxxxxxxxxx
For CI/CD environments, configure the token as a secret environment variable. GitHub Actions automatically provides
GITHUB_TOKEN
for repositories in the same organization.
​
Test locally before distribution
Test your marketplace locally before sharing:
/plugin
marketplace
add
./my-local-marketplace
/plugin
install
test-plugin@my-local-marketplace
For the full range of add commands (GitHub, Git URLs, local paths, remote URLs), see
Add marketplaces
.
​
Require marketplaces for your team
You can configure your repository so team members are automatically prompted to install your marketplace when they trust the project folder. Add your marketplace to
.claude/settings.json
:
{
"extraKnownMarketplaces"
: {
"company-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"your-org/claude-plugins"
}
}
}
}
You can also specify which plugins should be enabled by default:
{
"enabledPlugins"
: {
"code-formatter@company-tools"
:
true
,
"deployment-tools@company-tools"
:
true
}
}
For full configuration options, see
Plugin settings
.
If you use a local
directory
or
file
source with a relative path, the path resolves against your repository’s main checkout. When you run Claude Code from a git worktree, the path still points at the main checkout, so all worktrees share the same marketplace location. Marketplace state is stored once per user in
~/.claude/plugins/known_marketplaces.json
, not per project.
​
Pre-populate plugins for containers
For container images and CI environments, you can pre-populate a plugins directory at build time so Claude Code starts with marketplaces and plugins already available, without cloning anything at runtime. Set the
CLAUDE_CODE_PLUGIN_SEED_DIR
environment variable to point at this directory.
To layer multiple seed directories, separate paths with
:
on Unix or
;
on Windows. Claude Code searches each directory in order, and the first seed that contains a given marketplace or plugin cache wins.
The seed directory mirrors the structure of
~/.claude/plugins
:
$CLAUDE_CODE_PLUGIN_SEED_DIR/
known_marketplaces.json
marketplaces/<name>/...
cache/<marketplace>/<plugin>/<version>/...
To build a seed directory, run Claude Code once during image build, install the plugins you need, then copy the resulting
~/.claude/plugins
directory into your image and point
CLAUDE_CODE_PLUGIN_SEED_DIR
at it.
To skip the copy step, set
CLAUDE_CODE_PLUGIN_CACHE_DIR
to your target seed path during the build so plugins install directly there:
CLAUDE_CODE_PLUGIN_CACHE_DIR
=
/opt/claude-seed
claude
plugin
marketplace
add
your-org/plugins
CLAUDE_CODE_PLUGIN_CACHE_DIR
=
/opt/claude-seed
claude
plugin
install
my-tool@your-plugins
Then set
CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed
in your container’s runtime environment so Claude Code reads from the seed on startup.
At startup, Claude Code registers marketplaces found in the seed’s
known_marketplaces.json
into the primary configuration, and uses plugin caches found under
cache/
in place without re-cloning. This works in both interactive mode and non-interactive mode with the
-p
flag.
Behavior details:
Read-only
: the seed directory is never written to. Auto-updates are disabled for seed marketplaces since git pull would fail on a read-only filesystem.
Seed entries take precedence
: marketplaces declared in the seed overwrite any matching entries in the user’s configuration on each startup. To opt out of a seed plugin, use
/plugin disable
rather than removing the marketplace.
Path resolution
: Claude Code locates marketplace content by probing
$CLAUDE_CODE_PLUGIN_SEED_DIR/marketplaces/<name>/
at runtime, not by trusting paths stored inside the seed’s JSON. This means the seed works correctly even when mounted at a different path than where it was built.
Mutation is blocked
: running
/plugin marketplace remove
or
/plugin marketplace update
against a seed-managed marketplace fails with guidance to ask your administrator to update the seed image.
Composes with settings
: if
extraKnownMarketplaces
or
enabledPlugins
declare a marketplace that already exists in the seed, Claude Code uses the seed copy instead of cloning.
​
Managed marketplace restrictions
For organizations requiring strict control over plugin sources, administrators can restrict which plugin marketplaces users are allowed to add using the
strictKnownMarketplaces
setting in managed settings.
When
strictKnownMarketplaces
is configured in managed settings, the restriction behavior depends on the value:
Value
Behavior
Undefined (default)
No restrictions. Users can add any marketplace
Empty array
[]
Complete lockdown. Users cannot add any new marketplaces
List of sources
Users can only add marketplaces that match the allowlist exactly
​
Common configurations
Disable all marketplace additions:
{
"strictKnownMarketplaces"
: []
}
Allow specific marketplaces only:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
},
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
},
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
}
]
}
Allow all marketplaces from an internal git server using regex pattern matching on the host. This is the recommended approach for
GitHub Enterprise Server
or self-hosted GitLab instances:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
Allow filesystem-based marketplaces from a specific directory using regex pattern matching on the path:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"pathPattern"
,
"pathPattern"
:
"^/opt/approved/"
}
]
}
Use
".*"
as the
pathPattern
to allow any filesystem path while still controlling network sources with
hostPattern
.
strictKnownMarketplaces
restricts what users can add, but does not register marketplaces on its own. To make allowed marketplaces available automatically without users running
/plugin marketplace add
, pair it with
extraKnownMarketplaces
in the same
managed-settings.json
. See
Using both together
.
​
How restrictions work
Restrictions are checked before any network or filesystem operation. The check runs on marketplace add and on plugin install, update, refresh, and auto-update. If a marketplace was added before the policy was configured and its source no longer matches the allowlist, Claude Code refuses to install or update plugins from it. The same enforcement applies to
blockedMarketplaces
.
The allowlist uses exact matching for most source types. For a marketplace to be allowed, all specified fields must match exactly:
For GitHub sources:
repo
is required, and
ref
or
path
must also match if specified in the allowlist
For URL sources: the full URL must match exactly
For
hostPattern
sources: the marketplace host is matched against the regex pattern
For
pathPattern
sources: the marketplace’s filesystem path is matched against the regex pattern
Exact matching does not normalize URLs: a trailing slash,
.git
suffix, or
ssh://
versus
https://
form are treated as different values. If your organization’s marketplace can be cloned by more than one URL form, prefer a
hostPattern
entry over a literal URL so all forms match.
Because
strictKnownMarketplaces
is set in
managed settings
, individual users and project configurations cannot override these restrictions.
For complete configuration details including all supported source types and comparison with
extraKnownMarketplaces
, see the
strictKnownMarketplaces reference
.
​
Version resolution and release channels
Plugin versions determine cache paths and update detection: if the resolved version matches what a user already has,
/plugin update
and auto-update skip the plugin.
Claude Code resolves a plugin’s version from the first of these that is set:
version
in the plugin’s
plugin.json
version
in the plugin’s marketplace entry
The git commit SHA of the plugin’s source
For the git-based source types
github
,
url
,
git-subdir
, and relative paths inside a git-hosted marketplace, you can omit
version
entirely and every new commit is treated as a new version. This is the simplest setup for internal or actively-developed plugins.
Setting
version
pins the plugin. If
plugin.json
declares
"version": "1.0.0"
, pushing new commits without changing that string does nothing for existing users, because Claude Code sees the same version and keeps the cached copy. Bump the field on every release, or omit it to use the commit SHA.
Avoid setting
version
in both
plugin.json
and the marketplace entry. The
plugin.json
value always wins silently, so a stale manifest version can mask a version you set in
marketplace.json
.
​
Set up release channels
To support “stable” and “latest” release channels for your plugins, you can set up two marketplaces that point to different refs or SHAs of the same repo. You can then assign the two marketplaces to different user groups through
managed settings
.
Each channel must resolve to a different version. If you use explicit versions,
plugin.json
must declare a different
version
at each pinned ref. If you omit
version
, the distinct commit SHAs already distinguish the channels. If two refs resolve to the same version string, Claude Code treats them as identical and skips the update.
Example
{
"name"
:
"stable-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
,
"ref"
:
"stable"
}
}
]
}
{
"name"
:
"latest-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
,
"ref"
:
"latest"
}
}
]
}
Assign channels to user groups
Assign each marketplace to the appropriate user group through managed settings. For example, the stable group receives:
{
"extraKnownMarketplaces"
: {
"stable-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/stable-tools"
}
}
}
}
The early-access group receives
latest-tools
instead:
{
"extraKnownMarketplaces"
: {
"latest-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/latest-tools"
}
}
}
}
​
Pin dependency versions
A plugin can constrain its dependencies to a semver range so that updates to a dependency do not break the dependent plugin. See
Constrain plugin dependency versions
for the
{plugin-name}--v{version}
git-tag convention, range syntax, and how multiple constraints on the same dependency are combined.
​
Validation and testing
Test your marketplace before sharing.
Validate your marketplace JSON syntax:
claude
plugin
validate
.
Or from within Claude Code:
/plugin
validate
.
Add the marketplace for testing:
/plugin
marketplace
add
./path/to/marketplace
Install a test plugin to verify everything works:
/plugin
install
test-plugin@marketplace-name
For complete plugin testing workflows, see
Test your plugins locally
. For technical troubleshooting, see
Plugins reference
.
​
Manage marketplaces from the CLI
Claude Code provides non-interactive
claude plugin marketplace
subcommands for scripting and automation. These are equivalent to the
/plugin marketplace
commands available inside an interactive session.
​
Plugin marketplace add
Add a marketplace from a GitHub repository, git URL, remote URL, or local path.
claude
plugin
marketplace
add
<
sourc
e
>
[options]
Arguments:
<source>
: GitHub
owner/repo
shorthand, git URL, remote URL to a
marketplace.json
file, or local directory path. To pin to a branch or tag, append
@ref
to the GitHub shorthand or
#ref
to a git URL
Options:
Option
Description
Default
--scope <scope>
Where to declare the marketplace:
user
,
project
, or
local
. See
Plugin installation scopes
user
--sparse <paths...>
Limit checkout to specific directories via git sparse-checkout. Useful for monorepos
Add a marketplace from GitHub using
owner/repo
shorthand:
claude
plugin
marketplace
add
acme-corp/claude-plugins
Pin to a specific branch or tag with
@ref
:
claude
plugin
marketplace
add
acme-corp/claude-plugins@v2.0
Add from a git URL on a non-GitHub host:
claude
plugin
marketplace
add
https://gitlab.example.com/team/plugins.git
Add from a remote URL that serves the
marketplace.json
file directly:
claude
plugin
marketplace
add
https://example.com/marketplace.json
Add from a local directory for testing:
claude
plugin
marketplace
add
./my-marketplace
Declare the marketplace at project scope so it is shared with your team via
.claude/settings.json
:
claude
plugin
marketplace
add
acme-corp/claude-plugins
--scope
project
For a monorepo, limit the checkout to the directories that contain plugin content:
claude
plugin
marketplace
add
acme-corp/monorepo
--sparse
.claude-plugin
plugins
​
Plugin marketplace list
List all configured marketplaces.
claude
plugin
marketplace
list
[options]
Options:
Option
Description
--json
Output as JSON
​
Plugin marketplace remove
Remove a configured marketplace. The alias
rm
is also accepted.
claude
plugin
marketplace
remove
<
nam
e
>
Arguments:
<name>
: marketplace name to remove, as shown by
claude plugin marketplace list
. This is the
name
from
marketplace.json
, not the source you passed to
add
Removing a marketplace also uninstalls any plugins you installed from it. To refresh a marketplace without losing installed plugins, use
claude plugin marketplace update
instead.
​
Plugin marketplace update
Refresh marketplaces from their sources to retrieve new plugins and version changes.
claude
plugin
marketplace
update
[name]
Arguments:
[name]
: marketplace name to update, as shown by
claude plugin marketplace list
. Updates all marketplaces if omitted
Both
remove
and
update
fail when run against a seed-managed marketplace, which is read-only. When updating all marketplaces, seed-managed entries are skipped and other marketplaces still update. To change seed-provided plugins, ask your administrator to update the seed image. See
Pre-populate plugins for containers
.
​
Troubleshooting
​
Marketplace not loading
Symptoms
: Can’t add marketplace or see plugins from it
Solutions
:
Verify the marketplace URL is accessible
Check that
.claude-plugin/marketplace.json
exists at the specified path
Ensure JSON syntax is valid and frontmatter is well-formed using
claude plugin validate
or
/plugin validate
For private repositories, confirm you have access permissions
​
Marketplace validation errors
Run
claude plugin validate .
or
/plugin validate .
from your marketplace directory to check for issues. The validator checks
plugin.json
, skill/agent/command frontmatter, and
hooks/hooks.json
for syntax and schema errors. Common errors:
Error
Cause
Solution
File not found: .claude-plugin/marketplace.json
Missing manifest
Create
.claude-plugin/marketplace.json
with required fields
Invalid JSON syntax: Unexpected token...
JSON syntax error in marketplace.json
Check for missing commas, extra commas, or unquoted strings
Duplicate plugin name "x" found in marketplace
Two plugins share the same name
Give each plugin a unique
name
value
plugins[0].source: Path contains ".."
Source path contains
..
Use paths relative to the marketplace root without
..
. See
Relative paths
YAML frontmatter failed to parse: ...
Invalid YAML in a skill, agent, or command file
Fix the YAML syntax in the frontmatter block. At runtime this file loads with no metadata.
Invalid JSON syntax: ...
(hooks.json)
Malformed
hooks/hooks.json
Fix JSON syntax. A malformed
hooks/hooks.json
prevents the entire plugin from loading.
Warnings
(non-blocking):
Marketplace has no plugins defined
: add at least one plugin to the
plugins
array
No marketplace description provided
: add a top-level
description
to help users understand your marketplace
Plugin name "x" is not kebab-case
: the plugin name contains uppercase letters, spaces, or special characters. Rename to lowercase letters, digits, and hyphens only (for example,
my-plugin
). Claude Code accepts other forms, but the Claude.ai marketplace sync rejects them.
​
Plugin installation failures
Symptoms
: Marketplace appears but plugin installation fails
Solutions
:
Verify plugin source URLs are accessible
Check that plugin directories contain required files
For GitHub sources, ensure repositories are public or you have access
Test plugin sources manually by cloning/downloading
​
Private repository authentication fails
Symptoms
: Authentication errors when installing plugins from private repositories
Solutions
:
For manual installation and updates:
Verify you’re authenticated with your git provider (for example, run
gh auth status
for GitHub)
Check that your credential helper is configured correctly:
git config --global credential.helper
Try cloning the repository manually to verify your credentials work
For background auto-updates:
Set the appropriate token in your environment:
echo $GITHUB_TOKEN
Check that the token has the required permissions (read access to the repository)
For GitHub, ensure the token has the
repo
scope for private repositories
For GitLab, ensure the token has at least
read_repository
scope
Verify the token hasn’t expired
​
Marketplace updates fail in offline environments
Symptoms
: Marketplace
git pull
fails and Claude Code wipes the existing cache, causing plugins to become unavailable.
Cause
: By default, when a
git pull
fails, Claude Code removes the stale clone and attempts to re-clone. In offline or airgapped environments, re-cloning fails the same way, leaving the marketplace directory empty.
Solution
: Set
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1
to keep the existing cache when the pull fails instead of wiping it:
export
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE
=
1
With this variable set, Claude Code retains the stale marketplace clone on
git pull
failure and continues using the last-known-good state. For fully offline deployments where the repository will never be reachable, use
CLAUDE_CODE_PLUGIN_SEED_DIR
to pre-populate the plugins directory at build time instead.
​
Git operations time out
Symptoms
: Plugin installation or marketplace updates fail with a timeout error like “Git clone timed out after 120s” or “Git pull timed out after 120s”.
Cause
: Claude Code uses a 120-second timeout for all git operations, including cloning plugin repositories and pulling marketplace updates. Large repositories or slow network connections may exceed this limit.
Solution
: Increase the timeout using the
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
environment variable. The value is in milliseconds:
export
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
=
300000
# 5 minutes
​
Plugins with relative paths fail in URL-based marketplaces
Symptoms
: Added a marketplace via URL (such as
https://example.com/marketplace.json
), but plugins with relative path sources like
"./plugins/my-plugin"
fail to install with “path not found” errors.
Cause
: URL-based marketplaces only download the
marketplace.json
file itself. They do not download plugin files from the server. Relative paths in the marketplace entry reference files on the remote server that were not downloaded.
Solutions
:
Use external sources
: Change plugin entries to use GitHub, npm, or git URL sources instead of relative paths:
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/repo"
} }
Use a Git-based marketplace
: Host your marketplace in a Git repository and add it with the git URL. Git-based marketplaces clone the entire repository, making relative paths work correctly.
​
Files not found after installation
Symptoms
: Plugin installs but references to files fail, especially files outside the plugin directory
Cause
: Plugins are copied to a cache directory rather than used in-place. Paths that reference files outside the plugin’s directory (such as
../shared-utils
) won’t work because those files aren’t copied.
Solutions
: See
Plugin caching and file resolution
for workarounds including symlinks and directory restructuring.
For additional debugging tools and common issues, see
Debugging and development tools
.
​
See also
Discover and install prebuilt plugins
- Installing plugins from existing marketplaces
Plugins
- Creating your own plugins
Plugins reference
- Complete technical specifications and schemas
Plugin settings
- Plugin configuration options
strictKnownMarketplaces reference
- Managed marketplace restrictions
Was this page helpful?
Yes
No
Track team usage with analytics
Plugin dependency versions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugin-marketplaces" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Create and distribute a plugin marketplace
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distri...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Plugin distribution
Create and distribute a plugin marketplace
Setup and access
Administration overview
Advanced setup
Authentication
Server-managed settings
Auto mode
Deployment
Overview
Amazon Bedrock
Claude Platform on AWS
Google Vertex AI
Microsoft Foundry
Network configuration
LLM gateway
Development containers
Usage and costs
Monitoring
Costs
Track team usage with analytics
Plugin distribution
Create and distribute a plugin marketplace
Plugin dependency versions
Security and data
Security
Data usage
Zero data retention
Adoption
Communications kit
Champion kit
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
A
plugin marketplace
is a catalog that lets you distribute plugins to others. Marketplaces provide centralized discovery, version tracking, automatic updates, and support for multiple source types (git repositories, local paths, and more). This guide shows you how to create your own marketplace to share plugins with your team or community.
Looking to install plugins from an existing marketplace? See
Discover and install prebuilt plugins
.
​
Overview
Creating and distributing a marketplace involves:
Creating plugins
: build one or more plugins with skills, agents, hooks, MCP servers, or LSP servers. This guide assumes you already have plugins to distribute; see
Create plugins
for details on how to create them.
Creating a marketplace file
: define a
marketplace.json
that lists your plugins and where to find them (see
Create the marketplace file
).
Host the marketplace
: push to GitHub, GitLab, or another git host (see
Host and distribute marketplaces
).
Share with users
: users add your marketplace with
/plugin marketplace add
and install individual plugins (see
Discover and install plugins
).
Once your marketplace is live, you can update it by pushing changes to your repository. Users refresh their local copy with
/plugin marketplace update
.
​
Walkthrough: create a local marketplace
This example creates a marketplace with one plugin: a
quality-review
skill for code reviews. You’ll create the directory structure, add a skill, create the plugin manifest and marketplace catalog, then install and test it.
1
Create the directory structure
mkdir
-p
my-marketplace/.claude-plugin
mkdir
-p
my-marketplace/plugins/quality-review-plugin/.claude-plugin
mkdir
-p
my-marketplace/plugins/quality-review-plugin/skills/quality-review
2
Create the skill
Create a
SKILL.md
file that defines what the
quality-review
skill does.
my-marketplace/plugins/quality-review-plugin/skills/quality-review/SKILL.md
---
description
:
Review code for bugs, security, and performance
disable-model-invocation
:
true
---
Review the code I've selected or the recent changes for:
-
Potential bugs or edge cases
-
Security concerns
-
Performance issues
-
Readability improvements
Be concise and actionable.
3
Create the plugin manifest
Create a
plugin.json
file that describes the plugin. The manifest goes in the
.claude-plugin/
directory.
my-marketplace/plugins/quality-review-plugin/.claude-plugin/plugin.json
{
"name"
:
"quality-review-plugin"
,
"description"
:
"Adds a quality-review skill for quick code reviews"
,
"version"
:
"1.0.0"
}
Setting
version
means users only receive updates when you change this field, so bump it on every release. If you omit
version
and host this marketplace in git, every commit automatically counts as a new version. See
Version resolution
to choose the right approach.
4
Create the marketplace file
Create the marketplace catalog that lists your plugin.
my-marketplace/.claude-plugin/marketplace.json
{
"name"
:
"my-plugins"
,
"owner"
: {
"name"
:
"Your Name"
},
"plugins"
: [
{
"name"
:
"quality-review-plugin"
,
"source"
:
"./plugins/quality-review-plugin"
,
"description"
:
"Adds a quality-review skill for quick code reviews"
}
]
}
5
Add and install
Add the marketplace and install the plugin.
/plugin
marketplace
add
./my-marketplace
/plugin
install
quality-review-plugin@my-plugins
6
Try it out
Select some code in your editor and run your new skill. Plugin skills are namespaced with the plugin name.
/quality-review-plugin:quality-review
To learn more about what plugins can do, including hooks, agents, MCP servers, and LSP servers, see
Plugins
.
How plugins are installed
: When users install a plugin, Claude Code copies the plugin directory to a cache location. This means plugins can’t reference files outside their directory using paths like
../shared-utils
, because those files won’t be copied.
If you need to share files across plugins, use symlinks. See
Plugin caching and file resolution
for details.
​
Create the marketplace file
Create
.claude-plugin/marketplace.json
in your repository root. This file defines your marketplace’s name, owner information, and a list of plugins with their sources.
Each plugin entry needs at minimum a
name
and
source
(where to fetch it from). See the
full schema
below for all available fields.
{
"name"
:
"company-tools"
,
"owner"
: {
"name"
:
"DevTools Team"
,
"email"
:
"devtools@example.com"
},
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
:
"./plugins/formatter"
,
"description"
:
"Automatic code formatting on save"
,
"version"
:
"2.1.0"
,
"author"
: {
"name"
:
"DevTools Team"
}
},
{
"name"
:
"deployment-tools"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"company/deploy-plugin"
},
"description"
:
"Deployment automation tools"
}
]
}
​
Marketplace schema
​
Required fields
Field
Type
Description
Example
name
string
Marketplace identifier (kebab-case, no spaces). This is public-facing: users see it when installing plugins (for example,
/plugin install my-tool@your-marketplace
).
"acme-tools"
owner
object
Marketplace maintainer information (
see fields below
)
plugins
array
List of available plugins
See below
Reserved names
: The following marketplace names are reserved for official Anthropic use and cannot be used by third-party marketplaces:
claude-code-marketplace
,
claude-code-plugins
,
claude-plugins-official
,
anthropic-marketplace
,
anthropic-plugins
,
agent-skills
,
knowledge-work-plugins
,
life-sciences
. Names that impersonate official marketplaces (like
official-claude-plugins
or
anthropic-tools-v2
) are also blocked.
​
Owner fields
Field
Type
Required
Description
name
string
Yes
Name of the maintainer or team
email
string
No
Contact email for the maintainer
​
Optional fields
Field
Type
Description
$schema
string
JSON Schema URL for editor autocomplete and validation. Claude Code ignores this field at load time.
description
string
Brief marketplace description
version
string
Marketplace manifest version
metadata.pluginRoot
string
Base directory prepended to relative plugin source paths (for example,
"./plugins"
lets you write
"source": "formatter"
instead of
"source": "./plugins/formatter"
)
allowCrossMarketplaceDependenciesOn
array
Other marketplaces that plugins in this marketplace may depend on. Dependencies from a marketplace not listed here are blocked at install. See
Depend on a plugin from another marketplace
.
description
and
version
are also accepted under
metadata
for backward compatibility.
​
Plugin entries
Each plugin entry in the
plugins
array describes a plugin and where to find it. You can include any field from the
plugin manifest schema
(like
description
,
version
,
author
,
commands
,
hooks
, etc.), plus these marketplace-specific fields:
source
,
category
,
tags
, and
strict
.
​
Required fields
Field
Type
Description
name
string
Plugin identifier (kebab-case, no spaces). This is public-facing: users see it when installing (for example,
/plugin install my-plugin@marketplace
).
source
string|object
Where to fetch the plugin from (see
Plugin sources
below)
​
Optional plugin fields
Standard metadata fields:
Field
Type
Description
description
string
Brief plugin description
version
string
Plugin version. If set (here or in
plugin.json
), the plugin is pinned to this string and users only receive updates when it changes. Omit to fall back to the git commit SHA. See
Version resolution
.
author
object
Plugin author information (
name
required,
email
optional)
homepage
string
Plugin homepage or documentation URL
repository
string
Source code repository URL
license
string
SPDX license identifier (for example, MIT, Apache-2.0)
keywords
array
Tags for plugin discovery and categorization
category
string
Plugin category for organization
tags
array
Tags for searchability
strict
boolean
Controls whether
plugin.json
is the authority for component definitions (default: true). See
Strict mode
below.
Component configuration fields:
Field
Type
Description
skills
string|array
Custom paths to skill directories containing
<name>/SKILL.md
commands
string|array
Custom paths to flat
.md
skill files or directories
agents
string|array
Custom paths to agent files
hooks
string|object
Custom hooks configuration or path to hooks file
mcpServers
string|object
MCP server configurations or path to MCP config
lspServers
string|object
LSP server configurations or path to LSP config
​
Plugin sources
Plugin sources tell Claude Code where to fetch each individual plugin listed in your marketplace. These are set in the
source
field of each plugin entry in
marketplace.json
.
Once a plugin is cloned or copied into the local machine, it is copied into the local versioned plugin cache at
~/.claude/plugins/cache
.
Source
Type
Fields
Notes
Relative path
string
(e.g.
"./my-plugin"
)
none
Local directory within the marketplace repo. Must start with
./
. Resolved relative to the marketplace root, not the
.claude-plugin/
directory
github
object
repo
,
ref?
,
sha?
url
object
url
,
ref?
,
sha?
Git URL source
git-subdir
object
url
,
path
,
ref?
,
sha?
Subdirectory within a git repo. Clones sparsely to minimize bandwidth for monorepos
npm
object
package
,
version?
,
registry?
Installed via
npm install
Marketplace sources vs plugin sources
: These are different concepts that control different things.
Marketplace source
— where to fetch the
marketplace.json
catalog itself. Set when users run
/plugin marketplace add
or in
extraKnownMarketplaces
settings. Supports
ref
(branch/tag) but not
sha
.
Plugin source
— where to fetch an individual plugin listed in the marketplace. Set in the
source
field of each plugin entry inside
marketplace.json
. Supports both
ref
(branch/tag) and
sha
(exact commit).
For example, a marketplace hosted at
acme-corp/plugin-catalog
(marketplace source) can list a plugin fetched from
acme-corp/code-formatter
(plugin source). The marketplace source and plugin source point to different repositories and are pinned independently.
​
Relative paths
For plugins in the same repository, use a path starting with
./
:
{
"name"
:
"my-plugin"
,
"source"
:
"./plugins/my-plugin"
}
Paths resolve relative to the marketplace root, which is the directory containing
.claude-plugin/
. In the example above,
./plugins/my-plugin
points to
<repo>/plugins/my-plugin
, even though
marketplace.json
lives at
<repo>/.claude-plugin/marketplace.json
. Do not use
../
to reference paths outside the marketplace root.
Relative paths only work when users add your marketplace via Git (GitHub, GitLab, or git URL). If users add your marketplace via a direct URL to the
marketplace.json
file, relative paths will not resolve correctly. For URL-based distribution, use GitHub, npm, or git URL sources instead. See
Troubleshooting
for details.
​
GitHub repositories
{
"name"
:
"github-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/plugin-repo"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"github-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/plugin-repo"
,
"ref"
:
"v2.0.0"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
Field
Type
Description
repo
string
Required. GitHub repository in
owner/repo
format
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
Git repositories
{
"name"
:
"git-plugin"
,
"source"
: {
"source"
:
"url"
,
"url"
:
"https://gitlab.com/team/plugin.git"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"git-plugin"
,
"source"
: {
"source"
:
"url"
,
"url"
:
"https://gitlab.com/team/plugin.git"
,
"ref"
:
"main"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
Field
Type
Description
url
string
Required. Full git repository URL (
https://
or
git@
). The
.git
suffix is optional, so Azure DevOps and AWS CodeCommit URLs without the suffix work
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
Git subdirectories
Use
git-subdir
to point to a plugin that lives inside a subdirectory of a git repository. Claude Code uses a sparse, partial clone to fetch only the subdirectory, minimizing bandwidth for large monorepos.
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"git-subdir"
,
"url"
:
"https://github.com/acme-corp/monorepo.git"
,
"path"
:
"tools/claude-plugin"
}
}
You can pin to a specific branch, tag, or commit:
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"git-subdir"
,
"url"
:
"https://github.com/acme-corp/monorepo.git"
,
"path"
:
"tools/claude-plugin"
,
"ref"
:
"v2.0.0"
,
"sha"
:
"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
The
url
field also accepts a GitHub shorthand (
owner/repo
) or SSH URLs (
git@github.com:owner/repo.git
).
Field
Type
Description
url
string
Required. Git repository URL, GitHub
owner/repo
shorthand, or SSH URL
path
string
Required. Subdirectory path within the repo containing the plugin (for example,
"tools/claude-plugin"
)
ref
string
Optional. Git branch or tag (defaults to repository default branch)
sha
string
Optional. Full 40-character git commit SHA to pin to an exact version
​
npm packages
Plugins distributed as npm packages are installed using
npm install
. This works with any package on the public npm registry or a private registry your team hosts.
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
}
}
To pin to a specific version, add the
version
field:
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
,
"version"
:
"2.1.0"
}
}
To install from a private or internal registry, add the
registry
field:
{
"name"
:
"my-npm-plugin"
,
"source"
: {
"source"
:
"npm"
,
"package"
:
"@acme/claude-plugin"
,
"version"
:
"^2.0.0"
,
"registry"
:
"https://npm.example.com"
}
}
Field
Type
Description
package
string
Required. Package name or scoped package (for example,
@org/plugin
)
version
string
Optional. Version or version range (for example,
2.1.0
,
^2.0.0
,
~1.5.0
)
registry
string
Optional. Custom npm registry URL. Defaults to the system npm registry (typically npmjs.org)
​
Advanced plugin entries
This example shows a plugin entry using many of the optional fields, including custom paths for commands, agents, hooks, and MCP servers:
{
"name"
:
"enterprise-tools"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"company/enterprise-plugin"
},
"description"
:
"Enterprise workflow automation tools"
,
"version"
:
"2.1.0"
,
"author"
: {
"name"
:
"Enterprise Team"
,
"email"
:
"enterprise@example.com"
},
"homepage"
:
"https://docs.example.com/plugins/enterprise-tools"
,
"repository"
:
"https://github.com/company/enterprise-plugin"
,
"license"
:
"MIT"
,
"keywords"
: [
"enterprise"
,
"workflow"
,
"automation"
],
"category"
:
"productivity"
,
"commands"
: [
"./commands/core/"
,
"./commands/enterprise/"
,
"./commands/experimental/preview.md"
],
"agents"
: [
"./agents/security-reviewer.md"
,
"./agents/compliance-checker.md"
],
"hooks"
: {
"PostToolUse"
: [
{
"matcher"
:
"Write|Edit"
,
"hooks"
: [
{
"type"
:
"command"
,
"command"
:
"${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
]
}
]
},
"mcpServers"
: {
"enterprise-db"
: {
"command"
:
"${CLAUDE_PLUGIN_ROOT}/servers/db-server"
,
"args"
: [
"--config"
,
"${CLAUDE_PLUGIN_ROOT}/config.json"
]
}
},
"strict"
:
false
}
Key things to notice:
commands
and
agents
: You can specify multiple directories or individual files. Paths are relative to the plugin root.
${CLAUDE_PLUGIN_ROOT}
: use this variable in hooks and MCP server configs to reference files within the plugin’s installation directory. This is necessary because plugins are copied to a cache location when installed. For dependencies or state that should survive plugin updates, use
${CLAUDE_PLUGIN_DATA}
instead.
strict: false
: Since this is set to false, the plugin doesn’t need its own
plugin.json
. The marketplace entry defines everything. See
Strict mode
below.
​
Strict mode
The
strict
field controls whether
plugin.json
is the authority for component definitions (skills, agents, hooks, MCP servers, output styles).
Value
Behavior
true
(default)
plugin.json
is the authority. The marketplace entry can supplement it with additional components, and both sources are merged.
false
The marketplace entry is the entire definition. If the plugin also has a
plugin.json
that declares components, that’s a conflict and the plugin fails to load.
When to use each mode:
strict: true
: the plugin has its own
plugin.json
and manages its own components. The marketplace entry can add extra skills or hooks on top. This is the default and works for most plugins.
strict: false
: the marketplace operator wants full control. The plugin repo provides raw files, and the marketplace entry defines which of those files are exposed as skills, agents, hooks, etc. Useful when the marketplace restructures or curates a plugin’s components differently than the plugin author intended.
​
Host and distribute marketplaces
​
Host on GitHub (recommended)
GitHub provides the easiest distribution method:
Create a repository
: Set up a new repository for your marketplace
Add marketplace file
: Create
.claude-plugin/marketplace.json
with your plugin definitions
Share with teams
: Users add your marketplace with
/plugin marketplace add owner/repo
Benefits
: Built-in version control, issue tracking, and team collaboration features.
​
Host on other git services
Any git hosting service works, such as GitLab, Bitbucket, and self-hosted servers. Users add with the full repository URL:
/plugin
marketplace
add
https://gitlab.com/company/plugins.git
​
Private repositories
Claude Code supports installing plugins from private repositories. For manual installation and updates, Claude Code uses your existing git credential helpers, so HTTPS access via
gh auth login
, macOS Keychain, or
git-credential-store
works the same as in your terminal. SSH access works as long as the host is already in your
known_hosts
file and the key is loaded in
ssh-agent
, since Claude Code suppresses interactive SSH prompts for the host fingerprint and key passphrase.
Background auto-updates run at startup without credential helpers, since interactive prompts would block Claude Code from starting. To enable auto-updates for private marketplaces, set the appropriate authentication token in your environment:
Provider
Environment variables
Notes
GitHub
GITHUB_TOKEN
or
GH_TOKEN
Personal access token or GitHub App token
GitLab
GITLAB_TOKEN
or
GL_TOKEN
Personal access token or project token
Bitbucket
BITBUCKET_TOKEN
App password or repository access token
Set the token in your shell configuration (for example,
.bashrc
,
.zshrc
) or pass it when running Claude Code:
export
GITHUB_TOKEN
=
ghp_xxxxxxxxxxxxxxxxxxxx
For CI/CD environments, configure the token as a secret environment variable. GitHub Actions automatically provides
GITHUB_TOKEN
for repositories in the same organization.
​
Test locally before distribution
Test your marketplace locally before sharing:
/plugin
marketplace
add
./my-local-marketplace
/plugin
install
test-plugin@my-local-marketplace
For the full range of add commands (GitHub, Git URLs, local paths, remote URLs), see
Add marketplaces
.
​
Require marketplaces for your team
You can configure your repository so team members are automatically prompted to install your marketplace when they trust the project folder. Add your marketplace to
.claude/settings.json
:
{
"extraKnownMarketplaces"
: {
"company-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"your-org/claude-plugins"
}
}
}
}
You can also specify which plugins should be enabled by default:
{
"enabledPlugins"
: {
"code-formatter@company-tools"
:
true
,
"deployment-tools@company-tools"
:
true
}
}
For full configuration options, see
Plugin settings
.
If you use a local
directory
or
file
source with a relative path, the path resolves against your repository’s main checkout. When you run Claude Code from a git worktree, the path still points at the main checkout, so all worktrees share the same marketplace location. Marketplace state is stored once per user in
~/.claude/plugins/known_marketplaces.json
, not per project.
​
Pre-populate plugins for containers
For container images and CI environments, you can pre-populate a plugins directory at build time so Claude Code starts with marketplaces and plugins already available, without cloning anything at runtime. Set the
CLAUDE_CODE_PLUGIN_SEED_DIR
environment variable to point at this directory.
To layer multiple seed directories, separate paths with
:
on Unix or
;
on Windows. Claude Code searches each directory in order, and the first seed that contains a given marketplace or plugin cache wins.
The seed directory mirrors the structure of
~/.claude/plugins
:
$CLAUDE_CODE_PLUGIN_SEED_DIR/
known_marketplaces.json
marketplaces/<name>/...
cache/<marketplace>/<plugin>/<version>/...
To build a seed directory, run Claude Code once during image build, install the plugins you need, then copy the resulting
~/.claude/plugins
directory into your image and point
CLAUDE_CODE_PLUGIN_SEED_DIR
at it.
To skip the copy step, set
CLAUDE_CODE_PLUGIN_CACHE_DIR
to your target seed path during the build so plugins install directly there:
CLAUDE_CODE_PLUGIN_CACHE_DIR
=
/opt/claude-seed
claude
plugin
marketplace
add
your-org/plugins
CLAUDE_CODE_PLUGIN_CACHE_DIR
=
/opt/claude-seed
claude
plugin
install
my-tool@your-plugins
Then set
CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed
in your container’s runtime environment so Claude Code reads from the seed on startup.
At startup, Claude Code registers marketplaces found in the seed’s
known_marketplaces.json
into the primary configuration, and uses plugin caches found under
cache/
in place without re-cloning. This works in both interactive mode and non-interactive mode with the
-p
flag.
Behavior details:
Read-only
: the seed directory is never written to. Auto-updates are disabled for seed marketplaces since git pull would fail on a read-only filesystem.
Seed entries take precedence
: marketplaces declared in the seed overwrite any matching entries in the user’s configuration on each startup. To opt out of a seed plugin, use
/plugin disable
rather than removing the marketplace.
Path resolution
: Claude Code locates marketplace content by probing
$CLAUDE_CODE_PLUGIN_SEED_DIR/marketplaces/<name>/
at runtime, not by trusting paths stored inside the seed’s JSON. This means the seed works correctly even when mounted at a different path than where it was built.
Mutation is blocked
: running
/plugin marketplace remove
or
/plugin marketplace update
against a seed-managed marketplace fails with guidance to ask your administrator to update the seed image.
Composes with settings
: if
extraKnownMarketplaces
or
enabledPlugins
declare a marketplace that already exists in the seed, Claude Code uses the seed copy instead of cloning.
​
Managed marketplace restrictions
For organizations requiring strict control over plugin sources, administrators can restrict which plugin marketplaces users are allowed to add using the
strictKnownMarketplaces
setting in managed settings.
When
strictKnownMarketplaces
is configured in managed settings, the restriction behavior depends on the value:
Value
Behavior
Undefined (default)
No restrictions. Users can add any marketplace
Empty array
[]
Complete lockdown. Users cannot add any new marketplaces
List of sources
Users can only add marketplaces that match the allowlist exactly
​
Common configurations
Disable all marketplace additions:
{
"strictKnownMarketplaces"
: []
}
Allow specific marketplaces only:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"github"
,
"repo"
:
"acme-corp/approved-plugins"
},
{
"source"
:
"github"
,
"repo"
:
"acme-corp/security-tools"
,
"ref"
:
"v2.0"
},
{
"source"
:
"url"
,
"url"
:
"https://plugins.example.com/marketplace.json"
}
]
}
Allow all marketplaces from an internal git server using regex pattern matching on the host. This is the recommended approach for
GitHub Enterprise Server
or self-hosted GitLab instances:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"hostPattern"
,
"hostPattern"
:
"^github
\\
.example
\\
.com$"
}
]
}
Allow filesystem-based marketplaces from a specific directory using regex pattern matching on the path:
{
"strictKnownMarketplaces"
: [
{
"source"
:
"pathPattern"
,
"pathPattern"
:
"^/opt/approved/"
}
]
}
Use
".*"
as the
pathPattern
to allow any filesystem path while still controlling network sources with
hostPattern
.
strictKnownMarketplaces
restricts what users can add, but does not register marketplaces on its own. To make allowed marketplaces available automatically without users running
/plugin marketplace add
, pair it with
extraKnownMarketplaces
in the same
managed-settings.json
. See
Using both together
.
​
How restrictions work
Restrictions are checked before any network or filesystem operation. The check runs on marketplace add and on plugin install, update, refresh, and auto-update. If a marketplace was added before the policy was configured and its source no longer matches the allowlist, Claude Code refuses to install or update plugins from it. The same enforcement applies to
blockedMarketplaces
.
The allowlist uses exact matching for most source types. For a marketplace to be allowed, all specified fields must match exactly:
For GitHub sources:
repo
is required, and
ref
or
path
must also match if specified in the allowlist
For URL sources: the full URL must match exactly
For
hostPattern
sources: the marketplace host is matched against the regex pattern
For
pathPattern
sources: the marketplace’s filesystem path is matched against the regex pattern
Exact matching does not normalize URLs: a trailing slash,
.git
suffix, or
ssh://
versus
https://
form are treated as different values. If your organization’s marketplace can be cloned by more than one URL form, prefer a
hostPattern
entry over a literal URL so all forms match.
Because
strictKnownMarketplaces
is set in
managed settings
, individual users and project configurations cannot override these restrictions.
For complete configuration details including all supported source types and comparison with
extraKnownMarketplaces
, see the
strictKnownMarketplaces reference
.
​
Version resolution and release channels
Plugin versions determine cache paths and update detection: if the resolved version matches what a user already has,
/plugin update
and auto-update skip the plugin.
Claude Code resolves a plugin’s version from the first of these that is set:
version
in the plugin’s
plugin.json
version
in the plugin’s marketplace entry
The git commit SHA of the plugin’s source
For the git-based source types
github
,
url
,
git-subdir
, and relative paths inside a git-hosted marketplace, you can omit
version
entirely and every new commit is treated as a new version. This is the simplest setup for internal or actively-developed plugins.
Setting
version
pins the plugin. If
plugin.json
declares
"version": "1.0.0"
, pushing new commits without changing that string does nothing for existing users, because Claude Code sees the same version and keeps the cached copy. Bump the field on every release, or omit it to use the commit SHA.
Avoid setting
version
in both
plugin.json
and the marketplace entry. The
plugin.json
value always wins silently, so a stale manifest version can mask a version you set in
marketplace.json
.
​
Set up release channels
To support “stable” and “latest” release channels for your plugins, you can set up two marketplaces that point to different refs or SHAs of the same repo. You can then assign the two marketplaces to different user groups through
managed settings
.
Each channel must resolve to a different version. If you use explicit versions,
plugin.json
must declare a different
version
at each pinned ref. If you omit
version
, the distinct commit SHAs already distinguish the channels. If two refs resolve to the same version string, Claude Code treats them as identical and skips the update.
Example
{
"name"
:
"stable-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
,
"ref"
:
"stable"
}
}
]
}
{
"name"
:
"latest-tools"
,
"plugins"
: [
{
"name"
:
"code-formatter"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/code-formatter"
,
"ref"
:
"latest"
}
}
]
}
Assign channels to user groups
Assign each marketplace to the appropriate user group through managed settings. For example, the stable group receives:
{
"extraKnownMarketplaces"
: {
"stable-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/stable-tools"
}
}
}
}
The early-access group receives
latest-tools
instead:
{
"extraKnownMarketplaces"
: {
"latest-tools"
: {
"source"
: {
"source"
:
"github"
,
"repo"
:
"acme-corp/latest-tools"
}
}
}
}
​
Pin dependency versions
A plugin can constrain its dependencies to a semver range so that updates to a dependency do not break the dependent plugin. See
Constrain plugin dependency versions
for the
{plugin-name}--v{version}
git-tag convention, range syntax, and how multiple constraints on the same dependency are combined.
​
Validation and testing
Test your marketplace before sharing.
Validate your marketplace JSON syntax:
claude
plugin
validate
.
Or from within Claude Code:
/plugin
validate
.
Add the marketplace for testing:
/plugin
marketplace
add
./path/to/marketplace
Install a test plugin to verify everything works:
/plugin
install
test-plugin@marketplace-name
For complete plugin testing workflows, see
Test your plugins locally
. For technical troubleshooting, see
Plugins reference
.
​
Manage marketplaces from the CLI
Claude Code provides non-interactive
claude plugin marketplace
subcommands for scripting and automation. These are equivalent to the
/plugin marketplace
commands available inside an interactive session.
​
Plugin marketplace add
Add a marketplace from a GitHub repository, git URL, remote URL, or local path.
claude
plugin
marketplace
add
<
sourc
e
>
[options]
Arguments:
<source>
: GitHub
owner/repo
shorthand, git URL, remote URL to a
marketplace.json
file, or local directory path. To pin to a branch or tag, append
@ref
to the GitHub shorthand or
#ref
to a git URL
Options:
Option
Description
Default
--scope <scope>
Where to declare the marketplace:
user
,
project
, or
local
. See
Plugin installation scopes
user
--sparse <paths...>
Limit checkout to specific directories via git sparse-checkout. Useful for monorepos
Add a marketplace from GitHub using
owner/repo
shorthand:
claude
plugin
marketplace
add
acme-corp/claude-plugins
Pin to a specific branch or tag with
@ref
:
claude
plugin
marketplace
add
acme-corp/claude-plugins@v2.0
Add from a git URL on a non-GitHub host:
claude
plugin
marketplace
add
https://gitlab.example.com/team/plugins.git
Add from a remote URL that serves the
marketplace.json
file directly:
claude
plugin
marketplace
add
https://example.com/marketplace.json
Add from a local directory for testing:
claude
plugin
marketplace
add
./my-marketplace
Declare the marketplace at project scope so it is shared with your team via
.claude/settings.json
:
claude
plugin
marketplace
add
acme-corp/claude-plugins
--scope
project
For a monorepo, limit the checkout to the directories that contain plugin content:
claude
plugin
marketplace
add
acme-corp/monorepo
--sparse
.claude-plugin
plugins
​
Plugin marketplace list
List all configured marketplaces.
claude
plugin
marketplace
list
[options]
Options:
Option
Description
--json
Output as JSON
​
Plugin marketplace remove
Remove a configured marketplace. The alias
rm
is also accepted.
claude
plugin
marketplace
remove
<
nam
e
>
Arguments:
<name>
: marketplace name to remove, as shown by
claude plugin marketplace list
. This is the
name
from
marketplace.json
, not the source you passed to
add
Removing a marketplace also uninstalls any plugins you installed from it. To refresh a marketplace without losing installed plugins, use
claude plugin marketplace update
instead.
​
Plugin marketplace update
Refresh marketplaces from their sources to retrieve new plugins and version changes.
claude
plugin
marketplace
update
[name]
Arguments:
[name]
: marketplace name to update, as shown by
claude plugin marketplace list
. Updates all marketplaces if omitted
Both
remove
and
update
fail when run against a seed-managed marketplace, which is read-only. When updating all marketplaces, seed-managed entries are skipped and other marketplaces still update. To change seed-provided plugins, ask your administrator to update the seed image. See
Pre-populate plugins for containers
.
​
Troubleshooting
​
Marketplace not loading
Symptoms
: Can’t add marketplace or see plugins from it
Solutions
:
Verify the marketplace URL is accessible
Check that
.claude-plugin/marketplace.json
exists at the specified path
Ensure JSON syntax is valid and frontmatter is well-formed using
claude plugin validate
or
/plugin validate
For private repositories, confirm you have access permissions
​
Marketplace validation errors
Run
claude plugin validate .
or
/plugin validate .
from your marketplace directory to check for issues. The validator checks
plugin.json
, skill/agent/command frontmatter, and
hooks/hooks.json
for syntax and schema errors. Common errors:
Error
Cause
Solution
File not found: .claude-plugin/marketplace.json
Missing manifest
Create
.claude-plugin/marketplace.json
with required fields
Invalid JSON syntax: Unexpected token...
JSON syntax error in marketplace.json
Check for missing commas, extra commas, or unquoted strings
Duplicate plugin name "x" found in marketplace
Two plugins share the same name
Give each plugin a unique
name
value
plugins[0].source: Path contains ".."
Source path contains
..
Use paths relative to the marketplace root without
..
. See
Relative paths
YAML frontmatter failed to parse: ...
Invalid YAML in a skill, agent, or command file
Fix the YAML syntax in the frontmatter block. At runtime this file loads with no metadata.
Invalid JSON syntax: ...
(hooks.json)
Malformed
hooks/hooks.json
Fix JSON syntax. A malformed
hooks/hooks.json
prevents the entire plugin from loading.
Warnings
(non-blocking):
Marketplace has no plugins defined
: add at least one plugin to the
plugins
array
No marketplace description provided
: add a top-level
description
to help users understand your marketplace
Plugin name "x" is not kebab-case
: the plugin name contains uppercase letters, spaces, or special characters. Rename to lowercase letters, digits, and hyphens only (for example,
my-plugin
). Claude Code accepts other forms, but the Claude.ai marketplace sync rejects them.
​
Plugin installation failures
Symptoms
: Marketplace appears but plugin installation fails
Solutions
:
Verify plugin source URLs are accessible
Check that plugin directories contain required files
For GitHub sources, ensure repositories are public or you have access
Test plugin sources manually by cloning/downloading
​
Private repository authentication fails
Symptoms
: Authentication errors when installing plugins from private repositories
Solutions
:
For manual installation and updates:
Verify you’re authenticated with your git provider (for example, run
gh auth status
for GitHub)
Check that your credential helper is configured correctly:
git config --global credential.helper
Try cloning the repository manually to verify your credentials work
For background auto-updates:
Set the appropriate token in your environment:
echo $GITHUB_TOKEN
Check that the token has the required permissions (read access to the repository)
For GitHub, ensure the token has the
repo
scope for private repositories
For GitLab, ensure the token has at least
read_repository
scope
Verify the token hasn’t expired
​
Marketplace updates fail in offline environments
Symptoms
: Marketplace
git pull
fails and Claude Code wipes the existing cache, causing plugins to become unavailable.
Cause
: By default, when a
git pull
fails, Claude Code removes the stale clone and attempts to re-clone. In offline or airgapped environments, re-cloning fails the same way, leaving the marketplace directory empty.
Solution
: Set
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1
to keep the existing cache when the pull fails instead of wiping it:
export
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE
=
1
With this variable set, Claude Code retains the stale marketplace clone on
git pull
failure and continues using the last-known-good state. For fully offline deployments where the repository will never be reachable, use
CLAUDE_CODE_PLUGIN_SEED_DIR
to pre-populate the plugins directory at build time instead.
​
Git operations time out
Symptoms
: Plugin installation or marketplace updates fail with a timeout error like “Git clone timed out after 120s” or “Git pull timed out after 120s”.
Cause
: Claude Code uses a 120-second timeout for all git operations, including cloning plugin repositories and pulling marketplace updates. Large repositories or slow network connections may exceed this limit.
Solution
: Increase the timeout using the
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
environment variable. The value is in milliseconds:
export
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS
=
300000
# 5 minutes
​
Plugins with relative paths fail in URL-based marketplaces
Symptoms
: Added a marketplace via URL (such as
https://example.com/marketplace.json
), but plugins with relative path sources like
"./plugins/my-plugin"
fail to install with “path not found” errors.
Cause
: URL-based marketplaces only download the
marketplace.json
file itself. They do not download plugin files from the server. Relative paths in the marketplace entry reference files on the remote server that were not downloaded.
Solutions
:
Use external sources
: Change plugin entries to use GitHub, npm, or git URL sources instead of relative paths:
{
"name"
:
"my-plugin"
,
"source"
: {
"source"
:
"github"
,
"repo"
:
"owner/repo"
} }
Use a Git-based marketplace
: Host your marketplace in a Git repository and add it with the git URL. Git-based marketplaces clone the entire repository, making relative paths work correctly.
​
Files not found after installation
Symptoms
: Plugin installs but references to files fail, especially files outside the plugin directory
Cause
: Plugins are copied to a cache directory rather than used in-place. Paths that reference files outside the plugin’s directory (such as
../shared-utils
) won’t work because those files aren’t copied.
Solutions
: See
Plugin caching and file resolution
for workarounds including symlinks and directory restructuring.
For additional debugging tools and common issues, see
Debugging and development tools
.
​
See also
Discover and install prebuilt plugins
- Installing plugins from existing marketplaces
Plugins
- Creating your own plugins
Plugins reference
- Complete technical specifications and schemas
Plugin settings
- Plugin configuration options
strictKnownMarketplaces reference
- Managed marketplace restrictions
Was this page helpful?
Yes
No
Track team usage with analytics
Plugin dependency versions
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/plugin-marketplaces" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Stream responses in real-time</title>
  <link>https://code.claude.com/docs/en/agent-sdk/streaming-output</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/agent-sdk/streaming-output</guid>
  <pubDate>Wed, 03 Jan 2024 00:00:00 +0000</pubDate>
  <category>Agent</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Stream responses in real-time
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Stream responses in real-time
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
By default, the Agent SDK yields complete
AssistantMessage
objects after Claude finishes generating each response. To receive incremental updates as text and tool calls are generated, enable partial message streaming by setting
include_partial_messages
(Python) or
includePartialMessages
(TypeScript) to
true
in your options.
This page covers output streaming (receiving tokens in real-time). For input modes (how you send messages), see
Send messages to agents
. You can also
stream responses using the Agent SDK via the CLI
.
​
Enable streaming output
To enable streaming, set
include_partial_messages
(Python) or
includePartialMessages
(TypeScript) to
true
in your options. This causes the SDK to yield
StreamEvent
messages containing raw API events as they arrive, in addition to the usual
AssistantMessage
and
ResultMessage
.
Your code then needs to:
Check each message’s type to distinguish
StreamEvent
from other message types
For
StreamEvent
, extract the
event
field and check its
type
Look for
content_block_delta
events where
delta.type
is
text_delta
, which contain the actual text chunks
The example below enables streaming and prints text chunks as they arrive. Notice the nested type checks: first for
StreamEvent
, then for
content_block_delta
, then for
text_delta
:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_response
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Bash"
,
"Read"
],
)
async
for
message
in
query(
prompt
=
"List the files in my project"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
if
event.get(
"type"
)
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"text_delta"
:
print
(delta.get(
"text"
,
""
),
end
=
""
,
flush
=
True
)
asyncio.run(stream_response())
​
StreamEvent reference
When partial messages are enabled, you receive raw Claude API streaming events wrapped in an object. The type has different names in each SDK:
Python
:
StreamEvent
(import from
claude_agent_sdk.types
)
TypeScript
:
SDKPartialAssistantMessage
with
type: 'stream_event'
Both contain raw Claude API events, not accumulated text. You need to extract and accumulate text deltas yourself. Here’s the structure of each type:
Python
TypeScript
@dataclass
class
StreamEvent
:
uuid:
str
# Unique identifier for this event
session_id:
str
# Session identifier
event: dict[
str
, Any]
# The raw Claude API stream event
parent_tool_use_id:
str
|
None
# Parent tool ID if from a subagent
The
event
field contains the raw streaming event from the
Claude API
. Common event types include:
Event Type
Description
message_start
Start of a new message
content_block_start
Start of a new content block (text or tool use)
content_block_delta
Incremental update to content
content_block_stop
End of a content block
message_delta
Message-level updates (stop reason, usage)
message_stop
End of the message
​
Message flow
With partial messages enabled, you receive messages in this order:
StreamEvent (message_start)
StreamEvent (content_block_start) - text block
StreamEvent (content_block_delta) - text chunks...
StreamEvent (content_block_stop)
StreamEvent (content_block_start) - tool_use block
StreamEvent (content_block_delta) - tool input chunks...
StreamEvent (content_block_stop)
StreamEvent (message_delta)
StreamEvent (message_stop)
AssistantMessage - complete message with all content
... tool executes ...
... more streaming events for next turn ...
ResultMessage - final result
Without partial messages enabled (
include_partial_messages
in Python,
includePartialMessages
in TypeScript), you receive all message types except
StreamEvent
. Common types include
SystemMessage
(session initialization),
AssistantMessage
(complete responses),
ResultMessage
(final result), and a compact boundary message indicating when conversation history was compacted (
SDKCompactBoundaryMessage
in TypeScript;
SystemMessage
with subtype
"compact_boundary"
in Python).
​
Stream text responses
To display text as it’s generated, look for
content_block_delta
events where
delta.type
is
text_delta
. These contain the incremental text chunks. The example below prints each chunk as it arrives:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_text
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
)
async
for
message
in
query(
prompt
=
"Explain how databases work"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
if
event.get(
"type"
)
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"text_delta"
:
# Print each text chunk as it arrives
print
(delta.get(
"text"
,
""
),
end
=
""
,
flush
=
True
)
print
()
# Final newline
asyncio.run(stream_text())
​
Stream tool calls
Tool calls also stream incrementally. You can track when tools start, receive their input as it’s generated, and see when they complete. The example below tracks the current tool being called and accumulates the JSON input as it streams in. It uses three event types:
content_block_start
: tool begins
content_block_delta
with
input_json_delta
: input chunks arrive
content_block_stop
: tool call complete
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_tool_calls
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Read"
,
"Bash"
],
)
# Track the current tool and accumulate its input JSON
current_tool
=
None
tool_input
=
""
async
for
message
in
query(
prompt
=
"Read the README.md file"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
event_type
=
event.get(
"type"
)
if
event_type
==
"content_block_start"
:
# New tool call is starting
content_block
=
event.get(
"content_block"
, {})
if
content_block.get(
"type"
)
==
"tool_use"
:
current_tool
=
content_block.get(
"name"
)
tool_input
=
""
print
(
f
"Starting tool:
{
current_tool
}
"
)
elif
event_type
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"input_json_delta"
:
# Accumulate JSON input as it streams in
chunk
=
delta.get(
"partial_json"
,
""
)
tool_input
+=
chunk
print
(
f
"  Input chunk:
{
chunk
}
"
)
elif
event_type
==
"content_block_stop"
:
# Tool call complete - show final input
if
current_tool:
print
(
f
"Tool
{
current_tool
}
called with:
{
tool_input
}
"
)
current_tool
=
None
asyncio.run(stream_tool_calls())
​
Build a streaming UI
This example combines text and tool streaming into a cohesive UI. It tracks whether the agent is currently executing a tool (using an
in_tool
flag) to show status indicators like
[Using Read...]
while tools run. Text streams normally when not in a tool, and tool completion triggers a “done” message. This pattern is useful for chat interfaces that need to show progress during multi-step agent tasks.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
import
sys
async
def
streaming_ui
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Read"
,
"Bash"
,
"Grep"
],
)
# Track whether we're currently in a tool call
in_tool
=
False
async
for
message
in
query(
prompt
=
"Find all TODO comments in the codebase"
,
options
=
options
):
if
isinstance
(message, StreamEvent):
event
=
message.event
event_type
=
event.get(
"type"
)
if
event_type
==
"content_block_start"
:
content_block
=
event.get(
"content_block"
, {})
if
content_block.get(
"type"
)
==
"tool_use"
:
# Tool call is starting - show status indicator
tool_name
=
content_block.get(
"name"
)
print
(
f
"
\n
[Using
{
tool_name
}
...]"
,
end
=
""
,
flush
=
True
)
in_tool
=
True
elif
event_type
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
# Only stream text when not executing a tool
if
delta.get(
"type"
)
==
"text_delta"
and
not
in_tool:
sys.stdout.write(delta.get(
"text"
,
""
))
sys.stdout.flush()
elif
event_type
==
"content_block_stop"
:
if
in_tool:
# Tool call finished
print
(
" done"
,
flush
=
True
)
in_tool
=
False
elif
isinstance
(message, ResultMessage):
# Agent finished all work
print
(
f
"
\n\n
--- Complete ---"
)
asyncio.run(streaming_ui())
​
Known limitations
Some SDK features are incompatible with streaming:
Extended thinking
: when you explicitly set
max_thinking_tokens
(Python) or
maxThinkingTokens
(TypeScript),
StreamEvent
messages are not emitted. You’ll only receive complete messages after each turn. Note that thinking is disabled by default in the SDK, so streaming works unless you enable it.
Structured output
: the JSON result appears only in the final
ResultMessage.structured_output
, not as streaming deltas. See
structured outputs
for details.
​
Next steps
Now that you can stream text and tool calls in real-time, explore these related topics:
Interactive vs one-shot queries
: choose between input modes for your use case
Structured outputs
: get typed JSON responses from the agent
Permissions
: control which tools the agent can use
Was this page helpful?
Yes
No
Handle approvals and user input
Get structured output from agents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/streaming-output" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Stream responses in real-time
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Input and output
Stream responses in real-time
Agent SDK
Overview
Quickstart
Core concepts
How the agent loop works
Use Claude Code features
Work with sessions
Input and output
Streaming Input
Handle approvals and user input
Stream responses in real-time
Get structured output from agents
Extend with tools
Give Claude custom tools
Connect to external tools with MCP
Scale to many tools with tool search
Subagents in the SDK
Customize behavior
Modifying system prompts
Slash Commands in the SDK
Agent Skills in the SDK
Plugins in the SDK
Control and observability
Configure permissions
Intercept and control agent behavior with hooks
Rewind file changes with checkpointing
Track cost and usage
Observability with OpenTelemetry
Todo Lists
Deployment
Hosting the Agent SDK
Securely deploying AI agents
SDK references
TypeScript SDK
TypeScript V2 (deprecated)
Python SDK
Migration Guide
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
By default, the Agent SDK yields complete
AssistantMessage
objects after Claude finishes generating each response. To receive incremental updates as text and tool calls are generated, enable partial message streaming by setting
include_partial_messages
(Python) or
includePartialMessages
(TypeScript) to
true
in your options.
This page covers output streaming (receiving tokens in real-time). For input modes (how you send messages), see
Send messages to agents
. You can also
stream responses using the Agent SDK via the CLI
.
​
Enable streaming output
To enable streaming, set
include_partial_messages
(Python) or
includePartialMessages
(TypeScript) to
true
in your options. This causes the SDK to yield
StreamEvent
messages containing raw API events as they arrive, in addition to the usual
AssistantMessage
and
ResultMessage
.
Your code then needs to:
Check each message’s type to distinguish
StreamEvent
from other message types
For
StreamEvent
, extract the
event
field and check its
type
Look for
content_block_delta
events where
delta.type
is
text_delta
, which contain the actual text chunks
The example below enables streaming and prints text chunks as they arrive. Notice the nested type checks: first for
StreamEvent
, then for
content_block_delta
, then for
text_delta
:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_response
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Bash"
,
"Read"
],
)
async
for
message
in
query(
prompt
=
"List the files in my project"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
if
event.get(
"type"
)
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"text_delta"
:
print
(delta.get(
"text"
,
""
),
end
=
""
,
flush
=
True
)
asyncio.run(stream_response())
​
StreamEvent reference
When partial messages are enabled, you receive raw Claude API streaming events wrapped in an object. The type has different names in each SDK:
Python
:
StreamEvent
(import from
claude_agent_sdk.types
)
TypeScript
:
SDKPartialAssistantMessage
with
type: 'stream_event'
Both contain raw Claude API events, not accumulated text. You need to extract and accumulate text deltas yourself. Here’s the structure of each type:
Python
TypeScript
@dataclass
class
StreamEvent
:
uuid:
str
# Unique identifier for this event
session_id:
str
# Session identifier
event: dict[
str
, Any]
# The raw Claude API stream event
parent_tool_use_id:
str
|
None
# Parent tool ID if from a subagent
The
event
field contains the raw streaming event from the
Claude API
. Common event types include:
Event Type
Description
message_start
Start of a new message
content_block_start
Start of a new content block (text or tool use)
content_block_delta
Incremental update to content
content_block_stop
End of a content block
message_delta
Message-level updates (stop reason, usage)
message_stop
End of the message
​
Message flow
With partial messages enabled, you receive messages in this order:
StreamEvent (message_start)
StreamEvent (content_block_start) - text block
StreamEvent (content_block_delta) - text chunks...
StreamEvent (content_block_stop)
StreamEvent (content_block_start) - tool_use block
StreamEvent (content_block_delta) - tool input chunks...
StreamEvent (content_block_stop)
StreamEvent (message_delta)
StreamEvent (message_stop)
AssistantMessage - complete message with all content
... tool executes ...
... more streaming events for next turn ...
ResultMessage - final result
Without partial messages enabled (
include_partial_messages
in Python,
includePartialMessages
in TypeScript), you receive all message types except
StreamEvent
. Common types include
SystemMessage
(session initialization),
AssistantMessage
(complete responses),
ResultMessage
(final result), and a compact boundary message indicating when conversation history was compacted (
SDKCompactBoundaryMessage
in TypeScript;
SystemMessage
with subtype
"compact_boundary"
in Python).
​
Stream text responses
To display text as it’s generated, look for
content_block_delta
events where
delta.type
is
text_delta
. These contain the incremental text chunks. The example below prints each chunk as it arrives:
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_text
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
)
async
for
message
in
query(
prompt
=
"Explain how databases work"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
if
event.get(
"type"
)
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"text_delta"
:
# Print each text chunk as it arrives
print
(delta.get(
"text"
,
""
),
end
=
""
,
flush
=
True
)
print
()
# Final newline
asyncio.run(stream_text())
​
Stream tool calls
Tool calls also stream incrementally. You can track when tools start, receive their input as it’s generated, and see when they complete. The example below tracks the current tool being called and accumulates the JSON input as it streams in. It uses three event types:
content_block_start
: tool begins
content_block_delta
with
input_json_delta
: input chunks arrive
content_block_stop
: tool call complete
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
async
def
stream_tool_calls
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Read"
,
"Bash"
],
)
# Track the current tool and accumulate its input JSON
current_tool
=
None
tool_input
=
""
async
for
message
in
query(
prompt
=
"Read the README.md file"
,
options
=
options):
if
isinstance
(message, StreamEvent):
event
=
message.event
event_type
=
event.get(
"type"
)
if
event_type
==
"content_block_start"
:
# New tool call is starting
content_block
=
event.get(
"content_block"
, {})
if
content_block.get(
"type"
)
==
"tool_use"
:
current_tool
=
content_block.get(
"name"
)
tool_input
=
""
print
(
f
"Starting tool:
{
current_tool
}
"
)
elif
event_type
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
if
delta.get(
"type"
)
==
"input_json_delta"
:
# Accumulate JSON input as it streams in
chunk
=
delta.get(
"partial_json"
,
""
)
tool_input
+=
chunk
print
(
f
"  Input chunk:
{
chunk
}
"
)
elif
event_type
==
"content_block_stop"
:
# Tool call complete - show final input
if
current_tool:
print
(
f
"Tool
{
current_tool
}
called with:
{
tool_input
}
"
)
current_tool
=
None
asyncio.run(stream_tool_calls())
​
Build a streaming UI
This example combines text and tool streaming into a cohesive UI. It tracks whether the agent is currently executing a tool (using an
in_tool
flag) to show status indicators like
[Using Read...]
while tools run. Text streams normally when not in a tool, and tool completion triggers a “done” message. This pattern is useful for chat interfaces that need to show progress during multi-step agent tasks.
Python
TypeScript
from
claude_agent_sdk
import
query, ClaudeAgentOptions, ResultMessage
from
claude_agent_sdk.types
import
StreamEvent
import
asyncio
import
sys
async
def
streaming_ui
():
options
=
ClaudeAgentOptions(
include_partial_messages
=
True
,
allowed_tools
=
[
"Read"
,
"Bash"
,
"Grep"
],
)
# Track whether we're currently in a tool call
in_tool
=
False
async
for
message
in
query(
prompt
=
"Find all TODO comments in the codebase"
,
options
=
options
):
if
isinstance
(message, StreamEvent):
event
=
message.event
event_type
=
event.get(
"type"
)
if
event_type
==
"content_block_start"
:
content_block
=
event.get(
"content_block"
, {})
if
content_block.get(
"type"
)
==
"tool_use"
:
# Tool call is starting - show status indicator
tool_name
=
content_block.get(
"name"
)
print
(
f
"
\n
[Using
{
tool_name
}
...]"
,
end
=
""
,
flush
=
True
)
in_tool
=
True
elif
event_type
==
"content_block_delta"
:
delta
=
event.get(
"delta"
, {})
# Only stream text when not executing a tool
if
delta.get(
"type"
)
==
"text_delta"
and
not
in_tool:
sys.stdout.write(delta.get(
"text"
,
""
))
sys.stdout.flush()
elif
event_type
==
"content_block_stop"
:
if
in_tool:
# Tool call finished
print
(
" done"
,
flush
=
True
)
in_tool
=
False
elif
isinstance
(message, ResultMessage):
# Agent finished all work
print
(
f
"
\n\n
--- Complete ---"
)
asyncio.run(streaming_ui())
​
Known limitations
Some SDK features are incompatible with streaming:
Extended thinking
: when you explicitly set
max_thinking_tokens
(Python) or
maxThinkingTokens
(TypeScript),
StreamEvent
messages are not emitted. You’ll only receive complete messages after each turn. Note that thinking is disabled by default in the SDK, so streaming works unless you enable it.
Structured output
: the JSON result appears only in the final
ResultMessage.structured_output
, not as streaming deltas. See
structured outputs
for details.
​
Next steps
Now that you can stream text and tool calls in real-time, explore these related topics:
Interactive vs one-shot queries
: choose between input modes for your use case
Structured outputs
: get typed JSON responses from the agent
Permissions
: control which tools the agent can use
Was this page helpful?
Yes
No
Handle approvals and user input
Get structured output from agents
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/agent-sdk/streaming-output" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
<item>
  <title>Commands</title>
  <link>https://code.claude.com/docs/en/commands</link>
  <guid isPermaLink="false">https://code.claude.com/docs/en/commands</guid>
  <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
  <category>Documentation</category>
  <description><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Commands
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Commands control Claude Code from inside a session. The...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Commands
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Commands control Claude Code from inside a session. They provide a quick way to switch models, manage permissions, clear context, run a workflow, and more.
Type
/
to see every command available to you, or type
/
followed by letters to filter.
A command is only recognized at the start of your message. Text that follows the command name is passed to it as arguments.
​
Commands across a typical workflow
Most commands are useful at a specific point in a session, from setting up a project to shipping a change.
First session in a repo.
Run
/init
to generate a starter
CLAUDE.md
, then
/memory
to refine it. Use
/mcp
and
/agents
to set up any servers or subagents the project needs, and
/permissions
to set the approval rules you want.
During a task.
/plan
switches into plan mode before a large change.
/model
and
/effort
adjust how much reasoning you’re spending. When the conversation gets long,
/context
shows where the window is going and
/compact
summarizes it down; use
/btw
for a quick aside that shouldn’t bloat history.
Running work in parallel.
/agents
opens the manager for the
subagents
Claude can delegate side tasks to, and
/tasks
lists what’s running in the background of the current session.
/background
detaches the whole session to keep running as a
background agent
and frees your terminal. For a large change that spans the codebase,
/batch
decomposes it into independent units and runs each in its own
worktree
. See
Run agents in parallel
for how these approaches relate.
Before you ship.
/diff
shows what changed,
/simplify
reviews recent files and applies quality and efficiency fixes, and
/review
or
/security-review
give a deeper read-only pass.
Between sessions.
/clear
starts fresh on a new task while keeping project memory.
/resume
and
/branch
let you return to or fork an earlier conversation.
/teleport
pulls a web session into this terminal, and
/remote-control
lets you continue this local session from another device.
When something is wrong.
/rewind
rolls code and conversation back to a checkpoint, or summarizes part of the conversation.
/doctor
and
/debug
diagnose install and runtime issues, and
/feedback
reports a bug with session context attached.
​
All commands
The table below lists all the commands included in Claude Code. Entries marked
Skill
are bundled skills. They use the same mechanism as skills you write yourself: a prompt handed to Claude, which Claude can also invoke automatically when relevant. Everything else is a built-in command whose behavior is coded into the CLI. To add your own commands, see
skills
.
In the table below,
<arg>
indicates a required argument and
[arg]
indicates an optional one.
Not every command appears for every user. Availability depends on your platform, plan, and environment. For example,
/desktop
only shows on macOS and Windows, and
/upgrade
only shows on Pro and Max plans.
Command
Purpose
/add-dir <path>
Add a working directory for file access during the current session. Most
.claude/
configuration is
not discovered
from the added directory. You can later resume the session from the added directory with
--continue
or
--resume
/agents
Manage
agent
configurations
/autofix-pr [prompt]
Spawn a
Claude Code on the web
session that watches the current branch’s PR and pushes fixes when CI fails or reviewers leave comments. Detects the open PR from your checked-out branch with
gh pr view
; to watch a different PR, check out its branch first. By default the remote session is told to fix every CI failure and review comment; pass a prompt to give it different instructions, for example
/autofix-pr only fix lint and type errors
. Requires the
gh
CLI and access to
Claude Code on the web
/background [prompt]
Detach the current session to run as a
background agent
and free this terminal. Pass a prompt to send one more instruction before detaching. Monitor the session with
claude agents
. Alias:
/bg
/batch <instruction>
Skill
.
Orchestrate large-scale changes across a codebase in parallel. Researches the codebase, decomposes the work into 5 to 30 independent units, and presents a plan. Once approved, spawns one
background subagent
per unit in an isolated
git worktree
. Each subagent implements its unit, runs tests, and opens a pull request. Requires a git repository. Example:
/batch migrate src/ from Solid to React
/branch [name]
Create a branch of the current conversation at this point. Switches you into the branch and preserves the original, which you can return to with
/resume
. Alias:
/fork
. When
CLAUDE_CODE_FORK_SUBAGENT
is set,
/fork
instead spawns a
forked subagent
and is no longer an alias for this command
/btw <question>
Ask a quick
side question
without adding to the conversation
/chrome
Configure
Claude in Chrome
settings
/claude-api [migrate|managed-agents-onboard]
Skill
.
Load Claude API reference material for your project’s language (Python, TypeScript, Java, Go, Ruby, C#, PHP, or cURL) and Managed Agents reference. Covers tool use, streaming, batches, structured outputs, and common pitfalls. Also activates automatically when your code imports
anthropic
or
@anthropic-ai/sdk
. Run
/claude-api migrate
to upgrade existing Claude API code to a newer model: Claude asks which files to scan and which model to target, then updates model IDs, thinking configuration, and other parameters that changed between versions. Run
/claude-api managed-agents-onboard
for an interactive walkthrough that creates a new Managed Agent from scratch
/clear [name]
Start a new conversation with empty context. The previous conversation stays available in
/resume
. Pass a name to label the previous conversation in the
/resume
picker. To free up context while continuing the same conversation, use
/compact
instead. Aliases:
/reset
,
/new
/color [color|default]
Set the prompt bar color for the current session. Available colors:
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
,
cyan
. Use
default
to reset, or run with no argument to pick a random color. When
Remote Control
is connected, the color syncs to claude.ai/code
/compact [instructions]
Free up context by summarizing the conversation so far. Optionally pass focus instructions for the summary. See
how compaction handles rules, skills, and memory files
/config
Open the
Settings
interface to adjust theme, model,
output style
, and other preferences. Alias:
/settings
/context [all]
Visualize current context usage as a colored grid. Shows optimization suggestions for context-heavy tools, memory bloat, and capacity warnings. In
fullscreen mode
the per-item breakdown is collapsed to keep the grid visible. Pass
all
to expand it
/copy [N]
Copy the last assistant response to clipboard. Pass a number
N
to copy the Nth-latest response:
/copy 2
copies the second-to-last. When code blocks are present, shows an interactive picker to select individual blocks or the full response. Press
w
in the picker to write the selection to a file instead of the clipboard, which is useful over SSH
/cost
Alias for
/usage
/debug [description]
Skill
.
Enable debug logging for the current session and troubleshoot issues by reading the session debug log. Debug logging is off by default unless you started with
claude --debug
, so running
/debug
mid-session starts capturing logs from that point forward. Optionally describe the issue to focus the analysis
/desktop
Continue the current session in the Claude Code Desktop app. macOS and Windows only. Alias:
/app
/diff
Open an interactive diff viewer showing uncommitted changes and per-turn diffs. Use left/right arrows to switch between the current git diff and individual Claude turns, and up/down to browse files
/doctor
Diagnose and verify your Claude Code installation and settings. Results show with status icons. Press
f
to have Claude fix any reported issues
/effort [level|auto]
Set the model
effort level
. Accepts
low
,
medium
,
high
,
xhigh
, or
max
; available levels depend on the model and
max
is session-only.
auto
resets to the model default. Without an argument, opens an interactive slider; use left and right arrows to pick a level and
Enter
to apply. Takes effect immediately without waiting for the current response to finish
/exit
Exit the CLI. In an attached
background session
, this detaches and the session keeps running. Alias:
/quit
/export [filename]
Export the current conversation as plain text. With a filename, writes directly to that file. Without, opens a dialog to copy to clipboard or save to a file
/extra-usage
Configure extra usage to keep working when rate limits are hit
/fast [on|off]
Toggle
fast mode
on or off
/feedback [report]
Submit feedback about Claude Code. Alias:
/bug
/fewer-permission-prompts
Skill
.
Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project
.claude/settings.json
to reduce permission prompts
/focus
Toggle the focus view, which shows only your last prompt, a one-line tool-call summary with edit diffstats, and the final response. The selection persists across sessions; set
viewMode
in settings to override it. Only available in
fullscreen rendering
/goal [condition|clear]
Set a
goal
: Claude keeps working across turns until the condition is met. With no argument, shows the current or most recently achieved goal.
clear
,
stop
,
off
,
reset
,
none
, or
cancel
removes an active goal early
/heapdump
Write a JavaScript heap snapshot and a memory breakdown to
~/Desktop
, or your home directory on Linux without a Desktop folder, for diagnosing high memory usage. See
troubleshooting
/help
Show help and available commands
/hooks
View
hook
configurations for tool events
/ide
Manage IDE integrations and show status
/init
Initialize project with a
CLAUDE.md
guide. Set
CLAUDE_CODE_NEW_INIT=1
for an interactive flow that also walks through skills, hooks, and personal memory files
/insights
Generate a report analyzing your Claude Code sessions, including project areas, interaction patterns, and friction points
/install-github-app
Set up the
Claude GitHub Actions
app for a repository. Walks you through selecting a repo and configuring the integration
/install-slack-app
Install the Claude Slack app. Opens a browser to complete the OAuth flow
/keybindings
Open or create your keybindings configuration file
/login
Sign in to your Anthropic account
/logout
Sign out from your Anthropic account
/loop [interval] [prompt]
Skill
.
Run a prompt repeatedly while the session stays open. Omit the interval and Claude self-paces between iterations. Omit the prompt and Claude runs an autonomous maintenance check, or the prompt in
.claude/loop.md
if present. Example:
/loop 5m check if the deploy finished
. See
Run prompts on a schedule
. Alias:
/proactive
/mcp
Manage MCP server connections and OAuth authentication
/memory
Edit
CLAUDE.md
memory files, enable or disable
auto-memory
, and view auto-memory entries
/mobile
Show QR code to download the Claude mobile app. Aliases:
/ios
,
/android
/model [model]
Select or change the AI model. For models that support it, use left/right arrows to
adjust effort level
. With no argument, opens a picker that asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context. Once confirmed, the change applies without waiting for the current response to finish
/passes
Share a free week of Claude Code with friends. Only visible if your account is eligible
/permissions
Manage allow, ask, and deny rules for tool permissions. Opens an interactive dialog where you can view rules by scope, add or remove rules, manage working directories, and review
recent auto mode denials
. Alias:
/allowed-tools
/plan [description]
Enter plan mode directly from the prompt. Pass an optional description to enter plan mode and immediately start with that task, for example
/plan fix the auth bug
/plugin
Manage Claude Code
plugins
/powerup
Discover Claude Code features through quick interactive lessons with animated demos
/pr-comments [PR]
Removed in v2.1.91. Ask Claude directly to view pull request comments instead. On earlier versions, fetches and displays comments from a GitHub pull request; automatically detects the PR for the current branch, or pass a PR URL or number. Requires the
gh
CLI
/privacy-settings
View and update your privacy settings. Only available for Pro and Max plan subscribers
/radio
Open Claude FM lo-fi radio in your browser. Prints the stream URL when no browser is available. Not available on Bedrock, Vertex, or Foundry
/recap
Generate a one-line summary of the current session on demand. See
Session recap
for the automatic recap that appears after you’ve been away
/release-notes
View the changelog in an interactive version picker. Select a specific version to see its release notes, or choose to show all versions
/reload-plugins
Reload all active
plugins
to apply pending changes without restarting. Reports counts for each reloaded component and flags any load errors
/remote-control
Make this session available for
remote control
from claude.ai. Alias:
/rc
/remote-env
Configure the default remote environment for
web sessions started with
--remote
/rename [name]
Rename the current session and show the name on the prompt bar. Without a name, auto-generates one from conversation history
/resume [session]
Resume a conversation by ID or name, or open the session picker. Alias:
/continue
/review [PR]
Review a pull request locally in your current session. For a deeper cloud-based review, see
/ultrareview
/rewind
Rewind the conversation and/or code to a previous point, or summarize from a selected message. See
checkpointing
. Aliases:
/checkpoint
,
/undo
/sandbox
Toggle
sandbox mode
. Available on supported platforms only
/schedule [description]
Create, update, list, or run
routines
, which execute on Anthropic-managed cloud infrastructure. Claude walks you through the setup conversationally. Alias:
/routines
/scroll-speed
Adjust mouse wheel
scroll speed
interactively, with a ruler you can scroll while the dialog is open to preview the change. Available in
fullscreen rendering
only and not in the JetBrains IDE terminal
/security-review
Analyze pending changes on the current branch for security vulnerabilities. Reviews the git diff and identifies risks like injection, auth issues, and data exposure
/setup-bedrock
Configure
Amazon Bedrock
authentication, region, and model pins through an interactive wizard. Only visible when
CLAUDE_CODE_USE_BEDROCK=1
is set. First-time Bedrock users can also access this wizard from the login screen
/setup-vertex
Configure
Google Vertex AI
authentication, project, region, and model pins through an interactive wizard. Only visible when
CLAUDE_CODE_USE_VERTEX=1
is set. First-time Vertex AI users can also access this wizard from the login screen
/simplify [focus]
Skill
.
Review your recently changed files for code reuse, quality, and efficiency issues, then fix them. Spawns three review agents in parallel, aggregates their findings, and applies fixes. Pass text to focus on specific concerns:
/simplify focus on memory efficiency
/skills
List available
skills
. Press
t
to sort by token count. Press
Space
to
hide a skill from Claude or the
/
menu
, then
Enter
to save
/stats
Alias for
/usage
. Opens on the Stats tab
/status
Open the Settings interface (Status tab) showing version, model, account, and connectivity. Works while Claude is responding, without waiting for the current response to finish
/statusline
Configure Claude Code’s
status line
. Describe what you want, or run without arguments to auto-configure from your shell prompt
/stickers
Order Claude Code stickers
/stop
Stop the current
background session
. Only available while attached to a background session; the transcript and any worktree are kept. To detach without stopping, use
/exit
or press
←
/tasks
List and manage background tasks. Also available as
/bashes
/team-onboarding
Generate a team onboarding guide from your Claude Code usage history. Claude analyzes your sessions, commands, and MCP server usage from the past 30 days and produces a markdown guide a teammate can paste as a first message to get set up quickly. For claude.ai subscribers on Pro, Max, Team, and Enterprise plans, also returns a share link teammates can open directly in Claude Code
/teleport
Pull a
Claude Code on the web
session into this terminal: opens a picker, then fetches the branch and conversation. Also available as
/tp
. Requires a claude.ai subscription
/terminal-setup
Configure terminal keybindings for Shift+Enter and other shortcuts. Only visible in terminals that need it, like VS Code, Cursor, Windsurf, Alacritty, or Zed
/theme
Change the color theme. Includes an
auto
option that matches your terminal’s light or dark background, light and dark variants, colorblind-accessible (daltonized) themes, ANSI themes that use your terminal’s color palette, and any
custom themes
from
~/.claude/themes/
or plugins. Select
New custom theme…
to create one
/tui [default|fullscreen]
Set the terminal UI renderer and relaunch into it with your conversation intact.
fullscreen
enables the
flicker-free alt-screen renderer
. With no argument, prints the active renderer
/ultraplan <prompt>
Draft a plan in an
ultraplan
session, review it in your browser, then execute remotely or send it back to your terminal
/ultrareview [PR]
Run a deep, multi-agent code review in a cloud sandbox with
ultrareview
. Includes 3 free runs on Pro and Max, then requires
extra usage
/upgrade
Open the upgrade page to switch to a higher plan tier
/usage
Show session cost, plan usage limits, and activity stats. See the
cost tracking guide
for subscription-specific details.
/cost
and
/stats
are aliases
/vim
Removed in v2.1.92. To toggle between Vim and Normal editing modes, use
/config
→ Editor mode
/voice [hold|tap|off]
Toggle
voice dictation
, or enable it in a specific mode. Requires a Claude.ai account
/web-setup
Connect your GitHub account to
Claude Code on the web
using your local
gh
CLI credentials.
/schedule
prompts for this automatically if GitHub isn’t connected
​
MCP prompts
MCP servers can expose prompts that appear as commands. These use the format
/mcp__<server>__<prompt>
and are dynamically discovered from connected servers. See
MCP prompts
for details.
​
See also
Skills
: create your own commands
Interactive mode
: keyboard shortcuts, Vim mode, and command history
CLI reference
: launch-time flags
Was this page helpful?
Yes
No
CLI reference
Environment variables
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/commands" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></description>
  <content:encoded><![CDATA[<p style="color:#666;font-size:14px;margin-bottom:16px">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Commands
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Commands control Claude Code from inside a session. The...</p><div style="font-size:16px;line-height:1.8;color:#333">Claude Code Docs
home page
English
Search...
Ctrl
K
Ask AI
Search...
Navigation
Reference
Commands
Reference
CLI reference
Commands
Environment variables
Tools reference
Interactive mode
Checkpointing
Hooks reference
Plugins reference
Channels reference
Glossary
Glossary
Documentation Index
Fetch the complete documentation index at:
https://code.claude.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Commands control Claude Code from inside a session. They provide a quick way to switch models, manage permissions, clear context, run a workflow, and more.
Type
/
to see every command available to you, or type
/
followed by letters to filter.
A command is only recognized at the start of your message. Text that follows the command name is passed to it as arguments.
​
Commands across a typical workflow
Most commands are useful at a specific point in a session, from setting up a project to shipping a change.
First session in a repo.
Run
/init
to generate a starter
CLAUDE.md
, then
/memory
to refine it. Use
/mcp
and
/agents
to set up any servers or subagents the project needs, and
/permissions
to set the approval rules you want.
During a task.
/plan
switches into plan mode before a large change.
/model
and
/effort
adjust how much reasoning you’re spending. When the conversation gets long,
/context
shows where the window is going and
/compact
summarizes it down; use
/btw
for a quick aside that shouldn’t bloat history.
Running work in parallel.
/agents
opens the manager for the
subagents
Claude can delegate side tasks to, and
/tasks
lists what’s running in the background of the current session.
/background
detaches the whole session to keep running as a
background agent
and frees your terminal. For a large change that spans the codebase,
/batch
decomposes it into independent units and runs each in its own
worktree
. See
Run agents in parallel
for how these approaches relate.
Before you ship.
/diff
shows what changed,
/simplify
reviews recent files and applies quality and efficiency fixes, and
/review
or
/security-review
give a deeper read-only pass.
Between sessions.
/clear
starts fresh on a new task while keeping project memory.
/resume
and
/branch
let you return to or fork an earlier conversation.
/teleport
pulls a web session into this terminal, and
/remote-control
lets you continue this local session from another device.
When something is wrong.
/rewind
rolls code and conversation back to a checkpoint, or summarizes part of the conversation.
/doctor
and
/debug
diagnose install and runtime issues, and
/feedback
reports a bug with session context attached.
​
All commands
The table below lists all the commands included in Claude Code. Entries marked
Skill
are bundled skills. They use the same mechanism as skills you write yourself: a prompt handed to Claude, which Claude can also invoke automatically when relevant. Everything else is a built-in command whose behavior is coded into the CLI. To add your own commands, see
skills
.
In the table below,
<arg>
indicates a required argument and
[arg]
indicates an optional one.
Not every command appears for every user. Availability depends on your platform, plan, and environment. For example,
/desktop
only shows on macOS and Windows, and
/upgrade
only shows on Pro and Max plans.
Command
Purpose
/add-dir <path>
Add a working directory for file access during the current session. Most
.claude/
configuration is
not discovered
from the added directory. You can later resume the session from the added directory with
--continue
or
--resume
/agents
Manage
agent
configurations
/autofix-pr [prompt]
Spawn a
Claude Code on the web
session that watches the current branch’s PR and pushes fixes when CI fails or reviewers leave comments. Detects the open PR from your checked-out branch with
gh pr view
; to watch a different PR, check out its branch first. By default the remote session is told to fix every CI failure and review comment; pass a prompt to give it different instructions, for example
/autofix-pr only fix lint and type errors
. Requires the
gh
CLI and access to
Claude Code on the web
/background [prompt]
Detach the current session to run as a
background agent
and free this terminal. Pass a prompt to send one more instruction before detaching. Monitor the session with
claude agents
. Alias:
/bg
/batch <instruction>
Skill
.
Orchestrate large-scale changes across a codebase in parallel. Researches the codebase, decomposes the work into 5 to 30 independent units, and presents a plan. Once approved, spawns one
background subagent
per unit in an isolated
git worktree
. Each subagent implements its unit, runs tests, and opens a pull request. Requires a git repository. Example:
/batch migrate src/ from Solid to React
/branch [name]
Create a branch of the current conversation at this point. Switches you into the branch and preserves the original, which you can return to with
/resume
. Alias:
/fork
. When
CLAUDE_CODE_FORK_SUBAGENT
is set,
/fork
instead spawns a
forked subagent
and is no longer an alias for this command
/btw <question>
Ask a quick
side question
without adding to the conversation
/chrome
Configure
Claude in Chrome
settings
/claude-api [migrate|managed-agents-onboard]
Skill
.
Load Claude API reference material for your project’s language (Python, TypeScript, Java, Go, Ruby, C#, PHP, or cURL) and Managed Agents reference. Covers tool use, streaming, batches, structured outputs, and common pitfalls. Also activates automatically when your code imports
anthropic
or
@anthropic-ai/sdk
. Run
/claude-api migrate
to upgrade existing Claude API code to a newer model: Claude asks which files to scan and which model to target, then updates model IDs, thinking configuration, and other parameters that changed between versions. Run
/claude-api managed-agents-onboard
for an interactive walkthrough that creates a new Managed Agent from scratch
/clear [name]
Start a new conversation with empty context. The previous conversation stays available in
/resume
. Pass a name to label the previous conversation in the
/resume
picker. To free up context while continuing the same conversation, use
/compact
instead. Aliases:
/reset
,
/new
/color [color|default]
Set the prompt bar color for the current session. Available colors:
red
,
blue
,
green
,
yellow
,
purple
,
orange
,
pink
,
cyan
. Use
default
to reset, or run with no argument to pick a random color. When
Remote Control
is connected, the color syncs to claude.ai/code
/compact [instructions]
Free up context by summarizing the conversation so far. Optionally pass focus instructions for the summary. See
how compaction handles rules, skills, and memory files
/config
Open the
Settings
interface to adjust theme, model,
output style
, and other preferences. Alias:
/settings
/context [all]
Visualize current context usage as a colored grid. Shows optimization suggestions for context-heavy tools, memory bloat, and capacity warnings. In
fullscreen mode
the per-item breakdown is collapsed to keep the grid visible. Pass
all
to expand it
/copy [N]
Copy the last assistant response to clipboard. Pass a number
N
to copy the Nth-latest response:
/copy 2
copies the second-to-last. When code blocks are present, shows an interactive picker to select individual blocks or the full response. Press
w
in the picker to write the selection to a file instead of the clipboard, which is useful over SSH
/cost
Alias for
/usage
/debug [description]
Skill
.
Enable debug logging for the current session and troubleshoot issues by reading the session debug log. Debug logging is off by default unless you started with
claude --debug
, so running
/debug
mid-session starts capturing logs from that point forward. Optionally describe the issue to focus the analysis
/desktop
Continue the current session in the Claude Code Desktop app. macOS and Windows only. Alias:
/app
/diff
Open an interactive diff viewer showing uncommitted changes and per-turn diffs. Use left/right arrows to switch between the current git diff and individual Claude turns, and up/down to browse files
/doctor
Diagnose and verify your Claude Code installation and settings. Results show with status icons. Press
f
to have Claude fix any reported issues
/effort [level|auto]
Set the model
effort level
. Accepts
low
,
medium
,
high
,
xhigh
, or
max
; available levels depend on the model and
max
is session-only.
auto
resets to the model default. Without an argument, opens an interactive slider; use left and right arrows to pick a level and
Enter
to apply. Takes effect immediately without waiting for the current response to finish
/exit
Exit the CLI. In an attached
background session
, this detaches and the session keeps running. Alias:
/quit
/export [filename]
Export the current conversation as plain text. With a filename, writes directly to that file. Without, opens a dialog to copy to clipboard or save to a file
/extra-usage
Configure extra usage to keep working when rate limits are hit
/fast [on|off]
Toggle
fast mode
on or off
/feedback [report]
Submit feedback about Claude Code. Alias:
/bug
/fewer-permission-prompts
Skill
.
Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project
.claude/settings.json
to reduce permission prompts
/focus
Toggle the focus view, which shows only your last prompt, a one-line tool-call summary with edit diffstats, and the final response. The selection persists across sessions; set
viewMode
in settings to override it. Only available in
fullscreen rendering
/goal [condition|clear]
Set a
goal
: Claude keeps working across turns until the condition is met. With no argument, shows the current or most recently achieved goal.
clear
,
stop
,
off
,
reset
,
none
, or
cancel
removes an active goal early
/heapdump
Write a JavaScript heap snapshot and a memory breakdown to
~/Desktop
, or your home directory on Linux without a Desktop folder, for diagnosing high memory usage. See
troubleshooting
/help
Show help and available commands
/hooks
View
hook
configurations for tool events
/ide
Manage IDE integrations and show status
/init
Initialize project with a
CLAUDE.md
guide. Set
CLAUDE_CODE_NEW_INIT=1
for an interactive flow that also walks through skills, hooks, and personal memory files
/insights
Generate a report analyzing your Claude Code sessions, including project areas, interaction patterns, and friction points
/install-github-app
Set up the
Claude GitHub Actions
app for a repository. Walks you through selecting a repo and configuring the integration
/install-slack-app
Install the Claude Slack app. Opens a browser to complete the OAuth flow
/keybindings
Open or create your keybindings configuration file
/login
Sign in to your Anthropic account
/logout
Sign out from your Anthropic account
/loop [interval] [prompt]
Skill
.
Run a prompt repeatedly while the session stays open. Omit the interval and Claude self-paces between iterations. Omit the prompt and Claude runs an autonomous maintenance check, or the prompt in
.claude/loop.md
if present. Example:
/loop 5m check if the deploy finished
. See
Run prompts on a schedule
. Alias:
/proactive
/mcp
Manage MCP server connections and OAuth authentication
/memory
Edit
CLAUDE.md
memory files, enable or disable
auto-memory
, and view auto-memory entries
/mobile
Show QR code to download the Claude mobile app. Aliases:
/ios
,
/android
/model [model]
Select or change the AI model. For models that support it, use left/right arrows to
adjust effort level
. With no argument, opens a picker that asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context. Once confirmed, the change applies without waiting for the current response to finish
/passes
Share a free week of Claude Code with friends. Only visible if your account is eligible
/permissions
Manage allow, ask, and deny rules for tool permissions. Opens an interactive dialog where you can view rules by scope, add or remove rules, manage working directories, and review
recent auto mode denials
. Alias:
/allowed-tools
/plan [description]
Enter plan mode directly from the prompt. Pass an optional description to enter plan mode and immediately start with that task, for example
/plan fix the auth bug
/plugin
Manage Claude Code
plugins
/powerup
Discover Claude Code features through quick interactive lessons with animated demos
/pr-comments [PR]
Removed in v2.1.91. Ask Claude directly to view pull request comments instead. On earlier versions, fetches and displays comments from a GitHub pull request; automatically detects the PR for the current branch, or pass a PR URL or number. Requires the
gh
CLI
/privacy-settings
View and update your privacy settings. Only available for Pro and Max plan subscribers
/radio
Open Claude FM lo-fi radio in your browser. Prints the stream URL when no browser is available. Not available on Bedrock, Vertex, or Foundry
/recap
Generate a one-line summary of the current session on demand. See
Session recap
for the automatic recap that appears after you’ve been away
/release-notes
View the changelog in an interactive version picker. Select a specific version to see its release notes, or choose to show all versions
/reload-plugins
Reload all active
plugins
to apply pending changes without restarting. Reports counts for each reloaded component and flags any load errors
/remote-control
Make this session available for
remote control
from claude.ai. Alias:
/rc
/remote-env
Configure the default remote environment for
web sessions started with
--remote
/rename [name]
Rename the current session and show the name on the prompt bar. Without a name, auto-generates one from conversation history
/resume [session]
Resume a conversation by ID or name, or open the session picker. Alias:
/continue
/review [PR]
Review a pull request locally in your current session. For a deeper cloud-based review, see
/ultrareview
/rewind
Rewind the conversation and/or code to a previous point, or summarize from a selected message. See
checkpointing
. Aliases:
/checkpoint
,
/undo
/sandbox
Toggle
sandbox mode
. Available on supported platforms only
/schedule [description]
Create, update, list, or run
routines
, which execute on Anthropic-managed cloud infrastructure. Claude walks you through the setup conversationally. Alias:
/routines
/scroll-speed
Adjust mouse wheel
scroll speed
interactively, with a ruler you can scroll while the dialog is open to preview the change. Available in
fullscreen rendering
only and not in the JetBrains IDE terminal
/security-review
Analyze pending changes on the current branch for security vulnerabilities. Reviews the git diff and identifies risks like injection, auth issues, and data exposure
/setup-bedrock
Configure
Amazon Bedrock
authentication, region, and model pins through an interactive wizard. Only visible when
CLAUDE_CODE_USE_BEDROCK=1
is set. First-time Bedrock users can also access this wizard from the login screen
/setup-vertex
Configure
Google Vertex AI
authentication, project, region, and model pins through an interactive wizard. Only visible when
CLAUDE_CODE_USE_VERTEX=1
is set. First-time Vertex AI users can also access this wizard from the login screen
/simplify [focus]
Skill
.
Review your recently changed files for code reuse, quality, and efficiency issues, then fix them. Spawns three review agents in parallel, aggregates their findings, and applies fixes. Pass text to focus on specific concerns:
/simplify focus on memory efficiency
/skills
List available
skills
. Press
t
to sort by token count. Press
Space
to
hide a skill from Claude or the
/
menu
, then
Enter
to save
/stats
Alias for
/usage
. Opens on the Stats tab
/status
Open the Settings interface (Status tab) showing version, model, account, and connectivity. Works while Claude is responding, without waiting for the current response to finish
/statusline
Configure Claude Code’s
status line
. Describe what you want, or run without arguments to auto-configure from your shell prompt
/stickers
Order Claude Code stickers
/stop
Stop the current
background session
. Only available while attached to a background session; the transcript and any worktree are kept. To detach without stopping, use
/exit
or press
←
/tasks
List and manage background tasks. Also available as
/bashes
/team-onboarding
Generate a team onboarding guide from your Claude Code usage history. Claude analyzes your sessions, commands, and MCP server usage from the past 30 days and produces a markdown guide a teammate can paste as a first message to get set up quickly. For claude.ai subscribers on Pro, Max, Team, and Enterprise plans, also returns a share link teammates can open directly in Claude Code
/teleport
Pull a
Claude Code on the web
session into this terminal: opens a picker, then fetches the branch and conversation. Also available as
/tp
. Requires a claude.ai subscription
/terminal-setup
Configure terminal keybindings for Shift+Enter and other shortcuts. Only visible in terminals that need it, like VS Code, Cursor, Windsurf, Alacritty, or Zed
/theme
Change the color theme. Includes an
auto
option that matches your terminal’s light or dark background, light and dark variants, colorblind-accessible (daltonized) themes, ANSI themes that use your terminal’s color palette, and any
custom themes
from
~/.claude/themes/
or plugins. Select
New custom theme…
to create one
/tui [default|fullscreen]
Set the terminal UI renderer and relaunch into it with your conversation intact.
fullscreen
enables the
flicker-free alt-screen renderer
. With no argument, prints the active renderer
/ultraplan <prompt>
Draft a plan in an
ultraplan
session, review it in your browser, then execute remotely or send it back to your terminal
/ultrareview [PR]
Run a deep, multi-agent code review in a cloud sandbox with
ultrareview
. Includes 3 free runs on Pro and Max, then requires
extra usage
/upgrade
Open the upgrade page to switch to a higher plan tier
/usage
Show session cost, plan usage limits, and activity stats. See the
cost tracking guide
for subscription-specific details.
/cost
and
/stats
are aliases
/vim
Removed in v2.1.92. To toggle between Vim and Normal editing modes, use
/config
→ Editor mode
/voice [hold|tap|off]
Toggle
voice dictation
, or enable it in a specific mode. Requires a Claude.ai account
/web-setup
Connect your GitHub account to
Claude Code on the web
using your local
gh
CLI credentials.
/schedule
prompts for this automatically if GitHub isn’t connected
​
MCP prompts
MCP servers can expose prompts that appear as commands. These use the format
/mcp__<server>__<prompt>
and are dynamically discovered from connected servers. See
MCP prompts
for details.
​
See also
Skills
: create your own commands
Interactive mode
: keyboard shortcuts, Vim mode, and command history
CLI reference
: launch-time flags
Was this page helpful?
Yes
No
CLI reference
Environment variables
Ctrl
+I
Assistant
Responses are generated using AI and may contain mistakes.</div><hr style="margin:24px 0;border:none;border-top:1px solid #eee"/><p style="margin:12px 0 0"><a href="https://code.claude.com/docs/en/commands" style="color:#1890ff;text-decoration:none;font-size:14px">View Original &rarr;</a></p>]]></content:encoded>
</item>
</channel>
</rss>
