llms.txt@02-Claude-Code-CLI · git:20261001.bf1f66b · 2026-10-01 · sha256 fb3f1e67a917f130
llms.txt@02-Claude-Code-CLI git:20261001.bf1f66bF
Immutable. This exact content never changes and is served at /api/v1/blob/fb3f1e67a917f130.
# Claude Code CLI
> Every page below, concatenated. Each section gives the page title, its upstream source and its path in this repository.
---
## Claude Code on the web | Claude Help Center
Source: https://support.claude.com/en/articles/12618689-claude-code-on-the-web
Path: 02-Claude-Code-CLI/12618689-claude-code-on-the-web.md
# Claude Code on the web
March 16, 2026
Claude Code on the web runs Claude Code tasks remotely, working with code from your GitHub repositories. This article explains how it works, when to use it instead of running Claude Code in your terminal or IDE, and what workflows it enables.
## What Claude Code on the web provides
Claude Code on the web lets you delegate tasks to Claude that run without your active supervision. In your browser, you select a GitHub repository, describe what you want done, and Claude works on the task in a remote environment. Once Claude Code has started working on a task, you can leave the page completely; Claude will continue its work. When finished, Claude will automatically create a pull request with changes for you to review.
This feature works with repositories you may not have on your local machine. You can kick off tasks on any GitHub repository you have access to without needing to clone it locally or set up a development environment. This makes it useful for projects you contribute to occasionally or for exploring codebases you're still learning about.
Claude Code for web enables asynchronous development workflows. With Claude Code in your terminal or editor, you typically work synchronously: you make a request, wait for Claude to respond, review the changes, then make another request. Synchronous work like this gives you fine-grained control but requires your attention throughout the process. Claude Code on the web handles this differently: you can assign a larger task, let Claude work independently, and return later to review the completed work.
You can also run multiple tasks in parallel. Since each task runs in its own isolated environment, you can have Claude working on several different issues or repositories simultaneously. Each task proceeds independently and creates its own pull request when complete. More than one task can work on the same repository at the same time.
## How It Works
When you start a task, Claude Code on the web creates an isolated virtual machine for your work. Your GitHub repository is cloned into this environment, which comes pre-configured with common development tools and language ecosystems.
Claude prepares the environment by running any setup commands you've defined in your repository's configuration. This includes installing dependencies, setting up databases, or running other initialization steps your project needs. If your task requires network access, maybe to install packages or fetch data, you can configure the level of internet access the environment has.
Once the environment is ready, Claude begins working on your task. Claude reads your code, makes changes, writes tests, and runs commands to verify the work. You can monitor progress and provide guidance through the web interface if needed.
When Claude completes the task, it pushes the changes to a new branch in your GitHub repository. You receive a notification and can review the changes, then create a pull request directly from the interface. The pull request includes all of Claude's work, ready for your review and any additional changes you want to make.
Each task runs in complete isolation. The virtual machine exists only for that specific task and includes security controls like restricted network access and protected credential handling. Your GitHub authentication is managed through a secure proxy, so credentials never exist directly in the environment where Claude is working.
## When to use Claude Code on the web vs. terminal
Claude Code on the web is a new way of working with Claude Code. Some tasks are well-suited for asynchronous execution on the web, while others will continue to be best run with Claude Code via your terminal or IDE.
### Use Claude Code on the web for:
- **Well-defined tasks with clear requirements:** When you can describe exactly what needs to be done and don't expect to need to steer Claude mid-task, the web interface lets you start the work and return when it's complete.
- **Background work on bug backlogs:** You can assign Claude multiple issues from your backlog and let them run in parallel. Each task proceeds independently, allowing you to tackle several fixes at once without monitoring each one individually.
- **Repositories you don't have locally:** If you need to make changes to a repository you haven't cloned or don't want to set up on your machine, Claude Code on the web handles the environment setup for you.
- **Tasks you want to queue up:** When you have a list of changes to make but don't want to work on them right now, you can start tasks on the web and review the results later. This lets you batch similar work or delegate tasks during times when you're focused on something else.
### Use Claude Code in your terminal/IDE for:
- **Tasks needing frequent course correction:** When you're not sure exactly what the right approach is or expect you'll need to redirect Claude based on what you see, working in your terminal gives you immediate feedback. You can adjust direction as Claude works rather than waiting for a complete result.
- **Exploratory work with unclear requirements:** If you're figuring out how to solve a problem or investigating different approaches, the terminal lets you refine your request as you learn. The back-and-forth helps clarify requirements that weren't obvious at the start.
- **Local development with uncommitted changes:** When you're actively developing and have uncommitted work in your local repository, using Claude Code in your terminal keeps everything in one place. You can iterate quickly on changes without needing to commit or push work that isn't ready yet.
- **Tasks requiring immediate feedback:** If you need to see results quickly and want to iterate rapidly, the terminal provides lower latency. You can watch Claude work in real-time and stop or redirect if something goes wrong early in the process.
## Example Use Cases
### Backend Changes with Test-Driven Development
Let Claude write tests that define the expected behavior, then implement the code to make those tests pass. This works particularly well for backend changes where behavior can be validated through automated testing.
**Example prompt:**
Add rate limiting to the /api/search endpoint.
The rate limiter should:
- Allow 100 requests per minute per API key
- Return 429 status when limit exceeded
- Reset limits after 60 seconds
- Track different API keys independently
Use a TDD approach: write comprehensive tests first, then implement the rate limiting logic to pass them.
**When to use this approach:** This works well on the web because the tests give Claude clear validation criteria to work towards. You don't need to monitor Claude's progress since the tests will catch issues and guide iteration toward a working solution. The self-contained nature of the task, where Claude writes tests then makes them pass, doesn't require your input once started.
**What makes this effective:** Claude can iterate on the implementation without your supervision, using test failures to identify and fix problems. The task runs longer than a simple code change, but you can let it complete in the background. When you review the pull request, both the tests and implementation are ready, and you have confidence the solution works because the tests pass.
### Documentation Updates
Generate or update technical documentation such as README files, API documentation, code comments, or user guides.
**Example prompt:**
Update CHANGELOG.md with all changes since the v2.3.0 release:
- Review commits on main branch since that tag.
- Categorize changes into "Added, "Changed, "Fixed", and "Removed" sections.
- Include the commit hash for each entry.
**When to use this approach:** Changelog updates are well-suited for the web because Claude can review commit history independently and format entries without guidance. The task is tedious to do manually but straightforward enough that Claude can complete it without questions about which commits to include or how to categorize them.
**What makes this effective:** You can delegate the entire changelog update and review the result when complete. Claude reads through commits, extracts meaningful changes, and follows your existing changelog format.
### Refactoring with Clear Scope
Restructure code to improve organization or readability when you can define clear boundaries for the change. This includes extracting code, splitting up large files, or organizing module structure.
**Example prompt:**
The UserService class in /src/services/user.go has 800 lines long.
Split it into three focused services:
- UserAuthService (login/logout/sessions)
- UserProfileService (profile CRUD operations)
- UserPreferencesService (settings/preferences)
Ensure all tests still pass.
**When to use this approach:** Refactoring with clear constraints works well on the web because you can set clear boundaries for Claude to follow. Test suites can provide validation, allowing Claude to verify the refactor didn't break any existing functionality.
**What makes this effective:** The task takes time, but doesn't need your active input once the structure is defined. You can start the refactor and review the organized result later, rather than monitoring Claude as it works through the task. The clear scope means Claude is unlikely to need guidance mid-task.
## Tips for Effective Use
- Consider adding a test suite to your repository so Claude more easily verify that it has successfully completed a task
- Specify success criteria rather than vague goals like "improve" or "fix"
- Define what should change and what should stay the same in your prompt
- Scope tasks with clear boundaries so Claude doesn't need guidance mid-task
- If you're thinking "I'll need to see how this goes first," consider using your terminal instead
- Use "Open in CLI" if you realize mid-task that you need to provide guidance
---
## Use Claude Code with a screen reader - Claude Code Docs
Source: https://code.claude.com/docs/en/accessibility
Path: 02-Claude-Code-CLI/accessibility.md
## On this page
- [Turn on screen reader mode](#turn-on-screen-reader-mode)
- [Turn off screen reader mode](#turn-off-screen-reader-mode)
- [Accessibility settings](#accessibility-settings)
- [What your screen reader hears](#what-your-screen-reader-hears)
- [Jump between turns](#jump-between-turns)
- [Answer menus and prompts](#answer-menus-and-prompts)
- [Hear when Claude Code needs you](#hear-when-claude-code-needs-you)
- [Known limitations](#known-limitations)
- [Report an issue](#report-an-issue)
Interface
# Use Claude Code with a screen reader
Copy pageCopy page
Set up Claude Code for screen readers such as VoiceOver and NVDA, plus settings for screen magnifiers, reduced motion, and colorblind-friendly themes.
Copy pageCopy page
Claude Code has a screen reader mode that replaces its visual terminal interface with plain, linear text. Instead of boxes, progress animations, and in-place redraws, Claude Code prints labeled lines that a screen reader such as VoiceOver or NVDA reads in order. You can hold a full conversation, approve tool permissions, and review output end to end. Screen reader mode is opt-in. If you use a screen magnifier, reduced motion, or a colorblind-friendly theme instead of a screen reader, set `CLAUDE_CODE_ACCESSIBILITY`, `prefersReducedMotion`, or `theme` from the [Accessibility settings](#accessibility-settings) table. Screen reader mode adapts the terminal interface only, so you don’t need it in the VS Code extension’s chat panel. On Claude Code v2.1.236 or later, the extension [announces conversation activity to your screen reader](../03-IDE-Integrations/vs-code.md#use-a-screen-reader) there without any setting.
[](#turn-on-screen-reader-mode)
Turn on screen reader mode
Pick the method that matches how often you use a screen reader:
- For one session: run `claude --ax-screen-reader`.
- For sessions started from one shell: set the `CLAUDE_AX_SCREEN_READER` environment variable to `1`. In Bash or Zsh, run `export CLAUDE_AX_SCREEN_READER=1`. In PowerShell, run `$env:CLAUDE_AX_SCREEN_READER = "1"`. Add that line to your shell profile to keep it for future shells.
- For every session on the machine: add `"axScreenReader": true` to your user [settings file](settings.md). The setting applies in any terminal, including the VS Code integrated terminal.
If you combine methods, Claude Code applies the [`--ax-screen-reader`](cli-reference.md#cli-flags) flag over the [`CLAUDE_AX_SCREEN_READER`](env-vars.md#variables) environment variable, and the variable over the [`axScreenReader`](settings-reference.md#axscreenreader) setting. If you use Claude Code over SSH, set the environment variable or setting on the remote machine where Claude Code runs. The first line Claude Code prints confirms the mode: `[Screen Reader Mode: on via flag]`, `[Screen Reader Mode: on via env]`, or `[Screen Reader Mode: on via settings]`.
[](#turn-off-screen-reader-mode)
Turn off screen reader mode
Reverse whichever method turned the mode on: start without the flag, unset the environment variable, or set `axScreenReader` to `false`. If you set `CLAUDE_AX_SCREEN_READER` to `0`, Claude Code keeps the mode off even when the setting is `true`.
[](#accessibility-settings)
Accessibility settings
The table lists each accessibility option, whether you set it as a flag, an environment variable, or a setting, and what it changes.
| Option | Type | What it changes |
|:-----------------------------------------------------------------------------|:---------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`--ax-screen-reader`](cli-reference.md#cli-flags) | Flag | Screen reader mode for one session. |
| [`CLAUDE_AX_SCREEN_READER`](env-vars.md#variables) | Environment variable | Screen reader mode for sessions started from the shell where you set it. |
| [`axScreenReader`](settings-reference.md#axscreenreader) | Setting | Screen reader mode for every session when `true`. |
| [`CLAUDE_AX_STARTUP_QUIET_MS`](env-vars.md#variables) | Environment variable | How long Claude Code waits after the confirmation line before it draws the first prompt in screen reader mode. Requires Claude Code v2.1.217 or later. |
| [`CLAUDE_AX_PREPARK_MS`](env-vars.md#variables) | Environment variable | How long Claude Code waits, with the cursor at the start of the line, before it writes a new or changed line in screen reader mode. Requires Claude Code v2.1.233 or later. |
| [`CLAUDE_CODE_ACCESSIBILITY`](env-vars.md#variables) | Environment variable | A terminal cursor that stays visible for screen magnifiers such as macOS Zoom when you set it to `1`. The cursor follows the input caret and, on Claude Code v2.1.218 or later, the highlighted row in menus and panels such as `/config` and `/plugin`. |
| [`prefersReducedMotion`](settings-reference.md#prefersreducedmotion) | Setting | Reduced or no spinners, shimmer, and other animations when `true`. |
| [`theme`](settings-reference.md#theme) | Setting | The interface colors, including the colorblind-friendly `dark-daltonized` and `light-daltonized` themes. You can also pick one with [`/theme`](commands.md#all-commands). |
| [`preferredNotifChannel`](settings-reference.md#preferrednotifchannel) | Setting | With the value `"terminal_bell"`, a terminal bell outside screen reader mode when Claude is waiting on you. |
[](#what-your-screen-reader-hears)
What your screen reader hears
In screen reader mode, Claude Code writes flat text:
- No box-drawing characters for the interface chrome
- No color-only cues
- No redraws of content that hasn’t changed. Progress spinners render as static text
- Tables in Claude’s replies read as `Header: value` sentences instead of a box-character grid
Claude Code leaves everything it prints in your terminal’s scrollback, so you can re-read earlier turns with your screen reader’s review commands or your terminal’s search. Claude Code ignores the [`tui` setting](settings-reference.md#tui) in screen reader mode. Apart from the attached background sessions listed under [Known limitations](#known-limitations), it prints scrolling text instead of [fullscreen rendering](fullscreen.md). Claude Code also waits at two points so your screen reader can keep up:
- After Claude Code prints the confirmation line, it waits 3 seconds before it draws the prompt, so your screen reader can finish the line. Press any key to end the wait. To change the length of the wait, set [`CLAUDE_AX_STARTUP_QUIET_MS`](env-vars.md#variables).
- Before Claude Code writes a new or changed line, such as a hint or more of Claude’s reply, it moves the cursor to the start of the line and waits 50 milliseconds. Your screen reader then reads the line from its first character. Characters you type or delete at the end of the input line appear immediately. To change the length of the wait, set [`CLAUDE_AX_PREPARK_MS`](env-vars.md#variables).
Each message in the transcript starts with a label your screen reader announces, naming what it is: your messages, Claude’s replies and thinking, tool activity, errors and warnings, and prompts. The labels are also searchable, so you can jump between sections of the transcript by searching your terminal’s scrollback:
| Label | Meaning |
|:-----------------------|:-----------------------------------------------------------------------------------------------|
| `you:` | Your messages |
| `claude:` | Claude’s replies |
| `thinking:` | Claude’s thinking |
| `tool:` | Tool activity, such as a file edit or a command run |
| `tool error:` | A tool that failed |
| `error:` | An error in the conversation, such as a failed API request |
| `warning:` | A warning from Claude Code, such as a switch to a fallback model |
| `Permission Required:` | A permission prompt waiting for your answer |
| `Cost:` | The session cost summary when Claude Code exits, if your account [shows costs](../17-Billing-Plans/costs.md) |
Claude Code keeps the terminal cursor on the input caret, so your screen reader’s read-current-line command reads the prompt you’re editing. As you type at the end of the input line, or press `Backspace` there, Claude Code writes only the characters that change. Your screen reader echoes only those characters. When you delete a word or a line with one of the [text editing shortcuts](interactive-mode.md#text-editing), Claude Code announces the deleted text:
- Deleting words with `Ctrl+W` or `Alt+D`, or with `Option+Delete` on macOS or `Ctrl+Backspace` on Windows
- Deleting to the start of the line with `Ctrl+U` or `Cmd+Backspace`
- Deleting to the end of the line with `Ctrl+K`
When you cycle [permission modes](permission-modes.md) with `Shift+Tab`, Claude Code announces the permission mode you land on, such as `[plan mode on]` or `[accept edits on]`. Claude Code prints the announcement once and doesn’t repeat it on later redraws.
[](#jump-between-turns)
Jump between turns
Claude Code emits OSC 133 shell-integration markers at turn boundaries, so your terminal’s jump-to-previous-prompt key moves between turns without reading through the whole transcript:
- iTerm2: Cmd+Shift+Up
- VS Code terminal: Ctrl+Up on Windows, Cmd+Up on macOS
- Windows Terminal: no key by default; bind the `scrollToMark` action in its settings
- Kitty and Ghostty: check the terminal’s documentation for its jump-to-prompt key
macOS Terminal doesn’t act on the markers, and Claude Code doesn’t emit them in WezTerm. In those terminals, search the scrollback for the `you:` label instead.
[](#answer-menus-and-prompts)
Answer menus and prompts
In screen reader mode, menus you’d normally navigate with the arrow keys, including permission prompts, become numbered lists. Claude Code announces each option as a numbered line, then a `Select with numbers` prompt that names the valid range. Type the number of the option you want and press Enter.
- Press Escape to cancel a menu whose prompt ends with `or Escape to cancel`.
- If you type a number that isn’t on the list, Claude Code announces the valid range and lets you try again.
The [`/effort`](model-config.md#adjust-effort-level) selector, which is a slider outside screen reader mode, becomes the same kind of numbered list. Yes-or-no prompts ask for a typed answer instead of a two-option menu. Answer `y` or `n` and press Enter. `yes` and `no` also work.
[](#hear-when-claude-code-needs-you)
Hear when Claude Code needs you
In screen reader mode, Claude Code rings the terminal bell when it needs your attention, so you don’t have to keep checking the transcript. The bell rings when:
- Claude finishes a reply
- A prompt or dialog needs your answer, such as a permission prompt
- A tool that ran longer than 5 seconds finishes
The bell is your terminal’s standard alert. To silence it, change the bell setting in your terminal application. Outside screen reader mode, set [`preferredNotifChannel`](settings-reference.md#preferrednotifchannel) to `"terminal_bell"` to get a [similar bell](terminal-config.md#get-a-terminal-bell-or-notification) when Claude is waiting on you.
[](#known-limitations)
Known limitations
Some behaviors aren’t adapted for screen reader mode:
- Screen reader mode doesn’t turn on automatically when a screen reader is running.
- Claude Code doesn’t announce a permission mode change made in any way other than cycling with `Shift+Tab`, such as entering [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) from a command.
- Attaching to a [background session](../09-Agents-Patterns/agent-view.md) with `claude attach` or from agent view enters the terminal’s alternate screen, which has no native scrollback. This is the [same behavior as other attached sessions](fullscreen.md). To get back out, press Left Arrow on an empty prompt, or Ctrl+Z if a dialog has focus.
- Claude Code announces costs in the summary it prints at exit, not per turn.
- Screen reader mode doesn’t change [non-interactive mode](headless.md) with the `-p` flag. Non-interactive mode already writes plain text and remains an alternative for scripting.
[](#report-an-issue)
Report an issue
If something doesn’t work with your screen reader, magnifier, or terminal, open an issue on the [Claude Code issue tracker](https://github.com/anthropics/claude-code/issues) and mention your assistive technology in the title. Include your operating system, terminal application, and assistive technology name and version in the report.
---
## Escalate hard decisions with the advisor tool - Claude Code Docs
Source: https://code.claude.com/docs/en/advisor
Path: 02-Claude-Code-CLI/advisor.md
## On this page
- [When to use the advisor](#when-to-use-the-advisor)
- [Enable the advisor](#enable-the-advisor)
- [Use the /advisor command](#use-the-%2Fadvisor-command)
- [Set advisorModel in settings](#set-advisormodel-in-settings)
- [Use the --advisor flag](#use-the-advisor-flag)
- [Choose an advisor model](#choose-an-advisor-model)
- [Fable advisor and usage credits](#fable-advisor-and-usage-credits)
- [Common model pairings](#common-model-pairings)
- [When Claude consults the advisor](#when-claude-consults-the-advisor)
- [What you see during a session](#what-you-see-during-a-session)
- [Cost](#cost)
- [Impact on prompt caching](#impact-on-prompt-caching)
- [Requirements](#requirements)
- [Turn the advisor off](#turn-the-advisor-off)
- [Compare with related features](#compare-with-related-features)
- [See also](#see-also)
Model and responses
# Escalate hard decisions with the advisor tool
Copy pageCopy page
Pair your main model with a stronger advisor model that Claude consults at key moments during a task.
Copy pageCopy page
The advisor tool is experimental and requires the Anthropic API. It is not available on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry. Behavior, pricing, and availability may change.
The advisor tool lets Claude consult a second, typically stronger model at key moments during a task, such as before committing to an approach, when stuck on a recurring error, or before declaring a task complete. The advisor receives the full conversation, including every tool call and result, and returns guidance that Claude applies before continuing. The advisor runs server-side on Anthropic’s infrastructure as a [server tool](https://code.claude.com/docs/04-API-Reference/Agents-Tools/agents-and-tools-tool-use-advisor-tool-0a75684a7b.md), available to both subscription and API-billed accounts. You choose which model acts as the advisor, and Claude decides when to call it. This page covers how to enable the advisor, which model pairings are accepted, what Claude shows during a consultation, and how advisor usage is billed.
[](#when-to-use-the-advisor)
When to use the advisor
The advisor fits long, multi-step tasks where most turns are routine but plan quality determines the outcome. Examples include large refactors, debugging sessions where an error keeps recurring, and tasks you want independently checked before Claude declares them done. It adds less value on short tasks where there is little to plan, or on work where every turn needs the strongest model. For those, [switch the main model](model-config.md#setting-your-model) instead, or see [how the advisor compares with opusplan and subagents](#compare-with-related-features) for other ways to get a second opinion.
[](#enable-the-advisor)
Enable the advisor
You can set the advisor model in three ways:
- **`/advisor` command**: set or change the advisor mid-session and save it as your default
- **`advisorModel` setting**: configure a persistent default in your [settings file](settings.md)
- **`--advisor` flag**: set the advisor for a single session at launch
Each of these enables the advisor for sessions whose main model [supports it](#choose-an-advisor-model). After the session starts, Claude Code shows an `Advisor Tool (experimental) is on and may use more tokens · /advisor` notification. To stop using the advisor, see [Turn the advisor off](#turn-the-advisor-off). On some plans, Fable as the advisor also needs your one-time [consent to bill Fable usage to usage credits](model-config.md#fable-and-usage-credits). For what happens before you have given that consent, see [Fable advisor and usage credits](#fable-advisor-and-usage-credits).
[](#use-the-/advisor-command)
Use the `/advisor` command
Run `/advisor` without arguments to open a picker listing the available advisor models, or pass the model directly:
```python
/advisor opus
```
The command confirms with `Advisor set to` followed by the advisor model name. Your selection is saved to `advisorModel` in your user settings and persists across sessions, except in the cases the [`advisorModel` entry](settings-reference.md#advisormodel) lists as applying to the current session only. The command also works where there is no terminal picker: in [non-interactive mode](headless.md) with `-p`, in the Agent SDK, in the desktop app, and over [Remote Control](remote-control.md). This requires Claude Code v2.1.260 or later. On those surfaces:
- Run `/advisor` with no argument to print the current advisor model and the aliases it accepts.
- Run `/advisor` with a model, such as `/advisor opus`, to set it.
- Run `/advisor off` to turn it off.
Claude Code doesn’t invoke a saved advisor that your organization’s [`availableModels`](model-config.md#restrict-model-selection) allowlist excludes. To use the advisor, pick an allowed model with `/advisor`. Claude Code still saves an advisor that your current main model doesn’t support. That advisor activates after you switch to a [compatible main model](#choose-an-advisor-model) with [`/model`](model-config.md#setting-your-model). If the API already refused the saved advisor in the current conversation, it stays off until `/clear` or `/compact`, even after you switch models. On some plans, Fable as the advisor also needs your one-time [consent to bill Fable usage to usage credits](model-config.md#fable-and-usage-credits). For what `/advisor fable` does before you have given that consent, see [Fable advisor and usage credits](#fable-advisor-and-usage-credits).
[](#set-advisormodel-in-settings)
Set `advisorModel` in settings
To configure the advisor as a default without opening a session, set it in your settings file:
```python
{
"advisorModel": "opus"
}
```
[](#use-the-advisor-flag)
Use the `--advisor` flag
To set the advisor for a single session without changing your saved setting, launch with the flag:
```python
claude --advisor opus
```
Claude Code uses the flag instead of the `advisorModel` setting for that session. It doesn’t list `--advisor` in `claude --help`. Claude Code exits with an error at launch if:
- The session’s main model doesn’t support the advisor
- The requested model, such as Haiku, can’t act as an advisor
- Your organization’s [`availableModels`](model-config.md#restrict-model-selection) allowlist excludes the requested model
- You requested Fable and your account still requires the [usage-credits consent](#fable-advisor-and-usage-credits)
If you start a [background session](../09-Agents-Patterns/agent-view.md) with `--advisor` and one of these applies, Claude Code starts the session without the advisor instead of exiting.
[](#choose-an-advisor-model)
Choose an advisor model
The advisor must be at least as capable as the main model. The accepted advisors for each main model are:
| Main model | Accepted advisors | Notes |
|------------------------|---------------------------------------------|------------------------------------------------------------------------------------------------|
| Haiku 4.5 | Fable, Opus, Sonnet | Haiku can call the advisor but cannot act as one |
| Sonnet 4.6 | Fable, Opus, Sonnet | |
| Sonnet 5.5 or Sonnet 5 | Fable, Opus 4.7 or later, Sonnet 5 or later | A Sonnet 4.6 advisor is rejected, and the API refuses an Opus 4.6 advisor |
| Opus 4.6 | Fable, Opus, Sonnet 5 or later | A Sonnet 4.6 advisor is rejected |
| Opus 4.7 or Opus 4.8 | Fable, and Opus 4.7 or later | An Opus 4.6 or Sonnet advisor is rejected |
| Opus 5.5 or Opus 5 | Fable, and Opus 5 or later | An Opus 4.6 or Sonnet advisor is rejected, and the API refuses an Opus 4.7 or Opus 4.8 advisor |
| Fable 5 | Fable 5.1 or Fable 5 | An Opus or Sonnet advisor is rejected |
| Fable 5.1 | Fable 5.1 | An Opus or Sonnet advisor is rejected, and the API refuses a Fable 5 advisor |
Fable 5.1 requires Claude Code v2.1.257 or later. Both Fable models require [Fable access](model-config.md#work-with-fable). Set the advisor as `fable`, `opus`, or `sonnet`. These aliases resolve to Claude Code’s built-in default version for each model family, which advances with new Claude Code releases. You can also pass a full model ID such as `claude-opus-5-5`. Subagents inherit the configured advisor and apply the same pairing check against their own model. Claude Code validates the pairing before sending a request, and the API validates it again:
- For an advisor the table lists as rejected, Claude Code doesn’t attach it to the main model’s requests. The `/advisor` command output and a notification show this. Subagents whose own model satisfies the pairing may still use the advisor.
- For an advisor the table lists as refused by the API, Claude Code attaches it and the API refuses it. Claude Code then resends that request without the advisor, and the rest of the conversation runs without one, so you see no error and get no advisor calls. Pick an accepted advisor with `/advisor`; the change takes effect after `/clear` or `/compact` and in new sessions.
- If the main model or the advisor is a model Claude Code does not recognize, the advisor is not attached.
[](#fable-advisor-and-usage-credits)
Fable advisor and usage credits
On some plans, Fable usage bills to usage credits, and Fable as the advisor bills the same way. If your account requires the [one-time consent to bill Fable usage to usage credits](model-config.md#fable-and-usage-credits), Claude Code asks for it when you select a Fable model with `/model` and doesn’t apply Fable as the advisor until you have accepted that consent. Before you have accepted it, Claude Code doesn’t save Fable as the advisor when you type `/advisor fable` or pick Fable in the `/advisor` picker. It points you to `/model fable` instead. With `claude --advisor fable`, Claude Code exits at launch with a message that points to `/model fable`. In a [background session](#use-the-advisor-flag), it starts the session without the advisor instead of exiting. With Fable already saved as your `advisorModel`, Claude Code sends requests without the advisor. In an interactive session whose main model supports the advisor, it also shows a notification that points to `/model fable`. To accept the consent, run `/model fable` and choose to continue on Fable. Claude Code records the consent and [saves Fable as your selected model](model-config.md#default-model-setting). Then select Fable as the advisor.
[](#common-model-pairings)
Common model pairings
Any accepted pairing works. These combinations balance cost against capability in different ways:
| Pairing | When to use |
|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| Sonnet main + Opus advisor | Sonnet handles routine work and escalates planning, ambiguous failures, and completion checks to Opus |
| Sonnet main + Fable advisor | Fable guidance at decision points without running Fable throughout. Requires Fable access |
| Haiku main + Opus advisor | Lowest-cost main model with strong planning. Expect higher cost than Haiku alone but lower than switching the main model to Sonnet or Opus |
| Opus main + Opus advisor | A second Opus reviews the first. Useful for high-stakes tasks where an independent check matters more than cost |
| Fable main + Fable advisor | Highest-capability pairing when Fable is available. Claude Code doesn’t apply an Opus or Sonnet advisor to a Fable main model |
| Sonnet main + Sonnet advisor | A lower-cost second opinion for catching routine oversights |
[](#when-claude-consults-the-advisor)
When Claude consults the advisor
Claude decides when to call the advisor. It tends to consult before committing to an approach, when an error keeps recurring, and before declaring a task done, but the timing is model-driven rather than rule-based. You can ask for a consultation in your prompt the same way you would request any tool, for example `consult the advisor before you continue`. There is no setting to cap or force advisor calls; if you want Claude to consult more or less often during a task, say so in your instructions.
[](#what-you-see-during-a-session)
What you see during a session
When Claude calls the advisor, the transcript shows an `Advising` line with the advisor model name while the call is in progress. When the result returns, the line reports whether the advisor gave guidance:
- **Reviewed**: the line confirms that the advisor has reviewed the conversation. When the advisor returned readable guidance, press `Ctrl+O` to read it.
- **Declined**: the line reads `Advisor declined to advise on this request`. If the advisor gave a reason, press `Ctrl+O` to read it.
- **Unavailable**: the advisor call failed, and the line reads `Advisor unavailable (<error_code>)`, where `<error_code>` is the code the call returned.
Claude generally follows the advisor’s guidance, but adapts when its own evidence contradicts a specific claim: if a recommended step fails when tried, or the file contents contradict the advice, Claude surfaces the conflict rather than following the guidance unconditionally. The advisor always receives the full conversation, and Claude controls the timing. For more control or a different configuration, see [how the advisor compares with subagents and opusplan](#compare-with-related-features).
[](#cost)
Cost
When Claude calls the advisor, the advisor model reads the conversation, so each call consumes tokens at the advisor model’s rates in addition to your main model’s usage. How those advisor tokens are billed depends on how you pay:
- **API billing**: you pay the advisor model’s input and output rates for advisor tokens
- **Subscription plans**: advisor usage counts toward your plan’s usage limits, except that a Fable advisor bills to [usage credits](model-config.md#fable-and-usage-credits) on plans where Fable usage does
If your account requires the usage-credits consent, a Fable advisor bills nothing before you give it, because Claude Code [doesn’t apply the selection](#fable-advisor-and-usage-credits) until then. Claude calls the advisor at decision points rather than on every turn, so pairing a faster main model with a stronger advisor typically costs less than running the stronger model throughout. Advisor usage counts toward the session totals shown by [`/usage`](../17-Billing-Plans/costs.md#track-your-costs). For how advisor tokens are reported in API responses, see [Usage and billing](https://code.claude.com/docs/04-API-Reference/Agents-Tools/agents-and-tools-tool-use-advisor-tool-0a75684a7b.md#usage-and-billing) in the Claude API documentation.
[](#impact-on-prompt-caching)
Impact on prompt caching
Enabling or disabling the advisor mid-session does not invalidate your main model’s [prompt cache](prompt-caching.md). Unlike [switching models](prompt-caching.md#switching-models), toggling `/advisor` keeps the cached prefix intact, and the advisor’s returned guidance is cached as part of the transcript on later turns. The advisor model’s own read of the conversation is not cached. Each advisor call processes the full transcript anew, with no reuse between calls.
[](#requirements)
Requirements
The advisor tool requires all of the following:
- **Anthropic API only**: the advisor is a server-executed tool. It is not available on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry. Through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) configured with `ANTHROPIC_BASE_URL`, availability depends on whether the gateway forwards the request intact to the Anthropic API. If the gateway or its upstream doesn’t recognize the advisor tool, see [Automatic retry and error forwarding](../13-Enterprise-Admin/llm-gateway-protocol.md#automatic-retry-and-error-forwarding) for how Claude Code responds.
- **Supported main model**: Fable, Opus 4.6 or later, Sonnet 4.6 or later, or Haiku 4.5. See [Choose an advisor model](#choose-an-advisor-model) for which advisors each accepts.
- **Feature-flag fetching**: Claude Code turns the advisor on through a feature flag it fetches from Anthropic. In a session where a variable that turns flag fetching off is set, such as `DISABLE_TELEMETRY`, the advisor stays off. See [Features that need feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching).
[](#turn-the-advisor-off)
Turn the advisor off
To stop using the advisor, run `/advisor off` or choose **No advisor** in the `/advisor` picker:
```python
/advisor off
```
To disable the advisor tool entirely, set `CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1`. The `/advisor` command becomes unavailable and any configured `advisorModel` is ignored. The `--advisor` flag is accepted but has no effect. See [Environment variables](env-vars.md).
[](#compare-with-related-features)
Compare with related features
The advisor is one of several ways to combine model strengths. Pick based on when you want a second model involved.
| Approach | When the stronger model runs | How it starts |
|------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| Advisor tool | At decision points mid-task | Claude calls it when it needs guidance |
| [`opusplan`](model-config.md#opusplan-model-setting) | During plan mode when [allowed by `availableModels`](model-config.md#restrict-model-selection), then switches to Sonnet for execution | You enter plan mode |
| [Subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model) with `model` set | For the entire delegated subtask | Claude delegates, or you invoke the subagent |
| [`/model`](model-config.md#setting-your-model) | From the next request onward | You switch models |
[](#see-also)
See also
- [Model configuration](model-config.md): switch models, set effort levels, and use `opusplan`
- [Manage costs effectively](../17-Billing-Plans/costs.md): track token usage across models
- [Advisor tool in the Claude API](https://code.claude.com/docs/04-API-Reference/Agents-Tools/agents-and-tools-tool-use-advisor-tool-0a75684a7b.md): understand the underlying server tool, or use it directly from the Messages API
- [The advisor strategy](https://claude.com/blog/the-advisor-strategy): why pairing a fast main model with a stronger advisor works
---
## Claude Code on Amazon Bedrock - Claude Code Docs
Source: https://code.claude.com/docs/en/amazon-bedrock
Path: 02-Claude-Code-CLI/amazon-bedrock.md
## On this page
- [Prerequisites](#prerequisites)
- [Sign in with Bedrock](#sign-in-with-bedrock)
- [Set up manually](#set-up-manually)
- [1. Submit use case details](#1-submit-use-case-details)
- [2. Configure AWS credentials](#2-configure-aws-credentials)
- [Credential caching and resolution timeout](#credential-caching-and-resolution-timeout)
- [Advanced credential configuration](#advanced-credential-configuration)
- [3. Configure Claude Code](#3-configure-claude-code)
- [4. Pin model versions](#4-pin-model-versions)
- [Map each model version to an inference profile](#map-each-model-version-to-an-inference-profile)
- [Startup model checks](#startup-model-checks)
- [Cross-region inference profile prefixes](#cross-region-inference-profile-prefixes)
- [IAM configuration](#iam-configuration)
- [1M token context window](#1m-token-context-window)
- [Service tiers](#service-tiers)
- [AWS Guardrails](#aws-guardrails)
- [Use the Mantle endpoint](#use-the-mantle-endpoint)
- [Enable Mantle](#enable-mantle)
- [Select a Mantle model](#select-a-mantle-model)
- [Run Mantle alongside the Invoke API](#run-mantle-alongside-the-invoke-api)
- [Route Mantle through a gateway](#route-mantle-through-a-gateway)
- [Mantle environment variables](#mantle-environment-variables)
- [Troubleshooting](#troubleshooting)
- [Authentication loop with SSO and corporate proxies](#authentication-loop-with-sso-and-corporate-proxies)
- [Certificate errors behind a TLS-inspecting proxy](#certificate-errors-behind-a-tls-inspecting-proxy)
- [Region issues](#region-issues)
- [Streaming errors behind a gateway or proxy](#streaming-errors-behind-a-gateway-or-proxy)
- [Zero token counts in /context](#zero-token-counts-in-%2Fcontext)
- [Mantle endpoint errors](#mantle-endpoint-errors)
- [Additional resources](#additional-resources)
Deployment
# Claude Code on Amazon Bedrock
Copy pageCopy page
Learn about configuring Claude Code through Amazon Bedrock, including setup, IAM configuration, and troubleshooting.
Copy pageCopy page
[](#prerequisites)
Prerequisites
Before configuring Claude Code with Amazon Bedrock, ensure you have:
- An AWS account with Amazon Bedrock access enabled
- Access to desired Claude models (for example, Claude Sonnet 4.6) in Amazon 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 Amazon Bedrock credentials, follow [Sign in with Amazon Bedrock](#sign-in-with-bedrock) below. To deploy Claude Code across a team, use the [manual setup](#set-up-manually) steps and [pin your model versions](#4-pin-model-versions) before rolling out.
[](#sign-in-with-bedrock)
Sign in with Bedrock
If you have AWS credentials and want to start using Claude Code through Amazon 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](https://console.aws.amazon.com/bedrock/), 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](#1-submit-use-case-details) for AWS Organizations and [IAM configuration](#iam-configuration) for the permissions your role needs.
2
Start Claude Code and choose Amazon Bedrock
Run `claude`. At the login prompt, select **3rd-party platform**, then **Amazon Bedrock**. If you’re already signed in and see the chat prompt instead, run `/setup-bedrock` to open the wizard. Until `CLAUDE_CODE_USE_BEDROCK=1` is set, Claude Code [hides the command from the command menu](commands.md#how-the-command-menu-matches-what-you-type); type it in full.
3
Follow the wizard prompts
Choose how you authenticate to AWS: an AWS profile detected from your `~/.aws` directory, an Amazon Bedrock API key, an access key and secret, or credentials already in your environment. The wizard asks for 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](settings.md), 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. The model pin step starts from your currently pinned models. The wizard writes to `~/.claude/settings.json`, or to `$CLAUDE_CONFIG_DIR/settings.json` when [`CLAUDE_CONFIG_DIR`](env-vars.md#variables) is set.
[](#set-up-manually)
Set up manually
To configure Amazon 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)
1. Submit use case details
Before you invoke an Anthropic model for the first time, submit use case details. You do this once per AWS account.
1. Ensure you have the right IAM permissions described below
2. Go to the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/)
3. Select an Anthropic model from the **Model catalog**
4. 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](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_PutUseCaseForModelAccess.html). This call requires the `bedrock:PutUseCaseForModelAccess` IAM permission. Approval extends to child accounts automatically.
[](#2-configure-aws-credentials)
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**
```python
aws configure
```
**Option B: Environment variables (access key)**
```python
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)** Replace `your-profile-name` with the name of your AWS profile before running these commands.
```python
aws sso login --profile=your-profile-name
export AWS_PROFILE=your-profile-name
```
Claude Code requests role credentials from the IAM Identity Center region named by the profile’s `sso_region`, which doesn’t need to match the region you run Amazon Bedrock in. In v2.1.207, the Amazon Bedrock region overrode `sso_region`, so a profile whose IAM Identity Center instance is in a different region failed to authenticate with a `Session token not found or invalid` error. **Option D: AWS Management Console credentials**
```python
aws login
```
[Learn more](https://docs.aws.amazon.com/signin/latest/userguide/command-line-sign-in.html) about `aws login`. **Option E: Amazon Bedrock API keys**
```python
export AWS_BEARER_TOKEN_BEDROCK=your-bedrock-api-key
```
Amazon Bedrock API keys provide a simpler authentication method without needing full AWS credentials. [Learn more about Amazon Bedrock API keys](https://aws.amazon.com/blogs/machine-learning/accelerate-ai-development-with-amazon-bedrock-api-keys/).
[](#credential-caching-and-resolution-timeout)
Credential caching and resolution timeout
Claude Code resolves the AWS default credential provider chain once and keeps the resolved credentials in memory. It reuses them until five minutes before they expire, or for one hour when they carry no expiration, so an SSO-backed profile requests credentials from IAM Identity Center about once per credential lifetime. A credential error from the API clears the cache, and the retry resolves fresh credentials. Requires Claude Code v2.1.207 or later. The cache covers every credential option above except an Amazon Bedrock API key, which doesn’t use the provider chain. To resolve the chain on every request instead, set [`CLAUDE_CODE_SKIP_AWS_CRED_CACHE=1`](env-vars.md). Each resolve of the chain times out after 60 seconds. If a step in the chain stalls, for example a `credential_process` helper that waits for input it can’t receive, the request fails with [`AWS default-chain credential resolve timed out`](errors.md#aws-default-chain-credential-resolve-timed-out). If your chain runs an interactive sign-in that legitimately needs longer, such as browser-based SSO with MFA through a wrapper like `aws-vault`, raise the limit in milliseconds with [`CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS`](env-vars.md). Before v2.1.207, a stalled credential resolution left the request waiting indefinitely. Except when you authenticate with an Amazon Bedrock API key, the [setup wizard](#sign-in-with-bedrock) applies the same limit to each AWS call it makes while verifying your credentials, and to the credential lookup before each model check. During credential verification, a check that exceeds it fails with [`Timed out after 60s waiting for AWS`](errors.md#bedrock-setup-verification-timed-out-waiting-for-aws).
[](#advanced-credential-configuration)
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](settings.md) 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 the API 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 Amazon Bedrock account requires cross-account credentials that differ from the ones the default provider chain would resolve.
Before running the `awsAuthRefresh` command, Claude Code makes an STS `GetCallerIdentity` call to confirm that your credentials are actually expired, and skips the command when they still work. Claude Code sends this check through your [proxy configuration](../13-Enterprise-Admin/network-config.md#proxy-configuration), honoring `HTTPS_PROXY` and `NO_PROXY`. Before v2.1.239, Claude Code sent this check directly and hung at startup on networks that only allow egress through a proxy.
##### Example configuration
```python
{
"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. Output is captured silently and not shown to the user. The command must output JSON in this format:
```python
{
"Credentials": {
"AccessKeyId": "value",
"SecretAccessKey": "value",
"SessionToken": "value",
"Expiration": "2026-01-01T00:00:00Z"
}
}
```
The flat output from `aws configure export-credentials --format process` is also accepted, with the same keys at the top level instead of nested under `Credentials`. `Expiration` is optional. When the command returns a valid ISO 8601 `Expiration`, Claude Code caches the credentials until five minutes before that time. Without it, credentials are cached for one hour. When you configure `awsCredentialExport` without `awsAuthRefresh`, Claude Code uses the exported credentials directly and doesn’t re-resolve the AWS default credential provider chain at startup. Requires Claude Code v2.1.206 or later.
[](#3-configure-claude-code)
3. Configure Claude Code
Set the following environment variables to enable Amazon Bedrock:
```python
# Enable Bedrock integration
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_REGION=us-east-1 # optional if your AWS profile already sets a 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 Amazon Bedrock for Claude Code, keep the following in mind:
- You only need to set `AWS_REGION` to override your AWS profile’s region or when your profile has no region. Claude Code resolves the region in this order:
- `AWS_REGION`
- `AWS_DEFAULT_REGION`
- the `region` set on your active AWS profile, read from the AWS shared credentials file first and then the shared config file, matching AWS SDK precedence
- `us-east-1`
If a value from any of these sources isn’t shaped like a region name, Claude Code treats it as unset and continues down the order. For example, Claude Code treats a value containing a slash, dot, or space as unset. The active profile is `AWS_PROFILE` if set, otherwise `default`. Set `AWS_SHARED_CREDENTIALS_FILE` or `AWS_CONFIG_FILE` to point at non-default file paths. Run `/status` to see the resolved region. When the region came from your AWS config files or the default fallback, Claude Code also notes the source in the `/status` output.
- When using Amazon Bedrock, the `/logout` command is unavailable since authentication is handled through AWS credentials.
- The WebSearch tool is not available on Amazon Bedrock. See [WebSearch tool behavior](tools-reference.md#websearch-tool-behavior).
- You can use settings files for environment variables like `AWS_PROFILE` that you don’t want to leak to other processes. See [Settings](settings.md) for more information.
[](#4-pin-model-versions)
4. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as `sonnet` and `opus` resolve to Claude Code’s built-in default for Amazon Bedrock, which can lag the newest release and may not yet be available in your account. Claude Code [falls back](#startup-model-checks) to an earlier or lower-tier model at startup when the default is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Amazon Bedrock model IDs. Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias on Amazon Bedrock resolves to Opus 5.5, and without `ANTHROPIC_DEFAULT_SONNET_MODEL`, the `sonnet` alias resolves to Sonnet 4.5. This example pins each alias to a specific version:
```python
export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'
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 IDs use the `us.` cross-region inference profile prefix. If you use a different region prefix or application inference profiles, adjust accordingly. In AWS GovCloud regions, use the `us-gov.` prefix. To keep the built-in default models and change only their preferred prefix, set [`ANTHROPIC_BEDROCK_REGION_PREFIX`](#cross-region-inference-profile-prefixes) instead of pinning. The difference shows in what the `opus` alias resolves to:
| You set | The `opus` alias resolves to |
|:--------------------------------------------------------------|:--------------------------------------------------------------------------------|
| `ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` | `us.anthropic.claude-opus-4-8`, the exact ID you pinned |
| `ANTHROPIC_BEDROCK_REGION_PREFIX=eu` | `eu.anthropic.claude-opus-5-5`, the built-in default with your preferred prefix |
For current and legacy model IDs, see [Models overview](../20-Models/about-claude-models-overview.md). For the full list of pinning environment variables, see [Model configuration](model-config.md#pin-models-for-third-party-deployments). Claude Code uses these default models when no pinning variables are set:
| Model type | Default model |
|:-----------------|:------------------------------------------------------------------------------------------|
| Primary model | Opus 5.5, for example `us.anthropic.claude-opus-5-5` in a `us-*` region |
| Small/fast model | Sonnet 4.5, for example `us.anthropic.claude-sonnet-4-5-20250929-v1:0` in a `us-*` region |
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Amazon Bedrock, Claude Code uses the default Sonnet model for background tasks because Haiku may not be enabled in every account or region. Two selections change which model carries them:
- When you select a primary model with `--model`, `ANTHROPIC_MODEL`, or the `model` setting, background tasks use that model. When Claude Code starts the session on the model you set with [`ANTHROPIC_DEFAULT_MODEL`](model-config.md#set-a-default-model-for-new-sessions), background tasks use that model too. Setting `ANTHROPIC_DEFAULT_OPUS_MODEL` without `ANTHROPIC_DEFAULT_SONNET_MODEL` also counts as a selection, because the built-in Sonnet model may not be enabled in an account that steers its own Opus.
- To use Haiku for background tasks, set `ANTHROPIC_DEFAULT_HAIKU_MODEL` to a model ID that is available in your account.
Opus models have a higher per-token price than Sonnet models, so a deployment that doesn’t pin a primary model is billed at the Opus rate once it updates to v2.1.207 or later. To keep Sonnet 4.5 as the primary model, set `ANTHROPIC_MODEL` to its full model ID. A deployment that steers the default with `ANTHROPIC_DEFAULT_SONNET_MODEL` and doesn’t set `ANTHROPIC_DEFAULT_OPUS_MODEL` keeps its steered Sonnet model as the default.
Before v2.1.280, the primary model on Amazon Bedrock defaulted to Opus 5 and the `opus` alias resolved to Opus 5 from v2.1.219. On v2.1.207 through v2.1.218, the primary model on Amazon Bedrock defaulted to Opus 4.8 and the `opus` alias resolved to Opus 4.8. Before v2.1.207, the primary model defaulted to Sonnet 4.5, the `opus` alias resolved to Opus 4.6, and background tasks always used the primary model. To customize models further, use one of these methods:
```python
# 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
```
The 1-hour cache TTL is billed at a higher rate than the 5-minute default. See [cache lifetime](prompt-caching.md#cache-lifetime). To set different TTLs for your main conversation and for the requests Claude Code makes outside it, [choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself).
Prompt caching may not be available in all Amazon Bedrock regions. If cache token counts stay at zero, check [supported models, regions, and limits](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html#prompt-caching-models) in the Amazon Bedrock documentation.
[](#map-each-model-version-to-an-inference-profile)
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](settings.md#where-settings-live) instead. This example maps four Opus versions to distinct ARNs so users can switch between them without bypassing your organization’s inference profiles:
```python
{
"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 Amazon Bedrock with the mapped ARN. The same mapping applies when you pass the Anthropic model ID directly through `--model` or `ANTHROPIC_MODEL`. Versions without an override fall back to the built-in Amazon Bedrock model ID or any matching inference profile discovered at startup. Before v2.1.200, `--model` and `ANTHROPIC_MODEL` values reached Amazon Bedrock as-is without going through the override map. See [Override model IDs per version](model-config.md#override-model-ids-per-version) for details on how overrides interact with `availableModels` and other model settings.
[](#startup-model-checks)
Startup model checks
When Claude Code starts with Amazon Bedrock configured, it verifies that the models it intends to use are accessible in your account. 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](settings.md) and restarts Claude Code. Declining is remembered until the next default version change. Pins that point to an [application inference profile ARN](#map-each-model-version-to-an-inference-profile) 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 for the current session and shows a notice. It tries earlier versions of the default model first and, when the default is an Opus model and no Opus version is available, falls back to the default Sonnet model. The fallback is not persisted. Enable the newer model in your Amazon Bedrock account or [pin a version](#4-pin-model-versions) to make the choice permanent. When you start the session on a specific Sonnet or Opus version, for example with `--model`, `ANTHROPIC_MODEL`, or the [`model` setting](settings-reference.md#model), that version acts as the session’s pinned default for the matching `sonnet` or `opus` alias. Claude Code skips the availability check for the built-in default your model replaces and starts on the model you configured, with no fallback notice. Model aliases such as `opus` don’t act as pins, and neither does a model ID Claude Code doesn’t recognize, such as an application inference profile ARN.
[](#cross-region-inference-profile-prefixes)
Cross-region inference profile prefixes
On the Amazon Bedrock [Invoke API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html), Claude Code resolves its built-in default models to [cross-region inference profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html) IDs; to route model versions through your own inference profiles instead, see [Map each model version to an inference profile](#map-each-model-version-to-an-inference-profile). This table shows the prefix Claude Code prefers for each resolved AWS region:
| AWS region | Prefix |
|:--------------------------|:----------|
| `us-gov-*` (AWS GovCloud) | `us-gov.` |
| `us-*` | `us.` |
| `eu-*` | `eu.` |
| `ap-*` | `apac.` |
| All other regions | `global.` |
Set `ANTHROPIC_BEDROCK_REGION_PREFIX` to choose the prefix Claude Code tries first; when Claude Code can check profile availability and finds no matching profile for a model, it falls back as described in the resolution order below. Valid values are `us`, `eu`, `apac`, `jp`, `au`, and `global`. For example, set it to `global` when your account has `global.` profiles enabled but Claude Code would derive a geography-specific one from your AWS region. Requires Claude Code v2.1.224 or later. This example routes the default models through `global.` profiles:
```python
export ANTHROPIC_BEDROCK_REGION_PREFIX=global
# In a us-* region, the primary model now resolves to
# global.anthropic.claude-opus-5-5 instead of us.anthropic.claude-opus-5-5
```
The preferred prefix is a preference, not a guarantee, whether it comes from your region or from the variable. How Claude Code applies it depends on whether it can check profile availability in your account:
- When Claude Code can [list the inference profiles](#iam-configuration) in your account, it resolves each model in this order:
1. The profile with your preferred prefix.
2. Any matching profile, for a model that has no profile with that prefix.
3. The built-in model ID with your preferred prefix, for a model that has no matching profile at all. Claude Code applies this ID without checking availability at this step; the [startup model checks](#startup-model-checks) still cover the session’s default models.
- When profile discovery is unavailable, Claude Code applies the prefix without checking availability. If your account doesn’t have inference profiles with that prefix enabled, requests fail with a 400 error.
Claude Code doesn’t rewrite Amazon Bedrock inference profile IDs or ARNs you configure yourself, or [`modelOverrides`](#map-each-model-version-to-an-inference-profile) values; Anthropic-format model IDs resolve through [the same mapping as the `/model` picker](#map-each-model-version-to-an-inference-profile). Claude Code also ignores the variable in two cases:
- In AWS GovCloud regions, Claude Code always uses `us-gov.`, the only prefix that routes within the GovCloud partition.
- When you set a value that isn’t one of the valid values, Claude Code falls back to the region-derived preferred prefix.
[](#iam-configuration)
IAM configuration
Create an IAM policy with the required permissions for Claude Code:
```python
{
"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](#map-each-model-version-to-an-inference-profile) 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 [Amazon Bedrock IAM documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html).
Create a dedicated AWS account for Claude Code to simplify cost tracking and access control.
[](#1m-token-context-window)
1M token context window
Claude Sonnet 5, Opus 4.6 and later, and Sonnet 4.6 support the [1M token context window](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model) on Amazon Bedrock. Sonnet 5 always runs with the 1M window on both the Invoke API and the [Mantle endpoint](#use-the-mantle-endpoint), with no `[1m]` variant to select. For the other models on the Invoke API, Claude Code automatically enables the extended context window when you select a 1M model variant. The [setup wizard](#sign-in-with-bedrock) 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](model-config.md#pin-models-for-third-party-deployments) for details, including how to use the 1M window without changing the pin.
[](#service-tiers)
Service tiers
[Amazon Bedrock service tiers](https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html) let you trade off cost against latency. Set `ANTHROPIC_BEDROCK_SERVICE_TIER` to `default`, `flex`, or `priority`:
```python
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](https://docs.aws.amazon.com/bedrock/latest/userguide/prov-throughput.html) ARN as the model ID instead of this setting.
[](#aws-guardrails)
AWS Guardrails
[Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) let you implement content filtering for Claude Code. Create a Guardrail in the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/), publish a version, then add the Guardrail headers to your [settings file](settings.md). Enable Cross-Region inference on your Guardrail if you’re using cross-region inference profiles. Example configuration:
```python
{
"env": {
"ANTHROPIC_CUSTOM_HEADERS": "X-Amzn-Bedrock-GuardrailIdentifier: your-guardrail-id\nX-Amzn-Bedrock-GuardrailVersion: 1"
}
}
```
If your organization delivers the guardrail headers through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) policy instead, they count as [settings that need approval](../13-Enterprise-Admin/server-managed-settings.md#environment-variables-and-the-approval-dialog).
[](#use-the-mantle-endpoint)
Use the Mantle endpoint
Mantle is an Amazon Bedrock endpoint that serves Claude models through the native Anthropic API shape rather than the Amazon Bedrock Invoke API. It uses the same [AWS credentials](#2-configure-aws-credentials) and [`awsAuthRefresh` configuration](#advanced-credential-configuration). Mantle has its own IAM actions under the `bedrock-mantle:` prefix, so the `bedrock:` actions in [IAM configuration](#iam-configuration) don’t cover it. Grant your IAM identity `bedrock-mantle:CreateInference` for inference and `bedrock-mantle:CountTokens` for token counting. See [Making inference requests](https://docs.aws.amazon.com/bedrock/latest/userguide/inference.html) and [Counting tokens](https://docs.aws.amazon.com/bedrock/latest/userguide/count-tokens.html) in the AWS documentation, and the [service authorization reference](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonbedrockpoweredbyawsmantle.html) for every Mantle action.
[](#enable-mantle)
Enable Mantle
With AWS credentials already configured, set `CLAUDE_CODE_USE_MANTLE` to route requests to the Mantle endpoint:
```python
export CLAUDE_CODE_USE_MANTLE=1
export AWS_REGION=us-east-1
```
Claude Code constructs the endpoint URL from the AWS region, resolved with the same precedence as [Amazon Bedrock above](#3-configure-claude-code). To override the URL 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)
Select a Mantle model
Mantle uses model IDs prefixed with `anthropic.` and without a version suffix, for example `anthropic.claude-sonnet-5` or `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:
```python
claude --model anthropic.claude-haiku-4-5
```
[](#run-mantle-alongside-the-invoke-api)
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 Amazon Bedrock Invoke API.
```python
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](settings.md). This setting also restricts the picker to the listed entries. Listing `anthropic.claude-haiku-4-5` removes the bare `haiku` alias from the picker, so also list version prefixes or full IDs for the versions you want to keep selectable. The Mantle ID and the `haiku` alias resolve to the same model family, so the merge keeps only the more specific entry. See [Merge behavior](model-config.md#merge-behavior):
```python
{
"availableModels": ["opus", "sonnet", "claude-haiku-4-5", "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](model-config.md#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)
Route Mantle through a gateway
If your organization routes model traffic through a centralized [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) that injects AWS credentials server-side, disable client-side authentication so Claude Code sends requests without SigV4 signatures or `x-api-key` headers:
```python
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)
Mantle environment variables
These variables are specific to the Mantle endpoint. See [Environment variables](env-vars.md) 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 Amazon Bedrock) |
[](#troubleshooting)
Troubleshooting
[](#authentication-loop-with-sso-and-corporate-proxies)
Authentication loop with SSO and corporate proxies
If browser tabs spawn repeatedly when using AWS SSO, remove the `awsAuthRefresh` setting from your [settings file](settings.md). 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`.
[](#certificate-errors-behind-a-tls-inspecting-proxy)
Certificate errors behind a TLS-inspecting proxy
Claude Code applies your [CA certificate store](../13-Enterprise-Admin/network-config.md#ca-certificate-store) configuration to its requests to AWS, including:
- Model discovery
- Token counting
- The STS and SSO role-credential calls that resolve your AWS credentials
- The [setup wizard](#sign-in-with-bedrock)’s credential verification and model checks
For these requests, a corporate root certificate in your OS trust store or `NODE_EXTRA_CA_CERTS` bundle needs no Amazon Bedrock-specific setup. Before v2.1.260, Claude Code applied your CA configuration to these requests only when they went through a configured proxy, and on a direct connection they trusted only the runtime’s default certificate store. Before v2.1.261, the credential lookup behind the setup wizard’s model checks with the **Use credentials already in my environment** option still trusted only the runtime’s default certificate store. Behind a TLS-inspecting proxy whose root certificate is only in the OS store, the affected requests failed with `unable to get local issuer certificate`, or the wizard showed models as `unreachable`, while inference requests succeeded. Update to v2.1.261 or later.
[](#region-issues)
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](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html) ID
Claude Code uses the Amazon Bedrock [Invoke API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html) and does not support the Converse API.
[](#streaming-errors-behind-a-gateway-or-proxy)
Streaming errors behind a gateway or proxy
Amazon Bedrock streams `InvokeModelWithResponseStream` responses in a binary event-stream format with the header `Content-Type: application/vnd.amazon.eventstream`. A gateway or proxy between Claude Code and Amazon Bedrock must forward the response body and its headers, including `Content-Type`, as Amazon Bedrock sent them. If the gateway rewrites `Content-Type` to another value, Claude Code rejects the response with an error that begins `Bedrock streaming response has content-type`, naming the value it received. The common rewrite is `text/event-stream`, from an integration that re-emits the stream as server-sent events. If the gateway drops or blanks the header instead, Claude Code assumes the body is Amazon Bedrock’s event stream and decodes it, so a body the gateway passed through unmodified keeps streaming. If a gateway that drops the header also re-emits the stream as server-sent events, Claude Code can’t decode the body and falls back to a slower non-streaming path on every turn: each response appears only once it is complete instead of streaming in. In that case, set [`CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_DEFAULT=1`](env-vars.md) so Claude Code reads the body as server-sent events instead. To fix the error or the fallback, configure the gateway to forward the `InvokeModelWithResponseStream` response body and its `Content-Type` header unmodified. A gateway that converts the stream to server-sent events is no longer serving the Amazon Bedrock API. If it also accepts Anthropic Messages API requests, connect to it as an [LLM gateway](../13-Enterprise-Admin/llm-gateway-connect.md) with `ANTHROPIC_BASE_URL` instead of `CLAUDE_CODE_USE_BEDROCK`.
[](#zero-token-counts-in-/context)
Zero token counts in /context
The `/context` command counts tokens for each tool group by sending the tool schemas to the Amazon Bedrock count-tokens API. On Claude Code versions before v2.1.196, Amazon Bedrock rejected that request because the schemas carried fields its count-tokens API doesn’t accept, so every tool group showed 0 tokens. Other rows in the breakdown, such as messages and memory files, aren’t affected. Update to v2.1.196 or later.
[](#mantle-endpoint-errors)
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](settings.md). What a `403` from the Mantle endpoint means depends on whether the error names an IAM action:
- If the error names a `bedrock-mantle:` action, grant your IAM identity that action.
- If the error names no action and your credentials are valid, 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 Amazon 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](#run-mantle-alongside-the-invoke-api) so Claude Code routes each request to the endpoint where the model is available.
[](#additional-resources)
Additional resources
- [Amazon Bedrock documentation](https://docs.aws.amazon.com/bedrock/)
- [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/)
- [Amazon Bedrock inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html)
- [Amazon Bedrock token burndown and quotas](https://docs.aws.amazon.com/bedrock/latest/userguide/quotas-token-burndown.html)
- [Claude Code on Amazon Bedrock: Quick Setup Guide](https://builder.aws.com/content/2tXkZKrZzlrlu0KfH8gST5Dkppq/claude-code-on-amazon-bedrock-quick-setup-guide)
- [Claude Code Monitoring Implementation (Amazon Bedrock)](https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/blob/main/assets/docs/MONITORING.md)
---
## Share session output as artifacts - Claude Code Docs
Source: https://code.claude.com/docs/en/artifacts
Path: 02-Claude-Code-CLI/artifacts.md
## On this page
- [When to use an artifact](#when-to-use-an-artifact)
- [What an artifact is not](#what-an-artifact-is-not)
- [Create an artifact](#create-an-artifact)
- [Update an artifact](#update-an-artifact)
- [Find an artifact again](#find-an-artifact-again)
- [Share an artifact](#share-an-artifact)
- [Let someone edit with you](#let-someone-edit-with-you)
- [Read an artifact shared with you](#read-an-artifact-shared-with-you)
- [Collect comments on an artifact](#collect-comments-on-an-artifact)
- [Let Claude reply to comments on its own](#let-claude-reply-to-comments-on-its-own)
- [Pull live data with MCP connectors](#pull-live-data-with-mcp-connectors)
- [How connector calls work for viewers](#how-connector-calls-work-for-viewers)
- [The page shows no live data for a viewer](#the-page-shows-no-live-data-for-a-viewer)
- [Offer a file download](#offer-a-file-download)
- [What you can build](#what-you-can-build)
- [Walk through a change](#walk-through-a-change)
- [Compare alternatives](#compare-alternatives)
- [Tune with interactive controls](#tune-with-interactive-controls)
- [Bring the result back to your session](#bring-the-result-back-to-your-session)
- [Track work in progress](#track-work-in-progress)
- [Improve the visual design](#improve-the-visual-design)
- [Start from a Slides, Design, or Docs template](#start-from-a-slides-design-or-docs-template)
- [Make a slide deck](#make-a-slide-deck)
- [Draft a design canvas](#draft-a-design-canvas)
- [Write a document with Claude Docs](#write-a-document-with-claude-docs)
- [Page constraints](#page-constraints)
- [Availability](#availability)
- [Disable artifacts](#disable-artifacts)
- [Manage artifacts for your organization](#manage-artifacts-for-your-organization)
- [Enable or disable artifacts](#enable-or-disable-artifacts)
- [Control connector calls from artifacts](#control-connector-calls-from-artifacts)
- [Control public sharing](#control-public-sharing)
- [Set a retention policy](#set-a-retention-policy)
- [Review the audit log](#review-the-audit-log)
- [Allowlist the viewer domain](#allowlist-the-viewer-domain)
- [List and delete artifacts with the Compliance API](#list-and-delete-artifacts-with-the-compliance-api)
- [Related resources](#related-resources)
Artifacts
# Share session output as artifacts
Copy pageCopy page
Artifacts turn Claude Code’s work into live, interactive pages on claude.ai that you can keep private, share with your organization, or publish to a public link.
Copy pageCopy page
Artifacts are available on Pro, Max, Team, and Enterprise plans and require a session signed in with [`/login`](../01-Getting-Started/setup.md#authenticate). See [Availability](#availability) for the full set of requirements.
An [artifact](https://claude.com/features/artifacts) is a live, interactive web page that Claude Code publishes from your session to a private URL on claude.ai. You open it in a browser, and it updates in place as the session continues. Share it from the page header when you want someone else to see it too.
[](#when-to-use-an-artifact)
When to use an artifact
Use an artifact when terminal text is the wrong medium for what Claude produced: output that is easier to look at and interact with than to read line by line. Claude builds the page from anything your session can reach, including your codebase and data it pulls through your [connected tools](../06-MCP-Tools/General/mcp.md), so the page can show things that would take paragraphs to describe. For example, ask Claude to:
- Walk a reviewer through a pull request with annotated diffs
- Render a dashboard from data the session already pulled
- Lay out several design or implementation options side by side
- Keep an investigation timeline that fills in while a long task runs
- Send a teammate a link instead of pasting output into Slack
- Publish a status board that [pulls fresh data through MCP connectors](#pull-live-data-with-mcp-connectors) each time someone opens it
See [What you can build](#what-you-can-build) for prompts that match these, and [Pull live data with MCP connectors](#pull-live-data-with-mcp-connectors) for the connector-backed board’s prompt.
[](#what-an-artifact-is-not)
What an artifact is not
An artifact is a capture of work: one self-contained page with no backend, so it can’t serve multiple routes. For a hosted internal tool with a backend, deploy it on your own infrastructure instead. See [Page constraints](#page-constraints) for the full set of limits.
[](#create-an-artifact)
Create an artifact
Claude may publish an artifact on its own when the output suits a page, or you can ask for one directly. To ask, name the feature or describe the visual output you want in plain language. A good candidate is anything easier to see than to read as text, such as an annotated diff, a chart, or a set of options to compare. The prompts below are two examples; see [What you can build](#what-you-can-build) for more patterns.
```python
Make an artifact that walks through this PR with the diff annotated inline.
```
```python
Build a dashboard artifact of last week's deploy failures by service and keep it updated as you investigate.
```
Unless you name a location, Claude writes the page to an HTML or Markdown file in a temporary directory outside your project, then publishes it. Outside [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode), a new artifact that Claude publishes in response to a prompt you type goes through without a permission prompt or classifier review, unless that publish declares runtime capabilities for the page, such as [connector calls](#pull-live-data-with-mcp-connectors) or [file downloads](#offer-a-file-download). In plan mode, Claude Code asks you before the first publish of each artifact. The artifact stays private to you until you [share it](#share-an-artifact). After you share it publicly, Claude Code asks for your approval once per conversation before changing it, or in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) has the classifier review the change. If you turned [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) off, Claude Code asks before the first publish of each artifact, or in auto mode has the classifier review it. After the first publish, Claude prints the URL, and your browser opens to the new page. If you sent the prompt through [Remote Control](remote-control.md) from claude.ai, Claude Desktop, or the Claude mobile app, no tab opens on the machine running the session. The browser opens there the next time Claude publishes the artifact from a prompt you type at the terminal. Press `Ctrl+]` at any time to reopen the session’s most recent artifact. Claude picks the artifact’s title and an emoji, and both appear in your [gallery of artifacts](#share-an-artifact) on claude.ai and in shared links. Claude can also pick a browser-tab icon that matches what the page is, such as a chart or a calendar. Ask Claude for a specific title, emoji, or tab icon if you want one. To stop the browser from opening automatically when a new artifact is published, set `CLAUDE_CODE_ARTIFACT_AUTO_OPEN=0` in your environment. If Claude responds that it cannot publish, or writes a local HTML file without a link, the tool is not enabled for your session. Check the [Availability](#availability) requirements.
[](#update-an-artifact)
Update an artifact
Ask Claude to revise the page, or let a long-running task republish as it makes progress. Claude edits the underlying file and publishes again to the same URL.
```python
Add a per-region breakdown below the summary chart and republish.
```
Anyone with the page open sees the update in place. Each publish becomes a version, and from the **Share** control in the page header you can choose which version viewers see. To update an artifact from a different session, give Claude its URL, or attach it with [`/artifacts`](#find-an-artifact-again). Without either, a new session creates a new artifact instead of updating one.
```python
Update https://claude.ai/code/artifact/5fbea6f3-... with today's numbers.
```
[](#find-an-artifact-again)
Find an artifact again
Run `/artifacts` in Claude Code to list every artifact you own and every artifact shared with you. Select one and press `o` to open it in your browser or `c` to copy its link. Press `Enter` to attach it to the current session; before v2.1.216, `Enter` opened it in your browser. Claude Code reads the list from your claude.ai account, so it works in a new session and after `/clear`, when the link has scrolled out of the terminal. Requires Claude Code v2.1.208 or later.
[](#share-an-artifact)
Share an artifact
A new artifact is visible only to you. To share it, open the artifact in your browser and use the **Share** control in the page header. The header also links to your gallery at [claude.ai/code/artifacts](https://claude.ai/code/artifacts), which lists every artifact you have created. Viewers in your organization can see who published the page: on an artifact shared within your organization, your name is in the title menu, and on a public artifact it’s in the page header for signed-in viewers in your organization. A viewer who opens a public link without signing in, or from outside your organization, sees the label `Content is user-generated and unverified.` instead of your name. Who you can share with depends on your plan:
- **Within your organization**: on Team and Enterprise plans, grant access to specific people in your organization, or to everyone in it. Viewers sign in to claude.ai as members of your organization to see the page.
- **Publicly**: share a link that anyone on the internet can open, with no claude.ai sign-in required. On Team and Enterprise plans, public sharing is off until an Owner [enables it for the organization](#control-public-sharing).
[](#let-someone-edit-with-you)
Let someone edit with you
People you share with are viewers by default: they see each version you publish but can’t change the page. On Team and Enterprise plans, you can also make someone an editor. In the share dialog, add a person and switch their role from **viewer** to **editor**. An editor publishes new versions the same way you [update the artifact from another session](#update-an-artifact): they give Claude the artifact’s URL, or attach it from [`/artifacts`](#find-an-artifact-again), and Claude pulls the current content and republishes with their changes. Everyone with the page open sees each update live.
[](#read-an-artifact-shared-with-you)
Read an artifact shared with you
When someone shares an artifact with you, you can have Claude read it: give Claude its URL, or attach it from [`/artifacts`](#find-an-artifact-again). Claude reads a page someone else wrote the way it reads a web page with [WebFetch](tools-reference.md#webfetch-tool-behavior): it gets a summary of what it asked about rather than the raw page, and the summary reports instructions written into the page instead of relaying them. Claude Code also saves the page’s full source to a local file, which Claude can open when it needs the exact content, such as to republish the artifact as an [editor](#let-someone-edit-with-you).
[](#collect-comments-on-an-artifact)
Collect comments on an artifact
When you share an artifact within your organization, the people you share it with can leave comments on the page, and you can have Claude read those comments and reply to them. You need Claude Code v2.1.221 or later. Claude reads the comments in two cases:
- **You ask Claude to read them**: give Claude the artifact’s URL and ask for the comments. Claude lists each thread and marks the comments someone who can edit the artifact sent to it.
- **Someone who can edit the artifact sends a comment to Claude**: in a thread on the page, they send a comment with **Send to Claude**, or mention `@claude` in one. Either way, they activate the thread.
Claude can reply to or resolve only an activated thread. Other threads stay open until a person resolves them on the page. Viewers see each reply attributed to Claude, via you. If you share an artifact publicly, people whose only access is the public link don’t see its comments and can’t add any. Existing comment threads stay on the artifact, and you and its editors can still read and reply to them. To ask for the comments yourself, give Claude the URL:
```python
Read the comments on https://claude.ai/code/artifact/5fbea6f3-... and make the changes the commenters ask for.
```
If Claude tells you it can’t read comments, confirm your version, your session, and your feature-flag setting:
- You’re running Claude Code v2.1.221 or later.
- You’re not in your first session since you installed Claude Code or upgraded from a version before v2.1.221. In that [first session after an install or upgrade](env-vars.md#first-session-after-an-install-or-upgrade), Claude might not be able to read comments yet; start a new session and ask again.
- You haven’t turned feature-flag fetching off.
[](#let-claude-reply-to-comments-on-its-own)
Let Claude reply to comments on its own
After your session publishes an artifact, Claude Code watches that artifact for comments for as long as the session runs. When someone who can edit the artifact sends a comment to Claude, it reaches your session right away, and Claude can read the thread and reply without you asking. You need Claude Code v2.1.228 or later. If you turned [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) off, Claude Code doesn’t watch for comments. Your [permission mode](permission-modes.md) decides what Claude does when a sent comment arrives:
- **Claude replies on its own**: when your permission mode lets Claude post the reply without asking you, Claude reads the thread and replies, and edits the artifact when the comment asks for a change. You see `Auto-replied to comment thread on Artifact: <name>` or `Auto-edited Artifact: <name> in response to a comment thread`.
- **Claude waits for you**: outside plan mode, when posting the reply would need your approval, you see `Comments are waiting on Artifact: <name>`. Claude then asks you for approval to read the thread, and again to post the reply.
- **Claude pauses in plan mode**: you see `Comments are waiting on Artifact: <name>`, and Claude doesn’t reply until you leave plan mode and ask it to read and reply.
Claude also stops replying on its own to an artifact after it handles 60 sent comments or thread activations on that artifact within an hour. You see `Comments are waiting on Artifact: <name>` once, and Claude picks up again as that hour’s comments age out. Run `/tasks` to see each artifact your session is watching, listed as a live-updates task. You can stop Claude from replying on its own in any of these ways:
- **Press Ctrl+C once at an idle prompt**: Claude pauses replying on every artifact your session is watching. Replies start again after you send your next message.
- **Stop the task in `/tasks`**: Claude stops replying on that artifact until you ask it to resume replies there. Publishing the artifact again doesn’t start replies again, and the stop still applies when you resume the session later.
- **Press `Ctrl+X Ctrl+K` twice within 3 seconds**: the chord that [stops every running background subagent](interactive-mode.md#general-controls) also stops Claude from replying on every artifact for the rest of the session. Asking Claude to resume replies doesn’t undo this stop.
If the service that delivers comments becomes unavailable or stops answering, Claude Code keeps trying to reconnect for a while, then stops watching each artifact your session was watching.
[](#pull-live-data-with-mcp-connectors)
Pull live data with MCP connectors
An artifact can call [MCP connectors](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) each time someone views it, so the page shows current data rather than a snapshot from the session that built it. Connector calls from artifacts are available on Pro, Max, Team, and Enterprise plans and require Claude Code v2.1.209 or later. On earlier versions, Claude publishes the page with whatever data the session gathered while building it. To create a connector-backed page, name the connector and the data you want in your prompt:
```python
Build a dashboard artifact of our open pull requests that pulls the live list through my GitHub connector when the page loads.
```
Claude declares which connectors the page may call as part of publishing, and the page can’t call connectors outside that declaration. Only connectors from your claude.ai account qualify: Claude names them in the declaration, and when someone views the page, each call [runs through the viewing account’s own connection](#how-connector-calls-work-for-viewers) to that connector. Local MCP servers you configure in Claude Code, such as servers from `.mcp.json`, can supply data while Claude builds the page, but the published page can’t call them. The page fetches data when it loads and can refresh on an interval or when a viewer uses a refresh control on the page. Responses are cached in the viewer’s browser, so a reopened page renders from the cached responses immediately, then updates with fresh results.
[](#how-connector-calls-work-for-viewers)
How connector calls work for viewers
When a published page calls a connector, the call uses the account of the person viewing the page, not the account of the person who published it:
- **Each viewer uses their own connectors**: calls go through the viewing account’s connected tools, so two people opening the same dashboard can see different data depending on what their accounts can access. The page never sees anyone’s credentials; claude.ai makes the calls on the page’s behalf.
- **Viewers approve access first**: claude.ai asks each viewer for permission before the page’s first connector call. A viewer who declines, or who hasn’t connected a connector the page uses, still sees the page without its live sections.
- **Actions use the viewer’s account too**: a page can offer controls that invoke connector tools with side effects, such as posting a message or updating an issue. The action goes through the account of whoever selects the control.
When you plan to share a connector-backed page, ask Claude to include a fallback message in each live section that names the connector it needs. A viewer who’s missing the connection then sees what to connect instead of an empty section. You can [share a connector-backed page](#share-an-artifact) within your organization or publicly, as your plan and organization settings allow. Connector calls don’t run for a viewer who opens the public link without signing in to claude.ai, or from outside your organization. That viewer sees the page without its live sections.
[](#the-page-shows-no-live-data-for-a-viewer)
The page shows no live data for a viewer
When a connector-backed page renders but its live sections stay empty for a viewer in your organization, work through these causes:
- **The viewer hasn’t connected the connector**: connectors are per-account, so each viewer needs their own connection to every connector the page calls. They can add one under **Settings \> Connectors** on claude.ai, then reload the page.
- **The viewer declined the permission ask**: a denial lasts for the rest of that page load. Reloading the page brings the permission ask back.
- **Connector calls are turned off for the organization**: an Owner controls the [**Enable artifact connectors** toggle](#control-connector-calls-from-artifacts) in admin settings.
- **The page calls tool names the connector doesn’t expose**: the affected sections stay empty for everyone, including you. This can happen when a page names the individual tools behind a gateway-style connector that exposes only a few tools of its own. Ask Claude to fix the tool names the page calls and publish it again. When Claude publishes the page and that connector’s tools are available in your session, Claude Code checks the tool names the page declares against them, warns Claude about names that don’t match, and refuses the publish when none do. Before v2.1.265, it published the page without checking them.
[](#offer-a-file-download)
Offer a file download
An artifact can offer viewers a file the page generates, such as a CSV export of a table or a PNG of a chart. The viewer saves it through a download control on the page, such as a button. File downloads are a runtime capability that claude.ai enables per account, so Claude checks whether your account has it before it builds the control. Viewers can’t save a file from an ordinary download link or a script on the page, because the artifact viewer on claude.ai blocks any download the page starts itself, including links to `data:` or `blob:` URLs. If a page has download buttons built that way, ask Claude to rebuild them with the downloads capability. To offer a file, ask for the control and the file format in your prompt:
```python
Add a button that downloads this table as a CSV file.
```
Claude declares the downloads capability as part of publishing, the same way it [declares connectors](#pull-live-data-with-mcp-connectors).
[](#what-you-can-build)
What you can build
An artifact is a single HTML page, so anything you can express in HTML, CSS, and inline JavaScript is in scope. The patterns below come up most often.
[](#walk-through-a-change)
Walk through a change
Ask for a page that renders a diff or a design change with annotations beside the relevant lines, so reviewers can read your reasoning next to the code instead of reconstructing it from a description.
```python
Make an artifact that walks through this PR. Render the diff with margin annotations and color-code findings by severity.
```
[](#compare-alternatives)
Compare alternatives
Ask for several variants on one page so you can evaluate them against each other. This works for layouts, copy, API shapes, or implementation plans.
```python
Make an artifact with four distinctly different layouts for the settings panel. Vary density and grouping, and lay them out as a grid with a one-line tradeoff under each.
```
[](#tune-with-interactive-controls)
Tune with interactive controls
Ask for sliders, toggles, or input fields bound to whatever you are adjusting, so you can explore values directly instead of describing them.
```python
Build an artifact with sliders for the easing curve, duration, and delay so I can try values on this transition. Show the animation live as I move them.
```
[](#bring-the-result-back-to-your-session)
Bring the result back to your session
An artifact can act as a lightweight editor for a decision you then send back to Claude. Ask for an export control that produces text you can paste into the terminal, so the result of interacting with the page flows back into the session instead of staying on the page.
```python
Make a triage board artifact with each open issue as a draggable card across Now, Next, Later, and Cut columns. Add a "Copy as prompt" button that gives me the final ordering to paste back here.
```
[](#track-work-in-progress)
Track work in progress
Ask Claude to keep an artifact current while a long task runs, so anyone with the link can follow along without reading the terminal.
```python
Turn this migration plan into a checklist artifact. Check items off as you complete them and add a note for anything you skip.
```
[](#improve-the-visual-design)
Improve the visual design
Claude applies a built-in design skill when it builds an artifact, so pages get a deliberate palette, typography, and layout without extra prompting. That skill also looks for an existing design system in your project before choosing its own. Design tokens are the named color, typography, and spacing values your design system reuses. To keep artifacts consistent with your product’s branding, record them where Claude can find them, such as the project’s [CLAUDE.md](memory.md) or a theme file in your repository:
```python
## Design system
- Colors: primary #1a4d8f, accent #f59e0b, surface #f8fafc
- Typography: Inter for body, JetBrains Mono for code
- Spacing: 8px scale, 6px border radius
```
Claude treats your design system as higher precedence than its own choices, and your prompt as higher precedence than both. The heading and format above are an example; any clear list of colors, fonts, and spacing works. For typography, Claude can load a typeface from Google Fonts, the one external font source an artifact page can load from. Claude inlines any other typeface as a `@font-face` data URI and gives every typeface a fallback stack, so the page still renders if a font doesn’t load. To use a specific typeface, name it in your prompt or your design system.
[](#start-from-a-slides-design-or-docs-template)
Start from a Slides, Design, or Docs template
Instead of building a page from scratch, Claude can start an artifact from one of the templates on your claude.ai account: [Claude Slides](../15-Claude-AI-Features/what-are-artifacts-and-how-do-i-use-them.md#h_11d5a9a5fa) for a presentation, [Claude Design](https://support.claude.com/en/articles/14604416-get-started-with-claude-design) for a visual design, or [Claude Docs](https://support.claude.com/en/articles/16923645-get-started-with-claude-docs) for a document other people will read and edit. Each opens in its own editor on claude.ai, where you and your teammates change it directly or ask Claude to, and export it to formats such as PowerPoint, PDF, or Word. To start from a template, describe what you want, such as “turn the migration notes into a deck for Thursday’s review” or “write this plan up as a doc for the team”. Claude picks the matching template, fills it from your request and from what the session already has, and gives you the link. For a deck or a design you can also run `/slides` or `/design` with a brief.
Templates are in beta. They’re on by default on Pro, Max, and Team plans. On Enterprise plans, an Owner [turns each template on](https://support.claude.com/en/articles/16994751-artifacts-admin-guide-for-team-and-enterprise-plans) under **Organization settings \> Artifacts**. If your organization has the Slides template turned off, `/slides` doesn’t appear; if it has the Design template turned off, `/design` doesn’t draft designs. Both commands require Claude Code v2.1.265 or later and a session where [artifacts are available](#availability).
[](#make-a-slide-deck)
Make a slide deck
Run `/slides` with a brief that says what the deck covers and who it’s for:
```python
/slides a quarterly review of the platform team's reliability work, for the engineering all-hands
```
Claude creates a Claude Slides artifact and gives you the link. Open it in a desktop browser to edit or present the deck. If you run `/slides` without a brief, Claude asks what the deck should be about before creating anything.
[](#draft-a-design-canvas)
Draft a design canvas
To mock up a UI, a screen flow, a landing page, or a poster rather than build a page, run `/design` with a brief. Claude drafts the design as artboards on one canvas and publishes the canvas as a Claude Design artifact. The brief names what you want drawn:
```python
/design a settings screen for a mobile banking app
```
Open the published artifact in a desktop browser to review the artboards. Select an element on an artboard and change it, and your edits save automatically. You can export each artboard as PNG or PDF.
[](#write-a-document-with-claude-docs)
Write a document with Claude Docs
Claude Docs reaches Claude Code as a claude.ai [connector](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) rather than a command. When it’s connected, `/mcp` lists it as `claude.ai Claude Docs`. A request for a document meant for other people then goes to Claude Docs instead of an artifact page: a spec, a proposal, or a write-up of the plan you worked through in the session. Claude gives you the doc’s link when it’s drafted. A document that belongs in the codebase, such as a README, stays a file. To get a file for something Claude would otherwise put in Claude Docs, name the format, such as `.docx` or a Markdown file in the repository. To turn the connector off, add `claude.ai Claude Docs` to `deniedMcpServers` or use the `/mcp` toggle, both described in [Disable claude.ai connectors](../06-MCP-Tools/General/mcp.md#disable-claude-ai-connectors).
[](#page-constraints)
Page constraints
Each artifact is one self-contained page. Claude Code wraps the file you publish in an HTML document shell and serves it under a strict Content Security Policy (CSP), which shapes what the page can do.
| Constraint | Effect |
|:------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| External requests | The page can load typefaces from Google Fonts, and scripts from [five public CDN hosts](#allowlist-the-viewer-domain): cdnjs, unpkg, the Tailwind and jQuery CDNs, and selected paths on jsDelivr such as `/npm/`. The CSP blocks every external image and all other external scripts, stylesheets, and fonts, and lets `fetch`, XHR, and WebSocket calls reach only the page’s own origin and the Google Fonts hosts. Claude therefore loads any library the page needs from one of those CDNs, inlines all other CSS and JavaScript, and embeds images as data URIs. [Connector calls](#pull-live-data-with-mcp-connectors) go through claude.ai, which makes the network call itself. |
| No backend | An artifact is a static page. It can’t authenticate viewers itself. |
| Downloads | The page can’t start a download itself. To let viewers save a file the page generates, Claude declares the downloads capability. See [Offer a file download](#offer-a-file-download). |
| Single page | Relative links do not resolve, because nothing is deployed alongside the page. For multi-section content, Claude uses in-page anchors rather than separate files. |
| Source file types | The published file must be `.html`, `.htm`, or `.md`, and must decode as UTF-8, or as little-endian UTF-16 by its byte-order mark. Markdown files render as styled document pages with syntax-highlighted code. A file that doesn’t decode, or that contains the replacement character `U+FFFD`, is [refused with the line and column to fix](errors.md#the-source-file-is-not-valid-utf-8-text). |
| Rendered size | The rendered page must be 16 MiB or smaller. Large embedded images are the usual cause when a publish fails for size. |
Generating an artifact uses output tokens like any other response, and a styled page is more token-intensive than the same content as terminal text. Inline CSS, JavaScript for interactive controls, and especially images embedded as data URIs are the main contributors. To reduce an artifact’s token cost:
- Prefer SVG, or HTML and CSS, for diagrams over embedded raster images
- Omit interactivity you do not need
- Have the page summarize large datasets rather than inline them in full
[](#availability)
Availability
Artifacts require every condition below. When one is not met, Claude writes a local HTML file or says it cannot publish instead.
| Requirement | Available when |
|:--------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plan | Pro, Max, Team, or Enterprise. On Pro and Max plans, artifacts are private to you until you share them, and no admin management applies. On Team and Enterprise plans, artifacts are on by default, and an Owner can [turn them off for the organization](#manage-artifacts-for-your-organization) in claude.ai admin settings. |
| Authentication | The session is backed by a claude.ai account: sign in with `/login` in the CLI or desktop app. Claude Tag sessions are signed in through the agent’s identity, so no step is needed there. Sessions using an API key, [gateway token](../13-Enterprise-Admin/llm-gateway.md), or cloud-provider credential cannot publish. |
| Model provider | Anthropic API. Not available on [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md). |
| Organization policy | Customer-managed encryption keys (CMEK), HIPAA, and [Zero Data Retention](zero-data-retention.md) are not enabled for the organization. |
| Surface | Claude Code CLI, or the Claude desktop app version 1.13576.0 or later. [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions can also publish artifacts when both Claude Tag and artifacts are enabled for the organization. Off by default in [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), GitHub Action, and MCP-server contexts, and when [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](env-vars.md) is set. |
Whether artifacts are allowed for your organization comes from your organization’s policy, which Claude Code loads from `api.anthropic.com`. When Claude Code can’t load the policy, artifacts are unavailable. When you ask for one, Claude says why. If a proxy, VPN, or web filter is involved, ask your IT admin to let `api.anthropic.com` through. Claude Code keeps retrying in the background, and artifacts become available once the policy loads and allows them.
[](#disable-artifacts)
Disable artifacts
To turn artifacts off for your own sessions regardless of your organization’s setting, use any of:
| Where | What to do |
|:------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
| [`/config`](commands.md) | Turn the **Artifacts** row off, which writes [`"enableArtifact": false`](settings-reference.md#enableartifact) to your user settings |
| [Settings file](settings.md) | Set `"enableArtifact": false`. The deprecated `"disableArtifact": true` also turns artifacts off |
| [Environment variable](env-vars.md) | Set `CLAUDE_CODE_DISABLE_ARTIFACT=1` |
| [Permission rule](permissions.md) | Add `Artifact` to `permissions.deny` |
Once you turn artifacts off in a [`--settings`](cli-reference.md#cli-flags) file or with `CLAUDE_CODE_DISABLE_ARTIFACT`, or your administrator turns them off in [managed settings](../13-Enterprise-Admin/server-managed-settings.md), no settings file turns them back on. Before v2.1.242, a file higher in the [precedence stack](settings.md#settings-precedence) could turn artifacts back on even when a lower-precedence file set `"enableArtifact": false`. You can also set `"enableArtifact": false` in a project’s `.claude/settings.json` or `.claude/settings.local.json` to turn artifacts off for sessions in that project. An `"enableArtifact": true` in either file doesn’t turn them back on. Honoring the key in project and local settings requires Claude Code v2.1.242 or later. If you add a `WebFetch` deny or ask rule with no `domain:` part, it doesn’t turn artifacts off or block artifact reads. A [`WebFetch(domain:claude.ai)` rule in `deny` or `ask` does apply to artifact reads](permissions.md#allow-or-deny-every-fetch).
[](#manage-artifacts-for-your-organization)
Manage artifacts for your organization
Owners on Team and Enterprise plans control artifacts from [claude.ai admin settings](https://claude.ai/admin-settings/artifacts). Artifact content is stored on Anthropic-operated infrastructure and is visible only to authenticated members of the publishing organization and the people they share it with, unless the artifact is [shared publicly](#control-public-sharing).
[](#enable-or-disable-artifacts)
Enable or disable artifacts
To enable or disable artifacts for the whole organization, go to [**Organization settings \> Artifacts**](https://claude.ai/admin-settings/artifacts) and use the **Artifacts** toggle. On Enterprise plans with role-based access control, you can additionally scope artifacts to specific roles: go to [**Organization settings \> Roles**](https://claude.ai/admin-settings/roles), edit a role, and set the **Artifacts** permission.
[](#control-connector-calls-from-artifacts)
Control connector calls from artifacts
[Connector calls from artifacts](#pull-live-data-with-mcp-connectors) have their own toggle, separate from the **Artifacts** toggle that turns artifacts on or off. Go to [**Organization settings \> Capabilities**](https://claude.ai/admin-settings/capabilities) and use the **Enable artifact connectors** toggle. The same toggle governs connector calls from artifacts created in claude.ai conversations.
[](#control-public-sharing)
Control public sharing
Public sharing is off by default on Team and Enterprise plans. To let members publish artifacts to public links that anyone can view without signing in, go to [**Organization settings \> Artifacts**](https://claude.ai/admin-settings/artifacts) and turn on **External sharing** under the **Artifacts** toggle. Turning it back off blocks access through existing public links without changing each artifact’s audience; access resumes if you re-enable it.
[](#set-a-retention-policy)
Set a retention policy
To set how long artifacts are kept before automatic deletion, go to [**Organization settings \> Data and privacy**](https://claude.ai/admin-settings/data-privacy-controls). You can set separate retention periods for artifacts that are still private to their author and artifacts that have been shared.
[](#review-the-audit-log)
Review the audit log
Publishing, sharing, and deleting an artifact each appear in your organization’s audit log under the `claude_artifact_*` event types, the same family used for artifacts created in claude.ai conversations.
[](#allowlist-the-viewer-domain)
Allowlist the viewer domain
The viewer on claude.ai loads each artifact from a sandboxed `*.claudeusercontent.com` origin. If your organization restricts outbound network access, add that domain to your allowlist alongside `claude.ai`. See [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements) for the full list. An artifact that loads a typeface from [Google Fonts](#improve-the-visual-design) also requests `fonts.googleapis.com` and `fonts.gstatic.com`. Both hosts are optional. If you block them, artifacts render in fallback typefaces. Block with a fast rejection rather than a silent drop so the font request fails immediately instead of delaying the page’s first render. Artifacts can also load JavaScript libraries, such as React or a charting package, from `cdnjs.cloudflare.com`, `cdn.jsdelivr.net`, `cdn.tailwindcss.com`, `code.jquery.com`, and `unpkg.com`, and from no other external host. If you block those hosts, the parts of an artifact that depend on a library don’t work, and unlike a blocked font, a blocked library has no fallback. Block with a fast rejection here too, so a blocked library request fails at once rather than hanging until it times out.
[](#list-and-delete-artifacts-with-the-compliance-api)
List and delete artifacts with the Compliance API
The [Compliance API](https://docs.claude.com/en/api/compliance) provides endpoints to list an organization’s artifacts, retrieve a specific version’s content, and delete an artifact:
| Method | Endpoint |
|:---------|:--------------------------------------------------------------------|
| `GET` | `/v1/compliance/code/artifacts` |
| `GET` | `/v1/compliance/code/artifacts/{artifact_id}/versions/{version_id}` |
| `DELETE` | `/v1/compliance/code/artifacts/{artifact_id}` |
For the request and response schemas, see the [Compliance API reference](https://docs.claude.com/en/api/compliance/code/artifacts).
[](#related-resources)
Related resources
- Browse [prompting patterns and workflows](prompt-library.md) that pair with artifacts
- Turn an artifact prompt you reuse into a [skill](../08-Plugins-Skills/skills.md) so you can invoke it as a command
- [Connect MCP servers](../06-MCP-Tools/General/mcp.md) so Claude can pull data into an artifact while it builds the page
---
## Configure auto mode - Claude Code Docs
Source: https://code.claude.com/docs/en/auto-mode-config
Path: 02-Claude-Code-CLI/auto-mode-config.md
## On this page
- [Common boundaries](#common-boundaries)
- [Add a human checkpoint](#add-a-human-checkpoint)
- [Where the classifier reads configuration](#where-the-classifier-reads-configuration)
- [Define trusted infrastructure](#define-trusted-infrastructure)
- [Generate environment entries with /auto-mode-setup](#generate-environment-entries)
- [What /auto-mode-setup reads](#what-auto-mode-setup-reads)
- [Review and save the draft](#review-and-save-the-draft)
- [Turn off /auto-mode-setup](#turn-off-auto-mode-setup)
- [Override the block and allow rules](#override-the-block-and-allow-rules)
- [Edit rules from /permissions](#edit-rules-from-permissions)
- [Route all shell commands through the classifier](#route-all-shell-commands-through-the-classifier)
- [Inspect the defaults and your effective config](#inspect-the-defaults-and-your-effective-config)
- [Review denials](#review-denials)
- [Fix a denial with an allow rule, an environment entry, or a retry](#fix-a-denial-with-an-allow-rule-an-environment-entry-or-a-retry)
- [Fix repeated denials](#fix-repeated-denials)
- [See also](#see-also)
Setup and access
# Configure auto mode
Copy pageCopy page
Tell the auto mode classifier which repos, buckets, and domains your organization trusts. Set environment context, override the default block and allow rules, and inspect your effective config with the auto-mode CLI subcommands.
Copy pageCopy page
[Auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) lets Claude Code run without routine permission prompts by routing tool calls through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Deny and explicit ask rules are evaluated before the classifier and still block or prompt. Use the `autoMode` settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.
This page is the configuration reference. Turning auto mode on and off is covered on the Permission modes page:
- **Switch to auto mode mid-session, or back out of it**: see [Switch permission modes](permission-modes.md#switch-permission-modes)
- **Start a session in auto mode**: see [Start in a different permission mode](permission-modes.md#start-in-a-different-mode)
Auto mode is available to all users on every provider, including the Anthropic API, [Claude Platform on AWS](claude-platform-on-aws.md), Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and signed-in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions. If Claude Code reports auto mode as unavailable for your account, check the [full requirements](permission-modes.md#eliminate-prompts-with-auto-mode), which also cover the supported models and the organization-level control on Team and Enterprise plans. By default, 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`. This page covers how to:
- [Add a human checkpoint](#add-a-human-checkpoint) for pushes and pull requests with `permissions.ask`
- [Define trusted infrastructure](#define-trusted-infrastructure) with `autoMode.environment`
- [Generate environment entries](#generate-environment-entries) with `/auto-mode-setup`
- [Review denials](#review-denials) so you know what to add next
[](#common-boundaries)
Common boundaries
Auto mode allows pushes to any branch of the repository you’re working in, including the default branch, and pull request creation by default. A non-default branch whose name marks it as a deploy or publication target, such as `production`, `release`, or `gh-pages`, isn’t covered by that default: the classifier judges a push there on its own terms, including as a production deploy. The push’s content is also still checked, so a force push, a secret entering the commit, or a change that would send secrets outside the repository when CI or a deploy pipeline runs it stays blocked. If you want a human checkpoint before Claude’s push and pull request commands, add permission rules: the [recipes below](#add-a-human-checkpoint) keep auto mode on for everything else.
[](#add-a-human-checkpoint)
Add a human checkpoint
The most direct mechanism is [`permissions.ask`](permissions.md#permission-rule-syntax). Content-scoped ask rules like the ones below are evaluated before the classifier and always force a permission prompt, even in auto mode, because an explicit ask rule is your stated intent to be prompted for that action. Add the rules in your [settings](settings.md#where-settings-live):
```python
{
"permissions": {
"ask": [
"Bash(git push *)",
"Bash(gh pr create *)"
]
}
}
```
These rules match commands that begin with `git push` or `gh pr create`. A push Claude writes another way, such as `git -C <dir> push` or `git -c <key>=<value> push`, [doesn’t match the rule](permissions.md#bash-rule-limits), so it isn’t checkpointed. For a checkpoint that inspects the full command text, add a [PreToolUse hook](../07-Hooks/hooks.md#pretooluse). Pick the mechanism that matches how firm the boundary needs to be:
| Boundary | Mechanism | Behavior in auto mode |
|:----------------------------------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Prompt before the action | `permissions.ask` | Always prompts for a command that matches a content-scoped rule like the recipe above. The classifier cannot auto-approve a matching action. |
| Never run the action | `permissions.deny` | Blocks before the classifier is consulted. Neither the classifier nor user intent can override it. |
| One-off boundary for this session | State it in conversation, like “don’t push until I review” | The classifier blocks matching actions, but the boundary can be lost if [context compaction](../17-Billing-Plans/costs.md#reduce-token-usage) removes the message that stated it. Use an ask or deny rule for a durable guarantee. |
[](#where-the-classifier-reads-configuration)
Where the classifier reads configuration
The classifier reads the same [CLAUDE.md](memory.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 |
| Organization-wide | [Managed settings](../13-Enterprise-Admin/server-managed-settings.md) | Trusted infrastructure distributed to all developers |
| `--settings` flag or Agent SDK | Inline JSON | Per-invocation overrides for automation |
The classifier doesn’t read `autoMode` from project settings in `.claude/settings.json` or `.claude/settings.local.json`. Both files live in the repo directory, so a checked-in repo or a build step could otherwise inject its own allow rules. Move any `autoMode` block in `.claude/settings.local.json` to `~/.claude/settings.json`. Entries from each scope are combined. A developer can extend `environment`, `allow`, `soft_deny`, and `hard_deny` with personal entries but can’t 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](permissions.md). 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 can’t be overridden.
[](#define-trusted-infrastructure)
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. `claude auto-mode defaults` prints three kinds of environment entry.
- **Context slots**: describe your organization, stack, and security posture so the classifier reads the other rules in your context. Each defaults to `None configured` or to the conservative assumption named next to it:
- **Organization**
- **Primary use of Claude Code**: defaults to software development
- **Cloud provider(s)**
- **Repository visibility**: a repository is assumed private unless its remote host and name indicate otherwise, or the classifier reads a visibility check earlier in the conversation showing it is public. In the classifier requests sent by Claude Code itself, the classifier reads your messages and the commands Claude runs, not their output. The evidence has to be something the classifier can read, such as your own message naming the repository as public; the output of a `gh repo view` on its own doesn’t reach it.
- **Internal sharing / snippet hosting**: public paste and gist services are treated as outside the trust boundary until you name one
- **Org-specific CLIs**
- **Secrets management**
- **CI/CD deploy targets**
- **Network posture**
- **Host containment**: defaults to an ordinary developer machine or CI runner with open internet. If Claude Code runs in a container, VM, or pod with an egress allow-list or neighbors it must not touch, name the allowed hosts, whether the cloud metadata endpoint should be reachable, and which cloud project, cluster, or registry the task uses and under what identity. Until this entry names that identity, the classifier [blocks](permission-modes.md#what-the-classifier-blocks-by-default) requests for the host’s own credentials. Requires Claude Code v2.1.257 or later
- **Protected deployment namespaces / environments**: falls back to the Sensitive remote targets heuristic until you name them
- **Data retention / declassification**
- **Trust slots**: name what the classifier treats as inside your boundary. The slots are Trusted repo, Source control, Trusted internal domains, Trusted cloud buckets, Key internal services, and Internal package registry. The repo and source-control entries default to the working repository and its configured remotes. Every other trust slot defaults to `None configured`, so nothing else is trusted until you add it. A repository’s visibility scopes only confidential material: a private repository is an acceptable destination for confidential material, but making a repository private never clears secrets or personal or entrusted data into it, and the classifier treats content ported, repointed, or first read from outside the working repository as not that repository’s own work.
- **Sensitivity slots**: name what the protective rules treat as high-risk. The slots are Sensitive data locations & audiences, Sensitive remote targets, and Protected IaC scopes. Each defaults to a broad heuristic, such as treating any host or namespace whose name carries `prod` or `production` as a sensitive remote target, so the protective rules are active before you configure anything. Naming concrete targets in a sensitivity slot makes those rules apply to the named targets instead of the heuristic.
To add your own entries alongside the defaults, 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. The following example keeps the default entries and adds an organization’s repos, buckets, domains, and services.
```python
{
"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"
]
}
}
```
After you save your settings, run `claude auto-mode config` to [confirm the effective rules](#inspect-the-defaults-and-your-effective-config) include your entries. 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
- **Internal package registry**: the private npm, PyPI, or other registry that installs should route through, so installs that bypass it for a public registry get blocked
- **Sensitive data locations & audiences**: the buckets, databases, or paths that hold personal data, confidential business data, credentials, regulated data, or similarly sensitive material, and the audiences that data in each location may be shared with, so the classifier protects those locations instead of guessing from content.
- **Sensitive remote targets**: the namespaces, hosts, or containers that count as production, so remote shells and port-forwards into them need your explicit approval
- **Protected IaC scopes**: the infrastructure resources whose apply or destroy should always require you to name the change
- **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.
```python
{
"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}"
]
}
}
```
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.
[](#generate-environment-entries)
Generate environment entries with `/auto-mode-setup`
Run `/auto-mode-setup` to have Claude Code draft `autoMode.environment` entries, and sometimes [rule entries](#override-the-block-and-allow-rules) too, from your project and your recent sessions in it. If you accept the draft, Claude Code writes it to `~/.claude/settings.json`.
`/auto-mode-setup` requires a Pro, Max, or Team plan and Claude Code v2.1.228 or later. On native Windows it requires v2.1.233 or later. You can’t run it in a [cloud session](claude-code-on-the-web.md). It also needs [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching), so you can’t run it in a session where you’ve turned flag fetching off.
[](#what-auto-mode-setup-reads)
What `/auto-mode-setup` reads
If `~/.claude/settings.json` already holds `autoMode` entries, Claude Code starts by asking whether to add to your environment list or replace it, and keeps the rules you wrote either way. Claude Code then asks how you use this project and offers two optional scans before it scans anything. In the scan, Claude Code always reads these sources:
- This project’s `CLAUDE.md`, `README.md`, config files, and git remotes
- Your `autoMode` and `permissions.allow` settings
- The hosts, buckets, and command names from the commands Claude ran in your recent sessions in this project, never your messages
The two optional scans add one source each:
- The first word of each command in your shell history
- The remote hosts and names of the repositories under your home directory
[](#review-and-save-the-draft)
Review and save the draft
Claude Code scans in the background, then shows you the draft. You accept or discard it as a whole, so edit `~/.claude/settings.json` afterwards to adjust single entries. When you accept, Claude Code writes the draft and reconciles it with the settings you already have:
- Claude Code writes the `environment` list without `"$defaults"`, because the draft spells out the built-in entries it left unchanged
- Claude Code includes `"$defaults"` in each of the `allow`, `soft_deny`, and `hard_deny` lists the draft adds entries to, unless you already wrote an `allow` list without it, so the [built-in rules](#override-the-block-and-allow-rules) you haven’t replaced stay in effect
- After saving, Claude Code offers to remove `permissions.allow` rules in `~/.claude/settings.json` that auto mode ignores, such as `Bash(*)`, or that auto-approve destructive commands
Then run `claude auto-mode config` to [see the effective result](#inspect-the-defaults-and-your-effective-config).
[](#turn-off-auto-mode-setup)
Turn off `/auto-mode-setup`
Once auto mode has blocked several actions and you still have no `autoMode.environment` entries, Claude Code shows a dialog titled “Teach auto mode about your environment?” at the end of a turn and offers to run `/auto-mode-setup` for you. To stop the offer but keep the command, select **Don’t show again** in that dialog. To turn off both the command and the offer, add this [`skillOverrides`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) entry to `~/.claude/settings.json`:
```python
{
"skillOverrides": {
"auto-mode-setup": "off"
}
}
```
`/auto-mode-setup` is a built-in command rather than a [bundled skill](../08-Plugins-Skills/skills.md#bundled-skills), so this `skillOverrides` entry still applies to it, but [`disableBundledSkills`](settings-reference.md#disablebundledskills) doesn’t turn it off.
[](#override-the-block-and-allow-rules)
Override the block and allow rules
Three additional fields let you replace the classifier’s built-in rule lists:
- `autoMode.hard_deny`: unconditional security boundaries
- `autoMode.soft_deny`: destructive actions that user intent can clear
- `autoMode.allow`: exceptions to soft block rules
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`](permissions.md). Inside the classifier, precedence works in four tiers:
- `hard_deny` rules block unconditionally. User intent and `allow` exceptions don’t 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” doesn’t 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. The following example keeps the defaults in all four lists and adds organization-specific rules to each.
```python
{
"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. If you set an array without `"$defaults"`, you discard the built-in rules for that section:
- `soft_deny`: every built-in soft block rule, including force push, `curl | bash`, production deploys, and auto-mode bypass
- `hard_deny`: the built-in data exfiltration rule
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.
[](#edit-rules-from-permissions)
Edit rules from `/permissions`
To view and edit classifier rules without opening a settings file, run [`/permissions`](permissions.md#manage-permissions) and select the **Auto mode** tab. The tab requires Claude Code v2.1.246 or later, and it appears only when [auto mode is available](permission-modes.md#eliminate-prompts-with-auto-mode) to your session. The tab lists the `allow`, `soft_deny`, `hard_deny`, and `environment` entries from each of the [scopes the classifier reads](#where-the-classifier-reads-configuration), and shows whether the built-in rules are in effect for each section. Claude Code shows entries from [managed settings](../13-Enterprise-Admin/server-managed-settings.md) or the `--settings` flag as read-only, and saves every change you make on the tab to `~/.claude/settings.json`. From the tab you can:
- Add, edit, or delete rules in the `allow`, `soft_deny`, and `hard_deny` sections. When you add the first rule to a section, Claude Code also inserts `"$defaults"` so the [built-in rules](#override-the-block-and-allow-rules) stay in effect.
- Turn the built-in rules for `allow`, `soft_deny`, or `hard_deny` off or back on. Claude Code records the choice by adding or removing `"$defaults"` in your list for that section, so a section needs at least one rule of your own before you can turn its built-in rules off.
- Edit the `environment` entries as one document in your editor. If you haven’t configured any `environment` entries yet, Claude Code first asks whether to replace the built-in environment, then opens the editor on the full built-in text. When you save, Claude Code replaces your `autoMode.environment` array with the document. Include the `"$defaults"` line to [keep the built-in entries](#define-trusted-infrastructure).
[](#route-all-shell-commands-through-the-classifier)
Route all shell commands through the classifier
By default, narrow Bash and PowerShell allow rules such as `Bash(npm test)` stay in effect in auto mode. Claude Code resolves them before the classifier runs, unless the command carries [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode). Claude Code suspends only the broad rules that grant arbitrary code execution, such as `Bash(*)` or wildcarded interpreters, together with every rule that names [`Monitor`](tools-reference.md#monitor-tool), because Monitor commands run through the shell. This means a narrow rule can still let a destructive argument through without the classifier seeing it, for example a script path or flag the rule’s prefix didn’t anticipate. Set `autoMode.classifyAllShell` to `true` to suspend every Bash and PowerShell allow rule while auto mode is active, so the classifier evaluates every shell command regardless of your allow list, except [critical-path removals](permission-modes.md#critical-paths).
```python
{
"autoMode": {
"classifyAllShell": true
}
}
```
This trades latency for coverage: a command that an allow rule would have approved instantly now waits for a classifier decision, and each shell command counts as a classifier call. The setting applies only while auto mode is active, and your allow rules behave normally in other permission modes.
[](#inspect-the-defaults-and-your-effective-config)
Inspect the defaults and your effective config
The `claude auto-mode` subcommands help you inspect, validate, and reset your configuration. Print the built-in `environment`, `allow`, `soft_deny`, and `hard_deny` rules as JSON:
```python
claude auto-mode defaults
```
To read one rule’s full wording without piping through `jq`, pass `--label` with the start of the rule’s label, such as `claude auto-mode defaults --label 'Git Destructive'`. Matching is a case-insensitive prefix on each rule’s label, and sections with no match print as empty lists. Requires Claude Code v2.1.208 or later. Print what the classifier actually uses as JSON, with your settings applied where set and defaults otherwise:
```python
claude auto-mode config
```
Both `defaults` and `config` print the four rule lists as a single JSON object, with each rule as a prose string. This is a truncated example:
```python
{
"allow": [
...
"Test Artifacts: Hardcoded test API keys, placeholder credentials in examples, or hardcoding test cases. Placeholder means authored as a placeholder — a file or value copied from a real secret or sensitive path is never a test artifact (see Sensitive-Source Provenance).",
...
],
"soft_deny": [
"Git Destructive [named+specifics — **must name:** the destructive operation and its target]: Force pushing (`git push --force`), deleting remote branches, tags, or releases, or rewriting remote history. Also `git commit --amend` when the commit being rewritten is not the agent's own unpushed work: either no prior `git commit` is visible (HEAD pre-dates the session), or a `git push` of the current branch is visible after the most recent commit (it has been pushed). Clears when the user asked to amend/reword/fixup, or when it is a message-only reword (`--amend -m …`, nothing newly staged) of a commit the agent visibly created this session.",
...
],
"hard_deny": [...],
"environment": [
...
"**Trusted repo**: The git repository the agent started in (its working directory) and its configured remote(s). When the repo's public/private visibility is given — by the Repository visibility entry or the user's own message — use it to scope what is OK to commit or push there: confidential material is fine in a private repo; in a public one, only that repo's own work is — and content ported, repointed, or first read from outside this session's repo is not its own work, whoever directed the port. Visibility scopes confidential material only: secrets and sensitive data (personal & entrusted) are never cleared into any repo by its visibility (see Definitions).",
...
]
}
```
Get AI feedback on your custom `allow`, `soft_deny`, and `hard_deny` rules:
```python
claude auto-mode critique
```
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. To discard your customizations and return to the built-in defaults, run the reset subcommand. It requires Claude Code v2.1.212 or later and removes the `autoMode` section from your user settings file:
```python
claude auto-mode reset
```
The command summarizes what it will remove and asks `Reset auto mode configuration to defaults?` before writing; pass `--yes` to skip the confirmation. Reset changes only `~/.claude/settings.json`: `autoMode` rules from [managed settings](../13-Enterprise-Admin/server-managed-settings.md) or the `--settings` flag still apply.
[](#review-denials)
Review denials
To review and retry actions the auto mode classifier denied, open `/permissions` and select the **Recently denied** tab, where Claude Code records each denial. 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. When the classifier produces [no verdict on the action](errors.md#auto-mode-cannot-determine-the-safety-of-an-action), because a safety check separate from auto mode refused the classifier’s own request or its response didn’t parse, Claude Code denies the action without recording it under **Recently denied**. The linked error entry covers what Claude is told and how to run the action if you need it.
[](#fix-a-denial-with-an-allow-rule-an-environment-entry-or-a-retry)
Fix a denial with an allow rule, an environment entry, or a retry
To see what the classifier blocked, find the tool call in the conversation. If the call appears shortened or folded into a summary line such as `Ran 3 shell commands`, press `Ctrl+O` to open the [transcript viewer](interactive-mode.md#transcript-viewer), which expands it. Two other places on screen that report denials leave out the command or URL: the notice near the input box, such as `bash denied by auto mode · [Data Exfiltration] · /permissions`, gives the tool and the reason, and the **Recently denied** tab lists a shell command by the description Claude wrote for it. To capture the exact input of these denials programmatically, add a [`PermissionDenied` hook](../07-Hooks/hooks.md#permissiondenied), which receives it as `tool_input`. The text beneath the call tells you whether there is anything to fix. Text that reports a problem with the classifier itself, such as a model that `is temporarily unavailable` or a classifier error, means Claude Code blocked the call without a final verdict from the classifier; see [Auto mode cannot determine the safety of an action](errors.md#auto-mode-cannot-determine-the-safety-of-an-action) for what to do. Otherwise, a line reading `Denied by auto mode classifier` with a reason such as `[Production Deploy]` or `Blocked by classifier` means the classifier judged the call unsafe, so pick the fix from what the call was trying to reach or do:
- A destination Claude needs throughout the task, such as a package registry, an internal domain, or a repository host: add it to `autoMode.environment`.
- A command you want to run without review from now on: add an `allow` rule.
- A one-off action you did intend: state that intent in your next message and let Claude retry.
You can add the environment entry or `allow` rule from the `/permissions` dialog’s [**Auto mode** tab](#edit-rules-from-permissions). The text in square brackets, such as `[Data Exfiltration]`, is the name of the rule the classifier matched. To read that rule’s full wording, see [Inspect the defaults and your effective config](#inspect-the-defaults-and-your-effective-config).
[](#fix-repeated-denials)
Fix repeated denials
Repeated denials for the same destination usually mean the classifier is missing context. Add that destination to `autoMode.environment`, or [run `/auto-mode-setup`](#generate-environment-entries) to have Claude Code draft the entries, then run `claude auto-mode config` to confirm the change took effect.
[](#see-also)
See also
- [Permission modes](permission-modes.md#eliminate-prompts-with-auto-mode): what auto mode is, what it blocks by default, and which sessions start in it
- [Managed settings](../13-Enterprise-Admin/server-managed-settings.md): deploy `autoMode` configuration across your organization
- [Permissions](permissions.md): allow, ask, and deny rules that apply before the classifier runs
- [All settings](settings-reference.md#automode): every settings key, including `autoMode`
---
## Automated Security Reviews in Claude Code | Claude Help Center
Source: https://support.claude.com/en/articles/11932705-automated-security-reviews-in-claude-code
Path: 02-Claude-Code-CLI/automated-security-reviews-in-claude-code.md
# Automated Security Reviews in Claude Code
March 16, 2026
Claude Code now includes automated security review features to help you identify and fix vulnerabilities in your code. This guide explains how to use the /security-review command and GitHub Actions to improve your code security.
**Note:** While automated security reviews help identify many common vulnerabilities, they should complement, not replace, your existing security practices and manual code reviews.
## Overview
Automated security reviews in Claude Code help developers catch vulnerabilities before they reach production. These features check for common security issues including SQL injection risks, cross-site scripting (XSS) vulnerabilities, authentication flaws, insecure data handling, and dependency vulnerabilities.
You can use security reviews in two ways: through the /security-review command for on-demand checks in your terminal, or through GitHub Actions for automatic review of pull requests.
## Availability
These features are available for all Claude Code users, including:
- Users on individual paid plans (Pro or Max).
- Individual users or enterprises with pay-as-you-go API Console accounts.
## Using the /security-review command
The /security-review command lets you run security analysis directly from your terminal before committing code.
### Running a Security Review
To check your code for vulnerabilities:
1. Open Claude Code in your project directory.
2. Run /security-review in the terminal.
3. Claude will analyze your codebase and identify potential security concerns.
4. Review the detailed explanations provided for each issue found.
### Implementing Fixes
After Claude identifies vulnerabilities, you can ask it to implement fixes directly. This keeps security reviews integrated into your development workflow, allowing you to address issues when they're easiest to resolve.
### Customizing the Command
You can customize the /security-review command for your specific needs. See the [security review documentation](https://github.com/anthropics/claude-code-security-review/tree/main?tab=readme-ov-file#security-review-slash-command) for configuration options.
## Setting up GitHub Actions for automated PR reviews
After installing and configuring the GitHub action, it will automatically review every pull request for security vulnerabilities when it's opened.
### Installation
To set up automated security reviews for your repository:
1. Navigate to your repository's GitHub Actions settings
2. Follow the [step-by-step installation guide](https://github.com/anthropics/claude-code-security-review) in our documentation
3. Configure the action according to your team's security requirements
### How It Works
Once configured, the GitHub action:
- Triggers automatically when new pull requests are opened.
- Reviews code changes for security vulnerabilities.
- Applies customizable filtering rules to reduce false positives.
- Posts inline comments on the PR with identified concerns and recommended fixes.
This creates a consistent security review process across your entire team, ensuring code is checked for vulnerabilities before merging.
### Customization Options
You can customize the GitHub action to match your team's security policies, including setting specific rules for your codebase and adjusting sensitivity levels for different vulnerability types.
## What security issues can be detected?
Both the /security-review command and GitHub action check for common vulnerability patterns:
- **SQL injection risks**: Identifies potential database query vulnerabilities.
- **Cross-site scripting (XSS)**: Detects client-side script injection vulnerabilities.
- **Authentication and authorization flaws**: Finds issues with access control.
- **Insecure data handling**: Identifies problems with data validation and sanitization.
- **Dependency vulnerabilities**: Checks for known issues in third-party packages.
## Getting Started
To start using automated security reviews:
- **For the /security-review command**: Update Claude Code to the latest version (run), then run `/security-review` in your project directory.
- Claude Code automatically keeps itself up to date to ensure you have the latest features and security fixes, but you can also run `claude update` to update manually.
- **For the GitHub actions**: Visit our [documentation](https://github.com/anthropics/claude-code-security-review) for installation and configuration instructions.
## Best Practices
For optimal results, we recommend running /security-review before committing significant changes and configuring the GitHub action for all repositories containing production code. Consider adjusting the filtering rules based on your team's specific security requirements and codebase characteristics.
---
## Best practices for Claude Code - Claude Code Docs
Source: https://code.claude.com/docs/en/best-practices
Path: 02-Claude-Code-CLI/best-practices.md
## On this page
- [Give Claude a way to verify its work](#give-claude-a-way-to-verify-its-work)
- [Explore first, then plan, then code](#explore-first-then-plan-then-code)
- [Provide specific context in your prompts](#provide-specific-context-in-your-prompts)
- [Provide rich content](#provide-rich-content)
- [Configure your environment](#configure-your-environment)
- [Write an effective CLAUDE.md](#write-an-effective-claude-md)
- [Configure permissions](#configure-permissions)
- [Use CLI tools](#use-cli-tools)
- [Connect MCP servers](#connect-mcp-servers)
- [Set up hooks](#set-up-hooks)
- [Create skills](#create-skills)
- [Create custom subagents](#create-custom-subagents)
- [Install plugins](#install-plugins)
- [Communicate effectively](#communicate-effectively)
- [Ask codebase questions](#ask-codebase-questions)
- [Let Claude interview you](#let-claude-interview-you)
- [Manage your session](#manage-your-session)
- [Course-correct early and often](#course-correct-early-and-often)
- [Manage context aggressively](#manage-context-aggressively)
- [Use subagents for investigation](#use-subagents-for-investigation)
- [Rewind with checkpoints](#rewind-with-checkpoints)
- [Resume conversations](#resume-conversations)
- [Automate and scale](#automate-and-scale)
- [Run non-interactive mode](#run-non-interactive-mode)
- [Run multiple Claude sessions](#run-multiple-claude-sessions)
- [Fan out across files](#fan-out-across-files)
- [Run autonomously with auto mode](#run-autonomously-with-auto-mode)
- [Add an adversarial review step](#add-an-adversarial-review-step)
- [Avoid common failure patterns](#avoid-common-failure-patterns)
- [Develop your intuition](#develop-your-intuition)
- [Related resources](#related-resources)
Use Claude Code
# Best practices for Claude Code
Copy pageCopy page
Tips and patterns for getting the most out of Claude Code, from configuring your environment to scaling across parallel sessions.
Copy pageCopy page
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, see [How Claude Code works](how-claude-code-works.md).
------------------------------------------------------------------------
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](context-window.md) of what loads at startup and what each file read costs. Track context usage continuously with a [custom status line](statusline.md), and see [Reduce token usage](../17-Billing-Plans/costs.md#reduce-token-usage) for strategies on reducing token usage.
------------------------------------------------------------------------
[](#give-claude-a-way-to-verify-its-work)
Give Claude a way to verify its work
Give Claude a check it can run: tests, a build, a screenshot to compare. It’s the difference between a session you watch and one you walk away from.
Claude stops when the work looks done. Without a check it can run, “looks done” is the only signal available, and you become the verification loop: every mistake waits for you to notice it. Give Claude something that produces a pass or fail, and the loop closes on its own. Claude does the work, runs the check, reads the result, and iterates until the check passes. The check is anything that returns a signal Claude can read in the conversation: a test suite, a build exit code, a linter, a script that diffs output against a fixture, or a [browser screenshot](../03-IDE-Integrations/chrome.md) compared against a design. Run [`/verify`](../08-Plugins-Skills/skills.md#run-and-verify-your-app) yourself after Claude’s check passes to confirm the change against the running app.
| Strategy | Before | After |
|---------------------------------------|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Provide verification criteria** | *”implement a function that validates email addresses"* | *"write a validateEmail function. example test cases: [user@example.com](mailto:user@example.com) is true, invalid is false, [user@.com](mailto: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”* |
Once the check exists, decide how hard it gates the stop:
- **In one prompt**: ask Claude to run the check and iterate in the same message, as in the table above.
- **Across a session**: set the check as a [`/goal` condition](goal.md). A separate evaluator re-checks it after every turn and Claude keeps working until the goal resolves. If Claude stalls, Claude Code eventually stops the run with the goal still set — see [how /goal evaluation works](goal.md#how-evaluation-works).
- **As a deterministic gate**: a [Stop hook](../07-Hooks/hooks.md#stop) runs your check as a script and blocks the turn from ending until it passes. [Stop input](../07-Hooks/hooks.md#stop-input) covers the cap on consecutive blocks.
- **By a second opinion**: a [verification subagent](../09-Agents-Patterns/sub-agents.md) or a [dynamic workflow](workflows.md) that checks its own findings has a fresh model try to refute the result, so the agent doing the work isn’t the one grading it.
Each step trades setup for attention. The prompt version works on any task today. The `/goal` and Stop hook versions are what let an unattended run finish correctly without you. Have Claude show evidence rather than asserting success: the test output, the command it ran and what it returned, or a screenshot of the result. Reviewing evidence is faster than re-running the verification yourself, and it works for sessions you weren’t watching.
------------------------------------------------------------------------
[](#explore-first-then-plan-then-code)
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](permission-modes.md#analyze-before-you-edit-with-plan-mode) to separate exploration from execution. The recommended workflow has four phases:
1
Explore
Enter plan mode by pressing `Shift+Tab` until the status bar shows `⏸ plan mode on`, or start the session with `claude --permission-mode plan`. Claude reads files and answers questions without making changes.
claude (plan mode)
```python
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)
```python
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 by approving the plan or pressing `Shift+Tab`, then let Claude code, verifying against its plan.
claude
```python
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
```python
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)
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)
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)
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](features-overview.md).
[](#write-an-effective-claude-md)
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. There’s no required format for CLAUDE.md files, but keep it short and human-readable. For example:
CLAUDE.md
```python
# 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
```
Run `/context` to confirm Claude loaded the file. 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](../08-Plugins-Skills/skills.md) 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. For a checked-in CLAUDE.md, run [`/doctor`](commands.md#all-commands) and Claude proposes cuts for content it can derive from the codebase. If Claude keeps skipping one instruction, add emphasis such as “IMPORTANT” to that line alone. If you emphasize many lines, none of them stands out. 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. For import rules and where CLAUDE.md files can live, see [CLAUDE.md files](memory.md#claude-md-files).
[](#configure-permissions)
Configure permissions
To get fewer prompts without giving up control, pre-approve the tools you trust with `/permissions` and let sandboxed commands run without asking with `/sandbox`. Switch to Manual mode when you want to approve edits and commands yourself.
With Claude Code v2.1.283 or later, auto mode is the [built-in starting permission mode](permission-modes.md#eliminate-prompts-with-auto-mode) for interactive terminal and VS Code sessions: a separate classifier model reviews most actions instead of you and blocks only what looks risky, such as scope escalation, unknown infrastructure, or hostile-content-driven actions. On earlier versions, auto mode is the built-in starting permission mode only on Pro, Max, and Team plans. In Manual mode, Claude Code asks before actions that might modify your system: file writes, Bash commands, MCP tools. That’s safe but tedious. After the tenth approval you’re clicking through rather than reviewing. Two tools cut those interruptions in Manual mode and apply in auto mode as well:
- **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-modes.md), [permission rules](permissions.md), and [sandboxing](sandboxing.md).
[](#use-cli-tools)
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)
Connect MCP servers
Run `claude mcp add` with a server name and URL or command to connect external tools like Notion, Figma, or your database. For example: `claude mcp add --transport http notion https://mcp.notion.com/mcp`.
With [MCP servers](../06-MCP-Tools/General/mcp.md), 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)
Set up hooks
Use hooks for actions that must happen every time with zero exceptions.
[Hooks](../07-Hooks/hooks-guide.md) 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 skills
Create `SKILL.md` files in `.claude/skills/` to give Claude domain knowledge and reusable workflows.
[Skills](../08-Plugins-Skills/skills.md) 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
```python
---
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
```python
---
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)
Create custom subagents
Define specialized assistants in `.claude/agents/` that Claude can delegate to for isolated tasks.
[Subagents](../09-Agents-Patterns/sub-agents.md) 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
```python
---
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)
Install plugins
Run `/plugin` to browse the marketplace. Plugins add skills, tools, and integrations without configuration.
[Plugins](../08-Plugins-Skills/plugins.md) 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](../08-Plugins-Skills/plugins-code-intelligence.md) 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](features-overview.md#match-features-to-your-goal).
------------------------------------------------------------------------
[](#communicate-effectively)
Communicate effectively
Ask Claude the questions you’d ask another engineer, and for larger features have Claude interview you and write a spec before you start implementing.
[](#ask-codebase-questions)
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)
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. Replace `[brief description]` with your feature before sending the prompt.
```python
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. The most useful specs are self-contained: they name the files and interfaces involved, state what is out of scope, and end with an end-to-end verification step that proves the feature works. Time spent making the spec precise pays off more than time spent watching the implementation.
------------------------------------------------------------------------
[](#manage-your-session)
Manage your session
Conversations are persistent and reversible. Use this to your advantage!
[](#course-correct-early-and-often)
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)
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 [the rewind menu’s summarize options](checkpointing.md#rewind-and-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 questions that don’t need to stay in context, use [`/btw`](interactive-mode.md#side-questions-with-%2Fbtw). The answer never enters conversation history, so you can check a detail without growing context.
[](#use-subagents-for-investigation)
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, use subagents to keep research out of it. 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:
```python
Use subagents to investigate how our authentication system handles token
refresh, and whether we have any existing OAuth utilities I should reuse.
```
You can also use subagents for verification after Claude implements something. See [Add an adversarial review step](#add-an-adversarial-review-step).
[](#rewind-with-checkpoints)
Rewind with checkpoints
Every prompt you send that starts a turn 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](checkpointing.md) 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 are saved with the conversation, so you can close your terminal, resume the session later, and still rewind.
Checkpoints only track changes made through Claude’s file editing tools. Changes made through Bash commands or external processes are not captured. This isn’t a replacement for git.
[](#resume-conversations)
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`](sessions.md#resume-a-session) to pick up where you left off, or `claude --resume` to choose from a list. Give sessions descriptive names like `oauth-migration` so you can find them later. See [Manage sessions](sessions.md) for the full set of resume, branch, and naming controls.
------------------------------------------------------------------------
[](#automate-and-scale)
Automate and scale
Once you’re effective with one Claude, multiply your output with parallel sessions, non-interactive mode, and fan-out patterns.
[](#run-non-interactive-mode)
Run non-interactive mode
Use `claude -p "prompt"` in CI, pre-commit hooks, or scripts. Add `--output-format stream-json --verbose` for streaming JSON output.
With `claude -p "your prompt"`, you can run Claude non-interactively, without an interactive prompt. The run still creates a resumable session unless you pass `--no-session-persistence`. [Non-interactive mode](headless.md) 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.
```python
# 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 --verbose
```
The first command prints plain text. The `json` format returns a single JSON object with a `result` field. The `stream-json` format prints one JSON object per line, starting with an init event.
[](#run-multiple-claude-sessions)
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, and add messaging when the sessions need to pass findings between them:
- [Worktrees](worktrees.md): run separate CLI sessions in isolated git checkouts so edits don’t collide
- [Cross-session messaging](cross-session-messaging.md): let the sessions you run yourself pass findings to each other
- [Desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions): manage multiple local sessions visually, optionally each in its own worktree
- [Use Claude Code in the cloud](claude-code-on-the-web.md): run sessions on Anthropic-managed infrastructure by default
- [Agent view](../09-Agents-Patterns/agent-view.md): research preview. Run `claude agents` to dispatch sessions that keep running in the background and watch them from one screen
- [Agent teams](../09-Agents-Patterns/agent-teams.md): experimental and disabled by default. 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)
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. Run [`/batch <instruction>`](commands.md#all-commands) to have Claude split the change across 5 to 30 subagents. Each subagent works in its own worktree. To drive the fan-out from your own script instead, loop over `claude -p`:
1
Generate a task list
Have Claude write the list of files that need migrating to a file, so the loop in the next step can read it, with a prompt like `list all 2,000 Python files that need migrating and save the list to files.txt`
2
Write a script to loop through the list
```python
for file in $(cat files.txt); do
claude -p "Migrate $file from Python 2 to Python 3. Return OK or FAIL." \
--allowedTools "Edit,Bash(git commit *)"
done
```
3
Test on a few files, then run on all of them
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:
```python
claude -p "<your prompt>" --output-format json | your_command
```
[](#run-autonomously-with-auto-mode)
Run autonomously with auto mode
For uninterrupted execution with background safety checks, use [auto mode](permission-modes.md#eliminate-prompts-with-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.
```python
claude --permission-mode auto -p "fix all lint errors"
```
When the classifier repeatedly blocks actions in a non-interactive run with the `-p` flag, Claude Code doesn’t stop the run. See [when auto mode falls back](permission-modes.md#when-auto-mode-falls-back) for what happens instead and for the thresholds.
[](#add-an-adversarial-review-step)
Add an adversarial review step
Before treating a task as done, have a subagent review the diff in a fresh context and report gaps.
The longer Claude works unattended, the more an independent check matters before you count the work as done. A reviewer running in a fresh [subagent](../09-Agents-Patterns/sub-agents.md) context sees only the diff and the criteria you give it, not the reasoning that produced the change, so it evaluates the result on its own terms. For a correctness check, run the bundled [`/code-review` skill](commands.md), which reviews the current diff for bugs in a fresh subagent and returns findings to the session. To check the diff against your plan instead, write the review prompt yourself. Name the work to check, the plan to check it against, and what counts as a finding:
```python
Use a subagent to review the rate limiter diff against PLAN.md. Check that
every requirement is implemented, the listed edge cases have tests, and
nothing outside the task's scope changed. Report gaps, not style preferences.
```
Because the reviewer runs as a subagent, the implementing session receives the gaps directly and can fix them and re-review without you copying findings between windows.
A reviewer prompted to find gaps will usually report some, even when the work is sound, because that is what it was asked to do. Chasing every finding leads to over-engineering: extra abstraction layers, defensive code, and tests for cases that can’t happen. Tell the reviewer to flag only gaps that affect correctness or the stated requirements, and treat the rest as optional.
------------------------------------------------------------------------
[](#avoid-common-failure-patterns)
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)
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)
Related resources
- [How Claude Code works](how-claude-code-works.md): the agentic loop, tools, and context management
- [Extend Claude Code](features-overview.md): skills, hooks, MCP, subagents, and plugins
- [Common workflows](common-workflows.md): step-by-step recipes for debugging, testing, PRs, and more
- [CLAUDE.md](memory.md): store project conventions and persistent context
---
## Claude Code changelog - Claude Code Docs
Source: https://code.claude.com/docs/en/changelog
Path: 02-Claude-Code-CLI/changelog.md
## On this page
- [2.1.285](#2-1-285)
- [2.1.284](#2-1-284)
- [2.1.283](#2-1-283)
- [2.1.282](#2-1-282)
- [2.1.281](#2-1-281)
- [2.1.280](#2-1-280)
- [2.1.278](#2-1-278)
- [2.1.277](#2-1-277)
- [2.1.276](#2-1-276)
- [2.1.275](#2-1-275)
- [2.1.274](#2-1-274)
- [2.1.273](#2-1-273)
- [2.1.272](#2-1-272)
- [2.1.271](#2-1-271)
- [2.1.270](#2-1-270)
- [2.1.269](#2-1-269)
- [2.1.268](#2-1-268)
- [2.1.267](#2-1-267)
- [2.1.266](#2-1-266)
- [2.1.265](#2-1-265)
- [2.1.263](#2-1-263)
- [2.1.261](#2-1-261)
- [2.1.260](#2-1-260)
- [2.1.259](#2-1-259)
- [2.1.258](#2-1-258)
- [2.1.257](#2-1-257)
- [2.1.252](#2-1-252)
- [2.1.251](#2-1-251)
- [2.1.250](#2-1-250)
- [2.1.248](#2-1-248)
- [2.1.247](#2-1-247)
- [2.1.246](#2-1-246)
- [2.1.245](#2-1-245)
- [2.1.243](#2-1-243)
- [2.1.241](#2-1-241)
- [2.1.240](#2-1-240)
- [2.1.239](#2-1-239)
- [2.1.238](#2-1-238)
- [2.1.237](#2-1-237)
- [2.1.236](#2-1-236)
- [2.1.235](#2-1-235)
- [2.1.234](#2-1-234)
- [2.1.233](#2-1-233)
- [2.1.232](#2-1-232)
- [2.1.231](#2-1-231)
- [2.1.229](#2-1-229)
- [2.1.228](#2-1-228)
- [2.1.227](#2-1-227)
- [2.1.226](#2-1-226)
- [2.1.225](#2-1-225)
- [2.1.224](#2-1-224)
- [2.1.223](#2-1-223)
- [2.1.222](#2-1-222)
- [2.1.221](#2-1-221)
- [2.1.220](#2-1-220)
- [2.1.219](#2-1-219)
- [2.1.218](#2-1-218)
- [2.1.217](#2-1-217)
- [2.1.216](#2-1-216)
- [2.1.215](#2-1-215)
- [2.1.214](#2-1-214)
- [2.1.212](#2-1-212)
- [2.1.211](#2-1-211)
- [2.1.210](#2-1-210)
- [2.1.209](#2-1-209)
- [2.1.208](#2-1-208)
- [2.1.207](#2-1-207)
- [2.1.206](#2-1-206)
- [2.1.205](#2-1-205)
- [2.1.204](#2-1-204)
- [2.1.203](#2-1-203)
- [2.1.202](#2-1-202)
- [2.1.201](#2-1-201)
- [2.1.200](#2-1-200)
- [2.1.199](#2-1-199)
- [2.1.198](#2-1-198)
- [2.1.197](#2-1-197)
- [2.1.196](#2-1-196)
- [2.1.195](#2-1-195)
- [2.1.193](#2-1-193)
- [2.1.191](#2-1-191)
- [2.1.190](#2-1-190)
- [2.1.187](#2-1-187)
- [2.1.186](#2-1-186)
- [2.1.185](#2-1-185)
- [2.1.183](#2-1-183)
- [2.1.181](#2-1-181)
- [2.1.179](#2-1-179)
- [2.1.178](#2-1-178)
- [2.1.176](#2-1-176)
- [2.1.175](#2-1-175)
- [2.1.174](#2-1-174)
- [2.1.173](#2-1-173)
- [2.1.172](#2-1-172)
- [2.1.170](#2-1-170)
- [2.1.169](#2-1-169)
- [2.1.168](#2-1-168)
- [2.1.167](#2-1-167)
- [2.1.166](#2-1-166)
- [2.1.165](#2-1-165)
- [2.1.163](#2-1-163)
- [2.1.162](#2-1-162)
- [2.1.161](#2-1-161)
- [2.1.160](#2-1-160)
- [2.1.159](#2-1-159)
- [2.1.158](#2-1-158)
- [2.1.157](#2-1-157)
- [2.1.156](#2-1-156)
- [2.1.154](#2-1-154)
- [2.1.153](#2-1-153)
- [2.1.152](#2-1-152)
- [2.1.150](#2-1-150)
- [2.1.149](#2-1-149)
- [2.1.148](#2-1-148)
- [2.1.147](#2-1-147)
- [2.1.145](#2-1-145)
- [2.1.144](#2-1-144)
- [2.1.143](#2-1-143)
- [2.1.142](#2-1-142)
- [2.1.141](#2-1-141)
- [2.1.140](#2-1-140)
- [2.1.139](#2-1-139)
- [2.1.138](#2-1-138)
- [2.1.137](#2-1-137)
- [2.1.136](#2-1-136)
- [2.1.133](#2-1-133)
- [2.1.132](#2-1-132)
- [2.1.131](#2-1-131)
- [2.1.129](#2-1-129)
- [2.1.128](#2-1-128)
- [2.1.126](#2-1-126)
- [2.1.123](#2-1-123)
- [2.1.122](#2-1-122)
- [2.1.121](#2-1-121)
- [2.1.120](#2-1-120)
- [2.1.119](#2-1-119)
- [2.1.118](#2-1-118)
- [2.1.117](#2-1-117)
- [2.1.116](#2-1-116)
- [2.1.114](#2-1-114)
- [2.1.113](#2-1-113)
- [2.1.112](#2-1-112)
- [2.1.111](#2-1-111)
- [2.1.110](#2-1-110)
- [2.1.109](#2-1-109)
- [2.1.108](#2-1-108)
- [2.1.107](#2-1-107)
- [2.1.105](#2-1-105)
- [2.1.101](#2-1-101)
- [2.1.98](#2-1-98)
- [2.1.97](#2-1-97)
- [2.1.96](#2-1-96)
- [2.1.94](#2-1-94)
- [2.1.92](#2-1-92)
- [2.1.91](#2-1-91)
- [2.1.90](#2-1-90)
- [2.1.89](#2-1-89)
- [2.1.87](#2-1-87)
- [2.1.86](#2-1-86)
- [2.1.85](#2-1-85)
- [2.1.84](#2-1-84)
- [2.1.83](#2-1-83)
- [2.1.81](#2-1-81)
- [2.1.80](#2-1-80)
- [2.1.79](#2-1-79)
- [2.1.78](#2-1-78)
- [2.1.77](#2-1-77)
- [2.1.76](#2-1-76)
- [2.1.75](#2-1-75)
- [2.1.74](#2-1-74)
- [2.1.73](#2-1-73)
- [2.1.72](#2-1-72)
- [2.1.71](#2-1-71)
- [2.1.70](#2-1-70)
- [2.1.69](#2-1-69)
- [2.1.68](#2-1-68)
- [2.1.66](#2-1-66)
- [2.1.63](#2-1-63)
- [2.1.62](#2-1-62)
- [2.1.61](#2-1-61)
- [2.1.59](#2-1-59)
- [2.1.58](#2-1-58)
- [2.1.56](#2-1-56)
- [2.1.55](#2-1-55)
- [2.1.53](#2-1-53)
- [2.1.52](#2-1-52)
- [2.1.51](#2-1-51)
- [2.1.50](#2-1-50)
- [2.1.49](#2-1-49)
- [2.1.47](#2-1-47)
- [2.1.46](#2-1-46)
- [2.1.45](#2-1-45)
- [2.1.44](#2-1-44)
- [2.1.43](#2-1-43)
- [2.1.42](#2-1-42)
- [2.1.41](#2-1-41)
- [2.1.39](#2-1-39)
- [2.1.38](#2-1-38)
- [2.1.37](#2-1-37)
- [2.1.36](#2-1-36)
- [2.1.34](#2-1-34)
- [2.1.33](#2-1-33)
- [2.1.32](#2-1-32)
- [2.1.31](#2-1-31)
- [2.1.30](#2-1-30)
- [2.1.29](#2-1-29)
- [2.1.27](#2-1-27)
- [2.1.25](#2-1-25)
- [2.1.23](#2-1-23)
- [2.1.22](#2-1-22)
- [2.1.21](#2-1-21)
- [2.1.20](#2-1-20)
- [2.1.19](#2-1-19)
- [2.1.18](#2-1-18)
- [2.1.17](#2-1-17)
- [2.1.16](#2-1-16)
- [2.1.15](#2-1-15)
- [2.1.14](#2-1-14)
- [2.1.12](#2-1-12)
- [2.1.11](#2-1-11)
- [2.1.10](#2-1-10)
- [2.1.9](#2-1-9)
- [2.1.7](#2-1-7)
- [2.1.6](#2-1-6)
- [2.1.5](#2-1-5)
- [2.1.4](#2-1-4)
- [2.1.3](#2-1-3)
- [2.1.2](#2-1-2)
- [2.1.0](#2-1-0)
- [2.0.76](#2-0-76)
- [2.0.75](#2-0-75)
- [2.0.74](#2-0-74)
- [2.0.73](#2-0-73)
- [2.0.72](#2-0-72)
- [2.0.71](#2-0-71)
- [2.0.70](#2-0-70)
- [2.0.69](#2-0-69)
- [2.0.68](#2-0-68)
- [2.0.67](#2-0-67)
- [2.0.65](#2-0-65)
- [2.0.64](#2-0-64)
- [2.0.62](#2-0-62)
- [2.0.61](#2-0-61)
- [2.0.60](#2-0-60)
- [2.0.59](#2-0-59)
- [2.0.58](#2-0-58)
- [2.0.57](#2-0-57)
- [2.0.56](#2-0-56)
- [2.0.55](#2-0-55)
- [2.0.54](#2-0-54)
- [2.0.52](#2-0-52)
- [2.0.51](#2-0-51)
- [2.0.50](#2-0-50)
- [2.0.49](#2-0-49)
- [2.0.47](#2-0-47)
- [2.0.46](#2-0-46)
- [2.0.45](#2-0-45)
- [2.0.43](#2-0-43)
- [2.0.42](#2-0-42)
- [2.0.41](#2-0-41)
- [2.0.37](#2-0-37)
- [2.0.36](#2-0-36)
- [2.0.35](#2-0-35)
- [2.0.34](#2-0-34)
- [2.0.33](#2-0-33)
- [2.0.32](#2-0-32)
- [2.0.31](#2-0-31)
- [2.0.30](#2-0-30)
- [2.0.28](#2-0-28)
- [2.0.27](#2-0-27)
- [2.0.25](#2-0-25)
- [2.0.24](#2-0-24)
- [2.0.22](#2-0-22)
- [2.0.21](#2-0-21)
- [2.0.20](#2-0-20)
- [2.0.19](#2-0-19)
- [2.0.17](#2-0-17)
- [2.0.15](#2-0-15)
- [2.0.14](#2-0-14)
- [2.0.13](#2-0-13)
- [2.0.12](#2-0-12)
- [2.0.11](#2-0-11)
- [2.0.10](#2-0-10)
- [2.0.9](#2-0-9)
- [2.0.8](#2-0-8)
- [2.0.5](#2-0-5)
- [2.0.1](#2-0-1)
- [2.0.0](#2-0-0)
- [1.0.126](#1-0-126)
- [1.0.124](#1-0-124)
- [1.0.123](#1-0-123)
- [1.0.120](#1-0-120)
- [1.0.119](#1-0-119)
- [1.0.117](#1-0-117)
- [1.0.115](#1-0-115)
- [1.0.113](#1-0-113)
- [1.0.112](#1-0-112)
- [1.0.111](#1-0-111)
- [1.0.110](#1-0-110)
- [1.0.109](#1-0-109)
- [1.0.106](#1-0-106)
- [1.0.97](#1-0-97)
- [1.0.94](#1-0-94)
- [1.0.93](#1-0-93)
- [1.0.90](#1-0-90)
- [1.0.88](#1-0-88)
- [1.0.86](#1-0-86)
- [1.0.85](#1-0-85)
- [1.0.84](#1-0-84)
- [1.0.83](#1-0-83)
- [1.0.82](#1-0-82)
- [1.0.81](#1-0-81)
- [1.0.80](#1-0-80)
- [1.0.77](#1-0-77)
- [1.0.73](#1-0-73)
- [1.0.72](#1-0-72)
- [1.0.71](#1-0-71)
- [1.0.70](#1-0-70)
- [1.0.69](#1-0-69)
- [1.0.68](#1-0-68)
- [1.0.65](#1-0-65)
- [1.0.64](#1-0-64)
- [1.0.63](#1-0-63)
- [1.0.62](#1-0-62)
- [1.0.61](#1-0-61)
- [1.0.60](#1-0-60)
- [1.0.59](#1-0-59)
- [1.0.58](#1-0-58)
- [1.0.57](#1-0-57)
- [1.0.56](#1-0-56)
- [1.0.55](#1-0-55)
- [1.0.54](#1-0-54)
- [1.0.53](#1-0-53)
- [1.0.52](#1-0-52)
- [1.0.51](#1-0-51)
- [1.0.48](#1-0-48)
- [1.0.45](#1-0-45)
- [1.0.44](#1-0-44)
- [1.0.43](#1-0-43)
- [1.0.42](#1-0-42)
- [1.0.41](#1-0-41)
- [1.0.40](#1-0-40)
- [1.0.39](#1-0-39)
- [1.0.38](#1-0-38)
- [1.0.37](#1-0-37)
- [1.0.36](#1-0-36)
- [1.0.35](#1-0-35)
- [1.0.34](#1-0-34)
- [1.0.33](#1-0-33)
- [1.0.32](#1-0-32)
- [1.0.31](#1-0-31)
- [1.0.30](#1-0-30)
- [1.0.29](#1-0-29)
- [1.0.28](#1-0-28)
- [1.0.27](#1-0-27)
- [1.0.25](#1-0-25)
- [1.0.24](#1-0-24)
- [1.0.23](#1-0-23)
- [1.0.22](#1-0-22)
- [1.0.21](#1-0-21)
- [1.0.18](#1-0-18)
- [1.0.17](#1-0-17)
- [1.0.11](#1-0-11)
- [1.0.10](#1-0-10)
- [1.0.8](#1-0-8)
- [1.0.7](#1-0-7)
- [1.0.6](#1-0-6)
- [1.0.4](#1-0-4)
- [1.0.1](#1-0-1)
- [1.0.0](#1-0-0)
- [0.2.125](#0-2-125)
- [0.2.117](#0-2-117)
- [0.2.108](#0-2-108)
- [0.2.107](#0-2-107)
- [0.2.106](#0-2-106)
- [0.2.105](#0-2-105)
- [0.2.102](#0-2-102)
- [0.2.100](#0-2-100)
- [0.2.98](#0-2-98)
- [0.2.96](#0-2-96)
- [0.2.93](#0-2-93)
- [0.2.82](#0-2-82)
- [0.2.75](#0-2-75)
- [0.2.74](#0-2-74)
- [0.2.72](#0-2-72)
- [0.2.70](#0-2-70)
- [0.2.69](#0-2-69)
- [0.2.67](#0-2-67)
- [0.2.66](#0-2-66)
- [0.2.63](#0-2-63)
- [0.2.61](#0-2-61)
- [0.2.59](#0-2-59)
- [0.2.54](#0-2-54)
- [0.2.53](#0-2-53)
- [0.2.50](#0-2-50)
- [0.2.49](#0-2-49)
- [0.2.47](#0-2-47)
- [0.2.44](#0-2-44)
- [0.2.41](#0-2-41)
- [0.2.37](#0-2-37)
- [0.2.36](#0-2-36)
- [0.2.34](#0-2-34)
- [0.2.32](#0-2-32)
- [0.2.31](#0-2-31)
- [0.2.30](#0-2-30)
- [0.2.26](#0-2-26)
- [0.2.21](#0-2-21)
Getting started
# Claude Code changelog
Copy pageCopy page
Release notes for Claude Code, including new features, improvements, and bug fixes by version.
Copy pageCopy page
This page is generated from the [CHANGELOG.md on GitHub](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md). Run `claude --version` to check your installed version.
[](#2-1-285)
2.1.285
September 29, 2026
- Added `CLAUDE_CODE_DISABLE_WEB_FETCH` environment variable to turn off the WebFetch tool
- Added `claude --desktop` to open the Claude desktop app on the current directory, or on a session with `--continue` / `--resume <id>`
- Added `claude plugin configure <plugin>` to show a plugin’s options and which are unset, or save new values read from stdin with `--values-stdin`
- Added `<server>.<key>=<value>` to `claude plugin install --config`, so a bundled `.mcpb` MCP server’s own settings can be set at install time and it starts without visiting `/plugin` → Configure
- Added `allowedProviders` managed setting to limit which API providers a machine may use (Anthropic API, a custom endpoint, Bedrock, Mantle, Vertex AI, Foundry, Claude Platform on AWS, or a Cloud gateway)
- Added `CLAUDE_CODE_NONSTREAMING_TIMEOUT_RETRIES` environment variable to cap re-sends of a non-streaming fallback request that timed out
- Fixed `claude -p` with `CLAUDE_CODE_FORK_SUBAGENT=1`: a subagent’s own Agent call now runs in the foreground, so the subagent gets the child’s result
- Fixed plugin and marketplace installs and updates over SSH ignoring the ssh program set in `GIT_SSH` or in your git config’s `core.sshCommand`
- Fixed Claude Code refusing to start when the OS denies reading the managed settings file; it now warns and starts without that file’s policies. Other read errors and unparseable files stop every session
- Fixed cloud sessions that restarted after their conversation was compacted refusing the next update to an artifact the session had already read or published
- Fixed `claude plugin disable` and `enable` with a full `name@marketplace` id changing a settings entry in another letter case instead of the installed plugin’s own
- Fixed files attached to a message sent over Remote Control being left out after a single failed download; a network error, timeout or server error is now retried up to twice
- Fixed switching models mid-session with a `set_model` request (such as the Agent SDK’s `setModel`) leaving the new model on the built-in output-token limit and auto-compact window until restart
- Fixed redacted logs and transcripts showing part of a URL password that contains `@`, or all of it when the URL writes its `@` as `%40`
- Fixed SSH passphrase and new-host prompts from worktree and `/teleport` fetches taking over the terminal; these fetches now fail fast instead of asking
- Fixed switching off an MCP server added mid-session in SDK and `-p` sessions leaving its tools available
- Fixed `claude -p --permission-prompt-tool`: a background subagent’s permission request now goes to the prompt tool instead of being auto-denied
- Fixed `claude mcp list` and `claude mcp get`, and the not-found error of `claude mcp remove`, `login` and `logout`, printing line breaks and terminal escape sequences from MCP server names and values
- Fixed sandbox auto-allow asking for approval on every run of many inline scripts (`python3 -c`, `node -e`) just because they contain `=`
- Fixed fork subagents not keeping the session’s plan mode or `dontAsk` mode: a fork now runs under its parent’s permission mode and cannot exit plan mode
- Fixed `claude remote-control --help` saying `--[no-]chrome` defaults to the machine’s `/chrome` setting; spawned sessions keep Claude in Chrome off unless `--chrome` is passed
- Fixed background subagents in auto mode prompting a second, redundant reply after each report
- Fixed cloud session creation and `/remote-env` reading only the newest 20 of an account’s environments
- Fixed Remote Control marking a message as read as soon as it arrived instead of when Claude started on it, and losing a message still queued when the terminal quit (it now arrives on the next resume)
- Fixed installing a plugin with `claude plugin install` or `/plugin` putting it into an installed plugin’s cache or data folder when their ids differ only in `.`, `-`, `@` or (macOS, Windows) capitals; the install is now refused
- Fixed hooks and SDK permission callbacks seeing a missing or outdated plan on ExitPlanMode when the plan was written in the same response
- Fixed the first reply in cloud sessions arriving tens of milliseconds late, a regression in 2.1.283
- Fixed sessions that authenticate with `ANTHROPIC_AUTH_TOKEN` against the Anthropic API never loading the organization’s policy
- Fixed a failed `agent()`, `parallel()` or `pipeline()` call that a workflow script awaits later, or not at all, being treated as an unhandled promise rejection, which could end a background session
- Fixed synchronous hooks hanging Claude Code while a background process the hook started (for example `some-daemon &`) kept its output open; the hook now finishes shortly after its own process exits
- Fixed WebFetch reporting a rate-limited domain safety check as a network or enterprise policy block
- Fixed the fullscreen ctrl+o transcript freezing briefly when opened on turns with hundreds of file reads or searches; tool calls still running when the transcript opens now show their results when they finish
- Fixed Amazon Bedrock mid-stream `modelTimeoutException` and `serviceUnavailableException` errors showing a raw JSON body instead of the error message
- Fixed `/autofix-pr` and `/schedule` saying the Claude GitHub App is not installed on a repository whose install status had not been checked yet
- Fixed dismissing a row (x) in `/artifacts` unlinking its file from the artifact, so publishing the same file again created a new artifact instead of updating it
- Fixed Artifact tool publishes after a conversation rewind (Esc Esc) overwriting a file’s newer content that Claude had read only in the rewound turns; the publish is now refused until Claude re-reads the file
- Fixed an `Artifact` allow rule (“don’t ask again”) letting the Artifact tool publish a file outside the working directories without asking; add the file’s folder with `--add-dir` for the rule to cover it
- Fixed `/cost` and SDK `modelUsage` reporting a turn under the wrong model when the server answered a refusal with a different fallback model than the client expected
- Fixed the Artifact tool so that publishing a page no longer lets Claude overwrite its source file without re-reading it when Claude’s earlier read was cut short or the file had changed since
- Fixed auto mode skipping its classifier for Artifact tool asset uploads and reads of someone else’s artifact when you had approved that artifact earlier in another permission mode
- Fixed a misleading “core.worktree is set” error from `/ultrareview` when the project folder briefly could not be read
- Fixed `/ultrareview` on macOS and Linux failing to upload the working tree from a git worktree whose per-worktree config sets `core.longpaths`
- Fixed the Artifact tool sometimes reporting a publish as a conflict with another session after retrying a temporary server error, when the first attempt had actually succeeded
- Fixed `/ultrareview` uploads including uncommitted changes to credential files whose name has a colon before the extension, such as `server:8443.key`
- Fixed a rare auth failure when two sessions recover a login refresh lock left by a crashed process at the same time
- Fixed the PowerShell tool’s permission check skipping deny and ask rules, and caching that failure for later checks, when its command parser failed to start (for example when the machine was out of memory)
- Fixed `/ultrareview` uploads on macOS and Linux running slowly on some unusual file names, and their credential-file check missing file or folder names with many backup or editor marks
- Fixed a cancelled shell command or hook still starting, and running to its end, when the cancel arrived while it was being set up
- Fixed vim mode: after editing in the external editor (Ctrl+G), `x` or `r` in NORMAL mode no longer breaks a pasted-text placeholder at the end of the prompt
- Fixed responses blocked by the API’s output content filter being re-sent and retried, sometimes for minutes, instead of showing the filter’s error right away
- Fixed plugins silently skipping a bundled `.mcpb` MCP server that still needs configuration: `/plugin`, the install message and `claude plugin install` now say so and point to Configure
- Fixed compacting or resuming a session failing, opening without its history, or crashing when its saved transcript holds a compaction marker or loop wakeup entry with missing or malformed fields
- WSL: Fixed `/ultrareview` refusing to upload a checkout on a Linux volume when a changed file’s name has a colon or ends in a dot or space
- Fixed `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` re-running a turn that had ended at `--max-turns`
- Fixed sign-in that could wait forever after the browser showed success
- Windows: Fixed `/ultrareview` uploading a linked worktree of a repository rooted at your home folder in some cases
- Fixed cloud sessions reporting the uploads folder as missing before any file had been uploaded
- Fixed a reply sent from `claude agents` to a background session waiting on a permission prompt sometimes approving the pending command
- Fixed `claude attach`, `logs`, `stop`, `respawn` and `rm` starting a new session with the command name as its prompt when options came before it, such as from a shell alias
- Fixed `claude mcp list` leaving out WebSocket (`ws`) MCP servers; each is now listed with its URL and health status
- Fixed `claude mcp get` showing no Type, Command, Args, or Environment for stdio servers whose config entry omits the `type` field
- Fixed `.claude/settings.local.json` allow rules being held back outside a git repository when git’s trace2 output is configured
- Fixed the `/claude-api` eval runner scaffold and report builder writing through a symlink or hard link planted at an output file
- Fixed the `/claude-api` eval runner scaffold counting responses cut off at `max_tokens` in the score averages; they are now marked truncated and counted separately
- Fixed ` ` showing as literal text in the terminal when a reply uses it to indent text, such as row labels in a markdown table
- Fixed a brief freeze (up to a second) partway through long sessions outside fullscreen mode, which came back after `/clear` or `/compact`
- Fixed an approved Edit never going through when its target is a device, such as a file symlinked to /dev/null, and the approval came from the IDE diff view or changed the edit
- Fixed a failing API request being retried up to 21 times when streaming kept failing; the non-streaming fallback now shares the request’s retry budget instead of getting a fresh set of retries
- Improved Claude in Chrome: the native host now reports your computer’s name, so connected browsers can be labeled by computer instead of “Browser 1” / “Browser 2”
- Improved Bedrock and Vertex AI sessions to switch to an older available model of the same tier, instead of failing, when an admin removes access to the default model; session titles and summaries now fall back with it
- Improved plugin marketplace errors to name why a git address is refused instead of citing enterprise policy
- Improved validation of git URLs for plugins, marketplaces and the current repository’s remote
- Improved Artifact tool results: they now suggest publishing in the same step as writing or editing the page, which can save a round trip
- Improved Remote Control: a `/btw` side question asked of a session hosted by an app such as Claude Desktop now sees the turn in progress, not only the last finished one
- Improved pictures Claude sends as BMP, HEIC, HEIF, AVIF or TIFF files: the Claude apps now show a preview where Claude Code can convert them
- Improved subagents in auto mode: a subagent’s run now ends as soon as it hands its report back to its caller, instead of taking extra turns that reach no one
- Improved Bedrock and Vertex start-up model checks: models your account cannot use are now remembered for up to a day instead of being re-checked on every launch
- Improved Artifact tool publish results to use fewer tokens: the note on updating an artifact is shorter, and where to find your artifacts is no longer repeated after every publish
- Improved SDK liveness during a non-streaming fallback request: with partial messages on, a `ping` stream event is now sent every 30 seconds on the Anthropic API, Claude Platform on AWS and gateways
- Improved `/resume` and `claude --resume` on a session that is running in the background: they now open that session instead of refusing, and a prompt given with `claude --resume <id> "prompt"` is sent to it as its next turn
- Improved per-turn performance when many permission deny rules and MCP tools are configured
- Improved responsiveness when leaving the ctrl+o transcript view in long sessions when fullscreen rendering is off
- Improved Bedrock, Vertex and Mantle start-up model checks to send the same User-Agent, x-app and session ID headers as regular requests
- Changed MCP tools so a tool that sets its own `_meta['anthropic/alwaysLoad']` to false stays deferred when its `--mcp-config`, Agent SDK or plugin server is set to `alwaysLoad`
- Changed background Bash and PowerShell commands to stop after a time limit (their `timeout` with `run_in_background`, default 30 min, max 2 h); Claude is notified when one is stopped
- Changed Code Review’s pull request reviews and `/ultrareview` to run when `disableWorkflows` is on, unless the machine running the review has it set by its own administrator (MDM or the managed-settings file)
- Changed sessions behind a custom `ANTHROPIC_BASE_URL` to use the 1M context window of models that have one (Opus 4.7+, Sonnet 5+, Fable); run `/autocompact 200k` if your gateway stops at 200K
- Changed Team and Enterprise sessions, and sessions whose sign-in plan Claude Code can’t determine, to withhold WebFetch until the organization policy loads if it couldn’t be loaded at startup
- Changed /memory so that Auto-memory can no longer be turned on from a background session or from a session one of Claude Code’s own tools started; turning it off there still works
- Changed the one-time offer to make auto mode your default permission mode to also show on third-party providers and with telemetry off, when your user settings default to another mode
- Changed `claude -p` and Python Agent SDK sessions on third-party providers or with telemetry off to start in auto mode when no permission mode is configured, like interactive sessions; `--permission-mode` still overrides it
- Changed Bedrock, Mantle and Claude Platform on AWS requests to a base URL with a non-default port to include the port in the SigV4-signed Host header
- Changed the MCP server name `widgets` to be reserved in cloud sessions and on self-hosted runners: your own server under it, or a close spelling such as `widgets_`, no longer loads, so rename it
- Changed `/ultrareview` on macOS and Linux to leave symbolic refs out when uploading a local checkout; a checkout whose current branch is a symbolic ref is now refused with an explanation
- Windows: Changed project and local settings `env` to no longer set `ALLUSERSPROFILE`, `SystemDrive`, or the `CommonProgramFiles` variables; set them in user or managed settings instead
- Changed `/tasks` to fold background work Claude Code runs for itself under one “System tasks” row; press Enter on it to show those tasks
- Changed `/ultrareview` on macOS and Linux to require git 2.31 or newer to upload a local repository; checkouts made with `--separate-git-dir` are now refused instead of being uploaded with an older method
- Changed `/ultrareview` uploads on macOS and Linux to send a partial clone as a working-tree snapshot on git 2.31 or newer, instead of falling back or refusing when git’s version looked too old
- Changed `/ultrareview` uploads on macOS and Linux to refuse, instead of fetching, a partial clone missing some of its working tree’s files on older git versions; a clone made without `--filter` uploads
- Changed Bedrock, Vertex and Mantle start-up model checks to identify themselves as Claude Code, like other Claude Code requests
- Changed `claude mcp get` to hide the command, arguments, and environment values of stdio MCP servers provided by plugins; variable names are still shown
- Changed `/claude-api` so it can no longer be run from Remote Control clients
- Changed `/config chrome=true` to direct you to the /config panel instead of enabling Claude in Chrome by default; `/config chrome=false` still turns it off when it was on
- Changed sandbox settings so project settings cannot widen or turn off an admin-required sandbox, replace the proxy behind a managed deny list, extend a strict allowlist, or reopen managed read-denies
- \[VSCode\] Added a note under a restored tab’s last message when a window reload interrupted it and no reply will follow
- \[VSCode\] Added a plugin options form to Manage plugins: installing a plugin that has options asks for the unset ones, and a gear on its row changes them later
- \[VSCode\] Added an on-demand diagnostics tool so Claude in the panel can read the Problems panel’s current errors and warnings at any time, not only right after it edits a file
- \[VSCode\] Fixed pressing Enter after typing a slash command running an unrelated menu item picked by fuzzy match, or doing nothing
- \[VSCode\] Fixed an open agent transcript losing the agent’s newer messages during a long session
- \[VSCode\] Fixed a message that quotes a Claude Code or IDE tag losing the rest of its text in the chat
- \[VSCode\] Fixed a message sent while Claude was working disappearing from the conversation after the session was reopened
- \[VSCode\] Fixed the session list’s Web tab showing the previous account’s sessions after an account switch
- \[VSCode\] Fixed restored tabs re-running an interrupted turn when VS Code was started with `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` set, even with Continue After Reload off
- \[VSCode\] Fixed Escape stopping the running turn instead of closing the command menu after clicking one of its rows
- \[VSCode\] Fixed opening Past conversations replacing a live conversation with its saved copy
- \[VSCode\] Fixed a Claude tab reloaded after an extension restart staying blank instead of saying how to recover
- \[VSCode\] Fixed opening a conversation that is already open in another window or app starting a second copy of it without warning; it now asks first
- \[VSCode\] Fixed a hook’s reason for blocking or stopping a prompt disappearing after a window reload
- \[VSCode\] Fixed tabs stuck on a conversation that can’t be resumed: the error now says so and offers to start a new conversation
- \[VSCode\] Fixed every file Read, Write and Edit stalling for ten minutes and then being skipped when the editor stops responding to the extension’s automatic save before the tool runs
- \[VSCode\] Fixed the agent map labeling a sub-agent with the session’s model instead of the model it actually ran on (e.g. under `CLAUDE_CODE_SUBAGENT_MODEL_FORCE` or an agent’s own `model`)
- \[VSCode\] Fixed uninstalling a plugin from the Manage plugins dialog, which removed the wrong installation or failed for a plugin installed for the project
- \[VSCode\] Fixed sign-in staying on the authorization-code step after going back and choosing the same sign-in method again
- \[VSCode\] Fixed the chat panel stalling when a long session trims its oldest rows
- \[VSCode\] Fixed the conversation disappearing from a session when many agents run
- \[VSCode\] Fixed the editor tab keeping an old name after a session was renamed with /rename, by a SessionStart hook, or on claude.ai
- \[VSCode\] Fixed the agent map’s transcript view leaving out messages sent to a running agent
- \[VSCode\] Improved the Manage plugins dialog: a failed plugin action now opens a popup that explains it and, where there is one, offers the fix
- \[VSCode\] Changed the Manage plugins dialog to ask before removing a marketplace or turning off a plugin that your project’s shared `.claude/settings.json` turns on
- \[Cloud sessions\] Fixed Run now on a routine showing internal error text when the run is refused before it starts; it now shows the same explanation as the routine’s failure notification
- \[Cloud sessions\] Changed `MCP_DISCOVERY_CACHE=1`, when set in your cloud environment’s variables rather than a settings file, to reuse your connectors’ tool lists after a session restart; other MCP servers are no longer cached and connect at startup
- \[Claude Tag\] Added direct messages with Claude for members on an Enterprise plan Standard or Usage-Based Chat seat who also have Cowork; a seat that includes Claude Code is no longer required
- \[Claude Tag\] Fixed the Default model setting in admin settings and a channel’s Configure page offering models your organization can’t use, which made saves or new sessions fail
- \[Claude Tag\] Fixed the note under Claude’s Slack messages saying it answered on a fallback model, and why, disappearing when Claude later edited that message
- \[Code Review\] Fixed the organization menu in Code Review’s “Add a repository” dialog showing only a few of your GitHub organizations; it now loads more as you scroll
- \[Code Review\] Improved the Code Review check run to say when your repository’s REVIEW.md wasn’t applied, for example on a very large pull request or when REVIEW.md is a symbolic link
[](#2-1-284)
2.1.284
September 28, 2026
- Added Claude Sonnet 5.5 (`claude-sonnet-5-5`), now the default Sonnet model on the Anthropic API — 1M context, $2/$2/10 per Mtok with \$0.20/Mtok cache reads
- Added a “Yes, but ask again next time” answer to auto mode’s prompt before a read outside the working directories, so you can allow that one read and still be asked about later ones
- Added dollar amounts to the Claude apps gateway spend limit in `/usage` and the status line (for example “$271.40/$271.40/500.00 spent this month”) when the gateway runs this version or later; the status line’s `rate_limits.spend_limit` also gains `used_usd`, `limit_usd` and `period`
- Added `effortSlider:decreaseEffort`, `increaseEffort` and `toggleUltracode` keybinding actions, so the `/effort` slider’s arrow and Tab keys can be rebound in `keybindings.json`
- Added `/rate-limit-options` to `/help` and the command menu for claude.ai subscribers, so the usage-limit notices that mention it point to a command you can find
- Added `/mcp reconnect all` in the interactive terminal to retry every MCP server that failed to connect or needs authentication at once
- Added Claude apps gateway startup warnings when a managed policy’s `availableModels` is empty, or leaves out the model Claude Code starts on without setting `model` or `enforceAvailableModels`
- Added `auth: { google: {} }` for Claude apps gateway `telemetry.forward_to` destinations, so telemetry can be exported straight to Google Cloud’s OTLP endpoint using the gateway’s Google Cloud credentials
- Added certificate client authentication (`private_key_jwt`) between the Claude apps gateway and its identity provider, for identity providers that issue certificate credentials instead of client secrets
- Fixed a damaged response stream showing raw errors such as “JSON Parse error” or “undefined is not an object”, or writing the word “undefined” into an answer, instead of being retried or reported as an interrupted response
- Fixed an overloaded or server error arriving right after a thinking block ending the turn with an error instead of being retried
- Fixed “Prompt is too long” errors that persisted after compacting: when the compacted request is still too long, Claude Code now compacts once more, keeping less of the recent conversation
- Fixed a session whose model is unavailable, with no fallback model left, showing a bare “is currently unavailable” message (or “Something went wrong” in cloud sessions) instead of the model-unavailable notice and its Learn more link
- Fixed Agent SDK sessions crashing when a user message contains an image with a malformed `source`, and failing on every later turn after a malformed document block; a malformed image is now replaced with an explanatory note
- Fixed MCP tool calls in a resumed session failing with “No such tool available” while their server was still connecting; the call now waits up to 10 seconds for the server
- Fixed repeated calls to the plan-usage endpoint after it rate-limits or rejects your login: `/usage`, `/extra-usage` and IDE usage views now back off instead of re-asking
- Fixed `claude mcp add` reporting success when managed settings restrict MCP servers to plugins; it now refuses and says what to do, instead of saving a server that never loads
- Fixed the `/plugin` configure screen: boolean options are now a true/false choice instead of free text, number options refuse invalid input, and ←/→ change an options field instead of switching tabs
- Fixed `ANTHROPIC_FOUNDRY_RESOURCE` being interpolated into the Foundry endpoint host unvalidated; a value that is not a plain resource name is now refused
- Fixed Claude Desktop behind a Claude apps gateway offering no 1M context option: the gateway now marks each 1M-capable model for Desktop automatically
- Fixed ↓ in shell mode selecting a hidden background-tasks pill, which stopped Backspace and Ctrl+U from editing the prompt
- Fixed Bash tool failing on Windows with many plugins enabled: plugin `bin/` directories that don’t exist are no longer added to PATH, and inherited entries aren’t added twice
- Fixed `sparsePaths` plugin marketplaces cloning empty and replacing a working local copy on older git (before 2.39), which failed every refresh with “marketplace.json file is no longer present”
- Fixed fullscreen rendering erasing the terminal output above the session when `[` in transcript mode writes the conversation to scrollback (macOS and Linux)
- Fixed fullscreen scroll position jumping to the previous message or to the bottom when a reply finished streaming while scrolled up
- Fixed tab bars in dialogs such as `/config` and `/plugin` breaking the title and tab labels mid-word in a narrow terminal; a tab that doesn’t fit now moves to the next line whole
- Fixed the `/model` picker showing “+1 model” below the list after scrolling to the last model; the count now covers only the models below the visible rows
- Fixed `/keybindings` writing Backspace and Delete bindings for a footer action that does nothing into the generated `keybindings.json`
- Fixed a rebound agent panel close key (`footer:close`) typing “x” instead of itself on the row of the agent you’re viewing
- Fixed vim mode `.` not repeating text typed very fast (for example over ssh or in tmux) or pasted without bracketed paste, and leaving the prompt in INSERT mode after repeating a change with nothing typed (such as `cw` then Esc)
- Fixed vim mode leaving the cursor on an image placeholder’s opening bracket after `dd` on the last line or `yy` at the end of the prompt, where `r` or `x` would break or delete the image
- Fixed a key pressed the instant the terminal regained focus answering the Remote Control enable prompt before its short safety delay restarted
- Fixed the workspace trust dialog appearing a second time after switching renderers or updating when Claude Code was started in the home directory
- Fixed rules symlinked into `.claude/rules` from outside the project being skipped without ever showing the external-imports approval prompt; a `.claude` directory symlinked from outside the project now asks for the same approval
- Fixed plugins from marketplaces, claude.ai and npm pre-approving their own tools via `allowed-tools` under managed `allowManagedPermissionRulesOnly`; only plugins from an official Anthropic source or a source that managed settings vouch for keep that pre-approval
- Fixed a failed first `claude plugin install` leaving the plugin enabled and recorded when a dependency’s version range could not be met
- Fixed the debug log dropping a failed hook’s stderr when the hook also wrote to stdout, and logging nothing for a failed hook with no output; failed hooks now also log their status code
- Fixed `{"decision":"block"}` returned by Elicitation and ElicitationResult hooks being ignored; it now declines the MCP elicitation, as exit code 2 does
- Fixed sessions launched without the `SendMessage` tool (such as by Claude Desktop) still being told to message other sessions with it
- Fixed a photo sent from the Claude app over Remote Control being lost when its queued message was pulled back into the terminal prompt to edit, and the cursor moving one character for a photo with no caption
- Fixed typing a message during an automatic usage-limit wait taking the wait out of the “Continue automatically at usage limit” setting’s control when that turn hit the limit again
- Fixed usage-limit warnings suggesting `/upgrade` to users already on the highest Max plan; the warnings and `/upgrade` itself now point at `/usage-credits` when it is available
- Fixed the Explore subagent switching to Opus on the Claude API when the session runs a model ID Claude Code doesn’t recognize, such as a custom model behind a proxy; Explore now inherits that model
- Fixed `/loop` status updates in self-paced mode often not being shown because Claude wrote them only in its reasoning; Claude now writes each update, and the outcome when the loop stops, as visible text
- Fixed `/ultrareview` failing to upload the working tree when started from a git worktree that the Claude desktop app created on macOS or Linux
- Fixed sandboxed Bash commands failing to start on Linux when the working directory is write-denied and contains a read-denied directory
- Fixed artifact database write results telling Claude that every viewer sees a write to a viewer’s private `data/users/` subtree, and added a “view” level to `as_level`
- Fixed the Claude apps gateway answering `431 Request Header Fields Too Large` to every request from a sign-in whose identity provider lists many groups; it now accepts request headers up to 256 KiB
- Improved the usage-limit wait: the limit’s state and the countdown with the usage-credits option now show as one block under the prompt, and limit messages no longer repeat the countdown
- Improved the “No such tool available” error for Claude in Chrome tools called without their prefix: it now names the tool to call
- Improved Monitor event rows to show what each event printed instead of repeating the description, and stopped repeating an unchanged “Waiting for N … to finish” line after every event
- Improved Workflow tool sandbox hardening for errors thrown by async script hooks
- Improved startup time and memory use by building only the parts of the settings schema that your settings files actually use
- Improved `/claude-api`: `hillclimb` no longer spends rounds on prompt rewordings too small for the eval to measure, and an extra page you ask for beside `report.html` is built as one local file that loads nothing from the network
- Improved lists such as `/tasks`, `/copy` and `/hooks`: the details after each name now line up in one column when they fit, and otherwise sit at the right edge
- Improved `claude plugin marketplace add` to say when it replaces a marketplace already added under the same name from a different source, and how to undo it
- Improved the startup refusal when managed settings require a sign-in (`forceLoginMethod` or `forceLoginOrgUUID`) and an API key, token or `apiKeyHelper` is configured: it now names the credential in use, where it is set, and how to remove it
- Improved auto-memory loading: invisible characters and tags that imitate Claude Code’s own markup are neutralized in `MEMORY.md` and recalled memory notes before they reach Claude
- Improved `claude remote-control`: in a folder you haven’t trusted yet, it now asks for workspace trust on the terminal instead of exiting
- Improved artifact pages: Claude writes its design plan into the page instead of the reply, and uses the name you already gave something as the page title
- Improved the Artifact tool so that when Claude is given a claude.ai chat or project link, an artifact from a chat, or an artifact id on its own, it asks for the right link or the content instead of stopping
- Changed interactive terminal and VS Code sessions to start in auto mode when no permission mode is configured, on every plan and provider; `permissions.defaultMode` still overrides it
- Changed Ultracode into its own toggle in `/effort` (Tab, or `/effort ultracode [on|off]`): it no longer forces xhigh effort and stays on at any effort level
- Changed retries after a dropped connection mid-response to share one budget with the rest of the request’s retries, so a failing request gives up sooner
- Changed the notice shown when a Sonnet model’s safeguards flag a message to explain why it happened and to offer editing and retrying
- Changed safety-related model switches in sessions that pin an Opus model with `ANTHROPIC_DEFAULT_OPUS_MODEL` or `modelOverrides`: on the Anthropic API, the API now picks the model to switch to for each kind of flag, not the pinned model
- Changed the non-interactive first turn to still wait up to 2s for connecting MCP servers named by `--allowedTools` or an `mcp_tool` hook, even when `CLAUDE_CODE_MCP_STARTUP_WAIT_MS` is `0`
- Changed `/recap` to decline with a short notice when it arrives relayed from a chat thread (your own included) or from a routine or webhook; typed in the terminal, the Claude apps, Remote Control, `-p` or an SDK host, it runs as before
- Changed `/artifacts` to show its filter tabs beside the title with one-word labels (All, Mine, Shared), using the same tab bar as `/config` and `/plugin`
- Changed artifact publishing to refuse a file on a network share (a `\\host\share` path or a `/net` automount) unless it is on a mapped network drive added with `--add-dir`
- \[VSCode\] Added an optional time above each prompt and response, with a date line where the day changes (Claude Code: Show Message Timestamps setting, off by default)
- \[VSCode\] Added plugin load errors and notes to the Manage plugins rows, with a popup to disable, uninstall or copy the error
- \[VSCode\] Added an Ultracode on/off switch under the Effort slider, replacing the slider’s Ultracode stop; the model pill shows ”· Ultracode” at any effort level
- \[VSCode\] Fixed Reload Claude from the Memory dialog restarting before an edited file was saved
- \[VSCode\] Fixed a restored tab opening a conversation another Claude process still has open; it now asks first
- \[VSCode\] Fixed Focus view sections you expanded closing on their own while a sub-agent is working or when the section’s first step is trimmed from view
- \[VSCode\] Fixed typing `/model` and Enter printing usage text into the chat instead of opening the model selector
- \[VSCode\] Fixed `/feedback` on Vertex, Bedrock and Foundry being refused after you pressed Send; the report is now saved on this computer, as the terminal does
- \[VSCode\] Fixed sign-in waiting up to a minute for the Python extension after a window reload
- \[VSCode\] Fixed Claude Code tabs that stopped responding after Restart Extensions: they now reopen on their conversation
- \[VSCode\] Fixed a message from another agent with no recorded sender showing as raw XML in the chat
- \[VSCode\] Fixed messages from other agents, sessions or channels disappearing after a reload
- \[VSCode\] Fixed a user’s own `/mcp`, `/config` or `/settings` command being shadowed by the extension’s dialog
- \[VSCode\] Fixed Escape stopping every background agent when no turn was running
- \[VSCode\] Fixed plugin install links replacing a marketplace you already have that uses the same name
- \[VSCode\] Fixed “Prompt is too long” errors after compaction when a large text file is attached to a message
- \[VSCode\] Fixed chat links to files with non-ASCII characters, spaces or brackets in their path not opening
- \[VSCode\] Changed `CLAUDE_CONFIG_DIR` in the `claudeCode.environmentVariables` setting to apply only when it is an absolute path, and passed it to terminals that continue the chat
- \[Cloud sessions\] Fixed a routine’s Edit and Duplicate controls saying the routine was still loading while you were offline; they now tell you you’re offline
- \[Claude Tag\] Added model family choices such as “Opus (latest)” for a thread, a channel default or your DM, so the choice follows the newest model in that family
- \[Claude Tag\] Added the spend that counts toward your organization-wide limit to the analytics spend projection chart, with how much of the limit is used
- \[Claude Tag\] Fixed the earlier Claude in Slack app’s progress card and link previews omitting the repository and Create PR button when a GitHub Enterprise host name contains an underscore
- \[Claude Tag\] Fixed Claude staying silent in a channel whose environment declines to start it; it now posts one notice asking you to contact an admin, and retries when @-mentioned
- \[Claude Tag\] Changed Claude to post its private sign-in notice at every @mention from someone who hasn’t connected their Claude account, instead of going quiet after the first
- \[Claude Tag\] Improved “Notify members now” in admin settings: one press reaches every workspace your organization claimed in an Enterprise Grid, and more members in large workspaces
- \[Claude Tag\] Improved Claude’s wait notice on self-hosted environments with on-demand runners: it now says whether a runner is starting, a start will be retried, or no runner will start
- \[Claude Tag\] Improved the error shown when adding a channel manager fails because the channel’s Slack workspace can’t be confirmed as connected to your organization
- \[Claude Tag\] Improved a channel’s access lists in admin settings to show the connectors, repositories and plugins an auto-join pattern attaches, and where each comes from
- \[Claude Tag\] Improved adding repositories as a channel manager: when your GitHub sign-in can’t confirm you’re a repository admin, the page asks you to sign in with GitHub
- \[Code Review\] Fixed Code Review giving up without posting a finished review when an unsubmitted review under its GitHub App was open on the pull request; it now retries the post first
[](#2-1-283)
2.1.283
September 25, 2026
- Added `x-claude-code-prompt-id` to the gateway hint headers so LLM gateways can group the requests that serve one user prompt; opt in with `CLAUDE_CODE_GATEWAY_HINT_HEADERS=1`
- Added `availableModelsMatch` managed setting: with `"exact"`, an `availableModels` entry allows only the model version it names, so new releases stay blocked until listed
- Added `deniedModels` managed setting to block specific models, even when `availableModels` allows them
- Added MCP tool, WebFetch and WebSearch outputs to the `tool.output` OpenTelemetry span event when `OTEL_LOG_TOOL_CONTENT=1`
- Added `/doctor prompt-audit` (also `/checkup prompt-audit`) to audit your CLAUDE.md files, skills, agents and commands for prompting patterns written for older models
- Added click-to-expand for truncated messages from your other sessions in fullscreen mode
- Added `path` to `--plugin-dir` load-failure entries in the stream-json `system/init` `plugin_errors`, naming the directory that did not load
- Added an opt-in `load_test_mode` block to the Claude apps gateway config: requests are built and signed but not sent upstream, and clients get a canned reply, so a deployment can be load tested
- Added a `mantle` upstream provider to the Claude apps gateway for Amazon Bedrock’s Mantle endpoint
- Fixed SDK sessions losing a deferred tool call or finished tool result when a turn ended early, a held approval prompt after a worker restart, and a non-streaming fallback’s `result.usage`
- Fixed MCP progress notifications being discarded once a long-running tool call moved to the background; the background task now shows the latest progress
- Fixed stdio MCP servers being left running when the session ended while they were still starting
- Fixed a brief HTTP 404 from a stateless remote MCP server (for example a proxy mid-redeploy) leaving that server unusable for the rest of the session while still shown as connected
- Fixed MCP sign-in for a server with no valid URL failing with an opaque SDK error; `/mcp` no longer offers Authenticate for such servers
- Fixed the weekly Fable limit not appearing in `/usage` and the VS Code usage meters when telemetry is disabled
- Fixed `/model` accepting Sonnet 4.6 or Sonnet 5 with `[1m]` when the id carried a date or `-v1:0` suffix, in the cases where the plain id was refused
- Fixed `/model` picker showing a hardcoded Haiku version and price when `ANTHROPIC_DEFAULT_HAIKU_MODEL` pins a different model
- Fixed dynamic workflows started during a model fallback running every agent on the fallback model instead of retrying the configured model
- Fixed `DISABLE_PROMPT_CACHING_HAIKU` having no effect when Haiku is the session’s main model
- Fixed `claude plugin validate` saying Claude Code accepts a plugin or marketplace name it cannot install; such names in `marketplace.json` now fail validation
- Fixed `claude plugin validate` passing plugins whose `outputStyles`, `themes`, `monitors`, or `lspServers` paths are missing or point outside the plugin directory
- Fixed `claude plugin details` showing 0 MCP servers for plugins that declare their servers in `plugin.json`
- Fixed `claude plugin marketplace remove` not saying which installed plugins it uninstalled with the marketplace; it now lists them
- Fixed `claude plugin uninstall` removing the other of two installed plugins whose ids differ only in case, with its options and secrets, when the one named had no `enabledPlugins` entry at that scope
- Fixed plugins that declare no version being silently restored at their source’s newest commit, not the installed one, when their cached files were missing
- Fixed user-installed plugins and marketplaces failing to load with “cache-miss” after the home or config directory was moved, for example in bind-mounted devcontainers
- Fixed `installed_plugins.json` showing no plugins when it holds a record under an invalid plugin id; such a file loads again
- Fixed `installed_plugins.json` being rewritten, losing records, when it holds a record this version cannot read; `claude plugin` commands now name the record and say how to recover
- Fixed permission dialogs in screen-reader mode reading quoted commands and paths as if they were the dialog’s own text
- Fixed `/context` not counting MCP server instructions: they now appear as their own row and count toward the total
- Fixed markdown links in the Warp terminal rendering as plain text instead of clickable hyperlinks
- Fixed `claude mcp add`, `add-json`, and `remove` reporting success when the user or local config file could not be written, for example inside a sandbox
- Fixed the first words of a reply in a cloud session sometimes appearing late instead of streaming as Claude writes them
- Fixed Claude’s built-in keybindings guide saying chords time out after 1 second instead of 3, and calling `cmd` an alias of `meta`, which could produce `cmd+` shortcuts most terminals never send
- Fixed `keybindings.json` silently accepting a misspelled modifier such as `ctl+k`; it now warns in the debug log and suggests the fix
- Fixed footer hints still saying “Enter to view” after `footer:openSelected` was rebound or unbound in `keybindings.json`
- Fixed keys typed quickly together (type-ahead, key repeat, bursts over ssh or tmux) sometimes being handled against stale state
- Fixed worktree checkouts failing certificate verification (for example on Git LFS downloads) when the CA certificate is passed to git as `GIT_CONFIG_COUNT` environment pairs
- Fixed sandboxed `git` asking credential helpers to store the sandbox proxy’s login, which printed “failed to store”
- Fixed managed `sandbox` settings being ignored entirely when one nested value was invalid; the invalid value now fails closed and the rest of the block still applies
- Fixed Claude’s edits to its own auto-memory notes being blocked as sensitive-file writes when Claude Code was started in a subdirectory of a git repository
- Fixed Remote Control being unavailable on paid plans when telemetry is turned off with `DISABLE_TELEMETRY` or `DO_NOT_TRACK`
- Fixed the `/remote-control` menu cutting its QR-code hint mid-word in narrow terminals
- Fixed vim mode `.` dropping a Shift+Enter newline, leaving the cursor inside an accented letter, and repeating an older change after `3J` or Visual-mode `J` on the last line
- Fixed vim mode cursor placement: recalling a prompt over 10,000 characters in normal mode no longer leaves the cursor past the end, and `V` then `p` now lands on the first non-blank
- Fixed vim mode `J` joining lines with different spacing than Vim (such as a space before `)` or after a tab), and `3J` or Visual-mode `J` on the last line not moving the cursor as Vim does
- Windows: Fixed the PowerShell tool letting `cmd /c rd`, `rmdir`, `del` or `erase` delete drive roots, the home folder and other folders that `Remove-Item` refuses
- Improved the `/mcp` tool list: it shows more tools at once, scrolls with the page keys and mouse, and marks tools your organization blocked with a warning icon
- Improved MCP tool results: images returned by MCP tools are now also saved to a file, so Bash, Read and other tools can open them
- Improved `/tasks`: rows show a status icon, the name and whole facts, the title and key hints stay on screen with many tasks, and the list gains paging keys, the mouse wheel and clicks
- Improved lists in `/help`, `/hooks`, `/copy`, `/chrome`, `/memory`, `/ide`, `/release-notes`, `/rewind`, `/diff`, `/remote-env`, `/plugin` and other pickers with page keys, mouse wheel and clicks
- Improved lists beside a search box, such as `/skills` and `/artifacts`, to draw their pointer dim while the search box has the keys, so only one pointer is highlighted
- Improved the compaction spinner: its timer now starts when compaction begins and it counts the summary’s tokens as they stream, replacing the percentage bar
- Improved the browser page shown after signing in to an MCP server: centered layout, dark mode, and new artwork
- Improved the Skill tool’s reply when a skill belongs to a plugin that failed to load, so Claude tells you the plugin could not be loaded instead of calling the skill uninstalled
- Improved `prompt-audit` on Claude Code configuration: stale paths, stale commands and contradicting instruction files now lead the report, and thinking keywords that Claude Code documents are kept
- Improved recovery from an `installed_plugins.json` that cannot be read at all: its contents are kept in a file beside it before it is rebuilt, and `claude plugin list` names that file
- Improved artifact database reads: an ordered query that returns a full page now says it is one page and how to read the rest
- Improved first-reply latency: a pattern-compile step that ran at the end of a session’s first reply now runs while the reply streams in
- Improved first-request latency by reusing the preconnected API connection
- Improved startup: `claude -p` and Claude Code Remote no longer load the interactive UI, and the auto-mode classifier’s rules and the Artifact tool load on first use instead of at launch
- Improved startup for claude.ai accounts whose Artifact tool features aren’t known yet, as on a first run: the prompt no longer waits up to 1.5 s to check them; the first message waits if needed
- Changed interactive sessions on third-party providers or with telemetry off to start in auto mode when no permission mode is configured; `permissions.defaultMode` still overrides it
- Changed the `/ultrareview` launch dialog to say that reviewing a local branch may upload uncommitted changes to tracked files
- Changed the `/model` picker’s Opus row and the Default model’s name to drop “(1M context)” where Opus already has a 1M context window; the window is unchanged
- Changed prompt suggestions in the terminal to appear less often after 20 in a row go unused; using one brings them back
- Changed `--system-prompt` and `--append-system-prompt` to accept their text and `-file` forms together; the file’s text comes first
- Changed `Skill(anthropic-skills:<name>)` deny rules to also block that skill when Claude Desktop delivers it as a plugin, and `Skill(skill:<name>)` denies to match the skill’s alias and display name
- Changed `/rewind` and `/diff` lists to move on the same keybinding actions as every other list (`select:*`); `messageSelector:*`/`diff:*` rebinds still work
- Changed the `/workflows` run list to size itself like other lists: half the terminal inline, and it keeps its title on screen when the prompt shows below
- Changed `claude plugin eval` to require git 2.31 or later when git is installed; a run on an older git is refused with a message naming the version
- Changed artifact watching: a watch that was armed automatically (not one you asked for) now ends after 3.5 hours with no activity; publishing or watching the artifact again re-arms it
- Self-hosted runner: Changed lifecycle hooks’ git to skip a repository’s Git LFS `pre-push` hook, ignore a writable system `core.hooksPath`, and not sign commits without `--configure-git`
- Self-hosted runner: Changed `GIT_SSL_CAINFO` and `GIT_SSL_NO_VERIFY` under Anthropic-managed git: the runner’s own git always verifies Anthropic’s git route, and warning lines say what applies where
- Reverted the 2.1.282 reservation of the `claude-ai` name: skills, commands, workflows and MCP servers’ skills and prompts so named load again, and `Skill(claude-ai:*)` rules are ordinary prefix rules
- \[VSCode\] Fixed the permission mode indicator showing Default while the session kept running in auto or bypass mode after an automatic switch out of it failed; the switch is now retried until it lands
- \[VSCode\] Fixed a session teleported from the web dropping the messages sent while Claude was working
- \[VSCode\] Fixed a Web session staying hidden from the session list, and an empty chat opening in its place, when an older version had saved an empty local copy of it
- \[VSCode\] Fixed a reopened session splitting a turn at a message Claude received mid-turn, such as an automatic continuation
- \[VSCode\] Fixed a reloaded session showing a rewound-away turn, or only the rows before a compaction
- \[VSCode\] Fixed the footer’s agents pill drawing its icon off-center, with the status dot against the edge, in narrow panels
- \[VSCode\] Fixed the chat input showing its text slightly below the cursor and selection after pasting lines that end with a line break into a long prompt
- \[Cloud sessions\] Improved adding a repository to a running cloud session: a private repository your GitHub account can read but not push to now attaches for reading
- \[Cloud sessions\] Fixed cloud sessions occasionally redoing an already-finished step, such as posting a duplicate comment or push, after recovering from a server-side restart
- \[Cloud sessions\] Changed new routine schedules to default to a few minutes past the hour, with a note that routines set exactly on the hour can start several minutes late
- \[Claude Tag\] Added a “Channels Claude can search” admin setting that limits Claude’s Slack search to public channels it has been added to, set per organization, workspace or channel
- \[Claude Tag\] Added a Back to Slack button on the page shown after connecting your Claude account, returning you to the thread you started from
- \[Claude Tag\] Fixed a channel’s configure page listing no connectors or plugins when the channel gets its access bundle through an attach rule; rule-attached bundles are now shown
- \[Claude Tag\] Fixed access-bundle repository search missing repositories on GitHub App installs that are limited to a large list of selected repositories
- \[Claude Tag\] Fixed Claude occasionally posting the same reply twice when a new message interrupted it mid-reply
- \[Claude Tag\] Fixed channel routines that stopped running in older private channels whose Slack channel ID changed, for example after a Slack Connect share
- \[Claude Tag\] Fixed conversations in a channel set to “Channel only” all ending when a non-guest member joined and Slack was slow to confirm their membership
- \[Code Review\] Fixed “@claude review” requests going silent when GitHub failed to return the pull request: the request is retried once, and a comment explains if it still fails
- \[Code Review\] Fixed billing for a review that stopped at its time limit with nothing verified: it now shows as incomplete, isn’t charged, and is retried once
[](#2-1-282)
2.1.282
September 24, 2026
- Added a `maxProseWidth` setting that caps the width of Claude’s prose in wide terminals while tables and code blocks keep the full width
- Added a startup notice, and `/status` and `claude doctor` entries, listing telemetry variables in a project’s settings files that were ignored or that turned telemetry off
- Added the `allowClaudeInChromeWithManagedMcp` managed setting to let `claude --chrome` run alongside an exclusive `managed-mcp.json`; the error shown when Chrome is blocked now names it
- Added `store.readiness_grace_seconds` to the Claude apps gateway so `/readyz` can stay ready through a short Postgres outage such as a database failover
- Added a scrollbar to the `/feedback` drafts list in fullscreen mode; it appears while the mouse is over the list
- Fixed every request failing with a 400 error in conversations whose history holds web search results the API cannot decrypt (for example, from a turn answered through a third-party gateway)
- Fixed more cases of continued or resumed sessions (`--continue`, `--resume`) re-sending earlier messages in a changed form, which could make the API drop Claude’s earlier reasoning
- Fixed earlier extended thinking being dropped when `/model`, `/rename`, `/artifacts` or another immediate slash command was used while Claude was working
- Fixed continued or resumed conversations losing earlier extended thinking when relaunched with a `--tools` list that leaves out a built-in tool offered earlier in the conversation
- Fixed sessions failing on every turn with an “Invalid `data` in `redacted_thinking` block” API error; Claude Code now drops the conversation’s thinking blocks and retries once
- Fixed compaction failing when the summarization request is refused; it now retries on a fallback model
- Fixed a failed turn (“Effort ‘xhigh’ isn’t available with thinking turned off”) after a safety-related model switch in sessions with thinking off and effort above high
- Fixed an unanswered Fable usage-credits prompt switching models in SDK-hosted sessions such as Claude Desktop; the turn now ends instead, and Remote Control clients now see the model-switch notice
- Fixed `/model` with a full Fable model id stopping at an API error instead of opening the usage-credits prompt when the plan needs usage credits that aren’t turned on yet
- Fixed requests failing for up to a minute with an “another Claude Code process is refreshing it” login error after that other process was closed or killed mid-refresh
- Fixed sessions started while another Claude Code window was refreshing the sign-in (common with several VS Code windows) not retrying their organization policy fetch
- Fixed CLAUDE.md and rules being read at startup through a repository symlink reaching macOS’s `/Network` via `..` or a `/.vol`-style kernel path, or a rules link to macOS’s `/home` being listed
- Fixed Bash permission rules with a mid-pattern `:*` being skipped in settings files while `--allowedTools` honored them; they now work from every source, with a startup warning on how they match
- Fixed a command approved on a restored permission prompt running twice when a remote session’s worker restarted
- Fixed managed settings ignoring a mistyped value for boolean lock keys such as `disableClaudeAiConnectors` or `allowManagedPermissionRulesOnly`; the lock now applies and startup names the key
- Fixed managed `permissions`, `autoMode`, `worktree` and `attribution` settings being ignored entirely when one nested value was invalid; the rest of the block now still applies
- Fixed repository, user and `--add-dir` skills, commands and skills-directory plugin manifests pre-approving their own tools via `allowed-tools` under managed `allowManagedPermissionRulesOnly`
- Fixed safeguard block messages on Amazon Bedrock and Bedrock Mantle not showing a request ID; block messages now also show the message ID
- Vertex AI: Fixed web search not being offered for models Claude Code doesn’t recognize yet, such as newly released ones
- Fixed Bash and PowerShell hiding a full disk quota behind “Exit code 1” and leaving large output files in temp
- Fixed tool input validation errors naming only an unknown, missing or mistyped parameter when other parameters in the same call were also invalid; those are now listed too
- Fixed pasted multi-line text being submitted line by line after the terminal’s bracketed paste mode was reset mid-session
- Fixed the prompt’s example text flashing and disappearing at startup in projects with a `SessionStart` hook
- Fixed a blank screen flashing before the first frame when starting in fullscreen mode
- Fixed garbled, misplaced rows in the non-fullscreen renderer after the screen got shorter while still taller than the terminal, e.g. deleting a prompt line while a shell command streams output
- Fixed a stale character left in the last column of a diff when a redrawn line’s CJK character or emoji wrapped to the next row
- Fixed the cursor landing before the end of a prompt recalled from history when the prompt contains a tab
- Fixed the send-now hint showing ctrl+enter on terminals that send it as a newline (Windows Terminal before 1.25); it now shows ctrl+x ctrl+s there
- Fixed `claude remote-control --debug` failing with “Unknown argument: —debug”, although Remote Control’s own eligibility error says to run with `--debug`
- Fixed `/install-github-app` saying “cancelled” and then still pushing the branch and saving the API key secret; leaving now stops the remaining steps and reports what was already done
- Fixed /feedback, /bug and /share on Bedrock, Vertex and other third-party providers still saving the report file after you cancelled during the save
- Fixed plugin uninstall reporting success and deleting the plugin’s saved options when its settings file still enabled it or could not be read; it now stops and names the file
- Fixed plugin uninstall deleting a plugin’s saved options and secrets when the list of installed plugins could not be read after the removal; they are now kept and the uninstall says so
- Fixed a key typed right after `/` in `/skills` moving the skill list instead of reaching the search box
- Fixed the terminal cursor jumping from the `/skills` search box to the skill list while typing, which could hide the caret and put IME input in the wrong place
- Fixed lists with a scrollbar, such as `/skills` and `/mcp`, being two columns narrower outside fullscreen mode, where the scrollbar can never appear
- Fixed the agent panel footer wrapping onto two lines with long rebound keys, and its “Esc to collapse” hint ignoring a rebound collapse key
- Fixed a doubled `·` separator in the `/tasks` dialog footer when the stop-all-agents shortcut is unbound in `keybindings.json`
- Fixed artifact publishes failing when Claude gave the version a label longer than 60 characters; the label is now shortened
- Fixed screen-reader mode, quoted lists and very long lists dropping the blank lines at the top of a code block that opens a list item, directly or inside a quote
- Fixed PDF page-read error messages: paths with accented or non-Latin characters now appear readably, and a folder named like “password” or “invalid” can no longer make the error name the wrong cause
- Fixed vim mode `>>` indenting empty lines, `r` with a count longer than the line changing text, `2J` joining one line too many, and a count on the last line (`2dd`, `2>>`) shifting or deleting it
- Fixed vim mode cursor placement: after `dd`, `dj`, `dG` or a whole-line `p`/`P` it lands on the first non-blank, `yy` no longer moves it, and Esc after an emoji no longer leaves it inside the emoji
- Fixed vim mode ignoring a count typed before `.` when repeating `x`, `s`, `p`, `d` or `c`, and whole-line `p`/`P`, `o`, `O`, `J`, `>>` and `<<` acting on the wrong line when a line above wraps
- Fixed vim mode leaving the cursor past the end of a prompt recalled from history or pulled back from the queue in normal mode, so `x` did nothing
- Improved the time to resume very large sessions, including ones that were never compacted
- Improved the error shown on Windows when a session can’t be resumed because its transcript file could not be read (EBADF): it now names possible causes and what to try
- Improved the Claude Desktop unknown-model error to suggest switching to a different model
- Improved rendering of unusual Unicode in permission prompts
- Improved `/artifacts`: titles line up in one column, details are dropped whole instead of cut mid-word, and the list supports PgUp/PgDn, Home/End, the mouse wheel and clicks
- Updated the `claude-api` skill: pre-output refusal billing now links to the How refusals are billed docs, mid-stream refusals bill at normal rates, and pre-output refusals count against rate limits
- Updated the `claude-api` skill to recommend `ant apply` for keeping Managed Agents resources as version-controlled files
- Changed auto mode to use the server-side classifier by default on a direct Anthropic API connection when telemetry is off (`CLAUDE_CODE_AUTO_MODE_SERVER=0` opts out)
- Changed `sandbox.excludedCommands` to ignore project and local settings entries when managed settings or `--settings` set `allowUnsandboxedCommands: false`, or managed `allowManagedDomainsOnly: true`
- Changed project and local settings to ignore OpenTelemetry variables that turn on export, set its endpoint, or capture content, like `CLAUDE_CODE_ENABLE_TELEMETRY` and `OTEL_LOG_*`
- Changed Windows/WSL managed settings so an admin policy that is present but invalid or unreadable (HKLM, `managed-settings.json`) keeps user-writable HKCU and WSL `/etc/claude-code` from applying
- Changed `Skill(anthropic-skills:*)` and `Skill(claude-ai:*)` allow rules to cover only skills synced from claude.ai, not plugins or other skills that merely use such a name
- Changed skill folders, command files and workflow commands in the `anthropic-skills` or `claude-ai` namespace to no longer load; a plugin so named still loads but yields name ties to synced skills
- Changed MCP servers configured under the name `anthropic-skills` or `claude-ai` to list no skills or prompts (their tools still work); rename the server in your MCP configuration to list them again
- Changed the `ultracode` visuals in `/effort` and the prompt input to plain styling (no ripple, border flourish or keyword glimmer) and removed the dynamic-workflows spinner tip
- Changed the Clawd mascot’s feet in the start-up banner to sit under the corners of his body
- \[VSCode\] Fixed long replies falling behind the stream: the panel no longer re-parses the whole reply on every update
- \[VSCode\] Fixed the dictation mic button covering the message input’s scrollbar when the input is tall enough to scroll
- \[VSCode\] Fixed Remote Control sessions started on this computer not opening from their Web entry in the session list; they now open the local conversation unless it’s running elsewhere
- \[VSCode\] Fixed an editor tab’s sign-in screen hanging silently after the extension host restarts; it now shows the “stopped responding” notice too
- \[Cloud sessions\] Added Claude GitHub App status to Settings › Connectors › GitHub: whether the app is installed and reachable for your account, plus steps to connect, install or reconnect
- \[Cloud sessions\] Added “Open repository” and “Open compare page” links to the repository menu of a cloud session whose repository is hosted on a Git server other than GitHub
- \[Cloud sessions\] Added attaching a repository from a different GitHub owner, such as a fork’s upstream, to a running cloud session that already has one, including sessions started from Slack
- \[Cloud sessions\] Fixed the next run time shown for an hourly routine being 30 minutes off for people in half-hour-offset time zones such as India
- \[Cloud sessions\] Improved how quickly the Routines page and the sidebar’s Scheduled list load for accounts whose past sessions scheduled many check-in reminders
- \[Claude Tag\] Fixed auto-join channel patterns saved for one workspace in Claude Tag admin settings being ignored on an Enterprise Grid org-wide install; Claude now joins matching new channels
- \[Claude Tag\] Fixed Claude not responding in an Enterprise Grid channel shared between two workspaces of one organization when the channel’s Claude Tag version was saved from the other workspace
- \[Claude Tag\] Fixed the earlier Claude in Slack app’s progress card for sessions on a GitHub Enterprise Server repository: it now names the repository and offers a working Create PR button
- \[Claude Tag\] Fixed Slack threads whose model has been retired falling back to another model on every reply, slower and with a fallback note each time; the thread now moves to a working model
- \[Claude Tag\] Fixed files Claude uploads to Slack not being able to carry a caption containing a table; captions now render with the same formatting as replies
- \[Claude Tag\] Fixed Claude’s threads in Slack’s Agents & tools view sometimes being listed under their first message instead of their name; later renames now update the list too
- \[Claude Tag\] Fixed removing a GitHub organization’s grant from an access bundle’s Repositories tab in Claude Tag admin settings failing to save after that GitHub organization was disconnected
- \[Claude Tag\] Fixed Claude always replying “Couldn’t check this channel just now” in a channel shared with a Grid workspace it isn’t added to; the notice now says which workspace needs the app
- \[Claude Tag\] Fixed the cost and token totals in Claude’s reply footer reading many times too high after the session’s cloud worker restarted
- \[Claude Tag\] Changed the bordered cards Claude uses in Slack replies for plans, tables and details to render wide by default instead of a narrow width
- \[Claude Tag\] Changed newly connected Slack workspaces to follow the current default model instead of keeping whichever model was the default when they were connected
[](#2-1-281)
2.1.281
September 23, 2026
- Added Claude apps gateway support for newer Claude Desktop keys in `desktop` policy blocks, including `blockReadsOutsideWorkingDirectories` and `disableBypassPermissionsMode`
- Added `assume_role` on Claude apps gateway Bedrock upstreams: the gateway calls Bedrock as an IAM role it assumes through STS, in another AWS account if needed, optionally one session per developer
- Added `guardrail: {id, version}` on Claude apps gateway Bedrock upstreams to apply an Amazon Bedrock guardrail to every request sent through them (set it on all Bedrock upstreams or none)
- Added `telemetry.resource_attributes` to the Claude apps gateway config, to put fixed labels on the telemetry of Claude Desktop and `/login` sessions
- Added `"attribution": false` in `settings.json` to hide all commit and PR attribution; older CLI versions skip a settings file that holds it, so keep the object form in files shared across versions
- Added MCP URL-mode elicitation on 2026-07-28 protocol connections, so servers can ask Claude Code to open a browser-based flow; no waiting dialog is left on screen when the server has no way to confirm completion
- Added MCP server checks to `claude plugin validate`: it reports `.mcp.json` entries that would be silently dropped at load, undeclared `${user_config.*}` references, and insecure URLs
- Added an auto mode recommendation to `/insights` that estimates how many permission prompts auto mode could have handled in your recent sessions
- Added a scrollbar to the `/skills`, `/mcp` and `/plugin` Installed lists in fullscreen mode, like the one `/workflows` now has: it appears while the mouse is over the list and can be clicked or dragged
- Fixed a crash (“unrecoverable interface error”) that could end a session while an API request was being retried
- Fixed a turn that could retry indefinitely, ignoring `--max-turns`, when the model alternated unparseable tool calls and output-limit truncation
- Fixed resumed sessions re-sending earlier turns in a changed form (a parallel tool-call turn, an MCP tool call’s input or a tool-search result while its server was still reconnecting, or a tool-search result whose loading turn was interrupted), which could make the API drop the conversation’s prior reasoning
- Fixed resuming a very large session sometimes restoring only its last few messages
- Fixed a session resumed after a restart during a pending permission prompt sending a different history than before, which broke the prompt cache from that point
- Fixed resuming a session that ended during a tool call: Claude now sees the call and is told its outcome is unknown, and a manual resume no longer adds a hidden “Continue” message
- Fixed sessions with an earlier advisor result the API could no longer read failing one request every turn and repeatedly losing earlier reasoning; the history is now repaired once
- Fixed the prompt cache being lost when an MCP server disconnects mid-conversation, or is still connecting after a resume, while tool search is off (for example behind a proxy or gateway)
- Fixed responses cut short by a proxy or gateway that closes the stream cleanly being shown as complete with no warning, and tool calls running twice on duplicated stream events
- Fixed responses failing with “Content block not found” when a proxy drops a stream event mid-response; the partial response is now kept, and web search keeps results that already arrived
- Fixed an empty completed response being requested twice when the connection dropped before the stream’s final event
- Fixed the stop reason being lost when a proxy sends a trailing usage-only frame
- Fixed `CLAUDE_CODE_RETRY_WATCHDOG` sessions failing on the first 5xx or dropped connection after a run of 429/529 waits, and sleeping uncapped and silently on a long `Retry-After` from a 5xx
- Fixed fast mode retrying rate-limited requests back to back when the server sent `Retry-After: 0`
- Fixed a tool that returned an oversized image leaving sibling tool calls unanswered and still running, or ending the turn with no final message
- Fixed conversations getting permanently stuck on “tool_use.name: String should have at most 200 characters” after the model called a tool by an overlong name
- Fixed tool calls failing with “Failed to get memory usage”, or being reported as failed after they ran, when Claude Code cannot read its own memory usage, for example when it has run out of file descriptors
- Fixed `--input-format stream-json` sessions (Agent SDK, VS Code extension) and scheduled cloud sessions failing every turn with an error when an earlier assistant message had plain-string content
- Fixed non-interactive sessions (`-p`, Agent SDK) failing on the next turn after the directory they were started in was deleted mid-session
- Fixed headless sessions with host-side (SDK) MCP servers stalling on the first message when the host stops responding mid-handshake; remote sessions now wait a few seconds at most
- Fixed interactive startup waiting on the managed-settings network request (about 80 ms, 17+ seconds when the network is unreachable) when no MCP servers or plugins are configured
- Fixed a delay of up to two minutes before responding when reading or @-mentioning a PDF larger than 3 MB
- Fixed an interrupted Read of specific PDF pages leaving its page render running for up to two minutes
- Fixed permission dialogs and attachment checks reading a path under macOS’s `/.vol`, `/.nofollow` or `/.resolve` (which can reach a network mount) before approval
- Fixed a recursive `rm` whose target is only command-substitution output, such as `rm -rf "$(pwd)"`, running unprompted in auto and `--dangerously-skip-permissions` mode; it now asks even with a Bash allow rule, unless run with `CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT=1`
- Fixed a permission rule containing a NUL byte being expanded into a wildcard match; such a rule now matches nothing
- Fixed sandbox `excludedCommands` entries not matching `git rev-parse --git-dir`, programs named like shell builtins, and commit messages containing `[WIP]` or `#` lines
- Fixed sandboxed Bash commands being unable to write to `$TMPDIR` when `CLAUDE_CODE_TMPDIR` is set
- Fixed `claude --bg` starting a background session, and running its project hooks, in a directory that had not passed the workspace trust prompt; it now asks for trust first, or exits when not run interactively
- Fixed `--setting-sources` (and SDK `settingSources`) not being forwarded to spawned sessions: teammates, `/bg`, `claude agents` sessions and `--worktree --tmux` now start with the parent’s restriction
- Fixed Read, Write, Edit and NotebookEdit: a file path containing a null byte now fails that tool call with a clear error instead of ending the whole turn
- Fixed Write refusing a call that gives the file path or content twice under two parameter names with identical values
- Fixed CLAUDE.md and rules files from an `--add-dir` directory inside the working directory being sent to the model twice in headless and SDK sessions
- Fixed remote sessions staying on “needs approval” with a stale prompt after a permission prompt and a sandbox network-access prompt overlapped and both were answered
- Fixed cloud sessions not telling Claude about background agents that finished just before a worker restart
- Fixed scheduled routine and notification turns in remote sessions not receiving turn-start notices (newly available tools, MCP changes, date, todos) until after the first tool call
- Fixed scheduled tasks and `/loop` wakeups being fired again every second when their delivery failed, which could make Claude Code exit at the end of a turn
- Fixed Remote Control reporting “disabled by your organization’s policy” when the org policy simply hadn’t loaded yet; it now retries the fetch and says it couldn’t verify
- Fixed the Artifact tool missing from Remote Control sessions that `claude remote-control` starts for you to open from Claude Desktop, claude.ai or the mobile app
- Fixed macOS credential writes dropping stored MCP OAuth tokens or deleting the keychain entry when the login keychain was locked (e.g. right after wake)
- Fixed `gcpAuthRefresh`/`awsAuthRefresh` login processes being left running (and holding their localhost callback port on Windows) when Claude Code exits or the refresh times out
- Fixed the “Not logged in · Run /login” footer and missing claude.ai connectors persisting in a session after logging in from another Claude Code process
- Fixed `mcp_tool` hooks on blocking events (PreToolUse and similar) being skipped while their MCP server was still connecting; they now wait for it, up to the MCP connect timeout
- Fixed the same MCP server being connected twice when a plugin or claude.ai connector and a configured server spell its URL differently (host letter case, default port, trailing slash)
- Fixed `MCP_CONNECTION_NONBLOCKING=0` giving up on claude.ai connectors after 1s instead of honoring `MCP_CONNECT_TIMEOUT_MS`
- Fixed `--channels` plugin entries being checked against the installed plugin’s marketplace alone; the installed plugin’s name must now match the entry as well
- Fixed `--plugin-dir` on a folder of plugins that also has a `.claude-plugin/marketplace.json` loading one empty plugin instead of the plugins in it
- Fixed `claude plugin uninstall` refusing to remove a project-scope plugin that isn’t enabled, saying it is “enabled at project scope” while `claude plugin disable` says it is already disabled
- Fixed `claude plugin update` failing for project-scoped plugins when `--scope` is omitted — it now resolves the scope the plugin is installed at instead of assuming user
- Fixed `claude plugin validate` reporting `privacyPolicyUrl`, `supportUrl` and other listing metadata keys in plugin.json as unknown fields
- Fixed `known_marketplaces.json` recording a marketplace as refreshed when its remote could not be reached and `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE` kept the existing clone
- Fixed the `/plugin` Errors tab showing no confirmation after its last error is resolved
- Fixed `/plugin` starting a second uninstall or update of the same plugin when Enter was pressed again while the first was still running
- Fixed a `y` held while `/plugin` checks a marketplace source adding the marketplace the instant the “Add marketplace?” question appears, before it can be read
- Fixed `1` answering Yes in `/permissions`’ delete and remove-directory confirms while the pointer is on No, which let a held `1` remove one workspace directory after another
- Fixed Alt+T and `/config` offering to turn thinking off on models that can’t; thinking now stays on there, with a one-line reason in place of the switch
- Fixed `/context` total leaving out messages added since the last response; it now matches its categories and can read higher than the status line
- Fixed `/model` showing the raw API error JSON and request ID when the API refuses the picked model; it now shows the server’s message and says the model was not changed
- Fixed API errors from an HTML error page (such as a proxy’s 429 or 502 page) printing the page’s raw markup or leaving out the HTTP status, and error messages breaking onto a second line when the server’s error text ended in a newline
- Fixed /feedback, /bug and /share still sending your report after you cancelled it while it was being sent
- Fixed /feedback, /bug and /share failing every send with “Couldn’t send feedback” after a Remote Control Stop arrived while the dialog was open
- Fixed `/ide` showing “No available IDEs detected” while also listing a running IDE
- Fixed the terminal being left in a broken state (crash or garbled input) when `/setup-bedrock` or `/setup-vertex` restarts Claude Code to apply new settings
- Fixed `/config` exiting when `respectGitignore` or `copyFullResponse` in `~/.claude.json` holds `null`
- Fixed the session name from /rename disappearing while Claude asks a multiple-choice question, so side-by-side sessions stay identifiable
- Fixed one-line pastes showing on their own lines in the sent message for prompts from VS Code or Remote Control and for expanded paste placeholders
- Fixed a message queued while Claude is working losing or changing the IDE selection it was written with, and queued messages not showing their selection
- Fixed pressing Shift+Tab twice quickly landing on the wrong permission mode
- Fixed Ctrl+C or Ctrl+D pressed twice quitting Claude Code instead of closing the dialog in the remaining dialogs and pickers, such as `/memory`, `/hooks`, `/mcp` (including a server’s sign-in screen), `/export`, `/copy`, `/theme`, and `/teleport`’s uncommitted-changes and login prompts (where Esc also quit)
- Fixed keys that arrive in one burst of input (e.g. over Remote Control), such as an arrow key followed by Enter, `x` or `s`, acting on the previous selection: a stale effort level in `/effort` and the model picker, and the previously highlighted row in `/skills`, the background task rows under the prompt, MCP server prompts and `/install-github-app`
- Fixed `/install-github-app` updating the workflow after “Skip workflow update” was chosen, running setup twice on a repeated Enter, and ↑ on the repository step blocking a typed repository name when no repository was detected
- Fixed vim mode: `dj`/`dk`/`dG`/`dgg` and their `c`/`y` forms acting on part of a line; `1G` going to the last line; `d0`/`c0`/`y0` doing nothing; the cursor being off by one after `.` repeats an insert; and `o`/`p` on a `!`-prefixed line switching to shell mode
- Fixed vim mode `cw` on a space, an empty line, a word’s last letter or a one-letter word also changing the next word; word motions stopping inside words in Hindi, Bengali and other scripts; and `.`, `p` or `P` that inserts text starting with `!` switching to shell mode, losing text or editing the wrong character
- Fixed the prompt cursor moving one character too far after an accent typed as its own key
- Fixed an extra blank line above a list item whose text starts on the line after its bullet, in screen-reader mode, quoted lists and long lists
- Fixed bulleted lists of plain numbers (like `- 316.`) showing as letters, roman numerals or the wrong numbers
- Fixed the agent panel’s footer hint ignoring keys rebound in `keybindings.json`, and showing a stray `·` when the stop-all-agents shortcut is unbound
- Fixed the agent panel footer offering “Enter to view” and “x to stop” on the agent you are already viewing (where x types into its input), and “Enter to view” on the main row when main is already shown
- Fixed a mouse click on an agent-panel row leaving the keyboard cursor on the previously selected row
- Fixed Esc interrupting the running turn instead of deselecting the selected agent-panel row
- Fixed PgUp and PgDn doing nothing in a dialog’s list (for example `/skills`) in fullscreen mode
- Fixed `/heapdump` summary saying most memory is native when it is in the JS heap snapshot
- Fixed Bash edit-diff snapshot directories piling up in the temp folder: abandoned ones are now deleted right away and the rest when Claude Code exits
- Fixed /workflows moving the pointer to a different run, and `x` stopping it, when a new run started while the list was open
- Fixed the selected tab in tabbed dialogs (`/config`, `/plugin`, `/permissions`) showing no highlight while the tab bar has focus when color is off (`NO_COLOR`)
- Fixed the mouse wheel over the `/plugin` Installed list scrolling the pane behind it instead of the list
- Fixed the hover highlight lingering on a list row in fullscreen mode after scrolling or filtering moved it away from the mouse
- Fixed long list rows, such as in the /remote-control menu, wrapping onto a second line in narrow terminals; they’re now cut with …
- Fixed `/hooks` and `/mcp` detail views printing a long value over the row below it in narrow terminals
- Fixed lists such as a skill’s state options in `/plugin` not being answerable by typing a number in screen-reader mode
- Windows: Fixed Bash commands that write to `$TMPDIR/…` failing with “Permission denied”
- Windows: Fixed a race in which Claude Code sessions updating at the same moment could delete each other’s `claude.exe` backup, which could leave no `claude.exe` behind
- Improved Claude Desktop sign-in and usage-limit error messages to point at the app instead of terminal commands
- Improved startup: managed settings and policy fetches no longer retry requests that can never succeed
- Improved interactive startup time: git reads, startup telemetry and the Bedrock/Vertex model-upgrade checks no longer run before the first frame
- Improved the time to resume long sessions that read many files; the restored file cache now matches the files as they were read
- Improved the time to resume very long sessions that have been compacted, most noticeably through the Agent SDK and Claude Desktop
- Improved “Prompt is too long” recovery in sessions dominated by one very large first prompt: that prompt is now summarized on its own instead of being left out of the summary
- Improved auto mode after resuming a session in a new process: the permission classifier can now reuse its earlier prompt cache instead of rewriting it
- Improved the auto mode denial message so Claude treats a denial as covering the outcome, not only the exact command
- Improved the dangerous-rm check to also flag a removal at a shell variable followed by a top-level directory name, at a variable derived from the working directory, or at a backslash-only target
- Improved sandbox guidance on macOS: when a local dev server can’t bind a port, Claude now points to `sandbox.network.allowLocalBinding`
- Improved `--agents` to accept the path to a JSON file (with `-p`) as well as inline JSON, and to allow an empty `prompt`
- Improved `/batch` to run where a WorktreeCreate hook provides the agent worktrees, not only inside a git repository
- Improved plugin hook-failure errors to name the offending plugin, and added a `claude plugin validate` warning when a shell-form hook leaves `${CLAUDE_PLUGIN_ROOT}` unquoted (it breaks on plugin paths with spaces)
- Improved the `/` menu, `/skills`, `/context` and the `/plugin` Installed list to show skills synced from claude.ai by their short name when no other command uses it, not `anthropic-skills:<name>`
- Improved `/deep-research` reliability on long research briefs by removing unused required fields from the scope step’s output
- Improved the writing in published artifact pages: the bundled artifact-design skill now asks Claude for plain, direct prose
- Improved artifact publishing on slow connections: large page uploads are now sent compressed
- Improved the large CLAUDE.md startup notice to also count instruction files together, so many mid-sized files and @-imports are caught
- Improved debug logs to name settings `env` variables ignored because the session’s launch environment already sets them
- Improved keyboard navigation in tabbed dialogs such as `/permissions` and `/usage`: ↑/↓ move focus between the tab row and the content, and a list responds to keys only while it has focus
- Improved `/help` and `/sandbox`: ←/→ and Tab switch tabs from inside a tab’s list, and ↓ on an empty Custom commands tab in `/help` no longer leaves the keys stuck until Esc
- Improved `/install-github-app`, `/desktop`, the `/permissions` auto mode environment prompts, and the `/plugin` “Add marketplace?” and “Run this command?” prompts: they now use the standard dialog frame with key hints, and Ctrl+C or Ctrl+D cancels them on the second press like other dialogs
- Improved the `/workflows` and `/mcp` lists: they page (PgUp/PgDn, Home/End) and take j/k and the mouse like other lists, their arrows follow `select:previous`/`select:next` rebinds, and `x` in `/workflows` stops the run the pointer is on
- Improved the `/plugin` plugin and marketplace details menus and the `/remote-control` already-connected menu: they now support Home/End and clicking a row
- Improved the background workflow row below the prompt: it now shows the name, a progress bar, the agent count on wide terminals, elapsed time, total tokens, and the large-workflow warning
- Improved the /plugin Installed list: rows now line up in columns (status, name, type, details) across every section
- Improved `/skills`: each row now leads with the skill’s name, with ✔ or ◯ alone showing on or off, and stays on one line in narrow terminals
- Improved narrow list rows (`/skills`, `/workflows`, `/feedback`): a name keeps 20 columns beside its first detail, and details are shown whole or not at all
- Improved `/diff`: a scrollbar shows where you are in a long list of changed files, and long paths no longer wrap their rows
- Improved `/hooks`: a hook’s detail screen now says what kind of hook it is and where to change it, instead of always pointing at settings.json, and the hooks-disabled, safe mode and managed-hooks-only notices each say what is happening in one plain sentence
- Improved screen-reader output in `/mcp`: a disabled server is read as “off” instead of “pending”
- Improved the Remote Control confirmation: its options are briefly inactive again after the terminal window regains focus, so a key pressed while switching back cannot answer it
- Changed send now (ctrl+enter or ctrl+x ctrl+s) to move running tools to the background instead of cancelling the turn
- Changed auto mode so that, where its classifier review runs server-side, read-only and sandboxed shell commands also wait for that review and are blocked when it flags them
- Changed `CLAUDE_CODE_AUTO_MODE_SERVER` to also apply on a direct Anthropic API connection: `0` opts out of the server-side auto mode classifier (the local classifier then counts toward usage), `1` opts in
- Changed the dangerous `rm` prompt in `--dangerously-skip-permissions` and auto mode to wait 2 minutes for an answer, then deny the command with a rewrite hint so unattended sessions keep going (`CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT=1` turns this off)
- Changed AGENTS.md support to also work on Amazon Bedrock, Google Vertex AI, Microsoft Foundry, LLM gateways, and sessions with telemetry disabled
- Changed Claude apps gateway to refuse to start when a `managedMcpServers` entry’s `envHelper` path starts with `\??\` or `/??/`, a path form current Claude Desktop refuses to run
- Changed self-hosted runners to pass system prompts to Claude Code as private files instead of command-line text, so large prompts no longer fail the launch; a wrapper or `command` hook that appends `--system-prompt` or `--append-system-prompt` must switch to `--system-prompt-file` or `--append-system-prompt-file`
- Changed queued messages to show in the conversation above the spinner instead of under it
- Changed the session artifact links under the prompt into one footer pill (`⧉ name` or `⧉ N`) that opens `/artifacts`, which now lists this session’s artifacts first
- Changed the Artifact tool to let Claude load scripts from unpkg.com in artifact pages
- Changed hovering a list row in fullscreen mode, including in `/config`, to tint the row instead of drawing a second ❯ pointer beside the focused row’s
- Changed /mcp: each server’s row now starts with its status icon and name, says its state once, and in a narrow terminal drops trailing facts like “managed” before shortening the name
- Changed /workflows: each run’s row leads with its status icon and elapsed time, and a narrow terminal keeps the run’s name and time, dropping the agent and token counts first
- Changed Remote Control attachment downloads to reuse connections and to skip files already downloaded in the session
- Changed MCP resource lists (the resource list tool and @-mention suggestions) to skip MCP Apps UI resources; reading one by URI still works
- Changed `claude plugin uninstall --json` and the /plugin dialog to say a plugin’s data was kept when its folder stays because another installed plugin uses it or install records cannot be read
- Changed the background tasks list (`/tasks`): pressing `x` on a running `/ultrareview` now asks for confirmation before stopping the review
- Removed the leftover “(removed)” `/agents` entry from the command menu and `/help`; typing `/agents` still explains where the wizard went
- \[VSCode\] Added a Continue/Stop prompt in the VS Code and JetBrains panels when auto mode falls back to billed classifier requests, replacing the unanswerable warning line
- \[VSCode\] Fixed opening a Web session with no messages saving an empty local copy that could not be resumed; an error now says where to continue it
- \[VSCode\] Fixed a claude.ai/code session opening empty or with only part of its conversation, with no error, when the server failed to return its history, part of it failed to load, or a network sign-in page answered in its place; it now shows an error and can be opened again
- \[VSCode\] Fixed conversations in editor tabs hanging silently after the extension host restarts; the tab now tells you to reopen it from the session list
- \[VSCode\] Fixed Claude attaching option previews to multiple-choice questions in the chat panel, where the question card never shows them
- \[VSCode\] Fixed the session manager’s cost and usage block wrapping mid-text on a narrow side bar, and showing totals from a previous login after an account switch
- \[Claude Code on the web\] Added a Fast mode switch to the composer’s model menu in cloud sessions, shown when your plan includes fast mode and the selected model supports it
- \[Claude Code on the web\] Added a settings shortcut on the GitHub setup tip and a “Troubleshoot GitHub connection” link in the repository pickers, both opening your GitHub connection page
- \[Claude Code on the web\] Fixed routines with a GitHub trigger for a pull request being converted to draft never firing; they now start a run when the pull request is converted
- \[Claude Code on the web\] Fixed cloud sessions on a repository that isn’t hosted on GitHub showing a Create PR button that could never work; the button is now hidden there
- \[Claude Code on the web\] Fixed the GitHub setup tip on claude.ai/code covering the repository picker’s search box and rows while the picker is open; it now steps aside until the picker closes
- \[Claude Code on the web\] Improved the file card shown when a cloud session can’t open a file: it now says whether the file no longer exists or the session’s permission settings block reading it
- \[Claude Tag\] Added a short line in the Slack thread after someone presses Stop, naming who stopped Claude’s response and saying to mention @Claude to continue
- \[Claude Tag\] Fixed Slack channels where Claude could permanently stop responding to replies inside threads; affected channels now recover on their own with the next new message to Claude
- \[Claude Tag\] Fixed Claude resuming a stopped request after you press Stop in Slack, for example when a check-in fired or a background task ended; messages sent mid-response are now read
- \[Claude Tag\] Fixed Slack replies arriving many minutes late, or never, after Claude’s session crashed mid-task, such as on a failed setup script; it now restarts on its own within minutes
- \[Claude Tag\] Fixed Claude in Slack promising an automatic restart, then failing generically, when a session’s configuration is too large to start; the thread now says why and how to retry
- \[Claude Tag\] Fixed very long Slack threads: Claude could silently withhold a reply after judging it against weeks-old messages, and a restart deep into the thread could lose recent context
- \[Claude Tag\] Fixed Claude answering every mention with “Couldn’t check this channel just now” in a Slack channel moved from Enterprise Grid org-wide sharing into a single workspace
- \[Claude Tag\] Fixed very large Enterprise Grid workspaces reached mostly through channels shared across workspaces getting “Couldn’t check this channel” again after a quiet hour
- \[Claude Tag\] Fixed a Slack request blocked by your organization’s inference hook showing a generic retry notice; the thread now shows the hook’s deny message and Claude doesn’t retry
- \[Claude Tag\] Fixed Claude in Slack offering to switch to models your organization can’t use; it now lists and offers only models the switch will actually accept
- \[Claude Tag\] Fixed requests to DynamoDB and Kinesis account-based endpoints failing to authenticate when sent through an AWS connection in Claude Tag
- \[Claude Tag\] Fixed the Plugins sections in Claude Tag admin settings failing to load for organization admins and listing attached plugins as raw IDs; they now load and show each plugin’s name
- \[Claude Tag\] Changed the routine list Claude gives when asked in a Slack thread to show that thread’s own scheduled tasks by default instead of every routine in the channel
- \[Code Review\] Fixed a pull request getting no review when its reviewed commit was force-pushed away while a failed review was being retried in a repository not set to review every push
[](#2-1-280)
2.1.280
September 22, 2026
- Added Claude Opus 5.5 (`claude-opus-5-5`), now the default Opus model — 1M context, $4/$4/20 per Mtok with \$0.20/Mtok cache reads
- Added mouse support to more lists in fullscreen mode: the wheel scrolls the `/skills` list, and a skill’s state options in `/plugin` can be clicked
- Added `CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH` to change the 2,048-character cap on MCP tool descriptions and server instructions for every MCP server in the session
- Added hook output sizes and the number of oversized outputs saved to a file to the `hook_execution_complete` OpenTelemetry event
- Fixed writes through a symlinked path being judged by their in-tree spelling: the prompt names where the write lands, and `acceptEdits`, allow rules and auto mode no longer approve one landing outside
- Fixed auto mode retrying an action over and over when a safety check declined to review it; the action is now denied once, noting that retrying won’t help
- Fixed auto mode denying actions over and over without pause when a safety check gave no answer; retries now back off, and the turn stops with a message after ten in a row
- Fixed Write calls failing validation when a model sends `path`, `file_text`, `file_content` or a stray `description` instead of `file_path` and `content`
- Fixed Ctrl+C or Ctrl+D pressed twice in most dialogs (`/model`, `/effort`, `/config`, `/status`, `/usage`, `/plugin`, `/sandbox`, `/permissions`, `/artifacts`, `/mobile`, `/login`, `/upgrade`, `/usage-credits`, `/install-github-app`, `/setup-bedrock`, `/setup-vertex`) quitting Claude Code instead of closing the dialog
- Fixed a click that only brought the terminal window to the front also triggering the item under the pointer — in search pickers, tab bars, agent/workflow rows, slash-command links and suggestion dropdowns
- Fixed a stray `n` closing dialogs and a stray `y` confirming them; Enter and Esc accept and cancel (bind `y`/`n` to `confirm:yes`/`confirm:no` in `keybindings.json` to restore)
- Fixed text fields in dialogs losing a typed letter, digit or Space to a keybinding on that key
- Fixed the prompt line staying scrambled on Windows terminals after invisible characters were removed on Enter; the screen is now repainted so you review the exact text that will be sent
- Fixed the invisible-character cleanup removing the zero-width non-joiner that Persian and Arabic text uses to attach a suffix to a Latin word or number, such as the plural of “PDF”
- Fixed voice dictation not stopping on Ctrl+C (the prompt cleared but the microphone kept recording), Esc not cancelling while a transcript was processing, and held Space starting dictation from the transcript view and vim NORMAL mode
- Fixed a model switch made from a host app (Claude Desktop, VS Code, SDK) while Claude is working causing a prompt-cache miss on the next prompt
- Fixed resumed fork subagents rebuilding their tool list instead of re-sending the one they first used, which broke prompt caching for that agent
- Fixed subagent hand-back messages showing an internal provenance preamble when expanded outside verbose mode
- Fixed `installed_plugins.json` keeping the install-time commit after updating a plugin from a GitHub repository or git URL that tracks a branch or tag
- Fixed skills in `~/.claude/skills/` being moved to `~/.claude/skills/.trash/` when a `manifest.json` in that folder listed their names
- Fixed the session feedback survey showing no hover highlight on light and ANSI themes
- Fixed `/workflows` briefly showing a one-row list before opening the only run
- Fixed the mouse wheel not scrolling selection lists with hidden options (such as `/model` and `/permissions`) in fullscreen mode
- Fixed a skill you switched off showing the same red ✘ as a plugin that failed to load in `/plugin` and `/skills`; off now shows a dim ◯
- Fixed multi-select option descriptions being indented under the option number instead of under the label
- Fixed the search box in `/plugin`, `/skills` and `/mcp` losing its right border in fullscreen mode
- Fixed `/mcp` showing △ in the server list but ⚠ in the detail view for the same server; the list, detail views and `/plugin` now all show ⚠
- Fixed Home and End doing nothing in the `/config` settings list and in selection lists such as `/model`, `/memory` and permission prompts
- Fixed PgUp/PgDn in the `/skills` menu wrapping past the first or last skill instead of stopping there
- Fixed Tab silently changing the selected setting’s value in the `/config` list; it now does nothing there
- Fixed conversations failing on every turn with a “role ‘system’ must precede an ‘assistant’ message” API error
- Fixed conversations with the advisor on failing every turn with API Error 400 “Input tag ‘advisor_20260301’” behind a proxy or gateway that doesn’t support it; the request now retries without it
- Fixed a session failing on every turn and `/compact` when its saved history held a malformed notice about MCP tools that could not be loaded
- Fixed a crash when resuming a session whose saved transcript holds a malformed system message or a memory-saved notice without its file list
- Fixed one cause of long-running fullscreen sessions exiting with “Claude Code exited after an unrecoverable interface error”: a damaged cached message list is now rebuilt
- Fixed Claude Code hanging when a settings file, or a file it re-reads after an edit, is replaced by a named pipe mid-read
- Fixed `/config` crashing and some on/off preferences being misread when a preference that has moved to `settings.json` still holds a value like `null` or `"false"` in `~/.claude.json`
- Fixed resuming a session with unfinished background agents, shells or workflows starting a model turn on its own before you typed anything
- Fixed messages sent to a background subagent being silently lost in headless and SDK sessions when the subagent was finishing its turn
- Fixed a finished subagent’s report being lost when the conversation that launched it was compacted before the report was read
- Fixed background subagents being unable to use the LSP tool when an LSP plugin is active
- Fixed background shell tasks reporting benign non-zero exits (e.g. grep with no matches) as failures
- Fixed background sessions (`claude --bg`) being unable to run git, hooks, plugins and other helper programs when an environment variable handed to the session contained a NUL character
- Fixed Ctrl+C needing three or four presses to exit while background subagents are running; two presses now exit
- Fixed IDE selection being dropped when a sent prompt comes back into the input, such as pressing Esc to edit it, rewinding to it, or pressing Esc while startup hooks run
- Fixed a `!` shell-mode prompt stashed with Ctrl+S coming back as a plain prompt when restored, and `/` listing file paths right after stashing one
- Fixed `claude agents` showing a blank, unresponsive screen instead of an error when the temp directory is full, not writable or owned by another user
- Fixed an MCP server re-added under the same name after `claude mcp remove` still showing as needing authentication instead of reconnecting
- Fixed background plugin marketplace auto-update ignoring git credential helpers, so private-repo marketplaces were re-cloned every run or never updated
- Fixed `claude plugin update` clearing a plugin’s recorded commit and moving it to version “unknown” when the official marketplace’s snapshot file is a link or too large
- Fixed the Artifact tool silently disappearing when your organization’s policy can’t be loaded (for example behind a web proxy); Claude now says what’s blocking it
- Fixed artifact republishes silently resetting stored database access rules or dropping the viewer profile scope when that capability was re-sent without them; they are now refused
- Fixed `/ultrareview` reporting a stopped cloud review as completed or as an error to retry, and waiting out the full timeout when its session was deleted or the signed-in account changed
- Fixed the Claude app showing a missing or stale context usage figure for Remote Control and cloud sessions right after /compact or /clear
- Fixed the Claude app’s diff view for Remote Control and cloud sessions dropping a branch’s committed files whenever there are also uncommitted changes
- Fixed cloud and self-hosted runner sessions failing with “Authentication failed” after waiting out a long overload during which the session’s access token was rotated
- Fixed memory write conflicts in Cowork sessions showing Claude only the start and end of a memory file over about 10,800 characters, so the retried write dropped the middle
- Self-hosted runner: Fixed lifecycle-hook commits failing to sign under `--configure-git`
- Windows: Fixed background cleanup deleting a directory symlink or junction used to relocate `~/.claude/session-env`, `image-cache` or another cleaned-up folder
- Self-hosted runner: Fixed a turn that ended right at a `--retire-at` release losing its finished signal; the runner now briefly waits for the turn to be reported before stopping the session
- Reverted `ctrl+l` / `cmd+k` in fullscreen mode clearing the transcript view (added in 2.1.260); they redraw the screen again
- Improved `/permissions`: focus returns to the rule list after viewing, adding or deleting a rule, and the delete-rule and remove-directory confirmations now default to No
- Improved `/permissions` tab navigation: ←/→ and Tab pressed in a rule list now switch tabs without moving focus to the tab bar
- Improved `/cost` cache-miss causes to name thinking mode and thinking display changes
- Improved the Artifact tool so that when Claude cannot read an artifact link it was given, it tells the user before continuing
- Improved `/install-github-app`: the GitHub CLI check and repository selection steps now show “Esc to cancel”
- Improved the `/artifacts` and `/workflows` lists: a scrollbar at the right edge shows how much of a long list is hidden and where you are in it
- Improved the workflow progress tree: running agents and phases now show a dim dot instead of ⟳
- Improved `/plugin`’s Add Marketplace form in fullscreen: it no longer draws a box inside the pane, and its text and key hints line up with the rest of `/plugin`
- Improved the `/workflows` detail view in fullscreen: it no longer draws a second horizontal rule under the pane’s divider
- Improved code blocks that don’t name a language: they are now colored like inline code, so commands stand out from the surrounding text
- Improved `/btw` asked while a tool is still running: the side question now knows that call is in progress instead of reading it as a failed one
- Improved the UserPromptSubmit hook timeout notice and the debug log to name which hook command timed out
- Improved `@` file suggestions: a file whose name contains the query now ranks above one that only matches across its folder names
- Improved artifact pages: no Print buttons, confirm dialogs or device features the viewer blocks, email and phone details shown as text, and dark mode that reaches form controls and scrollbars
- Improved `/ultrareview` uploads: renamed copies of key files, such as `id_rsa copy` or `kubeconfig (1).yaml`, now also stay on your machine
- Improved the cross-session messaging startup warning to explain that `--debug-file` writes a debug log to a path you choose
- Changed the default model on Pro and Team Standard plans from Sonnet to Opus, matching Max, Team Premium, and Enterprise
- Changed an effort level saved before `/effort` became per-model to no longer apply to newly released models such as Opus 5.5; they start at their default until you pick a level
- Changed Opus 4.7, Opus 4.8 and Fable 5 to stop holding their launch-default effort over `/effort` in `-p` or the Agent SDK, a project, managed or `--settings` `effortLevel`, or a per-model level
- Changed `/autocompact`’s footer hint to name ←/→, the keys that adjust other ordered values
- Changed `/fast`’s footer to name Space as the toggle key
- Self-hosted runner: Changed git in lifecycle hooks to ignore hook folders and programs named in the runner’s shared git files; local-path and `git://` remotes there now need `GIT_ALLOW_PROTOCOL`
- Changed plugin marketplaces whose name imitates a reserved marketplace name to be refused when added, and to stop loading if one was already added
- Changed `PermissionRequest` hooks: an agent-type hook no longer runs there, since its answer could never allow or deny the request; it now shows an error pointing to command or http hooks
- \[VSCode\] Added a Status dialog, with a typed `/status`, showing the session’s version, account, model and server details
- \[VSCode\] Added a Sandbox dialog for the sandbox mode, the unsandboxed fallback and excluded commands, opened from the panel menu or by typing `/sandbox`
- \[VSCode\] Added a Claude in Chrome dialog (extension status, the install, reconnect and permissions pages, the enabled-by-default setting), opened from the panel menu or by typing `/chrome`
- \[VSCode\] Added Export conversation, with a typed `/export`, to copy or save the conversation as plain text
- \[VSCode\] Added each skill’s source, token estimate and on/off state to the Slash commands dialog, with a click to change the state, and a typed `/skills` that opens it
- \[VSCode\] Added a typed `/plan` that switches to plan mode, sends a first planning prompt, or shows the session’s plan
- \[VSCode\] Improved pasted-text handling in the chat box: a paste over 800 characters or over 2 line breaks is now marked so Claude can tell it from what you typed
- \[VSCode\] Improved prompt handling in the chat box: invisible Unicode formatting and tag characters are removed from pasted text with a notice, and from anything else before it is sent
- \[VSCode\] Changed “Open in New Tab” to open Claude beside the editor group you are working in rather than after the last group
- \[VSCode\] Fixed the effort chip showing a stale saved effort level instead of the level the session runs at
- \[VSCode\] Fixed Claude Code never starting when the Python extension hangs while activating; it now starts after 60 seconds without the Python environment
- \[VSCode\] Fixed the plan approval card never offering auto mode: when auto mode is available, its first option is now “Yes, and use auto mode”, as in the terminal
- \[VSCode\] Fixed arrow-key navigation in the session list stopping after archiving or unarchiving a session from the keyboard
- \[VSCode\] Fixed paste marker lines showing in your own messages after reopening a session
- \[Claude Code on the web\] Changed the admin Routines on/off setting to live under Admin settings → Capabilities → Remote sessions; the Claude Code admin page now links to it
- \[Claude Code on the web\] Fixed `gh` and GitHub API calls inside a cloud session on a GitHub Enterprise Server repository failing after about eight hours; the token now renews automatically
- \[Claude Code on the web\] Fixed a routine that resumes an existing session running with its old prompt and name when it was edited moments before the scheduled run started
- \[Claude Code on the web\] Fixed file links in a cloud session transcript that point outside the session’s working directory opening a file card that never loads; they’re now disabled and say why
- \[Claude Code on the web\] Fixed auto mode refusing to retry a tool call because an approval prompt that expired unanswered, or was superseded by a newer message, had been recorded as your rejection
- \[Claude Code on the web\] Improved cloud sessions viewed in the Claude app: Claude now saves files meant for you where the app can open them
- \[Claude Code on the web\] Removed the empty repository picker shown when starting a session on a self-hosted environment in an organization where an admin has turned GitHub off
- \[Claude Tag\] Added Slack’s native Working indicator, Stop button and thread title to Claude’s threads in channels; the indicator stays up until Claude finishes, and Stop interrupts the task
- \[Claude Tag\] Added a short notice in the Slack channel when a guest joining, or the last guest leaving, changes how Claude responds there under a Restrict or Channel only guest setting
- \[Claude Tag\] Fixed scheduled routines silently failing to run in Slack workspaces that were connected to Claude before the workspace joined its Enterprise Grid
- \[Claude Tag\] Fixed Claude asking you to re-upload a Slack file when a brief file-scanning outage, not the file, was the problem; it now retries the scan and is told when the scanner is down
- \[Claude Tag\] Fixed a bullet in Claude’s Slack reply whose text starts with +, - or \* rendering as an empty bullet with a stray nested item; it now shows as one bullet with the character kept
- \[Claude Tag\] Fixed the Slack notice for a failed cloud environment setup script sometimes being a generic “mention me to retry”; it now names the setup script and says to fix it first
- \[Claude Tag\] Improved the GitHub banner in Claude Tag admin settings to say why GitHub isn’t connected: not signed in, app not linked or not installed, sign-in expired, or SSO not authorized
- \[Code Review\] Improved the Code Review check run to say when REVIEW.md instructions were cut or left out of a review for exceeding a size limit, naming the file and the limit
[](#2-1-278)
2.1.278
September 19, 2026
- Changed auto mode for Claude API and Enterprise users, and on Bedrock, Vertex, Foundry and gateways, to default to the server-side classifier, which does not charge for classifier overhead (`CLAUDE_CODE_AUTO_MODE_SERVER=0` opts out on Bedrock, Vertex, Foundry and gateways); warns on billed fallback. See [https://code.claude.com/docs/en/auto-mode-classifier-billing](../17-Billing-Plans/auto-mode-classifier-billing.md)
- Added an `Auto mode server` row to `/status` showing whether this session’s auto mode classifier runs on the server
[](#2-1-277)
2.1.277
September 18, 2026
- Added AGENTS.md support: in a project with no CLAUDE.md, Claude Code reads AGENTS.md instead; change it under “Project instructions” in `/config`
- Added `CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY=1` for Claude apps gateways whose only egress is a forward proxy: every outbound request hands the proxy the hostname instead of resolving it locally
- Added an optional `headers:` map on Claude apps gateway upstreams, to send static headers to a proxy you run in front of a provider
- Added a line saying a background task’s update is waiting when it finishes while a panel such as `/tasks` is open
- Fixed `claude -p` and Agent SDK sessions that could hang with no result after an internal error; they now report the error and exit with code 1
- Fixed conversations failing every request with “text content blocks must be non-empty” when an earlier assistant turn held an empty text block beside other content, including after `--resume`
- Fixed being unexpectedly logged out when an older Claude Code build (for example an IDE extension’s bundled CLI) runs on the same machine as the current one
- Fixed interactive start-up hanging or showing an error for `ANTHROPIC_API_KEY` users when `~/.claude.json` holds a malformed `customApiKeyResponses` value
- Fixed update checks erroring every 30 minutes, and `claude update` hanging when a minimum or maximum version is set, if a proxy returns an invalid version; a malformed `minimumVersion` is now ignored
- Fixed `claude update` on winget- or apk-managed installs reporting “up to date” when the version lookup failed
- Fixed `claude plugin install` sometimes failing and breaking the installed copy when reinstalling a plugin version that a session or another program was using; an unchanged copy is now left alone
- Fixed Grep and Glob reporting no matches when the search could not start because the system was out of processes, memory or file handles; they now return an error saying so
- Fixed the Write tool silently ending the turn as a declined permission when the target path is an existing directory; it now reports a clear error
- Fixed the Edit tool treating an escaped backslash followed by `uXXXX` text as a `\uXXXX` escape, which could make an edit of a non-ASCII character rewrite an escaped backslash sequence instead
- Fixed the Edit tool reporting “Invalid regular expression: regular expression too large” instead of “String not found in file” when a very large edit containing non-ASCII text did not match the file
- Fixed a turn ending early with “Path contains null bytes” when a tool call’s file path contained `\u0000` written as an escape sequence; escaped control characters now stay as literal text
- Fixed background sessions (`claude --bg`) exiting when a plugin’s LSP server exited or closed its stdin
- Fixed a crash (“Type error”) when opening `/mcp` or `/plugin manage` with a malformed `claudeAiMcpEverConnected` value in `~/.claude.json`
- Fixed a crash at launch when `~/.claude.json` holds a malformed `theme` value
- Fixed a crash (“unrecoverable interface error”) when the prompt held text containing terminal color codes, for example a prompt recalled from history or text loaded from the external editor
- Fixed a crash when resuming a session whose saved history holds an assistant message stored as a plain string
- Fixed sessions on slow or heavily loaded machines sometimes exiting with “Claude Code exited after an unrecoverable interface error” when the first spinner appeared
- Fixed a rare case where the screen could stop updating for the rest of the session after an internal rendering error
- Fixed a rare case on Windows where a turn could stop with an error such as “Out of memory” right after Claude replied, so that reply’s tool calls never ran
- Fixed sessions continued after `/clear` (restart, `--continue`, `--resume`) missing part of their first message when a SessionStart hook printed output, causing a full prompt-cache miss
- Fixed messages from other agents (such as a subagent’s SendMessage) that arrived mid-turn showing up below the “Ran N shell commands” row instead of where they arrived
- Fixed the “copied” notice not appearing after drag-selecting text in the fullscreen `/resume` picker and other panels that cover the prompt area
- Fixed `$TMPDIR` expanding empty in Bash commands that run outside the sandbox while sandboxing is enabled
- Fixed WebFetch and WebSearch in Cowork cloud sessions not telling Claude why a request was refused, such as a used-up fetch budget or an admin policy
- Fixed the Claude apps gateway’s telemetry relay ignoring a collector hostname or domain listed in `NO_PROXY` when a proxy is set
- Fixed one malformed `strictKnownMarketplaces` or `blockedMarketplaces` entry silently disabling the whole enterprise marketplace policy
- Fixed failed auto-updates leaving large staged downloads behind in `~/.cache/claude/staging`
- Fixed `/plugin` not stripping terminal control characters from messages on the Installed tab, such as the error of a failed plugin update
- Fixed `/plugin` → Installed and `/skills` crashing when a skill or legacy command is named like a built-in Object property such as `constructor` or `toString`
- Fixed `/plugin` closing with no message when every install in a multi-select failed
- Fixed uninstalled plugins reappearing as “failed to load” rows in `/plugin` Installed, and Remove not clearing such a row
- Fixed plugins from the official marketplace being recorded without their commit in `installed_plugins.json`, and `installed_plugins.json` keeping the old commit after updating a pinned-commit plugin
- Fixed plugin reload previews keeping every previewed copy of a plugin archive unpacked until exit, and overwriting the cached `--plugin-url` archive a reload falls back to when its download fails
- Fixed Remote Control session bookkeeping failing when `~/.claude.json` holds a malformed placeholder record
- Fixed the error after a revoked claude.ai login blaming an expired Anthropic profile; it now leads with `/login`
- Fixed typed or pasted text occasionally coming out scrambled in the `claude agents` dispatch input during key repeat or very fast input
- Fixed a crash (“unrecoverable interface error”) when resuming a session whose saved transcript contains a stop hook summary without a well-formed hook list
- Fixed Enter on a selected agent panel row doing nothing when `keybindings.json` rebinds Enter in the Chat context, for example to `chat:queueSubmit`
- Fixed PDF page reads on Windows failing when the working folder’s path is long (about 120 characters or more)
- Fixed a headless resume (`claude -p --resume`, the SDK, a VS Code extension window reload) starting the session’s cost and usage totals at zero; headless sessions now save their totals at exit
- Fixed project skills from the main repository not loading in `--worktree` sessions when `.claude/skills` is untracked
- Fixed a `sandbox.excludedCommands` glob exempting an entire compound Bash command from the sandbox when only one part matched; every part must now match
- Fixed resumed subagents and teammates re-rendering the MCP tool definitions they had loaded, which broke prompt caching for that agent
- Fixed rate-limited artifact publishes telling Claude to stop retrying; Claude is now told nothing was published and when to send the same publish again
- Fixed attachments recorded earlier in a conversation being re-rendered after a resume or relaunch, which dropped extended thinking and missed the prompt cache
- Fixed Console sign-in showing only “Request failed with status code 400” when the server refuses to create an API key; it now shows the server’s message
- Fixed messages typed while Claude is still working sometimes being ignored by the model
- Improved session start-up for SDK and headless (`-p`) use: the first turn no longer waits on the per-directory CLAUDE.md lookup
- Improved the Claude apps gateway’s loopback error messages to name `CLAUDE_GATEWAY_ALLOW_LOOPBACK`
- Improved `/plugin` Installed: an MCP server listed apart from its plugin now shows which plugin it belongs to
- Improved `claude plugin install` on an already-installed plugin: it now says when the marketplace offers a newer version and names the `claude plugin update` command
- Improved the startup notice overflow line under the logo: it now reads “N more notices hidden” instead of “+N more · /status”
- Improved prompt handling: invisible Unicode formatting and tag characters in a prompt are removed and the cleaned prompt is shown for review before it is sent
- Improved `/ultrareview` when there’s nothing to review: messages say which case you’re in, offer a command that reviews your latest commit, and a new repository’s first commit is reviewed in full
- Improved artifact link handling so Claude reads claude.ai artifact links with the Artifact tool instead of WebFetch when that tool is available
- Improved the dangerous-rm permission prompt to name the flagged rm command and suggest a `${VAR:?}` guard, so headless runs can recover
- Improved the Artifact tool’s permission prompts: shorter sentences, pages and artifacts named by title or file name, and links listed after the text
- Changed Fable to always appear in `/model` on the Anthropic API; it is greyed out only when your organization’s settings disable it
- Changed the Bash sandbox instructions on Bedrock, Vertex and Foundry to the first-party wording, which frames the sandbox as the boundary of what the task was given
- Changed `/ultrareview` in non-interactive sessions to refuse when the repository has no base branch or shared history
- Changed subagent results to reach the main agent under a header marking them as subagent output, with the result indented, so text in a subagent’s result cannot pass as the session’s own instructions
- Changed workflow scripts’ computed `agent()` prompts on Bedrock, Vertex and Foundry to reach the subagent framed as script-authored text, so the safety classifier does not read them as the user
- Removed the background Haiku auto-title request from `claude -p` runs launched outside an SDK or IDE
- Removed the deprecated TaskOutput tool; Claude reads a background task’s output file with Read instead, and the `taskOutputMaxChars` setting and `TASK_MAX_OUTPUT_LENGTH` no longer have any effect
- \[VSCode\] Added a Sign out row to the panel menu, with `/logout` in the typed command menu
- \[VSCode\] Added background shells and other running tasks to the agent map, each with a Stop, and a typed `/tasks` that opens it
- \[VSCode\] Added a Copy response button on responses and a typed `/copy`
- \[VSCode\] Added a one-time notice when inactive sessions are archived automatically, and an “Unarchive all” action on the Archived sessions group
- \[VSCode\] Added the session’s cost and token usage to the Account & usage dialog and the session manager where plan limits do not apply (Vertex, Bedrock, Foundry, API key)
- \[VSCode\] Fixed the “General config” menu row showing `/config` usage text instead of opening settings, and made typed `/mcp`, `/hooks`, `/memory`, `/rewind` and similar commands open their dialogs
- \[VSCode\] Fixed the effort slider’s level not persisting into later sessions on a model that already had a level saved with `/effort`
- \[VSCode\] Fixed Auto missing from the mode picker for conversations opened in an already-used panel when the saved model setting is a differently-cased alias such as “Sonnet”
- \[VSCode\] Fixed `/fast` not saving fast mode as the default, so it was lost when the extension relaunched Claude Code
- \[Claude Code on the web\] Added Personal and Organization sections to the environment picker on Team and Enterprise plans, and admins can now share a personal environment with the organization
- \[Claude Code on the web\] Changed organization environments to open as a read-only summary from the Code tab on Team and Enterprise plans, with editing under Admin settings → Cloud environments
- \[Claude Code on the web\] Fixed a cloud environment saved with Custom network access and no domains silently reverting to Trusted; the dialog now asks for at least one domain
- \[Claude Code on the web\] Changed the admin Claude Code setting labeled “Web” to “Cloud sessions” and removed the redundant read-only Mobile row beneath it
- \[Claude Tag\] Fixed routines created in a Slack channel on an Enterprise Grid org-wide install failing to read other public channels in their workspace when they ran
- \[Claude Tag\] Fixed the “Learn more” links on credential presets in Claude Tag access bundles to open each vendor’s credential-setup page instead of a generic API reference
- \[Claude Tag\] Changed the Pylon credential preset in Claude Tag access bundles so admins can point it at Pylon’s EU host
- \[Claude Tag\] Fixed Google Cloud credential forms in Claude Tag access bundles: a refused key file now says why, the website and scopes stay locked, and a rejected rotation keeps the pasted key
- \[Claude Tag\] Fixed the network events log in Claude Tag admin settings showing no response status for requests through connections that use AWS signing, client certificates or a custom CA
[](#2-1-276)
2.1.276
September 18, 2026
- Fixed every request failing with `400 … Input tag 'advisor_20260301'` when `ANTHROPIC_BASE_URL` points at a proxy or gateway (2.1.275 regression)
[](#2-1-275)
2.1.275
September 17, 2026
- Added the signed-in account to Claude apps gateway sign-in: when the gateway names it, you confirm it before the credential is saved, and `/status` shows it
- Added a send-now key (ctrl+enter, or ctrl+x ctrl+s) that interrupts the current turn and sends all queued messages at once; sent and queued messages show in gray until the model receives them
- Added a startup warning when a configured `otelHeadersHelper` fails, so sessions that silently export no telemetry are noticed
- Added syncing of the skills and plugins enabled on your claude.ai account to terminal sessions signed in with it; opt out with `syncClaudeAiSkills: false` or `syncClaudeAiPlugins: false`
- Added `/plugin install <plugin> --marketplace <source>`, which offers to add the marketplace before installing the plugin
- Fixed a restored memory file’s age note changing between requests after a compaction or resume, which caused prompt cache misses
- Fixed `--forward-subagent-text` stream-json and SDK output dropping the messages of subagents spawned by a `context: fork` skill, and of forked skills invoked by a subagent or another forked skill
- Fixed @-mention file suggestions being buried below MCP resources when using a custom `fileSuggestion` command or typing `@.`/`@./`
- Fixed fullscreen mode placing background-task completion notices beneath a long turn’s collapsed tool row instead of where they arrived; each notice now closes the open row
- Fixed `claude plugin marketplace update` deleting a GitHub marketplace’s local copy when the fetch failed and the marketplace was named after its repository
- Fixed plugin and marketplace messages, logs and `claude plugin marketplace list` showing a password or token stored in a git, ssh or marketplace URL
- Fixed a resumed cloud session leaving an unanswered question open in the transcript after a queued message superseded it
- Fixed vim mode placing the cursor one character right after a dot-repeated ”!” or a fast-typed “i!” switched a non-empty prompt into shell mode
- Fixed fullscreen mode freezing or blanking for several seconds when scrolling up past a large file diff
- Fixed a stray `</ccmemory>`-style closing tag occasionally appearing in responses
- Fixed plugin messages, logs and the VS Code plugin dialog showing the wrong server for some git addresses
- Fixed a terminal `API Error: 400` on every turn for users behind a network gateway that rewrites API error responses when a beta request header is rejected
- Fixed sandboxed Bash commands on Linux reporting exit code 0 for failed commands when the shell is zsh
- Fixed the Read tool hanging instead of reporting an error when part of a large file could not be decoded under memory pressure
- Fixed `--resume`, the resume picker preview, resumed background agents and the transcript view failing on a session whose saved history contains a malformed task-reminder or @-file attachment entry
- Fixed a crash when resuming a conversation whose transcript contains a malformed message entry, and a fullscreen crash when such a conversation received new messages while scrolled up
- Fixed sessions failing to resume or start when their saved transcript contains a malformed message content block
- Fixed Grep, Glob and @-file suggestions hanging or running out of memory on searches over the 20MB output cap, and system ripgrep reporting “no matches” instead of an error after a flood of warnings
- Fixed `/rewind` in a forked or background session restoring a zero-filled or truncated file when the session’s file-history backups could not be fully copied
- Fixed fullscreen sessions sometimes exiting with “Claude Code exited after an unrecoverable interface error” when typing fast or holding a key with the slash-command dropdown open
- Fixed background sessions crashing and restarting their worker when a command fed through stdin ran on a machine that had run out of file descriptors
- Fixed a crash at launch when `~/.claude.json` holds a malformed `mcpNeedsAuthNoticed` value
- Fixed `--resume` and `--continue` dropping a conversation’s earlier thinking when a built-in tool it started with has since been switched off by a server-side flag
- Fixed text selected with the mouse in the fullscreen `claude --resume` session picker never reaching the clipboard
- Fixed plugin reload previews replacing a running session’s extracted plugin files when the plugin was loaded from a `--plugin-dir` or `--plugin-url` archive
- Fixed self-hosted runners with `--drain-wait-sec` losing the final result of a turn that finished during a SIGTERM drain; the runner now waits briefly for the turn to be reported
- Fixed `SubagentStop` hooks with a specific `matcher` firing for every stopping subagent whose agent type was empty
- Fixed sandboxed Bash commands being unable to write to project directories named `hooks/` or `config/`
- Fixed Artifact updates failing with “File not found” after a session resumes on another machine or its scratchpad is cleared: the page’s last published version is restored
- Fixed `/update-config` writing `Write(path)` permission rules, which file permission checks don’t match, instead of `Edit(path)` rules
- Fixed four dead documentation URLs (Pricing, Computer Use, Skills, CLI) in the bundled claude-api skill’s live-sources table
- Improved prompt caching for a `--system-prompt` that contains a `__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__` line: the text above it is now cached globally, as the SDK’s array form already is
- Improved the `/desktop` error when Claude Desktop does not open: it now says why and what to do next
- Improved the Artifact tool’s publish and read results: they now say who can open the page and what the owner’s Share menu offers
- Improved artifact publish results: they name the tab icon sent, warn when the page contains a NUL byte, and retry a flaky fetch of the newer page to merge after a stale publish
- Improved pasted and attached images: they are now saved where Claude can open them as files without a permission prompt, including in Desktop and VS Code
- Improved the Artifact tool’s guidance so Claude updates a shared artifact in place when you were given edit access to it, instead of publishing a separate copy
- Improved plan-usage reads: editor windows and non-interactive sessions on one machine now share a read made in the last minute instead of each calling the usage endpoint
- Improved the `ListPlugins` tool description so Claude knows it lists plugins enabled on your claude.ai account, not plugins installed locally with `/plugin`
- Improved responsiveness when the terminal is slow or paused: output no longer falls further behind while the terminal catches up
- Improved Write and Edit results for files in the synced account-skills folder: they now say the change is not saved to your account and how to save it
- Updated `/logout` for Claude apps gateway sign-ins to also end the session on gateways that advertise token revocation
- Changed hosted sessions to keep an unanswered permission prompt up after a container restart, instead of asking again
- Changed the Artifact tool to ask for a one-word tab icon on a first publish instead of an emoji favicon
- Changed Claude in Chrome in auto mode to skip the extension’s per-site check for classifier-approved calls, as bypass mode does, fixing `browser_batch` “Permission denied” after a redirect
- Changed plugins installed from an npm source to be fetched with `npm pack --ignore-scripts` and integrity-verified, so a package’s install scripts no longer run
- Changed scheduled and Run now routine runs to save data to, and republish the page of, an artifact you can edit without asking; public artifacts, first publishes and deletes still ask
- Removed the startup notice that told you a one-off scheduled routine had run since your last session
- \[VSCode\] Added viewing, editing and deleting a saved memory inside the Memory dialog
- \[VSCode\] Added sending an attached image without typing any text
- \[VSCode\] Added a Retry link to the MCP servers dialog when the server list fails to load
- \[VSCode\] Added accept and reject buttons under each change in the proposed-change diff tab, so an edit can be reviewed change by change
- \[VSCode\] Fixed the transcript creeping toward the bottom in small steps while a permission card waits and content keeps arriving
- \[VSCode\] Fixed rewound and forked conversations not keeping the permission mode you had picked for the original conversation
- \[VSCode\] Fixed an empty `CLAUDE_CONFIG_DIR` entry in the `environmentVariables` setting making Claude Code keep its files in the workspace
- \[VSCode\] Fixed plugin install links opening the Manage plugins dialog for plugin names and marketplace addresses that can’t be used in a link
- \[VSCode\] Fixed Remote Control staying shown as connected after a turn-off that Claude Code reported as failed; it now shows as off
- \[VSCode\] Fixed the scroll to the bottom on send stopping short of the reply when the reply starts arriving during the scroll
- \[VSCode\] Fixed the agent map showing agents a crash left unfinished as stopped instead of failed once the session is reopened
- \[VSCode\] Fixed the “Continuing the step” notice not appearing, and the continue limit resetting, after a reload that follows a crash with background tasks still running
- \[VSCode\] Fixed the session list showing when a session was last reopened, such as after a window reload, instead of when its last message was sent
- \[VSCode\] Fixed “Fork conversation from here” failing on the message right after one sent while Claude was working
- \[VSCode\] Fixed the prompt cache clock showing too few minutes after reopening a session with a message sent while Claude was working
- \[VSCode\] Fixed a background agent that finished while Claude was running a tool losing its completion notice, and its result on the agent map, after a window reload
- \[VSCode\] Fixed a rare case where text selected in a git-ignored file could be sent to Claude after the extension was unresponsive for several seconds
- \[VSCode\] Fixed renaming a running session reverting to the generated name (regression in 2.1.269)
- \[VSCode\] Fixed slash commands typed while Claude is responding being sent to the model as text instead of running once the response finishes
- \[VSCode\] Fixed unreadable code in the plan preview and the Hooks and Permission rules dialogs with the High Contrast Light theme
- \[VSCode\] Fixed `/remote-control` being ignored while Remote Control is still connecting: running it again now turns Remote Control off immediately
- \[VSCode\] Fixed the conversation pulling you back to the bottom while a reply streams after you scroll up, and added a `claudeCode.scrollToBottomOnSend` setting to turn off the jump on send
- \[VSCode\] Fixed the Manage plugins dialog showing a password or token that was typed into a marketplace URL
- \[VSCode\] Improved the agent map: the pill counts running agents and turns red after a failure, the main agent stays in view while the map scrolls, and agents sort by state then end time
- \[VSCode\] Changed New session in a Claude editor tab to open in the sidebar when Preferred Location is set to Sidebar, instead of always opening another tab
- \[VSCode\] Changed a message sent while Claude is working to wait at the bottom of the conversation until Claude starts on it
- \[Claude Code on the web\] Added a “New routine” button to the page shown when a routine link no longer resolves, next to the link back to your routines list
- \[Claude Code on the web\] Fixed routine “paused” and “on hold” notifications being cut off mid-sentence; the paused-subscription notice now says to turn the routine back on yourself
- \[Claude Code on the web\] Fixed cloud environments with a very long allowed-domains list saving fine and then failing every session start; saving now fails up front and says how much to trim
- \[Claude Code on the web\] Fixed Claude’s guidance when a cloud session on a personal account is denied GitHub access: it now links to claude.ai/connect-github instead of an admin settings page
- \[Claude Code on the web\] Improved what Claude tells you when asked to edit, delete or run a routine it didn’t create: it now links to the routine’s page so you can do it yourself
- \[Claude Tag\] Added attach conditions for access bundles in Claude Tag settings: an Owner can let a bundle also apply in channels with guests or Slack Connect channels, not just member-only
- \[Claude Tag\] Added Amazon CloudWatch, CloudWatch Logs, Amazon SNS, Google Cloud Monitoring and Cloud Logging presets to an access bundle’s Credentials tab in Claude Tag admin settings
- \[Claude Tag\] Added Datadog presets for the US3, AP1, AP2 and US1-FED sites; new Datadog connections are now limited to Datadog’s read and query API routes
- \[Claude Tag\] Fixed S3 uploads from recent AWS CLI and SDK versions failing with a 502 error when sent through an AWS connection
- \[Claude Tag\] Fixed Claude treating a channel as inactive, and skipping untagged messages there, while it was still posting in that channel from a routine or a thread
- \[Claude Tag\] Fixed a thread’s “Claude \[task\]” display name reverting to plain “Claude” after the session behind that thread was refreshed or restarted
- \[Claude Tag\] Fixed the model you switched to in a Slack thread silently reverting to the channel’s default after that thread’s session was restarted or refreshed
- \[Claude Tag\] Fixed Claude sometimes replying twice when another app or bot @mentioned it in a top-level channel message
- \[Claude Tag\] Improved Claude’s notices in Enterprise Grid channels shared across workspaces: they now say when no workspace is set up yet, or why only organization defaults apply
- \[Code Review\] Fixed reviews occasionally dropping part of their analysis when one of the reviewing agents returned its findings in an unexpected format
- \[Code Review\] Fixed pull requests with more than 100 Claude reviews getting a full re-review on every clean merge from the base branch instead of the lighter merge-focused review
[](#2-1-274)
2.1.274
September 17, 2026
- Added a visible warning when memory usage is critical, with steps to free memory or restart safely
- Added `CLAUDE_CODE_MCP_STARTUP_WAIT_MS` to bound how long the first non-interactive turn waits for connecting MCP servers (`0` = don’t wait)
- Added `effort` attribute to the `claude_code.llm_request` OpenTelemetry trace span, matching the `api_request` event
- Added `claude_code.managed_settings_resolved` OTel event: managed-settings sources and policy helper state; redacted settings and digests with `OTEL_LOG_MANAGED_SETTINGS=1`
- Added `store.connect_timeout_seconds` to the Claude apps gateway config to lengthen the Postgres connect timeout (default 5 seconds), and improved the boot error when the database is unreachable to point to `store.postgres_url` and the configured timeout
- Added `enduser.sub`, the IdP subject, to the telemetry Claude Desktop and Cowork send through a Claude apps gateway
- Added a Claude apps gateway warning when a replica has more requests open than the 256 it sends upstream at once, and a startup log line showing that limit
- Added click-to-expand for collapsed teammate and agent messages in fullscreen mode
- Fixed sessions getting stuck endlessly retrying “unexpected tool_use_id” 400 errors: corrupted transcripts now self-heal where possible, and otherwise a clear error (with a `/rewind` hint) ends the loop
- Fixed MCP servers configured as `http` that only speak legacy HTTP+SSE failing to connect when they answer the first request with 422 or another 4xx error
- Fixed Streamable HTTP MCP tool calls timing out after about 5 minutes even when a longer per-server `timeout` was set
- Fixed MCP prompts and resources not refreshing when a server sends list-changed notifications without declaring `listChanged`
- Fixed MCP tool calls refused with 403 insufficient_scope being reported as an expired sign-in: the error now names the missing permissions and points to `/mcp` re-authentication
- Fixed hook-driven sessions (such as an active `/goal`) ending with “Prompt is too long” instead of compacting when the context overflowed again after a reactive compaction
- Fixed an active `/goal` being lost when resuming (`--continue` / `--resume`) a session that had compacted
- Fixed `claude agents` losing `--model`, `--effort`, `--permission-mode`, `--allow-dangerously-skip-permissions` and `--agent` after an auto-update relaunch
- Fixed a per-turn slowdown when a language server publishes project-wide diagnostics for thousands of files
- Fixed subagents with `model: "opus"` on Bedrock, Vertex or Foundry leaving the session’s model when its id has no recognizable model family (unless `ANTHROPIC_DEFAULT_OPUS_MODEL` is set)
- Fixed self-hosted runner sessions failing every turn with a 401 after a few failed token refreshes, until the next scheduled refresh; the runner now keeps retrying, and fetches a new token after a 401
- Fixed clickable links to local file paths doing nothing in VS Code and other terminals that require a `file://` URI
- Fixed the transcript renumbering ordered lists in your own messages (typing “3. 2. 1.” displayed “3. 4. 5.”); numbers and “N)” markers now show as typed
- Fixed AskUserQuestion preview notes being attached to a previously chosen option instead of the highlighted one
- Fixed AskUserQuestion preview mode dropping the highlighted option when submitting a note with Enter
- Fixed a resumed background agent keeping half of an interrupted tool batch when one of its calls was approved with a message
- Fixed a local `claude -p --resume` started with `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` not reporting background tasks the previous process left unfinished
- Fixed the first turn of a cloud session sometimes starting without the tools of an SDK-hosted MCP server that was still connecting
- Fixed background agent notifications claiming the agent had no live background work when it was still waiting on its own background task and would resume
- Fixed error hints in Claude Desktop sessions to suggest slash commands like `/usage-credits` instead of CLI flags that cannot be used there
- Fixed `/schedule` saving a routine’s prompt without its message role when Claude writes the routine in the shape that listing routines returns
- Fixed `/status` not showing the `apiKeyHelper` failure that its own error banner told you to check
- Fixed `/fast on` in non-interactive sessions reporting on and then turning off under an organization’s managed fast mode policy; it now says the organization has disabled it
- Fixed the Artifact tool asking you to approve an update to an artifact that it then refused because the session had not read the latest version
- Fixed Cowork and claude.ai cloud sessions with network access on treating reads of a teammate’s artifact as if network access were off
- Fixed a plugin or marketplace directory with no git repository of its own taking its version from an enclosing git repository, such as a git-managed `~/.claude`
- Fixed `--strict-mcp-config` with an empty `--mcp-config` holding the first non-interactive turn for up to `MCP_TIMEOUT` on incidental MCP servers
- Fixed Stop prompt hooks re-sending their whole prompt on every block in a conversation; repeat blocks now name the condition with a 500-character label
- Fixed extra empty editor windows opening at startup on Linux under Wayland when running inside the Cursor or VS Code terminal
- Fixed an unhandled promise rejection in the Claude apps gateway when Postgres drops a connection during a spend check
- Fixed Claude apps gateway cutting every open stream on SIGTERM: it now lets in-flight requests finish for up to 25 seconds before exiting (`CLAUDE_GATEWAY_DRAIN_TIMEOUT_MS`)
- Fixed `installed_plugins.json` being rewritten on nearly every start-up when plugin policy comes from remote managed settings, which made Claude Desktop reload every open session’s plugins
- Fixed headless and SDK sessions making a separate model call for every background task that finished; completions already queued are now answered by one call
- Fixed the Bash tool re-sourcing the shell profile (a multi-second stall on the next command) after every plugin reload; it now does so only when the plugins’ `bin/` directories changed
- Fixed plugins with a top-level `$schema` in `hooks/hooks.json` showing an “unknown key” notice
- Fixed MCP connection errors and the MCP login tool’s description showing secrets resolved from `${VAR}` placeholders in MCP configs
- Fixed Bash permission checks for commands that loop over or assign certain special shell variables; these commands now ask for permission
- Fixed worktree-isolated sessions accepting Bash commands with certain nested shell expansions; these are now refused
- Fixed the Edit permission prompt preview sometimes showing a different location than the approved edit in files with multi-byte characters
- Fixed background commands being stopped after 30 idle minutes on machines under mild memory pressure; they’re now stopped only when memory is critically low, and the debug log says why
- Fixed a message a subagent sends to the main session disappearing from the Claude Desktop transcript after a relaunch
- Fixed a plugin loaded from a `.zip` being served from a stale extraction after several overlapping reloads
- Fixed a sub-agent’s progress summary being replaced by a runaway multi-paragraph reply
- Improved startup in `--input-format stream-json` sessions: the first turn no longer waits up to 2s for still-connecting MCP servers whose tools tool search defers; they arrive on a later turn
- Improved Monitor tool notifications: a script’s final output and its exit now arrive as one notification instead of two, saving a model turn
- Improved Artifact tool errors: when you are not signed in to claude.ai the terminal now says so on the first attempt, and Claude is told to stop retrying a rejected call sooner
- Improved artifact publishing: a publish built on an older version is stopped before it is sent, with the newer page to merge
- Improved safety checks before removing an agent worktree that contains submodule checkouts
- Improved `OTEL_LOG_RAW_API_BODIES=file:<dir>` output: a new `index.jsonl` and `request_body_id` / `message.id` event attributes link each response to its request file and transcript message
- Improved Claude apps gateway boot: it now tries the first Postgres connection up to three times before exiting, so a database that is reachable a few seconds late no longer fails the boot
- Improved the Claude apps gateway’s spend-limit check under load: it now takes one database round trip instead of four, so fewer checks time out on a busy gateway
- Improved Claude apps gateway sign-in rate limit errors: `/login` now explains the refusal, and the gateway log says which limit was hit and which setting to change
- Changed Bedrock, Vertex, Foundry and telemetry-disabled installs to use the v2 MCP client and MCP 2026-07-28 negotiation with direct HTTP servers by default, as other installs already do (opt out: `MCP_SDK_GENERATION=v1` or `MCP_PROTOCOL_NEGOTIATION=legacy`)
- Changed `/code-review` to use leaner inline review prompts for every model that has no tuned settings of its own, instead of spawning many review subagents
- Changed `"type": "sdk"` MCP entries in `.mcp.json`, settings, plugins and agent files to be skipped with a warning: only an SDK host application can register in-process servers
- Changed artifact watching in local sessions: a new version published elsewhere no longer starts a turn; Claude learns of it from a later Artifact tool result
- Changed plugin and marketplace clones to leave Git LFS files as pointers instead of downloading them; `git lfs pull` in the checkout fetches them
- Changed self-hosted runners to skip a read-only repository the git host refuses at the access check instead of failing the session start
- Changed the `/status` GitHub line to read “Cloud sessions”, and `/web-setup`, `/ultrareview`, and teleport messages to say “cloud session” instead of “Claude Code on the web”
- \[VSCode\] Added continuation of the step a window reload interrupted, labeled in the chat, with a Claude Code: Continue After Reload setting to turn it off
- \[VSCode\] Added Memory and Instructions entries to the Customize menu: Memory shows the auto-memory toggles, the saved memories and the memory folders, and Instructions edits the CLAUDE.md files
- \[VSCode\] Added a `claudeCode.lockEditorGroups` setting to stop Claude from locking the editor groups it opens in
- \[VSCode\] Fixed a `/btw` side question asked in a new conversation’s first seconds occasionally showing another session’s side-question history
- \[VSCode\] Fixed a brief freeze when the extension first looks up your global gitignore file
- \[VSCode\] Fixed a message sent while Claude was running a tool disappearing from the conversation after a window reload
- \[VSCode\] Fixed the Manage Plugins enable toggle and MCP servers dialog rows being unreachable from the keyboard
- \[VSCode\] Fixed sign-ins and sign-outs made in a terminal not showing until a reload after `CLAUDE_CONFIG_DIR` changed in the Environment Variables setting
- \[VSCode\] Fixed Edit diffs in the chat being cut off at the bottom at some panel widths and for long wrapped lines; diff boxes now fit the rows shown
- \[VSCode\] Fixed overlapping settings writes from the extension leaving `~/.claude/settings.json` unparseable or dropping a setting
- \[VSCode\] Fixed Open in New Tab (Ctrl/Cmd+Shift+Esc) sometimes leaving the new tab’s message box unfocused, so typing went nowhere until you clicked it
- \[VSCode\] Fixed reopening a closed Claude tab splitting the editor layout when its locked group still holds another Claude tab and a file
- \[VSCode\] Fixed New session opening another locked editor group whenever a file tab shared the group with your Claude tab
- \[VSCode\] Fixed session names shifting sideways in the session picker while typing a search query
- \[VSCode\] Fixed the plan review card cutting off its Send feedback button and reason field when a plan has several comments; the comment list now scrolls
- \[VSCode\] Fixed inline code and code blocks in chat replies being unreadable under the High Contrast themes
- \[VSCode\] Improved screen reader navigation of the conversation: each message is announced as “You” or “Claude”, with the tool name for tool steps
- \[VSCode\] Changed the default global gitignore file to `$XDG_CONFIG_HOME/git/ignore` when `XDG_CONFIG_HOME` is an absolute path
- \[Claude Code on the web\] Added a “Compare against” branch picker to a cloud session’s diff view, so you can diff its changes against any branch instead of only the base branch
- \[Claude Code on the web\] Fixed git operations in cloud sessions failing with “service unavailable” when GitHub’s token renewal briefly errors
- \[Claude Code on the web\] Fixed editing a routine occasionally making it fire twice or re-enabling a routine that had just been paused
- \[Claude Code on the web\] Fixed commits in cloud sessions occasionally failing with a signing error for a few minutes after the session’s credentials refreshed
- \[Claude Code on the web\] Fixed the toast after saving a routine whose GitHub trigger couldn’t be linked to show the reason, such as a per-repository trigger limit, instead of only “edit to retry”
- \[Claude Code on the web\] Fixed sessions sometimes flipping back to unread right after you mark them read
- \[Claude Code on the web\] Changed routines to skip a run and retry for up to 72 hours when the owner’s GitHub connection is missing, instead of switching the routine off at the first failed check
- \[Claude Code on the web\] Changed a routine’s on-hold notice: when your subscription is paused it now tells you to turn the routine back on yourself instead of promising an automatic resume
- \[Claude Tag\] Added a Guests setting to the Add channel and Add workspace forms in Claude Tag admin settings, so owners can pick Inherit, Allow, Channel only or Restrict up front
- \[Claude Tag\] Fixed Claude not answering when another Slack app or bot @mentions it; the tag now gets a reply and wakes Claude in a channel it had stopped following after days of inactivity
- \[Claude Tag\] Fixed Claude missing another app’s message that tagged @Claude right after a new Slack channel was created; it’s now delivered once Claude has joined
- \[Claude Tag\] Fixed Claude folding a follow-up sent minutes after its last Slack message into it as a silent edit; late updates such as blockers now post as a new reply that notifies
- \[Claude Tag\] Fixed Claude’s Slack search failing with an error whenever it searched within a single channel; it now returns that channel’s matching messages
- \[Claude Tag\] Fixed a safety-filter stop silently resetting a Slack thread’s context when nobody was waiting; Claude now always says so and no longer cancels background work still running
- \[Claude Tag\] Fixed email addresses in Claude’s Slack replies rendering with a visible `mailto:` prefix; they now show as the plain, clickable address
- \[Claude Tag\] Fixed Claude refusing to watch an Enterprise Grid channel shared with the whole organization when asked from another workspace in the grid
- \[Claude Tag\] Fixed the Environment picker in Claude Tag admin settings showing a raw environment ID instead of the environment’s name for archived or app-created environments
- \[Claude Tag\] Improved Claude’s live progress checklist in Slack: capped at 2,000 characters, reposted at most every 15 minutes in busy threads, with older “Latest task list” links updated
- \[Claude Tag\] Removed the repeated guest-attribution note Claude appended to a Slack canvas each time it edited one in a channel using the “Channel only” guest setting
- \[Code Review\] Fixed re-reviews occasionally leaving a fixed finding’s thread open when the new review also filed a lower-severity note under it
- \[Code Review\] Fixed rare reviews ending with “Code review encountered an error” when GitHub or an internal service failed transiently at launch; they now wait and retry
- \[Code Review\] Improved how Code Review words each posted finding: short plain sentences that say who is affected, where the code goes wrong, and the fix up front
- \[Code Review\] Improved the check-run card and PR comment when a review is skipped because of an organization limit: each cause now links the admin page that fixes it
[](#2-1-273)
2.1.273
September 15, 2026
- Added `x-claude-code-request-class`, `x-claude-code-agent-type`, `x-claude-code-prev-tool-durations`, `x-claude-code-compaction` and `x-claude-code-context-compacted` request headers for LLM gateways; opt in with `CLAUDE_CODE_GATEWAY_HINT_HEADERS=1`
- Added a notification when an MCP server disconnects mid-session and automatic reconnection gives up, pointing at `/mcp`
- Added forking a session started with `claude --remote-control` or `/remote-control` from the Claude app; the fork runs as a background session on your computer
- Fixed Bash commands the permission checker cannot fully analyze skipping the prompt under `permissions.blockReadsOutsideWorkingDirectories`, and a subshell hiding a dangerous `rm` in bypass mode
- Fixed skills synced from claude.ai staying available after your organization turns Skills off; they now move to the recoverable trash
- Fixed `allowManagedMcpServersOnly`, `deniedMcpServers` and `disableClaudeAiConnectors` set via MDM or `managed-settings.json` being ignored when server-managed settings are also present
- Fixed 401/403 errors on Bedrock, Vertex and Foundry, and Claude apps gateway 403s, telling you to run `/login`; the message now names the credential to refresh or points to your gateway administrator
- Fixed `/login`, `/upgrade`, and `/extra-usage` discarding earlier thinking from the conversation, which forced a full prompt-cache rewrite on the next request
- Fixed auto mode stopping for approval when the Artifact tool uploads a file you attached to the chat in a cloud or Remote Control session
- Fixed a long-running session recreating a stub `.git/info/exclude` after the repository’s `.git` directory was removed or moved away
- Fixed the main prompt dropping a `!` typed at the start while already in shell mode, so negated commands like `! grep …` can be typed
- Fixed Read on macOS refusing a dragged-in screenshot, or any file the system reports under a second path, with “symlink resolution changed after permission was checked”
- Fixed `permissions.blockReadsOutsideWorkingDirectories`: a memory directory chosen by a repository’s settings is no longer loaded into the prompt, recalled, indexed, or used by memory extraction
- Fixed sub-agents and background agents being reported as failed, with their result never delivered, when the final streamed reply omitted token usage or carried no model id
- Fixed the context meter and auto-compact counting advisor-tool turns at roughly twice their real context size, which made auto-compact fire at about half the real window
- Fixed `/tui` refusing to restart because of an agent-team teammate that had already finished its work and was no longer shown in the agents panel
- Fixed saved scheduled tasks running in the wrong session after `.claude/scheduled_tasks.json` was copied into another folder, such as a new worktree
- Fixed SDK and `--output-format stream-json` output dropping a subagent’s remaining messages and final report after it is moved to the background mid-run (e.g. by `CLAUDE_AUTO_BACKGROUND_TASKS`)
- Fixed `/install-github-app` reporting a SAML single sign-on block as “admin permissions required”
- Fixed Remote Control clients attached to a Claude Desktop, VS Code or JetBrains session being refused when they ask for the session’s context window usage
- Fixed the spinner showing a doubled ellipsis (”……”) on compaction status lines such as “Running PreCompact hooks…”
- Fixed a false-positive spinner tip suggesting the frontend-design plugin after reading or publishing Artifacts
- Reverted a 2.1.268 change that checked Read and Edit deny rules on Bash lines the permission checker can’t analyze (`eval`, `env -C`); commands like `time -p make build` prompt again instead of being denied
- Improved responsiveness in long sessions: hook progress and sub-agent activity no longer re-process the whole conversation on every update
- Improved the Artifact tool’s error when a publish includes a file type artifacts don’t serve: Claude is told which types are served and what to do instead, and the terminal shows one plain line
- Improved the Artifact tool’s page read to state the capabilities and database rules the artifact service holds for the page, for anyone who can publish to it
- Improved artifact database writes: an update can now remove a single field instead of rewriting the whole document
- Improved artifact publishing: a publish whose connection drops after reaching claude.ai is now re-sent safely instead of failing or creating a duplicate version
- Improved the cloud-session GitHub error for an IP allow list, a suspended app installation or SAML single sign-on to show the cause instead of a generic install hint
- Improved `/autofix-pr`: when `gh pr view` fails it now shows gh’s own error (sign-in, SAML, rate limit) instead of a generic exit-code line
- Improved `/autofix-pr` to say why GitHub webhook delivery couldn’t be set up for the PR (for example, no linked GitHub account) instead of a generic warning
- Improved `/web-setup` errors: a refused GitHub token now lists the likely reasons and the fix, and a connection failure names a configured proxy or TLS certificate problem
- Improved the in-session SSL certificate and proxy connection errors to name the error code and what to fix, such as `NODE_EXTRA_CA_CERTS` for an untrusted corporate CA
- Improved the error when a cloud session can’t be created because your Claude login expired or was revoked: it now tells you to run `/login`
- Improved the error shown when an MCP server’s sign-in expires mid-session to say how to re-authenticate (`/mcp`)
- Changed auto mode on Bedrock, Vertex and Foundry to use the local classifier by default for now; set `CLAUDE_CODE_AUTO_MODE_SERVER=1` to use the platform’s server-side classifier
- Changed `OTEL_LOG_TOOL_DETAILS=1` to also include real agent, skill, plugin and MCP server names on cost and token metrics
- Changed sign-in with a Claude account to also request access to your claude.ai plugins
- Changed `/bug` and `/feedback` reports to include only model-behavior params (model, system prompt, tools) from the last API request, omitting request metadata and `CLAUDE_CODE_EXTRA_BODY` fields
- \[VSCode\] Fixed “Report a problem” still appearing, and `/bug` / `/feedback` opening a report form, for organizations that have product feedback disabled
- \[VSCode\] Fixed a red “Claude Code process exited with code 4294967295” banner appearing after completed turns on Windows
- Windows: Improved the network-path permission check for UNC paths when a mapped network drive was added with `--add-dir`
- \[Claude Code on the web\] Fixed routines losing access to an organization connector, and still calling the old one, after an admin removed and re-added that connector
- \[Claude Code on the web\] Fixed creating a self-hosted environment from organization settings occasionally failing with a server error and leaving a half-created environment behind
- \[Claude Code on the web\] Changed the admin “Share cloud sessions” setting to live under Data and privacy instead of the Claude Code page, where Data and privacy admins can also manage it
- \[Claude Code on the web\] Added a “Discard unsaved changes?” confirmation before the New routine page or the Edit routine dialog throws away a routine name, prompt or edit you typed
- \[Claude Code on the web\] Removed the full-page desktop-app download screen that new users without a cloud environment saw on Mac and Windows; they now go straight to setup
- \[Claude Code on the web\] Improved the routine detail page: menu and rename in the breadcrumb, the on/off switch and Run now at the top, and run history beside the routine’s settings
- \[Claude Tag\] Fixed Claude going silent minutes after reinstalling the app when an Enterprise Grid was disconnected but one of its workspaces stayed connected
- \[Claude Tag\] Fixed scheduled tasks set up in an organization-shared private Slack channel silently never posting; they now keep running in the thread they were created in
- \[Claude Tag\] Fixed replying in an older Slack thread while Claude is mid-task sometimes restarting it from scratch and losing work it had not pushed yet
- \[Claude Tag\] Fixed Claude occasionally dropping a message with an incorrect “couldn’t find a Claude Code environment” notice right after your account token refreshed
- \[Claude Tag\] Fixed AWS connections refusing region-less endpoints such as Budgets, Savings Plans, WAF Classic and Import/Export; Global Accelerator requests now sign correctly
- \[Claude Tag\] Improved AWS connection failures: when a request can’t be signed, such as a hostname with no region, Claude is told why and how to fix it instead of a bare error
- \[Claude Tag\] Fixed OAuth client-credentials and JWT-bearer connections failing with providers that return a lowercase token type; requests now send the standard Bearer scheme
- \[Claude Tag\] Fixed adding a channel manager being refused on Enterprise Grid shared channels, on channels where Claude hasn’t been used yet, and on legacy private channels
- \[Claude Tag\] Changed Claude to start watching related public channels on its own, such as an incident channel a conversation depends on, instead of only when asked
- \[Claude Tag\] Fixed the admin Memory page not listing Slack channels Claude set up on its own even when they had saved memory; admins can now open, edit and delete that memory
- \[Code Review\] Fixed merging the base branch into a PR whose earlier review listed “Additional findings” triggering a full re-review; these pushes now get the lighter follow-up review
- \[Code Review\] Fixed a whole REVIEW.md being ignored because of an @-mention, a code span wrapped across lines, or a backticked HTML tag; only lines linking to changed files are withheld
- \[Code Review\] Improved suggested fixes to say what the fix must keep working when other code depends on the behavior being changed
- \[Code Review\] Improved review comments that point to a second affected location to state that location’s issue in a full sentence instead of a cut-off stub
- \[Code Review\] Fixed `/ultrareview --post` so a retry after a GitHub error posts the findings comment exactly once instead of never or twice; the comment now names the reviewed commit
- \[Code Review\] Fixed empty or content-identical pushes being re-reviewed on GitHub repositories whose owner or name contains a capital letter; these pushes are now skipped
[](#2-1-272)
2.1.272
September 15, 2026
- Bug fixes and reliability improvements
[](#2-1-271)
2.1.271
September 14, 2026
- Added fast mode in Claude Code Remote sessions (cloud and self-hosted runners): the host’s fast-mode setting or `/fast` typed in the session applies where your organization allows it
- Added mouse support to the `/config` panel in fullscreen mode: the wheel scrolls the settings list, a click on a setting’s value changes it, and the row under the pointer is highlighted
- Added `claude self-hosted-runner --drain-marker-file <path>`: when that file exists at a SIGTERM drain, the runner reports its exit to the server as a host drain (telemetry only)
- Added per-command `allowed_domains` to Bash, PowerShell and Monitor in auto mode with sandboxing: the hosts a command needs are reviewed with it and opened for it alone; other hosts are refused
- Added `omitClaudeMd` to agent frontmatter and `--agents` JSON, letting custom and plugin subagents run without user, project and local CLAUDE.md files; managed policy files still load
- Added `--accept-command <sha256>` to `claude plugin install` and `claude plugin update` to accept exactly the command a previous `--json` run displayed, instead of `-y`
- Added support for a `multiplier` above 1, up to 10, in the `modelPricing` managed setting and the Claude apps gateway `pricing` block, for marked-up internal chargeback rates
- Added a spinner tip pointing Bedrock, Vertex AI, Foundry and LLM gateway users to the Claude desktop app; the claude.ai desktop app tip now suggests `/desktop`, which offers to download the app
- Fixed a cached organization policy being reused after switching accounts, organizations, or API keys, and the policy not refreshing until the hourly check when the credential changes mid-session
- Fixed the tool and command lists not updating when the organization policy finishes loading after startup or changes mid-session
- Fixed an enterprise `managed-mcp.json` that can’t be read or parsed being ignored: it now keeps exclusive MCP control (user, project and plugin servers don’t load) and warns at startup
- Fixed org policy being fetched through, and rejected by, third-party local proxies set via `ANTHROPIC_UNIX_SOCKET`; they are again treated like other custom gateways, including for Remote Control
- Fixed cloud sessions rejecting every subagent tool call (“updatedInput … failed schema validation”) when a workflow or agent approval was applied after the session’s worker restarted
- Fixed `/fast off` answering “Fast mode unavailable” instead of turning fast mode off when the organization has fast mode disabled
- Fixed sessions started with `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK` re-sending fast requests every turn after the API rejected fast mode; the rejection now stands and its reason is shown
- Fixed fast mode under `CLAUDE_CODE_RETRY_WATCHDOG` failing the turn on a usage-credits limit, or retrying an overload at fast speed, instead of falling back to standard speed
- Fixed Bash permission checks missing the file that `fmt`, `column` and similar commands read when it follows an option the checker doesn’t recognize
- Fixed Bash permission checks skipping files a wildcard expands to when the wildcard sits in a command’s pattern or option value (for example `grep -v dir/* file`)
- Fixed Bash permission checks so that shell variable declaration flags cannot misrepresent the command being run
- Fixed Bash commands with two directory changes, a subshell, or a `cd`+`git` chain skipping the prompt under `permissions.blockReadsOutsideWorkingDirectories` in bypass and auto mode
- Fixed a stale `.git/config.lock` breaking `git checkout -b`, `git push -u` and `git config` for the rest of a session after a sandboxed command failed to start (Linux)
- Fixed settings file changes made outside the session going unnoticed on macOS machines whose system file-event service is saturated; the watcher now falls back to polling
- Fixed resumed `claude -p` sessions whose tools all come from MCP servers failing with “At least one tool must have defer_loading=false”
- Fixed turns failing with “API returned an empty or malformed response” when an LLM gateway returns the non-streaming reply as `text/plain`
- Fixed sustained high CPU usage and repeated tool-list requests when an MCP server sends `list_changed` notifications in a tight loop
- Fixed MCP OAuth mishandling client registrations: denying consent forced a new one, one for another redirect URI was reused, and a concurrent write could delete a valid one or keep a mismatched one
- Fixed tool search returning no match when Claude selects an MCP tool by its bare name instead of its full `mcp__server__tool` name
- Fixed Ctrl+O cancelling pending MCP server reconnects, and `/mcp` sent from Remote Control failing while the transcript view is open
- Fixed the Claude in Chrome prompt telling the model to load tools through ToolSearch when ToolSearch is unavailable
- Fixed cross-session messages held by the receiving session’s permission-mode policy leaving no trace: headless senders now get a delivery notice, and `SendMessage` results no longer imply it was read
- Fixed Claude starting a second copy of a background command (such as a watch task or dev server) that was still running after the conversation was compacted
- Fixed `/model` warning about losing the conversation cache when switching back to the model the conversation actually ran on
- Fixed `/reload-skills` reporting a skill count that disagreed with the slash menu after `/cd`
- Fixed `/resume` and `/continue` showing only 1-2 sessions in fullscreen mode on short terminals
- Fixed `/resume` and `/teleport` keeping the previous conversation’s file-read tracking, so Claude could edit files the resumed conversation had never read
- Fixed `--resume` dropping the 1M context window (`[1m]`) when the resumed session’s model family differs from the configured default model
- Fixed artifacts attached with `/artifacts` disappearing from the session after `--resume`
- Fixed background sessions (`claude --bg`, `claude agents`) not watching the artifacts they publish for republishes made elsewhere
- Fixed custom agents, slash commands and output styles beyond the first not loading from a virtual drive that reports inode 0, such as an encrypted vault mounted as a Windows drive
- Fixed self-hosted runner sessions silently losing all host config (settings, skills, plugins, MCP servers) when the host config directory exceeds 64 MiB; added `--host-config-snapshot disk|memory`
- Fixed skills synced from claude.ai staying on disk indefinitely after signing out; copies not refreshed within `cleanupPeriodDays` now move to the recoverable trash at the next launch
- Fixed spinner tips suggesting commands that aren’t available for your account type or are disabled in your session
- Fixed the `/add-dir` path input: the left and right arrow keys now move the cursor, and Enter adds only the typed path instead of also adding the highlighted completion
- Fixed text fields outside the main prompt moving a leading `!` to the end of what you typed (`!foo` came out as `foo!`)
- Fixed the interactive `/hooks` menu crashing when a hook matcher is named after an inherited object property such as `__proto__` or `constructor`
- Fixed a fullscreen rendering glitch where text kept a stale background color after the box around it lost its background
- Fixed Delete in st and Alt+arrow keys in rxvt-unicode not working in attached background sessions
- Fixed the terminal’s replies to capability queries (`^[[?1;2c`) appearing at the shell prompt or in an editor when Claude Code exits, is suspended, or opens an editor right after starting
- Improved terminal rendering performance: large diffs and long transcripts render faster, with fewer slow frames
- Improved startup time slightly by skipping a redundant validation of built-in model data on every launch
- Improved hook feedback: while a SessionStart, UserPromptSubmit, PreToolUse or SessionEnd hook runs, the spinner says so with elapsed time, and Esc cancels a prompt waiting on a SessionStart hook
- Improved the spinner status during long thinking: it now reads “deep in thought” after 45s, and shows “picking the thought back up” while recovering from the output-token limit
- Improved dynamic workflows to pause when you hit your usage limit and continue automatically when it resets, instead of dropping the affected agents
- Improved Remote Control to leave fewer empty sessions on claude.ai when setup fails on a flaky network
- Improved the Claude in Chrome message in cloud sessions when the browser can’t be reached: it now says the computer may be asleep before it suggests an install
- Improved `claude mcp serve`: a running tool call now sends a progress update every 30 seconds, so clients show it is still running and idle timeouts don’t abort a long command that prints nothing
- Improved Foundry and Claude Platform on AWS sessions: an `alwaysLoad` MCP server that finishes connecting mid-conversation is usable on the next turn without a tool-search round trip
- Improved Markdown files published as artifacts: they now render as styled document pages (title header, document typography, syntax-highlighted code)
- Improved Artifact tool publish errors: a publish with no file now says to write the page to a file first, and an unsupported file type is reported before a missing favicon
- Improved the Artifact tool’s error when a page declares a capability its contract version lacks: it now lists every supported capability and notes when a newer contract version has it
- Improved artifact watching: a session can now watch up to 10 published artifacts at once for republishes made elsewhere, up from 5
- Improved PDF @-mentions to say “page count unknown” instead of a page count guessed from the file size when pdfinfo cannot count the pages
- Improved `/mobile` to show a single QR code for claude.ai/mobile, which opens the right app store for your phone
- Changed auto mode so that a skill’s or slash command’s inline `!` shell commands follow default-mode permission rules instead of the classifier; a command no rule decides runs as a reviewed tool call
- Changed auto mode so a subagent reports back to its caller through a dedicated hand-back call that the safety classifier reviews, instead of its last message being reviewed after the fact
- Changed Monitor watches to always have a deadline (at most 30 minutes; 10 in single-prompt `-p` runs) and notify Claude to re-arm, replacing the no-timeout `persistent` option
- Changed the IDE selection indicator in the prompt to a `[⧉ …]` pill that wraps with the text instead of squeezing multi-line prompts; delete it with Backspace to leave the selection out
- Changed the default dynamic workflow size to small on Pro plans and lowered the medium size guideline from 15 to 10 agents
- Changed Claude apps gateway, Bedrock, Vertex AI, and Foundry sessions so that they no longer refresh a leftover claude.ai login that the session does not use
- Updated the bundled `claude-api` skill to enable `eager_input_streaming` on streaming custom tools, and to start deliverable-shaped Managed Agents work with `user.define_outcome`
- \[VSCode\] Added an Attach Open File setting that, when turned off, stops the open file from being added to messages; selected text is still attached
- \[VSCode\] Fixed the Hooks and Permission rules dialogs reporting a save that landed as failed, and the Hooks dialog going blank under a plugin-only policy lock or showing color codes in save errors
- \[VSCode\] Fixed Hooks dialog saves: no duplicate hook on replace, a header name retyped in other capitals keeps its secret, and settings.local.json is gitignored before the save returns
- \[VSCode\] Fixed session history showing only the current session when the workspace is on a Windows mapped network drive or SUBST drive
- \[VSCode\] Fixed the session list’s Active filter hiding open idle sessions when Open is also checked in the filter menu
- \[VSCode\] Fixed a new chat switching back to the previous chat when the session list refreshed
- \[VSCode\] Fixed open tabs and the side bar keeping the old config folder until a window reload after `CLAUDE_CONFIG_DIR` changed in the `environmentVariables` setting
- \[VSCode\] Fixed console windows flashing on Windows when the extension runs background commands such as git, ripgrep, and the sign-in status check
- \[VSCode\] Fixed the prompt cache clock’s hover text appearing only after a delay, and the auto-compact icon showing the browser’s own tooltip beside its popup
- \[VSCode\] Improved the Hooks dialog: a save refused because of the settings file itself now opens a popup with an “Open settings file” button and the reason behind “Copy error”
- \[VSCode\] Changed the on state of toggle switches from Claude orange to the editor theme’s button color
- \[Claude Code on the web\] Fixed a cloud session sometimes taking about ten minutes to respond after its process exited while the session still looked live; sending a message now restarts it right away
- \[Claude Code on the web\] Changed the Routines page on claude.ai/code to a new layout with Yours and Templates tabs and two-column routine cards that show run status, and removed its calendar view
- \[Claude Code on the web\] Added a Custom network access option to the Cloud environments editor in admin settings, with the same allowed-domains list the environment dialog on claude.ai/code offers
- \[Claude Code on the web\] Improved the Cloud environments admin page: it shows the default environment for Claude Tag and Claude Code, with a link to change it, and marks the recommended kind to create
- \[Claude Tag\] Fixed Claude in a channel where it stays active losing its working context about once an hour when the conversation is mostly in threads; thread activity now keeps it from being reset
- \[Claude Tag\] Fixed a thread that asked Claude to watch a pull request no longer hearing about CI failures, comments and reviews after Claude was restarted in that thread
- \[Claude Tag\] Fixed deleting the first message of a thread Claude had already replied in not ending Claude’s work there; it now stops, as it did when a message with no replies was deleted
- \[Claude Tag\] Fixed Claude holding back a post because of an earlier instruction addressed to a different bot or assistant; only instructions addressed to Claude bind it, and it asks when unsure
- \[Claude Tag\] Fixed the reply-mode card Claude posts on joining a busy channel saying it “sees a lot of automated posts” when the channel is only chatty or large; the card now names the real reason
- \[Claude Tag\] Improved the Environment picker in Claude Tag admin settings: options are labeled Anthropic-hosted or self-hosted, with links to edit that environment or create one
- \[Code Review\] Fixed a pull request in a repository reviewed once per PR sometimes getting no review when a commit arrived while its review was waiting to start; it now reviews the requested commit
- \[Code Review\] Fixed Code Review occasionally posting the same findings two or three times when GitHub reported an error for a review it had in fact created
- \[Code Review\] Fixed follow-up reviews re-posting a security finding a person had already resolved when a later push moved the lines it was anchored to
- \[Code Review\] Fixed reopening a finished /ultrareview cloud session in the Claude app starting the whole review over again unprompted
- Windows: Fixed PowerShell commands failing with “Exit code 1” and no output when the session’s temp output path reaches 260 characters
[](#2-1-270)
2.1.270
September 12, 2026
- Fixed read-only git commands in Bash unexpectedly asking for permission after a session had been running for a while (regression in 2.1.269)
[](#2-1-269)
2.1.269
September 11, 2026
- Added `claude plugin eval`: run a plugin’s eval suite against Claude Code and get scored, reproducible results (JSON + HTML report); see `claude plugin eval --help`
- Added `/output-style [name]` to list and switch output styles, including over Remote Control and in cloud and other headless sessions
- Added a diff of the files a Bash command changed to the Bash tool result when the Bash tool handles file edits (setting `bashEditDiffEnabled`)
- Added `OTEL_METRICS_INCLUDE_REPOSITORY` to tag OpenTelemetry metrics and events with `vcs.*` repository attributes; commit events get `vcs.ref.head.*` with `OTEL_LOG_TOOL_DETAILS`
- Added `CLAUDE_CODE_GATEWAY_MODEL_DISCOVERY_TIMEOUT_MS` to extend the LLM gateway `/v1/models` discovery timeout (default 3s)
- Added a spinner tip suggesting `/focus` for a view with just your prompt, a one-line work summary, and the response
- Added `CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS` (1–256) to raise the Workflow tool’s per-run concurrent agent limit for inference-bound fan-outs
- Fixed the prompt cache being partially invalidated on the turn after a response was cut off at the output-token limit and automatically resumed
- Fixed a case where resuming a session after interrupting Claude mid-thought could change how earlier context was re-sent, hurting prompt-cache reuse
- Fixed F1/F2/F4 not working in kitty-protocol terminals and Delete in st, Alt+arrows acting as Escape in rxvt-unicode, and Shift+punctuation typing the unshifted key in WezTerm (regression in 2.1.247)
- Fixed remote and headless sessions reporting “waiting for your input” while background agents were still running (set `CLAUDE_CODE_BG_TASKS_REPORT_RUNNING=0` to restore the old behavior)
- Fixed the terminal’s replies to capability queries (`^[[?1;2c`) appearing as stray text at startup in some terminals
- Fixed rows at the top or bottom of the transcript going blank in fullscreen after resizing the terminal
- Fixed a deny or ask permission rule starting with `!` applying beyond the settings source that wrote it; such a rule now applies only within its own source, and a bare `!` negation is ignored
- Fixed the git status Claude is told after a compaction: it is now the current status, not the one from the start of the session
- Fixed synced plugin MCP servers not connecting when a remote session resumes
- Fixed resumed headless sessions losing a turn’s replies when the model was switched or a request was retried mid-turn
- Fixed terminal escape codes, line breaks and oversized text from a background task’s on-disk record reaching the task list and task notifications when work is resumed
- Fixed CMYK JPEG images failing to attach with “cannot decode”; they are now converted and resized like other JPEGs
- Fixed the managed settings approval dialog not naming the collector for a gRPC telemetry endpoint set without a scheme
- Fixed plugin `headersHelper` consent prompts showing a URL path that could be misread as a different host
- Fixed plugin errors showing `[redacted URL]` in place of a relative Windows path with a folder name that starts with `@`
- Fixed missing cursor in the permission-rule, auto-mode-rule, add-directory, session-rename and feedback-review text fields when the terminal’s native cursor is enabled
- Fixed repeated clicks on a `/fork` receipt, each under a second apart, never backgrounding the session right away while it waited for the current tool to finish
- Fixed plugin LSP servers that reject `shutdown` params (e.g. rust-analyzer) being left running at session end; `exit` is now sent even if `shutdown` fails
- Fixed the attribution reminder overriding a CLAUDE.md or memory rule against commit and pull request attribution; lines set by managed settings still apply
- Fixed prompt suggestions being dropped for text in Japanese, Chinese, Thai and other languages written without spaces between words
- Fixed synchronized output being assumed from the terminal’s name in GNOME Terminal and Konsole versions that do not support it
- Fixed `permission_denials` in `--output-format stream-json` results omitting Read, Edit and Write calls blocked by a path-scoped deny rule
- Fixed sessions run through the SDK or the desktop app showing an unknown status in other sessions’ agent list
- Fixed `/insights` failing on Bedrock, Vertex, Foundry, and gateway deployments whose account can’t reach the default Opus model by using the session model there instead
- Fixed organization policy limits not loading for the session when another Claude Code process refreshed the login at the same moment
- Fixed Claude Desktop sessions using Bedrock, Vertex, or a gateway not getting the contextual “what Claude needs” turn-end notification text
- Fixed MCP servers reconnecting when an updated config only changed the order of the server URL’s query parameters
- Fixed the prompt box’s top border splitting into extra lines when viewing a background agent whose name or description has line breaks or is wider than the terminal
- Fixed sessions getting permanently stuck on “Prompt is too long” when auto-compaction had no complete earlier exchange to summarize (mostly Agent SDK sessions with very large prompts)
- Fixed `/goal` runs silently stalling after API errors, network drops, or token limits: the goal now retries with backoff, or pauses and says why, including until a usage limit resets
- Fixed prompt cache misses in cloud sessions by waiting briefly for server configuration before the first request
- Fixed `/btw` answers that contained made-up tool calls and output: the side question is now told not to write them, and any that appear are flagged as not executed
- Fixed `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` re-running a turn that had failed with an API error over 6 hours earlier, or longer ago than `CLAUDE_CODE_RESUME_INTERRUPTED_TURN_MAX_AGE_MS` when set
- Fixed organization plugins enabled through managed settings not loading in headless sessions and on Claude Desktop (once Desktop bundles this CLI version); they load from the next session
- Fixed plugin archives extracted for a session being readable by other local users, extracted files keeping world-writable bits from the archive, and stale files surviving re-extraction
- Fixed `Edit()` deny rules and the write-path check not applying to the file a Bash `tee` command writes; a `Bash(tee:*)` allow rule no longer covers destinations outside the working directories
- Fixed stray characters like `22c`, or a terminal’s color or version reply, being typed into the prompt at startup over slow connections (ssh, browser terminals)
- Fixed the terminal’s block cursor showing under the interface in rxvt-unicode after leaving or re-entering fullscreen
- Fixed the cursor block staying visible after returning from an external editor in fullscreen mode on rxvt-unicode
- Fixed the interface being drawn twice after returning from an external editor (Ctrl+G) outside fullscreen mode
- Fixed the interface being drawn twice in Konsole after returning from an external editor
- Windows: Fixed PowerShell tool commands sent to the background stopping when Claude Code exits
- Improved the `/diff` panel to open fully rendered in one step instead of showing a loading state first
- Improved prompt suggestion filtering for Japanese, Chinese and Korean text: mixed-script and single-word suggestions are kept, and meta or evaluative text is dropped as it is for English
- Improved the Skill tool’s “Unknown skill” error to name the plugin skill’s full name when a bare name matches exactly one plugin skill
- Improved keyboard support over SSH and in unrecognized terminals: terminals that answer the kitty keyboard query (such as foot and Alacritty 0.16+) now get Shift+Enter and Ctrl+Shift shortcuts
- Improved responsiveness in long sessions: transcript updates no longer re-process the whole conversation to build the collapsed tool-use summaries
- Improved first-party sessions with telemetry disabled: an `alwaysLoad` MCP server that finishes connecting mid-conversation is usable on the next turn without a tool-search round trip
- Changed `/ultrareview --post` to post the PR comment directly when the findings arrive and print the comment link, instead of starting a second cloud session to post it
- Changed artifact database reads that save into the session scratchpad so they no longer stop for working-folder approval
- Changed skills synced from claude.ai in cloud sessions to be named `anthropic-skills:<name>`, matching Claude Desktop; the bare name still works when nothing else uses it
- \[VSCode\] Added an agent map: an “N agents” footer pill opens a map of the session’s sub-agents with per-agent cards, Stop agent, and read-only transcripts
- \[VSCode\] Added a Hooks dialog to the command menu for viewing hooks and adding, editing, or removing them in user, project, and local settings; managed, plugin, and session hooks stay read-only
- \[VSCode\] Added live progress rows for running subagents under the tool-call groups in Focus view
- \[VSCode\] Added a Permission rules dialog that lists permission rules and adds or removes them in user, project, and local settings; startup-option, session-only, and managed rules stay read-only
- \[VSCode\] Added a Cancel button to the Switch account screen that returns to your session as the current account
- \[VSCode\] Fixed Focus view showing a turn started by a delivered plain-text prompt, such as a scheduled task’s, as part of the previous turn
- \[VSCode\] Fixed the footer’s prompt cache clock hiding its minutes when the panel is narrow
- \[VSCode\] Fixed the session list keeping sessions from the default folder when `CLAUDE_CONFIG_DIR` is set in a settings file or the `environmentVariables` setting
- \[VSCode\] Fixed a plan preview that finished loading late sometimes hiding its comment box or showing an older plan
- \[VSCode\] Fixed a plan preview accepting comments that went nowhere after its Claude tab closed
- \[VSCode\] Fixed the prompt cache clock and reopen notice for a session compacted after its last reply and then closed, which now reads as cold when reopened
- \[VSCode\] Fixed a session renamed in the extension while Remote Control is on keeping its old name on claude.ai/code
- \[VSCode\] Fixed the “Enable Remote Control for all sessions” toggle keeping its last position after the setting was reset to default from a terminal
- \[VSCode\] Fixed restored Claude tabs not counting as open in the session list after a window reload until clicked, and their row opening a second tab
- \[VSCode\] Fixed Switch account making a tab forget its dismissed usage-limit warnings when you sign back in as the same account
- \[VSCode\] Fixed a session rename being replaced by the generated name after a window reload when the session was renamed during a long turn
- \[VSCode\] Fixed the sidebar usage meter keeping a stale per-model weekly limit row after the account loses that limit
- \[VSCode\] Fixed a rare case where an @-mention sent with the keyboard shortcut while a new chat view was still starting could be inserted into the input long after the keystroke
- \[VSCode\] Fixed the session list jumping down when the Account & usage header appeared a moment after opening the Claude side bar
- \[VSCode\] Improved documents and messages written for someone other than the user: Claude now writes them for that audience and names it at the top of its reply
- \[VSCode\] Improved screen reader and keyboard accessibility in the slash-command menu, @-mention menu, output-style picker, Send/Stop button, permission and question cards, and onboarding checklist
- \[VSCode\] Changed the current-file chip in the message box: an X now removes it, replacing the Hide toggle
- \[VSCode\] Removed the Claude Code items from a session tab’s right-click menu and the editor title bar’s ”…” menu; they could not act on the tab the menu was opened on
- \[Claude Code on the web\] Added taking back a queued message in a cloud session before Claude reads it: remove it from the queue, or press Esc or Up, and the text returns to the message box
- \[Claude Code on the web\] Fixed `/model default` in a cloud session leaving every later message failing in organizations that restrict which models Claude Code can use
- \[Claude Code on the web\] Fixed one-off scheduled routines occasionally running a second time after a transient server error
- \[Claude Code on the web\] Fixed routine runs that use subagents sometimes being treated as finished too early, which could skip the retry after a real failure or start a duplicate run
- \[Claude Code on the web\] Fixed file links in cloud session transcripts opening a GitHub 404 when Claude was working from a subfolder of the repository
- \[Claude Code on the web\] Changed the Cloud environments admin page to list every environment instead of capping each table at five rows behind a Show more control that could be unreachable
- \[Claude Code on the web\] Changed claude.ai/code for Free-plan users to open the plans page with a path to upgrade, instead of a “Disabled by org admin” page with no way forward
- \[Claude Tag\] Added a confirmation dialog before Connect all or Disconnect on a GitHub installation in admin settings, to guard against accidental organization-wide changes
- \[Claude Tag\] Fixed threads occasionally going silent after a failed turn because the failure notice was dropped when Slack briefly rate-limited it; the notice is now retried
- \[Claude Tag\] Fixed Claude accepting a switch to a model your organization hasn’t enabled and then quietly answering with a fallback model; it now declines and says an admin can enable it
- \[Claude Tag\] Fixed a table posting as raw pipe text when Claude attached files to the same message; the table now posts as a normal reply and the files follow with a plain caption
- \[Claude Tag\] Fixed `@Claude !restart` at the top level of a channel where Claude isn’t active starting an unrelated conversation; it now privately says there is nothing to restart
- \[Claude Tag\] Fixed plugin rows in Slack access settings showing an unlabeled raw ID with no way to turn the plugin off; they now show its name and link to the bundle that manages it
- \[Claude Tag\] Fixed the shared-session banner and Share dialog on sessions started from Slack claiming the whole organization could open the link; they now name the Slack channel’s audience
- \[Claude Tag\] Improved load time of the admin settings page and its Slack channel picker, most noticeably for organizations with many channels or several connected workspaces
- \[Claude Tag\] Improved scheduled routines in Slack channels: a routine run can now reply in an existing thread instead of always posting a new top-level channel message
- \[Claude Tag\] Improved the timestamp on Claude’s live progress checklists to show each reader’s local time and how long ago it was updated, instead of a fixed UTC time
[](#2-1-268)
2.1.268
September 10, 2026
- Added to the Claude apps gateway: with `pricing:` set in `gateway.yaml`, signed-in Claude Code clients receive the same rates through managed settings, so `/cost` and telemetry match the spend meter
- Added a startup warning for gateways when `access_control.allow_cidrs` is empty, and a one-time warning the first time a request arrives from a public address
- Added the `gatewayInternalNetworks` managed setting, letting administrators allow `/login` to a Claude apps gateway on their organization’s own public IPv4 block
- Added `claude self-hosted-runner --remove-session-state` (default off): delete each session’s per-session directories under `<base-dir>/_sessions/` when the session ends
- Added `configDirectory` to the output of `claude auth status --json`
- Added `--json` to `claude plugin install`, `uninstall`, `update`, `enable` and `disable`, and `errorDetails`/`noteDetails` to each row of `claude plugin list --json`
- Added browser-tab icons for published artifacts, chosen by Claude to match each page
- Fixed every turn failing with HTTP 400 on third-party Anthropic-compatible endpoints (`ANTHROPIC_BASE_URL`) since 2.1.265: a regex in the Artifact tool’s input schema that those endpoints reject
- Fixed WebFetch hanging indefinitely on a server that keeps the response open without finishing; a fetch now fails after 300 seconds. Set `CLAUDE_CODE_WEBFETCH_DEADLINE_MS` to override the deadline (0 turns it off)
- Fixed a respawned in-process teammate picking up tools or a system prompt from a same-named agent file in a folder you have not trusted
- Fixed sustained high CPU usage: a busy loop in long-running idle sessions no longer pins a CPU core, and rapid terminal focus reports during a session recap no longer keep the CPU high
- Fixed Claude sometimes replying “your message came through empty” after an MCP tool call
- Fixed deny and ask permission rules on symlinked directories (`/etc`, `/tmp`, `/var` on macOS; `/bin` on Linux) not applying when a path was given by its real location, and Bash commands ignoring deny rules written on a symlinked path spelling
- Fixed a case where a Read or Edit deny rule did not apply when an `env -C`, `eval` or similar command the permission checker cannot analyze was on the same line
- Fixed plugin and marketplace errors showing a token or password from a git source URL
- Fixed `/mcp` and `/plugin` server details, `claude mcp list`/`get`, and MCP login errors showing secrets resolved from `${VAR}` placeholders in MCP configs
- Fixed prompt caching and extended thinking breaking mid-session for SDK sessions using `excludeDynamicSections`: the first message is no longer re-rendered each request
- Fixed entitled users being told a model is restricted after restart or in the Desktop Code tab when a cached model-access denial was stale
- Fixed a running session silently switching to the organization’s default model when another Claude Code process refreshed a stale model-access entry
- Fixed long-context 429s on Fable models showing the usage-credits consent prompt instead of the 1M-context message on Pro and Team plans
- Fixed workload identity federation via a profile (as claude-code-action configures it): processes sharing the profile could fail mid-run with `401 … jti reused`
- Fixed MCP server OAuth sign-in failing with “No available ports for OAuth redirect” when the local callback port range can’t be bound
- Fixed the conversation summary produced by `/compact` and auto-compact mangling text that contained `$` sequences
- Fixed resuming a conversation that ended with `/compact`: its restored-file notes now load in the same order on every resume
- Fixed SDK prompt suggestions, side questions and `/rename` sending the conversation from before a compaction
- Fixed `@` file and `/` command suggestions not appearing after recalling a previous prompt with the up arrow and editing it
- Fixed `claude agents`: pressing ← again at a natural pace to go back to the agent list no longer gets ignored until you pause for over a second
- Fixed `claude agents` session delete getting stuck when a worktree can’t be removed: the message names the cause and next step, and for a git worktree ctrl+x again deletes the directory anyway
- Fixed background agent and workflow rows in the agents panel expanding to many lines when their text contained line breaks
- Fixed Claude in Slack sessions losing their Slack tools when org managed settings set an MCP allowlist
- Fixed Claude in Chrome asking to allow the host “https” when a navigation URL had a scheme but a host that could not be parsed
- Fixed the spinner wrapping onto several lines when the current task’s label is long; the label and the “Next:” task line now stay within one terminal row
- Fixed the `/bug` and `/feedback` description field showing no cursor when the terminal’s native cursor is enabled
- Fixed Remote Control sessions served by `claude remote-control` showing a generated name instead of their session title in `ListAgents`
- Fixed `claude plugin validate` rejecting plugin paths whose directory name begins with two dots, which the plugin loader accepts
- Fixed plugins silently skipping a default monitors file or root SKILL.md that could not be checked
- Fixed WebFetch’s error for localhost and other dotless hostnames to explain why the URL is refused and suggest curl
- Fixed PermissionRequest hooks not firing in `--print` mode
- Fixed policy-helper warnings not printing on headless (`-p`) runs
- Fixed `/resume` listing a `/fork` background session under its parent’s name instead of its own `⑂` fork name
- Fixed `/remote-control` and other claude.ai-gated commands to suggest `/login` when signed out instead of showing a Claude for Enterprise migration message
- Fixed `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` not extending SessionEnd hooks that have no per-hook `timeout` (they were still cancelled after 1.5 seconds)
- Fixed `/autofix-pr` and other cloud-session commands saying to retry or install the Claude GitHub App when no GitHub account is connected; they now point to `/web-setup` or the web connect page
- Fixed cloud-session commands such as `/teleport` and `/remote-env` to explain when an organization policy turns them off, instead of answering “Unknown command”
- Fixed Bash sandbox instructions over-stating confinement: no unenforced path lists when filesystem isolation is off, and strict mode no longer claims commands can never run unsandboxed
- Improved fullscreen mode: adding or removing a prompt line (Shift+Enter) now repaints as fast as typing a character instead of re-rendering the visible transcript
- Improved `--continue` / `--resume`: the conversation appears immediately instead of waiting for SessionStart hooks, and the first message no longer re-reads the whole transcript
- Improved responsiveness during tool-heavy turns by no longer redrawing the transcript for a hidden per-tool-batch reminder
- Improved startup time in projects with `.claude/workflows/` scripts: listing them no longer parses each script
- Improved auto mode denials: the message Claude receives now names the rule that blocked the action and asks Claude to try a safer method and finish unrelated work before stopping to ask you
- Improved Claude in Chrome: long page reads now stay inline instead of being saved to a file and read back
- Improved the MEMORY.md truncation warning to say how many lines were cut and where the cut starts
- Improved the terminal permission prompt for artifacts: it now leads with the ask’s question
- Improved the prompt footer: an editor or `/diff` selection now shows inside the prompt input, and fullscreen mode shows Remote Control status in the header instead of the footer
- Improved the “Usage credits required for 1M context” message to say that usage credits turned on mid-session take effect after restarting Claude Code
- Improved `/plugin`: installing, enabling or disabling a plugin now takes effect when you close the menu; `/reload-plugins` is no longer needed afterwards
- Changed the system prompt on Bedrock, Vertex and Foundry to deliver environment, model and settings details as attachments, matching first-party sessions
- Changed Bedrock, Vertex and Foundry sessions to keep the tool list byte-stable across a conversation (late-connecting tools load deferred instead of rewriting it), matching first-party sessions
- Changed the task-tracking tools (TaskCreate/Get/Update/List, TodoWrite) to be offered only on Claude 3.x, Opus 4.0–4.7, Sonnet 4.0–4.6, Haiku 4.5; set `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` elsewhere
- Changed the artifact data-edit permission prompt in the terminal to a card that shows the document count and who can open the artifact
- Changed local Cowork sessions set to skip all approvals: the Artifact tool now refuses a local file outside the session’s folders, or behind a symlink, instead of reading it without asking
- Changed plain `WebFetch` deny and ask rules to no longer apply to Artifact tool reads and updates; use an `Artifact` rule (or `WebFetch(domain:claude.ai)`) to block or gate them
- Changed the “N MCP servers need authentication” startup notice to announce each server once instead of at every launch
- \[VSCode\] Fixed the session list, settings toggles, and chat tabs when `CLAUDE_CONFIG_DIR` is set in a settings file or the `environmentVariables` setting
- \[VSCode\] Fixed the model pill, model picker and command menu going blank in open tabs for a few seconds after a login, logout or account switch
- \[VSCode\] Fixed Auto disappearing from the mode picker in new-tab or just-reloaded conversations when a project or local setting overrides the model named in `~/.claude/settings.json`
- \[VSCode\] Fixed session names reverting to the last prompt after a window reload when a SessionStart hook is configured
- \[VSCode\] Fixed the footer’s model pill and Remote Control pill waiting for the new tab’s Claude process to start when another tab in the window is already up
- \[VSCode\] Fixed a second Claude process running through its full startup when a session tab’s launch arrived more than half a second after its config read
- \[VSCode\] Fixed resuming a session from the session list ignoring `claudeCode.preferredLocation: "sidebar"` (it always opened a panel), and programmatic opens resetting that setting to “panel”
- \[VSCode\] Fixed Windows issues: the WSL install prompt no longer appears on machines without WSL installed, and IDE diagnostics are now returned correctly for Windows files when WSL is installed
- \[VSCode\] Fixed the custom style builder saving a User level style in a folder the CLI does not read when `CLAUDE_CONFIG_DIR` is set through settings
- \[VSCode\] Added Left and Right arrow keys to change where an always-allow permission rule is saved, for keyboard and screen reader users
- \[VSCode\] Added a “Claude Code: Focus last message” command that moves keyboard focus to the newest message in the conversation, for keyboard and screen reader users
- \[VSCode\] Changed the Manage plugins dialog to apply installs, enables, disables and uninstalls to open sessions without a restart
- \[VSCode\] Changed some artifact permission prompts to omit the “don’t ask again” choice, matching the terminal
- \[Claude Code on the web\] Fixed cloud sessions running longer than about six hours silently losing files saved to persisted session folders; saves now persist for up to a day
- \[Claude Code on the web\] Fixed “Invalid effort level” errors when a routine resumes a session, or a session starts with no set effort, in orgs where an admin caps a model’s effort
- \[Claude Code on the web\] Improved routine creation from a conversation: when the new routine has no connectors, Claude now says so and how to add them instead of only confirming it
- \[Claude Tag\] Fixed the admin settings page hanging on a loading skeleton or going blank after a transient load failure; a section that fails to load now shows a Retry button
- \[Claude Tag\] Added a link from a Slack channel’s configure page back to the organization’s Claude in Slack admin settings
- \[Claude Tag\] Fixed a Slack Enterprise Grid channel losing its Claude settings (repository, environment, access) after a Slack admin moved it to another workspace
- \[Claude Tag\] Improved how Claude explains a blocked action: it now says whether a permission check, its own decision to confirm first, or missing access stopped it
- \[Claude Tag\] Improved reply speed: Claude now runs several read-only lookups (searching Slack, reading a thread, finding people) at once instead of one after another
- \[Claude Tag\] Improved formatting of comparisons: sentence-length comparisons now come as lists instead of wide tables that scroll sideways, and long table cells wrap
- \[Claude Tag\] Fixed `@Claude !restart` in a thread with its own session sometimes also posting a contradictory “this thread is handled by the channel session” notice
- \[Claude Tag\] Improved the message shown when your Claude account is in a different organization than the Slack workspace: it now explains how to connect the workspace to your org
- \[Claude Tag\] Fixed Markdown links whose URL is wrapped in angle brackets showing as literal bracket text in Slack instead of a clickable link
- \[Claude Tag\] Fixed a workspace guest’s top-level @mention in a channel where guests may use Claude sometimes getting a “your Slack account isn’t connected” reply instead of an answer
- \[Claude Tag\] Fixed a channel’s long-running session being replaced with a fresh one mid-conversation; the scheduled refresh now waits until the channel and its threads are quiet
- \[Claude Tag\] Fixed channel-settings cards clicked more than once telling the proposing session the change was refused after it had already applied; the outcome is now sent once
- \[Claude Tag\] Changed memory in public channels: each channel now keeps its own notes, and Claude no longer recalls notes it saved in other public channels; workspace notes stay shared
- \[Code Review\] Added a note under the still-open findings list in follow-up reviews: resolving a finding’s thread, not just replying to it, stops later reviews from counting it as open
- \[Code Review\] Fixed reviews sometimes ending as incomplete when one of the agents verifying a finding failed midway; the review now replaces that agent and reaches a verdict
- \[Code Review\] Fixed a push-triggered review that was queued behind a running review still posting after the pull request had been converted to draft
- \[Code Review\] Fixed reviews ignoring a directory’s CLAUDE.md conventions when the PR edited a root file (e.g. README.md) that only shares a name with a file that CLAUDE.md lists
[](#2-1-267)
2.1.267
September 9, 2026
- Added `maxEffortLevel` setting (top-level or per model under `modelSettings`): caps the effort level on every provider, including Bedrock, Vertex and Foundry; users can still pick a lower level
- Added `--system-prompt-snapshot off` to render the system prompt fresh on every request instead of reusing the conversation’s recorded prompt (for iterating on prompt text)
- Fixed Cowork scheduled tasks in the cloud failing at startup for organizations whose managed settings require sandboxing
- Fixed `/context` and other local command output rendering blank on mobile clients
- Fixed shift+enter and option+backspace not working after reconnecting to a tmux or ssh session inside an agent view
- Fixed the dim last-prompt header not appearing at the top of the conversation when scrolling up in fullscreen mode
- Fixed Workflow `agent()` calls with large output schemas being refused in auto mode instead of being checked by the safety classifier
- Fixed a case where a marketplace entry path containing a backslash could bypass the containment check for fetched marketplaces on macOS and Linux
- Fixed expired AWS or Google Cloud credentials under a host app such as Claude Desktop retrying ten times with a generic “request failed” before the re-authenticate error appeared
- Fixed resuming a session after `/compact` or another slash command ran via `-p --resume`: a spurious “Continue from where you left off.” turn is no longer inserted
- Fixed resuming a large session (transcript over 5 MB): parallel tool calls and their hook output are no longer dropped from the reloaded conversation
- Fixed managed `allowedHttpHookUrls`, `httpHookAllowedEnvVars` and `allowedChannelPlugins` to admit nothing, not everything, when unreadable
- Fixed `/login` on machines whose managed settings require Claude apps gateway sign-in: Esc now closes the dialog instead of doing nothing
- Fixed artifact publishes cut off by a dropped connection mid-upload: they now retry once when Claude Code can tell the upload never completed, instead of reporting an unknown outcome
- Fixed `effort:` frontmatter on custom commands, skills, and subagents being ignored on models whose default effort is still pinned (Opus 4.7, Opus 4.8, Fable 5)
- Fixed artifact publish failing with an unhelpful error when the page file isn’t valid UTF-8 or contains a replacement character (U+FFFD); the error now names the line and column to fix
- Fixed `claude agents` `@` directory menu not listing repositories created after the session started
- Fixed Remote Control clients that join a Claude Desktop or VS Code session showing a stale permission mode until it was changed again
- Fixed `claude remote-control` exiting and dropping every attached session when its server credential expires (about 30 days after start); the host now re-registers and keeps going
- Fixed the usage-limit warning flickering on and off during a session when requests for different models or modes report different limit windows
- Fixed earlier reasoning being dropped when an MCP server re-sends, or a built-in tool re-renders, a tool the model already loaded
- Fixed a tool that disappears mid-conversation, from a disconnected MCP server or an upgrade, rewriting the tool list and discarding earlier thinking
- Fixed a background worker forked from a conversation adding EnterWorktree to the conversation’s tool block mid-session, which broke prompt-cache reuse
- Fixed mid-session MCP and plugin tools being added to the tool list in sessions without ToolSearch, which broke prompt-cache reuse; supported models now receive them as deferred definitions
- Fixed switching models with /model re-sending every tool definition (a prompt-cache miss); commit and PR attribution text now arrives as a conversation note that updates on model changes
- Fixed resumed sessions rewriting the inline tool set when an MCP connector reconnects at a different moment than before
- Fixed resumed sessions re-rendering tool descriptions instead of replaying the recorded ones when the first turn ran a tool
- Fixed prompt-cache misses and dropped extended thinking when a claude.ai connector’s tools change between a session and its resume
- Fixed resumed sessions rewriting earlier MCP tool announcements (and dropping extended thinking) before their connectors reconnect
- Fixed a prompt-cache break when a print-mode (`-p`) conversation is resumed interactively: the system prompt prefix no longer changes
- Improved the `/diff` panel: it no longer flashes “0 files changed” and a spinner before settling, and its empty state is centered in the panel
- Improved the Bash tool’s description guidance so Claude describes what a command does in plain words instead of echoing the command
- Improved sandbox guidance so Claude suggests `/copy` when clipboard commands such as `pbcopy` fail inside the sandbox
- Improved `--resume` first-render time for sessions with many Bash tool calls
- Improved prompt input responsiveness: keystrokes no longer occasionally wait a frame behind spinner or streaming repaints
- Improved prompt-cache stability: subagents and sessions started with `--system-prompt` or `--append-system-prompt` now record the system prompt and tool definitions once instead of re-rendering them
- Improved Artifact tool publish errors: when a publish is refused, the message now says why and what to do about it
- Self-hosted runner: Changed `--use-anthropic-git-proxy` to be reported to the server at registration and to print a warning for each session that still clones through the legacy git proxy
- Gateway: Changed `forward_user_identity` upstreams to return a 429 as-is to a developer whose email was forwarded, instead of failing over to the next upstream, so the proxy’s per-user limits hold
- \[VSCode\] Fixed the extension host hanging at 100% CPU when forking, editing an earlier message, or rewinding in a conversation whose saved transcript contains a cyclic parent link
- \[VSCode\] Fixed pasting a screenshot on WSL2/WSLg inserting raw image bytes into the chat input; the image is now attached when the clipboard provides it, otherwise the paste is ignored
- \[VSCode\] Fixed chat diff blocks always rendering with a dark editor theme; they now follow the active VS Code color theme, including high contrast
- \[VSCode\] Fixed mixed right-to-left and English text rendering in the wrong order while typing in the message input
- \[VSCode\] Fixed accepting an edit in the diff view on a file with Windows (CRLF) line endings failing with “String not found in file”
- \[VSCode\] Fixed @-mentions dropping files whose paths contain spaces
- \[VSCode\] Fixed the sessions list view failing to load in windows connected over Remote-SSH when the workspace folder exists only on the remote host
- \[VSCode\] Fixed runaway ripgrep processes when viewing files in large or symlink-heavy workspaces
- \[Claude Code on the web\] Fixed GitHub Enterprise Server sessions showing your GitHub account as disconnected once its token expired; PR and issue operations now refresh it automatically
- \[Claude Code on the web\] Fixed `gh` and GitHub API calls failing in organizations without the Claude GitHub App; they now use your connected GitHub account and say so when none is connected
- \[Claude Tag\] Added a “Use a custom connector” link to the preset connection forms in Claude Tag admin settings, so you can switch to a custom connection without starting over
- \[Claude Tag\] Fixed Claude replying “The API rejected the request as invalid” when the organization has run out of usage credits; the reply now says so and explains how to add more
- \[Claude Tag\] Fixed thread requests to edit or delete a message Claude posted at the channel’s top level being answered with a correction instead of reaching the session that posted it
- \[Claude Tag\] Fixed **Connect** on Tool access requests under Admin settings \> Review requests failing with “Authorization failed” or showing the requested access bundle as deleted
[](#2-1-266)
2.1.266
September 8, 2026
- Fixed a 2.1.265 regression affecting LLM-gateway and proxy setups: the undocumented `CLAUDE_CODE_USE_GATEWAY` environment variable, previously ignored unless `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN` were both set, began forcing Cloud-gateway sign-in on its own in 2.1.265, so configurations that set it alongside an API key, `apiKeyHelper`, or custom auth headers failed every request with “Not signed in to the Cloud gateway”. The variable on its own is ignored again; no configuration change is needed
[](#2-1-265)
2.1.265
September 8, 2026
- Added `user.email` and `user.groups` to the telemetry Claude Desktop and Cowork send through a Claude apps gateway, matching terminal sessions
- Added support for pointing `--plugin-dir` at a folder of plugins: each child folder with a manifest loads, and children added or removed while running are picked up
- Added a 1 GB cap on tool results saved to disk; the in-conversation preview says when a saved file was truncated
- Fixed resuming a foreground-spawned subagent changing its tool list and system prompt prefix, which broke prompt-cache reuse for that agent
- Fixed agent teammates and resumed subagents moving SubagentStart hook context and preloaded skills out of the prompt prefix on later turns, which broke prompt-cache reuse
- Fixed resume after the previous process died while a tool was running: the last prompt is no longer rewritten, and the interrupted tool call is kept and marked interrupted
- Fixed `/model opusplan[1m]` being rejected with “Model not found”
- Fixed syntax-highlighted code in permission prompts and messages sometimes omitting a character after a Ruby `?`, Erlang `$`, or Perl `$` sigil
- Fixed the fullscreen transcript jumping by one row whenever the slash-command or @-file suggestion list opened or closed
- Fixed a plugin path containing a backslash bypassing the symlink containment check on macOS and Linux
- Fixed plugin directories whose names begin with two dots being wrongly refused as outside the plugin root
- Fixed VS Code and SDK sessions occasionally requiring re-login when a session was closed while refreshing its token
- Fixed Remote Control sessions sending the end-of-turn signal before the reply’s last message, which could show a reply as finished in the Claude app before its last part arrived
- Fixed background (`--bg`) sessions occasionally being retired mid-turn when a message arrived just before the idle timeout
- Fixed Claude Code’s own git status and diff probes running clean filters configured by a nested repository inside the working tree
- Fixed the advisor tool and its instructions being re-decided per request from the request’s model; the decision is now made once and announced in the conversation when it changes
- Fixed artifact publish accepting connector tool names the connector doesn’t expose; the publish is now refused when none of the declared tools exist, and warned when only some don’t
- Fixed `/add-dir <subdirectory>` refusing to load a subdirectory’s agents when managed settings lock only skills to plugins, and promising agents when only agents are locked
- Fixed two-key keyboard shortcuts cancelling silently when the second key arrived more than a second later, as happens inside tmux; they now wait 3 seconds and show a notice when they time out
- Fixed forked skills (`context: fork`) not streaming their kickoff prompt and, with `--forward-subagent-text`, their text turns as progress events in stream-json
- Fixed a plugin’s default component folder that the OS cannot check, such as a symlink loop, being silently skipped; it is now reported in `/plugin` with the error code
- Fixed the Claude apps gateway’s OTLP telemetry relay pausing all forwarding to a collector for 30 seconds after it rejected a few payloads as malformed or too large
- Fixed `/plugin` Discover/Browse and `claude plugin list --json --available` showing no description or display name for marketplace plugins whose metadata lives only in their `plugin.json`
- Fixed `/login` showing “no gateway URL is configured” when re-run in a session that signed in to a Claude apps gateway set by managed settings
- Fixed `/model` claiming a model was “saved as your default” when the settings file couldn’t be written; it now says the save failed and why
- Fixed `/clear` from Remote Control waiting on SessionStart hooks and on open terminal dialogs before completing
- Fixed the `/config` dialog changing height when switching between its tabs
- Fixed resuming a workflow run after its container restarted; a resume whose run journal is missing now fails with a clear error instead of rerunning every agent
- Fixed the `claude-api` skill’s error-code reference: model access failures return 404 and unavailable beta headers return 400, not 403
- Fixed non-interactive sessions (`-p` with stream-json input, Agent SDK, cloud sessions) resetting the shell working directory at each new user message; a `cd` now persists across turns
- Fixed MCP servers configured as `http` that only speak the legacy HTTP+SSE transport never connecting; Claude Code now falls back to SSE as the MCP spec describes
- Fixed some claude.ai connectors in cloud sessions showing as needing authentication even though they are connected in claude.ai (servers that answer an unsupported request with HTTP 401)
- Fixed remote sessions keeping their sandbox container alive while a connector approval or sign-in link waits for you
- Fixed resumed sessions showing long model-facing recovery instructions in “background task didn’t finish” notices instead of a short status line
- Windows: Fixed Read, Write and Edit refusing every file (“symlink resolution changed after permission was checked”) when running inside an AppContainer or restricted-token sandbox
- Improved `--worktree` startup on large repositories: the new worktree is now checked out in parallel (git 2.32+)
- Improved `/workflows` agent detail: tool calls are marked running, failed or done, the subagent’s task list is shown when it has one, and Enter unfolds the listed calls with their inputs and results
- Improved slash commands typed mid-prompt: matches now show in a list (Tab opens it outside fullscreen) instead of a single suggestion, and a plugin skill is now found by its bare name
- Improved remote MCP servers that need sign-in: Claude Code no longer registers an OAuth client with them until you actually authenticate
- Improved the time to resume long sessions that read many files
- Improved the error shown when an image over the size limits cannot be decoded: it now names the cause and how to fix it instead of only citing the limit
- Improved the Artifact tool’s read of an artifact someone else wrote: the summary now treats the page as untrusted content and flags embedded instructions rather than relaying them
- Updated the `.claude` folder permission option to say what it actually allows: editing files in the project’s `.claude` folder (or `~/.claude`) for the session
- Changed machines with `forceLoginGatewayUrl` in managed settings to be Claude apps gateway sessions from startup, like `forceLoginMethod: "gateway"`; a leftover claude.ai login or API key is not used
- Changed image processing to use the runtime’s built-in image support; the CLI no longer extracts a native image module to the temp directory
- Changed plugin display metadata to prefer the marketplace entry over `plugin.json` on the Installed tab and `claude plugin details`, filling gaps from `plugin.json`
- Changed Claude apps gateway sessions to export OpenTelemetry directly to a collector the gateway’s managed settings name in `OTEL_EXPORTER_OTLP_ENDPOINT`, instead of through the gateway’s relay; sessions without a named collector still use the relay
- \[VSCode\] Added automatic archiving of sessions inactive for a set period (new “Archive inactive sessions” setting, default 14 days)
- \[VSCode\] Fixed the sidebar chat coming back blank after Reload Window or a restart when the conversation had been open for more than 10 minutes
- \[VSCode\] Fixed the timeline dot sitting below the text on the “Remote Control is active” message
[](#2-1-263)
2.1.263
September 6, 2026
- Bug fixes and reliability improvements
[](#2-1-261)
2.1.261
September 4, 2026
- Added an “Organization policy” line to `/status` and `claude doctor` that says why your organization’s policy could not be loaded, such as a proxy not passing the endpoint through
- Added `bashOutputMaxChars` and `taskOutputMaxChars` settings to raise how much command and background-task output Claude receives inline before it is saved to a file, up to 128K characters
- Added `--append-subagent-system-prompt-file` to read the subagent system prompt from a file, for prompts too large to pass on the command line
- Added `/skill-doctor` to show which loaded skills go unused and what they cost in context, so you can prune them
- Fixed typed or pasted characters occasionally landing out of order or being dropped during fast input or key repeat
- Fixed `/add-dir <subdirectory>` printing a false “couldn’t be resolved” error when the working directory is on a `/net` automount
- Fixed the Bedrock setup wizard hanging when AWS or an AWS credential helper never responds (it now times out with a clear error), and its model checks failing behind a TLS-inspecting proxy
- Fixed cloud sessions discarding a plugin synced from claude.ai when managed settings force-enable it in `enabledPlugins`, then falling back to a marketplace clone that could fail
- Fixed being unable to delete the character immediately before an inline `[Image #N]` chip in the prompt input
- Fixed resuming a session losing hook output and other context around parallel tool calls, which changed the resumed request
- Fixed Remote Control showing a stale permission mode when a phone, browser, or claude.ai app attaches to a terminal session or after the mode changes in the terminal
- Fixed Remote Control sessions showing as still working (stuck spinner and Stop button) after stopping a turn from a connected phone or browser, or after a local slash command like `/clear`
- Fixed SDK and cloud sessions ignoring a Stop or interrupt sent just after the first prompt, before the turn had started; the turn now stops instead of running to completion
- Fixed Remote Control uploading a session pulled with `/teleport` into the connected session, which appeared appended to the original on phone and web
- Fixed Remote Control’s inbound event stream failing behind TLS-inspecting corporate proxies on native Windows
- Fixed Remote Control sessions showing the default effort level on claude.ai when the effort comes from settings
- Fixed `gcpAuthRefresh` opening a browser at startup when the Google credential check was slow, even though the credential was still valid
- Fixed claude.ai connectors staying absent for the whole session when the startup connector fetch timed out — the CLI now retries in the background
- Fixed sustained high CPU usage when a background agent could not be resumed and its wake-up was retried in a tight loop
- Fixed feature flags gated to a newer version occasionally applying to an older Claude Code version running on the same machine
- Fixed `/usage` and the VS Code usage panel dropping a model-specific weekly limit row when the usage endpoint is rate limited or when opened right after startup
- Fixed `claude -p --resume <file>` adopting a malformed session ID recorded in the transcript; it now resumes under a fresh session ID instead
- Fixed the terminal progress indicator (iTerm2, Ghostty, ConEmu) showing the session as finished while a background workflow or agent was still running
- Fixed a rare layout glitch where a box could render with the wrong height after its container switched between row and column direction
- Fixed Claude apps gateway client IP when a trusted proxy appends a port to `X-Forwarded-For`; with an access list set, an unreadable entry now gets 403
- Fixed Claude apps gateway telling Claude Desktop to export OpenTelemetry as JSON even when the terminal CLI uses protobuf, so protobuf-only collectors rejected Desktop’s data
- Fixed Desktop and web showing a session as busy while it only watches an artifact for updates
- Fixed Claude in Chrome `file_upload` failing with “paths: expected array, received undefined” in local Cowork sessions run from the Claude Desktop app
- Fixed `SendMessage` to an offline Remote Control session on another machine reading as delivered; the result now says delivery is queued until that machine reconnects
- Fixed plugin install hints from CLIs run in background Bash commands: they are now detected, and the raw `<claude-code-hint>` tag no longer leaks into the conversation
- Fixed in-process agent-team teammates re-sending their first-turn tool and skill announcements on the second turn, which changed the request prefix and missed the prompt cache
- Improved the `/model` picker and the VS Code model pill to show a model’s name instead of its raw Bedrock, Vertex AI, or LLM gateway ID when Claude Code recognizes it
- Improved startup on Google Vertex AI when `GOOGLE_APPLICATION_CREDENTIALS` is set: API client creation no longer re-runs Google Cloud project discovery or spawns extra `gcloud` processes
- Improved streaming performance: already-rendered blocks are no longer re-checked by layout on each update
- Improved the dangerous-`rm` safety prompt to also catch `rm -rf` on positional parameters and inside double-quoted `sh -c` scripts
- Improved handling when the API sends no response headers: the retry now waits up to `API_TIMEOUT_MS` (10 minutes by default) instead of another 3 minutes, and the messages say what to change
- Changed a Claude apps gateway 403 on the managed settings load (at startup or after `/login`) to say Claude Code may not be enabled for the organization, instead of advising a new sign-in
- Changed machines whose managed settings pin `forceLoginMethod: "gateway"` to ignore a leftover API key or claude.ai login and ask for `/login`; Bedrock, Vertex AI, and Foundry sessions are unaffected
- Changed auto mode to treat a link that packs content into a public diagram renderer’s URL as an upload to that site: no longer auto-approved unless you asked for it
- Changed the prompt’s word-editing keys to match Bash: Ctrl+W deletes back to whitespace, Alt+F and Alt+D stop at word end, punctuation separates words; `keybindingFlavor` no longer has any effect
- Changed `/context` token counting to use a local estimate when the token-counting API is unavailable, instead of extra small-model requests
- \[VSCode\] Added a “Build a custom style” walkthrough to the Output styles menu that writes a custom output style file and lists it right away
- \[VSCode\] Added an Add server form and a Remove action to the MCP servers dialog, so MCP servers can be added and removed without leaving the IDE
- \[VSCode\] Added a hollow ring in the session list for sessions open in a terminal, another VS Code window, or Claude Desktop, so they no longer look closed
- \[VSCode\] Added a fold button to permission and question prompts so the conversation behind them can be read without dismissing them; the space beside the prompt now scrolls the conversation
- \[VSCode\] Added “Archive session” to the session list’s right-click menu and gave Unarchive its own icon
- \[VSCode\] Fixed a session teleported from Claude Code on the web treating a question that was cut off when the cloud session shut down as declined
- \[VSCode\] Fixed the session tab’s Rename box opening empty for a tab restored with the window; it now starts with the current name
- \[VSCode\] Fixed collapsed sections in the session list panel briefly showing expanded each time the panel loaded
- \[VSCode\] Fixed Focus view showing a tool call as still running after Claude had moved on, such as while a question waited for your answer
- \[VSCode\] Fixed the session list’s active-row highlight going stale when an unfocused Claude tab’s session ID is corrected
- \[VSCode\] Fixed Cmd/Ctrl+Shift+T reopen and deep-link opens placing the Claude tab outside the Claude editor group when a Claude tab has focus
- \[VSCode\] Fixed the session tab’s “Add to group” putting a session opened from Claude Code on the Web in two groups; it now moves the entry the session list shows
- \[VSCode\] Fixed the model picker showing models an organization has since disabled until the window was reloaded twice
- \[VSCode\] Fixed a tab opened from the session list jumping back to that session, and a tab opened from a Web session restarting its teleport or staying empty, after VS Code reloads the tab’s view
- \[VSCode\] Fixed `/btw` side-question history from earlier sessions being overwritten when a question is asked right after a window reload or while a settings file has errors
- \[VSCode\] Fixed the pending question card not reappearing after the Claude panel reloads when signed in with a Claude.ai or Console account
- \[VSCode\] Fixed claude.ai-only features staying visible in a window’s other Claude panels after one panel picked up a third-party provider from a settings file
- \[VSCode\] Fixed the sign-in screen appearing despite the Disable Login Prompt setting when Claude Code reports no login or a request fails for lack of one
- \[VSCode\] Fixed the next queued permission prompt keeping text typed on the previous prompt and accepting an immediate second click
- \[VSCode\] Fixed install-plugin links opening the Claude sidebar without the install dialog in a window where only the session list had been shown
- \[VSCode\] Fixed the sidebar usage meter staying empty on a new window until the Account & usage dialog was opened, and a 0% usage limit being left out of the meter
- \[VSCode\] Fixed “Start new session in this group” losing the group after New conversation, and a missing unread dot for a session that finished before the sidebar’s unread list loaded
- \[VSCode\] Fixed the editor tab badge showing unread during a running turn or missing on a tab opened from the session list, and “Add Session Tab to Group” doing nothing for an archived session
- \[VSCode\] Fixed “Enable Remote Control for all sessions” so flipping it also applies right away to sessions open in other VS Code windows
- \[VSCode\] Fixed the session list’s Open filter for sessions continued from claude.ai whose tab was still recorded under the web session, and labeled the filter menu’s sections for screen readers
- \[VSCode\] Changed the model picker to one flat list of every model, with rows kept for older model spellings listed last
[](#2-1-260)
2.1.260
September 3, 2026
- Added a diff panel that opens beside the conversation in fullscreen mode and shows your uncommitted changes as Claude edits; toggle it with `/diff`
- Added a likely cause for prompt-cache misses (e.g. tool definitions or system prompt changed, idle past the TTL) to `/cost` and the status line’s `prompt_cache` field
- Added `/reload-plugins` to headless sessions, so it appears in the Claude Code Desktop and SDK command lists
- Added a text form of `/advisor` (`/advisor`, `/advisor <model>`, `/advisor off`) for the desktop app, Remote Control, and other headless (`-p`/Agent SDK) sessions
- Added `oidc.scope_on_refresh` to the Claude apps gateway for IdPs that return an id_token on refresh only when asked for `openid` again
- Added Claude apps gateway support for newer Claude Desktop keys in `desktop` policy blocks, including `userPluginMarketplacesEnabled` and `userPluginUploadsEnabled`
- Fixed `Edit`/`Write`/`Read` permission rules whose path contains parentheses being dropped as invalid or ignored by the Bash sandbox, which left “read-only” folders writable
- Fixed one file permission rule with an uncompilable pattern (e.g. an unclosed `[`) making every file edit fail with `Invalid regular expression`; such a deny rule now guards the literal path it spells
- Fixed Bash permission checks auto-approving zsh commands that hide a command substitution in a REPORTTIME, REPORTMEMORY or DIRSTACKSIZE assignment; these now prompt for approval
- Fixed Bedrock model discovery, token counting and AWS SSO/STS credential calls failing with “unable to get local issuer certificate” when the corporate root CA is only in the OS certificate store
- Fixed `permissions.blockReadsOutsideWorkingDirectories` on macOS hiding the user’s git config from sandboxed git and hiding a worktree-isolated sub-agent’s own checkout
- Fixed managed settings not loading for claude.ai Enterprise/Team users who also had a leftover API key from an earlier `/login`
- Fixed `/status` listing a signed-in claude.ai account and a configured API key as if both were in effect; the credential not in use is now marked
- Fixed managed `skillOverrides` entries keyed on a bundled skill’s alias (e.g. `checkup` for `/doctor`) not applying, and `Skill(name)` deny rules not covering a nested skill listed as `<dir>:name`
- Fixed `model: fable` agents ignoring the `[1m]` tag on an `ANTHROPIC_DEFAULT_FABLE_MODEL` pin and silently running with a 200K context window
- Fixed the `/model` picker not showing Fable 5.1 for organizations that can use it, which was only accepted when typed as `/model claude-fable-5-1`
- Fixed prompt caching on Claude Fable 5.1 not covering the context attached after tool results, so it was re-sent as uncached input on every tool-call turn
- Fixed model switching staying blocked for the rest of the session after a plugin hook load failure; each switch now re-checks and the refusal names the cause
- Fixed model switching being blocked for the session when an organization-managed plugin’s marketplace could not be loaded
- Fixed SDK-provided MCP servers (e.g. Desktop connectors) sometimes missing from the first turn and only appearing on the next one
- Fixed Claude in Chrome tools failing with “Not connected” mid-task in cloud-hosted claude.ai sessions when a connector was added or removed
- Fixed flags, joined emoji and accented letters splitting across wrapped lines, and stale text staying on screen when a flag or joined emoji falls in the terminal’s last two columns (now shown as `…`)
- Fixed Remote Control accepting a model pick that is not a valid model name; it is now refused with an error instead of failing on the next message
- Fixed `/rewind` and `--rewind-files` reporting success when checkpoint backup files were missing and nothing was actually restored
- Fixed `/rewind` leaving stale file-read tracking from the rewound-away turns, which caused “File unchanged since last read” stubs and full-file re-injection after external edits
- Fixed `-p --resume`/`--continue` (as used by the desktop app) failing on every retry once a session’s worktree directory lost its git metadata; it now fails once, then resumes without the worktree
- Fixed a subagent that resumed another agent via SendMessage never being woken by that agent’s completion (the notification went to the main conversation instead)
- Fixed agent teams: an in-process teammate’s transcript losing messages, or going blank, during long API retry waits (e.g. under `CLAUDE_CODE_RETRY_WATCHDOG`) as retry notices evicted real messages
- Fixed a session that moved to the background appearing twice in ListAgents (once as a phantom “interactive” twin with the same name) and receiving SendMessage deliveries in the viewer
- Fixed intermittent “task output swap refused” errors when many sessions share a project directory
- Fixed Ctrl+Z in fullscreen leaving the shell on the alternate screen, drawn over the paused interface
- Fixed Workflow tool subagents being restarted as stalled while a long context compaction was still in progress
- Fixed plugins from a URL marketplace failing to install with “marketplace entry path does not stay inside the marketplace directory” when a host app (e.g. Claude Desktop) stores it as a directory
- Fixed an extra browser tab opening when an artifact is published in a session you’re driving from claude.ai, the desktop app, or mobile (Remote Control)
- Fixed the Artifact tool’s first call failing with an “Invalid tool parameters” validation error in some Cowork sessions
- Fixed IDE line selections being dropped when running a skill or slash command (the “N lines selected” context now reaches Claude)
- Fixed repository detection for GitLab projects in nested subgroups (e.g. `gitlab.com/group/subgroup/project`)
- Fixed `owner/repo#123` issue references in rendered output linking to github.com when working in a GitLab repository; they now link to the gitlab.com issue
- Glob/Grep: Fixed the search path being probed on disk before the permission check; a missing path is now reported after permission is decided, as Read does
- Reverted the 2.1.259 change applying `Read()` deny rules to Bash arguments; it denied `npm run build` under a `Read(./**/build/**)` rule in every mode and made `cd … && grep` prompt even in auto mode
- Improved structured output: Workflow `agent({schema})` rejects a JSON Schema that can never be satisfied up front, and retry-cap errors now include the last validation failure
- Improved deleting a background session whose worktree has unpushed commits: the message now names the branch and commit count, and deleting again discards the worktree
- Improved the Claude apps gateway’s refresh-failure log to name the step that failed
- Improved idle CPU usage of non-interactive (`-p` / SDK) sessions
- Improved the Claude apps gateway on Amazon Bedrock: input tokens for an aborted request are now counted with AWS’s free CountTokens API (grant `bedrock:CountTokens`) instead of a one-token request
- Improved the settings error for rules such as `Edit(C:\dir\(name)\**)`, where `\(` is read as an escaped parenthesis rather than a path separator, to suggest an unambiguous spelling
- Improved auto-compact for 1M-context models: Opus and Fable sessions now compact shortly before the 1M-token limit, and recovery compaction on very large contexts no longer times out at 10 minutes
- Improved `/ultrareview` and `claude ultrareview` to wait up to 45 minutes (previously 30) for long-running cloud reviews
- Improved `/effort` on Claude Fable 5.1 so changing effort mid-session no longer invalidates the prompt cache
- Updated the bundled `claude-api` skill so its Go, Java, and C# samples use current-generation model IDs, and clarified that cheaper worker or sub-agent models should be current-generation too
- Changed `ctrl+l` / `cmd+k` in fullscreen mode to clear the transcript view like a terminal `clear`; scroll up to see earlier messages
- Changed permission rules with text after the closing parenthesis (e.g. `Bash(ls) x`), which never matched anything, to be reported as invalid settings instead of being silently ignored
- Changed server-managed settings so a managed CLAUDE.md (`claudeMd`) no longer triggers the security approval dialog; hooks, shell-command, sandbox, and unsafe `env` settings still require approval
- Changed Claude in Chrome to follow your organization’s Claude in Chrome admin setting; when an admin turns it off, `--chrome`, `/chrome` and the browser tools are unavailable
- Changed Claude apps gateway to send `orgPluginSettings` in the list form read by Claude Desktop 1.15200.0 and later; older desktops ignore it
- Changed Claude apps gateway to also refuse to start, naming the field, when a `desktop` policy misspells a field in a nested object of a `managedMcpServers` or `orgPluginSettings` entry
- Changed commands typed at the `!` bash-mode prompt to run outside the sandbox even when strict sandbox mode (`sandbox.allowUnsandboxedCommands: false`) is on, like typing into your own terminal
- Changed self-hosted runner `--kill-session-after-min` to release a session that is only waiting on its user (paused, resumable on the next message) instead of killing it and reporting a failure
- Removed the one-hour time limit on background commands started by subagents; they now run until they exit or are stopped, matching the main session
- \[VSCode\] Added the selected effort level to the footer model pill, fixed a stale effort level after switching models, and returned the footer pills to their earlier compact size
- \[VSCode\] Added Open and Closed to the session list’s status filter menu
- \[VSCode\] Fixed the welcome screen disappearing in a new session when Remote Control turns on automatically
- \[VSCode\] Fixed the session history picker loading a session a second time when it is already open in another tab; it now switches to that tab
- \[VSCode\] Fixed the session tab’s Rename command silently doing nothing while the tab’s view was reloading; it now always applies
- \[VSCode\] Fixed a half-finished message, an empty tool card or an extra “Thought for” line staying on screen after Claude Code retried a dropped response
- \[VSCode\] Fixed “Enable Remote Control for all sessions” not applying to a session tab that was still starting when the toggle was flipped
[](#2-1-259)
2.1.259
September 2, 2026
- Added `managedMcpServers` managed setting: organizations can provide HTTP/SSE MCP servers to every user (same entry shape as `.mcp.json`); entries that name a command to run are skipped
- Added `--permission-prompts none` for unattended headless hosts: anything that would prompt is denied automatically while the active permission mode (including auto mode) keeps deciding
- Added recognition of `glab mr create/merge/close/reopen/note/update` so GitLab merge requests show as `MR !N` in the collapsed tool summary and refresh the footer MR badge
- Added `--json` to `claude plugin validate` for a machine-readable validation report
- Fixed concurrent sessions silently reverting each other’s `~/.claude.json` changes — workspace trust no longer resets and MCP/project state is no longer lost when running many sessions at once
- Fixed a conversation whose thinking was rejected once being rejected again on every later turn
- Fixed Bash `Read()` deny rules not covering files given as option values (`--ignore-revs-file=.env`, `-f.env`, `@file`), `git diff`/`git grep` file operands, or `cd DIR && cat FILE` compounds; `grep -r`/`cp -r` over a directory holding a denied file now asks
- Fixed the prompt cache being invalidated when the OAuth token refreshed in sessions with telemetry disabled
- Fixed fullscreen mode showing a blank conversation after a long turn with hundreds of tool calls
- Fixed auto mode running a turn on a model it doesn’t support when a command or skill’s frontmatter `model:` named one; the turn now keeps the session model
- Fixed `CLAUDE_CODE_MAX_CONTEXT_TOKENS` being ignored for Vertex-style model IDs (`@YYYYMMDD` suffix) of model versions Claude Code doesn’t recognize
- Fixed the live output preview of a running shell command hiding its newest lines when an earlier line wrapped
- Fixed a background GitHub connection check that ran on every launch for claude.ai users; the result is now remembered across launches
- Fixed `--resume` failing (and `--continue` opening an empty conversation) when a saved session contains an attachment entry with no payload
- Fixed frontmatter `model:` on custom commands and skills being ignored in interactive sessions
- Fixed Artifact publishing failing once with an “unexpected parameter `note`” error in conversations continued from an older version
- Fixed managed `forceRemoteSettingsRefresh` being ignored at startup when a policy helper configured by MDM or the managed settings file had already run
- Fixed worktree isolation refusing hook-created worktrees on machines where `git rev-parse` fails with a message other than “not a git repository”
- Fixed OpenTelemetry metrics and events from cloud sessions missing the `user.email`, `organization.id`, and `user.account_uuid` attributes
- Fixed MCP servers that disconnect while their tools are being listed at startup showing as connected with no tools instead of reporting the error
- Fixed the file edit permission dialog sometimes showing a changed line cut short with no indication
- Fixed repository detection dropping a known repo identity after a transient git probe failure
- Fixed managed settings silently going unenforced when the managed-settings file, a drop-in, the MDM plist, or the HKLM value cannot be parsed: Claude Code now refuses to start and names the source
- Fixed Stop not actually stopping background agents and workflows in remote-control sessions: killed tasks now stay visible and re-stoppable until their processes exit
- Fixed resuming a workflow run while its previous stopped run was still exiting, which could run duplicate copies of its agents
- Fixed marketplace repo URLs on github.com with a trailing slash or dangling `?`/`#` producing an unusable `.git` clone URL
- Fixed blocking Stop hooks causing the turn after a block to lose the model’s reasoning from that turn and, on some models, miss the prompt cache
- Fixed remote (claude.ai) sessions taking 60 seconds to start a turn after a browser-hosted MCP server’s page had gone away
- Fixed worktree-isolated sessions refusing common Bash loops, xargs pipelines and launcher-wrapped commands that cannot reach the main checkout
- Improved terminal resize and first-render performance for long responses by reusing text measurements
- Improved `/workflows` agent detail: JSON outcomes are pretty-printed with syntax colors and real line breaks, and long outcomes fold behind an expand toggle
- Improved headless/SDK session start: the first turn begins up to 50 ms sooner when MCP servers finish connecting
- Improved `/install-github-app` to explain it is GitHub-only and point to the GitLab CI/CD docs when run inside a GitLab repository
- Improved nested background subagent results to be saved in the parent subagent’s transcript, so resumed subagents keep them and shared transcripts show the delivery
- Changed `allowedMcpServers` to govern only servers users add: a literal `managed-mcp.json` server your allowlist used to filter out now loads on upgrade; use `deniedMcpServers` to keep it off
- \[VSCode\] Added an Active quick filter and a status filter menu (Needs input, Working, Completed) to the session list sidebar
- Fixed remote and scheduled sessions doing nothing after a connector-tool permission prompt was approved while the session was paused
[](#2-1-258)
2.1.258
September 1, 2026
- Fixed Claude Code failing to launch on macOS 12 (Monterey), a regression introduced in 2.1.255
- Fixed remote and scheduled sessions failing with “user messages must have non-empty content” after a re-sent permission approval could not be applied
[](#2-1-257)
2.1.257
September 1, 2026
- Added Claude Fable 5.1 (`claude-fable-5-1`), now the default Fable model — 1M context, $10/$10/50 per Mtok with \$0.25/Mtok cache reads
- Added “Time format” (`timeFormat`) and `timeZone` settings: 12-hour, 24-hour, 24-hour UTC, or a strftime pattern for the turn-end clock and transcript-view timestamps
- Added a Containment Escape rule to auto mode so cloud metadata-credential fetches, egress evasion, and cross-tenant reach are no longer auto-approved unless your environment marks them expected
- Added `CLAUDE_CODE_SUBAGENT_MODEL_FORCE` to apply `CLAUDE_CODE_SUBAGENT_MODEL` (or the main model) to every subagent, ignoring per-spawn and agent-definition model overrides
- Added `s` in `/effort` to change effort for the current session only, matching `/model`
- Added a `/doctor` warning for stale sandbox mask files left by a killed session
- Added a one-time prompt in auto mode before the first file read outside the working directories, with the option to block such reads (`permissions.blockReadsOutsideWorkingDirectories`)
- Added support for a gateway-supplied `description` on discovered `/model` picker entries (`CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY`); entries without one still read “From gateway”
- Fixed settings in a `.claude/` folder created after startup not being picked up until restart
- Fixed sessions dispatched from an agent view opened with `←` always starting in the original session’s permission mode, overriding the target directory’s `defaultMode` and the agent’s `permissionMode`
- Fixed `keybindings.json` rebinds of Ctrl+G being ignored in `claude agents`; its Ctrl+S / Ctrl+T are now rebindable via the new `Agents` context
- Fixed background sessions failing to start on macOS npm installs during a self-update, and on Windows when a stale daemon lock file pointed at a reused process id
- Fixed the working spinner stopping while a response streams behind a slash-command panel
- Fixed a background session’s `state.json` `detail` repeating its own dispatch prompt after a scheduled wake-up
- Fixed `claude agents` keeping a background session you re-prompted buried in Completed after it finished again; Completed now orders by the latest finish
- Fixed `claude --bg` from a directory that was just deleted reporting “backgrounded” and leaving a crashed session row; it now prints the reason and exits 1
- Fixed Remote Control connecting mid-session re-sending the Bash tool definition, causing a prompt-cache miss
- Fixed a doubly-listed custom `Authorization` header overriding the configured credential on Bedrock, Mantle, Vertex, and WIF, and the Vertex setup wizard picking up a leftover Anthropic profile from `~/.config/anthropic`
- Fixed Claude apps gateway sending stray host `Authorization` or profile headers to Foundry, Vertex, and Bedrock, and Foundry Entra ID upstreams not starting when `ANTHROPIC_FOUNDRY_API_KEY` is set
- Fixed a leftover Anthropic API key or auth token being sent alongside your Foundry subscription key in API-key mode
- Fixed `/schedule` routines whose prompt was saved without a message role and then ran with nothing to do
- Fixed `claude agents` not saying that a background session is waiting for you to approve a message from another session, or who sent it
- Fixed a prompt stashed with Ctrl+S inside an opened background session being lost when the session went idle or was stopped and then reopened
- Fixed telemetry (OTEL) settings pushed through server-managed settings being ignored on warm starts, including desktop-app Code sessions
- Fixed a teammate permission request being answered twice when the leader’s mailbox write was briefly locked
- Fixed a phantom duplicate slash-command row rendering below the in-flight turn while a command’s auto-continued response streamed
- Fixed `policyHelper` `timeoutMs` and `refreshIntervalMs` values above the timer maximum (2147483647) causing failures or re-runs every millisecond; they are now clamped
- Fixed the token counter freezing or crawling after switching to another subagent’s transcript, and made background subagents’ and teammates’ counters update live while a response streams
- Fixed sandbox network hosts written with a trailing dot (`example.com.`): a `deniedDomains` entry didn’t block the host inside the sandbox, and “don’t ask again” for such a host kept prompting
- Fixed dismissing the Remote Control consent prompt (Esc, or `n` at `claude remote-control`) counting as consent, so the next request connected without asking
- Fixed `/mcp` reconnect and enable still connecting a settings-file MCP server that a managed MCP allow/deny list or `strictPluginOnlyCustomization` loaded after startup should block
- Fixed `claude mcp remove` leaving a remote server’s stored OAuth credentials behind when `strictPluginOnlyCustomization` locks MCP to plugin-only servers
- Fixed Remote Control (`claude remote-control`) sessions started from the Claude app ignoring the selected model and running on the machine’s default instead
- Fixed `--disallowedTools` and session deny rules being dropped after the first settings reload when `allowManagedPermissionRulesOnly` is enabled
- Fixed `--resume` listing a backgrounded conversation twice and `--continue` reopening its stalled pre-background copy; `--continue` now also opens finished background sessions
- Fixed fullscreen mode not letting you click `!` shell command output to expand it
- Fixed background sessions left running an older Claude Code binary piling up across auto-updates instead of being retired
- Fixed `claude agents --json` briefly switching the terminal to raw mode and undoing another program’s terminal settings on exit
- Fixed Proactive output style sessions busy-looping with filler messages and repeated log reads instead of idling while a background command or Monitor they started is still running
- Fixed subagents stopping when a response was cut off mid-stream by a computer sleep, dropped connection, or server error; they now automatically continue instead of ending with an incomplete response
- Fixed `←` doing nothing in the `/btw` panel inside a `claude agents` session: it now returns to the agents list (even mid-answer), and the panel comes back when you reopen the session
- Fixed sessions with an advisor model set missing the prompt cache on background requests (compaction, `/recap`, prompt suggestions) and re-sending the full conversation uncached each time
- Fixed `claude -p` exiting about 5 seconds after its final result while a Monitor the model armed was still running; it now waits for the watch to fire or time out
- Fixed a `permissions.ask` rule being skipped in auto mode when the matching command ran inside a compound command or subshell, letting it run without the confirmation prompt
- Fixed plugins being able to read files outside their own directory through a declared command, agent, skill, hooks or other component path that is a symlink; such paths are now refused with an error
- Fixed `/add-dir` rejecting a directory inside the current working directory; it now loads that directory’s skills, commands, and agents like `--add-dir` does at startup
- Fixed the main agent not being told when you resume a subagent you had stopped from its transcript view
- Fixed a crash when pasting ANSI-colored text (e.g. a CI log) into dialogs like `/feedback`
- Fixed `claude mcp add/remove` hanging or exhausting memory when the project’s `.mcp.json` is a FIFO or a device-file symlink; it now fails fast with an actionable message
- Fixed unbounded memory growth when non-JSONL data is piped into `claude -p --input-format stream-json`; it now fails fast with a clear error
- Fixed backgrounding a turn (`←` or Ctrl+B) while a subagent or other tool was running occasionally making the background session treat that tool as rejected instead of re-running it
- Fixed Bash `Read()`/`Edit()` deny rules not applying to `< file` redirects and reader commands like `tac` and `egrep`; a deny rule on any argument or redirect target now refuses the command
- Fixed resuming or messaging a subagent whose transcript had grown past 5 MB (for example after reading many images) failing with “No transcript found”
- Fixed worktree-isolated sessions refusing Bash loops, `$VAR` reads, `"$(…)"` and heredocs that never touch git as “too complex to verify that it stays inside the worktree”
- Fixed `/model` and `/effort` showing a prompt-cache warning after rewinding a conversation back to empty
- Fixed prompt-cache misses on every turn in long screenshot-heavy sessions once images exceeded the per-request size cap
- Fixed the Edit permission prompt’s diff view rendering emoji and multi-code-point characters with incorrect widths
- Fixed WebSocket MCP server connection failures being logged as “\[object ErrorEvent\]” instead of the underlying error
- Fixed background sessions failing to open with “Couldn’t start the background service” while another Claude Code process was downloading an npm update; the start now waits for it
- Fixed background commands that detach from their shell (for example under `timeout` or `setsid`) surviving a task stop or Claude Code exit
- Fixed Claude not being told when you stop a background command from the tasks panel or a connected client
- Fixed stopping a background subagent leaving its monitors running
- Fixed sandboxed git commands in a linked worktree losing write access to the repository’s common `.git` directory after `cd` into a subdirectory
- Fixed Bedrock and Bedrock Mantle requests going silent during long hidden-thinking phases on Opus 4.7 and later, which let idle timeouts cut the connection; the stream now carries progress events
- Fixed launching Claude Code after a Claude apps gateway expired or revoked your session: it now says the session ended and offers `/login` instead of reporting a network error
- Fixed cloud sessions losing git/GitHub credentials for the rest of the session when the session’s network proxy failed to start at launch; it now retries in the background and recovers
- Fixed leftover `cc-daemon-*` folders in the system temp directory after an interrupted background daemon start; the `cleanupPeriodDays` retention sweep now removes them
- Fixed Bash permission checks auto-approving certain `[[ ]]` conditionals that zsh parses differently from bash; these commands now prompt for approval
- Fixed the managed-settings approval prompt showing the generic warning instead of its telemetry wording when the settings also turn detailed tracing or raw API body logging off, or trace export on
- Fixed agent-team teammates in tmux/iTerm2 panes sometimes staying open after acknowledging a shutdown request
- Fixed the keyless Console sign-in (“Sign in with your Console account”) not applying your organization’s server-managed settings, and `/status` not showing the Organization for that sign-in
- Improved rendering performance: less re-render work per turn in long conversations, streaming no longer slows down as the reply grows, and background-agent updates no longer re-render the whole screen
- Improved prompt input responsiveness by reducing per-keystroke rendering work
- Improved policy helper diagnostics — refresh failures now show in `/status`, declining the managed-settings dialog prints why Claude Code exited, and helper timeouts are reported as timeouts
- Improved `/code-review --comment` to post findings on GitLab merge requests via `glab mr note` instead of reporting the target as unsupported
- Improved notifications: an MCP elicitation or permission ask queued under another dialog now sends its idle desktop notification at the same delay as a visible ask
- Improved verbose/transcript output: async hook completion notices that arrive together now appear on one line instead of one line per hook
- Improved `claude self-hosted-runner --configure-git` to also enable git push negotiation, so the first push of a new branch from a stale clone uploads only the new commits instead of the whole tree
- Improved liveness reporting to SDK hosts while a response is held open by gateway keep-alives, so long waits under a raised `CLAUDE_STREAM_IDLE_TIMEOUT_MS` are not mistaken for a hung session
- Improved MCP connection and OAuth debug/error logs so credentials carried in a server’s URL or request headers are redacted
- Improved `/fork` to keep the original conversation’s prompt cache in the new background session: its worktree briefing now arrives as a message instead of a system-prompt change
- Improved emoji autocomplete to accept the remaining GitHub/Slack shortcode aliases (`:satisfied:`, `:telephone:`, `:collision:`, …)
- Changed `--effort` to lift a new model’s default-effort hold for that session only rather than permanently; an effort picked on claude.ai for a Remote Control session now applies during the hold
- Changed a `policyHelper` in MDM or `managed-settings.json` shadowed at launch by cached server-managed settings to run (or exit) as soon as the fetch reports them removed, not at the next launch
- Changed `managedSourcesBehavior: "merge"` to take `sandbox.credentials.awsPairs` and `sandbox.ripgrep` whole from the highest managed source that sets them instead of combining the sources’ values
- Changed gateway model discovery (`CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`) to run even when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` is set, since it only queries your gateway
- Changed `claude --resume <session-id> --bg` to continue that session under its own ID when nothing is running it, instead of silently starting a copy; a copy is now announced
- Changed `/btw` history browsing from `←`/`→` to `Shift+←`/`Shift+→` (or `[`/`]`), stepping through your recent side questions and back to the live answer
- Changed `defaultMode: "bypassPermissions"` in `.claude/settings.json` or `.claude/settings.local.json` to be ignored, like `"auto"`; set it in user or managed settings, or pass `--permission-mode`
- Changed `fable` and `best` in Claude apps gateway sessions to keep resolving to Fable 5 for now, since gateways not yet configured for Fable 5.1 reject it; pick Fable 5.1 in `/model` to use it
- Changed `--add-dir`, `/add-dir`, and `additionalDirectories` to refuse network paths (UNC shares, `/net/<host>` automounts) with a message before touching them; on Windows use a mapped drive letter
- Changed Claude apps gateway sign-in and token refresh requests to verify the gateway’s pinned TLS certificate, as the managed settings fetch already does
- Changed Cowork and claude.ai cloud sessions: reading an artifact that isn’t yours now always asks you first, even in auto mode
- Removed the Ctrl+E command explanation on Bash and PowerShell permission prompts
- \[VSCode\] Added collapsible ACCOUNT & USAGE and SESSION MANAGER section headers to the session list panel, with the account email, the usage meter, and a View details link opening the usage dialog
- \[VSCode\] Added a model pill to the input footer that shows the current model and opens the model picker, with an Effort row and a “More models” page
- \[VSCode\] Added a collapse toggle to the Ungrouped section of the session list
- \[VSCode\] Added output style selection to the command menu, including custom styles
- \[VSCode\] Fixed third-party provider deployments (Bedrock, Vertex, and others) still showing claude.ai-only features (remote sessions, dictation, usage) and calling claude.ai with a leftover login
- \[VSCode\] Fixed the session list panel’s usage meter staying blank after the panel loads; it now shows the last known usage immediately
- \[VSCode\] Fixed the “Enable Remote Control for all sessions” toggle so turning it on or off applies to sessions that are already open, not only to new ones
- \[VSCode\] Fixed screen reader announcements: a control character before a fence or heading no longer drops visible lines from speech, and bold markers spanning a heading are no longer mis-paired
- \[VSCode\] Changed the action menu to list slash commands in a filterable “Slash commands” dialog instead of inline; picking one runs it; the MCP servers dialog gained the same filter box
- \[VSCode\] Changed “Delete session” to “Archive session”: archived sessions move to a collapsible “Archived sessions” group at the bottom of the list with an Unarchive action
[](#2-1-252)
2.1.252
August 31, 2026
- Fixed Bash commands failing with “task output swap refused (tasks dir moved or linked)” on some Macs
- Fixed “always allow” not saving in a project that has no .claude/settings.local.json yet
- Fixed Remote Control sessions hosted by Claude Desktop or VS Code stalling for minutes after a tool finished when the connection to claude.ai was degraded
- Fixed background task notifications with very large failure output (for example git errors on a full disk) making the conversation exceed the API request size limit
[](#2-1-251)
2.1.251
August 28, 2026
- Added `PreModelSwitch` and `PostModelSwitch` hook events (block, confirm, or annotate a model switch); `SessionStart` resume hooks now receive session staleness and the estimated re-cache cost
- Added live streaming of a foreground subagent’s tool calls and results to Remote Control clients (background subagents, the default, still show status only)
- Added a Spend limit bar to `/usage` and a `rate_limits.spend_limit` status line field for developers behind a Claude apps gateway with spend limits
- Added a per-session prompt-cache line to `/cost` (hit ratio, misses, tokens re-cached, warm/cold) and a matching `prompt_cache` object for status line scripts
- Added `attach`, `logs`, `stop`, `respawn`, and `rm` to `claude --help`; the `--resume` message for a running background session now names the exact `claude attach <id>` command
- Fixed file tools (Read, Write, Edit) following a symlink swapped inside the working directory after the permission check, which could read or write outside the approved location
- Fixed plugin commands declared in a marketplace entry being able to point outside the plugin directory; such paths are now rejected with a path-traversal error
- Fixed project settings being able to enable detailed beta tracing or raw API body logging, and a lower-scope beta tracing endpoint bypassing an OTLP collector pinned by managed settings or a host app
- Fixed the Workflow tool reading (and quoting in errors) a `scriptPath` outside what the session may read before the permission check ran
- Fixed Grep and Glob not applying `Read(...)` deny rules to files reached through a symlinked search path
- Fixed conversations getting stuck on “text content blocks must be non-empty” errors after a turn where the model produced only thinking
- Fixed the first launch on a fresh install starting in default mode instead of auto mode for accounts whose startup default is auto mode
- Fixed Opus 5 requests failing with “effort … is not supported when thinking is disabled” when effort was xhigh/max and thinking was turned off; effort is now sent as `high` in that case
- Fixed replying to a message Claude Desktop delivered from another session: `SendMessage` to that session id now delivers through Claude Desktop instead of failing with “not reachable”
- Fixed TUI lag with many parallel subagents: per-second progress ticks now replace their predecessor instead of piling up in the transcript
- Fixed agent teams: a teammate’s final answer not reaching the team lead — it now arrives in the idle notification instead of a content-free “available” notice
- Fixed background subagents being unable to reply to a message from an unnamed sibling or parent agent (`from` was the agent type, which is not an address)
- Fixed managed-settings `disableAutoMode` arriving mid-session not moving an already-running auto-mode session back to default mode
- Fixed a “switch to Opus 1M for 5x more context” tip that appeared even when the current Opus model already has a 1M context window
- Fixed Claude apps gateway sessions treating a stored Anthropic profile (e.g. a Console sign-in) as active: listing it in `/status` and retrying gateway 401s with it, though requests never use it
- Fixed cloud sessions telling Claude the model had changed when the host was only setting the session’s initial model
- Fixed Remote Control reporting a failure when an organization’s policy disables it; it now shows a single quiet notice instead
- Fixed `/mcp reconnect` on Remote Control showing a generic withheld-detail error instead of the real remedy when a server was disabled in another session
- Fixed `--input-format stream-json`: client-injected assistant tool calls sent without a message id were merged into the first one and their results lost, including when resuming older sessions
- Fixed session transcripts being silently overwritten when a directory change relocated a session onto an existing same-ID transcript
- Fixed background sessions and their subagents being unable to edit files inside a git worktree they created with `git worktree add`
- Fixed background sessions occasionally starting without any plugin skills (and staying that way) when another Claude Code process was refreshing the plugin marketplace at the same moment
- Fixed selecting text in an opened background session inside tmux over SSH: it now copies to the tmux buffer like a foreground session instead of falling back to OSC 52
- Fixed SDK and cloud sessions hanging indefinitely when an SDK MCP server’s handshake acknowledgment was lost; the wait now times out after 70 seconds and marks only that server failed
- Fixed self-hosted runner leaving a stuck session’s Bash tool processes running after the session was force-stopped
- Fixed `/usage-credits` for Team and Enterprise members whose admin set the org’s usage-credit limit to \$0: it now offers to ask the admin instead of saying a cap was reached
- Fixed `--worktree --tmux` with a merge-request number on a gitlab.com origin trying a doomed GitHub-style fetch first instead of fetching the GitLab ref directly
- Fixed Ctrl+G failing with “Emacs quit unexpectedly” in background sessions for editors that open `/dev/tty`, such as `emacs -nw` and `micro`
- Fixed an `additionalDirectories` entry containing a null byte crashing startup, or breaking `/add-dir` and later settings updates when it came from an SDK host, IDE, or hook; it is now skipped
- Fixed the MCP server menu’s copy shortcut: it now says how the sign-in URL was copied instead of always claiming success
- Fixed italic text (such as the session recap line) rendering as highlighted blocks in GNU screen and in tmux sessions using a `screen` terminal type
- Fixed `claude mcp add --header` and `claude mcp add-json` help text naming the wrong transports
- Fixed `claude ultrareview` and `/ultrareview` waiting the full 30 minutes when the cloud session fails to start; they now stop early and report the reason
- Fixed Bash permission checks auto-approving commands that assign an arithmetic expression to an integer shell variable (e.g. `OPTIND=1/0`, `RANDOM=2+2`); these now prompt for approval
- Fixed backgrounded sessions (`←`, `/background`, `--bg`) losing a Vertex/Bedrock gateway (`ANTHROPIC_*_BASE_URL` + `CLAUDE_CODE_SKIP_*_AUTH`) exported in the shell, so every request failed
- Fixed `claude --bg --model fable` on Max plans stopping to ask for usage credits while the interactive session on the same account still had Fable allowance
- Fixed the one-time “make auto mode your default” offer appearing in unattended sessions (e.g. agent-team teammate panes), where a stray keypress could accept it unread
- Fixed the managed-settings approval prompt re-appearing after signing in again to the same Claude apps gateway when the settings are unchanged
- Fixed disabled `/bug` and `/share` reporting that `/feedback` was disabled; tips, `/help`, and refusal messages no longer suggest `/feedback` when an org policy or env var turns it off
- Fixed cloud session creation advising GitHub setup after a transient GitHub connection failure — the message now says to retry instead
- Improved CPU usage during turns in interactive sessions by cutting redundant UI re-renders
- Improved install size: the native binary is about 5 MB smaller
- Improved cloud sessions: when the session’s network proxy drops a connection during a Bash command, the tool result now names the host and reason instead of only “connection reset”
- Improved `/schedule` to explain that MCP servers configured in Claude Code can’t be attached to cloud routines, instead of a bare “No MCP connectors” message
- Improved framing of messages from your own subagents: Claude is told the sender is a worker inside this session, not an unrelated Claude session
- Improved the prompt placeholder to read “Message @name…” while viewing a background subagent or fork transcript opened from the subagent panel or `/tasks`
- Improved sanitization of MCP server names in error messages, menus, and command results
- Improved Amazon Bedrock session start under `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST` (e.g. Claude Desktop): a session given a Bedrock model ID or ARN no longer waits for inference-profile discovery
- Improved the managed settings approval dialog to list only the settings that changed since you last approved them
- Improved retry when the model’s tool call is malformed: the broken output is now dropped from the retry context, including on Bedrock, Vertex, and Foundry
- Changed `/radio` to be available on Bedrock, Vertex AI, Foundry, and Claude Platform on AWS, and when telemetry is disabled
- Changed Claude in Chrome so browser actions always go through Claude Code’s permission checks, including in sessions with telemetry disabled, which previously used the Chrome extension’s own prompts
- Changed `CLAUDE_CODE_SUBAGENT_MODEL` to set the default subagent model rather than override everything: an agent definition’s `model:` and an explicit per-spawn model now take precedence over it
- Changed the default commit trailer to `Co-Authored-By: Claude Code` when the active model isn’t a recognized Claude model (e.g. third-party models behind a custom `ANTHROPIC_BASE_URL`)
- Changed the default model for seat-based Enterprise subscriptions to Opus 5, matching other premium plans
- Changed `/effort` to save your default effort level per model, so each model keeps its own setting when you switch
- Changed analytics to no longer turn off before sign-in solely because managed settings force gateway login (or cannot be read); they stay off once signed in to the gateway or via `DISABLE_TELEMETRY`
- Changed the footer PR badge on Bedrock, Vertex, and Foundry, and when telemetry is off, to call the GitHub API directly (via `gh auth token`, `GH_TOKEN`, or `GITHUB_TOKEN`) instead of `gh pr view`
- Changed how Bash command output files are created and read back when commands run in the sandbox, so a sandboxed command cannot redirect or replace them
- Changed plugin/LSP install suggestions and the auto-mode default offer to wait until you’ve sent or cleared what you’re typing, so the Enter that sends your prompt can’t answer them
- Changed server-managed settings that terminate sandbox TLS, route sandbox traffic through your own proxy, inject credentials, or weaken sandbox isolation to require approval before they apply
- Changed `ANTHROPIC_CUSTOM_HEADERS` from managed or project settings to require approval when it sets a credential, org/tenant, routing, or API-behavior header (e.g. `Authorization`, `Host`)
- Changed project-level `.claude/settings.json` `env` to no longer set `CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_TMPDIR`, or `TMPDIR`/`TMP`/`TEMP`; set them in your shell, user, or managed settings instead
- Removed syntax highlighting for six rarely used languages (1c, gml, isbl, mathematica, maxima, sqf); the binary is 2.5 MB smaller
- \[VSCode\] Fixed the sign-in screen’s “Bedrock, Foundry, or Vertex” button opening the docs at the top of the page instead of the third-party provider setup section
- \[VSCode\] Changed the Remote Control banner to a footer pill (shown while Remote Control is on or has failed) that opens the session on claude.ai/code; turn it on or off with `/remote-control`
[](#2-1-250)
2.1.250
August 28, 2026
- Bug fixes and reliability improvements
[](#2-1-248)
2.1.248
August 27, 2026
- Added `--restricted` (or `CLAUDE_CODE_RESTRICTED=1`): removes the built-in tools that run commands or code and `WebFetch` (unless named in `--tools`), keeps file tools inside the working directory, refuses `bypassPermissions`, and ignores user, project and local settings files
- Added `experimental.cacheTtl` (`"5m"` or `"1h"`) to agent frontmatter: a per-agent prompt cache TTL used when no subagent TTL setting is configured
- Added `claude self-hosted-runner --client-label <label>` (or `SELF_HOSTED_RUNNER_CLIENT_LABEL`) to override the label the runner registers with (default: hostname)
- Added server-managed settings diagnostics: a startup warning when the settings fail to load, and a `/doctor` and `/status` line explaining a load failure or why they weren’t fetched (Bedrock/Vertex/third-party provider, custom `ANTHROPIC_BASE_URL`)
- Added a warning in `/web-setup` when the GitHub CLI token lacks the `workflow` scope, since pushes to very large repositories can be rejected without it
- Added `/usage-credits` for Enterprise organizations billed through AWS Marketplace, self-serve Enterprise, and Enterprise trials, so members can request a higher usage limit from their admin
- Added cross-session messaging (`SendMessage` / `ListAgents`) between sessions on the same machine on Bedrock, Vertex, and Foundry, and when telemetry is disabled
- Fixed a prompt-cache miss (and lost extended-thinking context) roughly once an hour in long sessions, caused by tool definitions being re-rendered after an OAuth token refresh
- Fixed the `ScheduleWakeup` tool definition changing between a session and its `--resume` when the account had entered usage overage, causing a full prompt-cache miss on the resumed session’s first turn
- Fixed Claude Desktop and Cowork sessions disappearing after 30 days: the transcript cleanup now keeps desktop-written sessions while they are in the app (unless org policy manages retention); the new `desktopSessionCleanupPeriodDays` setting caps the exemption
- Fixed being sent to the login screen when another Claude Code process held the token refresh lock while the session token had expired; the request now fails with a retryable error instead
- Windows: Fixed the `claude agents` list not responding to the keyboard after detaching from a session, or when launched in a terminal tab left in win32-input-mode
- Fixed the recommended Console sign-in in `/login` failing with an OAuth error before showing a sign-in URL on machines where it can’t be used (for example when `ANTHROPIC_API_KEY` or an API key helper is set); it now falls back to the API-key sign-in
- Fixed model names in `/model` and fast-mode switch notices to render as code, so suffixes like `[1m]` display literally instead of as a link
- Fixed `claude agents` skipping the workspace trust prompt when the `CI` environment variable is set
- Fixed `claude agents` crashing on launch when the PR-status cache held a malformed entry
- Fixed agent view resurrecting a weeks-old background session after the machine was off: such a session now shows as stopped at its real end, and opening it asks before resuming its saved conversation
- Fixed agent view sometimes opening an older conversation, and dropping the typed prompt, when starting a new session
- Fixed `claude agents`: opening a stopped session that you already resumed in another terminal no longer starts a second process on that conversation; the row now says it is open in a terminal
- Fixed `claude agents` and `claude rm` refusing to delete a session (“has commits that are not pushed anywhere”) when its worktree branch was already merged into your checked-out default branch (e.g. local `main`) but not yet pushed
- Fixed background sessions waiting silently when a `PermissionRequest` or `PreToolUse` hook prints an invalid answer: the `claude agents` row now names the hook and the schema error
- Fixed hooks silently treating a stdout `{…}` object that isn’t valid JSON as plain text; it’s now reported as a hook error with the parse message
- Fixed `/mcp` listing a project `.mcp.json` entry that declares the claude.ai connector type under the trusted “claude.ai” heading; it now appears under its real scope
- Fixed MCP servers whose `headersHelper` supplies the `Authorization` header falling into OAuth discovery on a 401 instead of re-running the helper and retrying the call as documented
- Fixed `/login` to a Claude apps gateway hanging when the managed-settings security approval dialog was required
- Fixed gateway model discovery (`CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY`) never running when `apiKeyHelper` is the only credential
- Fixed `claude logs` leaving mouse tracking, bracketed paste and the alternate screen switched on in the terminal it was run from
- Fixed the trust dialog’s list of repo permission rules showing a garbled character when a long rule was cut off in the middle of an emoji
- Fixed the permission mode indicator staying hidden behind the “Press Ctrl-C again to exit” hint when you press shift+tab right after ctrl+c
- Fixed `/ultrareview` and locally seeded cloud sessions uploading uncommitted edits to `prod.env`-style and `*.tfvars` files, or to editor swap, temp, and backup copies of credential files (e.g. `key.pem.tmp`, `id_rsa.swo`); they now stay on your machine
- Fixed Remote Control sessions occasionally never showing a permission prompt or the latest messages on the connected device after the CLI silently reconnected
- Fixed cloud sessions occasionally failing at startup when the container’s session credentials were not yet readable
- Fixed `claude remote-control` rejecting its own flags (e.g. `--spawn`, `--name`) when a global flag or a wrapper-injected option precedes the subcommand
- Fixed startup warnings (e.g. “N MCP servers need authentication”) rendering one column right of the rest of the transcript
- Fixed a backgrounded worktree session losing its checkout: the background session now holds the worktree’s lock while it runs, so cleanup and `git worktree remove` leave it alone
- Fixed @-mentions of other sessions not matching names typed with non-Latin characters (for example Korean entered through an IME)
- Fixed an invalid `crossSessionInbound` value being silently ignored: it now warns and holds cross-session messages (user settings) or refuses them (managed settings) until fixed
- Fixed rate-limit, usage, and fast-mode messages telling you to run `/usage-credits` when that command isn’t available for your organization (e.g. hidden with `DISABLE_EXTRA_USAGE_COMMAND`)
- \[VSCode\] Fixed a chat tab getting stuck on “No conversation found” when its session was never saved; it now starts a new conversation instead
- Improved the Workflow tool’s prompt footprint: its description is now about 1k tokens instead of 5.7k, with the script-writing reference moved into a bundled `workflow-authoring` skill
- Improved the prompt-footer PR badge to check GitHub less often while the pull request is unchanged; a push or a `gh pr` command still refreshes it right away
- Improved managed settings: client-side timeout, MCP startup-mode, and stream-watchdog env vars no longer trigger the settings-approval prompt
- Improved `/ultrareview <PR#>` to check before launch that the GitHub account connected to your Claude account can access the repository, and to explain how to fix it, instead of failing after the cloud session starts
- Improved cross-session messaging: falls back to a private per-user `/tmp` directory when the default one can’t be used, and the notice and `/status` name the directory to fix
- Changed shift+enter in the agent view dispatch input to insert a newline (matching the prompt); ctrl+enter now dispatches and attaches
- Changed `/loop`: self-paced dynamic mode and the no-prompt autonomous default are now always available, including on Bedrock/Vertex/Foundry
- Changed Anthropic telemetry export failures to log at debug level as `[Anthropic telemetry]` instead of `[3P telemetry] OTEL diag error`, so they are not mistaken for your OTel collector failing
- Changed cross-session messaging in Linux user namespaces: root-equivalent trust for unmapped owners is limited to canonical system directories
- Changed `SendMessage` from a subagent to another session: the result now notes that any reply is delivered to the parent session’s conversation, not to the subagent
[](#2-1-247)
2.1.247
August 26, 2026
- Added the `SendFeedback` tool: when something goes wrong in a session, Claude can draft a feedback report for you to review and send from `/feedback` (turn off with the `feedbackDrafts` setting)
- Added `{id, text, cooldownSessions, priority}` entries, `tipsFile`, and `label` to `spinnerTipsOverride`, so organizations can rotate their own tips alongside the built-in ones
- Added a tip on Bash permission prompts pointing to auto mode, with a one-keystroke “Yes, and switch to auto mode” option
- Added `/claude-api cost-optimize` to profile an existing project’s Claude API spend and work through cost levers (caching, token hygiene, batch, effort, model choice) one measured change at a time
- Updated the `/claude-api` skill with Admin API coverage (organization members, invites, workspaces, API keys, rate limit reports, workload identity federation, CMEK)
- Fixed fast arrow-key + Enter sequences acting on the row above the one you navigated to in history search, `/config`, `/mcp`, `/skills`, background tasks, and `/model`
- Fixed sub-agents dying on a first-call model 404: they now use the session’s fallback model chain, and the error returned to the parent includes the error type, status, request id, and model
- Fixed a hook or background agent that printed megabytes of error output being able to overflow the conversation and wedge the session on “Prompt is too long”
- Fixed Ctrl keyboard shortcuts not firing under non-Latin (e.g. Cyrillic) keyboard layouts in kitty-protocol terminals
- Fixed text like `<35;150;7M` being inserted into the prompt when a mouse report arrived split across reads right after the escape prefix
- Fixed the Bash sandbox’s after-command cleanup deleting a dotfile-managed `~/.claude/settings.json` symlink (nix/home-manager, stow) when it is repointed outside the sandbox’s writable area
- Fixed `/terminal-setup` overwriting your entire Zed `keymap.json` instead of merging in its keybinding
- Fixed `/rename` silently confirming when the session registry could not be updated; it now says other sessions may still show the old name
- Fixed `/compact` and “Summarize from here” in sessions started with `--agent` summarizing under the default system prompt instead of the conversation’s own
- Fixed a background session showing “opening…” forever in `claude agents` after its terminal host process died; the row now fails within seconds with the reason, and Enter restarts it
- Fixed unbounded memory growth when a hook’s or background task’s output file could not be written; the file now notes where output was lost
- Fixed `/install-github-app` over SSH: the copy shortcut now says how the sign-in URL was copied instead of always claiming success, and the URL appears immediately when no browser can open
- Fixed shell commands carried over from the foreground logging an internal error or showing a misleading `[exited with code -1]` line when they finish in background sessions
- Fixed a version-less marketplace plugin’s live cache directory being deleted and recreated on a second-scope install, which could disrupt a running session using it
- Fixed Remote Control sessions started with `/remote-control` not reporting the working-tree diff to connected clients
- Fixed self-hosted runner sessions reporting `running` before Claude Code had started, which could trigger a premature “Claude is waiting for your input” notification from the Claude desktop app
- Fixed first-run setup exiting with “Unable to connect to Anthropic services” when managed settings configure Claude apps gateway sign-in and Anthropic endpoints are unreachable
- Fixed cloud sessions (Claude Code on the web, desktop and mobile apps) sometimes showing the previous permission mode when you switch modes right after sending a message
- Fixed cloud sessions going silent when the session’s container restarts between turns while a background agent, shell, or monitor is still running — the resumed session now reports the lost work
- Improved plugin marketplace hardening: names containing control or invisible characters are rejected, and marketplace-supplied text in `/plugin` and `claude plugin` output is escape-safe
- Improved Bedrock, Vertex, and Foundry sessions (and any with telemetry disabled): Claude is now told when a configured MCP server failed to connect, instead of concluding its tools don’t exist
- Changed Sonnet 5’s default auto-compact window to its full 1M context, so sessions on the 1M window now auto-compact at about 967K tokens instead of about 934K
- Changed cross-session peer messages to collapse by default to a one-line `Message from @<sender>: <first line>` preview; Ctrl+O expands the full body
- Changed terminal hyperlinks in rendered markdown: link targets that point at a network or automounter path, contain a control character, or lead with an invisible character now render as plain text
- Changed the prompt-footer PR badge to skip its GitHub re-check on terminal refocus when the last check is under a minute old
- Changed analytics to stay off from startup, not only after login, when managed settings force gateway login or a custom OAuth deployment is configured
- Changed Claude apps gateway sign-in requests to identify Claude Code (a `surface=claude_code` device-authorization parameter and a `claude-code/<version>` User-Agent)
- Changed organization sign-in enforcement to exit at start when the administrator’s managed settings cannot be read, even if host-supplied or per-user Windows registry settings exist
[](#2-1-246)
2.1.246
August 25, 2026
- Added a startup warning for Bash allow rules with a wildcard before the subcommand (e.g. `Bash(git * main)`), since they also match options inserted before the subcommand
- Added an Auto mode tab to `/permissions` for viewing and editing auto mode classifier rules
- Added the turn’s completion time to the end-of-turn duration line, e.g. `✻ Sautéed for 23s · done 6:05 PM`
- Fixed fullscreen mode showing a blank transcript after resizing the terminal and jumping to the bottom until the next keypress
- Fixed a severe transcript slowdown when a diff contained a very long single line (e.g. a base64 string); such lines now render truncated with a marker
- Fixed erratic fullscreen scrolling when positioned at an earlier message, including jump-to-bottom getting stuck mid-transcript
- Fixed background sessions failing to open after 45 seconds when Claude Code’s starting directory had been deleted, the machine had slept, or the host is slow to start processes
- Fixed background sessions failing to open with “Couldn’t start the background service … EACCES” when another Claude Code process was re-installing the npm package at that moment
- Fixed markdown rendering being disabled for a whole message when its first 500 characters contained no markdown, and for `+`/`N)` lists and setext headings
- Fixed MCP tool calls interrupted by an incoming message in headless/remote sessions being reported to the model as “completed with no output” instead of an explicit interrupted error
- Fixed MCP tool arguments being sent as JSON strings when the parameter’s schema is empty (`{}`), instead of their real type
- Fixed a command interrupted mid-run showing as “Ran 1 shell command” with no sign it was cut
- Fixed pressing ← or running `/background` during a dynamic workflow restarting its finished subagents; it now asks first and says how many subagents would restart
- Fixed opening a just-started session in `claude agents` while its worker was still booting (common on Windows) stopping it with “was stopped while the respawn was in flight”
- Fixed `claude agents` listing a backgrounded named session twice; backgrounding the same conversation again now numbers the new row (e.g. `my-session (2)`)
- Fixed the background retention sweep removing git worktrees under `.claude/worktrees/` that you created yourself when an old background-session record pointed at them
- Fixed auto mode tool calls being denied as “temporarily unavailable” on very large sessions by scaling the safety-check deadline with prompt size
- Fixed the plugin cache creating duplicate SHA-named directories for the same plugin
- Fixed plugin skills whose frontmatter `name` already includes the `<plugin>:` prefix showing it doubled in the slash menu (e.g. `/plugin:plugin:skill`)
- Fixed `claude plugin update` failing for an installed plugin given its bare name (only the fully-qualified name worked)
- Fixed plugin installation failing when `plugin.json` was saved with a UTF-8 byte-order mark (BOM)
- Fixed `/reload-plugins` reporting 0 skills for plugins that define skills under `skills/*/SKILL.md`
- Fixed hook error messages showing a literal `${CLAUDE_PLUGIN_ROOT}` instead of the resolved plugin path
- Fixed `/rename` replacing the theme’s prompt border color (including a custom theme’s `promptBorder`) with the default cyan; the border now keeps your theme’s color unless you pick one with `/color`
- Fixed custom theme diff colors (`diffAdded`/`diffRemoved` and their dimmed variants) being ignored in diffs and the `/theme` preview
- Fixed a `keybindings.json` binding with an unknown action name silently deadening that key; it is now skipped so the default binding keeps working, and a warning is logged under `--debug`
- Fixed `/stats` activity heatmap showing each day’s activity one cell off (Sunday’s count under Monday) in timezones east of UTC
- Fixed `/fork` from an already-forked or backgrounded session starting the new session with an empty conversation
- Fixed prompts beginning with `/--` (e.g. Lean doc comments) being rejected as an unknown slash command instead of being sent to Claude
- Fixed the `@` file picker staying open after the typed text stopped matching a real path
- Fixed the status line’s cost and duration resetting to zero after navigating to the agents view and back
- Fixed fullscreen mode moving keyboard focus onto the control under the pointer when you clicked the terminal window only to bring it back into focus
- Fixed path completion failing when the completion token or working directory contained a null byte
- Windows/macOS: Fixed headless sessions not cleaning up stale entries in `~/.claude/sessions` left by sessions that exited uncleanly
- Fixed the UI stopping with a render error on the first tool call when a third-party Anthropic-compatible endpoint (`ANTHROPIC_BASE_URL`) streams a `tool_use` block without an `id`
- Fixed the Write tool reporting “Out of memory” or freezing for a long time after overwriting a very large existing file, even though the file had been written
- Fixed `claude plugin install <name>` exiting silently (or hanging in a terminal) instead of reporting an error when `~/.claude/plugins/known_marketplaces.json` is empty or corrupted
- Fixed resumed sessions failing every turn with a 400 when the saved history contains tool blocks the Anthropic API does not accept (typically written by a third-party API proxy)
- Fixed `curl -fsSL https://claude.ai/install.sh | bash` failing with “Raw mode is not supported” for some Team/Enterprise users with server-managed settings
- Fixed sessions that ended in plan mode resuming outside plan mode in the VS Code extension, and in `claude -p --continue`/`--resume` with a permission prompt tool, when no permission mode was set
- Fixed the `Notification` hook not firing while the sandbox “Network request outside of sandbox” permission prompt is waiting
- Fixed Bash permission checks to always require approval for malformed commands with a dangling `&&` or `||` operator
- Fixed `--strict-mcp-config` sessions prompting to approve `.mcp.json` servers they would never load, which left background sessions waiting at startup
- Fixed telemetry and metrics requests to Anthropic carrying the API key configured for a third-party gateway (`ANTHROPIC_BASE_URL`); a credential is now only sent to its own host
- Fixed a visible API error on the first prompt after idle when `apiKeyHelper` returns short-lived JWTs: an expired cached token is now refreshed before sending, and 401/403 auth errors retry quietly
- Fixed memory growing with session length in the fullscreen and Ctrl+O transcript views: each rendered message row no longer retains a full copy of the transcript-wide tool lookups
- Fixed `/ultrareview` runs and cloud sessions launched at the same time from one repository (e.g. from several worktrees) sometimes starting with another launch’s uncommitted changes
- Fixed the task progress count (e.g. `3/5`) shown for background cloud sessions such as `/autofix-pr` occasionally missing a task
- Fixed Remote Control sessions keeping their placeholder name in claude.ai and the Claude app until the second prompt; the auto-generated title now appears after the first prompt
- Fixed MCP tools marked `requiresUserInteraction` still offering “Yes, and don’t ask again” in their permission prompt; the option wrote an allow rule the tool then ignored
- Fixed the self-hosted runner ending its live sessions or exiting when a work-poll response is malformed (e.g. an intercepting proxy’s HTML page); it now retries the poll
- Improved `/cd`: the new directory’s project settings, hooks, `.mcp.json` servers (behind the usual approval prompt), skills, and agents now take effect right after the move instead of on `--resume`
- Improved Bash tool latency on bash shells by replaying snapshot functions without a base64 subshell per function
- Improved subagent results: a subagent that stops at its `maxTurns` limit now returns its output marked as partial, with a hint to continue it via `SendMessage`, instead of appearing finished
- Improved non-interactive sessions (`-p`, SDK, cloud sessions) to automatically continue a response cut off mid-stream by a server error, connection loss, or stall instead of ending with an error
- Improved attribution of usage telemetry to your organization for workload identity federation sessions, events sent while `apiKeyHelper` runs at startup, and after a login token expired while idle
- Changed `/code-review` so Claude can also start it on its own on Bedrock, Vertex AI, and Foundry, through the Claude apps gateway, and when telemetry or non-essential traffic is disabled
- `/goal`: Changed idle sessions to start at most three check-ins on long-running background work per goal; your next message allows three more
- Changed `claude install` and `claude update` to defer a pending managed-settings consent prompt to the next interactive session instead of prompting mid-command
- Changed OpenTelemetry plugin events for plugins synced from claude.ai: `plugin_id_hash` now reflects the plugin’s real marketplace, and `enabled_via` is `admin-install` for admin-installed plugins
- Fixed the command sandbox’s filesystem configuration not respecting `--setting-sources`
[](#2-1-245)
2.1.245
August 25, 2026
- Fixed a crash on startup on Linux distributions that ship glibc 2.44 (for example Arch Linux, CachyOS and Fedora Rawhide)
[](#2-1-243)
2.1.243
August 25, 2026
- Added a Loops breakdown to `/usage`: per-loop run count, total tokens, tokens per run, and last run, so runaway or chatty `/loop` tasks are easy to spot
- Added `modelPicker` setting: curate the `/model` picker with an ordered, labeled list of models (any id spelling, including Vertex/Bedrock ids), appended to or replacing the built-in lineup
- Added `promptCacheTtl` and `subagentPromptCacheTtl` settings so API-key and cloud-provider users can keep a 1-hour prompt cache on the main conversation while subagents stay at 5 minutes
- Added `modelPricing` managed setting so an organization’s contracted per-model rates and discount multiplier are used for `/cost`, the status line, and telemetry cost figures instead of list price
- Added a keyless sign-in under `/login` → Anthropic Console: “Sign in with your Console account” (recommended) alongside creating an API key, so organizations that don’t allow API keys can sign in
- Added a `Skipped sources` line to `/status` that lists managed settings sources (for example `managed-settings.json`) present but not applied because a higher-precedence managed source is active
- Added a `managed` marker in `/mcp` and `/plugins` on claude.ai connectors whose authentication is managed by your organization
- Added a tip pointing claude.ai users who haven’t connected GitHub for Claude Code on the web to `/web-setup`
- Added a `/status` line showing whether GitHub is connected for Claude Code on the web (Pro/Max), pointing to `/web-setup` when it isn’t
- Added the model (and effort level) each subagent ran on to `/tasks` and the agent detail dialogs
- Fixed remote MCP servers in non-interactive (`-p`) and SDK sessions never recovering after a dropped connection; they now reconnect automatically or report as failed
- Fixed MCP server sign-in started from the desktop app failing with “Invalid redirect URI” on servers that support client ID metadata documents (for example Linear)
- Fixed auto mode staying unavailable at startup when a temporary server-side disable was cached and later flag fetches failed
- Fixed auto mode tool calls being denied as “temporarily unavailable” after about a minute of waiting when the API was briefly overloaded and asked the client to retry
- Fixed the `/model` picker silently ignoring an Ultracode selection; picking Ultracode now applies it to the current session
- Fixed `/resume` only listing the 50 most recent sessions; the picker now loads more as you scroll
- Fixed cloud sessions resuming after a mid-turn restart with a pending hook or background-task notification re-sent as the prompt instead of the normal continuation message
- Fixed cross-session messaging silently turning off inside user namespaces and rootless containers after the 2.1.232 socket-directory hardening
- Fixed text that hangs outside its container (for example the sign-in URL in `/login`) losing its leading columns when another part of the screen repaints
- Fixed `spellcheck` not underlining a misspelled word typed directly after an emoji
- Fixed background subagents not waking when their last background Bash task completes
- Fixed sessions going silent for 10+ minutes when the Anthropic API never starts a response: the request now times out after ~3 minutes, retries once, then shows `API Error: No response from API`
- Fixed auth, model-availability, and other client-generated error messages rendering like model output instead of as error lines
- Fixed workload identity federation in CI: processes in one job share the exchanged token instead of re-exchanging the single-use token; a rejected exchange fails fast with the server’s message
- Fixed server-managed `companyAnnouncements` not showing at startup in a session that began with signing in (for example the first launch after `/logout`)
- Fixed hook `if` conditions like `Bash(cat *)` firing on unrelated Bash commands when the command contained `$()` or backtick command substitution followed by more arguments
- Fixed plugin dependencies declared with a `marketplace` field never resolving when both plugins are loaded together via `--plugin-dir`
- Fixed `/reload-plugins` keeping the LSP tool after the last LSP plugin is disabled; it now also warns before an LSP plugin change that would re-read the conversation
- Fixed `--agents` silently ignoring invalid JSON or invalid agent definitions; it now exits with a clear error, like `--mcp-config`
- Fixed `/status` showing “Found invalid entries in: .” with no filename when `~/.claude.json` has an invalid MCP server entry
- Fixed `/clear` removing the `/rename` session name from the prompt bar even though the name was kept for the new session
- Fixed Ctrl+R history search and up-arrow history breaking when `~/.claude/history.jsonl` contains a malformed entry
- Fixed Ctrl+\[ not leaving vim INSERT mode in terminals that encode modified keys (modifyOtherKeys / kitty protocol)
- Fixed the local IDE connection being routed through `HTTPS_PROXY` (and sometimes failing) when `localhost` was listed in `NO_PROXY` but not lowercase `no_proxy`; both casings are now honored
- Fixed sandbox network-violation details being dropped from the Bash tool result when the blocked command still exited 0 (for example `curl` printing the proxy’s 403 page)
- Fixed the status line `rate_limits` fields and `/usage` still showing a rate-limit window’s pre-reset usage percentage after the window reset while the session was idle
- Fixed `claude --teleport <session>` exiting on uncommitted changes instead of offering to stash them and continue, as the session picker already does
- Fixed `/web-setup` repeatedly asking you to log in when an older GitHub CLI (without `gh auth token`) was already authenticated
- Fixed Claude in Chrome losing its connection to Claude Code after an auto-update cleaned up the version it was set up with; the native host now launches via the stable `claude` launcher
- \[VSCode\] Fixed sessions started before feature flags were first fetched (for example right after install) opening in the default permission mode instead of auto mode or your configured default mode
- \[VSCode\] Fixed Focus view sections you expanded collapsing on their own during subagent tool activity
- Improved startup time: sandbox and MCP bring-up no longer block the first frame, bare launches skip subcommand registration, and workflow discovery, settings, and trust-store work is cheaper
- Improved native install and auto-update download size: the binary is now zstd-compressed (about 75 MB instead of 340 MB on Linux x64)
- Improved attribution of usage telemetry to your organization for sessions that authenticate with `ANTHROPIC_AUTH_TOKEN` directly against the Anthropic API, so its data-handling settings apply
- Improved native binary size: about 2 MB smaller by storing the bundled skill and prompt text more compactly
- Improved memory usage of native builds: code is now loaded on demand instead of keeping the whole bundle resident (roughly 40–70 MB less memory per session)
- Improved peak memory usage in long-running sessions (the runtime now garbage-collects sooner as the heap grows)
- Improved `/login` over SSH: the sign-in URL appears immediately, pressing `c` reports how the URL was copied instead of always claiming success, and a hint explains how to select text in fullscreen
- Improved the error when effort `xhigh`/`max` is used with thinking turned off: it now names the level, the setting that disabled thinking, and `/effort high` as the fix
- Improved `/loop`: consecutive wake-ups where Claude has nothing to do now fold into a single line in the terminal instead of printing each one
- Changed the sandboxed Bash tool prompt to no longer list allowed network hosts, so Claude attempts requests (and you can approve new hosts) instead of assuming unlisted hosts are blocked
- Updated the `/model` picker and the bundled `claude-api` skill to show Sonnet 5’s $2/$2/10 per Mtok pricing as its standard list price rather than a limited-time promo
- Changed computer use on macOS so clicking the desktop, Dock, or a Finder window requires granting Finder via the access dialog, like any other app
- Changed `/model`, `/fast`, and `/effort` to also run immediately instead of queueing until the turn ends on Bedrock, Vertex, and Foundry and when telemetry is disabled
- Fixed `claude remote-control` exiting and stranding attached Remote Control sessions when the server drops its environment mid-session; it now recovers
- Fixed Remote Control sessions served by `claude remote-control` sometimes getting stuck after it was stopped and restarted, for Team and Enterprise members without an admin or owner role
- Changed the cross-session messaging inbox socket to close connections that send no complete line within 30 seconds; scripts posting to it should connect once their data is ready
- Improved the notice when resuming a conversation whose Remote Control is held by another terminal: it now says sessions on other machines can’t be seen from, or reach, this one
- \[VSCode\] Improved history trimming in long sessions: older tool-activity rows are dropped first so your messages and Claude’s replies stay visible
- \[VSCode\] Improved attribution of the extension’s own usage telemetry to your organization when you are signed in with a Claude account, so its data-handling settings apply
[](#2-1-241)
2.1.241
August 23, 2026
- Bug fixes and reliability improvements
[](#2-1-240)
2.1.240
August 22, 2026
- Bug fixes and reliability improvements
[](#2-1-239)
2.1.239
August 21, 2026
- Cost estimates (`/cost`, status line, `--max-budget-usd`) now include the 1.1× US-only-inference premium for data-residency workspaces
- Added the one-time fullscreen renderer offer on Bedrock, Vertex, Foundry and other previously excluded setups; new installs there now start in fullscreen
- Added `/claude-api upgrade` to migrate Python projects from `anthropic` 0.x to 1.x, and updated the skill’s Python reference for 1.x (timeouts use `anthropic.Timeout`, not `httpx.Timeout`)
- Cloud sessions: plugins synced from claude.ai now show as `name@synced`, work with `claude plugin enable/disable <name>@synced`, and never override a same-named plugin you installed
- Alpine/musl builds: native image paste, clipboard, and audio-capture add-ons now load (musl-built binaries instead of glibc ones refused by the runtime)
- The usage-limit message shown when your monthly spend limit is already used up now also says when your session or weekly limit resets
- Fixed Bedrock streaming behind proxies that strip the response Content-Type header, which silently doubled billed API calls by re-running every turn non-streaming
- Fixed Claude Code hanging at startup behind an HTTPS proxy when using Bedrock with an SSO profile and `awsAuthRefresh` — the credential pre-check now honors `HTTPS_PROXY`
- Fixed a raw crash dump when starting Claude Code from a directory that no longer exists; it now prints a clear message
- Fixed Edit and Write calls pausing for about 5 seconds in JetBrains IDE terminals when the Claude Code plugin is connected
- Fixed a race where pressing Esc with a prompt queued could let the next turn finish early, leaving the session idle while Claude was still working and letting a later resubmit repeat actions
- Fixed WebFetch retaining expired page content in memory for the whole session instead of the intended 15 minutes
- Fixed cloud sessions (Claude Code on the web, desktop and mobile apps) resuming out of plan mode after an idle worker restart
- Fixed MCP elicitation forms taller than the terminal being clipped in fullscreen mode: the form now fits the window, with hidden fields reachable by scrolling and Accept/Decline always visible
- Fixed remote MCP servers staying failed after a transient 5xx on a mid-session reconnect in cloud sessions or via SDK `setMcpServers()`
- Fixed custom session titles disappearing from `/resume` after more than ~64 KB of conversation was written following the rename
- Fixed `claude -c`/resume picking up sessions from a different directory whose path differed only by characters like `_`, `-`, or `.`
- Fixed `/resume` and the agents view showing a session as recently changed (and reordering it) when only its file was touched or it was merely reopened
- Fixed `/resume` in all-projects mode telling you to `cd` into a deleted directory (e.g. a removed worktree); such sessions now resume in the current directory
- Fixed the `dark-ansi` theme rendering expanded tool results in fullscreen mode with text the same color as the background
- Fixed the fullscreen renderer prompt reappearing on every launch when it could never be answered; it now stops after being shown on three launches
- Fixed `.worktreeinclude` patterns starting with `**/` silently matching nothing when the target lived in a gitignored directory
- Fixed agents, skills, and commands whose `.md` file starts with a UTF-8 BOM being silently ignored
- Fixed `/insights` echoing literal `<message>` tags in its response on some models
- Fixed marketplace `metadata.pluginRoot` having no effect: bare plugin source names now resolve under it as the docs describe
- Fixed mouse movement in browser-based terminals inserting text like `"35;150;7M"` into the prompt when a mouse report arrived split across writes
- Fixed custom theme overrides for the effort/ultracode status badge colors being ignored
- Fixed OpenTelemetry trace fragmentation: tool executions deferred by a `PreToolUse` hook now resume in the original turn’s trace instead of starting a new trace
- Fixed vim mode in the agent view: Escape now switches to NORMAL mode and keeps your text instead of clearing the prompt
- Fixed the `selection:copy` keybinding silently dropping a text selection that had been extended with Shift+Arrow keys
- Fixed the `/voice` startup tip still appearing after voice dictation was enabled via the `voice.enabled` setting
- Fixed shell-mode (`!`) Tab completion dropping the `./` from a `./script` path, which left a command the shell couldn’t run
- Fixed fullscreen mode answering a permission prompt or pressing a button when you clicked the terminal window only to bring it back into focus
- Fixed slash-command panels (e.g. `/config`, `/model`) in fullscreen mode covering the latest messages; the conversation now stays pinned above the panel
- Fixed the `/workflows` detail dialog overflowing the terminal and losing its header off-screen when opened while Claude is still responding
- Fixed the Linux sandbox making a nonexistent `.git/config.worktree` unreadable, which broke every sandboxed git command in repos with `extensions.worktreeConfig` set
- Fixed hooks failing with “posix_spawn ENOENT” after the session’s working directory was deleted; they now run from the project root or home directory instead
- Fixed `claudeMdExcludes` not excluding a symlinked `.claude/rules` file when the pattern names the rules directory or the symlink rather than its target
- Fixed runaway session-title syncing to Remote Control when two Claude Code processes shared one background job’s state (2.1.232 regression); title updates are now deduplicated and rate-limited
- Fixed sessions whose title starts with `/` being unaddressable by `SendMessage` and shown as “(untitled)” in `ListAgents`
- Fixed Ctrl+W, Ctrl+U, Ctrl+K, Option+Backspace, Option+D and vim `df`/`dt` leaving a broken `[Pasted text #N]` placeholder when the cursor was inside it
- Fixed masked (password-style) inputs such as the login code field letting their text be pasted back with Ctrl+Y elsewhere or saved to prompt history when cleared with double Esc
- Fixed Ctrl+Backspace deleting one character instead of a word in search boxes
- Fixed a request rejected by an organization policy check being re-sent before the rejection was shown
- Improved the reminder shown after compaction so a skill’s original arguments are not re-run as a new request
- Long file paths on tool-use rows now truncate in the middle to stay on one line
- Remote sessions keep sending keep-alives while a long `SessionStart` or `Setup` hook runs, so the container is not idle-reaped mid-hook
- `/goal`: repeat check-ins on long-running background work now back off (30 min, then 1 h, then every 2 h) instead of repeating every 30 minutes
- `/goal`: resuming a session from the `claude --resume` picker now restores its active goal
- `ListAgents` now tells a session its own name (the one peers use to message it), and `SendMessage` to your own name says so instead of “no agent named …”
- `ListAgents` and `/list-agents` now list your live teammates (previously only subagents and other sessions appeared, so a reachable teammate looked absent)
- `keybindingFlavor: "readline"` now also matches Bash for word keys: Alt+F and Ctrl/Option+→ stop at the end of the word, Alt+D deletes to it (Ctrl+Y pastes it back), and punctuation separates words
- Persistent retry mode (`CLAUDE_CODE_RETRY_WATCHDOG`) now fails immediately on organization spend-limit and out-of-credits errors instead of waiting indefinitely for a reset
- Claude in Chrome: `/clear` now closes the session’s Chrome tab group, and empty groups are closed on `/resume` and when Claude Code exits
- Remote sessions: images uploaded from mobile now include their saved file path, so Claude can copy them into files it creates
- Claude Code on the web: requests from Bash and other tools to non-API anthropic.com hosts (e.g. www, docs) now go through the session’s network proxy, so your environment’s allowed domains apply
- Remote Control: clearer message and `claude doctor` wording when Remote Control isn’t enabled for your account
- Windows: cross-session messaging is now available, so Claude Code sessions across your machines can message each other with `SendMessage` and find each other with `ListAgents`, as on macOS and Linux
- \[VSCode\] “View usage” in the usage-limit banner now sits inline with the warning text instead of floating mid-banner
[](#2-1-238)
2.1.238
August 20, 2026
- Added a `keybindingFlavor` setting: set it to `"readline"` to make Ctrl+W in the prompt delete back to the previous whitespace, as in Bash; the default (`"classic"`) is unchanged
- Plugin marketplaces: `headersHelper` on a url marketplace or a catalog entry runs a command that mints HTTP headers (e.g. a short-lived token) for catalog and same-origin archive fetches
- A catalog entry’s `headersHelper` runs only when you install or update that plugin, after its command is shown; `claude plugin install/update` ask `[y/N]` (or pass `-y`)
- Added `claude self-hosted-runner --defer-shutdown-max-min <minutes>`: on SIGTERM, keep serving attached sessions, park what is left after that many minutes, then exit
- Added `claude self-hosted-runner --proxy-authorization-command` / `--proxy-authorization-file` for egress proxies that require a freshly issued `Proxy-Authorization` header on every connection
- Fixed unbounded memory growth in long interactive sessions: subagent tool results are now released once they leave the recent display window
- Fixed custom, project, and plugin output styles drifting back to the default voice mid-session
- Fixed `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=true` not keeping prompt suggestions on when your account is near, but not over, its usage limit
- Fixed worktree-isolation Bash refusals telling you to remove a redirect when the command had none
- Fixed self-hosted runners occasionally being removed by the server after a single slow or lost poll request, handing their healthy session to another runner
- Fixed MCP elicitation dialogs showing nothing for URLs longer than 4,096 characters, and permission prompts dropping the “don’t ask again” option when the project path didn’t fit the terminal width
- Fixed leftover `/tmp/claude-*-cwd` files when a Bash command is killed, times out, or is interrupted
- Fixed held Backspace being ignored on terminals that send Ctrl+H for Backspace when keystrokes arrive in large bursts (slow SSH/mosh links)
- Fixed text-wrapping in permission prompt diffs: lines containing wide multi-code-point characters (such as emoji) or tabs are no longer clipped
- Fixed killing a suspended (Ctrl+Z) session sometimes leaving the terminal in bracketed-paste mode with the cursor hidden
- Fixed stdio MCP servers receiving a `server/discover` request before `initialize`, forcing lazy servers to start their backend on every session open
- Fixed a proxy’s refusal of a connection being reported as a generic network error instead of naming the proxy
- Fixed the `/model` and `/effort` cache-miss warning appearing when the prompt cache had already expired
- Fixed per-task Stop from the Remote Control tasks panel doing nothing on CLI-hosted sessions
- Fixed remote sessions exiting when a client delivered a user message without a valid role
- Fixed Remote Control sessions started by `claude remote-control` inheriting session-scoped environment variables from the launching shell
- Fixed a Remote Control session whose process crashed staying unavailable until `claude remote-control` was restarted; it can now be reused when you next message it
- Fixed Remote Control messages sent from the web or Desktop while Claude is mid-turn disappearing from the transcript after the turn finishes
- Fixed Remote Control model picks made on a phone or web not updating the model shown in the terminal
- Fixed Remote Control disconnecting with “login expired” when a brief network hiccup delays renewing your sign-in; it now retries and stays connected
- Fixed Remote Control reporting a failed reconnect on sign-out; signing out now ends the session with a clear message
- Fixed `ListAgents`/`SendMessage` reporting “Remote Control is not connected” in sessions run by `claude remote-control` (server mode) or Desktop/IDE hosts; they now list and reach Remote Control peers
- Fixed `ListAgents` and `SendMessage` exposing the idle worker that the agent view pre-warms for your next background session; it now appears only once a task claims it
- Cross-session messaging: sending to a session on this machine that refuses inbound messages (e.g. `crossSessionInbound: "refuse"`) now reports “refused” to the sender instead of a silent success
- Cross-session messaging: a session whose inbox drops your messages (rate limit or full queue) now tells your session, instead of the messages vanishing silently
- Improved startup: bare `claude` starts sooner on macOS
- Improved Bash tool permission checking for zsh-specific syntax in shell conditionals
- Improved Remote Control connection resilience: brief HTTP 403 refusals from a network edge, VPN, or proxy are now tolerated for up to 3 minutes, with the refusing party named when a block persists
- Improved startup responsiveness: the automatic update check now runs about 10 seconds after launch instead of competing with startup for CPU
- Updated the bundled `claude-api` skill for the Managed Agents Aug 19 release: web search/fetch domain settings and memory stores on self-hosted sandboxes
- Changed Ctrl+L and Cmd+K in fullscreen to always just repaint — the double-press `/clear` shortcut was removed, and 1-row nvim terminals no longer trigger automatic `/clear` loops
- Changed `claude mcp list` and `claude mcp get` to show disabled servers as `⊘ Disabled` instead of connecting to them for a health check
- MCP `headersHelper` in a project `.mcp.json`, and inline MCP servers in project or `--add-dir` agent files, now require that folder’s trust dialog to have been accepted (also under `claude -p`)
- MCP `headersHelper` from a project `.mcp.json`, plugin, or agent file runs without inherited credential env vars; user, managed and claude.ai-scope helpers now run from the Claude config dir
[](#2-1-237)
2.1.237
August 20, 2026
- Fixed prompt caching for sessions using an LLM gateway or custom base URL
- Added a built-in “Concise” output style: Claude leads with results and skips preamble and narration, while doing the work just as thoroughly. Select it under Output style in /config.
[](#2-1-236)
2.1.236
August 19, 2026
- Added `ANTHROPIC_DEFAULT_MODEL` environment variable: sets the model new sessions start on, while a `/model` pick still overrides it and persists across restarts (unlike `ANTHROPIC_MODEL`)
- Added `notify_when_idle` to cross-session `SendMessage`: ask another Claude Code session on this machine to send one notice when it next goes idle — opt-in, one-shot, no polling (macOS and Linux)
- Sandbox: on macOS, wildcard read-deny rules (e.g. `**/.env`) now take precedence inside allowed read regions, cover matched directories’ contents, and can’t be bypassed by renaming the denied file
- Fixed clipboard copy, background housekeeping, background sessions, and local MCP logs breaking after the directory a session had switched into was removed (since 2.1.229)
- Fixed the fullscreen renderer failing permanently after a single failed start: it now falls back to the classic renderer instead of exiting on every subsequent launch
- Fixed the `/model` picker rendering taller than the terminal: it now shows only as many models as fit the window, with the rest reachable by scrolling
- Fixed `SendMessage` calls being rejected when a malformed closing tag left the message text inside the summary field
- Fixed unhandled promise rejections when a subprocess fails to start, for example `powershell.exe` on WSL with Windows interop disabled (regression in 2.1.234)
- Fixed fullscreen mode sometimes not showing a newly sent message until the next update after the terminal was resized
- Fixed a blank band that could remain above the prompt after clearing a multi-line prompt, and panes not repainting after resizing the terminal away and back, in fullscreen mode
- Fixed the managed-settings approval prompt sometimes not appearing at startup while still capturing the first keypress as approval
- Fixed terminal tab titles jumping in tmux (iTerm tmux integration): the title is now written only when its text changes instead of animating every 960ms
- Fixed an unclear error when the cloud environments list came back empty or malformed
- Fixed the Fable 5 first-time usage-credits prompt auto-selecting the fallback model after 60 seconds with no answer when using Remote Control
- Fixed spinner tips never appearing, with a repeated background error, when the cached guest-pass reward in `~/.claude.json` was malformed
- Fixed skills hot-reload in SDK/VS Code sessions raising an error on every skills change after the session’s working directory was deleted (2.1.229+)
- Fixed self-hosted runner sessions released on idle, retire, or startup timeout occasionally resuming on another runner before the post-session hook had finished
- Fixed the Clawd mascot’s eyes and feet rendering unevenly in iTerm2 at some font sizes
- Fixed occasional runaway session recaps: recap text (automatic and `/recap`) is now capped at 400 characters, cut at a word boundary
- Improved startup performance: the session counter is now written in the background
- Improved auto mode: `Monitor` allow rules are now set aside while auto mode is active, so Monitor commands are reviewed the same way Bash commands are
- Improved auto mode on Bedrock, Vertex AI, and Foundry, and when telemetry is disabled: the classifier now uses the same defaults as on the Claude API, including severity-scored classification
- Improved auto mode: the git status check can no longer be fooled by a repo’s `status.showUntrackedFiles=no` setting into reporting a clean tree
- Changed the `/model` picker to highlight only the newest model’s name, so the highlight marks the new release rather than an arbitrary subset of the list
- `/goal`: an idle session whose goal is parked behind long-running background work now checks in automatically after 30 minutes (then 1h, 2h) instead of waiting for you to return
- `/usage` now shows the usage-credits spend row for Team and Enterprise members, and shows a capped row at 0% before anything is spent
- SIGTERM in print/SDK mode no longer records an interrupted turn or synthetic tool denials before exiting; running commands are still terminated and the process still exits with code 143
- Pressing Enter on a slash-command typo or a command unavailable in this session now reports it instead of running the closest fuzzy match; prefixes and aliases still run
- Remote Control now marks a session offline within seconds when the CLI exits or its terminal closes
- `SendMessage` now refuses further messages to a session up front once a rapid burst would exceed what that session’s inbox accepts, instead of reporting them sent while they were dropped
- Aligned the session title chip on the prompt border with the footer’s right edge
- Right-aligned footer items (goal indicator, session state, background agent status) and truncated notices now share a consistent right margin with the rest of the prompt area
- \[VSCode\] Added screen reader support for the transcript: live announcements for replies, permission requests, errors, and status changes, plus per-turn heading navigation
[](#2-1-235)
2.1.235
August 18, 2026
- Added an optional `spellcheck` setting that underlines misspelled words in the prompt input as you type, using your installed `aspell`, `hunspell`, or `ispell`
- Fixed whole-prompt-cache invalidation when a language server disconnected or reconnected mid-session
- Fixed nested markdown list items misaligning at depth 3+ and added a hanging indent to wrapped list items in the terminal UI
- Fixed prompt input highlights (slash commands, keywords, mentions) appearing shifted by one or more characters in some multi-line prompts
- Fixed Shift+Tab inside the permission prompt’s comment field approving the edit and granting session-wide edit permission instead of closing the field
- Fixed the Agent tool advertising a general-purpose default in sessions where that agent is unavailable: an omitted `subagent_type` there now gets a clear error listing the available agents
- Fixed notebook cell delete/replace approval dialogs silently omitting the existing cell content when the notebook or cell could not be read; the dialog now says why
- Fixed slash commands run while Claude is responding showing HTML entities instead of the actual characters
- Fixed the prompt footer not showing the “Update installed” restart notice after a background auto-update
- Fixed the expanded task list (`ctrl+t`) always starting collapsed when resuming or relaunching into a session that still has open tasks
- Improved memory and CPU usage while cloud sessions such as `/ultrareview` or `/autofix-pr` run in the background — their event streams are no longer re-scanned and re-rendered on every update
- Improved permission dialogs: display text and “don’t ask again” options now always match what a grant would cover, and “don’t ask again” is withheld when contents cannot be fully displayed
- Improved the embedded `grep` in native macOS/Linux builds: pathological patterns now fail fast instead of exhausting memory, and `-m N` with `-A/-C` prints correct context
- Improved the context-limit error to say when auto-compact is off and point to `/config` to re-enable it
- Vim mode: NORMAL mode and cursor position are now preserved when toggling the detailed transcript (ctrl+o) or closing a panel
- Dialogs: arrow keys and Enter pressed in quick succession now select the option you navigated to instead of the previously highlighted one
- `SendMessage` now refuses messages too large for cross-session delivery up front instead of silently dropping them
- Remote Control: `claude rc` now applies the same enterprise-gateway availability check as interactive startup
- \[VSCode\] Fixed focus jumping between open Claude tabs on its own when a window with several Claude panels is restored or reloaded
[](#2-1-234)
2.1.234
August 17, 2026
- Added the optional `CLAUDE_CODE_PROJECT_DIR_NAME` environment variable: hosts that give each session its own config directory can choose a short name for the per-project transcript directory
- Added the `selection:clear` keybinding action, so a key can be bound to clear an in-app text selection; also works in the agents view
- Added a GitLab merge request badge to the footer and statusline: repos with a GitLab remote and an authenticated glab CLI show MR !N with draft/pending/green states
- Claude Code now continues your session automatically when a claude.ai usage limit resets; turn it off in `/config` (“Continue automatically at usage limit”)
- Claude is now told to use your account email only to identify you, and not to send it to unrelated services unless you ask
- Security: remote file reads, session restore, CLAUDE.md includes, workflow scripts and file uploads now reject Windows NT-namespace (`\??\`) paths, hardening the remaining pre-approval file accesses against the NTLM credential-leak vector
- Fixed auto mode in very long sessions repeatedly re-checking and denying sandboxed commands’ network access after the conversation had been compacted
- Fixed session-scoped permission answers (including denies) being dropped when answering background subagent tool permission prompts
- Fixed a crash when an API response on the non-streaming fallback path (typically via third-party gateways) contained a thinking block missing its thinking field or a text block missing its text field
- Fixed markdown rendering becoming extremely slow for some messages containing unusual Unicode sequences
- Fixed `SendMessage` rejecting a recipient copied from `ListAgents` when the session name is at the 200-character cap or emoji-heavy
- Fixed repository detection mis-reading the host of git remotes with unusual userinfo, producing links and repo-specific behavior for the wrong host
- Fixed MCP diagnostics printing resolved secrets: scope-conflict warnings now show the configured `${VAR}` form, and connection-failure details show only the server origin
- Fixed `strictKnownMarketplaces` allowlists accepting SCP-style git marketplace sources whose host differs from the one git would actually connect to
- Fixed modal text such as the `/login` OAuth URL losing characters when copied in fullscreen
- Fixed a `---` horizontal rule in rendered markdown running into the line after it
- Fixed consecutive shell commands splitting into multiple “Ran 1 shell command” rows when todo/task updates were interleaved between them
- Fixed dialogs like `/permissions` opened while a `!` shell command was running being dismissed when the command finished
- Fixed a queued `!` shell command being sent to the model as plain text after pressing up-arrow to edit the queued input
- Fixed queued messages reappearing in the prompt history while still queued, Esc while selecting a queued message no longer interrupts the turn, and `!` mode no longer sticks after a mid-turn submit
- Fixed accepting the “Try the new fullscreen renderer?” prompt restarting the session without its permission mode (e.g. `--dangerously-skip-permissions`), tool allow/deny rules, model or effort flags
- Fixed `/tui` dropping launch `--allowed-tools`/`--disallowed-tools` rules when it restarts; it now declines to switch, with the reason, when the session has restrictions a restart can’t carry over
- Fixed trust prompts omitting the repository-wide scope warning when the directory was first seen before the repository existed there
- Fixed a case where an IDE diff tab closing during a permission re-prompt could answer the new prompt with the previous input
- Fixed: files sent to the user during Remote Control sessions hosted by Claude Code Desktop or VS Code now upload, so they open on phone and web instead of showing an empty card
- Fixed: after `/login` while `CLAUDE_CODE_OAUTH_TOKEN` is set, the stale-token reminder no longer leaks into Claude’s automatically resumed turn — it now appears only to you
- Fixed: permission previews now relay only to channel servers admitted by the inbound trust gate, and a server’s explicit permission-capability opt-out is honored
- Fixed: credential masking on relayed permission previews can no longer hide commands, paths, or destinations from the approver; oversized private-key blocks now redact under full-strength redaction
- Fixed: provider API tokens that mask on permission previews now mask even when directly followed by shell delimiters
- Fixed Claude Desktop inter-session messages being silently dropped by the recipient session when cross-session messaging read as disabled, which left the sender’s query “thinking” for many minutes
- Remote Control: signing this computer in to a different claude.ai account or organization now stops the running session within seconds and says why, instead of a misleading HTTP 404 hours later
- Remote Control sessions started from Claude Code Desktop or VS Code now keep phones and claude.ai/code updated on the session’s permission mode (and claude.ai/code on the model) as they change
- Remote Control: effort picks made on a phone or on claude.ai/code now apply to terminal- and Desktop/VS Code-hosted sessions, and the session publishes its effort level to connected clients
- `SendMessage` and `ListAgents` now say when your account’s session list was too long to check completely, instead of treating unseen sessions as absent
- Expired Anthropic profile credential now points you at `/login` when a claude.ai login would take precedence
- Improved the transcript: your own prompts now render markdown (highlighted code blocks, inline code, lists) the same way replies do
- Improved the “API returned an empty or malformed response” error to say what came back (content type, body kind, size, request ID) and why the original streaming request failed
- Improved auto-generated session titles to read as short, specific names (e.g. “Login button bug”) rather than sentences restating your request (e.g. “Fix the login button on mobile”)
- Reduced the context cost of loading the built-in `claude-api` skill from ~200k+ tokens to ~25k by loading reference docs on demand
- `/permissions` can now be opened while Claude is working — rule changes apply to the rest of the current turn
- `/add-dir <path>` can now be used while Claude is working; `/add-dir`, `/autocompact`, `/theme`, `/help`, `/config` and `/advisor` dialogs open mid-turn in the fullscreen TUI
- `/goal` now clears itself with a notice when a turn dies on an unrecoverable error (e.g. revoked auth, an exhausted credit balance, or a context overflow) instead of staying armed
- `/goal`: when background tasks keep a goal waiting for 30+ minutes, Claude now checks in on them instead of waiting indefinitely (set `CLAUDE_CODE_GOAL_CHECKIN_MINUTES=0` to opt out)
- `claude setup-token` now rejects unexpected extra arguments instead of silently ignoring them
- Changed Esc in fullscreen mode to no longer clear a mouse text selection: it interrupts or dismisses as usual and the selection stays highlighted
- Removed the redundant “Allowed by auto mode classifier” line that auto mode showed under every Agent tool call
- Removed the “Default teammate model” setting from `/config`; agent-team teammates now use the leader’s model unless the spawn names one
- Dimmed the elapsed-time counter on the running tool header so it no longer competes with the bold counts
- Background task notifications delivered between turns are now sent to the model inside `<system-reminder>` tags, matching mid-turn delivery
- Mantle: skip the admin-pin availability probe at startup when a main-loop model is already picked
- Windows: startup no longer stalls on repeated rename retries when `~/.claude.json` is read-only
[](#2-1-233)
2.1.233
August 14, 2026
- Added GitLab merge request URL support to the `--worktree` flag and the `claude agents` view (where MRs display as `!N`)
- Added an opt-in `forward_user_identity` apps gateway setting on Anthropic upstreams that sends the signed-in user’s identity as headers, so a proxy behind the gateway can attribute spend per user
- Added opt-in memory cgroup support for Bash tool commands on Linux (`CLAUDE_CODE_TOOL_MEMORY_LIMIT`) so a runaway build can’t stall the session
- Added `CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS` environment variable to configure the WebFetch session URL cache TTL (default unchanged: 15 minutes)
- Fixed cloud sessions occasionally being marked as lost when the environment shut down while Claude was waiting on a permission prompt
- Fixed MCP v2 connections endlessly reopening the subscriptions/listen stream against servers that terminate long-held streams on a fixed timeout (e.g. serverless hosts)
- Fixed Notification hooks not firing for permission prompts when running under Claude Desktop or VS Code
- Fixed idle sessions on Linux sometimes keeping one CPU core at 100% when sandboxing is enabled
- Fixed bundled skill aliases like `/checkup` and `/review` reporting “Unknown command” in `-p` mode or with plugins/MCP loaded when a user or project skill shadows the bundled skill
- Fixed skill/command argument substitution to prevent argument values from being re-expanded as template markers
- Fixed Windows paths spelled with the NT `\??\` device prefix bypassing UNC path validation, closing an NTLM credential-leak vector
- Improved `claude self-hosted-runner` session start time: the session branch is now created without rewriting the working tree, and two server round trips no longer block the agent’s launch
- Improved apps gateway error forwarding: 400/413 errors from Vertex, Foundry, and Claude Platform on AWS upstreams now carry the upstream’s own message; fixes a bug with auto-compact on apps gateway
- Improved `claude plugin validate` to check a bare `.claude/skills` directory, reporting SKILL.md files whose frontmatter fails to parse
- Improved screen reader mode: the `/effort` selector renders as a numbered list with a typed-number prompt, and hint and dialog text is no longer clipped
- Improved print mode diagnostics: a `[claude-code:unrecognized_model]` line is written to stderr when a request goes out for a model ID Claude Code doesn’t recognize; map it with `modelOverrides` to silence
- Changed the GitHub app setup tip to no longer appear in repositories whose origin remote is on gitlab.com or bitbucket.org; the enterprise marketplace tip now covers non-GitHub internal git hosts
- Todo/task-tracking tools (TaskCreate/Get/Update/List, TodoWrite) are no longer available on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, and newer models; set `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` to bring them back
- Windows: fixed auto mode repeatedly stopping for manual approval on ordinary `cd <dir> && <command> > file` Bash commands (a 2.1.232 regression)
- Reverted the 2.1.232 Bash permission changes for Cygwin-style symlinks on Windows and for input redirections (`< file`); a narrower version will return in a later release
[](#2-1-232)
2.1.232
August 13, 2026
- Subagent forking is now on by default: a `subagent_type: "fork"` subagent inherits the full conversation and prompt cache, and non-teammate agent spawns in interactive sessions now run in the background by default
- Type `@` in the prompt to mention another Claude session by name; Claude then uses `SendMessage` to reach that session directly
- `SendMessage` now delivers to a bare name that exactly matches one live session, instead of asking to confirm with a ref first
- Interactive sessions on one machine now keep unique names: starting or renaming a session to a name another live session already uses gives it a `name-word-word` variant and tells you
- Added `/config` rows for “Dialog expiry” and “Messages from your other sessions” (cross-session inbound accept/hold/refuse)
- Added secret redaction for GitLab token families (`glrt-`, `gloas-`, `glptt-`, `glagent-`, `glimt-`, `glsoat-`, `glcbt-`, `glft-`, `glffct-`) and full redaction of routable `glpat-`/`gldt-` tokens; the `glab` CLI config store gets the same sandbox and credential-path protection as `gh`
- Added GitLab support to plugin marketplaces: bare `gitlab.com` repo URLs (including nested subgroups) now clone like `github.com` URLs, and clone auth-failure hints name your actual git host
- Settings: `additionalMarketplaces` and `allowedMarketplaces` are now accepted as friendlier aliases for `extraKnownMarketplaces` and `strictKnownMarketplaces`
- Enterprise policy: a url-typed `blockedMarketplaces` entry for a bare repo URL keeps blocking that URL when the CLI classifies it as a git clone
- Gateway: the `desktop:` overlay now accepts every released Desktop setting (was 11 hand-listed keys), validated at boot against Desktop’s own schema; unknown or invalid keys fail boot
- Gateway: empty `managed.policies[].match.groups`/`admin.admin_groups` entries and malformed `email_domain` values (empty, or containing `@`, whitespace, or commas) now fail at boot instead of silently matching no one or granting admin access
- Fable 5 is offered as an advisor in `/advisor` again for organizations with Fable access, with usage-credits consent set up through `/model fable`
- Fixed a PowerShell permission bypass where variable-writing parameters could silently overwrite `$PSDefaultParameterValues` and redirect later commands’ file access
- Fixed a Windows permission bypass where Git Bash followed Cygwin-style symlinks that path validation saw as regular files; writes through them now require permission approval
- Fixed nested git repositories inheriting trust from a parent directory; each repository now requires its own trust confirmation
- Fixed MCP connections hanging for the full 30-second connect timeout when a server fails to answer or sends a malformed reply to the protocol-version probe
- Fixed Remote Control sessions hosted by a bridge inside a cloud session inheriting that session’s transcript or credentials
- Fixed Remote Control sessions started from Claude Desktop or an IDE appearing as a new claude.ai session each time the local session was resumed; they now reattach to the existing one
- Fixed Remote Control sessions appearing unreachable to newly attached clients while idle
- Fixed Remote Control bridge sessions not restoring conversation history when the session worker restarts
- Remote Control: resuming a conversation whose session was deleted from claude.ai or the app now starts a replacement instead of failing with a message about your login (regressed in v2.1.227)
- Fixed Cloud gateway `/login` exiting silently or leaving an unresponsive terminal after “Press Enter to continue” when managed settings failed to load; the reason is now shown
- Fixed voice mode on native builds getting stuck on “listening…” when the voice service rejected the connection; the rejection is now shown immediately
- Fixed mTLS client certificate rotation requiring a restart; Claude Code now reloads the rotated cert and key automatically on connection errors
- Fixed malformed AWS or Vertex region values being used to build request URLs; they now fall back to the default region
- Fixed stream idle timeout errors failing the request instead of recovering on Bedrock, Vertex, and gateway deployments
- Fixed content-sized overlays containing truncated text rendering one column too wide, and start-truncated text collapsing to an ellipsis
- Fixed a stray garbled character where a long shell-command or agent-description preview was cut off mid-emoji
- Fixed a startup race that could silently unregister a plugin marketplace due to concurrent writes to `known_marketplaces.json`
- Fixed `/update` and `/tui` refusing to restart while work that survives the relaunch was running
- Fixed usage-limit guidance suggesting unavailable slash commands in SDK and remote sessions
- Fixed the consent message for interactive `--advisor fable` launches, which told you to run `/model fable` in an interactive session that had just exited
- Improved fullscreen streaming: long sessions stay responsive because the whole conversation is no longer re-normalized on every update
- Improved the managed settings approval dialog: shows endpoint URLs, uses clearer wording for telemetry-only changes, skips routine OpenTelemetry options, and requires approval for server-managed sandbox binary overrides (`sandbox.bwrapPath`, `sandbox.socatPath`, `sandbox.ripgrep`)
- `/feedback` and `/bug` now open immediately when invoked while Claude is responding, instead of waiting for the turn to finish
- `/plugin install plugin@marketplace` now refreshes the marketplace first, so newly published plugins install without a manual marketplace update
- `/code-review` at high, xhigh, and max effort now runs in a background agent like the other levels
- Pasted and clipboard images are read without blocking the event loop
- Remote Control now keeps reconnecting for about 30 minutes after a network blip and no longer drops after a few blips spread across an hour
- Remote Control: resuming a conversation no longer silently takes Remote Control away from another Claude Code on the same machine that still has it; run `/remote-control` there to move it
- Updated agent panel: completed subagents hide immediately with a `/tasks` footer hint, and the ”↓ N more” overflow indicator moved left for visibility
- Remote Control: the terminal now says whether a session was taken over by another device, ended from another app, or deleted, and stops suggesting a reconnect that would undo it
- Bash input redirections (`< file`) are now permission-checked like their argument spellings on all platforms
- Shortened the message shown when resuming a completed background agent
- Cowork sessions no longer inline external @-imports from user-scope memory files
- Hardened the auto-generated cross-session messaging socket directory on shared `/tmp`: a pre-planted symlink or another user’s directory is now refused instead of used
- Hardened the Linux filesystem sandbox against a protected-path bypass
- Changed `sandbox.ripgrep` to be honored only from user, managed, and `--settings` settings; project settings can no longer override the sandbox’s ripgrep binary
- Removed the startup tip suggesting you create custom subagents, and the matching nudge in the `/powerup` tour
[](#2-1-231)
2.1.231
August 13, 2026
- Fixed MCP OAuth sign-in failing with a redirect URI mismatch for servers that use a pre-registered OAuth client, such as Slack
[](#2-1-229)
2.1.229
August 12, 2026
- Documented `claude remote-control --continue` for resuming the most recent Remote Control session
- Added server-supplied Claude Code hook support for self-hosted runner sessions, matching managed-environment behavior
- Added SSE keepalive pings to gateway streaming responses during long thinking pauses, preventing idle-timeout disconnects on Vertex and Bedrock upstreams
- Added plugin marketplace `command` sources: a local command (e.g. an IDE) prints the plugin directory, which is re-resolved each session and applied without a restart; `mode: "link"` uses it in place
- `ListAgents` now marks disconnected Remote Control sessions as `offline` and labels your cloud sessions as `cloud`
- Fixed long responses partly disappearing while streaming and being printed twice in the terminal
- Fixed a crash to the error screen (including on `--resume` of the affected session) when a tool call had a non-string `glob`, `file_path`, or `command` value
- Fixed a RangeError crash when a progress bar or markdown table rendered in a very narrow terminal window (could also crash `claude --continue`/`--resume` at startup)
- Fixed a crash on Windows when a tool call or message referenced a file by an extended-length (`\\?\`) or UNC path
- Fixed auto mode failing on every tool call for users who disable the attribution header via `CLAUDE_CODE_ATTRIBUTION_HEADER` (direct Anthropic API connections)
- Fixed `/model` rejecting Sonnet/Opus 1M for claude.ai subscribers using a custom `ANTHROPIC_BASE_URL` gateway
- Fixed MCP OAuth with strict authorization servers by using `127.0.0.1` instead of `localhost` in the redirect URI
- Fixed Remote Control clients showing a stuck working spinner after a slash command typed in the laptop terminal
- Fixed the Claude Code Review workflow generated by `/install-github-app` completing without posting its review on the pull request
- Fixed multi-second UI stalls after editing a file with thousands of IDE diagnostics while the IDE extension is connected
- Fixed one-shot `claude plugin` commands leaving a stray liveness file that could prevent cleanup of outdated plugin versions
- Fixed dynamic workflows inside CPU-limited containers using the host machine’s core count instead of the container’s CPU limit
- Fixed a file-watcher handle leak after atomic file replacements, and an uncaught error on Windows when the scheduled-tasks watcher failed on a network or virtual filesystem
- Fixed SDK and `--input-format stream-json` sessions getting a 400 API error when a whitespace-only message was submitted
- Fixed conversations whose messages alone exceed the API’s 32 MB request limit retrying compaction when no images or documents can be stripped; they now fail once with a clear message
- Fixed OpenTelemetry export from Claude Desktop sessions being rejected by the Desktop-managed gateway when that gateway is also the telemetry endpoint
- Fixed self-hosted runner and other remote sessions exiting at startup when `managed-mcp.json` is deployed and the server delivers MCP servers; those servers are now skipped with a warning
- Fixed self-hosted runner repository preparation hanging on a Git Credential Manager prompt; git now fails fast when credentials are missing
- Improved workflow fan-outs to stagger same-prefix sibling agents so subsequent agents read the cached prompt prefix instead of re-paying it (`CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS=0` disables)
- Improved “prompt is too long” errors to explain why automatic compaction could not recover instead of only suggesting `/compact`
- Improved sandbox: IPv6 literals in network domain lists are now bracketed (`[::1]:443`), and ambiguous spellings are enforced fail-closed and flagged by `/doctor`
- Updated `/login` to repeat the `CLAUDE_CODE_OAUTH_TOKEN` override warning after a successful login
- Changed `/commit-push-pr` so git/gh commands with dangerous flags (`--force`, `--amend`, `--no-verify`, etc.) are no longer auto-approved
- Changed self-hosted runner Windows startup to require an explicit `--base-dir`; there is no default checkout directory on Windows
- \[VSCode\] “Report a problem” and `/bug` now open the built-in feedback dialog instead of a retired survey link
- \[VSCode\] Made the `/btw` side-question panel resizable by dragging its boundary, in both side-docked and stacked layouts
- \[VSCode\] Added session groups in the sidebar — right-click to create, rename, or delete; Cmd/Ctrl- or Shift-click to move several sessions at once
[](#2-1-228)
2.1.228
August 11, 2026
- Fixed interactive sessions that could stop redrawing entirely, while the process kept running, after a rare internal layout error
- Fixed `git` / Git Bash not being found on Windows when Claude Code is launched from a parent folder of the git installation
- Fixed `/tui` reverting the session to an earlier model when `/model` had been changed since the last response
- Fixed cross-session messaging sometimes starting without an inbox in the first session after install or upgrade
- Fixed Remote Control `/resume` while connected leaking the resumed conversation’s title or history into the connected session
- Fixed `claude self-hosted-runner` sessions failing on every fresh runner when the `checkout` hook fails for a repository the session doesn’t push to; that repository is now skipped with a warning
- Fixed self-hosted runners ending sessions in the gap between a background task finishing and the follow-up turn starting
- Fixed session cleanup deleting contents inside a project’s memory folder
- Fixed background plugin-cache cleanup deleting a plugin’s cache when its only version is a symlinked development checkout
- Fixed a settings-merge issue where a marketplace entry redefined in a higher-precedence settings tier could inherit another tier’s custom headers; marketplace entries now merge as whole entries
- Fixed the deferred-tools reminder occasionally being sent to the model twice after a skill invocation
- Hardened skills synced from claude.ai: they no longer shadow local commands or MCP prompts, their descriptions are sanitized and labeled, and on your machine their bodies don’t run `!` commands or expand `@` files
- Improved cross-session messages: the sender and body now display inline instead of a collapsed line, and messages to Remote Control sessions on other machines show your Remote Control session name as the sender
- Improved Vertex AI credential handling: expired or missing Google Cloud credentials now fail within seconds instead of retrying for minutes
- Improved compaction progress: the retry countdown and stall hint now appear during compaction instead of only a progress bar
- Updated terminal title busy-spinner glyphs to reduce tab-bar jitter on some terminals
- Changed the Write tool so newer models can overwrite an existing file they haven’t read this session, matching the Edit tool’s rules; older models still require the read first
- Removed the outdated note about auto mode sessions costing slightly more from the first-use notice for Pro, Max, and Team plans
[](#2-1-227)
2.1.227
August 10, 2026
- Fixed feature flags being evaluated without the user’s subscription tier when a session started with an expired login token, which could wrongly prompt Max plan users to enable usage credits for Fable
- Fixed every Bash command failing under `claude-code-action` with `allowed_non_write_users` on GitHub-hosted runners
- Fixed `/tui` bringing back a conversation that had been rewound to before its first message
- Improved slash-command menu: blue now marks only the selected row, matched characters are bolded instead of recolored, and emoji or accented names keep their glyphs
- Improved performance: fewer event-loop stalls on file-not-found suggestions and at-mention size checks
[](#2-1-226)
2.1.226
August 8, 2026
- Bug fixes and reliability improvements
[](#2-1-225)
2.1.225
August 8, 2026
- Added gateway spend-limit support to Claude Code’s usage warning; the limit-reached message now names the cap, its reset time, and the operator’s message (requires the gateway on 2.1.225)
- Added a workspace trust prompt to `claude agents` for untrusted directories, matching the behavior of `claude`
- Fixed a transient 401 replacing a long-lived `CLAUDE_CODE_OAUTH_TOKEN` with a stored login’s short-lived token, breaking headless sessions until restart
- Fixed MCP OAuth servers on macOS intermittently failing with a burst of 401 errors, as if never authenticated, after a keychain read timed out
- Fixed auto mode counting a safety-filter refusal of its own permission check toward the consecutive-block limit; the action is still denied, but the model is now told to move on rather than retry
- Fixed cross-session messages staying parked without a notice or expiry in headless sessions and during startup
- Fixed conversation history breaking on Remote Control session resume after very large conversations were compacted
- Fixed hovering over a session in another project in the agents list changing the directory the next agent starts in
- Fixed `claude self-hosted-runner` registering and then failing every session when `--base-dir` cannot be created or written; it now exits at startup with a clear error
- Fixed Claude Code on the web sessions being misreported as stuck, re-sending a growing event backlog on every reconnect
- Improved Remote Control: photos attached from the Claude app are now shown to Claude directly instead of being read from disk with a separate tool call
- \[VSCode\] Fixed Focus view folding away the latest to-do list, a pending question’s context, and settled answers; thinking-only folds show “Thought for Ns” and re-collapse when their turn completes
- SendMessage can now start a conversation with your Remote Control sessions on other machines by name (`ListAgents` shows them as `name [ref]`), instead of only replying after they message you first
- SendMessage: a Remote Control recipient you already confirmed is never swapped for a same-named session on this machine when its own list couldn’t be checked
[](#2-1-224)
2.1.224
August 7, 2026
- Added self-hosted environments: `claude self-hosted-runner` turns your own machines or containers into a place Claude Code web, mobile, and desktop sessions can run, on Team and Enterprise plans
- Added `archive` plugin source: install plugins from a zip over HTTPS without git or npm, with optional SHA-256 pinning
- Added a cancel-and-confirm step when removing an unavailable paste changes a command’s text
- Added `ANTHROPIC_BEDROCK_REGION_PREFIX` env var for Bedrock to prefer a specific cross-region inference profile over the `AWS_REGION`-derived one
- Added `crossSessionInbound` and `dialogExpiry` settings: cross-session messages sent to a session running with bypassed permissions are held for your approval, and messages to other sessions auto-deliver
- Added sandbox credential-masking options: `extract` and `onExtractNoMatch` for structured env values, `decode: "jwt"` with `maskClaims` for JWT-aware masking, and `awsPairs`/`sigv4` for AWS SigV4 re-signing; these need `network.tlsTerminate` and are honored only from user, managed, or `--settings` settings
- Added cross-session `SendMessage`: Claude Code sessions can now message each other, on any of your machines, with `ListAgents` to discover them (macOS and Linux)
- Fixed long (\>200 char) project paths resolving to another project’s session directory under a shared sanitized prefix; session list, rename, fork, delete and `/resume` no longer cross projects
- Fixed `SendMessage` reporting “Message sent” when the write to a teammate’s inbox had actually failed; failed deliveries are now reported as errors
- Fixed sandbox filesystem deny entries written with a trailing slash (e.g. `denyRead: "~/.aws/"`) being silently bypassable on Linux and macOS
- Fixed sandbox violation details never appearing in Bash tool results; Claude now sees which file or network access was denied and why
- Fixed MCP tools that connect mid-turn being deferred for tool search without their names announced to the model
- Fixed plugin install records being silently corrupted when the same plugin is installed in multiple projects
- Fixed recalled or restored paste content occasionally attaching wrong data or silently losing text when the paste had aged out or placeholder numbers collided
- Fixed copy-on-select on Wayland sometimes not reaching the clipboard; the two selection writes no longer race
- Fixed the feedback survey’s transcript share silently failing on long sessions; a failed share now shows an error instead of a success message
- Fixed Remote Control auto-start intermittently failing with “Remote credentials fetch failed” on a cold start with a stale login token
- Fixed Remote Control and SDK clients showing a blank “(no content)” message after `/clear` and other output-less commands
- Fixed a Remote Control session recreated after its server session expired uploading prior local conversation history into the new session
- Improved fullscreen mode to keep the full pre-compaction history in scrollback across repeated compactions, instead of only the most recent interval
- Improved Remote Control: attached web and mobile clients now see compaction progress and the post-compaction boundary instead of a silent pause; `/clear` resets now propagate to attached clients
- Improved Remote Control: connection failures now show a persistent failure indicator with details and a reconnect shortcut, instead of only an 8-second toast
- Removed the 200-subagent-per-session spawn cap; long-running sessions no longer refuse new agents (concurrency and depth limits still apply)
- Changed managed settings: the approval prompt no longer re-appears after re-login or org switching when the organization’s settings are unchanged
- Changed the feedback-survey transcript share: with your consent it now also uploads the last request’s model settings — the system prompt (which includes your `CLAUDE.md` instructions), tool definitions, and model parameters. Secrets are redacted as before, and these fields are dropped first if the share is too large
- Changed the Bash tool description to always note that command output is displayed to the model, not reliably to the user
- Changed recalled paste placeholder numbers to renumber when accepted into the input
- Changed Remote Control to archive the stale server session instead of leaving a dead one listed when a fresh session is minted after compaction or `/resume`
- \[VSCode\] Fixed the extension showing Remote Control as connected after the connection failed
- Fixed a session resume silently reconnecting Remote Control after the user turned it off (`--resume`, SDK hosts, and the VS Code extension)
- \[VSCode\] Fixed sessions not honoring `remoteControlAtStartup` when explicitly enabled
[](#2-1-223)
2.1.223
August 6, 2026
- Added owner wildcard entries (`"owner/*"`) to the `strictKnownMarketplaces` and `blockedMarketplaces` managed settings for allowing or blocking all marketplace repos under a GitHub org
- Added a warning when workflow agents, forked skills, slash commands, or resumed background agents’ requested subagent model is restricted and the parent model runs instead
- Added a `/teleport` hint in cloud sessions showing how to continue locally with `claude --teleport <session id>`
- Fixed a Bash permission bypass where a crafted command could hide parts of itself from permission checks
- Fixed permission prompts so commands padded with tabs or invisible Unicode can no longer hide part of the command from the approval dialog
- Fixed workflow scripts being able to use dynamic `import()` to run code outside the workflow sandbox
- Fixed a permission gap where an agent definition’s `bypassPermissions` mode ignored the org bypass-permissions disable policy
- Fixed resuming a session after a mid-session `/cd` coming back empty
- Fixed gateway model discovery hiding Claude models registered under provider-prefixed IDs such as `vertex_ai/claude-*` or `bedrock/anthropic.claude-*`
- Fixed `modelOverrides` keys that aren’t Anthropic model IDs being treated as the session’s canonical model ID; unknown keys are now ignored as documented
- Fixed managed settings: server-delivered settings no longer disable the env block of a machine-local `managed-settings.json` or MDM profile; admin env now merges per key
- Fixed sandboxed commands failing to start on Linux when `sandbox.filesystem.denyWrite` covers the working directory
- Fixed forked background agents getting stuck “already resuming” for the rest of the session when rebuilding the fork’s parent prompt failed during resume
- Fixed a resumed session failing every turn, or leaving the interactive app on an unresponsive error screen, when its history held a malformed diagnostics attachment
- Fixed a rare hang when parsing unusual `git push` output
- Changed `CLAUDE_CODE_DISABLE_1M_CONTEXT` to hold every Claude model with a native 1M window to 200K via auto-compaction, not just a fixed list; a startup warning now appears when auto-compaction isn’t holding the session to 200K
- Changed auto-compact to keep sessions on unrecognized model IDs within the assumed context window instead of letting them grow past it; set `CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1` to restore the previous behavior
- Changed `/review` to be an alias of `/code-review`, which reviews the current diff or a PR (`/code-review <level> <pr#>`); use `/code-review ultra` for a deep cloud review
- Changed `/code-review` with no effort level to reuse the level you typed last; type a level like `/code-review high` to change it
[](#2-1-222)
2.1.222
August 4, 2026
- Fixed worktree-isolated sessions and their subagents being able to run destructive git commands against the main checkout; isolation now applies to file edits and Bash in every session type
- Fixed PreToolUse auto-allow hooks bypassing tool restrictions in background agent tasks (summaries, compaction, renames)
- Fixed `/usage-credits` on Team and Enterprise showing “you’ve already sent a usage credit request” for members whose earlier request was dismissed, blocking them from sending a new one
- Fixed the startup connectivity check hanging and then failing behind an HTTPS proxy; it now uses the same proxy-aware transport as API requests and times out with a clear message
- Fixed “Connection closed mid-response” errors being reported on responses that had actually completed
- Fixed `/usage` overattributing usage to MCP servers: a server’s share now reflects only the requests that actually consumed its tool results, instead of every turn after any call to it
- Fixed sessions not linking to pull requests created after the branch was pushed, including through the GitHub REST API
- Fixed org-restricted `model: opus`-style subagent and teammate family aliases dropping to the parent model instead of stepping down to the newest org-allowed model in the family
- Fixed stream idle timeout firing on custom `ANTHROPIC_BASE_URL` gateways despite server keep-alive pings arriving on the wire
- Fixed claude.ai connectors being falsely marked as needing authorization when the session token is invalid — they now show a `/login` hint instead
- Fixed tool errors not being displayed for tools no longer available locally, for example after an MCP server is removed
- Fixed `SendMessage` rejecting a long summary — it now truncates instead, so sends no longer fail on a character limit
- Fixed the spinner’s effort label in a subagent’s transcript view showing the session’s effort level instead of the subagent’s own `effort:` setting
- Fixed rare crashes when a file watcher hit a filesystem error or during file-watcher teardown
- Fixed screen readers re-reading the whole input line on every backspace in `--ax-screen-reader` mode — end-of-line deletions now echo just the deleted characters
- Fixed host model-selection keys not taking precedence over a stale on-disk `managed-settings.json` when `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST` is set
- Improved auto mode safety: messages sent to other agent sessions via `SendMessage` are now evaluated by the permission classifier before dispatch
- Improved the refusal when Claude tries to invoke a skill with `disable-model-invocation`: Claude is now told to ask you to run the skill instead of replicating its workflow
- Improved the `/diff` view, the Remote Control workspace diff, and file-edit diffs in Claude Code on the web sessions to use raw git blob content, ignoring workspace-configured diff drivers and textconv
- Changed Remote Control auto-start so repo-local settings (`.claude/settings.json` or `.claude/settings.local.json`) can no longer turn it on (they can still turn it off); enable it at user scope via `/config`
- Removed ultraplan feature
[](#2-1-221)
2.1.221
August 4, 2026
- \[VSCode\] Added Focus view: a chat-menu toggle that hides tool activity behind an expandable per-turn summary with a live running-tool indicator, toggled with `Ctrl+Alt+F` or the “Claude Code: Toggle Focus view” command
- Added `mode: "mask"` for sandbox credential files on Linux and WSL — sandboxed commands read a sentinel copy (the whole file, or just the spans captured by an `extract` regex) while the sandbox proxy substitutes the real value on egress; on macOS file masking falls back to `deny`
- Added warnings to `claude plugin validate` when a marketplace or plugin name would be rejected by Claude Desktop’s managed marketplace sync
- Added a `prompt-audit` subcommand to the `claude-api` skill for auditing prompts and tool descriptions for patterns written for older models
- Fixed a Bash tool permission-check bypass where zsh could execute hidden commands in `[[ ]]` regex conditionals; affected commands now prompt for permission
- Fixed PowerShell permission checks mishandling paths containing quote characters on Windows; such paths now prompt for approval
- Fixed the thinking toggle having no effect for the rest of a session that started with thinking off; disabling an MCP server mid-connect no longer silently reverts
- Fixed MCP servers from `--mcp-config` not being connected before the first turn in print mode (`-p`), which made the model emit tool calls as literal text
- Fixed @-mentioned files being silently dropped when pressing Esc to retract a prompt and resubmitting it
- Fixed a crash when preparing API requests for SDK MCP tools named after built-in object properties such as `constructor`
- Fixed WebSearch failing with a 400 error at effort `xhigh`/`max` when thinking is disabled
- Fixed sandboxed large uploads failing with TLS errors through the sandbox proxy
- Fixed Team and Enterprise spend-limit message incorrectly blaming the org’s monthly limit instead of your individual spend limit
- Fixed Bedrock authentication with AWS SSO named profiles failing in desktop-managed sessions on Windows machines that set a stray `HOME` environment variable
- Fixed `CLAUDE_CODE_RESUME_INTERRUPTED_TURN=0` not disabling interrupted-turn auto-resume; falsy values are now honored
- Fixed a rare wake-from-sleep race where two Claude Code processes could both refresh the same MCP connector or WIF OAuth token at once, forcing re-authentication
- Fixed renaming a session from Claude Code Desktop or claude.ai not updating the CLI’s session name; session names from every rename surface are now sanitized
- Fixed plugin- and org-delivered skills named after terminal-only built-ins (e.g. `/help`, `/feedback`) being un-invocable in non-interactive sessions
- Fixed the “Plugins changed” notification lingering after plugins were reloaded instead of clearing
- Fixed Vim mode: the yank register now survives dialogs, history search, and the transcript view instead of being silently emptied
- Fixed Vim mode: undoing back to an empty prompt now arms the “press ← again” confirm before returning to the agent view
- Improved tool search on Google Vertex AI: re-enabled for Claude 4.5-generation and newer models
- Improved auto mode: permission checks for parallel tool calls are now cache-efficient, and switching modes while a check is pending reliably prompts instead of applying the stale result
- Reduced prompt-cache costs for auto-mode permission checks by reusing the cached conversation prefix across decisions
- Improved Stats panel to count cache tokens in its token totals, with a breakdown by input, output, cache read, and cache write
- Improved `/ultrareview` error messages when a repo shares no history with its base: a checkout with no branches is now refused up front with advice to create one, and refusal hints no longer suggest `git fetch --unshallow` on clones that are already complete
- Improved Windows startup: process creation times are now read via a native kernel32 call instead of spawning PowerShell, so endpoint security tools that gate `powershell.exe` no longer prompt
- Changed background sessions to commit and push to preserve work, open a draft PR only when the task calls for one, follow your CLAUDE.md git instructions, and always end by reporting where the work lives
- Changed `/plugin install` to refresh a stale marketplace catalog and retry before reporting a plugin not found
- Changed plugins installed from `/plugin` to activate immediately when safe, instead of always requiring `/reload-plugins`
- Changed plugins to accept `"."` as a `skills` path, and the root-level `SKILL.md` validation error now suggests using the plugin root
- Changed `/status` to show the session kind: `interactive`, or a background job that is `attached` or `unattended`
- Changed emoji autocomplete to accept common alternate shortcodes like `:thumbsup:`, `:thumbsdown:`, and `:love:`
- Changed sessions forked with `/fork` to create a new worktree of their own instead of working in the original session’s checkout
- Changed Claude in Chrome to close the browser tabs it opens once it no longer needs them
- Changed fast mode to report on the stream when usage credits run out mid-session, instead of failing silently
- Changed Monitor: a watch that exits without producing any output now says so instead of reporting “stream ended”
- Changed the Gateway `model` field validation: non-string values are rejected with a 400 instead of being forwarded
- Removed the repeated “Permission mode changed while the auto-mode classifier call was queued” notice from approval prompts
[](#2-1-220)
2.1.220
July 25, 2026
- Bug fixes and reliability improvements
[](#2-1-219)
2.1.219
July 24, 2026
- Added Claude Opus 5 (`claude-opus-5`), now the default Opus model — 1M context, fast mode at $10/$10/50 per Mtok
- Added `sandbox.network.strictAllowlist` setting to deny non-allowlisted hosts for sandboxed commands without prompting
- Added `DirectoryAdded` hook that fires after `/add-dir` or the SDK `register_repo_root` control request registers a new working directory mid-session
- Added `mcp_server_errors` to the headless stream-json init event, listing `--mcp-config` entries skipped by config validation; terminal runs print a startup warning
- Added the `workflowSizeGuideline` settings key so the advisory Dynamic workflow size guideline can be set from any settings file; the `/config` row is hidden while one does
- Added nested subagent forwarding in stream-json: subagents spawned at depth-2+ now appear when `--forward-subagent-text` is set, keyed by their spawning Agent `tool_use` id
- Fixed `claude -p` text output dropping the answer already produced when a turn dies on a mid-stream API error
- Added HTTP status and error text to `claude mcp list` and `/mcp` when a server fails to connect, and a warning for MCP config values with hidden leading or trailing whitespace
- Fixed the Fable model row showing “Requires usage credits” for plans that include it, when a stale cache had baked the label in
- Fixed the `/model` picker showing the merged Opus row as plain “Opus” instead of “Opus (1M context)”
- Fixed copy-on-select inside GNU screen printing base64 into the terminal instead of copying the selection
- Fixed Remote Control clients keeping a stale fast-mode status after a model switch, reconnect, or failed org check
- Fixed `CLAUDE_CODE_GIT_BASH_PATH` on Windows exiting or being used as bash when the path isn’t a bash/sh binary; it’s now ignored with a warning
- Fixed Vim mode: pressing ← on an empty prompt now returns to the agent view from NORMAL mode, not just INSERT
- Fixed screen-reader mode rewriting the entire input line on every keystroke instead of echoing only the typed character
- Improved the “Remote Control is only available via api.anthropic.com” error to name the specific setting that caused it
- Improved `claude --teleport` to show which repo your current checkout points at when it doesn’t match the session’s repo
- Changed dynamic workflows to default to a medium size guideline (aim for fewer than 15 agents); pick another size or unrestricted with Dynamic workflow size in `/config`
- Changed managed MCP allowlist/denylist `${VAR}` entries to resolve from the startup environment and managed-settings env instead of settings-file env
- Changed the `/model` picker to highlight only the newest model’s name, so the highlight marks the new release rather than an arbitrary subset of the list
- Added the current default workflow size to the running-workflow status line, with a pointer to `/config` for changing it
- Removed Opus 4.7 from fast mode; `/fast` now applies to Opus 5 and Opus 4.8
- Updated the claude-api skill to default to Claude Opus 5, with a migration path from Opus 4.8
- Subagents can now spawn nested subagents up to depth 3 by default (was 1); set CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1 to disable nesting
[](#2-1-218)
2.1.218
July 22, 2026
- Changed `/code-review` to run as a background subagent, so review work no longer fills your conversation and keeps stacked slash commands as its review target
- Added screen-reader announcements of deleted text for word and line deletions (`Option+Delete`, `Ctrl+W`, `Cmd+Backspace`, `Ctrl+U`, `Ctrl+K`) in `--ax-screen-reader` mode
- Fixed Windows paths with `\u`-prefixed segments (like `C:\Users\unicorn`) being corrupted into CJK characters in tool inputs, which made those files inaccessible
- Fixed the left arrow key discarding the conversation with no undo: presses right after editing now ask to confirm, and Esc in the agent view returns to the conversation it backgrounded
- Fixed multi-line paste collapsing into one line with `j` in place of newlines in terminals that encode pasted newlines as Ctrl+J
- Fixed `/context` reporting stale pre-compact token usage after compacting from the message picker
- Fixed `/ultrareview` failing on descriptive arguments like “review my auth changes” — they now run a review of your current branch with the text applied as a note to the findings
- Fixed `/code-review ultra` silently running a local review in non-interactive sessions — it now launches the cloud review
- Fixed gateway spend metering to price Bedrock application-inference-profile ARNs and other config-mapped upstream model IDs at the configured model’s rates
- Fixed mojibake when a long IDE selection was truncated mid-emoji, and a case where a tool executor error could be silently dropped
- Fixed an engine teardown race that could start and abandon a phantom turn, and made input pushed after close consistently rejected
- Fixed spurious “\[Request interrupted by user\]” messages after interrupted tool calls, and an unpaired `tool_use` block left in the transcript when a tool aborted mid-response
- Fixed VoiceOver reading “new line” instead of echoing the typed space at the end of the input in `--ax-screen-reader` mode
- Fixed plugin and settings panels not moving the terminal cursor to the focused row, so screen readers and magnifiers can follow arrow-key navigation
- Fixed crashes (maximum call stack exceeded) when a deeply nested watched directory tree was deleted or moved, and when rendering deeply nested UI trees
- Fixed pull request events occasionally being lost when a session exited immediately after creating or linking a PR
- Fixed the Bedrock setup wizard failing profile verification for assume-role profiles in partitioned AWS regions and on proxy-only networks
- Fixed rare negative or incorrect turn duration measurements after a system clock adjustment by timing turns with a monotonic clock
- Fixed the “N MCP servers need authentication” startup notice over-counting claude.ai connectors that aren’t connected in claude.ai
- Fixed prompt history entries being dropped or duplicated when history writes raced or failed
- Fixed a retry loop that re-sent identical doomed requests after a context-overflow error with a large thinking budget; `Ctrl+B` backgrounding now applies the same background-shell caps as other paths
- Fixed agent frontmatter hooks running from untrusted folders: hooks now require the agent file’s own folder to have accepted workspace trust
- Fixed fork-session lineage being lost after compaction in headless and SDK sessions
- Fixed a resumed session failing every turn, or crashing on resume, when its history held a malformed delta attachment
- Improved `/ultrareview` error feedback so Claude can correct an invalid argument instead of retrying it unchanged
- Improved auto mode: the dangerous-rm, background-`&`, and suspicious-Windows-path checks no longer open permission dialogs; the auto-mode classifier adjudicates them instead
- Improved sandbox command restrictions for IDE interactions
- Improved trust dialogs to name the repository root the grant covers
- Changed `/deep-research` to start only when invoked manually; Claude no longer launches it on its own
- Changed plan mode with auto to no longer prompt for Bash commands the static analyzer can’t prove read-only; the auto-mode classifier judges them instead
- Added an announcement when fast mode changes as a result of switching models via `/config model=<x>` or Remote Control
- Changed server-managed settings so benign feature and cost toggles no longer trigger the settings-approval prompt
- Changed agent markdown files to reject agent names containing `:`, which is reserved for plugin namespacing
- Changed skills with `context: fork` to run in the background by default; opt out per skill with `background: false`
- Added `yes`/`no`/`on`/`off`/`1`/`0` (case-insensitive) as accepted values for skill and plugin frontmatter booleans, alongside `true`/`false`
- Fixed remote sessions continuing to send heartbeats after their worker was replaced, which left long-lived desktop and IDE processes retrying a rejected request every few seconds forever
[](#2-1-217)
2.1.217
July 21, 2026
- Added emoji shortcode autocomplete in the prompt input: type `:heart:` to insert ❤️, or `:hea` for suggestions — disable with the `emojiCompletionEnabled` setting
- Added warnings when transcript writes are failing (e.g. disk full) or when session saving is off due to an inherited environment variable, instead of losing transcripts silently
- Fixed a memory leak where truncated MCP tool outputs kept the full untruncated result in memory for the rest of the session
- Fixed Windows auto-update failures that could leave `claude.exe` missing; failed updates now restore the preserved executable automatically
- Fixed background session isolation not canonicalizing symlinked working directories, which could let sessions escape their workspace folder
- Fixed auto-compact never triggering for Claude Opus 4.8 on Bedrock and `/compact` failing once over the limit
- Fixed corporate mTLS, TLS-verify, OAuth scope, and proxy settings being ignored in Claude Desktop sessions
- Fixed screen reader mode’s startup announcement being cut off by the first prompt render, and the thinking status row re-rendering every few seconds to update elapsed time and token counts
- Fixed managed settings that set `OTEL_EXPORTER_OTLP_ENDPOINT` not governing all signals — lower-scope signal-specific overrides no longer redirect telemetry away from the managed endpoint
- Fixed `--resume`/`--continue` and `/resume` failing with a TypeError when a transcript has a malformed attachment entry
- Fixed Remote Control sessions not showing a pending permission prompt or dialog to viewers that connected after it appeared
- Fixed background shells sometimes becoming impossible to stop after a session is sent to the background (`/background` or `←`) or when the session exits on a heavily loaded machine, most visible on Windows
- Fixed a `CLAUDE.md` or `SKILL.md` paths frontmatter value with many brace groups OOM-killing or stalling the CLI at startup — brace expansion is now budget-bounded
- Fixed the transcript preview sitting flush against the input area when attaching to a starting background session; it now leaves the same one-line gap as the live layout, so the transcript no longer shifts when the session takes over
- Improved footer PR badge links to be clickable hyperlinks even when terminal support can’t be detected (e.g. over ssh/tmux); set `FORCE_HYPERLINK=0` to opt out
- Changed the login-expiry warning to appear 3 days before expiry instead of 5
- Capped the frontend-design plugin suggestion tip at 3 lifetime impressions instead of repeating indefinitely
- Added a cap on concurrently-running subagents (default 20, override with `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`) so one message can’t fan out unbounded background agents
- Changed subagents to no longer spawn nested subagents by default; set `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` to allow deeper nesting
- Fixed `--max-budget-usd` not stopping background subagents: once the cap is reached, new spawns are denied and running background agents are halted
[](#2-1-216)
2.1.216
July 20, 2026
- Added `sandbox.filesystem.disabled` setting to skip filesystem isolation while keeping network egress control
- Fixed a slowdown in long sessions where message normalization cost grew quadratically with the number of turns, causing multi-second stalls and slow resumes
- Fixed auto mode denying commands with “HTTP 401” classifier errors after the OAuth token expired or rotated mid-session
- Fixed AskUserQuestion telling Claude to continue even when your answer asked it to wait or explain first — free-text answers now get neutral wording
- Fixed Claude Code on the web re-asking the same question and dropping your answer after the session sat idle for a few minutes
- Fixed @-mentions silently attaching nothing after file-modifying hooks, vim dot-repeat of `c`-operators and paste, statusline running twice on resume, and resume-picker hangs on failure
- Fixed resumed background agent sessions reverting to the default agent: the agent’s prompt and tool restrictions are now restored
- Fixed worktree-isolated subagents redirecting git into the shared checkout via `git -C`, `--git-dir`, or `GIT_DIR`/`GIT_WORK_TREE`
- Fixed worktree sessions landing in another project’s leftover worktree when the working directory did not match the selected project
- Fixed background sessions whose worktree has no git repository being undeletable
- Fixed `claude daemon stop --any` potentially terminating an unrelated process via a stale legacy daemon lockfile
- Fixed Esc-Esc at an idle prompt not opening the rewind picker in long-running sessions with background tasks
- Fixed Bash command permission checking for compound statements with redirects inside `&&` lists or negations
- Fixed pressing Ctrl+X twice in the agent list failing to delete a session, and deleted sessions reappearing when their background worker had died
- Fixed background subagents getting cancelled when a high-priority message arrives during their startup window
- Fixed mouse and focus garbage in the terminal while a GUI editor from `/memory`, `/plan`, `/keybindings`, or Ctrl+G is open; `/memory` no longer waits for the editor to close
- Fixed Claude-in-Chrome 403-looping on reconnect when the session’s OAuth token lacks a required scope
- Fixed workflow saves and scheduled-task writes following a symlink at `.claude`, which could redirect writes outside the project
- Fixed MCP re-authenticate revoking working credentials before the new sign-in succeeds, and the reconnect needs-auth message in background sessions pointing at an unusable command
- Fixed read-only commands on Windows accessing network paths without a permission prompt
- Fixed Bash command parsing of non-ASCII characters to match real shell word boundaries
- Fixed PowerShell tool permission validation of commands containing invisible Unicode characters
- Fixed dialogs in fullscreen mode stretching past the right-hand edge of their panel
- Fixed the `/config` settings list in fullscreen mode clipping its keyboard-hint footer
- Fixed the transcript-mode (Ctrl+O) footer hint wrapping on terminals narrower than 104 columns
- Fixed the Prometheus metrics endpoint (`OTEL_METRICS_EXPORTER=prometheus`) emitting invalid `# UNIT` lines
- Fixed skills and commands changed during a session not appearing in the slash menu until restart
- Fixed plugin skills with a `name` frontmatter field losing their plugin prefix in slash-command autocomplete
- Fixed telemetry misreporting permission denials: failed permission-prompt requests no longer count as user rejections, and user interrupts are now reported as user aborts instead of rejections
- Improved the `/fork` confirmation to one line with the new session’s name, `claude attach` id, and a note when the copy shares your checkout
- Improved validation of `git` and `gh` command arguments in the PowerShell tool
- Improved the `/ultrareview` diff-too-large error to show configured limits, measured diff size, and largest contributing files
- Improved `/code-review ultra` empty-diff message to name the exact base ref and suggest passing an explicit base
- Improved the spend limit adjustment prompt to show the server’s reason when a spend limit change is rejected
- `/context` now shows an explicit warning when the conversation exceeds the context window, and a failed `/compact` displays as an error
- `/rewind` no longer restores or deletes files through symlinks or hard links at tracked paths and reports how many paths it skipped
- Background sessions: `/mcp` and `/install-github-app` now park a “needs input” request in the agent view when no client is attached
- Updated the bundled dataviz skill: reordered the default chart palette and fixed guidance that suggested direct labels for four-series charts
- \[VSCode\] Fixed right-to-left text (Arabic, Hebrew, Persian) rendering in the wrong order when mixed with English or code
- Fixed cloud sessions dropping the in-flight message when the session’s container restarts mid-turn — the interrupted turn now re-runs on resume instead of leaving the session unresponsive
[](#2-1-215)
2.1.215
July 19, 2026
- Claude no longer runs the `/verify` and `/code-review` skills on its own; invoke them with `/verify` or `/code-review` when you want them
[](#2-1-214)
2.1.214
July 18, 2026
- Fixed single-segment `dir/**` allow rules like `Edit(src/**)` auto-approving writes to nested `dir/` directories anywhere in the tree instead of only `<cwd>/dir`
- Fixed a permission-check bypass affecting commands run in Windows PowerShell 5.1 sessions
- Fixed Bash permission checks to fail closed on file-descriptor redirect forms that bash parses differently than the permission analyzer
- Fixed Bash permission checks misjudging very long commands — commands over 10,000 characters now always prompt instead of running automatically
- Fixed Bash permission checks treating zsh variable subscripts and modifiers in `[[ ]]` comparisons as inert text — these commands now prompt for approval
- Fixed Bash permission checks to no longer auto-approve certain `help` and `man` commands that could run unsafe options, command substitutions, or backslash paths
- Fixed permission prompts on remote sessions that could proceed before the local confirmation dialog
- Added the EndConversation tool: Claude can end sessions with highly abusive users or jailbreak attempts, as on claude.ai since 2025 — see [https://www.anthropic.com/research/end-subset-conversations](../19-Reference/end-subset-conversations.md)
- Added a periodic progress heartbeat for long-running tool calls that previously went silent
- Added an ISO `modified` timestamp to memory file frontmatter
- Added `message.uuid`, `client_request_id`, and `tool_source` attributes to OpenTelemetry log events for message-level correlation and tool provenance
- Added `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` to configure the 60 KB truncation limit on OpenTelemetry content attributes
- Added reasoning effort to the `subagentStatusLine` payload, so custom agent rows can render model and effort
- Added permission prompts for `docker` commands (including the Podman `docker` shim) carrying daemon-redirect flags (`--url`, `--connection`, `--identity`, and Podman’s remote mode) that previously ran without one
- Fixed a crash when a GrowthBook feature evaluates to null, and a bug where a malformed flag payload could wipe the cached feature flags
- Fixed Bash tool killing the Claude session when a `pkill -f` pattern accidentally matched the CLI’s own process (Linux)
- Fixed unbounded memory growth when `--settings` points at a device file or multi-GB file; oversized (\>2 MiB) settings files now fail at startup with a clear error
- Fixed streaming turns failing with “Socket is closed” behind corporate proxies on Windows
- Fixed stream-json output truncation at exit for slow-reading SDK/pipeline consumers; the exit drain now scales with queued bytes instead of a flat 2s cap
- Fixed scheduled tasks refusing their own configured prompt as untrusted input — the fired prompt is now delivered as the session’s assigned task
- Fixed PowerShell tool commands hanging until timeout when a child process waited on standard input (Windows)
- Fixed Python scripts under the PowerShell tool crashing with UnicodeDecodeError when reading non-UTF-8 data from standard input (Windows)
- Fixed Python scripts run via the PowerShell tool crashing with UnicodeEncodeError on non-ASCII output, and PowerShell 7 error messages containing raw ANSI escape sequences (Windows)
- Fixed the PowerShell tool reporting `where.exe`, `fc.exe`, and `diff.exe` as errors when they return a valid negative answer (Windows)
- Fixed `>` and `>>` under the PowerShell tool on Windows PowerShell 5.1 writing UTF-16LE files that other tools couldn’t read as UTF-8
- Fixed a displaced background daemon deleting its successor’s control socket on shutdown, which made the next client kill the healthy replacement daemon
- Fixed background sessions parked with `←` or `/background` and left idle keeping the background daemon and a worker process alive indefinitely
- Fixed completed background sessions being impossible to remove via `claude rm` or the agent view once the background service had gone idle
- Fixed background sessions dispatched from a non-git folder being impossible to delete from the agents view
- Fixed reopening a stopped background session failing to restore its saved conversation when an unreadable folder exists in the session store
- Fixed the Remote Control “session ready” push notification firing for sessions where Remote Control was not explicitly enabled
- Fixed `/install-github-app` and the `/mcp` settings menu being blocked in agent-view sessions — they’re now refused only in background sessions with no terminal attached
- Fixed plugins enabled via the `--settings` CLI flag not loading (regression since v2.1.181)
- Fixed feature flags going stale in long-running sessions after the OAuth token rotates
- Fixed `/ultrareview` refusing to run in repos with no merge base — it now offers to review all tracked files
- Fixed `claude update` and `claude doctor` hanging silently, and the `/status` System diagnostics section going blank, when a shell-config path is a directory
- Fixed memory frontmatter values being silently truncated at an inline `#` when memory files are saved
- Fixed session cost and token telemetry double-counting on streams that emit multiple cumulative `message_delta` frames
- Fixed a spurious “check your network” warning that appeared while the advisor was thinking
- Fixed hooks with exit code 2 not blocking as documented when the hook’s stdout JSON fails schema validation
- Fixed OTel log events emitted outside the turn’s async context missing the interaction span’s trace context
- Fixed MCP transient errors during prompts/resources refresh clearing the server’s slash commands and resources
- Improved the `claude rc` workspace-trust error in the home directory to say trust there is never saved and to suggest running from a project directory
- Changed single-segment `dir/**` hook `if:` conditions to match only `<cwd>/dir`; write `**/dir/**` for any-depth matching. `deny`/`ask` permission rules keep their any-depth match.
- Changed `file` commands using `-m`/`--magic-file` or `-f`/`--files-from` to require permission instead of being auto-allowed as read-only
- Changed keep-alive connection pooling to disable after a stale-connection error, so retries open a fresh socket
- Changed SessionStart hooks to report source `"fork"` when a session begins as a fork instead of `"resume"`
[](#2-1-212)
2.1.212
July 17, 2026
- `/fork` now copies your conversation into a new background session (its own row in `claude agents`) while you keep working; the in-session subagent it used to launch is now `/subtask`
- Added `claude auto-mode reset` to restore the default auto-mode configuration, with a confirmation prompt (pass `--yes` to skip)
- Added a session-wide limit on WebSearch tool calls (default 200, tunable via `CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION`) to stop runaway search loops
- Added a per-session cap on subagent spawns (default 200, override with `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION`) to stop runaway delegation loops; `/clear` resets the budget
- MCP tool calls running longer than 2 minutes now move to the background automatically so the session stays usable; configure the threshold or disable with `CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`
- Typing `/resume` in the agent view now opens a picker of past sessions — including sessions deleted from the list — and resumes your pick as a background session
- Fixed plan mode auto-running file-modifying Bash commands (e.g. `touch`, `rm`) without a permission prompt or SDK `canUseTool` callback
- Fixed worktree creation following a repository-committed symlink at `.claude/worktrees`, which could create files outside the repository
- Fixed a `continue:false` hook’s halt being dropped when the tool fails or completes mid-stream, and hook infrastructure errors being misreported as user rejections
- Fixed SIGTERM during a running Bash tool orphaning the command’s process tree in print/SDK mode; the CLI now aborts the turn, kills the tree, and exits 143
- Fixed `/background` and `claude --bg` failing with “EUNKNOWN: unknown error, uv_spawn” on Windows when Group Policy blocks PowerShell 5.1; the daemon now prefers PowerShell 7
- Fixed shell mode (`!`) not executing commands containing file paths while the path autocomplete popup was open
- Fixed auto-mode denial notifications rendering broken characters when a long denial reason was truncated mid-emoji
- Fixed Ctrl+J not inserting a newline in the agent view dispatch input on terminals with extended key reporting, and surfaced the newline shortcut in the `?` help overlay
- Fixed `/ultrareview` rejecting PR references like `#123`, `PR 123`, and pasted PR URLs; error hints now name the command you actually typed
- Fixed `/ultrareview <branch>` not fetching the branch from origin when it exists remotely; it now suggests the closest branch name on typos
- Fixed `/ultrareview` skipping the billing confirmation in a new conversation after `/clear`
- Fixed `/ultrareview`’s “not a git repository” error on Claude Desktop now suggesting the project’s repository folder instead of terminal commands
- Fixed hosted (host-managed) sessions failing at startup when repository settings configured mTLS certs, extra CA bundles, or OAuth scopes; these transport settings are now ignored with a warning
- Fixed a spurious “File has not been read yet” error when editing a file that had been read with offset/limit before resuming a session
- Fixed `ExitWorktree` failing with “no active EnterWorktree session” after resuming a session with `--continue`/`--resume` in print/SDK mode
- Fixed the workflow agent grid staying empty for Remote Control clients that join a session mid-run
- Fixed streaming-mode control requests being marked complete before their handler finished, which could lose the request on session restart
- Fixed background sessions created with `/fork` losing their live-parent protection after a state write failure
- Fixed reopening a stopped background session from the agent view failing silently — it now resumes the session, or shows why it can’t and lets you force a restart
- Fixed agent teams: a stopping teammate could send the leader duplicate idle notifications when team initialization re-ran within a session
- Fixed the plan-approval dialog footer splitting “ctrl+g to edit in `<editor>`” apart when the file path is long
- Fixed the welcome banner keeping its old panel widths after a combined width+height terminal resize in fullscreen mode
- Fixed diff previews losing their line numbers and +/- markers in narrow layouts
- Fixed @-mentions attaching nothing after a partial file read, plugin uninstall targeting the wrong marketplace, and false “Command timed out” on exit code 143
- Fixed OpenTelemetry HTTP exports being rejected with 411/400 by Azure Monitor and other endpoints that don’t accept chunked transfer encoding
- Fixed OTLP event log records missing `trace_id`/`span_id` when `TRACEPARENT` is set in SDK/headless mode
- Fixed conversations with many images incorrectly failing with “Request too large” errors, and improved the error message to explain the actual cause
- Fixed web search and web fetch returning “API Error” text as search results or page content when the API was overloaded
- Improved web search and web fetch reliability by retrying 529 errors and rate-limited requests with bounded backoff
- Improved prompt caching: the mid-conversation system block now works behind LLM gateways and custom base URLs (Bedrock, Vertex, 1P)
- Improved background agent attach: cold-attaching now instantly shows the formatted transcript while the session boots, instead of a blank wait
- Reduced token usage in inter-agent messaging: `SendMessage` bodies are no longer duplicated into replayed history and tool results
- Changed `/fork` to name the copy after your prompt when the session has no title, so the row is recognizable in the agent view
- Changed bare `/btw` to reopen the side-question panel on your most recent exchange so you can browse earlier answers
- Changed the `←` footer hint to pulse `N done` for a moment when a background agent finishes while nothing needs your input
- Deprecated the Task tool’s `mode` parameter (now ignored); subagents inherit the parent session’s permission mode by default
- Changed Enterprise `forceLoginMethod` to be enforced for VS Code extension, SDK, `setup-token`, and `install-github-app` logins, not just the terminal
- Changed session transcripts to record the reasoning effort level on each assistant message
- Changed headless/SDK sessions to apply a `set_model` control request mid-turn; the next model round-trip uses the new model instead of waiting for the next turn
- Changed agent view / `claude agents --json`: sessions waiting on a sandbox, MCP-input, or managed-settings prompt now show as “Needs input” instead of “Working”
- Updated the auth status panel title from “Cloud authentication” to “Authentication”
- Corrected an earlier release note (2.1.200): tmux through the 3.6 series lacks synchronized output; newer tmux with support is detected automatically
[](#2-1-211)
2.1.211
July 15, 2026
- Added `--forward-subagent-text` flag and `CLAUDE_CODE_FORWARD_SUBAGENT_TEXT` environment variable to include subagent text and thinking in stream-json output
- Fixed permission previews relayed to chat channels not neutralizing bidirectional-override, zero-width, and look-alike quote characters, so tool inputs cannot visually alter the approval message
- Fixed auto mode overriding a PreToolUse hook’s `ask` decision for unsandboxed Bash — a hook `ask` now floors the decision at a prompt
- Fixed parallel Claude Code sessions all logging out simultaneously after wake-from-sleep when many sessions share one credential store
- Fixed plugin MCP servers not reconnecting after an idle web session woke, leaving MCP calls failing until the next message
- Fixed Claude Code on Vertex and Bedrock attempting the default Opus model at startup and printing a spurious fallback notice when a model is explicitly configured
- Fixed subagents spawned with an explicit model override reverting to the parent’s model when resumed or sent a follow-up message
- Fixed nested `.claude/rules/*.md` files loading even when setting sources exclude project settings
- Fixed file upload validation: filenames ending in a DOS device suffix (`.prn`) or trailing dot are now accepted, and files with multiple hard links are refused
- Fixed file uploads to Claude in Chrome from remote and CLI sessions
- Fixed edits that leave the input as ”?” being silently swallowed and toggling the shortcuts panel
- Fixed a startup hang when the Claude in Chrome extension is enabled but Chrome is not running
- Fixed a 300ms delay revealing async content (Settings tabs, Stats, diff views, and other loading states)
- Fixed reopening a just-stopped background session from the agents view starting a blank conversation under the same session id
- Fixed `/loop` hiding the session from `/resume` after a single use
- Fixed screen reader users losing the audible terminal bell after `/terminal-setup` or onboarding terminal setup
- Fixed background jobs on LLM gateway auth (`ANTHROPIC_AUTH_TOKEN` + `ANTHROPIC_BASE_URL`) coming back “Not logged in” after the daemon respawns them
- Fixed `claude agents` jobs becoming permanently undeletable when git no longer recognizes their worktree — the row now shows why the delete was refused instead of silently reappearing
- Fixed `/clear` not resetting the session cost counter — the statusline’s cost now starts at \$0 after `/clear`
- Fixed Claude in Chrome setup pages failing to open in the browser on Windows
- Fixed headless print-mode sessions on Windows crashing or silently exiting when stdin is unreadable
- Fixed background session titles in the agents view showing the naming model’s refusal text when the prompt contains a link
- Fixed background agents killed by the user auto-respawning, and revived agents re-running stale prompts from old sessions
- Fixed routines with no schedule reporting a next run time in the year 1
- Hardened synced skill/plugin directory naming on Windows and kept CCR web fetch/search proxies working after `/clear`
- Improved terminal layout and rendering performance
- Improved background agent result reporting — Claude now reports the status of still-running agents and waits for the real completion instead of fabricating results
- Improved the memory index over-limit warning to measure only loaded content, excluding frontmatter and HTML comments
- Updated integer environment variables (timeouts, token budgets, retry counts) to accept scientific notation and digit-separator spellings like `1e6` and `64_000`
- Updated documentation links to the current docs sites
- Changed “always allow” permission rules to save at the repository root, so approvals granted in a git worktree persist across sessions and worktrees
- Changed `/usage-credits` to ask for confirmation before sending a request to organization admins
- Changed Vim mode `s` and `S` (substitute char/line) to work in NORMAL mode, matching vim behavior
- \[VSCode\] Updated the Remote Control banner to describe what it does
- Claude in Chrome: hardened file-upload path validation
- Claude in Chrome: `save_to_disk` on screenshot actions now writes the image to disk and returns the path; previously it did nothing
- Fixed a prompt-caching regression on Bedrock, Vertex, Mantle, and Foundry that billed the trailing system context block as fresh input tokens on every request.
[](#2-1-210)
2.1.210
July 14, 2026
- Added a live elapsed-time counter to the collapsed tool summary line so long-running tool calls visibly tick instead of looking stuck
- Added a startup warning for `Write(path)`, `NotebookEdit(path)`, and `Glob(path)` permission rules — use `Edit(path)` or `Read(path)` instead
- Fixed `isolation: 'worktree'` subagents being able to run git-mutating commands against the main repo checkout instead of their own isolated worktree
- Fixed the `ultracode` keyword opt-in firing on non-human-originated input such as webhook payloads and relayed PR comments
- Fixed a rendered text fragment leaking into crash telemetry when a UI component returned content outside a styled text element
- Fixed paste markers leaking into external editors opened from Claude Code, which could appear as stray È/É characters around pasted text
- Fixed `claude attach` sometimes failing with “job not found” or “agent is still starting” errors during session transitions — attach now waits for the daemon to settle, and terminal resizes during a slow attach are applied once it completes
- Fixed a session crash when a tool’s result renderer returned a numeric bigint value or plain text instead of a UI element
- Fixed a hook callback timeout being misreported to the model as a user rejection, which made unattended sessions stop and wait
- Fixed Claude assuming a `cd` took effect after its command was moved to the background; the tool result now states the working directory is unchanged
- Fixed plugin-provided MCP servers being torn down when MCP servers are re-synced mid-session
- Fixed plan approvals without edits being labeled “(edited by user)” and overwriting the plan file with a stale snapshot
- Fixed `/doctor` skipping its auto-mode-default proposal on Bedrock, Vertex, and Foundry, where auto mode no longer needs an opt-in
- Fixed Grep content mode claiming “No matches found” when paginating past the end of results
- Fixed unmatched `$1`/`$2` positional placeholders in skills and commands being silently stripped; they are now preserved verbatim
- Fixed plugin cache writes leaving temp files behind on failure and failing on locked-file renames on Windows and network filesystems
- Fixed background workers crash-looping when a client resets its connection to the background service
- Fixed `claude agents --effort ultracode` not reaching dispatched sessions; the value was silently dropped
- Fixed pressing ← to open the agents view dropping the task tracker when returning to the session
- Fixed the agents dashboard retaining pasted images from abandoned reply drafts after their session was deleted
- Fixed killed background sessions leaving a permanent `git worktree lock` behind; the periodic sweep now releases locks whose owning process is gone
- Fixed SDK MCP servers registered via an `initialize` control request waiting until the next turn to start connecting
- Fixed returning to the agents view from a session leaving overlapping ghost frames with `CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1`
- Fixed late-appearing `.claude/*` symlinks not being reconciled into the sandbox deny-write list
- Hardened the Agent tool against indirect prompt injection via content a subagent read
- Improved the Bash/PowerShell tool message when a command hits its timeout and is auto-backgrounded, so the model can distinguish a hang from an explicit background request
- Improved auto mode: the permission classifier now defaults to Sonnet 5 for external sessions, validated on the session’s first request and pinned for the session
- Improved the bundled dataviz skill’s chart color validation with perceptual OKLab color difference and recalibrated color-blindness thresholds
- Memory writes that leave a MEMORY.md index over its read limit now produce an explicit error instead of silent truncation
- Screen reader mode now announces permission mode changes aloud when cycling modes with Shift+Tab
- The agents footer hint now shows how many background agents are waiting on your input, with a brief color emphasis when the count changes
- Agent view: the session you pressed ← from stays visibly marked even after mouse hover or arrow keys move the selection
- Fable temporarily shows as unavailable in the advisor picker while a server-side issue causing Fable advisor failures is fixed
[](#2-1-209)
2.1.209
July 14, 2026
- Fixed /model and other dialogs being blocked in `claude agents` background sessions (reverts an overly broad guard)
[](#2-1-208)
2.1.208
July 14, 2026
- Added screen reader mode: opt-in plain-text rendering for screen reader users. Run `claude --ax-screen-reader`, set CLAUDE_AX_SCREEN_READER=1, or add “axScreenReader”: true to settings.
- Added `vimInsertModeRemaps` setting: map two-key insert-mode sequences like `jj` to Escape in vim mode
- Added `CLAUDE_CODE_PROCESS_WRAPPER`: agent view and the background service now honor a corporate launcher by running every Claude Code self-spawn through a required wrapper executable
- Added mouse-click support for multi-select menus and “Other” input rows in fullscreen mode
- Changed the Fable 5 usage-credits consent prompt to start with the decline option focused
- Fixed fast mode staying off after switching back to a model that supports it — it now restores automatically when enabled in settings
- Fixed replies typed to a background agent being lost when delivery fails — the text is now saved and delivered when the session restarts
- Fixed background-session attach failing permanently (“Couldn’t start the background daemon”) after an update replaced the binary a running `claude agents` process was launched from
- Fixed the context window (and auto-compact indicator) briefly resetting to 200k after the CLI auto-updates, causing a false “100% context used” when resuming long-context sessions
- Fixed supervised and background sessions crashing when a server closed an HTTP/2 connection with a GOAWAY while requests were in flight
- Fixed truncated stream-json/JSON output and missing result message when piping large responses from `claude -p`
- Fixed `CLAUDE_CODE_MAX_OUTPUT_TOKENS` and similar env vars silently using the mantissa of scientific-notation values (`1e6` became `1`)
- Fixed very large markdown tables stalling rendering or using excessive memory; tables over 200 rows show the first 200 with a ”… N more rows” notice
- Fixed the Edit tool failing on files modified after reading when the target text still matches uniquely
- Fixed Read reporting empty files as “shorter than offset”, Grep silently returning “No files found” for invalid regex patterns, Grep count mode under-reporting totals when paginated, and Glob crashing with an unclear error when the pattern, path, or working directory contained a null byte
- Fixed `apiKeyHelper` script failures being hidden behind a generic 401 after ~10 silent retries; the script’s own error is now shown within 3 attempts
- Fixed Bedrock streaming requests failing with a misleading “Truncated event message received” when a gateway transforms the response — the error now names the content-type and points at the proxy
- Fixed `/upgrade` showing a login flow instead of the upgrade URL when the browser fails to open
- Fixed stream-json input killing the session on blank CRLF or whitespace-only lines from Windows-style SDK hosts
- Fixed headless stream-json sessions hanging permanently when a `control_request` carried a non-string `set_model` payload; the CLI now answers with an error response
- Fixed repeated “No completion record was found” notices on session resume — orphaned background tasks now collapse into a single summary
- Fixed Remote Control clients attaching to a terminal-hosted session not seeing background agents and workflow progress until a task started or stopped
- Fixed the Agent tool launching with no tools when a subagent’s `tools` list resolves to nothing — it now returns a clear error naming the unrecognized entries
- Fixed `/usage` showing stale cached bars over fresher data, and `/mcp` not reclassifying placeholder servers after config edits
- Fixed “Change directory” in SDK hosts (e.g. Claude Desktop) failing with “A turn is in progress” on idle sessions that have a running background task
- Fixed the workflow save dialog showing `~/.claude/workflows/` instead of the `CLAUDE_CONFIG_DIR` location for user-scope saves
- Fixed `/release-notes` adding the viewed notes to the model’s context — “Show all” previously injected the entire changelog into every subsequent request
- Fixed a memory leak in the agent view where pasted images were retained for the screen’s lifetime after sending peek replies
- Fixed SDK sessions losing agents defined via the initialize request when a plugin refresh ran before the client attached
- Fixed several memory leaks in long sessions: MCP stdio server stderr accumulating up to 64 MB per server, LSP documents staying open indefinitely (now LRU with 50-doc cap), async hook output retained after backgrounding, and unbounded growth in headless/SDK sessions from large tool-result payloads
- Fixed a memory blowup when reading files with extremely long single lines using offset/limit — the read now returns a clean error instead of loading the whole line
- Fixed multi-second per-turn slowdowns in sessions with many permission deny/ask rules — rule matchers are now compiled once and cached
- Improved input responsiveness while agent task lists update — task updates no longer re-render the entire UI
- Reduced per-tool-call CPU overhead in print/SDK sessions with many MCP tools by caching tool-pool assembly (up to 7x faster tool rounds at high tool counts)
- Reduced memory usage by bounding the file edit read cache to 16 MB instead of pinning up to 1,000 full files
- Reduced session transcript size (up to 79x in edit-heavy sessions) and bounded checkpoint disk usage by pruning superseded file-history backups
- Reduced memory usage when resuming sessions with background agents or forks spawned from large conversations
- Completed background agents now stay listed in `/tasks` until cleanup instead of vanishing the moment they finish
- Attaching to a stopped background agent now shows its transcript immediately while the session warms up, instead of a blank “Session is starting” screen
- Background sessions: an older daemon no longer silently restarts workers spawned by a newer version onto the older binary
- Agent view: Ctrl+X now deletes renamed-branch worktrees, never destroys unpushed commits, keeps the session row when a worktree is kept, and reused worktree names reset to the current base
- Catastrophic removals (e.g. `rm -rf ~`) in commands containing `$(…)`/backticks/`<(…)` now prompt in `--dangerously-skip-permissions` and auto mode, matching the plain form
- `/install-github-app` and the `/mcp` settings menu no longer open in background sessions
- MCP servers configured with an empty URL now show as “not configured” in `/mcp` instead of a config error
- `/usage` now shows your last-known usage bars with an “as of” note when the usage endpoint is rate-limited, instead of an error screen
- Fixed Bedrock auth failing with “Session token not found or invalid” for AWS SSO profiles whose sso_region differs from the Bedrock region (2.1.207 regression)
[](#2-1-207)
2.1.207
July 11, 2026
- Auto mode is now available without `CLAUDE_CODE_ENABLE_AUTO_MODE` opt-in on Bedrock, Vertex AI, and Foundry; disable via `disableAutoMode` in settings
- Fixed the terminal freezing and keystrokes lagging while streaming responses containing very long lists, tables, paragraphs, or code blocks
- Fixed remote managed settings from a non-interactive run (`claude -p`, the SDK) being permanently recorded as consented without ever showing the security consent dialog
- Fixed spurious prompt-injection warnings triggered by benign system-generated conversation updates
- Fixed the auto-updater overwriting a custom launcher script or symlink at `~/.local/bin/claude` on every release; `/doctor` now reports an externally managed launcher
- Fixed compound commands with `cd` prompting for permission when the only output redirect was to `/dev/null`
- Fixed the transcript jumping above the start of the answer when a response finishes streaming
- Fixed `extensions.worktreeConfig` being left in the repo’s `.git/config` (breaking go-git tools like `tea`) after the last `worktree.sparsePaths` worktree was removed
- Fixed malformed bracket patterns in rules globs, skill paths, `.ignore`, and `.worktreeinclude` breaking file reads, file suggestions, and worktree creation
- Fixed a crash loop in agent teams where a malformed teammate mailbox message caused repeated errors every second until the mailbox file was manually deleted
- Fixed background sessions auto-named by accepting a plan not showing that name on their agent-view row
- Fixed background sessions that entered a git worktree resuming blank after a cold reopen from the agent list
- Fixed Remote Control task status updates being lost when the connection recovered from a network interruption or credential refresh
- Fixed Remote Control sessions hosted by the desktop app not showing background agent and workflow progress on mobile and web
- Fixed Deep research runs labeling every Fetch-phase agent “unknown” — chips now show the source hostname
- Fixed Bedrock repeatedly requesting fresh AWS SSO credentials from IAM Identity Center on every API request
- Improved agent view: pasting the same text again now expands the collapsed `[Pasted text #N]` placeholder instead of adding a second one
- Improved agent view: blocked session peeks now lead with the question and show a worded staleness clock (`waiting 3m`) instead of the same timestamp twice
- Changed Bedrock, Vertex, and Claude Platform on AWS to default to Claude Opus 4.8
- Changed auto mode to no longer read `autoMode` from `.claude/settings.local.json` (repo-resident); use `~/.claude/settings.json` instead
- Fixed an indefinite hang on Windows when AWS credential resolution stalls (e.g. a stuck `credential_process`): the 60-second stall guard now fires instead of waiting forever.
- Plugin hooks/monitors/MCP headersHelper: `${user_config.*}` in shell-form commands is now rejected (shell-injection fix). Hooks: use exec form (`args` array) or `$CLAUDE_PLUGIN_OPTION_<KEY>`; monitors and headersHelper: read the value inside the script (config file or the server’s `env` block).
- Plugin option values (`pluginConfigs`) are no longer read from project-level `.claude/settings.json`; only user, `--settings`, and managed settings are honored
- Fixed `/usage-credits` amount inputs silently stripping malformed values (e.g. a pasted timestamp) to digits; malformed amounts are now rejected with an error, and amounts over \$1,000 require a typed confirmation
[](#2-1-206)
2.1.206
July 9, 2026
- Added directory path suggestions to `/cd`, matching `/add-dir` behavior
- Added a `/doctor` check that proposes trimming checked-in `CLAUDE.md` files by cutting content Claude could derive from the codebase
- `/commit-push-pr` now auto-allows `git push` to the repo’s configured push remote (`remote.pushDefault`, or the sole remote when only one is configured) in addition to `origin`
- Gateway: `/login` now supports Anthropic-operated public gateway endpoints
- `EnterWorktree` now asks for confirmation before entering a git worktree outside the project’s `.claude/worktrees/` directory
- Background agents now upgrade to a new version in the background right after a Claude Code update, instead of paying a slow stale-session upgrade when you attach
- Fixed an expired login failing every model with a misleading “There’s an issue with the selected model” error instead of prompting to run `/login`
- Fixed `claude --resume` and `--continue` not responding to keyboard input on startup
- Fixed MCP servers configured via `--mcp-config` or `.mcp.json` ignoring a per-server `request_timeout_ms`, which caused long-running MCP tool calls to time out at the 60s default in fresh sessions
- Fixed `CLAUDE_CODE_EXTRA_BODY` being silently ignored by `claude agents` / `--bg` background workers; the shell-exported override now follows the dispatching session
- Fixed OAuth MCP servers requiring manual re-authentication after a single failed token refresh
- Fixed `--permission-prompt-tool` pointing at an MCP server crashing with “MCP tool not found” on cold start before the server finishes connecting
- Fixed `/model` picker rows printing a price for a different model than the row named, and stopped quoting first-party list prices on providers that don’t bill them
- Fixed server-provided model rows being misplaced in the `/model` picker when an entitlement or allowlist restriction drops the row they were positioned against
- Fixed desktop sessions getting stuck showing “running” after a slash command was sent mid-turn
- Fixed keyboard input being ignored in the agents view when a setup prompt appeared before a bare `claude --resume` on Windows
- Fixed `claude rm` leaving the removed job in the daemon roster, causing the row to reappear in `claude agents`
- Fixed `/remote-control` showing “Unknown command” when logged out — it now explains how to sign in
- Fixed left arrow not stepping back out of a phase or agent in the workflow detail view
- Fixed `/status` listing the same broken-install warning twice
- Fixed false “disused plugin” tips and skewed disuse telemetry for LSP plugins
- Fixed `/doctor`’s update check to compare Homebrew installs against their cask’s channel instead of the settings channel
- Fixed the fullscreen jump-to-bottom pill suggesting Ctrl+End on macOS, not showing rebound chords, and wrapping over the transcript
- Bedrock: fixed a multi-minute startup hang when using an `awsCredentialExport` helper on networks with restricted egress
- Improved `/code-review` findings quality on claude-opus-4-8 across all effort levels
- Improved agents view: status column now uses full terminal width instead of truncating at 64 characters
- Changed agents view: Ctrl+X now permanently removes a completed session, and sessions no longer render twice; deleted background jobs stay deleted
[](#2-1-205)
2.1.205
July 8, 2026
- Added an auto mode rule that blocks tampering with session transcript files
- Fixed `--json-schema` silently producing unstructured output when the schema was invalid, and schemas using the `format` keyword being rejected
- Fixed a message sent while Claude was working being silently lost when the turn ended at the `--max-turns` limit
- Fixed Windows worktree removal deleting files outside the worktree when an NTFS junction or directory symlink existed inside it
- Fixed background agents staying shown as “failed” or “completed” in the agent list after being resumed with `SendMessage`
- Fixed background jobs flipping from “needs input” back to “working” in the agent list when the agent’s turn contained no readable text
- Fixed `claude attach` erroring when a background agent was mid-upgrade restart instead of waiting for it to come back
- Fixed session-to-PR linking missing a PR created in a Bash call whose output exceeded the 30K inline limit
- Fixed `claude mcp add-from-claude-desktop` getting stuck when a server name contains unsupported characters; invalid names are now reported and remaining servers still import
- Fixed a plugin LSP server that fails to initialize preventing a valid LSP server from another plugin handling the same file extension
- Fixed a Windows crash when the directory Claude was launched from is deleted, locked, or unmounted while a command is running
- Fixed a crash when a file watcher was closed while a directory scan was still in flight
- Fixed project verify skills being rewritten on every session instead of only when a documented command changed
- Fixed the agent view rendering one line too high and clipping its header when the job list slightly overflowed the screen
- Fixed background tasks in the web and mobile Remote Control panels showing stale “Running” status by forwarding full task state on every membership change
- Improved auto mode to ask before running `rm -rf` on a variable it can’t resolve from context
- Auto-update binary downloads now stream to disk instead of buffering in memory, cutting the updater’s peak memory usage by roughly 400 MB
- Background task notifications now explicitly state that no human input has occurred, preventing fabricated in-transcript approvals from being acted on
- Improved agent view: sessions that edit, merge, comment on, or push to an existing PR now link it in `claude agents`
- Improved agent view: rows now show a colored state word and a classifier-written headline instead of raw tool call text, and the peek opens with full status including the exact ask for blocked sessions
- `/doctor` is now a full setup checkup that can diagnose and fix issues; `/checkup` is its alias
- Reserved the “Claude Browser” MCP server name (alongside “Claude Preview”) ahead of the Claude Desktop pane rename; user-configured MCP servers can no longer register under either name
- Fixed Cowork VM-mode local-agent sessions failing to start with “Not logged in · Please run /login” on CLI 2.1.203+
[](#2-1-204)
2.1.204
July 8, 2026
- Fixed hook events not streaming during SessionStart hooks in headless sessions, which could cause remote workers to be idle-reaped mid-hook
[](#2-1-203)
2.1.203
July 7, 2026
- Added a warning when your login is about to expire, so you can re-authenticate before background sessions are interrupted
- Added a grey ⏸ badge to the footer when in manual permission mode, making the active mode always visible
- Added the session’s additional working directories to MCP `roots/list`, with `notifications/roots/list_changed` sent when the set changes
- Fixed opening or switching background agent sessions on macOS stalling for 15–20 seconds due to a false low-memory detection (regression in 2.1.196)
- Fixed background sessions becoming permanently unresponsive to attach, replies, and stop when the daemon’s session token went stale — the session now recovers automatically
- Fixed returning to `claude agents` silently stopping running subagents and re-running the prompt from scratch — their work now carries over
- Fixed a memory and per-turn CPU regression in interactive sessions: the context-usage indicator no longer re-analyzes the entire transcript after every turn
- Fixed background agents inheriting a stale `PATH` from the daemon instead of the dispatching shell, causing missing tools on Windows
- Fixed background and agent-view sessions dropping a shell-exported `ANTHROPIC_BASE_URL`, which sent API keys to the default endpoint and failed with 401
- Fixed Bash failing with “argument list too long” in repos with many git worktrees
- Fixed worktree-isolated subagents sometimes running shell commands in the parent checkout instead of their own worktree
- Fixed worktree creation rejecting nested repositories in multi-repo workspaces, leaving background sessions unable to isolate and edit
- Fixed background agents crash-looping when their working directory was deleted, replaced by a file, or became an invalid path — they now fail once with a clear error
- Fixed a background daemon auto-upgrade failure silently killing all running background sessions
- Fixed `TaskStop` and `TaskOutput` failing to find background agents spawned by another agent — errors now list running agents by id and description
- Fixed the `claude agents` composer discarding your typed message when a slash command isn’t available there
- Fixed the agent list crashing when opening a stopped session whose conversation was already open in another session
- Fixed background sessions showing “Needs input” in the agent list after the question was already answered
- Fixed background agent startup failures showing only “exit_with_message” instead of the actual error
- Fixed background sessions ignoring `effortLevel` changes in settings.json when forked through the daemon
- Fixed attached background sessions ignoring `CLAUDE_CODE_DISABLE_MOUSE` and `CLAUDE_CODE_DISABLE_MOUSE_CLICKS` opt-outs
- Fixed `/exit` incorrectly warning about running background agents after all named agents had completed
- Fixed background sessions started from a non-git directory unable to edit files when a `WorktreeCreate` hook was configured
- Fixed the `@` directory picker in `claude agents` not showing registered git worktrees
- Fixed background task output on Windows being permanently replaced by an empty file after `/clear`
- Fixed content jumping when scrolling up through long transcript history
- Fixed the terminal flickering and jumping while typing in bash mode when a shell-history suggestion was shown
- Fixed literal `^[[I` / `^[[O` escape codes being printed when reattaching to a background session
- Fixed LSP-only plugins being incorrectly flagged for disuse when their language servers deliver diagnostics or answer navigation requests
- Improved responsiveness while long responses stream: live-preview updates no longer re-render the whole screen
- Improved subagent behavior: agents are now less likely to re-delegate their entire task to another subagent
- Reduced binary size by ~7 MB and startup memory by ~7 MB by loading a large bundled dependency lazily instead of inlining it
- Changed left arrow to no longer close the background tasks, diff, and workflow detail views — press Esc instead
- Changed the empty `claude agents` view to always show the organized sections (Needs input / Working / Completed) with descriptions
- Removed the startup “claude command missing or broken” warnings — they now appear in `/doctor` and `/status` instead
- Removed a redundant navigation hint from the `claude agents` footer
- \[VSCode\] Added a Settings toggle for “Enable Remote Control for all sessions”
[](#2-1-202)
2.1.202
July 6, 2026
- Added a “Dynamic workflow size” setting in `/config` for controlling how large Claude generally makes dynamic workflows (small/medium/large agent counts) — an advisory guideline, not an enforced cap
- Added `workflow.run_id` and `workflow.name` OpenTelemetry attributes to telemetry emitted by workflow-spawned agents, so a workflow run’s activity can be reconstructed from OTel data
- Fixed a crash in the inline Ctrl+R history search when accepting or cancelling while the search was still scanning the history file
- Fixed `/rename` on background sessions being reverted when the job restarts, which broke addressing the session by its new name
- Fixed transient mTLS handshake failures when settings were re-applied during an in-place client certificate rotation
- Fixed commands sent from Remote Control (mobile/web) into an interactive session failing with “Unknown command”
- Fixed images and files sent from the Remote Control mobile or web app without a caption being silently dropped
- Fixed the sign-in URL printed by `claude auth login` and `claude mcp login --no-browser` not being reliably clickable when it wraps over SSH — it is now emitted as a single hyperlink
- Fixed opening a chat from `claude agents` sometimes failing with “currently running as a background agent” followed by a worker crash/respawn loop
- Fixed workflow scripts with unicode quote escapes in strings being corrupted before parsing; workflow parse errors now show the offending line instead of always blaming TypeScript
- Fixed voice dictation retrying in an unbounded loop when the microphone or audio recorder fails — repeated capture failures now pause voice input
- Fixed `/remote-control` sessions showing the wrong permission mode in the mobile and web apps
- Fixed resuming a session by name, or opening the resume picker, taking minutes and using a large amount of memory in repositories with many git worktrees
- Fixed installer and updater downloads failing immediately with “aborted” when a proxy or network drops the connection mid-download — transient connection drops now retry
- Fixed re-invoking an already-loaded skill appending a duplicate copy of its instructions to context
- Improved `/workflows` agent list layout: wider titles, a dedicated time column, shorter model names, and no per-row tool-call counts
- Improved MCP error messages: clearer error when a server config has `url` but no `type`, suggesting `"type": "http"` instead of the misleading “command: expected string”
- Changed `/review <pr>` back to a fast single-pass review; use `/code-review <level> <pr#>` for the multi-agent review at a chosen effort level
[](#2-1-201)
2.1.201
July 3, 2026
- Claude Sonnet 5 sessions no longer use the mid-conversation system role for harness reminders
[](#2-1-200)
2.1.200
July 3, 2026
- Changed `AskUserQuestion` dialogs to no longer auto-continue by default; opt into an idle timeout via `/config`
- Changed the “default” permission mode to “Manual” across the CLI, `--help`, VS Code, and JetBrains; `--permission-mode manual` and `"defaultMode": "manual"` are accepted alongside `default`
- Fixed a crash at startup when `disabledMcpServers` or `enabledMcpServers` in `.claude.json` is set to a non-array value
- Fixed background sessions silently stopping mid-turn after sleep/wake or when reopening a stalled session
- Fixed background sessions re-running a turn cancelled with Esc after a stall respawn
- Fixed background agents never starting again after a crash left a stale `daemon.lock` whose PID the OS reused
- Fixed background-agent daemon handover so a reinstalled older build can no longer take over the daemon; build recency is now judged by the version’s embedded build timestamp
- Fixed background-agent roster issues: transient corruption permanently disabling orphan cleanup, older binaries not preserving fields written by newer versions, and socket auth tokens being stripped during daemon restarts
- Fixed subagents cut off by a rate limit before producing any text output returning an empty result instead of failing cleanly
- Fixed control bytes from background-agent output reaching the terminal in the agent view
- Fixed `claude agents --plugin-dir <dir>` not showing the plugin’s agents and skills in the agent view when the flag is placed after `agents`
- Fixed project-scoped plugins not loading correctly from git worktrees of the same repository
- Fixed `/mcp` server list not tracking focus for screen readers and magnifiers
- Fixed voice dictation showing a misleading “Voice connection failed” message when a recording captures no audio
- Fixed rendering flicker under tmux 3.4+ by enabling synchronized terminal output
- Improved screen-reader output: decorative glyphs are now hidden, transcript symbols read as short labels, and nested tables read as `Header: value.` lines
- Improved the install script to explain when installation is killed by the system running out of memory
[](#2-1-199)
2.1.199
July 2, 2026
- Stacked slash-skill invocations like `/skill-a /skill-b do XYZ` now load all leading skills (up to 5), not just the first
- Fixed SSL certificate errors (TLS-inspecting proxies, missing `NODE_EXTRA_CA_CERTS`, expired certs) burning retries before showing actionable guidance — they now fail immediately with the fix hint
- Fixed streaming responses being discarded when the API emits a mid-stream overloaded/server error after partial output — the partial is now kept with an incomplete-response notice
- Fixed subagents cut off by a rate limit or server error silently failing instead of returning their partial work to the parent
- Fixed subagents reporting API errors (e.g. usage limit reached) as successful results — the error is now reported to the parent agent
- Fixed the background-agent daemon on Linux killing itself and every running agent every ~50 seconds after an unclean shutdown left a corrupted worker record
- Fixed background agents failing to cold-start over SSH on macOS with “Could not switch to audit session” (regression in 2.1.196)
- Fixed `claude stop` being silently undone when it raced a background-agent respawn — the respawn now honors the stop
- Fixed background job progress indicators stalling for minutes while the job ran long commands
- Fixed background sessions on memory-starved machines showing a generic error — they now indicate low memory and suggest freeing resources
- Fixed remote sessions briefly flapping between Working and Idle in the agent view when a background agent completes
- Fixed idle subagents vanishing from the agent panel while other subagents were still working; surplus idle agents now collapse into an expandable summary row
- Fixed typing `/model` or `/fast` while viewing a subagent silently opening the lead’s model picker — a notice now explains the command applies to the lead
- Fixed `SessionStart`, `Setup`, and `SubagentStart` hooks silently hiding stderr when exiting with code 2 — the error is now shown in the transcript
- Fixed `claude --dangerously-skip-permissions daemon <subcommand>` being treated as a chat prompt instead of running the subcommand
- Fixed `SendMessage` silently misrouting when a re-spawned agent reuses a previous agent’s name — the tool now detects the mismatch and asks the caller to retarget
- Fixed opening or resuming a session with no new messages needlessly growing the transcript file
- Fixed backgrounding a session with `←` or `/background` dropping its `/color` from the agent view row
- Fixed resetting a corrupted config file from the startup recovery dialog destroying it unrecoverably — it now backs up the file first
- Fixed Claude in Chrome repeatedly opening the reconnect page when sessions run from different builds or config directories
- Fixed plan mode not prompting for state-changing browser tool calls; read-only `browser_batch` calls are now correctly auto-allowed
- Transient server rate-limit errors (429s unrelated to your usage limit) are now retried automatically with backoff for subscribers instead of failing the turn
- `CLAUDE_CODE_RETRY_WATCHDOG` now raises the default retry count for non-capacity transient errors to 300 and lifts the cap of 15 on `CLAUDE_CODE_MAX_RETRIES`
- `claude agents` session rows now show pull-request links as bare `#N` without the redundant “PR” label
[](#2-1-198)
2.1.198
July 1, 2026
- Subagents now run in the background by default, so Claude keeps working while they run and is notified when they finish (previously a gradual rollout)
- Claude in Chrome is now generally available
- Added background agent notifications in `claude agents` — sessions that need input or finish now fire the `Notification` hook (`agent_needs_input` / `agent_completed`)
- Added `/dataviz` skill for chart and dashboard design guidance with a runnable color-palette validator
- Gateway: added Claude Platform on AWS (anthropicAws) as an upstream provider; model-not-found responses now advance the failover chain
- Background agents launched from `claude agents` now commit, push, and open a draft PR when they finish code work in a worktree, instead of stopping to ask
- The built-in Explore agent now inherits the main session’s model (capped at opus) instead of running on haiku
- Subagents and context compaction now inherit the session’s extended thinking configuration, improving output quality on delegated tasks
- Fixed brief network drops mid-response aborting the turn — transient errors like ECONNRESET now retry with backoff instead of failing
- Fixed excessive background classifier requests when sandboxed processes repeatedly accessed the same network host
- Fixed background tasks in web, desktop, and VS Code task panels getting stuck on “Running” after they finish or after resuming a session
- Fixed agent teams: a teammate that dies on an API error now reports “failed” to the lead, and messaging a stuck teammate wakes it to retry immediately
- Fixed the `/diff` panel not refreshing when you switch branches or commit outside the session
- Fixed markdown tables overflowing and wrapping their right border when rendered in fullscreen mode
- Fixed Claude Platform on AWS and Mantle sessions dead-ending with “Please run /login” when the STS token expires — `awsAuthRefresh` now runs automatically
- Fixed “no route to host” for local-network hosts in macOS background agent sessions by declaring Local Network entitlements
- Fixed `/desktop` failing with “Cannot determine working directory” after entering and exiting a worktree
- Fixed background agents repeatedly showing “Reconnecting…” every ~52 seconds on macOS while the agents view was open
- Fixed pressing `←` inside `claude attach <id>` exiting to the shell instead of opening the agent view
- Fixed `claude --bg` silently creating an unattachable session when combined with `--print`/`-p`; the conflicting flags are now rejected up front
- Fixed the workflow progress view dropping the earliest agents from the list while the phase counter stayed correct in SDK and desktop-app sessions
- Fixed `.claude/rules/` conditional rules not loading when the target file is reached via a symlinked path
- Fixed Cmd+click not opening URLs in fullscreen mode in Warp on macOS
- Fixed double-click word selection in fullscreen mode to select the entire URL including the scheme
- Fixed plan mode not auto-allowing read-only tool calls when a session starts in plan mode
- Fixed `/branch` deriving its default fork name from the compaction summary instead of the first real prompt
- Improved focus mode: subagents launched in a turn now appear in its activity summary, and completed background notifications fold into a single count
- Improved syntax highlighting accuracy in code blocks, diffs, and file previews by upgrading to highlight.js 11
- Keyboard shortcut hints now show opt/cmd instead of alt/super when connected from a Mac over SSH
- Improved API retry UX: the error reason is now shown after the second attempt, and a status page link replaces the spinner tip when the API is overloaded
- `/login` now opens the sign-in dialog from the `claude agents` view instead of saying it isn’t available
- Subagents now treat messages from the agent that launched them as normal task direction; an agent’s message is still never treated as the user’s approval
- Removed the `/agents` wizard; ask Claude to create or manage subagents, or edit `.claude/agents/` directly
[](#2-1-197)
2.1.197
June 30, 2026
- Introducing Claude Sonnet 5: now the default model in Claude Code, with a native 1M-token context window and promotional pricing of $2/$2/10 per Mtok through August 31. Update to version 2.1.197 for access. [https://www.anthropic.com/news/claude-sonnet-5](../19-Reference/claude-sonnet-5.md)
[](#2-1-196)
2.1.196
June 29, 2026
- Added support for organization default models — admins set it in the org console; it shows as “Org default” (or “Role default”) in `/model` when you haven’t picked one yourself
- Added readable default names for sessions at start, making them easier to identify and message
- Added clickable file attachments in chat — Cmd/Ctrl-click reveals the file in Finder/Explorer
- Security: `claude mcp list`/`get` no longer spawn `.mcp.json` servers that a repo self-approved via a committed `.claude/settings.json`; untrusted workspaces show `⏸ Pending approval`
- Fixed waking a background job permanently deleting its conversation and re-running the original prompt when the transcript probe misread a real transcript; the file is now set aside, never deleted
- Fixed the rate-limit warning flickering off and rate-limit telemetry being over-counted when multiple parallel requests were in flight at the moment a usage limit was hit
- Fixed duplicate recap lines after a background session’s turn: a schema-rejected StructuredOutput attempt no longer renders alongside its retry
- Fixed PowerShell `git diff`/`git grep`, `egrep`/`fgrep`, and quoted search patterns containing `|` being reported as failures when they exit 1, matching Bash behavior
- Fixed multiple `claude agents` side panel issues: keyboard focus getting stuck when opening an agent, background jobs losing their subagent types on every open, and sessions showing incorrect status while actively running
- Fixed `claude agents --dangerously-skip-permissions` silently falling back to auto mode instead of showing the bypass disclaimer and applying bypass mode to spawned agents
- Fixed mid-turn crash recovery for Remote sessions — sessions interrupted by a server restart now auto-resume on the next worker
- Fixed sessions moved with `/cd` reappearing in the old directory’s resume list after a non-graceful exit when the old path contained special characters
- Fixed `claude plugin validate` skipping local plugins whose source is ”.” and stopping after the first error class
- Fixed Esc Esc at an idle prompt not opening the rewind menu (regression); use Ctrl+C or Ctrl+X Ctrl+K to stop background agents
- Fixed MCP OAuth requesting the authorization server’s full `scopes_supported` catalog when no scope is specified, causing `invalid_scope` failures on GitLab self-hosted and other enterprise IdPs
- Fixed `/context` showing 0 tokens for all tool groups on Bedrock
- Fixed `/deep-research` misreporting verifier failures as “all claims refuted” instead of `unverified`
- Fixed plugin dependency version pins not being honored when the marketplace was added as a local folder path backed by a git repo
- Fixed `claude agents` session status: completed rows no longer flip between “Done” and “Needs your input”, stalled agents are now labeled “Needs attention”, and results that mention a PR show a clickable link
- Fixed voice dictation swallowing spaces and spuriously starting a recording during very fast typing when voice mode is enabled
- Improved background session reliability: long-running commands and workflows now survive the session’s process being stopped, restarted, or updated — including on Windows, where background shells are handed off instead of being killed
- Improved background agents: workers killed by a daemon restart are now automatically resumed from where they left off the next time the agents view opens
- Improved `/code-review` workflow: merged five cleanup finders into one, cutting token usage by roughly 25%
- Reduced per-frame rendering work in the terminal UI by skipping no-op subtree walks during streaming
- The streaming idle watchdog is now on by default for all providers — it aborts and retries when a response stream produces no events for 5 minutes. Set `CLAUDE_ENABLE_STREAM_WATCHDOG=0` to disable.
- Remote Control is now disabled when `ANTHROPIC_BASE_URL` points at a non-Anthropic host, matching the existing behavior under `CLAUDE_CODE_USE_BEDROCK`/`_VERTEX`/`_FOUNDRY`
- Changed opening the agents view from a foreground session to require a single `←` press instead of two, matching the behavior in background sessions
[](#2-1-195)
2.1.195
June 26, 2026
- Added `CLAUDE_CODE_DISABLE_MOUSE_CLICKS` to disable mouse click/drag/hover in fullscreen mode while keeping wheel scroll
- Fixed hook matchers with hyphenated identifiers (e.g. `code-reviewer`, `mcp__brave-search`) accidentally substring-matching — they now exact-match. Use `mcp__brave-search__.*` to match all tools from a hyphenated MCP server.
- Fixed voice dictation on macOS capturing silence in long-running sessions after the default input device changes
- Fixed voice dictation auto-submit never firing for languages written without spaces (Japanese, Chinese, Thai)
- Fixed external plugins enabled only by project `.claude/settings.json` not requiring explicit install consent on every loader path
- Fixed `/plugin` Enable/Disable not working when a plugin’s `plugin.json` `name` differs from its marketplace entry name
- Fixed background jobs disappearing from `claude agents` or losing data when written by a newer Claude Code version
- Fixed reopening a crashed background task showing a blank screen for up to 5 seconds instead of its restart
- Fixed background agent daemons running unreachable when the control socket fails to start, blocking restarts
- Improved voice mode on Linux: now distinguishes “no microphone” from “SoX not installed” when SoX is present but no audio capture device exists
- Improved `claude agents` completed list to fill available vertical space; on short terminals the header compacts so live sessions stay visible
- Improved Remote session startup with a provisioning checklist while the container starts
[](#2-1-193)
2.1.193
June 25, 2026
- Added `autoMode.classifyAllShell` setting to route all Bash/PowerShell commands through the auto-mode classifier instead of only arbitrary-code-execution patterns
- Added auto-mode denial reasons to the transcript, the denial toast, and `/permissions` recent denials
- Added `claude_code.assistant_response` OpenTelemetry log event containing the model’s response text. Redacted unless `OTEL_LOG_ASSISTANT_RESPONSES=1`; when that var is unset it follows `OTEL_LOG_USER_PROMPTS`, so deployments that already log prompt content will start receiving response content on upgrade — set `OTEL_LOG_ASSISTANT_RESPONSES=0` to keep prompts-only.
- Added live file path autocomplete to bash mode (`!`)
- Added a startup notice when MCP servers need authentication, pointing at `/mcp`
- Added automatic memory-pressure reaping for idle background shell commands (disable with `CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP=1`)
- Fixed `/model` and other client-data-gated UI showing stale/empty state immediately after `/login`
- Fixed backgrounding (←←) spuriously cancelling with “N background tasks would be abandoned” when all running tasks carry over to the new session
- Fixed pinned background agents being re-prompted to “Continue from where you left off” after every auto-update
- Fixed backgrounding the main turn spawning a phantom “general-purpose (resumed)” subagent that re-ran the main conversation
- Fixed agent panel hiding sibling agents when viewing a subagent
- Improved background agents: the launch result no longer instructs Claude to “end your response” — it keeps working on other tasks while the agent runs
- Improved MCP `headersHelper` auth: the helper now re-runs and reconnects automatically when a tool call returns 401/403
- Improved plugin auto-rename: marketplace `renames` maps are now followed automatically, updating your settings to the new name
- Improved `/add-dir` message when the directory is already a working directory
[](#2-1-191)
2.1.191
June 24, 2026
- Added `/rewind` support for resuming a conversation from before `/clear` was run
- Fixed scroll position jumping to the bottom while reading earlier output during a streaming response
- Fixed background agents resurrecting after being stopped — stopping an agent from the tasks panel is now permanent
- Fixed `/voice` showing a generic “not available” message when disabled by an organization’s policy — it now explains the restriction
- Fixed `/login` URL opening truncated in Windows Terminal when it wraps across lines
- Fixed Cmd+click on links in fullscreen mode for Ghostty over ssh/tmux
- Fixed `claude agents` sending builtin slash commands like `/usage` to background sessions as prompt text instead of showing a hint
- Fixed `claude agents` job rows showing full filesystem paths for pasted images instead of the `[Image #N]` placeholder
- Fixed hooks with comma-separated matchers (e.g. `"Bash,PowerShell"`) silently never firing
- Fixed `/permissions` Recently-denied tab: approving a denial now persists on close instead of being silently discarded
- Fixed the agent panel jumping by one row when scrolling the roster past the overflow cap
- Fixed the welcome splash art overflowing the default 80×24 macOS Terminal window
- Fixed managed settings: `forceRemoteSettingsRefresh` now takes effect when set via MDM or file policy, and the fetch sends `Cache-Control: no-cache` to prevent proxies from serving stale responses
- Improved sandbox network permission dialog: hosts you allow with “Yes” are now remembered for the rest of the session instead of re-prompting on every connection
- Improved MCP server reliability: capability discovery (`tools/list`, `prompts/list`, `resources/list`) now retries transient network errors with short backoff
- Improved MCP OAuth: discovery and token requests now retry once after transient network errors, and headless environments skip the browser popup and go straight to the paste-the-URL prompt
- Improved MCP error messages: HTTP 404 errors now show the URL and point to your MCP config
- Improved vim mode prompt-history search (NORMAL `/`) to hint how to reach slash commands
- Reduced CPU usage during streaming responses by ~37% by coalescing text updates to 100ms
- Reduced long-session memory growth from terminal output cache
[](#2-1-190)
2.1.190
June 24, 2026
- Bug fixes and reliability improvements
[](#2-1-187)
2.1.187
June 23, 2026
- Added `sandbox.credentials` setting to block sandboxed commands from reading credential files and secret environment variables
- Added org-configured model restrictions to the model picker, `--model`, `/model`, and `ANTHROPIC_MODEL`, with a “restricted by your organization’s settings” message when a restricted model is selected
- Added mouse click support to select menus (permission prompts, `/model`, `/config`, etc.) in fullscreen mode
- Fixed `--resume` failing with “No conversation found” when the original `-p` run produced no model turns
- Fixed `--json-schema` and workflow `agent({schema})` structured output: the model can no longer re-call `StructuredOutput` indefinitely after a successful call, and follow-up turns now reliably return structured output
- Fixed remote MCP tool calls that hang with no response for 5 minutes — they now abort with an error instead of blocking indefinitely (override with `CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT`)
- Fixed Claude Code Remote sessions taking ~2.7s longer to start after the agent proxy CA system-trust install was added
- Fixed pasted Korean/CJK text turning into mojibake in terminals that deliver paste as per-byte extended-key events
- Fixed `/update` over Remote Control hanging when a startup trust dialog would have shown
- Fixed background jobs in the agents view getting stuck in “working” indefinitely when the agent ended a turn without producing structured output
- Fixed channel connections dropping after navigating to the agents view and back, and after `/bg`, `/tui`, or `/update`
- Fixed agent stop notifications not correctly attributing who stopped the agent, and improved wording (“finished”/“stopped” instead of “came to rest”)
- Fixed subagent depth tracking: resumed subagents now restore their original spawn depth, and forked subagents now count toward the depth cap
- Fixed leaked agent worktree registrations: locked `.git/worktrees/` entries from killed agents are now cleaned up automatically
- Fixed Cmd+click not opening URLs in fullscreen mode in Ghostty on macOS
- Fixed `claude --help` not listing the `--bg`/`--background` flag
- Fixed Esc, Ctrl-C, and Ctrl-D not working while `/share` is uploading
- Improved `/install-github-app`: GitHub Actions workflow setup is now optional — you can install just the GitHub App and skip the workflow/secret steps
- Improved `/btw` with ←/→ arrow navigation to step through earlier answers
- Improved `/plugin` to surface plugins you haven’t used recently so you can clean them up
- \[VSCode\] Fixed extension becoming unresponsive when resuming a large session
[](#2-1-186)
2.1.186
June 22, 2026
- Added `claude mcp login <name>` and `claude mcp logout <name>` to authenticate MCP servers from the CLI without opening the interactive `/mcp` menu, with `--no-browser` stdin redirect support for completing over SSH
- Added status filtering (press `f`) to the `/workflows` agent detail view
- Added a “Skills” section to the `/plugin` Installed tab
- Added `teammateMode: "iterm2"` setting with a warning when auto mode cannot find the `it2` CLI
- Added “Claude Platform on AWS - refresh credentials” option to `/login` when `awsAuthRefresh` is configured
- `!` bash commands now trigger Claude to respond to the output automatically; set `"respondToBashCommands": false` in settings.json to keep the previous context-only behavior
- Fixed streaming requests failing with “Content block not found” or JSON parse errors after the machine wakes from sleep
- Fixed subagent transcript scroll position bleeding into the main transcript on exit
- Fixed background task previews flashing raw tool names before the agent’s plan loaded
- Fixed Chrome tab-group isolation not applying when the in-product permissions gate is off for concurrent CLI sessions
- Fixed background session recaps being duplicated; the agent’s own end-of-turn summary now shows as the recap line
- Fixed opening a background session from `claude agents` leaving the previous screen painted behind it
- Fixed `Agent(type)` deny rules and `Agent(x,y)` allowed-types restrictions not being enforced for named subagent spawns
- Fixed Esc and Ctrl+C not responding while background agents are still running after the main turn ends
- Fixed misaligned option numbers in permission prompts when the option text overflows
- Fixed pressing `x` on a finished subagent in the agent panel not dismissing it
- Fixed a misleading “MCP server disconnected” notice for intentionally retired tools when resuming older sessions
- Fixed `/plugin` Installed showing a “more above” indicator when already scrolled to the top
- Fixed `~~strikethrough~~` showing literal tildes in assistant messages instead of rendering as strikethrough
- Fixed `--tools` allowing feature-gated tools to slip through before flags loaded on a cold first launch
- Fixed background job status in `claude agents` showing a stale “needs input” message after replying
- Fixed a dark-theme flash when opening a background session from `claude agents` on a light terminal
- Fixed mouse-selected text staying highlighted after deleting it in `claude agents`
- Fixed session cost not showing for usage-based Enterprise and Team subscribers
- Fixed agent teams: teammates spawned via tmux/pane backends now inherit the leader’s `--effort` level
- Fixed Workflow `agent({schema})` subagents looping forever on repeated schema validation failures instead of aborting after 5 attempts
- Improved `claude mcp get` and `claude mcp remove` to suggest the closest configured server name on a typo and truncate long server lists
- Improved memory: the agent is now reminded to compact its `MEMORY.md` index when nearing the size limit
- Improved skill frontmatter: `display-name`, `default-enabled`, `fallback`, and `metadata.*` keys now accept kebab-case, snake_case, and camelCase
- Improved malformed `SKILL.md` YAML frontmatter handling: loads the skill body with empty metadata instead of failing silently
- Changed `CLAUDE_CODE_MAX_RETRIES` to cap at 15; for unattended sessions, use `CLAUDE_CODE_RETRY_WATCHDOG` instead
- Changed background subagents to surface permission prompts in the main session instead of auto-denying; the dialog shows which agent is asking, and Esc denies just that tool
- Changed `/review <pr>` to use the same review engine as `/code-review medium`
[](#2-1-185)
2.1.185
June 20, 2026
- The stream-stall hint now reads “Waiting for API response · will retry in …” instead of “No response from API · Retrying in …”, and triggers after 20s of silence instead of 10s
[](#2-1-183)
2.1.183
June 19, 2026
- Improved auto mode safety: destructive git commands (`git reset --hard`, `git checkout -- .`, `git clean -fd`, `git stash drop`) are now blocked when you didn’t ask to discard local work, `git commit --amend` is blocked when the commit wasn’t made by the agent this session, and `terraform destroy`/`pulumi destroy`/`cdk destroy` are blocked unless you asked for the specific stack
- Added a warning when the requested model is deprecated or automatically updated to a newer model, shown on stderr in print mode (`-p`) and now also covering models set in agent frontmatter
- Added `attribution.sessionUrl` setting to omit the claude.ai session link from commits and PRs in web and Remote Control sessions
- Added `/config --help` to list all available shorthand keys for `/config key=value`
- Changed `/config` toggle behavior: Enter and Space both change the selected setting, and Esc now saves and closes instead of reverting
- Removed the startup “setup issues” line under the logo — run `/doctor` to see configuration issues or use `--debug`
- Fixed `thinking.disabled.display: Extra inputs are not permitted` 400 errors on subagent spawns and session-title generation for affected configurations
- Fixed WebSearch returning empty results in subagents
- Fixed the terminal cursor being stranded above the prompt after navigating history in vim mode with the native cursor enabled
- Fixed fullscreen TUI corruption (statusline mid-screen, duplicated spinner rows, merged text) in Windows Terminal under heavy nested-subagent load
- Fixed turns silently completing with no visible output when the model returned only a thinking block; Claude now re-prompts once
- Fixed user-level skills appearing multiple times in slash-command autocomplete when multiple plugins are enabled
- Fixed MCP servers requiring authentication exposing auth-stub tools to the model in headless/SDK mode
- Fixed tmux teammate panes failing to launch when the shell has slow rc-file initialization, and keystrokes typed during agent spawn leaking into the new tmux pane instead of the leader prompt
- Fixed background tasks started by a teammate being killed when the teammate finishes a turn
- Fixed scheduled task and webhook trigger deliveries being treated as keyboard input; they now classify as task notifications and can no longer approve a pending action or set the session title in auto mode
- Fixed focus mode showing “Ran N PostToolUse hooks” timing lines under each response
[](#2-1-181)
2.1.181
June 17, 2026
- Added `/config key=value` syntax to set any setting from the prompt (e.g. `/config thinking=false`) — works in interactive, `-p`, and Remote Control
- Added `sandbox.allowAppleEvents` opt-in setting that lets sandboxed commands send Apple Events on macOS
- Added `CLAUDE_CLIENT_PRESENCE_FILE` environment variable: point it at a marker file to suppress mobile push notifications while you’re at the machine
- Upgraded the bundled Bun runtime to 1.4
- Improved streaming of long paragraphs: text now appears line-by-line instead of waiting for the first line break
- Improved auto-retry: API connection drops mid-thinking now automatically retry instead of showing “Connection closed while thinking”
- Improved the subagent panel: idle subagents auto-hide after 30s, the list caps at 5 rows with scroll hints, and keyboard hints now show in the footer
- Improved the MCP OAuth browser page to match Claude Code’s visual style and auto-close on success
- Changed fullscreen mode URL opening to require Cmd+click (macOS) / Ctrl+click, matching native terminal behavior
- Changed the `Improved N memories` line to no longer list individual files outside verbose mode
- Fixed prompt caching not reading on custom `ANTHROPIC_BASE_URL` and on Foundry due to a per-request attestation token changing every turn
- Fixed Write/Edit producing 0-byte or truncated files on network drives and cloud-synced folders
- Fixed `open`, `osascript`, and browser-based auth flows failing with error -600 on macOS by adding the Apple Events entitlement
- Fixed a startup regression (~120ms per launch in fresh environments, introduced in 2.1.169): the first prompt no longer waits for the managed-settings fetch when no MCP servers are configured
- Fixed startup blocking with a blank terminal for up to 15 seconds when the account settings fetch is slow on a degraded network
- Fixed startup crash (`TypeError: Cannot read properties of null`) when `.claude.json` contains corrupted null project entries
- Fixed macOS TUI freezing at session start (Ctrl+C unresponsive) when Spotlight is busy reindexing
- Fixed long-running idle sessions losing their history when another Claude Code process ran the 30-day transcript cleanup
- Fixed foreground subagents spawning unbounded nested chains; they now respect the same 5-level depth limit as background subagents
- Fixed `/recap` and conversation forks using the previous model immediately after a model switch
- Fixed subagent “Thinking” duration showing the parent agent’s elapsed time instead of the subagent’s own
- Fixed subagents blocked on a nested agent showing a ticking elapsed time instead of “waiting” in the agent panel
- Fixed the API retry indicator (“Retrying in 0s · attempt N/10”) staying on screen after the retry succeeded
- Fixed AWS `awsCredentialExport` credentials with a short remaining lifetime causing credential refreshes every minute, and now accepts the JSON shape from `aws configure export-credentials`
- Fixed `claude mcp get`/`list` showing `✓ Connected` when tools/list fails; they now show `! Connected · tools fetch failed` with the error detail
- Fixed `/remote-control` leaving a stale “connecting…” line; it now confirms in the transcript once connected
- Fixed ExitWorktree refusing to remove a clean worktree with “Could not verify worktree state” when bare `git` cannot be resolved on Windows
- Fixed settings changes (such as `/effort` or `/model`) failing with ENOENT when `~/.claude/settings.json` is a relative symlink under a symlinked `~/.claude`
- Fixed IDE selection line numbers in context reminders being off by one (IntelliJ and VS Code)
- Fixed Ctrl+C in fullscreen after a native terminal selection (modifier+drag) overwriting the clipboard with the app’s prior selection
- Fixed Ctrl+V showing “No image found in clipboard” instead of pasting when the clipboard contains text
- Fixed agent creation failing with “EEXIST: file already exists” when the agents directory already exists (Windows/OneDrive)
- Fixed AskUserQuestion preview content being cut off at the dialog edge instead of word-wrapping
- Fixed AskUserQuestion multi-select questions silently dropping a typed “Other” free-text answer when submitting
- Fixed `/stats` “Most active day” and daily token chart dates showing one day early in UTC-negative timezones
- Fixed `/copy` and copy-on-select on Linux not detecting a clipboard utility installed after Claude Code started
- Fixed tab-indented code rendering with incorrect indentation in the Write (create-file) preview
- Fixed user prompts queued mid-turn not showing a full-width background highlight in the transcript
- Fixed the activity spinner’s pulse dwelling on the wrong glyph size in Ghostty
[](#2-1-179)
2.1.179
June 16, 2026
- Fixed mid-stream connection drops: partial responses are now preserved instead of showing a raw error, and the spinner no longer gets stuck at “running tool”
- Fixed mouse-wheel scrolling in WSL2 under Windows Terminal and VS Code (regression in 2.1.172)
- Fixed a sandbox `denyRead`/`allowRead` glob over a large directory tree making the Bash tool description enormous and the session unusable on Linux
- Fixed the feedback survey capturing a single-digit reply as a session rating immediately after a turn completes
- Fixed the welcome screen stacking multiple promotional banners — at most one promo now shows per session
- Fixed Ctrl+O not showing the subagent’s transcript when viewing a subagent
- Fixed clicking the prompt input not returning focus from the subagent/footer panel
- Fixed remote session background tasks appearing stuck as “still running” between turns
- Improved plugin loading performance in remote sessions
[](#2-1-178)
2.1.178
June 15, 2026
- Agent teams: removed the `TeamCreate` and `TeamDelete` tools. With `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` set, every session now has one implicit team — spawn teammates directly with the Agent tool’s `name` parameter, no setup step needed. The `team_name` parameter on the Agent tool is still accepted but ignored.
- Added `Tool(param:value)` syntax for permission rules to match a tool’s input parameters (with `*` wildcard), e.g. `Agent(model:opus)` to block Opus subagents
- Skills in nested `.claude/skills` directories now load when working on files there; on a name clash, the nested skill appears as `<dir>:<name>` so both stay available
- Nested `.claude/` directories: the agent, workflow, and output-style closest to the working directory now wins when names collide; project-scope workflow saves now target the closest existing `.claude/workflows/`
- Improved auto mode: subagent spawns are now evaluated by the classifier before launch, closing a gap where a subagent could request a blocked action without review
- Improved `/doctor` with consistent flat tree layout across all sections, clearer section status icons, and highlighted command names
- Improved the skill listing truncation warning to show how many skill descriptions are affected
- Changed the workflow prompt keyword to use a purple shimmer highlight and trigger only on explicit phrases like “run a workflow” or “workflow:”, not on any mention of the word
- Improved Remote Control error messages: connection failures now show a persistent red “/rc failed” indicator in the footer, and the “not yet enabled” error now explains whether it’s a gate, a check failure, stale entitlement, or org policy
- `/bug` now requires a description before submitting, and no longer uses model-refusal text as the GitHub issue title
- Fixed a crash (out-of-memory) when the CLI inherits a stale websocket/OAuth file-descriptor environment variable from a parent process
- Fixed Claude in Chrome silently failing to connect when the OAuth token belongs to a different account than the Claude Code login
- Fixed nested `.claude/skills` skills with directory-qualified names being blocked by permission prompts in non-interactive runs
- Fixed several subagent issues: viewing a subagent’s transcript now shows tool results and live progress, messages sent while it finishes its turn are no longer dropped, and backgrounding a running subagent (ctrl+b) no longer restarts it from scratch
- Fixed `claude agents` workers failing with `401 Invalid bearer token` when the daemon was started from a shell with a custom API gateway via `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN`
- Fixed compaction not honoring `--fallback-model`: compaction now falls back to the configured fallback model chain on overload or model-availability errors
- Fixed model requests continuing to fail with auth errors after credentials were refreshed outside the session, due to a stale cached request configuration
- Fixed background sessions created with `/bg` or `←←` after a turn finished showing “Working” forever in the agents list
- Fixed Linux sandbox failing to start when `.claude/skills` or `.claude/hooks` is a symlink
- Fixed `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1` preventing fresh marketplace installs from cloning
- Fixed MCP server-level specs (`mcp__server`, `mcp__server__*`, `mcp__*`) in subagent `disallowedTools` being silently ignored
- Fixed vim mode undo: `u` now steps through NORMAL/VISUAL-mode commands one at a time instead of merging commands in quick succession into a single undo step
- Fixed statusline links with custom URI schemes (e.g. `vscode://`) not opening when clicked in `claude agents`
- \[VSCode\] Fixed pressing Esc to dismiss a CJK IME candidate window canceling the running Claude task
[](#2-1-176)
2.1.176
June 12, 2026
- Session titles are now generated in the language of your conversation (set the `language` setting to pin a specific language)
- Added `footerLinksRegexes` setting for regex-matched link badges in the footer row, configurable via user or managed settings
- Improved Bedrock credential caching: credentials from `awsCredentialExport` are now cached until their `Expiration` instead of a fixed 1 hour
- Fixed `availableModels` enforcement: alias model picks can no longer be redirected to a blocked model via `ANTHROPIC_DEFAULT_*_MODEL` environment variables, and `/fast` now refuses to toggle when it would switch to a model outside the allowlist
- Fixed auto mode failing on Fable 5 for organizations without Opus 4.8 enabled — the classifier now falls back to the best available Opus model
- Fixed hook `if` conditions for Read/Edit/Write tool paths: documented patterns like `Edit(src/**)`, `Read(~/.ssh/**)`, and `Read(.env)` now match correctly
- Fixed Linux sandbox failing to start when `.claude/settings.json` is a symlink with an absolute target
- Fixed `/copy` and mouse-selection copy not reaching the system clipboard inside tmux over SSH, and tmux paste buffer not loading on versions older than 3.2
- Fixed Remote Control connecting from web/mobile silently switching the session’s model
- Fixed Remote Control disconnect notifications showing a bare numeric code instead of a human-readable reason, and connection failures adding a duplicate line to the conversation transcript
- Fixed Remote Control sessions not disconnecting when you sign in to a different account
- Fixed `/cd` and worktree moves leaving the session reporting the previous directory’s git branch
- Fixed `claude agents`: pressing back in one window no longer detaches other windows attached to the same session
- Fixed backgrounded sessions showing “Working” forever when `/bg` mid-turn had nothing left to continue
- Fixed background agent search by PR URL: PRs opened during scheduled wakeups or while a job was blocked now appear in `claude agents` search
- Fixed the agents view input showing no text cursor on Windows
- Fixed `claude --bg -cn <name>` not seeding the session name
- Fixed background sessions to neutralize Windows network paths in persisted state before respawn
- Fixed background-session respawn rejecting malformed resume IDs from corrupted state files
- Fixed the Windows background-service daemon not starting when `~/.claude/daemon` has the ReadOnly attribute set
- Fixed cloud sessions failing with “Could not resolve authentication method” when idle for too long before being claimed
- Background sessions now show clearer guidance when a window left open across an auto-update can’t submit a reply, and `claude daemon status` explains version-skew behavior
[](#2-1-175)
2.1.175
June 12, 2026
- Added `enforceAvailableModels` managed setting — when enabled, the `availableModels` allowlist also constrains the Default model (a Default that would resolve to a disallowed model now falls back to the first allowed model), and user or project settings can no longer widen a managed `availableModels` list
[](#2-1-174)
2.1.174
June 12, 2026
- Added `wheelScrollAccelerationEnabled` setting to disable mouse-wheel scroll acceleration in fullscreen mode
- Fixed the `/model` picker hiding the model family that Default resolves to — Opus now appears as its own row on Max/Team Premium/Enterprise plans, Sonnet on Pro/Team plans, and Opus on pay-as-you-go API accounts
- Fixed `/model` picker showing a hardcoded Sonnet version label when `ANTHROPIC_DEFAULT_SONNET_MODEL` pins a different Sonnet
- Fixed the “Fable 5 is now consuming usage credits” banner incorrectly showing for enterprise accounts with usage-based billing
- Fixed Bedrock GovCloud regions (`us-gov-*`) deriving the wrong inference profile prefix (`global` instead of `us-gov`), causing 400 errors on derived model IDs
- Fixed background sessions inheriting another session’s `ANTHROPIC_*` provider env (gateway URL, custom headers, `/model` aliases) from the shell that started the background daemon
- Fixed a 1-2 second pause when exiting Claude Code shortly after a shell command was interrupted or killed on macOS and Linux
- Fixed git commit co-author attribution showing an incorrect model name for some models
- Fixed the `/advisor` dialog pre-selecting a saved advisor model that is blocked by the `availableModels` allowlist
- Fixed skill hot-reload re-sending the entire skill listing when a single skill changed; only changed skills are now re-announced
- Fixed Workflow tool `agent()` subagents missing per-agent attribution headers
- \[VSCode\] Added usage attribution to the Account & usage dialog (`/usage`) showing cache misses, long context, subagents, and per-skill/agent/plugin/MCP breakdowns over the last 24h or 7d
- Fixed pre-warmed background workers failing with “Could not resolve authentication method” when claimed after sitting idle
[](#2-1-173)
2.1.173
June 11, 2026
- Fixed Fable 5 model names with a `[1m]` suffix not being normalized — Fable 5 includes 1M context by default, so the suffix is now stripped automatically
- Fixed a spurious “sandbox dependencies missing” startup warning on Windows when sandbox was enabled in settings
[](#2-1-172)
2.1.172
June 10, 2026
- Sub-agents can now spawn their own sub-agents (up to 5 levels deep)
- Amazon Bedrock now reads the AWS region from `~/.aws` config files when `AWS_REGION` isn’t set, matching AWS SDK precedence; `/status` shows where the region came from
- Added a search bar when browsing a marketplace’s plugins in `/plugin`
- Added `model` attribute to the `claude_code.lines_of_code.count` OTEL metric
- Fixed sessions using 1M context without usage credits getting permanently stuck — the session now automatically compacts back under the standard context limit
- Fixed a repeating “an image in the conversation could not be processed and was removed” error when the conversation contained multiple images
- Fixed the agents view keeping a session under Working with a busy spinner for up to 30 seconds after the worker replied
- Fixed background agents potentially reading another directory’s project settings (`.mcp.json` approvals, trust) when dispatched onto a pre-warmed worker
- Fixed background-session attach failing with EAUTH for sessions started on an older version after the daemon auto-updated
- Fixed a background sub-agent staying stuck as “active” in the agent panel after a nested agent it spawned was stopped
- Fixed `/model` suggestions in the `claude agents` dispatch input rendering with a misleading slash prefix and showing models disabled for your org
- Fixed `availableModels` restrictions not being applied to subagent model overrides, the agent dispatch model picker, and the advisor model
- Fixed `availableModels` allowlists hiding the `/model` picker’s Opus and Sonnet 1M rows when entries use version-specific IDs like `claude-opus-4-8`
- Fixed the `/model` picker on Bedrock offering models the provider doesn’t serve — selecting one silently switched the session model and lit the selection marker on multiple rows
- Fixed model IDs getting a doubled 1M-context suffix (e.g. `[1M][1m]`) when `ANTHROPIC_DEFAULT_OPUS_MODEL` already includes one
- Fixed `opusplan` model setting not shipping with 1M context in plan mode for entitled users; the `opusplan[1m]` workaround now also correctly switches to Opus in plan mode
- Fixed `WebFetch(domain:*.example.com)` wildcard domain rules never matching subdomains in allow, deny, and ask position, and file permission rules with mid-pattern wildcards (e.g. `Read(secrets-*/config.json)`) being rejected at startup
- Fixed up-arrow prompt history showing the main agent’s prompts while a subagent’s chat tab is open
- Fixed memory recall not finding mounted team memory stores (`CLAUDE_MEMORY_STORES`) in remote sessions
- Fixed workflow validation rejecting scripts whose prompt strings or comments merely mention `Date.now()`/`Math.random()`
- Disable mouse tracking on Windows consoles that don’t fully support it
- Fixed the `/plugin` marketplace list losing its cursor after backing out of a long plugin list, and Esc from the plugin browser returning to the wrong tab
- Improved performance in long conversations by removing redundant message normalization and avoiding full message-history transforms when streaming tool-use state is unchanged
- Reduced idle CPU usage: `/goal` status chip no longer re-renders the terminal at 5 Hz while idle, and fewer UI re-renders while subagents run in parallel
- Improved Claude in Chrome tool loading: browser tools now load in a single batched call instead of one per tool
- Improved the non-interactive Usage Policy refusal message to suggest starting a new session or changing your model
- `/code-review` now keeps the `ultra` option visible when you’re not signed in to claude.ai, with an explanation that the cloud review requires a claude.ai account
- Shortened the Remote Control footer indicator to “/rc active” and hid it on narrow terminals
- Stopped promoting `/loop` in remote sessions, where pending loops don’t keep the container alive
- \[VSCode\] Fixed PowerShell tool calls rendering as raw JSON instead of a proper command display and permission dialog, and stripped ANSI escape codes from displayed shell output
[](#2-1-170)
2.1.170
June 9, 2026
- Introducing Claude Fable 5: a Mythos-class model that we’ve made safe for general use. Fable’s capabilities exceed those of any model we’ve ever made generally available. Update to version 2.1.170 for access. [https://www.anthropic.com/news/claude-fable-5-mythos-5](../19-Reference/claude-fable-5-mythos-5.md)
- Fixed sessions not saving transcripts (and not appearing in —resume) when launched from the VS Code integrated terminal or any shell that inherited Claude Code environment variables.
[](#2-1-169)
2.1.169
June 8, 2026
- Added `--safe-mode` flag (and `CLAUDE_CODE_SAFE_MODE`) to start Claude Code with all customizations (CLAUDE.md, plugins, skills, hooks, MCP servers) disabled for troubleshooting
- Added `/cd` command to move a session to a new working directory without breaking the prompt cache mid-session
- Added a `disableBundledSkills` setting and `CLAUDE_CODE_DISABLE_BUNDLED_SKILLS` environment variable to hide bundled skills, workflows, and built-in slash commands from the model
- Fixed Up/Down arrows jumping to command history past the wrapped rows of a long input line — they now move through each visual row first, and history recall enters at the near edge
- Fixed enterprise managed MCP policies (`allowedMcpServers`/`deniedMcpServers`) not being enforced on reconnect, IDE-typed configs, `--mcp-config` servers during the first session after install, or before remote settings loaded; also fixed slow cold starts for orgs without remote settings
- Fixed a ~30-50ms UI stall at the start of each turn for macOS users logged in with claude.ai credentials
- Fixed `claude -p` being slow or appearing to hang on Windows while waiting for the slash-command/skill scan (regression in 2.1.161)
- Fixed Remote Control getting stuck on “reconnecting” after resuming a session when an OAuth token refresh happened at the same time
- Fixed Git Credential Manager’s “Connect to GitHub” popup appearing on Windows at startup when background git commands ran without cached credentials
- Fixed footer hints (e.g. “esc to interrupt”) not showing for users with a custom statusline
- Fixed stale permission and dialog prompts reappearing every time you reattached to a remote session whose worker had died while waiting on them
- Fixed `claude agents --json` omitting blocked and just-dispatched background sessions; added `--all` to include completed sessions, plus new `id` and `state` fields
- Fixed agents view leaving a stale/garbled frame after navigating back from an agent on WSL in Windows Terminal
- Fixed background agents ignoring project-level settings `env` values (e.g. `ANTHROPIC_MODEL`) when dispatched onto a pre-warmed worker
- Fixed MCPB plugin cache being spuriously invalidated on Windows, causing unnecessary re-extraction
- Fixed plugin `.in_use` PID lock files accumulating without bound; stale markers from crashed sessions are now swept once per day
- Fixed untrusted project settings being able to set OTEL client-certificate paths without trust confirmation
- `/workflows` now opens immediately even while a turn is in progress
- Improved `TaskCreate` reliability: malformed inputs are repaired automatically and validation errors for unloaded tools include the schema
- Improved the error message shown when your organization has disabled API key authentication, with guidance based on where the active API key comes from
- Reduced CPU usage while responses stream and during spinner animations
- Restored a default 5-minute idle timeout on Vertex/Foundry so a stalled stream aborts instead of hanging indefinitely; set `API_FORCE_IDLE_TIMEOUT=0` to opt out
- Remote-managed settings with an invalid entry now apply their remaining valid policies and surface the validation error, instead of silently dropping the whole payload
- Background sessions now preserve `--ide`, `--chrome`, `--bare`, `--remote-control`, and other flags across retire→wake, and respawn state validation was hardened
- Background sessions are now told that shared-checkout edits are blocked until they enter a worktree, avoiding a wasted rejected edit before `EnterWorktree`
- The “CLAUDE.md is too long” warning threshold now scales with the model’s context window
- Auto-updater on Windows now stops retrying within a session once `claude.exe` is held by another process
- Improved color contrast for skill tags in the slash-command menu
- Promo credit claims for Apple/Google-billed subscribers without a payment method now explain where to add one
- Added a tip suggesting `claude agents` when running multiple concurrent sessions
[](#2-1-168)
2.1.168
June 6, 2026
- Bug fixes and reliability improvements
[](#2-1-167)
2.1.167
June 6, 2026
- Bug fixes and reliability improvements
[](#2-1-166)
2.1.166
June 6, 2026
- Added `fallbackModel` setting to configure up to three fallback models tried in order when the primary model is overloaded or unavailable; `--fallback-model` now also applies to interactive sessions
- Added glob pattern support in deny rule tool-name position (`"*"` denies all tools); allow rules reject non-MCP globs, and unknown tool names in deny rules warn at startup
- Hardened cross-session messaging: messages relayed via `SendMessage` from other Claude sessions no longer carry user authority — receivers refuse relayed permission requests, and auto mode blocks them
- `MAX_THINKING_TOKENS=0`, `--thinking disabled`, and the per-model thinking toggle now disable thinking on models that think by default via the Claude API (3P providers unchanged)
- Claude Code now retries a turn once on the fallback model when the API rejects an unexpected non-retryable error; auth, rate-limit, request-size, and transport errors still surface immediately
- `claude update` now announces the target version before downloading instead of going silent
- `claude agents`: typing a URL into the list now filters to the session whose first prompt contained it
- Fixed a recurring “image could not be processed” error and extra token usage when an unprocessable image was sent in a session
- Fixed remote sessions becoming permanently stuck when a brief backend disruption occurred during worker registration at startup
- Fixed flickering in JetBrains IDE terminals (IntelliJ, PyCharm, WebStorm, etc.) on 2026.1+ by enabling synchronized output
- Fixed Shift+non-ASCII characters (e.g. Shift+ä → Ä) being dropped in terminals using the Kitty keyboard protocol (WezTerm, Ghostty, kitty)
- Fixed PowerShell command validation occasionally hanging far past its time budget on Windows when a killed process’s children held its output pipes
- Fixed orphaned `claude --bg-pty-host` processes spinning at 100% CPU after the daemon dies while connected on macOS
- Fixed voice mode requiring `/login` to clear a stale auth check after toggling `/voice`
- Fixed managed settings with an invalid entry silently disabling enforcement of their remaining valid policies
- Fixed managed-settings `allowedMcpServers`/`deniedMcpServers` predicates not matching when they use `${VAR}` references
- Fixed background agent sessions that entered a git worktree crash-looping with “No conversation found” when reopened from `claude agents`
- Fixed duplicated thinking text in the Ctrl+O transcript view while streaming
- Fixed `/doctor` showing a contradictory failed “Not inside a remote session” check when run inside a remote session
- Fixed the cursor sticking at the end of the first line when typing a multiline prompt in the `claude agents` dispatch and reply inputs
- Fixed blank lines appearing between background agent rows in the task list on terminals without Unicode support
[](#2-1-165)
2.1.165
June 5, 2026
- Bug fixes and reliability improvements
[](#2-1-163)
2.1.163
June 4, 2026
- Added `requiredMinimumVersion` and `requiredMaximumVersion` managed settings — Claude Code refuses to start if its version is outside the allowed range and directs the user to an approved version
- Added `/plugin list` command to list installed plugins, with `--enabled`/`--disabled` filters
- Added a “c to copy” shortcut to `/btw` that copies the raw markdown answer to the clipboard, preserving formatting when pasted elsewhere
- Hooks: Stop and SubagentStop hooks can now return `hookSpecificOutput.additionalContext` to give Claude feedback and keep the turn going without being labeled a hook error
- Skills: added `\$` escape syntax to include a literal `$` before a digit in command bodies
- stdio MCP servers now receive the same `CLAUDE_CODE_SESSION_ID` as hooks/Bash on `--resume`
- Fixed `claude -p` hanging forever after its final result when a backgrounded command never exits — background shells are now stopped ~5s after the result once stdin closes
- Fixed `claude -p` failing with “ANTHROPIC_API_KEY required” on Bedrock/Vertex/Foundry when `CI=true` and no Anthropic API key is set
- Fixed bash commands failing under bazel and EDR-protected Go workflows: `$TMPDIR` was overridden to `/tmp/claude-{uid}` for all commands instead of only sandboxed ones (regression in 2.1.154)
- Fixed Bash commands failing on Windows with “EEXIST: file already exists” on the session-env directory when it has the read-only attribute or is inside OneDrive
- Fixed org-managed permission rules not applying for the entire session when the managed settings fetch completed during startup on a fresh config directory
- Fixed background sessions in `claude agents` losing their running background tasks when reattached after a Claude Code update
- Fixed terminal misalignment and a multi-second hang when exiting the agent view by pressing Esc
- Fixed clicking Stop on a background-task chip in the desktop app not clearing the chip when the underlying process was already gone
- Fixed keyboard input becoming permanently unresponsive after a paste operation whose end marker is dropped by the terminal
- Fixed hook `if: "Bash(...)"` conditions firing on every Bash command containing `$()` or `$VAR`; the pattern now matches against commands inside subshells and backticks too
- Fixed deny rules on home-directory paths (e.g. `Read(~/Desktop/**)`) not blocking Bash commands that reference the path via `$HOME`
- Fixed a stray “(no content)” line left in the transcript after closing panel dialogs like /mcp and /plugins
- Background agent sessions now update to a new Claude Code version in the background, so opening a session after an update no longer waits on a cold restart
- Clearer descriptions for built-in commands and skills in the / menu
- The subscription-switch suggestion now shows in the startup announcement slot instead of a toast
- `claude agents` dispatching from the state-grouped view now starts the session in the directory the agent view was opened from
[](#2-1-162)
2.1.162
June 3, 2026
- `claude agents --json` now includes `waitingFor` showing what a waiting session is blocked on (e.g. permission prompt)
- `--tools`: explicitly listing Grep/Glob now provides the dedicated search tools on native builds with embedded search (previously these names were silently ignored)
- `/effort` now confirms when your chosen level will persist as the default for new sessions
- Clicking a slash command in the autocomplete menu now fills it into your prompt instead of running it immediately; press Enter to run
- Remote Control now shows as a persistent footer pill (with a link to the session) instead of a startup message
- Renamed Windsurf to Devin Desktop in the `/ide` menu, `/terminal-setup`, and `/scroll-speed`, following the editor’s rebrand
- Fixed a silent startup hang when the config directory is read-only or unwritable — Claude Code now starts with in-memory config and surfaces startup errors instead of showing a blank screen
- Fixed WebFetch permission rules not being applied to built-in preapproved domains; explicit `WebFetch(domain:...)` deny/ask/allow rules now take precedence over the preapproved-host auto-allow
- Fixed Windows permission rules never matching when spelled with backslashes (`~\`, `\\server\share`) or case-variant paths, and Read deny rules not hiding files from Glob/Grep results
- Fixed an interrupt (Esc) sent at the very start of a turn being silently dropped in stream-json/SDK sessions, leaving the turn running with no “Interrupted” feedback
- Fixed API 400 `no low surrogate in string` errors for classifier side-queries and MCP server descriptions containing emoji near a truncation boundary
- Fixed MCP per-server `timeout` config values below 1000 ms being floored to a 1-second watchdog that aborted every tool call; sub-1000 ms values are now ignored (falling back to `MCP_TOOL_TIMEOUT` or default), and `claude mcp get` annotates them accordingly
- Fixed the LSP tool’s `workspaceSymbol` operation returning no results; it now accepts a `query` parameter and passes it to the language server
- Fixed `claude agents` cutting live status text (tool args, replies, prompts, exec output) at 60–120 columns on wide terminals; the status detail now uses the full terminal width
- Fixed `claude agents` truncating long session names at 40 columns; the name column now grows with terminal width
- Fixed `claude agents` attach occasionally bouncing straight back to the session list on the first try after a background-service restart
- Fixed `claude agents` Ctrl+V image paste doing nothing in the dispatch input and the session reply box; pasting with no image now shows a hint
- Fixed backgrounding a session with ← silently losing the conversation when the background service cannot start; the session stays in the list as a failed row you can wake with Enter
- Fixed replies from the agents view that fail to send being lost; they are now queued for delivery on the next session start
- Fixed cross-session messaging (`SendMessage`) silently breaking when `CLAUDE_CODE_TMPDIR` or `$TMPDIR` points at a deep directory
- Fixed opening a running background session from `claude agents` stalling for 5 seconds before attaching
- Quieter startup: notices group by severity, and session info and announcements share a single line per launch
- Startup warnings rewritten to be shorter and clearer, each with a concrete fix
- Launch-prompt warnings (deep link/pre-filled prompt) now stay pinned below the input until you act instead of scrolling away
- Failed turns now show a compact warning line instead of a multi-line red error block
- Improved background service startup and `claude update` verification to wait out endpoint-security scanning of new binaries instead of failing after 5 seconds
- Background dispatch spawn failures now report the error class name when no errno is available
- Removed the “Claude in Chrome enabled” and “marketplace installed” startup messages; model auto-updates and the team-onboarding tip now show as quiet notices under the logo
[](#2-1-161)
2.1.161
June 2, 2026
- `OTEL_RESOURCE_ATTRIBUTES` values are now included as labels on metric datapoints, so you can slice usage metrics by custom dimensions like team or repo
- `claude agents` rows now show `done/total` before the detail when work is fanned out; peek shows the longest-running item
- `/mcp` now collapses claude.ai connectors you’ve never signed in to behind a “Show unused connectors” row
- Parallel tool calls: a failed Bash command no longer cancels other calls in the same batch — each tool returns its own result independently
- Fullscreen mode: clipboard now uses `wl-copy`/`xclip`/`xsel` on Linux when available, copies to both the clipboard and PRIMARY selection for middle-click paste, and the “hold `{key}` for native selection” hint now shows the correct key per terminal
- Fixed the `/effort` dialog, workflow animations, and prompt keyword shimmer not honoring the “Reduce motion” setting
- Fixed `forceLoginOrgUUID`/`forceLoginMethod` managed-settings policies blocking third-party provider sessions (Bedrock, Vertex, Foundry, Mantle) alongside the org pin (regression in 2.1.146)
- Fixed background subagent output corrupting `claude -p` stdout when using `--output-format text` or `json`
- Fixed `/usage-credits` starting a re-login for Team and Enterprise admins instead of pointing to the organization’s usage settings page
- Fixed `/autofix-pr` reporting “cannot run on the default branch” when the session is inside a git worktree or another repository
- Fixed `--resume` picker not showing sessions from the current directory when it isn’t a git worktree (e.g., jj workspaces)
- Fixed Windows hooks that invoke bash explicitly (e.g., `/usr/bin/bash script.sh`) failing with “command not found” or “cannot execute binary file”
- Fixed OpenTelemetry log events (`user_prompt`, `api_request`, `tool_result`, `tool_decision`) being silently dropped when emitted before telemetry initialization completed
- Fixed `claude mcp` list/get/add printing secrets to the terminal: `${VAR}` references are no longer expanded, and credential headers and URL secrets are redacted
- Fixed Workflow agents spawned with `isolation: "worktree"` in background sessions being blocked from editing files inside their own worktree
- Fixed background sessions dispatched from `claude agents` booting on a stale model from the daemon’s environment instead of the model in `settings.json`
- Fixed a potential crash when rendering Write tool results after resuming a session
- Fixed completed subagents getting stuck showing as running when an error occurs while finalizing their result
- Fixed `EADDRINUSE` errors from tools that bind Unix sockets under `$TMPDIR` when `CLAUDE_CODE_TMPDIR` is set to a deep path
- Improved terminal rendering performance by stabilizing the layout engine’s JIT compilation profile
- Improved rendering performance for large file writes
- \[VSCode\] Added a tip suggesting disabling terminal GPU acceleration (or running `/terminal-setup`) to fix garbled glyphs
[](#2-1-160)
2.1.160
June 2, 2026
- Added a prompt before writing to shell startup files (`.zshenv`, `.zlogin`, `.bash_login`) and `~/.config/git/`, which could otherwise lead to unintended command execution
- `acceptEdits` mode now prompts before writing build-tool config files that grant code execution (`.npmrc`, `.yarnrc*`, `bunfig.toml`, `.bazelrc`, `.pre-commit-config.yaml`, `.devcontainer/`, etc.)
- Edit no longer requires a separate Read after viewing a file with `grep`: single-file `grep`/`egrep`/`fgrep` commands now satisfy the read-before-edit check
- Fixed copy-on-select not writing to the Windows clipboard on WSL — now uses PowerShell interop instead of OSC 52, which terminals like MobaXterm don’t support
- Fixed restoring a completed session from `claude agents` dropping chat history and re-running the original prompt
- Fixed background sessions re-attached after overnight retire losing their conversation and re-running the original prompt
- Fixed `claude --bg` occasionally failing with “socket missing” when the background daemon was cold-starting on a loaded machine
- Fixed an issue on Windows where the directory a background session was started in could not be deleted after `claude rm` until the background daemon exited
- Fixed background agents that resumed work being shown under Completed in the agents list
- Fixed `claude agents` freezing for several seconds when returning to the session list due to the auto-updater re-checking on every exit
- Fixed Esc, arrow keys, and typing becoming unresponsive on Windows when attached to a background session or in the agent view while the host is under heavy CPU load
- Fixed background agents emitting terminal sync-output markers to terminals that don’t support them (Apple Terminal, tmux), causing render artifacts when entering a running agent
- Fixed mouse wheel scrolling prompt history instead of the transcript right after opening a session from the agents list
- Fixed CJK IME composition appearing at the bottom-left of the screen instead of at the input caret in the `claude agents` view
- Fixed valid `file:///C:/...` links being rewritten to a broken path on Windows terminals with hyperlink support
- Fixed voice mode failing to connect when the project directory or branch name contains non-ASCII or special characters
- Fixed the auto mode unavailability message on third-party providers (Bedrock/Vertex/Foundry) to point to the `CLAUDE_CODE_ENABLE_AUTO_MODE` opt-in instead of incorrectly blaming the model
- Fixed `/effort ultracode` incorrectly blaming the dynamic workflows setting when the model cannot run xhigh; ultracode is no longer offered on models that do not support it
- Fixed model-not-found errors suggesting `--model` when running via the SDK or other hosts where the CLI flag doesn’t apply
- Fixed Claude’s past replies disappearing from scrollback when resuming a brief mode session with brief mode turned off
- Fixed vim mode `p` pasting on the line below instead of at the cursor when the register was yanked with `v$`
- Improved performance of opening recently-inactive background agent sessions in `claude agents`
- Improved auto mode classifier latency by reducing reasoning on routine actions, lowering the chance of “could not evaluate this action” blocks
- Improved background-session teardown (`claude rm`/`stop`, idle reap) to send SIGTERM to running shell subprocesses before SIGKILL, so cleanup handlers run
- Removed `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE`; the environment variable is now a no-op
- Removed the JetBrains plugin install suggestion from startup
- Renamed the dynamic-workflow trigger keyword from `workflow` to `ultracode`. The word “workflow” no longer triggers a run; asking for one in your own words still works. The trigger keyword is highlighted in violet in the prompt input
[](#2-1-159)
2.1.159
May 31, 2026
- Internal infrastructure improvements (no user-facing changes)
[](#2-1-158)
2.1.158
May 30, 2026
- Auto mode is now available on Bedrock, Vertex, and Foundry for Opus 4.7 and Opus 4.8. Opt in by setting `CLAUDE_CODE_ENABLE_AUTO_MODE=1`
[](#2-1-157)
2.1.157
May 29, 2026
- Plugins in `.claude/skills` directories are now automatically loaded, no marketplace required
- Added `claude plugin init <name>` to scaffold a new plugin in `.claude/skills`
- Added autocomplete for `/plugin` arguments: subcommands, installed plugin names, and plugins from known marketplaces
- `claude agents`: the `agent` field in `settings.json` is now honored for dispatched sessions, with `--agent <name>` to override it
- `EnterWorktree` can now switch between Claude-managed worktrees mid-session
- `tool_decision` telemetry events now include `tool_parameters` (bash commands, MCP/skill names) when `OTEL_LOG_TOOL_DETAILS=1`
- Worktrees managed by Claude are now left unlocked when the agent finishes, so `git worktree remove`/`prune` can clean them up
- Fixed unprocessable images (zero-byte, corrupt) attached via paste, MCP, or dialog crashing the request instead of becoming a text placeholder
- Fixed sandbox network permission prompts appearing in auto and bypass-permissions mode when using the desktop app, IDE extensions, or SDK
- Fixed `claude agents` completed sessions not retiring when an idle subagent was still parked or had leaked a backgrounded shell
- Fixed `claude agents` pressing Esc not cancelling a slow “opening…”, leaving the list unresponsive
- Fixed background agent worktrees under `.claude/worktrees/` being orphaned after the 30-day job retention sweep
- Fixed background sessions re-attached after a sleep/wake not telling the model the correct date
- Fixed copy-on-select in `claude agents` not reaching the system clipboard inside tmux with `set-clipboard on` (regression in 2.1.153)
- Fixed `--resume` not reporting background subagents that were running when the previous Claude Code process exited
- Fixed the `--resume` session picker leaving its contents on the terminal after exiting in fullscreen mode
- Fixed `--worktree` and `--worktree --tmux` returning to the canonical repo root instead of the current linked worktree
- Fixed the `/model` picker showing an incorrect “Newer version available” hint when the selected model is already the newest in its family; the pinned-model row now shows the model’s description instead of its raw ID
- Fixed literal markdown markers (backticks, asterisks) appearing in the in-progress message text in fullscreen mode
- Fixed the terminal freezing after approving the managed-settings security dialog at startup
- Fixed a rare duplicate line appearing in scrollback after the terminal UI redraws
- Fixed right-click paste duplicating the clipboard in the VS Code, Cursor, and Windsurf integrated terminals
- WSL: fixed image paste (`alt+v` keybinding), screenshot paste on Windows 11, and added support for dragging images from Windows Explorer
- Improved performance of long and resumed conversations by eliminating redundant message-rendering recomputations
- `/terminal-setup` now disables GPU acceleration in VS Code/Cursor/Windsurf integrated terminals to prevent garbled-text rendering
- The Feature of the Week credit-claim status now appears as a notification in the status area instead of a line above the prompt
- `claude agents`: slash-command autocomplete in the dispatch input now matches substrings
- Removed the “bash commands will be sandboxed” startup banner — sandbox status still shows in `/status` and when a command is blocked
- Removed the “/ide for …” startup hint toast
- \[IDE\] Fixed clicking Stop while a background subagent is running not actually stopping it
- \[VSCode\] Fixed the fast mode indicator not appearing on Opus 4.8
- Pressing backspace right after a workflow trigger keyword now dismisses the workflow request (same as alt+w) instead of deleting a character
- Added a “Workflow keyword trigger” setting in /config to stop the word “workflow” in a prompt from triggering a dynamic workflow
[](#2-1-156)
2.1.156
May 29, 2026
- Fixed an issue when using Opus 4.8 where thinking blocks were modified, leading to API errors.
[](#2-1-154)
2.1.154
May 28, 2026
- Opus 4.8 is here! Now defaults to high effort · /effort xhigh for your hardest tasks
- Introducing dynamic workflows: ask Claude to create a workflow and it orchestrates work across tens to hundreds of agents in the background, so you can take on larger, more complex tasks. Run `/workflows` to view your runs
- Fast mode on Opus 4.8 is now available at a fraction of its previous cost: 2x the standard rate for 2.5x the speed
- The lean system prompt is now the default for all models except Haiku, Sonnet, and Opus 4.7 and earlier
- Claude now reserves the multiple-choice question prompt for decisions it genuinely cannot make itself, instead of asking when it already has enough context to proceed
- `/simplify` now runs a cleanup-only review (reuse, simplification, efficiency, altitude) and applies the fixes, instead of running the full `/code-review --fix` bug-hunting review
- Renamed the `/effort` slider labels from “Speed”/“Intelligence” to “Faster”/“Smarter” for clarity
- `claude agents`: type `! <command>` to run a shell command as a background session you can attach to and detach from. Also available as `claude --bg --exec '<command>'`
- `claude agents`: `/logout` now signs you out instead of being sent to a background session
- `←←` to open the agents view now works on Bedrock, Vertex, Foundry, and with telemetry disabled
- Claude in Chrome: pick which connected browser to use via `/chrome` → “Select browser…”, or in-chat when a browser action runs with multiple connected
- Plugins can now declare `defaultEnabled: false` in `plugin.json` or a marketplace entry; enable them with `/plugin` or `claude plugin enable`. Dependencies of enabled plugins are still enabled automatically
- The `/plugin` Discover tab now pins plugins whose relevance signals match the current directory with a “suggested for this directory” annotation
- Streaming tool execution is now always enabled, including when telemetry is disabled or on Bedrock/Vertex/Foundry (previously behind a feature flag)
- Stdio MCP server subprocesses now receive `CLAUDE_CODE_SESSION_ID` and `CLAUDECODE=1` in their environment
- `claude mcp list`/`get` now show unapproved `.mcp.json` servers as `⏸ Pending approval` instead of auto-approving and connecting when output is piped
- `/remote-control` autocomplete now shows “Disconnect Remote Control” when Remote Control is already active
- Added Claude Opus 4.8 support and 4.7 → 4.8 migration guidance to the `/claude-api` skill
- Deprecated `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE` (will be removed on 06/01). To use fast mode on Opus 4.6, switch with `/model claude-opus-4-6[1m]` and then `/fast on`
- Improved the auto-mode classifier’s detection of data exfiltration, particularly bulk transfers of repository contents
- Fixed `rm -rf $HOME` not being blocked as a dangerous path when `HOME` has a trailing slash
- Fixed `$TMPDIR` resolving to different directories in sandboxed vs unsandboxed Bash commands within the same session
- Fixed unreadable highlighted-row text in `claude agents` when the Claude Code theme doesn’t match the terminal background
- Fixed background-agent completion notifications triggering premature “out of context” behavior on some 1M-context models
- Fixed background-session classifier losing the user’s goal when a scheduled `/command` fires
- Fixed pinned background sessions respawning every minute after a Claude Code update, causing repeated agent-start notifications and process churn at idle
- Fixed background sessions stuck at “blocked”, “running”, or “working” not retiring after the idle grace period
- Fixed subagents in background sessions bypassing the worktree-isolation guard and writing to the shared checkout
- Fixed orphaned `claude --bg-pty-host` processes spinning at 100% CPU after the daemon exits on macOS
- Fixed number key shortcuts not working for options shown below the divider in option dialogs
- Fixed `worktree.baseRef: "head"` resolving to the main checkout’s HEAD instead of the current worktree’s HEAD when spawning subagents or calling `EnterWorktree` from inside a linked worktree
- Fixed a stray leading space on wrapped lines when the previous line ended exactly at the terminal width
- Fixed intermittent terminal rendering corruption in VS Code by capping the number of distinct colors the thinking spinner produces
- Fixed plan file names including `[Image #N]` / `[Pasted text #N]` placeholders when a plan-mode prompt starts with pasted images or text
- Fixed a phantom expand/click affordance on colored tool output: short ANSI-colored lines that fit on screen no longer show a “ctrl+o to expand” hint
- Fixed a single invalid `allowedMcpServers`/`deniedMcpServers` entry in managed settings discarding all managed-settings policy; the bad entry is now dropped with a `claude doctor` warning
- Fixed API 400 errors on models that don’t support the effort parameter when `CLAUDE_CODE_ALWAYS_ENABLE_EFFORT` is set
- Windows: Fixed update failures caused by `claude.exe` being in use showing a generic error instead of telling you to close other sessions and retry
- Removed the stale ”& for background” hint from the shortcuts help panel
- \[VSCode\] Auto mode no longer requires the bypass-permissions setting to appear in the mode picker, and a dismissable notice on the new-session screen explains auto mode the first time it’s active
- Fixed the task panel below the prompt showing a stray unselectable “main” row when only a workflow is running
- Fixed /mcp tools list and tool detail rendering when MCP servers have long or multi-line tool names or long descriptions
- Fixed the /model picker not showing fast mode pricing on the Default option for API (pay-as-you-go) users when fast mode is on
- Fixed auto mode incorrectly blocking actions with “could not evaluate this action” when the safety classifier ran out of output tokens while reasoning
[](#2-1-153)
2.1.153
May 28, 2026
- Added `skipLfs` option to `github`/`git` plugin marketplace sources to skip Git LFS downloads during clone and update
- Claude Code now shows a one-time notice when your npm global install can’t auto-update; `/doctor` lists the fixes
- Status line commands now receive `COLUMNS` and `LINES` environment variables so scripts can size output to the terminal width
- `claude agents`: autocomplete in the dispatch input now suggests native slash commands and bundled skills, not just project skills
- `claude agents`: PR column now shows `PR #N` for a single PR or `N PRs` for multiple
- `claude doctor` now shows the result of your last update attempt
- Combined the separate “needs authentication” startup notifications for MCP servers and connectors into a single message
- macOS: background agents now appear as “Claude Code” in Privacy & Security and keep their permission grants across upgrades
- Fixed stateful MCP servers without the optional GET SSE stream reconnect-looping on `tools/list` (regression in v2.1.147)
- Fixed a regression where a custom API gateway could receive the user’s Anthropic OAuth credential instead of the gateway’s own token
- Fixed subagent (Agent tool) frontmatter MCP servers ignoring `--strict-mcp-config`, `--bare`, remote mode, enterprise managed MCP config, and managed-settings MCP server allow/deny policies
- `--strict-mcp-config` no longer strips inline `mcpServers` from explicitly-passed agent definitions (`--agents` / SDK `agents`), and blocked subagent MCP servers now surface a visible warning
- Fixed the Windows PowerShell installer reporting “Installation complete!” when installation actually failed
- Fixed `claude update` installing the latest version instead of the configured release channel’s version for npm installations
- Fixed excessive memory usage (multiple GB) when resuming a session by transcript file path on machines with many stored sessions
- Fixed `claude agents` and `claude --bg` running on a stale daemon started before binary-takeover support, even after upgrading
- Fixed a hang where the CLI could fail to exit when stdin was closed without EOF in stream-json mode, leaving a stale session marker behind
- Fixed malformed `file://` links in Claude’s responses not being clickable in the terminal
- Fixed `claude --help` rendering unwrapped output on terminals narrower than 92 columns
- Fixed MCP tool progress notifications not rendering in the collapsed tool view
- Fixed `Agent` tool with `subagent_type: 'claude'` running in an undocumented temporary worktree, which could silently discard outputs written to gitignored paths
- `/bg` while Claude is responding now continues the response in the background session instead of dropping it
- Fixed `/btw` keyboard shortcuts becoming unresponsive in background sessions while a task is running
- Fixed background sessions writing temp files to `$CLAUDE_JOB_DIR` triggering a “sensitive file” permission prompt
- Fixed recovering a background agent whose working directory was deleted showing a truncated stack trace instead of a clear error message
- Fixed `EnterWorktree` not being available immediately in background sessions (previously required `ToolSearch` first)
- Fixed `cmd+k` in iTerm2/Terminal.app not repainting attached background sessions
- Fixed the IME candidate window appearing at the bottom of the screen instead of next to the input caret in attached background sessions on Windows
- Fixed background-color bleed when attaching to a background agent from 256-color-only terminals after the agent had rendered file diffs
- Fixed `/copy` and copy-on-select silently failing to update the system clipboard when attached to a background session inside tmux
- Fixed opening `claude agents` with Remote Control enabled leaving zombie session entries on the Code tab after exiting
- Fixed `/rename` in background sessions not updating the session banner immediately
- Fixed Windows update rollback: if a Windows update fails, Claude Code now restores the original executable by copy and tells you how to recover
- \[VSCode\] Fixed Claude Code processes not shutting down cleanly when VS Code closed on Windows, causing false “unclean exit” reports and orphaned MCP servers
- `/model` now saves your selection as the default for new sessions (matching the IDE). Press `s` in the picker to switch models for the current session only.
- If you customized the `modelPicker:setAsDefault` keybinding, rename it to `modelPicker:thisSessionOnly` in keybindings.json (the `d` action was replaced by `s`)
[](#2-1-152)
2.1.152
May 27, 2026
- `/code-review --fix` now applies review findings to your working tree after the review, surfacing reuse, simplification, and efficiency suggestions; `/simplify` now invokes `/code-review --fix`
- Skills and slash commands can now set `disallowed-tools` in frontmatter to remove tools from the model while the skill is active
- Added `/reload-skills` command to re-scan skill directories without restarting the session
- `SessionStart` hooks can now return `reloadSkills: true` to re-scan skill directories, making skills installed by the hook available in the same session
- `SessionStart` hooks can now set the session title via `hookSpecificOutput.sessionTitle` on startup and resume
- Added a `MessageDisplay` hook event that lets hooks transform or hide assistant message text as it is displayed
- Added `pluginSuggestionMarketplaces` managed setting: admins can allowlist org marketplaces whose plugins may be suggested via context-aware tips
- `claude plugin marketplace remove` now accepts `--scope user|project|local` for symmetry with `marketplace add`, `install`, and `uninstall`
- Claude Code now switches to your configured `--fallback-model` for the rest of the session when the primary model is not found, instead of failing every request
- Auto mode no longer requires opt-in consent
- Vim mode: `/` in NORMAL mode now opens reverse history search (like Ctrl+R), matching bash/zsh vi-mode
- The `/usage` breakdown now includes large session files; files are scanned with a streaming read so memory usage stays flat
- Thinking summaries in the collapsed group now stay readable for at least 3 seconds, render as markdown, and cap at 10 lines (`Ctrl+O` shows the full thinking)
- In fullscreen mode, the “Thinking for Ns” indicator now counts up live while the model is thinking, and keeps its value if you interrupt mid-thought
- Simplified the Workflow tool’s inline progress display — live agent counts now show only in the persistent workflow status row below the prompt
- The post-response timer now shows “Waiting for N background agents/workflows to finish” when backgrounded agents or workflows are still running, and reports the cumulative time once their results are processed
- Added the session entrypoint as an OpenTelemetry metric attribute (`app.entrypoint`, opt-in via `OTEL_METRICS_INCLUDE_ENTRYPOINT=true`)
- Fixed terminal styling degrading in very long sessions by recycling the renderer’s style pool
- Fixed the sandbox-enabled warning not appearing in condensed startup mode — it now shows in every layout
- Fixed the loading spinner showing “still thinking”/“almost done thinking” while a tool is running, and reset the thinking status to “thinking” after each tool
- Fixed focus mode showing a spurious “N messages hidden” count on turns with no hidden activity
- Fixed clicking a link inside an expanded tool result collapsing the section instead of opening the link
- Fixed markdown table cell borders inheriting the color of inline code, wrapped continuation lines losing their style, and empty header cells showing a label in the narrow-terminal stacked layout
- Fixed plugin MCP servers with the same command but different environment variables being incorrectly deduplicated
- Fixed `/doctor` reporting “marketplace not found” or “plugin not found” for stale `enabledPlugins` entries referencing removed marketplaces or dropped plugins
- Fixed plugins that track a git branch silently no longer receiving updates after the plugin registry was rebuilt
- Fixed remote MCP servers failing to connect in Claude Code Remote sessions when the egress proxy is enabled
- Fixed the effort-change confirmation dialog appearing when the conversation has no messages or when switching between effort levels that resolve to the same underlying value
- Fixed the Agent tool description referencing an agent list that is never delivered when running with `--bare` or with attachments disabled
- Fixed a background worker crash in `claude agents` when accepting a stale permission prompt after a subagent was cancelled
- Fixed `cache_creation_input_tokens` reporting as 0 in transcript and result usage when the API reports cache writes only via the nested `cache_creation` breakdown
- Fixed the PushNotification tool incorrectly reporting “Mobile push not sent (Remote Control inactive)” in SDK-hosted sessions when Remote Control is enabled
- Fixed sessions getting stuck after a model or login switch left stale thinking-block signatures in history; now stripped proactively with a retry safety-net
[](#2-1-150)
2.1.150
May 23, 2026
- Internal infrastructure improvements (no user-facing changes)
[](#2-1-149)
2.1.149
May 22, 2026
- `/usage` now shows a per-category breakdown of what’s driving your limits usage — skills, subagents, plugins, and per-MCP-server cost
- `/diff` detail view can now be scrolled with the keyboard (arrows, `j`/`k`, `PgUp`/`PgDn`, `Space`, `Home`/`End`)
- Markdown output now renders GFM task list checkboxes (`- [ ] todo` / `- [x] done`) instead of plain bullets
- Enterprise: added the `allowAllClaudeAiMcps` managed setting to load claude.ai cloud MCP connectors alongside `managed-mcp.json`
- Fixed a PowerShell permission bypass: built-in `cd` functions (`cd..`, `cd\`, `cd~`, `X:`) changed the working directory undetected, letting a later command read outside the workspace
- Fixed the sandbox write allowlist in git worktrees covering the entire main repository root instead of only the shared `.git` directory (with `hooks/` and `config` denied)
- Fixed PowerShell prefix/wildcard allow rules (e.g. `PowerShell(dotnet.exe build *)`) not pre-approving native executables and scripts
- Fixed a permission-analysis gap where the parser trusted stale variable-tracking values for `PWD`/`OLDPWD`/`DIRSTACK` across `cd`/`pushd`/`popd`
- Fixed `find` in the Bash tool exhausting the macOS system file/vnode table and crashing the host on large directory trees
- Fixed the managed-settings approval dialog leaving the terminal frozen after accepting at startup
- Fixed `/ultraplan` and remote session creation failing with “Could not capture uncommitted changes” when the working tree has no real changes
- Fixed `otelHeadersHelper` failing silently when the script path contains spaces; helper failures are now reported in `/doctor` and the debug log
- Fixed the thinking spinner staying amber across tool calls and onto fresh thinking bursts
- Fixed collapsed Bash output reporting the wrong hidden-line count for outputs with many short lines
- Fixed slash-command argument-hint clipping trailing typed characters when the hint overflows the input box
- Fixed argument-hint and progressive arg suggestions not appearing after Tab-completing a skill whose frontmatter `name:` differs from its directory basename
- Fixed the status bar showing the user’s baseline `/effort` setting instead of the effort level applied by skill/agent `effort:` frontmatter
- Fixed Ctrl+O transcript view freezing at the moment it was opened instead of tailing new messages
- Fixed editing a recalled prompt-history entry losing the edit when navigating further up/down with arrow keys
- Fixed `/config` exit summary reporting phantom changes to auto-compact and theme when toggling unrelated settings
- Fixed `/insights` crashing when cached session-meta files are missing optional fields
- Fixed malformed PowerShell and History tool calls with missing input being misclassified as reads in transcript collapsing
- Fixed renaming a Remote Control session from claude.ai or the Claude mobile app not updating the local session name for `claude --resume`
- Fixed a race where a just-submitted prompt could appear twice in the up-arrow history
- Fixed tapping the “Jump to bottom” pill in fullscreen mode not dismissing it immediately
- Improved `/feedback` reports to include the conversation that happened before context compaction, making issues from earlier in long sessions easier to triage
[](#2-1-148)
2.1.148
May 22, 2026
- Fixed the Bash tool returning exit code 127 on every command for some users (a regression introduced in 2.1.147)
[](#2-1-147)
2.1.147
May 21, 2026
- Pinned background sessions (`Ctrl+T` in `claude agents`) now stay alive when idle, are restarted in place to apply Claude Code updates, and are shed under memory pressure only after non-pinned sessions
- Renamed `/simplify` to `/code-review`. It now reports correctness bugs at a chosen effort level (e.g., `/code-review high`); pass `--comment` to post findings as inline GitHub PR comments. The old cleanup-and-fix behavior has been removed
- Improved auto-updater: retries transient network failures, reports specific error categories and OS error codes on failure, and shows the current version when an update fails
- Improved diff rendering performance for large file edits
- Prompt history no longer records consecutive duplicate entries — recalling a prompt with arrow-up and submitting it again won’t add another copy
- Fixed enterprise login restrictions (`forceLoginOrgUUID` and `forceLoginMethod` managed-settings) not being enforced against third-party-provider and API-key sessions
- Fixed `&` in `!` command output displaying as `&`, which broke copy-pasting URLs from commands like `gcloud auth login` on headless machines
- Fixed unknown slash commands silently doing nothing in headless/SDK mode — they now show an error message
- Fixed `/help` rendering a broken tab header and showing only one command per page on small terminals when not in fullscreen mode
- Fixed shell snapshot dropping user functions whose names start with a single underscore, which broke aliases referencing them
- Fixed plugin agents that declare multiple `Agent(...)` types in `tools:` frontmatter dropping all but the last entry
- Fixed hook `if` conditions like `PowerShell(git push*)` never matching — only `PowerShell(*)` worked
- Fixed PowerShell tool dropping output for commands that rely on the default formatter
- Fixed: on Windows, “Yes, and don’t ask again” for a PowerShell script invocation now writes a rule that actually matches on subsequent runs
- Fixed PowerShell tool failing on Windows with exit code 1 when `pwsh` is installed via winget or the Microsoft Store
- Fixed `/effort` opening with the slider on the wrong level — it now starts at your current effort
- Fixed paginating MCP servers dropping resources, templates, and prompts past page 1
- Fixed full-screen strobing in attached background sessions on Windows Terminal while Claude is streaming
- Fixed: on Windows, removing a background-job worktree no longer follows NTFS junctions into the main repo
- Fixed `/background` refusing sessions whose only typed input was a skill or custom slash command
- Fixed auto mode suppressing `AskUserQuestion` when the user or a skill explicitly relies on it; the auto-mode classifier now sees the user’s answers as intent signal
- Fixed `/theme` “New custom theme” and color editor dialogs not responding to Esc
- Fixed an uncaught exception at the end of streaming sessions when running via the Agent SDK
- Fixed a rare hang when waiting for scroll to settle on Windows
- Fixed stale and doubled rows in the agent view list on Windows when background session results contain wide (CJK) characters
- Fixed pasted text being delivered to agents as an unreadable `[Pasted text #N]` placeholder instead of the actual content
- Fixed plugin component counts in `claude plugin details` and `/plugin` being doubled when a plugin’s manifest listed paths overlapping its default directories
- Fixed backgrounded sessions re-prompting for tool permissions you already granted with “don’t ask again”
- Fixed GNOME Terminal right-click and middle-click paste not inserting text
- Fixed `CLAUDE_CODE_SUBAGENT_MODEL` not applying to teammate processes spawned by agent teams
- Fixed slash commands followed by a tab or newline being treated as an unknown command
- Fixed several spacing and layout glitches in the `/plugin`, `/status`, `/mobile`, `/sandbox`, and `/permissions` menus
- Fixed stripped images prompting the model to repeatedly re-read media that was no longer present
[](#2-1-145)
2.1.145
May 19, 2026
- Added `claude agents --json` to list live Claude sessions as JSON for scripting (tmux-resurrect, status bars, session pickers)
- Added `agent_id` and `parent_agent_id` attributes to `claude_code.tool` OTEL spans, and fixed trace parenting so background subagent spans nest under the dispatching Agent tool span
- Status line JSON input now includes GitHub repo and PR information when detected
- `/plugin` Discover and Browse screens now show a plugin’s commands, agents, skills, hooks, and MCP/LSP servers before installation
- `claude agents` terminal tab title now shows the awaiting-input count so an alt-tabbed window tells you when an agent needs attention
- Slash command and @-mention suggestion list now supports mouse hover and click in fullscreen mode
- Stop and SubagentStop hook input now includes `background_tasks` and `session_crons` fields
- Fixed a permission-prompt bypass where bare variable assignments to non-allowlisted environment variables in Bash commands were auto-approved
- Fixed MCP prompt slash commands showing raw server validation errors when a required argument is omitted — the error now names the missing argument and shows expected usage
- Fixed the spinner and elapsed-time display freezing until a keypress after the terminal was resized or refocused
- Fixed the cross-project resume hint failing in default Windows PowerShell 5.1 — Windows now uses `;` as the command separator
- Fixed voice push-to-talk not working in the agent view’s reply pane
- Fixed task lists rendering in random order when several tasks are created at once
- Fixed stale “Failed to install Anthropic marketplace” banner showing when the marketplace is already installed
- Fixed the PR badge in the footer not updating immediately after `gh pr create` and other PR-state-changing commands run in-session
- Fixed Agent Teams teammates with non-ASCII names failing every API call due to invalid header encoding
- Fixed `/review` using a deprecated `projectCards` GraphQL query that errored on repos with Classic Projects
- Fixed `claude plugin validate` not flagging `skills:` entries that point at a file instead of a directory — the error now suggests the parent directory
- Fixed an infinite loop where a skill using `context: fork` could repeatedly re-invoke itself instead of running
- Improved the Read tool to return a truncated first page with a “PARTIAL view” notice instead of a hard error when a whole-file read exceeds the token limit
[](#2-1-144)
2.1.144
May 19, 2026
- Added `/resume` support for background sessions — sessions started via `claude --bg` or agent view now appear alongside interactive ones, marked with `bg`
- Added elapsed duration to background subagent completion notifications (e.g. “Agent completed · 3h 2m 5s”)
- The `/plugin` browse and discover panes now show when a plugin was last updated
- `/model` now changes the model for the current session only; press `d` in the model picker to set a default for new sessions
- Renamed “extra usage” to “usage credits” across CLI copy; `/extra-usage` is now `/usage-credits` (old name still works)
- Fixed startup hanging up to 75s when `api.anthropic.com` is unreachable (captive portal, firewall, VPN issues) — side-channel API calls now time out after 15s
- Fixed garbled terminal output after a missed window-resize event (e.g. dragging a VS Code split-pane divider) — now self-heals on the next frame instead of requiring Ctrl+L
- Fixed progressive terminal display corruption (stale/garbled glyphs) that could appear in very long sessions and only cleared on terminal resize or restart
- Reduced terminal rendering glitches in VS Code by reducing spinner animation color count
- Fixed macOS background sessions crashing with “exit 1 before init” when the project lives under a Full Disk Access-protected folder (regression in 2.1.143)
- Fixed an unrecoverable conversation when reading a file whose image extension doesn’t match its contents (e.g. HTML saved as .png) — now falls back to text
- Fewer spurious tool errors during search: `head`/`tail` file views now satisfy the read-before-edit check, and a “no matches” result (exit code 1) from `egrep`, `fgrep`, `git grep`, or `git diff` is no longer reported as a command failure
- Fixed `/branch` failing with “No conversation to branch” after entering a worktree or in some background sessions
- Fixed pressing Escape in the AskUserQuestion notes field aborting the turn instead of returning to answer selection
- Fixed model selection not applying when changed via the IDE model picker or `applyFlagSettings` after startup
- Resumed sessions now keep the model they were using instead of picking up another session’s `/model` choice
- Fixed Bedrock and Vertex users unable to select “Opus (1M context)” from the `/model` picker (regression in v2.1.129)
- Fixed remote-session login failing with “Can’t access this organization” for users with `forceLoginMethod` and `forceLoginOrgUUID` set
- Fixed MCP servers with paginated `tools/list` responses only returning the first page, silently dropping tools
- Fixed MCP images with unsupported MIME types (e.g. SVG) breaking the conversation — now saved to disk and referenced in the tool result
- Fixed file descriptor exhaustion when a build runs inside a skill directory — non-`.md` files no longer trigger skill reloads
- Fixed session title being generated from plugin monitor output instead of the user’s first prompt
- Fixed Skill tool failing with permission error in headless mode (regression in v2.1.141)
- Fixed plugins enabled in your own settings showing “not cached” errors after first load on a fresh machine; plugins enabled only by a project’s `.claude/settings.json` now show an actionable `claude plugin install` hint
- Fixed `claude mcp list` silently reporting no servers when `.mcp.json` can’t be parsed (e.g. using VS Code’s `"servers"` key instead of `"mcpServers"`) — now shows configuration errors
- Fixed background side-queries on custom `ANTHROPIC_BASE_URL` setups and Bedrock Mantle not using Haiku — now falls back correctly when a first-party API key is configured or no Haiku model is set
- Fixed scrolling in attached background sessions on Windows — PgUp/PgDn, mouse wheel, and Ctrl+O transcript navigation now work
- Fixed a crash when closing the terminal while attached to a background session
- Fixed on Windows, pressing ← in `claude agents` leaving the list unresponsive to keyboard input
- Fixed ghost characters at the left edge when switching panes in Agent View on Windows Terminal with CJK content
- `/bg` and `←`-detach now preserve directories added via `/add-dir`
- Fixed Edit/Write refusing with “background session hasn’t isolated its changes yet” right after detaching a session that was already editing in place
- Fixed `claude respawn <id>` on a stopped background session showing “stopped” instead of running
- Fixed `/resume` picker not showing sessions forked from a background session
- Fixed opening a session from `claude agents` or running `claude logs <id>` hanging when the background service is unresponsive — now times out after 10s with a recovery hint
- Fixed background Bash tasks spawned by subagents staying “Running” in SDK task panels after the process exits
- Fixed completed or stopped background sessions briefly failing to wake being permanently marked as a startup crash
- Fixed markdown links in `claude agents` attached sessions rendering as plain text instead of clickable hyperlinks
- Fixed custom `spinnerVerbs` applying to the post-turn duration message — past-tense built-ins like “Worked for 5s” are restored there
- `claude agents` / `--bg` rejection messages now name the specific gate (non-TTY, env var, or setting) instead of a generic message
- `claude --bg --name <label>` now echoes the name in the post-spawn confirmation
- `claude agents`: renaming a background session with Ctrl+R now updates the attached session’s banner immediately
- Background session worktree isolation guard now applies for non-git VCS users with `WorktreeCreate` hooks configured
- Plugin marketplace add/update now respects `CLAUDE_CODE_PLUGIN_PREFER_HTTPS`
- `/plugin` now returns to the Installed list after enabling, disabling, or uninstalling a plugin
- `/doctor` now shows an exec-form example when a command hook is missing the `command` field
- Skill-listing truncation is no longer shown as a startup notification — run `/doctor` for the full breakdown
- Improved recovery from rare pre-response stream stalls — now retries streaming once instead of falling back to a slower non-streaming request
- Improved SDK/headless MCP startup: pre-wait now overlaps startup instead of blocking before the first turn (up to 2s faster with slow MCP servers)
- The post-survey follow-up hint now appears after every non-dismiss survey response with context-aware copy, making it easier to share more detail via /feedback.
[](#2-1-143)
2.1.143
May 15, 2026
- Added plugin dependency enforcement: `claude plugin disable` now refuses when another enabled plugin depends on the target (with a copy-pasteable disable-chain hint), and `claude plugin enable` force-enables transitive dependencies
- Added projected context cost (per-turn and per-invocation token estimates) to the `/plugin` marketplace browse pane
- Added `worktree.bgIsolation: "none"` setting to let background sessions edit the working copy directly without `EnterWorktree`, for repos where worktrees are impractical
- PowerShell tool now passes `-ExecutionPolicy Bypass`. Opt out with `CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY=1`
- Background sessions now preserve the model and effort level you set after waking from idle
- Shift+Tab in attached agent sessions now includes auto mode in the cycle
- Fixed a corrupt `.credentials.json` with a non-array `scopes` value hanging the CLI on startup or silently aborting OAuth token refresh
- Fixed right-click paste in `claude agents` on Windows Terminal and WSL
- Fixed stop hooks that block repeatedly looping forever — the turn now ends with a warning after 8 consecutive blocks (override via `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`)
- Fixed Esc/Ctrl+C not cancelling a pending `/loop` wakeup while Claude is idle between iterations
- Fixed `/goal` evaluator firing while background shells or delegated subagents are still running
- Fixed `NO_COLOR`/`FORCE_COLOR` in settings.json `env` stripping Claude Code’s own UI colors — they now apply to subprocesses only
- Fixed agent view spawning repeated PowerShell processes on Windows when listing sessions
- Fixed `/bg` without a prompt sending “continue” to the forked session — the fork now waits for input
- Fixed `--agent <name>` not finding plugin-contributed agents without the `plugin:` prefix
- Fixed deleting a session from agent view not removing its transcript file
- Fixed stale-fragment rendering when scrolling in attached background sessions on Windows Terminal
- Fixed background agents false-positive worker-stall detection storm after host sleep or macOS App Nap
- Fixed 5xx error messages pointing at status.claude.com instead of naming the configured gateway or cloud provider
- The PowerShell tool is now enabled by default on Windows for Bedrock, Vertex, and Foundry users. Opt out with `CLAUDE_CODE_USE_POWERSHELL_TOOL=0`.
- `claude agents` now accepts `--add-dir`, `--settings`, `--mcp-config`, and `--plugin-dir` and applies them to the dashboard and to background sessions dispatched from it
- `claude agents` accepts `--permission-mode`, `--model`, `--effort`, and `--dangerously-skip-permissions` to set defaults for sessions dispatched from the view
- `claude --bg --dangerously-skip-permissions` now persists across retire→wake
- Fixed background sessions silently capturing IDE file references into the warm spare’s input, which caused the reference to be prepended to the next prompt dispatched from `claude agents`
- Worktree cleanup no longer falls back to `rm -rf` when `git worktree remove` fails, preventing loss of gitignored or in-progress files
- Fixed background-job sessions on macOS getting “Operation not permitted” errors when reading files under `~/Documents`, `~/Desktop`, or `~/Downloads`, even with Full Disk Access granted.
- `/bg` now preserves `--mcp-config`, `--settings`, `--add-dir`, `--plugin-dir`, and `--strict-mcp-config`, so backgrounded sessions keep their MCP servers and settings across respawn.
- Background sessions launched from `claude agents` now honor `permissions.defaultMode` from settings.json (was previously overridden to auto mode)
- Fixed: on Windows, pressing ← in `claude agents` while a response was streaming could leave the agents list unresponsive to all input
- `/bg` and `←`-detach now preserve `--fallback-model`, so backgrounded workers degrade to the fallback model on overload instead of hard-failing.
- `/bg` and `←`-detach now preserve `--allow-dangerously-skip-permissions`, so the forked worker keeps bypass-permissions available in its Shift+Tab cycle.
- Fixed: background daemon spawn now falls back to the running binary when the `~/.local/bin/claude` launcher is missing or non-executable
- Fixed `claude agents --allow-dangerously-skip-permissions` defaulting dispatched sessions to bypass mode instead of making it available in the permission cycle
[](#2-1-142)
2.1.142
May 14, 2026
- Added new `claude agents` flags: `--add-dir`, `--settings`, `--mcp-config`, `--plugin-dir`, `--permission-mode`, `--model`, `--effort`, and `--dangerously-skip-permissions` to configure dispatched background sessions
- Fast mode now uses Opus 4.7 by default (previously Opus 4.6). Set `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE=1` to pin fast mode to Opus 4.6
- Plugins with a root-level `SKILL.md` and no `skills/` subdirectory are now surfaced as a skill
- The `/plugin` details pane and `claude plugin details` now show LSP servers a plugin provides
- `/web-setup` warns before replacing an existing GitHub App connection
- Fixed `MCP_TOOL_TIMEOUT` not raising the per-request fetch timeout for remote HTTP and SSE MCP servers, which capped tool calls at 60 seconds regardless of the configured value
- Fixed background sessions not recognizing pre-existing git worktrees, blocking Edit while EnterWorktree refused to create a duplicate
- Fixed background sessions disappearing and daemon reconnect failing after macOS sleep/wake — the daemon now detects clock jumps instead of treating them as elapsed idle time
- Fixed daemon not exiting cleanly after the binary is upgraded (e.g. `brew upgrade`), causing dispatched agents to crash-loop on the deleted path
- Fixed background agents crash-looping when the Claude-in-Chrome extension is connected without a shared tab
- Fixed clicking links in an attached `claude agents` session — the background worker’s headless browser shim no longer applies while attached
- Fixed `claude agents` “v to open in editor” using the daemon’s default editor instead of your shell’s `$EDITOR`/`$VISUAL`
- Fixed `claude agents` deadlocking on Windows with network-drive working directories; Ctrl+C now works during startup
- Fixed background-color bleed when attaching to a `claude agents` session from Apple Terminal or other 256-color-only terminals
- Fixed `claude --bg --dangerously-skip-permissions` not persisting across retire/wake
- Fixed session titles being derived from the URL when the first message is a link
- Fixed redundant `set_model` requests from remote clients injecting duplicate `/model` breadcrumbs into the transcript
- Fixed plugins using `skills: ["./"]` showing a false “path escapes plugin directory” error
- Fixed plugin cache cleanup deleting the active plugin version directory when no installation metadata is present
- Fixed `/plugin` browse pane showing “0 installs” for newly published plugins
- Fixed plugin advisories not naming every `plugin.json` key that shadows a default folder
- Improved reactive compaction: the first summarize attempt now seeds from the original request’s overflow size, avoiding a wasted near-full-context retry
- Improved hook configuration error: configuring a prompt- or agent-type hook for `SessionStart`/`Setup`/`SubagentStart` now shows a clear “use a command-type hook instead” error
- Removed stale `/model claude-sonnet-4-20250514` suggestion from Usage Policy refusal messages
[](#2-1-141)
2.1.141
May 13, 2026
- Added `terminalSequence` field to hook JSON output so hooks can emit desktop notifications, window titles, and bells without a controlling terminal
- Added `CLAUDE_CODE_PLUGIN_PREFER_HTTPS` to clone GitHub plugin sources over HTTPS instead of SSH, for environments without a GitHub SSH key
- Added `ANTHROPIC_WORKSPACE_ID` environment variable for workload identity federation — scopes the minted token to a specific workspace when the federation rule covers more than one
- Added `claude agents --cwd <path>` to scope the session list to a directory
- `/feedback` can now include recent sessions (last 24 hours or 7 days) for issues spanning more than the current session
- Rewind menu: added “Summarize up to here” to compress earlier context while keeping recent turns intact
- Auto mode permission dialog now explains when a `permissions.ask` rule caused the prompt
- Restored the “view diff in your IDE” option on file-edit permission prompts when an IDE is connected
- Background agents launched via `/bg` or `←←` now preserve the current permission mode instead of reverting to default
- `claude agents`: agents that finish work but leave a background shell running now move to Completed instead of staying under Working
- Improved spinner feedback during long thinking periods — the spinner now warms to amber after 10 seconds to signal Claude is still working
- Improved plugin menu navigation: `→`/Tab switch tabs, `↑` moves to the tab strip, and tab headers and search box are clickable in fullscreen mode
- Fixed background side-queries sending an unavailable Haiku model ID on Bedrock/Vertex/Foundry/gateway when no `ANTHROPIC_SMALL_FAST_MODEL` override is set — now falls back to the main-loop model
- Fixed `claude daemon status` and `/doctor` on Windows throwing when the daemon pipe key file is locked or unreadable — now shows the underlying error instead of an opaque failure
- Fixed `claude agents` showing the agent-type list instead of the dashboard when launched through a wrapper that adds flags
- Fixed `claude agents` opening a crashed session firing redundant dispatches when the working directory was deleted
- Fixed background jobs on a custom `ANTHROPIC_BASE_URL` gateway not getting auto-named — the namer now uses the main model when no Haiku model is configured
- Fixed `/model` in one session silently changing the autocompact threshold in other concurrent sessions
- Fixed switching permission mode while a tool-permission prompt is open not auto-dismissing the prompt when the new setting permits the tool
- Fixed pressing Enter while a permission/dialog prompt is open also submitting text in the input box
- Fixed hooks receiving a non-existent `transcript_path` after `EnterWorktree` switches the working directory
- Fixed markdown tables with cell wrapping falling back to the vertical key-value layout instead of rendering as a bordered grid (regression in 2.1.136)
- Fixed cancelled prompts being removed from Up-arrow history when auto-restored into the input box, avoiding duplicate entries
- Fixed prompts cancelled with Ctrl+C/Esc before any response being dropped from Up-arrow history
- Fixed Ctrl+C not interrupting a running turn while in vim INSERT/VISUAL mode
- Fixed alternative `chat:submit` keybindings (e.g. `meta+enter`, `ctrl+enter`) not working when `enter` is rebound to `chat:newline`
- Fixed prompt suggestions being silently disabled when an output style was configured
- Fixed `spinnerVerbs` setting not being honored in turn-completion messages
- Fixed AskUserQuestion popup hiding the last line of preceding chat content
- Fixed Web Search status showing “Did 0 searches” when searches returned errors
- Fixed multi-line statusline output dropping or corrupting rows when any line exceeds terminal width
- Fixed light-ansi theme using invisible white for diff context lines on light backgrounds — now uses black
- Fixed error overlay dumping minified bundle source that hid the original error message
- Fixed pressing Enter after typing a feedback survey rating digit submitting it as a chat message instead of the rating
- Fixed pressing `x` on a selected subagent in the agent panel typing into the prompt instead of stopping the agent
- Fixed session title being derived from plugin monitor notifications before the user’s first prompt
- Fixed “Allowed by PermissionRequest hook” repeating once per tool call under a collapsed read/search group
- Fixed `/tui` silently dropping running background shells and subagents — now refuses and asks to wait for them to finish
- Fixed welcome banner showing “API Usage Billing” on Bedrock, Vertex, Foundry, and other third-party providers — now shows the provider name
- Fixed `/mcp` server list not keeping the focused server visible in short terminals in fullscreen mode
- Fixed redaction in `/feedback` bundles producing invalid JSON for quoted values like session IDs
- Fixed desktop and third-party provider sessions incorrectly inheriting `apiKeyHelper`/`ANTHROPIC_AUTH_TOKEN` from host managed-settings
- Fixed early analytics events being silently dropped when fired before logger initialization
- Fixed `claude plugin install` failing for plugins whose marketplace `ref` no longer exists upstream when a `sha` is also pinned
- Fixed plugin details pane showing 0 MCP servers for plugins that declare them via `.mcp.json`
- Fixed plugin MCP servers with unset config variables showing a generic connection failure instead of a “config issue” message with a fix-it hint; malformed `.mcp.json` entries no longer drop other MCP servers
- Fixed MCP server configs using POSIX shell parameter expansions (e.g. `${var%pattern}`) being incorrectly flagged as missing environment variables
- Fixed MCP HTTP/SSE servers returning 403 on connect showing as “failed” instead of “needs auth”
- Fixed remote MCP servers disconnecting unnecessarily when the optional server-events stream failed to reconnect — tool calls continue over POST
- Fixed Remote Control MCP connectors all failing with 401 when the worker session token rotated mid-session
- Fixed Remote Control automatically re-enrolling a trusted device when the server rejects a stale token, instead of looping through `/login`
- Fixed a race where early OTel spans could be silently dropped in SDK/headless mode with beta tracing enabled
- Fixed custom `voice:pushToTalk` keybindings and `"space": null` unbinds being silently ignored
- Fixed Windows Alt+V image paste reporting “no image found” when the clipboard contains a screenshot
- Fixed SDK “Claude Code native binary not found” on Linux when both glibc and musl platform packages are installed
- Bedrock: `awsCredentialExport` now always runs when configured instead of being skipped when ambient AWS credentials resolve, fixing auth for cross-account access
- \[VSCode\] Fixed in-chat mic showing no feedback when the microphone produced only silence — now shows “No audio detected”
- \[VSCode\] Voice mode: the WSL error now suggests installing `sox libsox-fmt-pulse` for WSLg users
- `claude agents`: launching a session no longer fails when the pre-warmed background worker is unhealthy — now falls back to a fresh launch
- `claude agents` no longer shows empty placeholder sessions left over from backgrounding a fresh REPL, and shows onboarding text when entered via ← with no other agents
- Empty idle background sessions left over from `←` are now automatically retired by the daemon after 5 minutes
[](#2-1-140)
2.1.140
May 12, 2026
- Improved Agent tool `subagent_type` matching to accept case- and separator-insensitive values (e.g. `"Code Reviewer"` resolves to `code-reviewer`)
- Updated agent color palette
- Fixed `/goal` silently hanging when `disableAllHooks` or `allowManagedHooksOnly` is set — now shows a clear message instead of an indicator that never resolves
- Fixed a regression in settings hot-reload where symlinked settings files caused misattributed change events and spurious `ConfigChange` hooks
- Fixed `claude --bg` failing with “connection dropped mid-request” when the background service was about to idle-exit
- Fixed background service startup failing on machines with enterprise endpoint security by allowing more time
- Fixed remote managed settings not retrying on 401 — now retries once with a force-refreshed token
- Fixed managed `extraKnownMarketplaces` auto-update policy not being persisted to `known_marketplaces.json`
- Fixed `/loop` scheduling redundant wakeups to poll for background tasks that already notify on completion
- Fixed a recurring event-loop stall on Windows when a missing executable (e.g. `gh`) triggered synchronous `where.exe` re-spawns on every check
- Fixed `Read` tool calls failing validation when `offset` is passed as a whitespace-padded or `+`-prefixed string
- Fixed native terminal cursor not staying at the input caret when the terminal loses focus
- Plugins now warn when a default component folder (e.g. `commands/`) is silently ignored because `plugin.json` sets the matching key. Shown in `/doctor`, `claude plugin list`, and `/plugin`.
[](#2-1-139)
2.1.139
May 11, 2026
- Added agent view (Research Preview): a single list of every Claude Code session — running, blocked on you, or done. Run `claude agents` to get started. See [https://code.claude.com/docs/en/agent-view](../09-Agents-Patterns/agent-view.md)
- Added `/goal` command: set a completion condition and Claude keeps working across turns until it’s met. Works in interactive, `-p`, and Remote Control. Shows live elapsed/turns/tokens as an overlay panel
- Added `/scroll-speed` command to tune mouse wheel scroll speed with a live preview
- Added `claude plugin details <name>` to show a plugin’s component inventory and projected per-session token cost
- Added transcript view navigation: `?` for keyboard shortcuts, `{`/`}` to jump between user prompts, `v` to toggle shortcut panel
- Added hook `args: string[]` field (exec form) that spawns the command directly without a shell, so path placeholders never need quoting
- Added hook `continueOnBlock` config option for `PostToolUse` — set to `true` to feed the hook’s rejection reason back to Claude and continue the turn
- MCP stdio servers now receive `CLAUDE_PROJECT_DIR` in their environment, matching hooks. Plugin configs can reference `${CLAUDE_PROJECT_DIR}` in commands
- Compaction prompt now asks the model to preserve sensitive user instructions
- `/mcp` Reconnect now picks up `.mcp.json` edits without a restart, and shows the HTTP status and URL when reconnecting fails
- `/context all` per-skill token estimates now account for the model’s tokenizer and show rounded values
- `claude plugin install <name>@<marketplace>` now auto-refreshes the marketplace and retries before reporting a plugin as not found
- `/plugin` installed-plugin details now show hook event names and MCP server names cleanly
- `/context` now shows the providing plugin’s name for plugin-sourced skills
- Remote MCP server reconnect retry on transient failures is now enabled for all users
- API requests from subagents now carry `x-claude-code-agent-id` / `x-claude-code-parent-agent-id` headers, and `claude_code.llm_request` OTEL spans include `agent_id` / `parent_agent_id` attributes
- Remote Control, `/schedule`, claude.ai MCP connectors, and notification preferences are now disabled when `ANTHROPIC_API_KEY` / `apiKeyHelper` / `ANTHROPIC_AUTH_TOKEN` is set, even if a Claude.ai login also exists. Unset the API key to use these features
- Fixed a deadlock where expired credentials and the `forceRemoteSettingsRefresh` policy setting blocked `claude auth login`/`logout`/`status` with no way to recover
- Fixed `autoAllowBashIfSandboxed` not auto-approving commands with shell expansions like `$VAR` and `$(cmd)`
- Fixed a bug where a hook writing to the terminal could corrupt an on-screen interactive prompt; hooks now run without terminal access
- Fixed unbounded memory growth when an HTTP/SSE MCP server streams non-protocol data — response bodies now capped at 16 MB per SSE frame
- Fixed `Skill(name *)` permission rules — the wildcard form now works as a prefix match, matching `Bash(ls *)` behavior
- Fixed settings hot-reload not detecting edits to symlinked `~/.claude/settings.json`
- Fixed plugin details failing to load when the marketplace key differs from the manifest name
- Fixed `/model` picker “Default” row not reflecting `ANTHROPIC_DEFAULT_OPUS_MODEL`/`ANTHROPIC_DEFAULT_SONNET_MODEL` overrides
- Fixed spurious “stream idle timeout” 5 minutes after a response completed, caused by the watchdog timer not being cleared on stream cancellation
- Fixed silent `exit 1` when 10+ MCP servers are configured and the cache directory is unwritable — the error message now includes the underlying cause
- Fixed a typing cursor blinking on tab names, list pointers, and select rows in dialogs
- Fixed transcript view letter shortcuts not working after mouse click
- Fixed Bash-mode up-arrow history repeating the first entry and clobbering the in-progress draft
- Fixed pasting or dropping multiple images only inserting the last one
- Fixed hyperlinks using unreadable dark navy on dark themes — they now adapt to the active theme
- Fixed model picker showing a redundant “Current model” row for third-party users whose model is set to the `opus` alias
- Fixed legacy Opus picker entry on PAYG 3P providers resolving to the same model as the default entry
- Fixed mouse wheel scrolling speed in Cursor and VS Code 1.92–1.104; the trackpad now scrolls at a steady rate and the mouse wheel keeps ~3 lines per notch
- Fixed scroll behavior in Windows Terminal and VS Code when attached to background sessions
- Fixed MCP resources from disconnected servers lingering in `@server:` autocomplete
- Fixed two-file diff snippets over-reporting the number of truncated lines by one
- Fixed Grep results not relativizing Windows drive-letter paths and count mode reporting wrong totals for single-file paths
- Fixed border-embedded text overflowing on CJK/emoji due to visual cell width miscalculation
- Fixed fuzzy-match highlighting splitting emoji and astral-plane characters mid-pair
- Fixed skill argument names containing regex metacharacters breaking argument substitution
- Fixed ProgressBar rendering a full block for an almost-full fractional cell
- Fixed task polling and `fs.watch` being resurrected when the last subscriber leaves while a fetch is in flight
- Fixed plugin dependency resolution leaving a stale count when the manifest name differs from the source identifier
- Fixed Insights Time-of-Day chart skewing when a session has an unparseable timestamp
- Fixed keybindings using only the cmd/super/win modifier being flagged as unparseable
- Fixed `claude_code.active_time.total` OpenTelemetry metric not being emitted in `--print` mode
- Fixed `claude plugin update` not preserving cross-plugin symlinks inside a marketplace
- \[VSCode\] Press Cmd/Ctrl+Shift+T to reopen the most recently closed session tab, configurable via `claudeCode.enableReopenClosedSessionShortcut`
[](#2-1-138)
2.1.138
May 9, 2026
- Internal fixes
[](#2-1-137)
2.1.137
May 9, 2026
- \[VSCode\] Fixed extension failing to activate on Windows
[](#2-1-136)
2.1.136
May 8, 2026
- Added `CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL` to re-enable the session quality survey for enterprises capturing responses through OpenTelemetry
- Added `settings.autoMode.hard_deny` for auto mode classifier rules that block unconditionally regardless of user intent or allow exceptions
- Fixed MCP servers configured in `.mcp.json`, plugins, and claude.ai connectors silently disappearing after `/clear` in the VS Code extension, JetBrains plugin, and Agent SDK
- Fixed a rare login loop where a concurrent credential write could overwrite a freshly-rotated OAuth token and force re-login
- Fixed MCP OAuth refresh tokens being lost when multiple servers refresh concurrently — users with several remote MCP servers should no longer need daily re-authentication
- Fixed an API error (400) when extended thinking emitted a redacted thinking block after a tool call
- Fixed `--resume` / `--continue` not finding sessions when the project path contains underscores
- Fixed plan mode not blocking file writes when a matching `Edit(...)` allow rule exists
- WSL2: image paste from Windows clipboard now works via a PowerShell fallback when xclip/wl-paste cannot read image data
- Fixed plugin `Stop`/`UserPromptSubmit` hooks failing when cache cleanup deletes a version still in use by a running session
- Improved visual consistency across slash command dialogs: standardized footer hints, dialog spacing, and arrow-key styling, and the dialog frame now appears immediately during loading instead of popping in after
- Fixed colors appearing at wrong positions in bash command output and markdown code blocks
- Fixed ReasonML diffs rendering corrupted “undefined” text artifacts at word-diff boundaries
- Fixed worktree exit dialog warning about uncommitted files in the wrong directory after worktree removal
- Fixed `@` file picker not matching files created mid-session in small non-git directories
- Fixed `@`-mention file picker not finding files in directories with more than 100 entries
- Fixed failed tool calls not being click-to-expand in fullscreen mode when their output was truncated
- Fixed Backspace and Ctrl+Backspace getting swapped after using Ctrl+G to open an external editor on terminals with persistent extended-key modes
- Fixed `/usage` weekly reset showing time of day instead of the calendar date
- Fixed welcome banner ellipsis causing column overflow on CJK terminals
- Fixed `/insights` crash when session history contains tool calls with malformed input fields
- Fixed a renderer crash when a tool’s collapsibility classification changes mid-session
- Fixed a `skills` entry in `plugin.json` hiding the plugin’s default `skills/` directory, and listing a file path now shows an error instead of failing silently
- Fixed IDE shell-integration lock files not respecting `CLAUDE_CONFIG_DIR`
- Fixed trailing whitespace in copied terminal output during streaming
- Fixed plugin uninstall and enable/disable not matching slugs case-insensitively
- Fixed tool error truncation marker showing a negative count for surrogate-pair strings
- Fixed env vars from `CLAUDE_ENV_FILE` SessionStart hooks going stale after `/resume` or `/clear`
- Fixed `/branch` saving a multi-line session title when given a pasted multi-line name
- Fixed a stray leading space on the second line of wrapped text at the column boundary
- Fixed Esc not dismissing dialogs in `/install-github-app`, `/desktop`, `/resume`, and `/web-setup`
- Fixed `/doctor` MCP schema errors not naming the missing field or showing the source file path
- Fixed Bash permission prompts showing an internal parser diagnostic instead of a user-readable explanation
- Fixed plugin slash commands with spaces (e.g. `/myplugin review`) not resolving to their namespaced form
- Fixed `AskUserQuestion` discarding multi-select answers when supplied as an array
- Fixed `/clear <name>` not labeling the cleared session for `/resume`
- Fixed `CronList` output missing qualifiers and the scheduled prompt
- Fixed “Jump to bottom” overlay leaving color artifacts on CJK characters in fullscreen mode
- Fixed wide markdown tables leaving a stale bordered render in terminal scrollback while streaming
- Fixed pasted text being silently dropped when a long prompt with a pasted-text placeholder was auto-truncated
- Fixed `/release-notes` getting stuck on an old version after a failed changelog refresh
- Fixed `/mcp` server list not scrolling when there are more servers than fit in the terminal
- Fixed mid-input slash command autocomplete not working after an initial slash command
- Fixed scrolling to bottom re-engaging auto-follow with `autoScrollEnabled: false`
- Fixed prompt suggestions being auto-submitted by Enter on an empty input instead of requiring Tab or arrow to accept
- Fixed keyboard shortcut hints not reflecting rebound keys from `keybindings.json`
- Fixed `/settings` language change being reverted on Escape after confirming
- Fixed `/terminal-setup` only appearing in autocomplete on exact name match instead of partial prefixes
- Fixed “Chat about this” on an `AskUserQuestion` dialog erasing the question text
- Fixed MCP tool results being invisible when the server returns content blocks
- Improved error message when `--worktree` collides with an existing or stale worktree
- Changed plugin marketplace removal key to `d` (matching delete elsewhere) instead of `r` which collided with retry
[](#2-1-133)
2.1.133
May 7, 2026
- Added `worktree.baseRef` setting (`fresh` \| `head`) to choose whether `--worktree`, `EnterWorktree`, and agent-isolation worktrees branch from `origin/<default>` or local `HEAD`. **Note:** the default `fresh` changes `EnterWorktree`’s base back to `origin/<default>` (it has been local `HEAD` since 2.1.128) — set `worktree.baseRef: "head"` to keep unpushed commits in new worktrees
- Added `sandbox.bwrapPath` and `sandbox.socatPath` managed settings (Linux/WSL) to specify custom bubblewrap and socat binary locations
- Added `parentSettingsBehavior` admin-tier key (`'first-wins' | 'merge'`) to let admins opt SDK `managedSettings` (parent tier) into the policy merge
- 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`
- Improved focus mode behavior
- Improved memory usage by releasing warm-spare background workers under memory pressure
- Fixed parallel sessions all dead-ending at 401 after a refresh-token race wiped shared credentials
- Fixed `Edit`/`Write` allow rules scoped to a drive root (`C:\`) or POSIX `/` matching incorrectly and always prompting
- Fixed an unhandled rejection (`ECOMPROMISED`) when a history or session-log file lock is compromised by clock skew or slow disk
- Fixed pressing Esc during conversation compaction showing a spurious “Error compacting conversation” notification
- Fixed `HTTP(S)_PROXY` / `NO_PROXY` / mTLS not being respected for the full MCP OAuth flow including discovery, dynamic client registration, token exchange, and token refresh
- Fixed Read/Write/Edit being denied on mapped network drives passed via `--add-dir` / SDK `additionalDirectories`
- Fixed Remote Control stop/interrupt from claude.ai not fully canceling the CLI session the same way local Esc does, causing queued messages to never advance after interrupting a stuck tool or prompt
- Fixed `/effort` in one session unexpectedly changing the effort level of other concurrent sessions, and a related issue where an IDE effort change could be silently dropped
- Fixed subagents not discovering project, user, or plugin skills via the Skill tool
- `claude --help` now lists `--remote-control` alongside `--remote-control-session-name-prefix`
- \[VSCode\] Fixed `claudeCode.claudeProcessWrapper` failing with “Unsupported platform” when the extension build doesn’t bundle a Claude binary
[](#2-1-132)
2.1.132
May 6, 2026
- Added `CLAUDE_CODE_SESSION_ID` environment variable to the Bash tool subprocess environment, matching the `session_id` passed to hooks
- Added `CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1` env var to opt out of the fullscreen alternate-screen renderer and keep the conversation in the terminal’s native scrollback
- Added a “Pasting…” footer hint while a Ctrl+V image paste is being read from the clipboard
- Fixed external SIGINT (e.g. IDE stop button, `kill -INT`) not running graceful shutdown — terminal modes are now restored and the `--resume` hint is printed instead of an abrupt exit
- Fixed an uncaught exception when the terminal is closed or SSH disconnects mid-session under the native build
- Fixed `--resume` failing with `no low surrogate in string` when a tool error truncation split an emoji; pre-corrupted sessions are sanitized on load
- Fixed `--permission-mode` flag being ignored when resuming a plan-mode session with `-p --continue`/`--resume`, and plan mode not being re-applied after `ExitPlanMode` within the same session
- Fixed fullscreen mode showing a blank screen after laptop sleep/wake or Ctrl+Z/`fg` until the next keystroke or stream output
- Fixed cursor landing mid-grapheme on Ctrl+E/A/K/U/arrow keys when an Indic conjunct or ZWJ emoji wraps across lines
- Fixed vim operators corrupting text containing decomposed (NFD) accented characters
- Fixed pasting text starting with `/` silently swallowing the input or triggering an unknown-command reply
- Fixed pasting dumping stray escape sequences into the prompt when focus events or mouse-tracking reports interleave with the bracketed paste
- Fixed mouse wheel scrolling being too fast in Cursor and VS Code 1.92–1.104 due to an upstream xterm.js bug
- Fixed scroll-wheel handling in JetBrains IDE 2025.2 terminals (spurious arrow keys, wrong-direction events, runaway acceleration)
- Fixed `/usage` Ctrl+S hanging when copying the stats screenshot to the clipboard on Linux/X11
- Fixed `/terminal-setup` showing a contradictory error in Windows Terminal — Shift+Enter is natively supported there
- Fixed `/effort` picker not reflecting the `CLAUDE_CODE_EFFORT_LEVEL` env var override
- Fixed `/status` showing the wrong default model for some users
- Fixed slash command autocomplete popup being capped at ~3–5 visible commands instead of scaling with terminal height
- Fixed statusline `context_window` token counts reflecting cumulative session totals instead of current context usage
- Fixed Alt+T (thinking toggle) not working on macOS terminals without “Option as Meta” enabled (iTerm2, Terminal.app defaults)
- Fixed dead keyboard input on Windows after re-opening a background session from `claude agents`
- Fixed unbounded memory growth (10GB+ RSS) when a stdio MCP server writes non-protocol data to stdout
- Fixed MCP servers that connect but fail `tools/list` silently showing 0 tools — they now retry once and show “connected · tools fetch failed” in `/mcp`
- Fixed unauthorized claude.ai MCP connectors showing as “failed” instead of “needs auth”, and headless `-p` mode retrying non-transient 4xx connection failures
- Improved visual consistency in slash command dialogs and `/login`, `/upgrade`, `/extra-usage` dialog spacing
- Updated the `/tui fullscreen` startup banner to describe additional renderer benefits (lower memory usage, mouse support, auto-copy on select)
- Fixed Bedrock and Vertex 400 errors when `ENABLE_PROMPT_CACHING_1H` is set
[](#2-1-131)
2.1.131
May 6, 2026
- Fixed VS Code extension failing to activate on Windows due to a hardcoded build path in the bundled SDK (`createRequire` polyfill bug)
- Fixed Mantle endpoint authentication failing with missing `x-api-key` header
[](#2-1-129)
2.1.129
May 6, 2026
- Added `--plugin-url <url>` flag to fetch a plugin `.zip` archive from a URL for the current session
- Added `CLAUDE_CODE_FORCE_SYNC_OUTPUT=1` env var to force-enable synchronized output on terminals that auto-detection misses (e.g. Emacs `eat`)
- Added `CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE`: when set on Homebrew or WinGet installations, Claude Code runs the upgrade command in the background and prompts to restart
- Plugin manifests: `themes` and `monitors` should now be declared under `"experimental": { ... }`. Top-level declarations still work but `claude plugin validate` will warn
- Gateway `/v1/models` discovery for the `/model` picker is now opt-in via `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1` (was automatic in 2.1.126–2.1.128)
- Ctrl+R history picker now defaults to searching all prompts across all projects, matching pre-2.1.124 behavior. Press Ctrl+S to narrow to the current project or session
- Third-party deployments (Bedrock, Vertex, Foundry, or `ANTHROPIC_BASE_URL` gateway) no longer see spinner tips pointing at first-party Anthropic surfaces
- `skillOverrides` setting now works: `off` hides from model and `/`, `user-invocable-only` hides from model only, `name-only` collapses description
- The `claude_code.pull_request.count` OTel metric now counts PRs/MRs created via MCP tools, not just shell commands
- Policy refusal error messages now include the API Request ID for easier support debugging
- Fixed API errors with unrecognized 400 status codes showing raw JSON instead of the underlying error message
- Fixed `/clear` not resetting the terminal tab title after a conversation
- Fixed session title chip from `/rename` disappearing while a permission or other dialog is active
- Fixed agent panel below the prompt being hidden when subagents are running (regression in 2.1.122)
- Fixed external-editor handoff (Ctrl+G) blanking the conversation history above the prompt
- Fixed `/context` dumping its rendered ASCII visualization grid into the conversation, wasting ~1.6k tokens per call
- Fixed `/agents` Library list arrow-key navigation: the highlighted agent now stays visible when the list exceeds the viewport
- Fixed `/branch` success message not including the new branch’s session id for `/resume`
- Fixed bold headers with keycap/ZWJ/skin-tone emoji losing trailing characters in fullscreen mode
- Fixed server-managed settings policy not applying for enterprise/team users whose stored OAuth credentials lacked the `user:inference` scope
- Fixed OAuth refresh race after wake-from-sleep that could log out all running sessions
- Fixed 1-hour prompt cache TTL being silently downgraded to 5 minutes
- Fixed cache-miss warning appearing spuriously after `/clear` or compaction when changing `/effort` or `/model`
- Fixed `Bash(mkdir *)`, `Bash(touch *)` and similar allow rules not being honored for in-project paths
- Fixed `deniedMcpServers` patterns with a `*://` scheme wildcard not matching mixed-case hostnames
- Fixed harmless WebSocket warning being logged as an error in `--debug` during voice mode
- \[VSCode\] Fixed `/clear` not clearing the conversation context and displayed transcript
[](#2-1-128)
2.1.128
May 4, 2026
- Bare `/color` (no args) now picks a random session color
- `/mcp` now shows the tool count for connected servers and flags servers that connected with 0 tools
- `--plugin-dir` now accepts `.zip` plugin archives in addition to directories
- `--channels` now works with console (API key) authentication — console orgs with managed settings must set `channelsEnabled: true` to enable
- Updated `/model` picker: collapsed duplicate Opus 4.7 entries, and current Opus now shows as “Opus” instead of “Opus 4.7”
- Subprocesses (Bash, hooks, MCP, 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
- MCP: `workspace` is now a reserved server name — existing servers with that name will be skipped with a warning
- Reconnecting MCP servers no longer flood the conversation with full tool-name lists on every reconnect — re-announced tools are summarized by server prefix
- SDK hosts now receive a persistent `localSettings` suggestion for Bash permission prompts, so “Always allow” writes to `.claude/settings.local.json`
- `EnterWorktree` now creates the new branch from local HEAD as documented, instead of `origin/<default-branch>` — unpushed commits are no longer dropped
- Auto mode: when the classifier can’t evaluate an action, the error now includes a hint (retry, `/compact`, or run with `--debug`)
- Fixed focus mode briefly dimming the previous response when submitting a new prompt
- Fixed stray “4;0;” desktop notification on every `/exit` in Kitty and other terminals that interpret OSC 9 as a notification
- Fixed Remote Control showing an empty “Opening your options…” message on rate limit instead of actionable upsell options
- Fixed drag-and-drop image upload hanging on “Pasting text…” when the image read fails
- Fixed crash loop when piping very large input (\>10 MB) to `claude -p` via stdin
- Fixed long URLs not being individually clickable on every wrapped row in fullscreen mode
- Fixed `/plugin` Components panel showing “Marketplace ‘inline’ not found” for plugins loaded via `--plugin-dir`
- Fixed MCP tool results dropping images when the server returns both structured content and content blocks
- Fixed fenced code blocks inside list items carrying leading whitespace into the clipboard on copy-paste
- Fixed tab navigation in `/config` stranding focus — the tab header now stays focused so arrows and Esc keep working
- Fixed markdown link labels being lost on terminals without OSC 8 hyperlink support — links now render as `label (url)` instead of just the URL
- Fixed sessions on 1M-context models with a smaller autocompact window being falsely blocked with “Prompt is too long” before reaching the actual API limit
- Fixed parallel shell tool calls: a failing read-only command (grep, git diff, ls) no longer cancels sibling calls
- Fixed banner showing “with X effort” on models that don’t support effort
- Fixed `/fast` on 3P providers fuzzy-matching to an unrelated skill instead of showing “not available”
- Fixed Bedrock default model resolving to `global.*` instead of the region-appropriate prefix
- Fixed vim mode: `Space` in NORMAL mode now moves the cursor right, matching standard vi/vim behavior
- Fixed terminal progress indicator (OSC 9;4) flickering off between tool calls — stays visible across the full turn
- Fixed `/rename` without args failing on resumed sessions whose last entry is a compact boundary
- Fixed stale “remote-control is active” status lines from prior sessions appearing after `--resume`/`--continue`
- Fixed stale `installed_plugins.json` entries pointing at deleted cache directories polluting PATH
- Fixed MCP stdio servers receiving corrupted arguments when `CLAUDE_CODE_SHELL_PREFIX` is set and an argument contains spaces or shell metacharacters
- Fixed sub-agent progress summaries missing the prompt cache (~3× `cache_creation` reduction)
- Fixed `/plugin update` never detecting new versions of npm-sourced plugins
- Fixed sub-agent summaries firing repeatedly while a sub-agent’s transcript is static, capping worst-case token cost on idle sub-agents
- Headless `--output-format stream-json`: `init.plugin_errors` now includes `--plugin-dir` load failures in addition to dependency demotions
[](#2-1-126)
2.1.126
May 1, 2026
- The `/model` picker now lists models from your gateway’s `/v1/models` endpoint when `ANTHROPIC_BASE_URL` points at an Anthropic-compatible gateway
- - Added `claude project purge [path]` to delete all Claude Code state for a project (transcripts, tasks, file history, config entry) — supports `--dry-run`, `-y/--yes`, `-i/--interactive`, and `--all`
- `--dangerously-skip-permissions` now bypasses prompts for writes to `.claude/`, `.git/`, `.vscode/`, shell config files, and other previously-protected paths (catastrophic removal commands still prompt as a safety net)
- `claude auth login` now accepts the OAuth code pasted into the terminal when the browser callback can’t reach localhost (WSL2, SSH, containers)
- `claude_code.skill_activated` OpenTelemetry event now fires for user-typed slash commands and carries a new `invocation_trigger` attribute (`"user-slash"`, `"claude-proactive"`, or `"nested-skill"`)
- Auto mode: the spinner now turns red when a permission check stalls, instead of looking like the tool is running
- Host-managed deployments (`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`) no longer auto-disable analytics on Bedrock/Vertex/Foundry
- Windows: PowerShell 7 installed via the Microsoft Store, MSI without PATH, or `.NET global tool` is now detected
- Windows: when the PowerShell tool is enabled, Claude now treats PowerShell as the primary shell instead of defaulting to Bash
- Read tool: removed the per-file malware-assessment reminder that could cause spurious refusals and “this is not malware” commentary on legacy models
- **Security:** Fixed `allowManagedDomainsOnly` / `allowManagedReadPathsOnly` being ignored when a higher-priority managed-settings source lacked a `sandbox` block
- Fixed pasting an image larger than 2000px breaking the session — images are now downscaled on paste, and oversized images in history are automatically removed and the request retried
- Fixed showing the login screen for “OAuth not allowed for organization” errors — now shows guidance to contact your admin
- Fixed OAuth login failing with timeout on slow or proxied connections, in IPv6-only devcontainers, and when the browser callback can’t reach localhost
- Fixed a rare race where a concurrent credential write could clear a valid OAuth refresh token
- Fixed API retry countdown sticking at “0s” instead of counting down between attempts
- Fixed “Stream idle timeout” error after waking Mac from sleep mid-request
- Fixed background and remote sessions falsely aborting with “Stream idle timeout” during long model thinking pauses
- Fixed a hang where the assistant could finish thinking but show no output after a run of empty turns
- Fixed overly fast trackpad scrolling in Cursor and VS Code 1.92–1.104 integrated terminals
- Fixed claude.ai MCP connectors being suppressed by manual servers stuck in needs-auth state
- Fixed Japanese/Korean/Chinese text rendering as garbled characters on Windows in no-flicker mode
- Fixed `Ctrl+L` clearing the prompt input — it now only forces a screen redraw, matching readline behavior
- Fixed deferred tools (WebSearch, WebFetch, etc.) not being available to skills with `context: fork` and other subagents on their first turn
- Fixed plan-mode tools being unavailable in interactive sessions launched with `--channels`
- Fixed `/plugin` Uninstall reporting “Enabled” instead of “Uninstalled”
- Bounded total size of file-modified reminders when a linter touches many files at once
- Fixed `/remote-control` retries appearing stuck on “connecting…” — each retry now shows its result
- Fixed Remote Control failure notification not showing the error reason for initial connection failures
- Windows: clipboard writes no longer expose copied content in process command-line arguments visible to EDR/SIEM telemetry; also fixes \>22KB selections not reaching the clipboard
- PowerShell tool: bare `--` (e.g. `git diff -- file`) is no longer mis-flagged as the `--%` stop-parsing token
- Fixed Agent SDK hang when the model emits a malformed tool name in a parallel tool call batch
[](#2-1-123)
2.1.123
April 29, 2026
- Fixed OAuth authentication failing with a 401 retry loop when `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` is set
[](#2-1-122)
2.1.122
April 28, 2026
- Added `ANTHROPIC_BEDROCK_SERVICE_TIER` environment variable to select a Bedrock service tier (`default`, `flex`, or `priority`), sent as the `X-Amzn-Bedrock-Service-Tier` header
- Pasting a PR URL into the `/resume` search box now finds the session that created that PR (GitHub, GitHub Enterprise, GitLab, and Bitbucket)
- `/mcp` now shows claude.ai connectors hidden by a manually-added server with the same URL, with a hint to remove the duplicate
- Clarified the `/mcp` message shown when an MCP server is still unauthorized after the browser sign-in flow
- OpenTelemetry: numeric attributes on `api_request`/`api_error` log events are now emitted as numbers, not strings
- OpenTelemetry: added `claude_code.at_mention` log event for `@`-mention resolution
- Fixed `/branch` producing forks that fail with “tool_use ids were found without tool_result blocks” when the source session contained entries from rewound timelines
- Fixed `/model` not showing the Effort option for Bedrock application inference profile ARNs, and those ARNs not receiving `output_config.effort`
- Fixed Vertex AI / Bedrock returning `invalid_request_error: output_config: Extra inputs are not permitted` on session-title generation and other structured-output queries
- Fixed Vertex AI `count_tokens` endpoint returning 400 errors for users behind proxy gateways
- Fixed `spinnerTipsOverride.excludeDefault` not suppressing the time-based spinner tips
- Fixed ToolSearch missing MCP tools that connected after session start in nonblocking mode
- Fixed `!exit` / `!quit` in bash mode terminating the CLI instead of running as a shell command
- Fixed images sent to newer models being resized to 2576px per side instead of the correct 2000px maximum
- Fixed remote control session idle status redrawing twice per second, which could flood `tmux -CC` control pipes and pause the terminal
- Fixed assistant messages appearing blank in some sessions due to a stale view preference
- Fixed a malformed hooks entry in `settings.json` no longer invalidating the entire file
- Voice mode: keybindings bound to Caps Lock now show an error since terminals don’t deliver Caps Lock as a key event
[](#2-1-121)
2.1.121
April 28, 2026
- Added `alwaysLoad` option to MCP server config — when `true`, all tools from that server skip tool-search deferral and are always available
- Added `claude plugin prune` to remove orphaned auto-installed plugin dependencies; `plugin uninstall --prune` cascades
- Added a type-to-filter search box to `/skills` so you can find a skill in long lists without scrolling
- PostToolUse hooks can now replace tool output for all tools via `hookSpecificOutput.updatedToolOutput` (previously MCP-only)
- Fullscreen mode: typing into the prompt no longer jumps scroll back to the bottom after you’ve scrolled up to read earlier output
- Dialogs that overflow the terminal are now scrollable with arrow keys, PgUp/PgDn, home/end, and mouse wheel in both fullscreen and non-fullscreen modes
- Clicking any line of a long URL that wraps across rows in fullscreen mode now opens the full URL
- SDK and `claude -p`: `CLAUDE_CODE_FORK_SUBAGENT=1` now works in non-interactive sessions
- `--dangerously-skip-permissions` no longer prompts for writes to `.claude/skills/`, `.claude/agents/`, and `.claude/commands/`
- `/terminal-setup` now enables iTerm2’s “Applications in terminal may access clipboard” setting so `/copy` works, including from tmux
- MCP servers that hit a transient error during startup now auto-retry up to 3 times instead of staying disconnected
- The terminal tab session title is now generated in your configured `language` setting
- Claude.ai connectors with the same upstream URL are now deduplicated instead of appearing as duplicates
- Vertex AI: support X.509 certificate-based Workload Identity Federation (mTLS ADC)
- Faster startup after upgrading: removed the Recent Activity panel from the release-notes splash
- LSP diagnostic summaries now expand on click/ctrl+o and show the expand hint
- SDK: `mcp_authenticate` now supports `redirectUri` for custom scheme completion and claude.ai connectors
- OpenTelemetry: added `stop_reason`, `gen_ai.response.finish_reasons`, and `user_system_prompt` (gated behind `OTEL_LOG_USER_PROMPTS`) to LLM request spans
- \[VSCode\] Voice dictation now respects the `accessibility.voice.speechLanguage` setting when no Claude Code language is configured
- \[VSCode\] `/context` now opens a native token usage dialog
- Fixed unbounded memory growth (multi-GB RSS) when processing many images in a session
- Fixed `/usage` leaking up to ~2GB of memory on machines with large transcript histories
- Fixed memory leak when long-running tools fail to emit a clear progress event
- Fixed Bash tool becoming permanently unusable when the directory Claude was started in is deleted or moved mid-session
- Fixed `--resume` crashing on startup in external builds
- Fixed `--resume` failing on large sessions when a transcript line was corrupted by an unclean shutdown — the corrupt line is now skipped
- Fixed `thinking.type.enabled is not supported` error when using Bedrock application inference profile ARNs
- Fixed Microsoft 365 MCP OAuth failing with duplicate or unsupported `prompt` parameter
- Fixed scrollback duplication when pressing Ctrl+L or triggering a redraw in non-fullscreen mode on tmux, GNOME Terminal, Windows Terminal, and Konsole
- Fixed claude.ai MCP connectors silently disappearing when the connector-list fetch hits a transient auth error at startup
- Fixed “Always allow” rules for built-in tools in remote sessions not surviving worker restarts
- Fixed `NO_PROXY` not being respected for all HTTP clients when set via `managed-settings.json` under the native build
- Fixed managed settings approval prompt exiting the session even when accepted — now applies settings and continues
- Fixed `/usage` returning “rate limited” after a stale OAuth token — now refreshes automatically
- Fixed invalid legacy enum values in `settings.json` invalidating the entire settings file
- Fixed `/usage` dialog content being clipped when no-flicker mode is off
- Fixed `/focus` showing “Unknown command” when the fullscreen renderer is off — now explains how to enable it
- Fixed embedded grep/find/rg shell wrappers failing when the running binary is deleted mid-session — now falls back to installed tools
- Reduced peak file descriptor usage during `find` in the Bash tool on large directory trees
[](#2-1-120)
2.1.120
April 28, 2026
- Windows: Git for Windows (Git Bash) is no longer required — when absent, Claude Code uses PowerShell as the shell tool
- Added `claude ultrareview [target]` subcommand to run `/ultrareview` non-interactively from CI or scripts — prints findings to stdout (`--json` for raw output) and exits 0 on completion or 1 on failure
- Skills can now reference the current effort level with `${CLAUDE_EFFORT}` in their content
- Set `AI_AGENT` environment variable for subprocesses so `gh` can attribute traffic to Claude Code
- Spinner tips that recommend installing the desktop app or creating skills/agents are now hidden when you already have them
- Show a “use PgUp/PgDn to scroll” hint when the terminal sends arrow keys instead of scroll events
- Faster session start when you have many claude.ai connectors configured but not authorized
- The auto mode denial message now links to the configuration docs
- `claude plugin validate` now accepts `$schema`, `version`, and `description` at the top level of `marketplace.json` and `$schema` in `plugin.json`
- Auto-compact in auto mode now displays `auto` (lowercase, no token count) instead of a misleading token value
- Fixed pressing Esc during a stdio MCP tool call closing the entire server connection (regression in 2.1.105)
- Fixed `/rewind` and other interactive overlays not responding to keyboard input after launching with `claude --resume`
- Fixed terminal scrollback duplication in non-fullscreen mode (resize, dialog dismiss, long sessions)
- Fixed `DISABLE_TELEMETRY` / `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` not suppressing usage metrics telemetry for API and enterprise users
- Fixed false-positive “Dangerous rm operation” permission prompts in auto mode for multi-line bash commands containing both a pipe and a redirect
- Fixed long selection menus clipping below the terminal in fullscreen mode — the focused option now stays on screen as you scroll
- Fixed Write tool output collapsing instead of expanding when clicking “+N lines” in fullscreen
- Fixed slash command picker jumping while typing, and improved highlight to only match contiguous substrings in blue
- Fixed `/plugin` marketplace failing to load when one entry uses an unrecognized source format — that entry is shown but installing it prompts you to update
- \[VSCode\] `/usage` now opens the native Account & Usage dialog instead of returning plain-text session cost
- \[VSCode\] Voice dictation now respects the `language` setting in `~/.claude/settings.json`
- Fixed `find` in the Bash tool exhausting open file descriptors on large directory trees, causing host-wide crashes (macOS/Linux native builds)
[](#2-1-119)
2.1.119
April 23, 2026
- `/config` settings (theme, editor mode, verbose, etc.) now persist to `~/.claude/settings.json` and participate in project/local/policy override precedence
- Added `prUrlTemplate` setting to point the footer PR badge at a custom code-review URL instead of github.com
- Added `CLAUDE_CODE_HIDE_CWD` environment variable to hide the working directory in the startup logo
- `--from-pr` now accepts GitLab merge-request, Bitbucket pull-request, and GitHub Enterprise PR URLs
- `--print` mode now honors the agent’s `tools:` and `disallowedTools:` frontmatter, matching interactive-mode behavior
- `--agent <name>` now honors the agent definition’s `permissionMode` for built-in agents
- PowerShell tool commands can now be auto-approved in permission mode, matching Bash behavior
- Hooks: `PostToolUse` and `PostToolUseFailure` hook inputs now include `duration_ms` (tool execution time, excluding permission prompts and PreToolUse hooks)
- Subagent and SDK MCP server reconfiguration now connects servers in parallel instead of serially
- Plugins pinned by another plugin’s version constraint now auto-update to the highest satisfying git tag
- Vim mode: Esc in INSERT no longer pulls a queued message back into the input; press Esc again to interrupt
- Slash command suggestions now highlight the characters that matched your query
- Slash command picker now wraps long descriptions onto a second line instead of truncating
- `owner/repo#N` shorthand links in output now use your git remote’s host instead of always pointing at github.com
- Security: `blockedMarketplaces` now correctly enforces `hostPattern` and `pathPattern` entries
- OpenTelemetry: `tool_result` and `tool_decision` events now include `tool_use_id`; `tool_result` also includes `tool_input_size_bytes`
- Status line: stdin JSON now includes `effort.level` and `thinking.enabled`
- Fixed pasting CRLF content (Windows clipboards, Xcode console) inserting an extra blank line between every line
- Fixed multi-line paste losing newlines in terminals using kitty keyboard protocol sequences inside bracketed paste
- Fixed Glob and Grep tools disappearing on native macOS/Linux builds when the Bash tool is denied via permissions
- Fixed scrolling up in fullscreen mode snapping back to the bottom every time a tool finishes
- Fixed MCP HTTP connections failing with “Invalid OAuth error response” when servers returned non-JSON bodies for OAuth discovery requests
- Fixed Rewind overlay showing “(no prompt)” for messages with image attachments
- Fixed auto mode overriding plan mode with conflicting “Execute immediately” instructions
- Fixed async `PostToolUse` hooks that emit no response payload writing empty entries to the session transcript
- Fixed spinner staying on when a subagent task notification is orphaned in the queue
- Tool search is now disabled by default on Vertex AI to avoid an unsupported beta header error (opt in with `ENABLE_TOOL_SEARCH`)
- Fixed `@`-file Tab completion replacing the entire prompt when used inside a slash command with an absolute path
- Fixed a stray `p` character appearing at the prompt on startup in macOS Terminal.app via Docker or SSH
- Fixed `${ENV_VAR}` placeholders in `headers` for HTTP/SSE/WebSocket MCP servers not being substituted before requests
- Fixed MCP OAuth client secret stored via `--client-secret` not being sent during token exchange for servers requiring `client_secret_post`
- Fixed `/skills` Enter key closing the dialog instead of pre-filling `/<skill-name>` in the prompt
- Fixed `/agents` detail view mislabeling built-in tools unavailable to subagents as “Unrecognized”
- Fixed MCP servers from plugins not spawning on Windows when the plugin cache was incomplete
- Fixed `/export` showing the current default model instead of the model the conversation actually used
- Fixed verbose output setting not persisting after restart
- Fixed `/usage` progress bars overlapping with their “Resets …” labels
- Fixed plugin MCP servers failing when `${user_config.*}` references an optional field left blank
- Fixed list items containing a sentence-final number wrapping the number onto its own line
- Fixed `/plan` and `/plan open` not acting on the existing plan when entering plan mode
- Fixed skills invoked before auto-compaction being re-executed against the next user message
- Fixed `/reload-plugins` and `/doctor` reporting load errors for disabled plugins
- Fixed Agent tool with `isolation: "worktree"` reusing stale worktrees from prior sessions
- Fixed disabled MCP servers appearing as “failed” in `/status`
- Fixed `TaskList` returning tasks in arbitrary filesystem order instead of sorted by ID
- Fixed spurious “GitHub API rate limit exceeded” hints when `gh` output contained PR titles mentioning “rate limit”
- Fixed SDK/bridge `read_file` not correctly enforcing size cap on growing files
- Fixed PR not linked to session when working in a git worktree
- Fixed `/doctor` warning about MCP server entries overridden by a higher-precedence scope
- Windows: removed false-positive “Windows requires ‘cmd /c’ wrapper” MCP config warning
- \[VSCode\] Fixed voice dictation’s first recording producing nothing on macOS while the microphone permission prompt is showing
[](#2-1-118)
2.1.118
April 23, 2026
- Added vim visual mode (`v`) and visual-line mode (`V`) with selection, operators, and visual feedback
- Merged `/cost` and `/stats` into `/usage` — both remain as typing shortcuts that open the relevant tab
- Create and switch between named custom themes from `/theme`, or hand-edit JSON files in `~/.claude/themes/`; plugins can also ship themes via a `themes/` directory
- Hooks can now invoke MCP tools directly via `type: "mcp_tool"`
- Added `DISABLE_UPDATES` env var to completely block all update paths including manual `claude update` — stricter than `DISABLE_AUTOUPDATER`
- WSL on Windows can now inherit Windows-side managed settings via the `wslInheritsWindowsSettings` policy key
- Auto mode: include `"$defaults"` in `autoMode.allow`, `autoMode.soft_deny`, or `autoMode.environment` to add custom rules alongside the built-in list instead of replacing it
- Added a “Don’t ask again” option to the auto mode opt-in prompt
- Added `claude plugin tag` to create release git tags for plugins with version validation
- `--continue`/`--resume` now find sessions that added the current directory via `/add-dir`
- `/color` now syncs the session accent color to claude.ai/code when Remote Control is connected
- The `/model` picker now honors `ANTHROPIC_DEFAULT_*_MODEL_NAME`/`_DESCRIPTION` overrides when using a custom `ANTHROPIC_BASE_URL` gateway
- When auto-update skips a plugin due to another plugin’s version constraint, the skip now appears in `/doctor` and the `/plugin` Errors tab
- Fixed `/mcp` menu hiding OAuth Authenticate/Re-authenticate actions for servers configured with `headersHelper`, and HTTP/SSE MCP servers with custom headers being stuck in “needs authentication” after a transient 401
- Fixed MCP servers whose OAuth token response omits `expires_in` requiring re-authentication every hour
- Fixed MCP step-up authorization silently refreshing instead of prompting for re-consent when the server’s `insufficient_scope` 403 names a scope the current token already has
- Fixed an unhandled promise rejection when an MCP server’s OAuth flow times out or is cancelled
- Fixed MCP OAuth refresh proceeding without its cross-process lock under contention
- Fixed macOS keychain race where a concurrent MCP token refresh could overwrite a freshly-refreshed OAuth token, causing unexpected “Please run /login” prompts
- Fixed OAuth token refresh failing when the server revokes a token before its local expiry time
- Fixed credential save crash on Linux/Windows corrupting `~/.claude/.credentials.json`
- Fixed `/login` having no effect in a session launched with `CLAUDE_CODE_OAUTH_TOKEN` — the env token is now cleared so disk credentials take effect
- Fixed unreadable text in the “new messages” scroll pill and `/plugin` badges
- Fixed plan acceptance dialog offering “auto mode” instead of “bypass permissions” when running with `--dangerously-skip-permissions`
- Fixed agent-type hooks failing with “Messages are required for agent hooks” when configured for events other than `Stop` or `SubagentStop`
- Fixed `prompt` hooks re-firing on tool calls made by an agent-hook verifier subagent
- Fixed `/fork` writing the full parent conversation to disk per fork — now writes a pointer and hydrates on read
- Fixed Alt+K / Alt+X / Alt+^ / Alt+\_ freezing keyboard input
- Fixed connecting to a remote session overwriting your local `model` setting in `~/.claude/settings.json`
- Fixed typeahead showing “No commands match” error when pasting file paths that start with `/`
- Fixed `plugin install` on an already-installed plugin not re-resolving a dependency installed at the wrong version
- Fixed unhandled errors from file watcher on invalid paths or fd exhaustion
- Fixed Remote Control sessions getting archived on transient CCR initialization blips during JWT refresh
- Fixed subagents resumed via `SendMessage` not restoring the explicit `cwd` they were spawned with
[](#2-1-117)
2.1.117
April 22, 2026
- Forked subagents can now be enabled on external builds by setting `CLAUDE_CODE_FORK_SUBAGENT=1`
- Agent frontmatter `mcpServers` are now loaded for main-thread agent sessions via `--agent`
- Improved `/model`: selections now persist across restarts even when the project pins a different model, and the startup header shows when the active model comes from a project or managed-settings pin
- The `/resume` command now offers to summarize stale, large sessions before re-reading them, matching the existing `--resume` behavior
- Faster startup when both local and claude.ai MCP servers are configured (concurrent connect now default)
- `plugin install` on an already-installed plugin now installs any missing dependencies instead of stopping at “already installed”
- Plugin dependency errors now say “not installed” with an install hint, and `claude plugin marketplace add` now auto-resolves missing dependencies from configured marketplaces
- Managed-settings `blockedMarketplaces` and `strictKnownMarketplaces` are now enforced on plugin install, update, refresh, and autoupdate
- Advisor Tool (experimental): dialog now carries an “experimental” label, learn-more link, and startup notification when enabled; sessions no longer get stuck with “Advisor tool result content could not be processed” errors on every prompt and `/compact`
- The `cleanupPeriodDays` retention sweep now also covers `~/.claude/tasks/`, `~/.claude/shell-snapshots/`, and `~/.claude/backups/`
- OpenTelemetry: `user_prompt` events now include `command_name` and `command_source` for slash commands; `cost.usage`, `token.usage`, `api_request`, and `api_error` now include an `effort` attribute when the model supports effort levels. Custom/MCP command names are redacted unless `OTEL_LOG_TOOL_DETAILS=1` is set
- Native builds on macOS and Linux: the `Glob` and `Grep` tools are replaced by embedded `bfs` and `ugrep` available through the Bash tool — faster searches without a separate tool round-trip (Windows and npm-installed builds unchanged)
- Windows: cached `where.exe` executable lookups per process for faster subprocess launches
- Default effort for Pro/Max subscribers on Opus 4.6 and Sonnet 4.6 is now `high` (was `medium`)
- Fixed Plain-CLI OAuth sessions dying with “Please run /login” when the access token expires mid-session — the token is now refreshed reactively on 401
- Fixed `WebFetch` hanging on very large HTML pages by truncating input before HTML-to-markdown conversion
- Fixed a crash when a proxy returns HTTP 204 No Content — now surfaces a clear error instead of a `TypeError`
- Fixed `/login` having no effect when launched with `CLAUDE_CODE_OAUTH_TOKEN` env var and that token expires
- Fixed prompt-input undo (`Ctrl+_`) doing nothing immediately after typing, and skipping a state on each undo step
- Fixed `NO_PROXY` not being respected for remote API requests when running under Bun
- Fixed rare spurious escape/return triggers when key names arrive as coalesced text over slow connections
- Fixed SDK `reload_plugins` reconnecting all user MCP servers serially
- Fixed Bedrock application-inference-profile requests failing with 400 when backed by Opus 4.7 with thinking disabled
- Fixed MCP `elicitation/create` requests auto-cancelling in print/SDK mode when the server finishes connecting mid-turn
- Fixed subagents running a different model than the main agent incorrectly flagging file reads with a malware warning
- Fixed idle re-render loop when background tasks are present, reducing memory growth on Linux
- \[VSCode\] Fixed “Manage Plugins” panel breaking when multiple large marketplaces are configured
- Fixed Opus 4.7 sessions showing inflated `/context` percentages and autocompacting too early — Claude Code was computing against a 200K context window instead of Opus 4.7’s native 1M
[](#2-1-116)
2.1.116
April 20, 2026
- `/resume` on large sessions is significantly faster (up to 67% on 40MB+ sessions) and handles sessions with many dead-fork entries more efficiently
- Faster MCP startup when multiple stdio servers are configured; `resources/templates/list` is now deferred to first `@`-mention
- Smoother fullscreen scrolling in VS Code, Cursor, and Windsurf terminals — `/terminal-setup` now configures the editor’s scroll sensitivity
- Thinking spinner now shows progress inline (“still thinking”, “thinking more”, “almost done thinking”), replacing the separate hint row
- `/config` search now matches option values (e.g. searching “vim” finds the Editor mode setting)
- `/doctor` can now be opened while Claude is responding, without waiting for the current turn to finish
- `/reload-plugins` and background plugin auto-update now auto-install missing plugin dependencies from marketplaces you’ve already added
- Bash tool now surfaces a hint when `gh` commands hit GitHub’s API rate limit, so agents can back off instead of retrying
- The Usage tab in Settings now shows your 5-hour and weekly usage immediately and no longer fails when the usage endpoint is rate-limited
- Agent frontmatter `hooks:` now fire when running as a main-thread agent via `--agent`
- Slash command menu now shows “No commands match” when your filter has zero results, instead of disappearing
- Security: sandbox auto-allow no longer bypasses the dangerous-path safety check for `rm`/`rmdir` targeting `/`, `$HOME`, or other critical system directories
- Claude Code and installer now use `https://downloads.claude.ai/claude-code-releases` instead of `https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases`
- Fixed Devanagari and other Indic scripts rendering with broken column alignment in the terminal UI
- Fixed Ctrl+- not triggering undo in terminals using the Kitty keyboard protocol (iTerm2, Ghostty, kitty, WezTerm, Windows Terminal)
- Fixed Cmd+Left/Right not jumping to line start/end in terminals that use the Kitty keyboard protocol (Warp fullscreen, kitty, Ghostty, WezTerm)
- Fixed Ctrl+Z hanging the terminal when Claude Code is launched via a wrapper process (e.g. `npx`, `bun run`)
- Fixed scrollback duplication in inline mode where resizing the terminal or large output bursts would repeat earlier conversation history
- Fixed modal search dialogs overflowing the screen at short terminal heights, hiding the search box and keyboard hints
- Fixed scattered blank cells and disappearing composer chrome in the VS Code integrated terminal during scrolling
- Fixed an intermittent API 400 error related to cache control TTL ordering that could occur when a parallel request completed during request setup
- Fixed `/branch` rejecting conversations with transcripts larger than 50MB
- Fixed `/resume` silently showing an empty conversation on large session files instead of reporting the load error
- Fixed `/plugin` Installed tab showing the same item twice when it appears under Needs attention or Favorites
- Fixed `/update` and `/tui` not working after entering a worktree mid-session
[](#2-1-114)
2.1.114
April 18, 2026
- Fixed a crash in the permission dialog when an agent teams teammate requested tool permission
[](#2-1-113)
2.1.113
April 17, 2026
- Changed the CLI to spawn a native Claude Code binary (via a per-platform optional dependency) instead of bundled JavaScript
- Added `sandbox.network.deniedDomains` setting to block specific domains even when a broader `allowedDomains` wildcard would otherwise permit them
- Fullscreen mode: Shift+↑/↓ now scrolls the viewport when extending a selection past the visible edge
- `Ctrl+A` and `Ctrl+E` now move to the start/end of the current logical line in multiline input, matching readline behavior
- Windows: `Ctrl+Backspace` now deletes the previous word
- Long URLs in responses and bash output stay clickable when they wrap across lines (in terminals with OSC 8 hyperlinks)
- Improved `/loop`: pressing Esc now cancels pending wakeups, and wakeups display as “Claude resuming /loop wakeup” for clarity
- `/extra-usage` now works from Remote Control (mobile/web) clients
- Remote Control clients can now query `@`-file autocomplete suggestions
- Improved `/ultrareview`: faster launch with parallelized checks, diffstat in the launch dialog, and animated launching state
- Subagents that stall mid-stream now fail with a clear error after 10 minutes instead of hanging silently
- Bash tool: multi-line commands whose first line is a comment now show the full command in the transcript, closing a UI-spoofing vector
- Running `cd <current-directory> && git …` no longer triggers a permission prompt when the `cd` is a no-op
- Security: on macOS, `/private/{etc,var,tmp,home}` paths are now treated as dangerous removal targets under `Bash(rm:*)` allow rules
- Security: Bash deny rules now match commands wrapped in `env`/`sudo`/`watch`/`ionice`/`setsid` and similar exec wrappers
- Security: `Bash(find:*)` allow rules no longer auto-approve `find -exec`/`-delete`
- Fixed MCP concurrent-call timeout handling where a message for one tool call could silently disarm another call’s watchdog
- Fixed Cmd-backspace / `Ctrl+U` to once again delete from the cursor to the start of the line
- Fixed markdown tables breaking when a cell contains an inline code span with a pipe character
- Fixed session recap auto-firing while composing unsent text in the prompt
- Fixed `/copy` “Full response” not aligning markdown table columns for pasting into GitHub, Notion, or Slack
- Fixed messages typed while viewing a running subagent being hidden from its transcript and misattributed to the parent AI
- Fixed Bash `dangerouslyDisableSandbox` running commands outside the sandbox without a permission prompt
- Fixed `/effort auto` confirmation — now says “Effort level set to max” to match the status bar label
- Fixed the “copied N chars” toast overcounting emoji and other multi-code-unit characters
- Fixed `/insights` crashing with `EBUSY` on Windows
- Fixed exit confirmation dialog mislabeling one-shot scheduled tasks as recurring — now shows a countdown
- Fixed slash/@ completion menu not sitting flush against the prompt border in fullscreen mode
- Fixed `CLAUDE_CODE_EXTRA_BODY` `output_config.effort` causing 400 errors on subagent calls to models that don’t support effort and on Vertex AI
- Fixed prompt cursor disappearing when `NO_COLOR` is set
- Fixed `ToolSearch` ranking so pasted MCP tool names surface the actual tool instead of description-matching siblings
- Fixed compacting a resumed long-context session failing with “Extra usage is required for long context requests”
- Fixed `plugin install` succeeding when a dependency version conflicts with an already-installed plugin — now reports `range-conflict`
- Fixed “Refine with Ultraplan” not showing the remote session URL in the transcript
- Fixed SDK image content blocks that fail to process crashing the session — now degrade to a text placeholder
- Fixed Remote Control sessions not streaming subagent transcripts
- Fixed Remote Control sessions not being archived when Claude Code exits
- Fixed `thinking.type.enabled is not supported` 400 error when using Opus 4.7 via a Bedrock Application Inference Profile ARN
[](#2-1-112)
2.1.112
April 16, 2026
- Fixed “claude-opus-4-7 is temporarily unavailable” for auto mode
[](#2-1-111)
2.1.111
April 16, 2026
- Claude Opus 4.7 xhigh is now available! Use /effort to tune speed vs. intelligence
- Auto mode is now available for Max subscribers when using Opus 4.7
- Added `xhigh` effort level for Opus 4.7, sitting between `high` and `max`. Available via `/effort`, `--effort`, and the model picker; other models fall back to `high`
- `/effort` now opens an interactive slider when called without arguments, with arrow-key navigation between levels and Enter to confirm
- Added “Auto (match terminal)” theme option that matches your terminal’s dark/light mode — select it from `/theme`
- Added `/less-permission-prompts` skill — scans transcripts for common read-only Bash and MCP tool calls and proposes a prioritized allowlist for `.claude/settings.json`
- Added `/ultrareview` for running comprehensive code review in the cloud using parallel multi-agent analysis and critique — invoke with no arguments to review your current branch, or `/ultrareview <PR#>` to fetch and review a specific GitHub PR
- Auto mode no longer requires `--enable-auto-mode`
- Windows: PowerShell tool is progressively rolling out. Opt in or out with `CLAUDE_CODE_USE_POWERSHELL_TOOL`. On Linux and macOS, enable with `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` (requires `pwsh` on PATH)
- Read-only bash commands with glob patterns (e.g. `ls *.ts`) and commands starting with `cd <project-dir> &&` no longer trigger a permission prompt
- Suggest the closest matching subcommand when `claude <word>` is invoked with a near-miss typo (e.g. `claude udpate` → “Did you mean `claude update`?”)
- Plan files are now named after your prompt (e.g. `fix-auth-race-snug-otter.md`) instead of purely random words
- Improved `/setup-vertex` and `/setup-bedrock` to show the actual `settings.json` path when `CLAUDE_CONFIG_DIR` is set, seed model candidates from existing pins on re-run, and offer a “with 1M context” option for supported models
- `/skills` menu now supports sorting by estimated token count — press `t` to toggle
- `Ctrl+U` now clears the entire input buffer (previously: delete to start of line); press `Ctrl+Y` to restore
- `Ctrl+L` now forces a full screen redraw in addition to clearing the prompt input
- Transcript view footer now shows `[` (dump to scrollback) and `v` (open in editor) shortcuts
- The “+N lines” marker for truncated long pastes is now a full-width rule for easier scanning
- Headless `--output-format stream-json` now includes `plugin_errors` on the init event when plugins are demoted for unsatisfied dependencies
- Added `OTEL_LOG_RAW_API_BODIES` environment variable to emit full API request and response bodies as OpenTelemetry log events for debugging
- Suppressed spurious decompression, network, and transient error messages that could appear in the TUI during normal operation
- Reverted the v2.1.110 cap on non-streaming fallback retries — it traded long waits for more outright failures during API overload
- Fixed terminal display tearing (random characters, drifting input) in iTerm2 + tmux setups when terminal notifications are sent
- Fixed `@` file suggestions re-scanning the entire project on every turn in non-git working directories, and showing only config files in freshly-initialized git repos with no tracked files
- Fixed LSP diagnostics from before an edit appearing after it, causing the model to re-read files it just edited
- Fixed tab-completing `/resume` immediately resuming an arbitrary titled session instead of showing the session picker
- Fixed `/context` grid rendering with extra blank lines between rows
- Fixed `/clear` dropping the session name set by `/rename`, causing statusline output to lose `session_name`
- Improved plugin error handling: dependency errors now distinguish conflicting, invalid, and overly complex version requirements; fixed stale resolved versions after `plugin update`; `plugin install` now recovers from interrupted prior installs
- Fixed Claude calling a non-existent `commit` skill and showing “Unknown skill: commit” for users without a custom `/commit` command
- Fixed 429 rate-limit errors on Bedrock/Vertex/Foundry referencing status.claude.com (it only covers Anthropic-operated providers)
- Fixed feedback surveys appearing back-to-back after dismissing one
- Fixed bare URLs in bash/PowerShell/MCP tool output being unclickable when the terminal wraps them across lines
- Windows: `CLAUDE_ENV_FILE` and SessionStart hook environment files now apply (previously a no-op)
- Windows: permission rules with drive-letter paths are now correctly root-anchored, and paths differing only by drive-letter case are recognized as the same path
[](#2-1-110)
2.1.110
April 15, 2026
- Added `/tui` command and `tui` setting — run `/tui fullscreen` to switch to flicker-free rendering in the same conversation
- Added push notification tool — Claude can send mobile push notifications when Remote Control and “Push when Claude decides” config are enabled
- Changed `Ctrl+O` to toggle between normal and verbose transcript only; focus view is now toggled separately with the new `/focus` command
- Added `autoScrollEnabled` config to disable conversation auto-scroll in fullscreen mode
- Added option to show Claude’s last response as commented context in the `Ctrl+G` external editor (enable via `/config`)
- Improved `/plugin` Installed tab — items needing attention and favorites appear at the top, disabled items are hidden behind a fold, and `f` favorites the selected item
- Improved `/doctor` to warn when an MCP server is defined in multiple config scopes with different endpoints
- `--resume`/`--continue` now resurrects unexpired scheduled tasks
- `/context`, `/exit`, and `/reload-plugins` now work from Remote Control (mobile/web) clients
- Write tool now informs the model when you edit the proposed content in the IDE diff before accepting
- Bash tool now enforces the documented maximum timeout instead of accepting arbitrarily large values
- SDK/headless sessions now read `TRACEPARENT`/`TRACESTATE` from the environment for distributed trace linking
- Session recap is now enabled for users with telemetry disabled (Bedrock, Vertex, Foundry, `DISABLE_TELEMETRY`). Opt out via `/config` or `CLAUDE_CODE_ENABLE_AWAY_SUMMARY=0`.
- Fixed MCP tool calls hanging indefinitely when the server connection drops mid-response on SSE/HTTP transports
- Fixed non-streaming fallback retries causing multi-minute hangs when the API is unreachable
- Fixed session recap, local slash-command output, and other system status lines not appearing in focus mode
- Fixed high CPU usage in fullscreen when text is selected while a tool is running
- Fixed plugin install not honoring dependencies declared in `plugin.json` when the marketplace entry omits them; `/plugin` install now lists auto-installed dependencies
- Fixed skills with `disable-model-invocation: true` failing when invoked via `/<skill>` mid-message
- Fixed `--resume` sometimes showing the first prompt instead of the `/rename` name for sessions still running or exited uncleanly
- Fixed queued messages briefly appearing twice during multi-tool-call turns
- Fixed session cleanup not removing the full session directory including subagent transcripts
- Fixed dropped keystrokes after the CLI relaunches (e.g. `/tui`, provider setup wizards)
- Fixed garbled startup rendering in macOS Terminal.app and other terminals that don’t support synchronized output
- Hardened “Open in editor” actions against command injection from untrusted filenames
- Fixed `PermissionRequest` hooks returning `updatedInput` not being re-checked against `permissions.deny` rules; `setMode:'bypassPermissions'` updates now respect `disableBypassPermissionsMode`
- Fixed `PreToolUse` hook `additionalContext` being dropped when the tool call fails
- Fixed stdio MCP servers that print stray non-JSON lines to stdout being disconnected on the first stray line (regression in 2.1.105)
- Fixed headless/SDK session auto-title firing an extra Haiku request when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` or `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` is set
- Fixed potential excessive memory allocation when piped (non-TTY) Ink output contains a single very wide line
- Fixed `/skills` menu not scrolling when the list overflows the modal in fullscreen mode
- Fixed Remote Control sessions showing a generic error instead of prompting for re-login when the session is too old
- Fixed Remote Control session renames from claude.ai not persisting the title to the local CLI session
[](#2-1-109)
2.1.109
April 15, 2026
- Improved the extended-thinking indicator with a rotating progress hint
[](#2-1-108)
2.1.108
April 14, 2026
- Added `ENABLE_PROMPT_CACHING_1H` env var to opt into 1-hour prompt cache TTL on API key, Bedrock, Vertex, and Foundry (`ENABLE_PROMPT_CACHING_1H_BEDROCK` is deprecated but still honored), and `FORCE_PROMPT_CACHING_5M` to force 5-minute TTL
- Added recap feature to provide context when returning to a session, configurable in `/config` and manually invocable with `/recap`; force with `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` if telemetry disabled.
- The model can now discover and invoke built-in slash commands like `/init`, `/review`, and `/security-review` via the Skill tool
- `/undo` is now an alias for `/rewind`
- Improved `/model` to warn before switching models mid-conversation, since the next response re-reads the full history uncached
- Improved `/resume` picker to default to sessions from the current directory; press `Ctrl+A` to show all projects
- Improved error messages: server rate limits are now distinguished from plan usage limits; 5xx/529 errors show a link to status.claude.com; unknown slash commands suggest the closest match
- Reduced memory footprint for file reads, edits, and syntax highlighting by loading language grammars on demand
- Added “verbose” indicator when viewing the detailed transcript (`Ctrl+O`)
- Added a warning at startup when prompt caching is disabled via `DISABLE_PROMPT_CACHING*` environment variables
- Fixed paste not working in the `/login` code prompt (regression in 2.1.105)
- Fixed subscribers who set `DISABLE_TELEMETRY` falling back to 5-minute prompt cache TTL instead of 1 hour
- Fixed Agent tool prompting for permission in auto mode when the safety classifier’s transcript exceeded its context window
- Fixed Bash tool producing no output when `CLAUDE_ENV_FILE` (e.g. `~/.zprofile`) ends with a `#` comment line
- Fixed `claude --resume <session-id>` losing the session’s custom name and color set via `/rename`
- Fixed session titles showing placeholder example text when the first message is a short greeting
- Fixed terminal escape codes appearing as garbage text in the prompt input after `--teleport`
- Fixed `/feedback` retry: pressing Enter to resubmit after a failure now works without first editing the description
- Fixed `--teleport` and `--resume <id>` precondition errors (e.g. dirty git tree, session not found) exiting silently instead of showing the error message
- Fixed Remote Control session titles set in the web UI being overwritten by auto-generated titles after the third message
- Fixed `--resume` truncating sessions when the transcript contained a self-referencing message
- Fixed transcript write failures (e.g., disk full) being silently dropped instead of being logged
- Fixed diacritical marks (accents, umlauts, cedillas) being dropped from responses when the `language` setting is configured
- Fixed policy-managed plugins never auto-updating when running from a different project than where they were first installed
[](#2-1-107)
2.1.107
April 14, 2026
- Show thinking hints sooner during long operations
[](#2-1-105)
2.1.105
April 13, 2026
- Added `path` parameter to the `EnterWorktree` tool to switch into an existing worktree of the current repository
- Added PreCompact hook support: hooks can now block compaction by exiting with code 2 or returning `{"decision":"block"}`
- Added background monitor support for plugins via a top-level `monitors` manifest key that auto-arms at session start or on skill invoke
- `/proactive` is now an alias for `/loop`
- Improved stalled API stream handling: streams now abort after 5 minutes of no data and retry non-streaming instead of hanging indefinitely
- Improved network error messages: connection errors now show a retry message immediately instead of a silent spinner
- Improved file write display: long single-line writes (e.g. minified JSON) are now truncated in the UI instead of paginating across many screens
- Improved `/doctor` layout with status icons; press `f` to have Claude fix reported issues
- Improved `/config` labels and descriptions for clarity
- Improved skill description handling: raised the listing cap from 250 to 1,536 characters and added a startup warning when descriptions are truncated
- Improved `WebFetch` to strip `<style>` and `<script>` contents from fetched pages so CSS-heavy pages no longer exhaust the content budget before reaching actual text
- Improved stale agent worktree cleanup to remove worktrees whose PR was squash-merged instead of keeping them indefinitely
- Improved MCP large-output truncation prompt to give format-specific recipes (e.g. `jq` for JSON, computed Read chunk sizes for text)
- Fixed images attached to queued messages (sent while Claude is working) being dropped
- Fixed screen going blank when the prompt input wraps to a second line in long conversations
- Fixed leading whitespace getting copied when selecting multi-line assistant responses in fullscreen mode
- Fixed leading whitespace being trimmed from assistant messages, breaking ASCII art and indented diagrams
- Fixed garbled bash output when commands print clickable file links (e.g. Python `rich`/`loguru` logging)
- Fixed alt+enter not inserting a newline in terminals using ESC-prefix alt encoding, and Ctrl+J not inserting a newline (regression in 2.1.100)
- Fixed duplicate “Creating worktree” text in EnterWorktree/ExitWorktree tool display
- Fixed queued user prompts disappearing from focus mode
- Fixed one-shot scheduled tasks re-firing repeatedly when the file watcher missed the post-fire cleanup
- Fixed inbound channel notifications being silently dropped after the first message for Team/Enterprise users
- Fixed marketplace plugins with `package.json` and lockfile not having dependencies installed automatically after install/update
- Fixed marketplace auto-update leaving the official marketplace in a broken state when a plugin process holds files open during the update
- Fixed “Resume this session with…” hint not printing on exit after `/resume`, `--worktree`, or `/branch`
- Fixed feedback survey shortcut keys firing when typed at the end of a longer prompt
- Fixed stdio MCP server emitting malformed (non-JSON) output hanging the session instead of failing fast with “Connection closed”
- Fixed MCP tools missing on the first turn of headless/remote-trigger sessions when MCP servers connect asynchronously
- Fixed `/model` picker on AWS Bedrock in non-US regions persisting invalid `us.*` model IDs to `settings.json` when inference profile discovery is still in-flight
- Fixed 429 rate-limit errors showing a raw JSON dump instead of a clean message for API-key, Bedrock, and Vertex users
- Fixed crash on resume when session contains malformed text blocks
- Fixed `/help` dropping the tab bar, Shortcuts heading, and footer at short terminal heights
- Fixed malformed keybinding entry values in `keybindings.json` being silently loaded instead of rejected with a clear error
- Fixed `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` in one project’s settings permanently disabling usage metrics for all projects on the machine
- Fixed washed-out 16-color palette when using Ghostty, Kitty, Alacritty, WezTerm, foot, rio, or Contour over SSH/mosh
- Fixed Bash tool suggesting `acceptEdits` permission mode when exiting plan mode would downgrade from a higher permission level
[](#2-1-101)
2.1.101
April 10, 2026
- Added `/team-onboarding` command to generate a teammate ramp-up guide from your local Claude Code usage
- Added OS CA certificate store trust by default, so enterprise TLS proxies work without extra setup (set `CLAUDE_CODE_CERT_STORE=bundled` to use only bundled CAs)
- `/ultraplan` and other remote-session features now auto-create a default cloud environment instead of requiring web setup first
- Improved brief mode to retry once when Claude responds with plain text instead of a structured message
- Improved focus mode: Claude now writes more self-contained summaries since it knows you only see its final message
- Improved tool-not-available errors to explain why and how to proceed when the model calls a tool that exists but isn’t available in the current context
- Improved rate-limit retry messages to show which limit was hit and when it resets instead of an opaque seconds countdown
- Improved refusal error messages to include the API-provided explanation when available
- Improved `claude -p --resume <name>` to accept session titles set via `/rename` or `--name`
- Improved settings resilience: an unrecognized hook event name in `settings.json` no longer causes the entire file to be ignored
- Improved plugin hooks from plugins force-enabled by managed settings to run when `allowManagedHooksOnly` is set
- Improved `/plugin` and `claude plugin update` to show a warning when the marketplace could not be refreshed, instead of silently reporting a stale version
- Improved plan mode to hide the “Refine with Ultraplan” option when the user’s org or auth setup can’t reach Claude Code on the web
- Improved beta tracing to honor `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_DETAILS`, and `OTEL_LOG_TOOL_CONTENT`; sensitive span attributes are no longer emitted unless opted in
- Improved SDK `query()` to clean up subprocess and temp files when consumers `break` from `for await` or use `await using`
- Fixed a command injection vulnerability in the POSIX `which` fallback used by LSP binary detection
- Fixed a memory leak where long sessions retained dozens of historical copies of the message list in the virtual scroller
- Fixed `--resume`/`--continue` losing conversation context on large sessions when the loader anchored on a dead-end branch instead of the live conversation
- Fixed `--resume` chain recovery bridging into an unrelated subagent conversation when a subagent message landed near a main-chain write gap
- Fixed a crash on `--resume` when a persisted Edit/Write tool result was missing its `file_path`
- Fixed a hardcoded 5-minute request timeout that aborted slow backends (local LLMs, extended thinking, slow gateways) regardless of `API_TIMEOUT_MS`
- Fixed `permissions.deny` rules not overriding a PreToolUse hook’s `permissionDecision: "ask"` — previously the hook could downgrade a deny into a prompt
- Fixed `--setting-sources` without `user` causing background cleanup to ignore `cleanupPeriodDays` and delete conversation history older than 30 days
- Fixed Bedrock SigV4 authentication failing with 403 when `ANTHROPIC_AUTH_TOKEN`, `apiKeyHelper`, or `ANTHROPIC_CUSTOM_HEADERS` set an Authorization header
- Fixed `claude -w <name>` failing with “already exists” after a previous session’s worktree cleanup left a stale directory
- Fixed subagents not inheriting MCP tools from dynamically-injected servers
- Fixed sub-agents running in isolated worktrees being denied Read/Edit access to files inside their own worktree
- Fixed sandboxed Bash commands failing with `mktemp: No such file or directory` after a fresh boot
- Fixed `claude mcp serve` tool calls failing with “Tool execution failed” in MCP clients that validate `outputSchema`
- Fixed `RemoteTrigger` tool’s `run` action sending an empty body and being rejected by the server
- Fixed several `/resume` picker issues: narrow default view hiding sessions from other projects, unreachable preview on Windows Terminal, incorrect cwd in worktrees, session-not-found errors not surfacing in stderr, terminal title not being set, and resume hint overlapping the prompt input
- Fixed Grep tool ENOENT when the embedded ripgrep binary path becomes stale (VS Code extension auto-update, macOS App Translocation); now falls back to system `rg` and self-heals mid-session
- Fixed `/btw` writing a copy of the entire conversation to disk on every use
- Fixed `/context` Free space and Messages breakdown disagreeing with the header percentage
- Fixed several plugin issues: slash commands resolving to the wrong plugin with duplicate `name:` frontmatter, `/plugin update` failing with `ENAMETOOLONG`, Discover showing already-installed plugins, directory-source plugins loading from a stale version cache, and skills not honoring `context: fork` and `agent` frontmatter fields
- Fixed the `/mcp` menu offering OAuth-specific actions for MCP servers configured with `headersHelper`; Reconnect is now offered instead to re-invoke the helper script
- Fixed `ctrl+]`, `ctrl+\`, and `ctrl+^` keybindings not firing in terminals that send raw C0 control bytes (Terminal.app, default iTerm2, xterm)
- Fixed `/login` OAuth URL rendering with padding that prevented clean mouse selection
- Fixed rendering issues: flicker in non-fullscreen mode when content above the visible area changed, terminal scrollback being wiped during long sessions in non-fullscreen mode, and mouse-scroll escape sequences occasionally leaking into the prompt as text
- Fixed crash when `settings.json` env values are numbers instead of strings
- Fixed in-app settings writes (e.g. `/add-dir --remember`, `/config`) not refreshing the in-memory snapshot, preventing removed directories from being revoked mid-session
- Fixed custom keybindings (`~/.claude/keybindings.json`) not loading on Bedrock, Vertex, and other third-party providers
- Fixed `claude --continue -p` not correctly continuing sessions created by `-p` or the SDK
- Fixed several Remote Control issues: worktrees removed on session crash, connection failures not persisting in the transcript, spurious “Disconnected” indicator in brief mode for local sessions, and `/remote-control` failing over SSH when only `CLAUDE_CODE_ORGANIZATION_UUID` is set
- Fixed `/insights` sometimes omitting the report file link from its response
- \[VSCode\] Fixed the file attachment below the chat input not clearing when the last editor tab is closed
[](#2-1-98)
2.1.98
April 9, 2026
- Added interactive Google Vertex AI setup wizard accessible from the login screen when selecting “3rd-party platform”, guiding you through GCP authentication, project and region configuration, credential verification, and model pinning
- Added `CLAUDE_CODE_PERFORCE_MODE` env var: when set, Edit/Write/NotebookEdit fail on read-only files with a `p4 edit` hint instead of silently overwriting them
- Added Monitor tool for streaming events from background scripts
- Added subprocess sandboxing with PID namespace isolation on Linux when `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` is set, and `CLAUDE_CODE_SCRIPT_CAPS` env var to limit per-session script invocations
- Added `--exclude-dynamic-system-prompt-sections` flag to print mode for improved cross-user prompt caching
- Added `workspace.git_worktree` to the status line JSON input, set whenever the current directory is inside a linked git worktree
- Added W3C `TRACEPARENT` env var to Bash tool subprocesses when OTEL tracing is enabled, so child-process spans correctly parent to Claude Code’s trace tree
- LSP: Claude Code now identifies itself to language servers via `clientInfo` in the initialize request
- Fixed a Bash tool permission bypass where a backslash-escaped flag could be auto-allowed as read-only and lead to arbitrary code execution
- Fixed compound Bash commands bypassing forced permission prompts for safety checks and explicit ask rules in auto and bypass-permissions modes
- Fixed read-only commands with env-var prefixes not prompting unless the var is known-safe (`LANG`, `TZ`, `NO_COLOR`, etc.)
- Fixed redirects to `/dev/tcp/...` or `/dev/udp/...` not prompting instead of auto-allowing
- Fixed stalled streaming responses timing out instead of falling back to non-streaming mode
- Fixed 429 retries burning all attempts in ~13s when the server returns a small `Retry-After` — exponential backoff now applies as a minimum
- Fixed MCP OAuth `oauth.authServerMetadataUrl` config override not being honored on token refresh after restart, affecting ADFS and similar IdPs
- Fixed capital letters being dropped to lowercase on xterm and VS Code integrated terminal when the kitty keyboard protocol is active
- Fixed macOS text replacements deleting the trigger word instead of inserting the substitution
- Fixed `--dangerously-skip-permissions` being silently downgraded to accept-edits mode after approving a write to a protected path via Bash
- Fixed managed-settings allow rules remaining active after an admin removed them, until process restart
- Fixed `permissions.additionalDirectories` changes not applying mid-session — removed directories lose access immediately and added ones work without restart
- Fixed removing a directory from `additionalDirectories` revoking access to the same directory passed via `--add-dir`
- Fixed `Bash(cmd:*)` and `Bash(git commit *)` wildcard permission rules failing to match commands with extra spaces or tabs
- Fixed `Bash(...)` deny rules being downgraded to a prompt for piped commands that mix `cd` with other segments
- Fixed false Bash permission prompts for `cut -d /`, `paste -d /`, `column -s /`, `awk '{print $1}' file`, and filenames containing `%`
- Fixed permission rules with names matching JavaScript prototype properties (e.g. `toString`) causing `settings.json` to be silently ignored
- Fixed agent team members not inheriting the leader’s permission mode when using `--dangerously-skip-permissions`
- Fixed a crash in fullscreen mode when hovering over MCP tool results
- Fixed copying wrapped URLs in fullscreen mode inserting spaces at line breaks
- Fixed file-edit diffs disappearing from the UI on `--resume` when the edited file was larger than 10KB
- Fixed several `/resume` picker issues: `--resume <name>` opening uneditable, filter reload wiping search state, empty list swallowing arrow keys, cross-project staleness, and transient task-status text replacing conversation summaries
- Fixed `/export` not honoring absolute paths and `~`, and silently rewriting user-supplied extensions to `.txt`
- Fixed `/effort max` being denied for unknown or future model IDs
- Fixed slash command picker breaking when a plugin’s frontmatter `name` is a YAML boolean keyword
- Fixed rate-limit upsell text being hidden after message remounts
- Fixed MCP tools with `_meta["anthropic/maxResultSizeChars"]` not bypassing the token-based persist layer
- Fixed voice mode leaking dozens of space characters into the input when re-holding the push-to-talk key while the previous transcript is still processing
- Fixed `DISABLE_AUTOUPDATER` not fully suppressing the npm registry version check and symlink modification on npm-based installs
- Fixed a memory leak where Remote Control permission handler entries were retained for the lifetime of the session
- Fixed background subagents that fail with an error not reporting partial progress to the parent agent
- Fixed prompt-type Stop/SubagentStop hooks failing on long sessions, and hook evaluator API errors showing “JSON validation failed” instead of the real message
- Fixed feedback survey rendering when dismissed
- Fixed Bash `grep -f FILE` / `rg -f FILE` not prompting when reading a pattern file outside the working directory
- Fixed stale subagent worktree cleanup removing worktrees that contain untracked files
- Fixed `sandbox.network.allowMachLookup` not taking effect on macOS
- Improved `/resume` filter hint labels and added project/worktree/branch names in the filter indicator
- Improved footer indicators (Focus, notifications) to stay on the mode-indicator row instead of wrapping at narrow terminal widths
- Improved `/agents` with a tabbed layout: a Running tab shows live subagents, and the Library tab adds Run agent and View running instance actions
- Improved `/reload-plugins` to pick up plugin-provided skills without requiring a restart
- Improved Accept Edits mode to auto-approve filesystem commands prefixed with safe env vars or process wrappers
- Improved Vim mode: `j`/`k` in NORMAL mode now navigate history and select the footer pill at the input boundary
- Improved hook errors in the transcript to include the first line of stderr for self-diagnosis without `--debug`
- Improved OTEL tracing: interaction spans now correctly wrap full turns under concurrent SDK calls, and headless turns end spans per-turn
- Improved transcript entries to carry final token usage instead of streaming placeholders
- Updated the `/claude-api` skill to cover Managed Agents alongside Claude API
- \[VSCode\] Fixed false-positive “requires git-bash” error on Windows when `CLAUDE_CODE_GIT_BASH_PATH` is set or Git is installed at a default location
- Fixed `CLAUDE_CODE_MAX_CONTEXT_TOKENS` to honor `DISABLE_COMPACT` when it is set.
- Dropped `/compact` hints when `DISABLE_COMPACT` is set.
[](#2-1-97)
2.1.97
April 8, 2026
- Added focus view toggle (`Ctrl+O`) in `NO_FLICKER` mode showing prompt, one-line tool summary with edit diffstats, and final response
- Added `refreshInterval` status line setting to re-run the status line command every N seconds
- Added `workspace.git_worktree` to the status line JSON input, set when the current directory is inside a linked git worktree
- Added `● N running` indicator in `/agents` next to agent types with live subagent instances
- Added syntax highlighting for Cedar policy files (`.cedar`, `.cedarpolicy`)
- Fixed `--dangerously-skip-permissions` being silently downgraded to accept-edits mode after approving a write to a protected path
- Fixed and hardened Bash tool permissions, tightening checks around env-var prefixes and network redirects, and reducing false prompts on common commands
- Fixed permission rules with names matching JavaScript prototype properties (e.g. `toString`) causing `settings.json` to be silently ignored
- Fixed managed-settings allow rules remaining active after an admin removed them until process restart
- Fixed `permissions.additionalDirectories` changes in settings not applying mid-session
- Fixed removing a directory from `settings.permissions.additionalDirectories` revoking access to the same directory passed via `--add-dir`
- Fixed MCP HTTP/SSE connections accumulating ~50 MB/hr of unreleased buffers when servers reconnect
- Fixed MCP OAuth `oauth.authServerMetadataUrl` not being honored on token refresh after restart, fixing ADFS and similar IdPs
- Fixed 429 retries burning all attempts in ~13 seconds when the server returns a small `Retry-After` — exponential backoff now applies as a minimum
- Fixed rate-limit upgrade options disappearing after context compaction
- Fixed several `/resume` picker issues: `--resume <name>` opening uneditable, Ctrl+A reload wiping search, empty list swallowing navigation, task-status text replacing conversation summary, and cross-project staleness
- Fixed file-edit diffs disappearing on `--resume` when the edited file was larger than 10KB
- Fixed `--resume` cache misses and lost mid-turn input from attachment messages not being saved to the transcript
- Fixed messages typed while Claude is working not being persisted to the transcript
- Fixed prompt-type `Stop`/`SubagentStop` hooks failing on long sessions, and hook evaluator API errors displaying “JSON validation failed” instead of the actual message
- Fixed subagents with worktree isolation or `cwd:` override leaking their working directory back to the parent session’s Bash tool
- Fixed compaction writing duplicate multi-MB subagent transcript files on prompt-too-long retries
- Fixed `claude plugin update` reporting “already at the latest version” for git-based marketplace plugins when the remote had newer commits
- Fixed slash command picker breaking when a plugin’s frontmatter `name` is a YAML boolean keyword
- Fixed copying wrapped URLs in `NO_FLICKER` mode inserting spaces at line breaks
- Fixed scroll rendering artifacts in `NO_FLICKER` mode when running inside zellij
- Fixed a crash in `NO_FLICKER` mode when hovering over MCP tool results
- Fixed a `NO_FLICKER` mode memory leak where API retries left stale streaming state
- Fixed slow mouse-wheel scrolling in `NO_FLICKER` mode on Windows Terminal
- Fixed custom status line not displaying in `NO_FLICKER` mode on terminals shorter than 24 rows
- Fixed Shift+Enter and Alt/Cmd+arrow shortcuts not working in Warp with `NO_FLICKER` mode
- Fixed Korean/Japanese/Unicode text becoming garbled when copied in no-flicker mode on Windows
- Fixed Bedrock SigV4 authentication failing when `AWS_BEARER_TOKEN_BEDROCK` or `ANTHROPIC_BEDROCK_BASE_URL` are set to empty strings (as GitHub Actions does for unset inputs)
- Improved Accept Edits mode to auto-approve filesystem commands prefixed with safe env vars or process wrappers (e.g. `LANG=C rm foo`, `timeout 5 mkdir out`)
- Improved auto mode and bypass-permissions mode to auto-approve sandbox network access prompts
- Improved sandbox: `sandbox.network.allowMachLookup` now takes effect on macOS
- Improved image handling: pasted and attached images are now compressed to the same token budget as images read via the Read tool
- Improved slash command and `@`-mention completion to trigger after CJK sentence punctuation, so Japanese/Chinese input no longer requires a space before `/` or `@`
- Improved Bridge sessions to show the local git repo, branch, and working directory on the claude.ai session card
- Improved footer layout: indicators (Focus, notifications) now stay on the mode-indicator row instead of wrapping below
- Improved context-low warning to show as a transient footer notification instead of a persistent row
- Improved markdown blockquotes to show a continuous left bar across wrapped lines
- Improved session transcript size by skipping empty hook entries and capping stored pre-edit file copies
- Improved transcript accuracy: per-block entries now carry the final token usage instead of the streaming placeholder
- Improved Bash tool OTEL tracing: subprocesses now inherit a W3C `TRACEPARENT` env var when tracing is enabled
- Updated `/claude-api` skill to cover Managed Agents alongside the Claude API
[](#2-1-96)
2.1.96
April 8, 2026
- Fixed Bedrock requests failing with `403 "Authorization header is missing"` when using `AWS_BEARER_TOKEN_BEDROCK` or `CLAUDE_CODE_SKIP_BEDROCK_AUTH` (regression in 2.1.94)
[](#2-1-94)
2.1.94
April 7, 2026
- Added support for Amazon Bedrock powered by Mantle, set `CLAUDE_CODE_USE_MANTLE=1`
- Changed default effort level from medium to high for API-key, Bedrock/Vertex/Foundry, Team, and Enterprise users (control this with `/effort`)
- Added compact `Slacked #channel` header with a clickable channel link for Slack MCP send-message tool calls
- Added `keep-coding-instructions` frontmatter field support for plugin output styles
- Added `hookSpecificOutput.sessionTitle` to `UserPromptSubmit` hooks for setting the session title
- Plugin skills declared via `"skills": ["./"]` now use the skill’s frontmatter `name` for the invocation name instead of the directory basename, giving a stable name across install methods
- Fixed agents appearing stuck after a 429 rate-limit response with a long Retry-After header — the error now surfaces immediately instead of silently waiting
- Fixed Console login on macOS silently failing with “Not logged in” when the login keychain is locked or its password is out of sync — the error is now surfaced and `claude doctor` diagnoses the fix
- Fixed plugin skill hooks defined in YAML frontmatter being silently ignored
- Fixed plugin hooks failing with “No such file or directory” when `CLAUDE_PLUGIN_ROOT` was not set
- Fixed `${CLAUDE_PLUGIN_ROOT}` resolving to the marketplace source directory instead of the installed cache for local-marketplace plugins on startup
- Fixed scrollback showing the same diff repeated and blank pages in long-running sessions
- Fixed multiline user prompts in the transcript indenting wrapped lines under the `❯` caret instead of under the text
- Fixed Shift+Space inserting the literal word “space” instead of a space character in search inputs
- Fixed hyperlinks opening two browser tabs when clicked inside tmux running in an xterm.js-based terminal (VS Code, Hyper, Tabby)
- Fixed an alt-screen rendering bug where content height changes mid-scroll could leave compounding ghost lines
- Fixed `FORCE_HYPERLINK` environment variable being ignored when set via `settings.json` `env`
- Fixed native terminal cursor not tracking the selected tab in dialogs, so screen readers and magnifiers can follow tab navigation
- Fixed Bedrock invocation of Sonnet 3.5 v2 by using the `us.` inference profile ID
- Fixed SDK/print mode not preserving the partial assistant response in conversation history when interrupted mid-stream
- Improved `--resume` to resume sessions from other worktrees of the same repo directly instead of printing a `cd` command
- Fixed CJK and other multibyte text being corrupted with U+FFFD in stream-json input/output when chunk boundaries split a UTF-8 sequence
- \[VSCode\] Reduced cold-open subprocess work on starting a session
- \[VSCode\] Fixed dropdown menus selecting the wrong item when the mouse was over the list while typing or using arrow keys
- \[VSCode\] Added a warning banner when `settings.json` files fail to parse, so users know their permission rules are not being applied
[](#2-1-92)
2.1.92
April 4, 2026
- Added `forceRemoteSettingsRefresh` policy setting: when set, the CLI blocks startup until remote managed settings are freshly fetched, and exits if the fetch fails (fail-closed)
- Added interactive Bedrock setup wizard accessible from the login screen when selecting “3rd-party platform” — guides you through AWS authentication, region configuration, credential verification, and model pinning
- Added per-model and cache-hit breakdown to `/cost` for subscription users
- `/release-notes` is now an interactive version picker
- Remote Control session names now use your hostname as the default prefix (e.g. `myhost-graceful-unicorn`), overridable with `--remote-control-session-name-prefix`
- Pro users now see a footer hint when returning to a session after the prompt cache has expired, showing roughly how many tokens the next turn will send uncached
- Fixed subagent spawning permanently failing with “Could not determine pane count” after tmux windows are killed or renumbered during a long-running session
- Fixed prompt-type Stop hooks incorrectly failing when the small fast model returns `ok:false`, and restored `preventContinuation:true` semantics for non-Stop prompt-type hooks
- Fixed tool input validation failures when streaming emits array/object fields as JSON-encoded strings
- Fixed an API 400 error that could occur when extended thinking produced a whitespace-only text block alongside real content
- Fixed accidental feedback survey submissions from auto-pilot keypresses and consecutive-prompt digit collisions
- Fixed misleading “esc to interrupt” hint appearing alongside “esc to clear” when a text selection exists in fullscreen mode during processing
- Fixed Homebrew install update prompts to use the cask’s release channel (`claude-code` → stable, `claude-code@latest` → latest)
- Fixed `ctrl+e` jumping to the end of the next line when already at end of line in multiline prompts
- Fixed an issue where the same message could appear at two positions when scrolling up in fullscreen mode (iTerm2, Ghostty, and other terminals with DEC 2026 support)
- Fixed idle-return “/clear to save X tokens” hint showing cumulative session tokens instead of current context size
- Fixed plugin MCP servers stuck “connecting” on session start when they duplicate a claude.ai connector that is unauthenticated
- Improved Write tool diff computation speed for large files (60% faster on files with tabs/`&`/`$`)
- Removed `/tag` command
- Removed `/vim` command (toggle vim mode via `/config` → Editor mode)
- Linux sandbox now ships the `apply-seccomp` helper in both npm and native builds, restoring unix-socket blocking for sandboxed commands
[](#2-1-91)
2.1.91
April 2, 2026
- Added MCP tool result persistence override via `_meta["anthropic/maxResultSizeChars"]` annotation (up to 500K), allowing larger results like DB schemas to pass through without truncation
- Added `disableSkillShellExecution` setting to disable inline shell execution in skills, custom slash commands, and plugin commands
- Added support for multi-line prompts in `claude-cli://open?q=` deep links (encoded newlines `%0A` no longer rejected)
- Plugins can now ship executables under `bin/` and invoke them as bare commands from the Bash tool
- Fixed transcript chain breaks on `--resume` that could lose conversation history when async transcript writes fail silently
- Fixed `cmd+delete` not deleting to start of line on iTerm2, kitty, WezTerm, Ghostty, and Windows Terminal
- Fixed plan mode in remote sessions losing track of the plan file after a container restart, which caused permission prompts on plan edits and an empty plan-approval modal
- Fixed JSON schema validation for `permissions.defaultMode: "auto"` in settings.json
- Fixed Windows version cleanup not protecting the active version’s rollback copy
- `/feedback` now explains why it’s unavailable instead of disappearing from the slash menu
- Improved `/claude-api` skill guidance for agent design patterns including tool surface decisions, context management, and caching strategy
- Improved performance: faster `stripAnsi` on Bun by routing through `Bun.stripANSI`
- Edit tool now uses shorter `old_string` anchors, reducing output tokens
[](#2-1-90)
2.1.90
April 1, 2026
- Added `/powerup` — interactive lessons teaching Claude Code features with animated demos
- Added `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE` env var to keep the existing marketplace cache when `git pull` fails, useful in offline environments
- Added `.husky` to protected directories (acceptEdits mode)
- Fixed an infinite loop where the rate-limit options dialog would repeatedly auto-open after hitting your usage limit, eventually crashing the session
- Fixed `--resume` causing a full prompt-cache miss on the first request for users with deferred tools, MCP servers, or custom agents (regression since v2.1.69)
- Fixed `Edit`/`Write` failing with “File content has changed” when a PostToolUse format-on-save hook rewrites the file between consecutive edits
- Fixed `PreToolUse` hooks that emit JSON to stdout and exit with code 2 not correctly blocking the tool call
- Fixed collapsed search/read summary badge appearing multiple times in fullscreen scrollback when a CLAUDE.md file auto-loads during a tool call
- Fixed auto mode not respecting explicit user boundaries (“don’t push”, “wait for X before Y”) even when the action would otherwise be allowed
- Fixed click-to-expand hover text being nearly invisible on light terminal themes
- Fixed UI crash when malformed tool input reached the permission dialog
- Fixed headers disappearing when scrolling `/model`, `/config`, and other selection screens
- Hardened PowerShell tool permission checks: fixed trailing `&` background job bypass, `-ErrorAction Break` debugger hang, archive-extraction TOCTOU, and parse-fail fallback deny-rule degradation
- Improved performance: eliminated per-turn JSON.stringify of MCP tool schemas on cache-key lookup
- Improved performance: SSE transport now handles large streamed frames in linear time (was quadratic)
- Improved performance: SDK sessions with long conversations no longer slow down quadratically on transcript writes
- Improved `/resume` all-projects view to load project sessions in parallel, improving load times for users with many projects
- Changed `--resume` picker to no longer show sessions created by `claude -p` or SDK invocations
- Removed `Get-DnsClientCache` and `ipconfig /displaydns` from auto-allow (DNS cache privacy)
[](#2-1-89)
2.1.89
April 1, 2026
- Added `"defer"` permission decision to `PreToolUse` hooks — headless sessions can pause at a tool call and resume with `-p --resume` to have the hook re-evaluate
- Added `CLAUDE_CODE_NO_FLICKER=1` environment variable to opt into flicker-free alt-screen rendering with virtualized scrollback
- Added `PermissionDenied` hook that fires after auto mode classifier denials — return `{retry: true}` to tell the model it can retry
- Added named subagents to `@` mention typeahead suggestions
- Added `MCP_CONNECTION_NONBLOCKING=true` for `-p` mode to skip the MCP connection wait entirely, and bounded `--mcp-config` server connections at 5s instead of blocking on the slowest server
- Auto mode: denied commands now show a notification and appear in `/permissions` → Recent tab where you can retry with `r`
- Fixed `Edit(//path/**)` and `Read(//path/**)` allow rules to check the resolved symlink target, not just the requested path
- Fixed voice push-to-talk not activating for some modifier-combo bindings, and voice mode on Windows failing with “WebSocket upgrade rejected with HTTP 101”
- Fixed Edit/Write tools doubling CRLF on Windows and stripping Markdown hard line breaks (two trailing spaces)
- Fixed `StructuredOutput` schema cache bug causing ~50% failure rate when using multiple schemas
- Fixed memory leak where large JSON inputs were retained as LRU cache keys in long-running sessions
- Fixed a crash when removing a message from very large session files (over 50MB)
- Fixed LSP server zombie state after crash — server now restarts on next request instead of failing until session restart
- Fixed prompt history entries containing CJK or emoji being silently dropped when they fall on a 4KB boundary in `~/.claude/history.jsonl`
- Fixed `/stats` undercounting tokens by excluding subagent usage, and losing historical data beyond 30 days when the stats cache format changes
- Fixed `-p --resume` hangs when the deferred tool input exceeds 64KB or no deferred marker exists, and `-p --continue` not resuming deferred tools
- Fixed `claude-cli://` deep links not opening on macOS
- Fixed MCP tool errors truncating to only the first content block when the server returns multi-element error content
- Fixed skill reminders and other system context being dropped when sending messages with images via the SDK
- Fixed PreToolUse/PostToolUse hooks to receive `file_path` as an absolute path for Write/Edit/Read tools, matching the documented behavior
- Fixed autocompact thrash loop — now detects when context refills to the limit immediately after compacting three times in a row and stops with an actionable error instead of burning API calls
- Fixed prompt cache misses in long sessions caused by tool schema bytes changing mid-session
- Fixed nested CLAUDE.md files being re-injected dozens of times in long sessions that read many files
- Fixed `--resume` crash when transcript contains a tool result from an older CLI version or interrupted write
- Fixed misleading “Rate limit reached” message when the API returned an entitlement error — now shows the actual error with actionable hints
- Fixed hooks `if` condition filtering not matching compound commands (`ls && git push`) or commands with env-var prefixes (`FOO=bar git push`)
- Fixed collapsed search/read group badges duplicating in terminal scrollback during heavy parallel tool use
- Fixed notification `invalidates` not clearing the currently-displayed notification immediately
- Fixed prompt briefly disappearing after submit when background messages arrived during processing
- Fixed Devanagari and other combining-mark text being truncated in assistant output
- Fixed rendering artifacts on main-screen terminals after layout shifts
- Fixed voice mode failing to request microphone permission on macOS Apple Silicon
- Fixed Shift+Enter submitting instead of inserting a newline on Windows Terminal Preview 1.25
- Fixed periodic UI jitter during streaming in iTerm2 when running inside tmux
- Fixed PowerShell tool incorrectly reporting failures when commands like `git push` wrote progress to stderr on Windows PowerShell 5.1
- Fixed a potential out-of-memory crash when the Edit tool was used on very large files (\>1 GiB)
- Improved collapsed tool summary to show “Listed N directories” for `ls`/`tree`/`du` instead of “Read N files”
- Improved Bash tool to warn when a formatter/linter command modifies files you have previously read, preventing stale-edit errors
- Improved `@`-mention typeahead to rank source files above MCP resources with similar names
- Improved PowerShell tool prompt with version-appropriate syntax guidance (5.1 vs 7+)
- Changed `Edit` to work on files viewed via `Bash` with `sed -n` or `cat`, without requiring a separate `Read` call first
- Changed hook output over 10,000 characters to be saved to disk with a file path + a 2,000-character preview instead of being injected directly into context
- Changed `cleanupPeriodDays: 0` in settings.json to be rejected with a validation error — it previously silently disabled transcript persistence
- Changed thinking summaries to no longer be generated by default in interactive sessions — set `showThinkingSummaries: true` in settings.json to restore
- Documented `TaskCreated` hook event and its blocking behavior
- Preserved task notifications when backgrounding a running command with Ctrl+B
- PowerShell tool on Windows: external-command arguments containing both a double-quote and whitespace now prompt instead of auto-allowing (PS 5.1 argument-splitting hardening)
- `/env` now applies to PowerShell tool commands (previously only affected Bash)
- `/usage` now hides redundant “Current week (Sonnet only)” bar for Pro and Enterprise plans
- Image paste no longer inserts a trailing space
- Pasting `!command` into an empty prompt now enters bash mode, matching typed `!` behavior
- `/buddy` is here for April 1st — hatch a small creature that watches you code
[](#2-1-87)
2.1.87
March 29, 2026
- Fixed messages in Cowork Dispatch not getting delivered
[](#2-1-86)
2.1.86
March 27, 2026
- Added `X-Claude-Code-Session-Id` header to API requests so proxies can aggregate requests by session without parsing the body
- Added `.jj` and `.sl` to VCS directory exclusion lists so Grep and file autocomplete don’t descend into Jujutsu or Sapling metadata
- Fixed `--resume` failing with “tool_use ids were found without tool_result blocks” on sessions created before v2.1.85
- Fixed Write/Edit/Read failing on files outside the project root (e.g., `~/.claude/CLAUDE.md`) when conditional skills or rules are configured
- Fixed unnecessary config disk writes on every skill invocation that could cause performance issues and config corruption on Windows
- Fixed potential out-of-memory crash when using `/feedback` on very long sessions with large transcript files
- Fixed `--bare` mode dropping MCP tools in interactive sessions and silently discarding messages enqueued mid-turn
- Fixed the `c` shortcut copying only ~20 characters of the OAuth login URL instead of the full URL
- Fixed masked input (e.g., OAuth code paste) leaking the start of the token when wrapping across multiple lines on narrow terminals
- Fixed official marketplace plugin scripts failing with “Permission denied” on macOS/Linux since v2.1.83
- Fixed statusline showing another session’s model when running multiple Claude Code instances and using `/model` in one of them
- Fixed scroll not following new messages after wheel scroll or click-to-select at the bottom of a long conversation
- Fixed `/plugin` uninstall dialog: pressing `n` now correctly uninstalls the plugin while preserving its data directory
- Fixed a regression where pressing Enter after clicking could leave the transcript blank until the response arrived
- Fixed `ultrathink` hint lingering after deleting the keyword
- Fixed memory growth in long sessions from markdown/highlight render caches retaining full content strings
- Reduced startup event-loop stalls when many claude.ai MCP connectors are configured (macOS keychain cache extended from 5s to 30s)
- Reduced token overhead when mentioning files with `@` — raw string content no longer JSON-escaped
- Improved prompt cache hit rate for Bedrock, Vertex, and Foundry users by removing dynamic content from tool descriptions
- Memory filenames in the “Saved N memories” notice now highlight on hover and open on click
- Skill descriptions in the `/skills` listing are now capped at 250 characters to reduce context usage
- Changed `/skills` menu to sort alphabetically for easier scanning
- Auto mode now shows “unavailable for your plan” when disabled by plan restrictions (was “temporarily unavailable”)
- \[VSCode\] Fixed extension incorrectly showing “Not responding” during long-running operations
- \[VSCode\] Fixed extension defaulting Max plan users to Sonnet after the OAuth token refreshes (8 hours after login)
- Read tool now uses compact line-number format and deduplicates unchanged re-reads, reducing token usage
[](#2-1-85)
2.1.85
March 26, 2026
- Added `CLAUDE_CODE_MCP_SERVER_NAME` and `CLAUDE_CODE_MCP_SERVER_URL` environment variables to MCP `headersHelper` scripts, allowing one helper to serve multiple servers
- Added conditional `if` field for hooks using permission rule syntax (e.g., `Bash(git *)`) to filter when they run, reducing process spawning overhead
- Added timestamp markers in transcripts when scheduled tasks (`/loop`, `CronCreate`) fire
- Added trailing space after `[Image #N]` placeholder when pasting images
- Deep link queries (`claude-cli://open?q=…`) now support up to 5,000 characters, with a “scroll to review” warning for long pre-filled prompts
- MCP OAuth now follows RFC 9728 Protected Resource Metadata discovery to find the authorization server
- Plugins blocked by organization policy (`managed-settings.json`) can no longer be installed or enabled, and are hidden from marketplace views
- PreToolUse hooks can now satisfy `AskUserQuestion` by returning `updatedInput` alongside `permissionDecision: "allow"`, enabling headless integrations that collect answers via their own UI
- `tool_parameters` in OpenTelemetry tool_result events are now gated behind `OTEL_LOG_TOOL_DETAILS=1`
- Fixed `/compact` failing with “context exceeded” when the conversation has grown too large for the compact request itself to fit
- Fixed `/plugin enable` and `/plugin disable` failing when a plugin’s install location differs from where it’s declared in settings
- Fixed `--worktree` exiting with an error in non-git repositories before the `WorktreeCreate` hook could run
- Fixed `deniedMcpServers` setting not blocking claude.ai MCP servers
- Fixed `switch_display` in the computer-use tool returning “not available in this session” on multi-monitor setups
- Fixed crash when `OTEL_LOGS_EXPORTER`, `OTEL_METRICS_EXPORTER`, or `OTEL_TRACES_EXPORTER` is set to `none`
- Fixed diff syntax highlighting not working in non-native builds
- Fixed MCP step-up authorization failing when a refresh token exists — servers requesting elevated scopes via `403 insufficient_scope` now correctly trigger the re-authorization flow
- Fixed memory leak in remote sessions when a streaming response is interrupted
- Fixed persistent ECONNRESET errors during edge connection churn by using a fresh TCP connection on retry
- Fixed prompts getting stuck in the queue after running certain slash commands, with up-arrow unable to retrieve them
- Fixed Python Agent SDK: `type:'sdk'` MCP servers passed via `--mcp-config` are no longer dropped during startup
- Fixed raw key sequences appearing in the prompt when running over SSH or in the VS Code integrated terminal
- Fixed Remote Control session status staying stuck on “Requires Action” after a permission is resolved
- Fixed shift+enter and meta+enter being intercepted by typeahead suggestions instead of inserting newlines
- Fixed stale content bleeding through when scrolling up during streaming
- Fixed terminal left in enhanced keyboard mode after exit in Ghostty, Kitty, WezTerm, and other terminals supporting the Kitty keyboard protocol — Ctrl+C and Ctrl+D now work correctly after quitting
- Improved @-mention file autocomplete performance on large repositories
- Improved PowerShell dangerous command detection
- Improved scroll performance with large transcripts by replacing WASM yoga-layout with a pure TypeScript implementation
- Reduced UI stutter when compaction triggers on large sessions
[](#2-1-84)
2.1.84
March 26, 2026
- Added PowerShell tool for Windows as an opt-in preview. Learn more at [https://code.claude.com/docs/en/tools-reference#powershell-tool](tools-reference.md#powershell-tool)
- Added `ANTHROPIC_DEFAULT_{OPUS,SONNET,HAIKU}_MODEL_SUPPORTS` env vars to override effort/thinking capability detection for pinned default models for 3p (Bedrock, Vertex, Foundry), and `_MODEL_NAME`/`_DESCRIPTION` to customize the `/model` picker label
- Added `CLAUDE_STREAM_IDLE_TIMEOUT_MS` env var to configure the streaming idle watchdog threshold (default 90s)
- Added `TaskCreated` hook that fires when a task is created via `TaskCreate`
- Added `WorktreeCreate` hook support for `type: "http"` — return the created worktree path via `hookSpecificOutput.worktreePath` in the response JSON
- Added `allowedChannelPlugins` managed setting for team/enterprise admins to define a channel plugin allowlist
- Added `x-client-request-id` header to API requests for debugging timeouts
- Added idle-return prompt that nudges users returning after 75+ minutes to `/clear`, reducing unnecessary token re-caching on stale sessions
- Deep links (`claude-cli://`) now open in your preferred terminal instead of whichever terminal happens to be first in the detection list
- Rules and skills `paths:` frontmatter now accepts a YAML list of globs
- MCP tool descriptions and server instructions are now capped at 2KB to prevent OpenAPI-generated servers from bloating context
- MCP servers configured both locally and via claude.ai connectors are now deduplicated — the local config wins
- Background bash tasks that appear stuck on an interactive prompt now surface a notification after ~45 seconds
- Token counts ≥1M now display as “1.5m” instead of “1512.6k”
- Global system-prompt caching now works when `ToolSearch` is enabled, including for users with MCP tools configured
- Fixed voice push-to-talk: holding the voice key no longer leaks characters into the text input, and transcripts now insert at the correct position
- Fixed up/down arrow keys being unresponsive when a footer item is focused
- Fixed `Ctrl+U` (kill-to-line-start) being a no-op at line boundaries in multiline input, so repeated `Ctrl+U` now clears across lines
- Fixed null-unbinding a default chord binding (e.g. `"ctrl+x ctrl+k": null`) still entering chord-wait mode instead of freeing the prefix key
- Fixed mouse events inserting literal “mouse” text into transcript search input
- Fixed workflow subagents failing with API 400 when the outer session uses `--json-schema` and the subagent also specifies a schema
- Fixed missing background color behind certain emoji in user message bubbles on some terminals
- Fixed the “allow Claude to edit its own settings for this session” permission option not sticking for users with `Edit(.claude)` allow rules
- Fixed a hang when generating attachment snippets for large edited files
- Fixed MCP tool/resource cache leak on server reconnect
- Fixed a startup performance issue where partial clone repositories (Scalar/GVFS) triggered mass blob downloads
- Fixed native terminal cursor not tracking the text input caret, so IME composition (CJK input) now renders inline and screen readers can follow the input position
- Fixed spurious “Not logged in” errors on macOS caused by transient keychain read failures
- Fixed cold-start race where core tools could be deferred without their bypass active, causing Edit/Write to fail with InputValidationError on typed parameters
- Improved detection for dangerous removals of Windows drive roots (`C:\`, `C:\Windows`, etc.)
- Improved interactive startup by ~30ms by running `setup()` in parallel with slash command and agent loading
- Improved startup for `claude "prompt"` with MCP servers — the REPL now renders immediately instead of blocking until all servers connect
- Improved Remote Control to show a specific reason when blocked instead of a generic “not yet enabled” message
- Improved p90 prompt cache rate
- Reduced scroll-to-top resets in long sessions by making the message window immune to compaction and grouping changes
- Reduced terminal flickering when animated tool progress scrolls above the viewport
- Changed issue/PR references to only become clickable links when written as `owner/repo#123` — bare `#123` is no longer auto-linked
- Slash commands unavailable for the current auth setup (`/voice`, `/mobile`, `/chrome`, `/upgrade`, etc.) are now hidden instead of shown
- \[VSCode\] Added rate limit warning banner with usage percentage and reset time
- Stats screenshot (Ctrl+S in /stats) now works in all builds and is 16× faster
[](#2-1-83)
2.1.83
March 25, 2026
- Added `managed-settings.d/` drop-in directory alongside `managed-settings.json`, letting separate teams deploy independent policy fragments that merge alphabetically
- Added `CwdChanged` and `FileChanged` hook events for reactive environment management (e.g., direnv)
- Added `sandbox.failIfUnavailable` setting to exit with an error when sandbox is enabled but cannot start, instead of running unsandboxed
- Added `disableDeepLinkRegistration` setting to prevent `claude-cli://` protocol handler registration
- Added `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1` to strip Anthropic and cloud provider credentials from subprocess environments (Bash tool, hooks, MCP stdio servers)
- Added transcript search — press `/` in transcript mode (`Ctrl+O`) to search, `n`/`N` to step through matches
- Added `Ctrl+X Ctrl+E` as an alias for opening the external editor (readline-native binding; `Ctrl+G` still works)
- Pasted images now insert an `[Image #N]` chip at the cursor so you can reference them positionally in your prompt
- Agents can now declare `initialPrompt` in frontmatter to auto-submit a first turn
- `chat:killAgents` and `chat:fastMode` are now rebindable via `~/.claude/keybindings.json`
- Fixed mouse tracking escape sequences leaking to shell prompt after exit
- Fixed Claude Code hanging on exit on macOS
- Fixed screen flashing blank after being idle for a few seconds
- Fixed a hang when diffing very large files with few common lines — diffs now time out after 5 seconds and fall back gracefully
- Fixed a 1–8 second UI freeze on startup when voice input was enabled, caused by eagerly loading the native audio module
- Fixed a startup regression where Claude Code would wait ~3s for claude.ai MCP config fetch before proceeding
- Fixed `--mcp-config` CLI flag bypassing `allowedMcpServers`/`deniedMcpServers` managed policy enforcement
- Fixed claude.ai MCP connectors (Slack, Gmail, etc.) not being available in single-turn `--print` mode
- Fixed `caffeinate` process not properly terminating when Claude Code exits, preventing Mac from sleeping
- Fixed bash mode not activating when tab-accepting `!`-prefixed command suggestions
- Fixed stale slash command selection showing wrong highlighted command after navigating suggestions
- Fixed `/config` menu showing both the search cursor and list selection at the same time
- Fixed background subagents becoming invisible after context compaction, which could cause duplicate agents to be spawned
- Fixed background agent tasks staying stuck in “running” state when git or API calls hang during cleanup
- Fixed `--channels` showing “Channels are not currently available” on first launch after upgrade
- Fixed uninstalled plugin hooks continuing to fire until the next session
- Fixed queued commands flickering during streaming responses
- Fixed slash commands being sent to the model as text when submitted while a message is processing
- Fixed scrollback jumping when collapsed read/search groups finish after scrolling offscreen
- Fixed scrollback jumping to top when the model starts or stops thinking
- Fixed SDK session history loss on resume caused by hook progress/attachment messages forking the parentUuid chain
- Fixed copy-on-select not firing when you release the mouse outside the terminal window
- Fixed ghost characters appearing in height-constrained lists when items overflow
- Fixed `Ctrl+B` interfering with readline backward-char at an idle prompt — it now only fires when a foreground task can be backgrounded
- Fixed tool result files never being cleaned up, ignoring the `cleanupPeriodDays` setting
- Fixed space key being swallowed for up to 3 seconds after releasing voice hold-to-talk
- Fixed ALSA library errors corrupting the terminal UI when using voice mode on Linux without audio hardware (Docker, headless, WSL1)
- Fixed voice mode SoX detection on Termux/Android where spawning `which` is kernel-restricted
- Fixed Remote Control sessions showing as Idle in the web session list while actively running
- Fixed footer navigation selecting an invisible Remote Control pill in config-driven mode
- Fixed memory leak in remote sessions where tool use IDs accumulate indefinitely
- Improved Bedrock SDK cold-start latency by overlapping profile fetch with other boot work
- Improved `--resume` memory usage and startup latency on large sessions
- Improved plugin startup — commands, skills, and agents now load from disk cache without re-fetching
- Improved Remote Control session titles: AI-generated titles now appear within seconds of the first message
- Improved `WebFetch` to identify as `Claude-User` so site operators can recognize and allowlist Claude Code traffic via `robots.txt`
- Reduced `WebFetch` peak memory usage for large pages
- Reduced scrollback resets in long sessions from once per turn to once per ~50 messages
- Faster `claude -p` startup with unauthenticated HTTP/SSE MCP servers (~600ms saved)
- Bash ghost-text suggestions now include just-submitted commands immediately
- Increased non-streaming fallback token cap (21k → 64k) and timeout (120s → 300s local) so fallback requests are less likely to be truncated
- Interrupting a prompt before any response now automatically restores your input so you can edit and resubmit
- `/status` now works while Claude is responding, instead of being queued until the turn finishes
- Plugin MCP servers that duplicate an org-managed connector are now suppressed instead of running a second connection
- Linux: respect `XDG_DATA_HOME` when registering the `claude-cli://` protocol handler
- Changed “stop all background agents” keybinding from `Ctrl+F` to `Ctrl+X Ctrl+K` to stop shadowing readline forward-char
- Deprecated `TaskOutput` tool in favor of using `Read` on the background task’s output file path
- Added `CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK` env var to disable the non-streaming fallback when streaming fails
- Plugin options (`manifest.userConfig`) now available externally — plugins can prompt for configuration at enable time, with `sensitive: true` values stored in keychain (macOS) or protected credentials file (other platforms)
- Claude can now reference the on-disk path of clipboard-pasted images for file operations
- `Ctrl+L` now clears the screen and forces a full redraw — use this to recover when Cmd+K leaves the UI partially blank. Use `Ctrl+U` or double-Esc to clear prompt input.
- `--bare -p` (SDK pattern) is ~14% faster to the API request
- Memory: `MEMORY.md` index now truncates at 25KB as well as 200 lines
- Disabled `AskUserQuestion` and plan-mode tools when `--channels` is active
- Fixed API 400 error when a pasted image was queued during a failing tool call
- Fixed MCP tool calls hanging indefinitely when an SSE connection drops mid-call and exhausts its reconnection attempts
- Fixed Remote Control session titles showing raw XML when a background agent completed before the first user message
- Fixed remote sessions forgetting conversation history after a container restart due to progress-message gaps in the resumed transcript chain
- Fixed remote sessions requiring re-login on transient auth errors instead of retrying automatically
- Fixed `rg ... | wc -l` and similar piped commands hanging and returning `0` in sandbox mode on Linux
- Fixed voice input hold-to-talk not activating when a CJK IME inserts a full-width space
- Fixed `--worktree` hanging silently when the worktree name contained a forward slash
- \[VSCode\] Spinner now turns red with “Not responding” when the backend hasn’t responded for 60 seconds
- \[VSCode\] Fixed session history not loading correctly when reopening a session via URL or after restart
- \[VSCode\] Added Esc-twice (or `/rewind`) to open a keyboard-navigable rewind picker
- \[VSCode\] Fixed “Fork conversation from here” and rewind actions failing silently after the session cache goes stale
[](#2-1-81)
2.1.81
March 20, 2026
- Added `--bare` flag for scripted `-p` calls — skips hooks, LSP, plugin sync, and skill directory walks; requires `ANTHROPIC_API_KEY` or an `apiKeyHelper` via `--settings` (OAuth and keychain auth disabled); auto-memory fully disabled
- Added `--channels` permission relay — channel servers that declare the permission capability can forward tool approval prompts to your phone
- Fixed multiple concurrent Claude Code sessions requiring repeated re-authentication when one session refreshes its OAuth token
- Fixed voice mode silently swallowing retry failures and showing a misleading “check your network” message instead of the actual error
- Fixed voice mode audio not recovering when the server silently drops the WebSocket connection
- Fixed `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` not suppressing the structured-outputs beta header, causing 400 errors on proxy gateways forwarding to Vertex/Bedrock
- Fixed `--channels` bypass for Team/Enterprise orgs with no other managed settings configured
- Fixed a crash on Node.js 18
- Fixed unnecessary permission prompts for Bash commands containing dashes in strings
- Fixed plugin hooks blocking prompt submission when the plugin directory is deleted mid-session
- Fixed a race condition where background agent task output could hang indefinitely when the task completed between polling intervals
- Resuming a session that was in a worktree now switches back to that worktree
- Fixed `/btw` not including pasted text when used during an active response
- Fixed a race where fast Cmd+Tab followed by paste could beat the clipboard copy under tmux
- Fixed terminal tab title not updating with an auto-generated session description
- Fixed invisible hook attachments inflating the message count in transcript mode
- Fixed Remote Control sessions showing a generic title instead of deriving from the first prompt
- Fixed `/rename` not syncing the title for Remote Control sessions
- Fixed Remote Control `/exit` not reliably archiving the session
- Improved MCP read/search tool calls to collapse into a single “Queried `{server}`” line (expand with Ctrl+O)
- Improved `!` bash mode discoverability — Claude now suggests it when you need to run an interactive command
- Improved plugin freshness — ref-tracked plugins now re-clone on every load to pick up upstream changes
- Improved Remote Control session titles to refresh after your third message
- Updated MCP OAuth to support Client ID Metadata Document (CIMD / SEP-991) for servers without Dynamic Client Registration
- Changed plan mode to hide the “clear context” option by default (restore with `"showClearContextOnPlanAccept": true`)
- Disabled line-by-line response streaming on Windows (including WSL in Windows Terminal) due to rendering issues
- \[VSCode\] Fixed Windows PATH inheritance for Bash tool when using Git Bash (regression in v2.1.78)
[](#2-1-80)
2.1.80
March 19, 2026
- Added `rate_limits` field to statusline scripts for displaying Claude.ai rate limit usage (5-hour and 7-day windows with `used_percentage` and `resets_at`)
- Added `source: 'settings'` plugin marketplace source — declare plugin entries inline in settings.json
- Added CLI tool usage detection to plugin tips, in addition to file pattern matching
- Added `effort` frontmatter support for skills and slash commands to override the model effort level when invoked
- Added `--channels` (research preview) — allow MCP servers to push messages into your session
- Fixed `--resume` dropping parallel tool results — sessions with parallel tool calls now restore all tool_use/tool_result pairs instead of showing `[Tool result missing]` placeholders
- Fixed voice mode WebSocket failures caused by Cloudflare bot detection on non-browser TLS fingerprints
- Fixed 400 errors when using fine-grained tool streaming through API proxies, Bedrock, or Vertex
- Fixed `/remote-control` appearing for gateway and third-party provider deployments where it cannot function
- Fixed `/sandbox` tab switching not responding to Tab or arrow keys
- Improved responsiveness of `@` file autocomplete in large git repositories
- Improved `/effort` to show what auto currently resolves to, matching the status bar indicator
- Improved `/permissions` — Tab and arrow keys now switch tabs from within a list
- Improved background tasks panel — left arrow now closes from the list view
- Simplified plugin install tips to use a single `/plugin install` command instead of a two-step flow
- Reduced memory usage on startup in large repositories (~80 MB saved on 250k-file repos)
- Fixed managed settings (`enabledPlugins`, `permissions.defaultMode`, policy-set env vars) not being applied at startup when `remote-settings.json` was cached from a prior session
[](#2-1-79)
2.1.79
March 18, 2026
- Added `--console` flag to `claude auth login` for Anthropic Console (API billing) authentication
- Added “Show turn duration” toggle to the `/config` menu
- Fixed `claude -p` hanging when spawned as a subprocess without explicit stdin (e.g. Python `subprocess.run`)
- Fixed Ctrl+C not working in `-p` (print) mode
- Fixed `/btw` returning the main agent’s output instead of answering the side question when triggered during streaming
- Fixed voice mode not activating correctly on startup when `voiceEnabled: true` is set
- Fixed left/right arrow tab navigation in `/permissions`
- Fixed `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` not preventing terminal title from being set on startup
- Fixed custom status line showing nothing when workspace trust is blocking it
- Fixed enterprise users being unable to retry on rate limit (429) errors
- Fixed `SessionEnd` hooks not firing when using interactive `/resume` to switch sessions
- Improved startup memory usage by ~18MB across all scenarios
- Improved non-streaming API fallback with a 2-minute per-attempt timeout, preventing sessions from hanging indefinitely
- `CLAUDE_CODE_PLUGIN_SEED_DIR` now supports multiple seed directories separated by the platform path delimiter (`:` on Unix, `;` on Windows)
- \[VSCode\] Added `/remote-control` — bridge your session to claude.ai/code to continue from a browser or phone
- \[VSCode\] Session tabs now get AI-generated titles based on your first message
- \[VSCode\] Fixed the thinking pill showing “Thinking” instead of “Thought for Ns” after a response completes
- \[VSCode\] Fixed missing session diff button when opening sessions from the left sidebar
[](#2-1-78)
2.1.78
March 17, 2026
- Added `StopFailure` hook event that fires when the turn ends due to an API error (rate limit, auth failure, etc.)
- Added `${CLAUDE_PLUGIN_DATA}` variable for plugin persistent state that survives plugin updates; `/plugin uninstall` prompts before deleting it
- Added `effort`, `maxTurns`, and `disallowedTools` frontmatter support for plugin-shipped agents
- Terminal notifications (iTerm2/Kitty/Ghostty popups, progress bar) now reach the outer terminal when running inside tmux with `set -g allow-passthrough on`
- Response text now streams line-by-line as it’s generated
- Fixed `git log HEAD` failing with “ambiguous argument” inside sandboxed Bash on Linux, and stub files polluting `git status` in the working directory
- Fixed `cc log` and `--resume` silently truncating conversation history on large sessions (\>5 MB) that used subagents
- Fixed infinite loop when API errors triggered stop hooks that re-fed blocking errors to the model
- Fixed `deny: ["mcp__servername"]` permission rules not removing MCP server tools before sending to the model, allowing it to see and attempt blocked tools
- Fixed `sandbox.filesystem.allowWrite` not working with absolute paths (previously required `//` prefix)
- Fixed `/sandbox` Dependencies tab showing Linux prerequisites on macOS instead of macOS-specific info
- **Security:** Fixed silent sandbox disable when `sandbox.enabled: true` is set but dependencies are missing — now shows a visible startup warning
- Fixed `.git`, `.claude`, and other protected directories being writable without a prompt in `bypassPermissions` mode
- Fixed ctrl+u in normal mode scrolling instead of readline kill-line (ctrl+u/ctrl+d half-page scroll moved to transcript mode only)
- Fixed voice mode modifier-combo push-to-talk keybindings (e.g. ctrl+k) requiring a hold instead of activating immediately
- Fixed voice mode not working on WSL2 with WSLg (Windows 11); WSL1/Win10 users now get a clear error
- Fixed `--worktree` flag not loading skills and hooks from the worktree directory
- Fixed `CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS` and `includeGitInstructions` setting not suppressing the git status section in the system prompt
- Fixed Bash tool not finding Homebrew and other PATH-dependent binaries when VS Code is launched from Dock/Spotlight
- Fixed washed-out Claude orange color in VS Code/Cursor/code-server terminals that don’t advertise truecolor support
- Added `ANTHROPIC_CUSTOM_MODEL_OPTION` env var to add a custom entry to the `/model` picker, with optional `_NAME` and `_DESCRIPTION` suffixed vars for display
- Fixed `ANTHROPIC_BETAS` environment variable being silently ignored when using Haiku models
- Fixed queued prompts being concatenated without a newline separator
- Improved memory usage and startup time when resuming large sessions
- \[VSCode\] Fixed a brief flash of the login screen when opening the sidebar while already authenticated
- \[VSCode\] Fixed “API Error: Rate limit reached” when selecting Opus — model dropdown no longer offers 1M context variant to subscribers whose plan tier is unknown
[](#2-1-77)
2.1.77
March 17, 2026
- Increased default maximum output token limits for Claude Opus 4.6 to 64k tokens, and the upper bound for Opus 4.6 and Sonnet 4.6 models to 128k tokens
- Added `allowRead` sandbox filesystem setting to re-allow read access within `denyRead` regions
- `/copy` now accepts an optional index: `/copy N` copies the Nth-latest assistant response
- Fixed “Always Allow” on compound bash commands (e.g. `cd src && npm test`) saving a single rule for the full string instead of per-subcommand, leading to dead rules and repeated permission prompts
- Fixed auto-updater starting overlapping binary downloads when the slash-command overlay repeatedly opened and closed, accumulating tens of gigabytes of memory
- Fixed `--resume` silently truncating recent conversation history due to a race between memory-extraction writes and the main transcript
- Fixed PreToolUse hooks returning `"allow"` bypassing `deny` permission rules, including enterprise managed settings
- Fixed Write tool silently converting line endings when overwriting CRLF files or creating files in CRLF directories
- Fixed memory growth in long-running sessions from progress messages surviving compaction
- Fixed cost and token usage not being tracked when the API falls back to non-streaming mode
- Fixed `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` not stripping beta tool-schema fields, causing proxy gateways to reject requests
- Fixed Bash tool reporting errors for successful commands when the system temp directory path contains spaces
- Fixed paste being lost when typing immediately after pasting
- Fixed Ctrl+D in `/feedback` text input deleting forward instead of the second press exiting the session
- Fixed API error when dragging a 0-byte image file into the prompt
- Fixed Claude Desktop sessions incorrectly using the terminal CLI’s configured API key instead of OAuth
- Fixed `git-subdir` plugins at different subdirectories of the same monorepo commit colliding in the plugin cache
- Fixed ordered list numbers not rendering in terminal UI
- Fixed a race condition where stale-worktree cleanup could delete an agent worktree just resumed from a previous crash
- Fixed input deadlock when opening `/mcp` or similar dialogs while the agent is running
- Fixed Backspace and Delete keys not working in vim NORMAL mode
- Fixed status line not updating when vim mode is toggled on or off
- Fixed hyperlinks opening twice on Cmd+click in VS Code, Cursor, and other xterm.js-based terminals
- Fixed background colors rendering as terminal-default inside tmux with default configuration
- Fixed iTerm2 session crash when selecting text inside tmux over SSH
- Fixed clipboard copy silently failing in tmux sessions; copy toast now indicates whether to paste with `⌘V` or tmux `prefix+]`
- Fixed `←`/`→` accidentally switching tabs in settings, permissions, and sandbox dialogs while navigating lists
- Fixed IDE integration not auto-connecting when Claude Code is launched inside tmux or screen
- Fixed CJK characters visually bleeding into adjacent UI elements when clipped at the right edge
- Fixed teammate panes not closing when the leader exits
- Fixed iTerm2 auto mode not detecting iTerm2 for native split-pane teammates
- Faster startup on macOS (~60ms) by reading keychain credentials in parallel with module loading
- Faster `--resume` on fork-heavy and very large sessions — up to 45% faster loading and ~100-150MB less peak memory
- Improved Esc to abort in-flight non-streaming API requests
- Improved `claude plugin validate` to check skill, agent, and command frontmatter plus `hooks/hooks.json`, catching YAML parse errors and schema violations
- Background bash tasks are now killed if output exceeds 5GB, preventing runaway processes from filling disk
- Sessions are now auto-named from plan content when you accept a plan
- Improved headless mode plugin installation to compose correctly with `CLAUDE_CODE_PLUGIN_SEED_DIR`
- Show a notice when `apiKeyHelper` takes longer than 10s, preventing it from blocking the main loop
- The Agent tool no longer accepts a `resume` parameter — use `SendMessage({to: agentId})` to continue a previously spawned agent
- `SendMessage` now auto-resumes stopped agents in the background instead of returning an error
- Renamed `/fork` to `/branch` (`/fork` still works as an alias)
- \[VSCode\] Improved plan preview tab titles to use the plan’s heading instead of “Claude’s Plan”
- \[VSCode\] When option+click doesn’t trigger native selection on macOS, the footer now points to the `macOptionClickForcesSelection` setting
[](#2-1-76)
2.1.76
March 14, 2026
- Added MCP elicitation support — MCP servers can now request structured input mid-task via an interactive dialog (form fields or browser URL)
- Added new `Elicitation` and `ElicitationResult` hooks to intercept and override responses before they’re sent back
- Added `-n` / `--name <name>` CLI flag to set a display name for the session at startup
- Added `worktree.sparsePaths` setting for `claude --worktree` in large monorepos to check out only the directories you need via git sparse-checkout
- Added `PostCompact` hook that fires after compaction completes
- Added `/effort` slash command to set model effort level
- Added session quality survey — enterprise admins can configure the sample rate via the `feedbackSurveyRate` setting
- Fixed deferred tools (loaded via `ToolSearch`) losing their input schemas after conversation compaction, causing array and number parameters to be rejected with type errors
- Fixed slash commands showing “Unknown skill”
- Fixed plan mode asking for re-approval after the plan was already accepted
- Fixed voice mode swallowing keypresses while a permission dialog or plan editor was open
- Fixed `/voice` not working on Windows when installed via npm
- Fixed spurious “Context limit reached” when invoking a skill with `model:` frontmatter on a 1M-context session
- Fixed “adaptive thinking is not supported on this model” error when using non-standard model strings
- Fixed `Bash(cmd:*)` permission rules not matching when a quoted argument contains `#`
- Fixed “don’t ask again” in the Bash permission dialog showing the full raw command for pipes and compound commands
- Fixed auto-compaction retrying indefinitely after consecutive failures — a circuit breaker now stops after 3 attempts
- Fixed MCP reconnect spinner persisting after successful reconnection
- Fixed LSP plugins not registering servers when the LSP Manager initialized before marketplaces were reconciled
- Fixed clipboard copying in tmux over SSH — now attempts both direct terminal write and tmux clipboard integration
- Fixed `/export` showing only the filename instead of the full file path in the success message
- Fixed transcript not auto-scrolling to new messages after selecting text
- Fixed Escape key not working to exit the login method selection screen
- Fixed several Remote Control issues: sessions silently dying when the server reaps an idle environment, rapid messages being queued one-at-a-time instead of batched, and stale work items causing redelivery after JWT refresh
- Fixed bridge sessions failing to recover after extended WebSocket disconnects
- Fixed slash commands not found when typing the exact name of a soft-hidden command
- Improved `--worktree` startup performance by reading git refs directly and skipping redundant `git fetch` when the remote branch is already available locally
- Improved background agent behavior — killing a background agent now preserves its partial results in the conversation context
- Improved model fallback notifications — now always visible instead of hidden behind verbose mode, with human-friendly model names
- Improved blockquote readability on dark terminal themes — text is now italic with a left bar instead of dim
- Improved stale worktree cleanup — worktrees left behind after an interrupted parallel run are now automatically cleaned up
- Improved Remote Control session titles — now derived from your first prompt instead of showing “Interactive session”
- Improved `/voice` to show your dictation language on enable and warn when your `language` setting isn’t supported for voice input
- Updated `--plugin-dir` to only accept one path to support subcommands — use repeated `--plugin-dir` for multiple directories
- \[VSCode\] Fixed gitignore patterns containing commas silently excluding entire filetypes from the @-mention file picker
[](#2-1-75)
2.1.75
March 13, 2026
- Added 1M context window for Opus 4.6 by default for Max, Team, and Enterprise plans (previously required extra usage)
- Added `/color` command for all users to set a prompt-bar color for your session
- Added session name display on the prompt bar when using `/rename`
- Added last-modified timestamps to memory files, helping Claude reason about which memories are fresh vs. stale
- Added hook source display (settings/plugin/skill) in permission prompts when a hook requires confirmation
- Fixed voice mode not activating correctly on fresh installs without toggling `/voice` twice
- Fixed the Claude Code header not updating the displayed model name after switching models with `/model` or Option+P
- Fixed session crash when an attachment message computation returns undefined values
- Fixed Bash tool mangling `!` in piped commands (e.g., `jq 'select(.x != .y)'` now works correctly)
- Fixed managed-disabled plugins showing up in the `/plugin` Installed tab — plugins force-disabled by your organization are now hidden
- Fixed token estimation over-counting for thinking and `tool_use` blocks, preventing premature context compaction
- Fixed corrupted marketplace config path handling
- Fixed `/resume` losing session names after resuming a forked or continued session
- Fixed Esc not closing the `/status` dialog after visiting the Config tab
- Fixed input handling when accepting or rejecting a plan
- Fixed footer hint in agent teams showing ”↓ to expand” instead of the correct “shift + ↓ to expand”
- Improved startup performance on macOS non-MDM machines by skipping unnecessary subprocess spawns
- Suppressed async hook completion messages by default (visible with `--verbose` or transcript mode)
- Breaking change: Removed deprecated Windows managed settings fallback at `C:\ProgramData\ClaudeCode\managed-settings.json` — use `C:\Program Files\ClaudeCode\managed-settings.json`
[](#2-1-74)
2.1.74
March 12, 2026
- Added actionable suggestions to `/context` command — identifies context-heavy tools, memory bloat, and capacity warnings with specific optimization tips
- Added `autoMemoryDirectory` setting to configure a custom directory for auto-memory storage
- Fixed memory leak where streaming API response buffers were not released when the generator was terminated early, causing unbounded RSS growth on the Node.js/npm code path
- Fixed managed policy `ask` rules being bypassed by user `allow` rules or skill `allowed-tools`
- Fixed full model IDs (e.g., `claude-opus-4-5`) being silently ignored in agent frontmatter `model:` field and `--agents` JSON config — agents now accept the same model values as `--model`
- Fixed MCP OAuth authentication hanging when the callback port is already in use
- Fixed MCP OAuth refresh never prompting for re-auth after the refresh token expires, for OAuth servers that return errors with HTTP 200 (e.g. Slack)
- Fixed voice mode silently failing on the macOS native binary for users whose terminal had never been granted microphone permission — the binary now includes the `audio-input` entitlement so macOS prompts correctly
- Fixed `SessionEnd` hooks being killed after 1.5 s on exit regardless of `hook.timeout` — now configurable via `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`
- Fixed `/plugin install` failing inside the REPL for marketplace plugins with local sources
- Fixed marketplace update not syncing git submodules — plugin sources in submodules no longer break after update
- Fixed unknown slash commands with arguments silently dropping input — now shows your input as a warning
- Fixed Hebrew, Arabic, and other RTL text not rendering correctly in Windows Terminal, conhost, and VS Code integrated terminal
- Fixed LSP servers not working on Windows due to malformed file URIs
- Changed `--plugin-dir` so local dev copies now override installed marketplace plugins with the same name (unless that plugin is force-enabled by managed settings)
- \[VSCode\] Fixed delete button not working for Untitled sessions
- \[VSCode\] Improved scroll wheel responsiveness in the integrated terminal with terminal-aware acceleration
[](#2-1-73)
2.1.73
March 11, 2026
- Added `modelOverrides` setting to map model picker entries to custom provider model IDs (e.g. Bedrock inference profile ARNs)
- Added actionable guidance when OAuth login or connectivity checks fail due to SSL certificate errors (corporate proxies, `NODE_EXTRA_CA_CERTS`)
- Fixed freezes and 100% CPU loops triggered by permission prompts for complex bash commands
- Fixed a deadlock that could freeze Claude Code when many skill files changed at once (e.g. during `git pull` in a repo with a large `.claude/skills/` directory)
- Fixed Bash tool output being lost when running multiple Claude Code sessions in the same project directory
- Fixed subagents with `model: opus`/`sonnet`/`haiku` being silently downgraded to older model versions on Bedrock, Vertex, and Microsoft Foundry
- Fixed background bash processes spawned by subagents not being cleaned up when the agent exits
- Fixed `/resume` showing the current session in the picker
- Fixed `/ide` crashing with `onInstall is not defined` when auto-installing the extension
- Fixed `/loop` not being available on Bedrock/Vertex/Foundry and when telemetry was disabled
- Fixed SessionStart hooks firing twice when resuming a session via `--resume` or `--continue`
- Fixed JSON-output hooks injecting no-op system-reminder messages into the model’s context on every turn
- Fixed voice mode session corruption when a slow connection overlaps a new recording
- Fixed Linux sandbox failing to start with “ripgrep (rg) not found” on native builds
- Fixed Linux native modules not loading on Amazon Linux 2 and other glibc 2.26 systems
- Fixed “media_type: Field required” API error when receiving images via Remote Control
- Fixed `/heapdump` failing on Windows with `EEXIST` error when the Desktop folder already exists
- Improved Up arrow after interrupting Claude — now restores the interrupted prompt and rewinds the conversation in one step
- Improved IDE detection speed at startup
- Improved clipboard image pasting performance on macOS
- Improved `/effort` to work while Claude is responding, matching `/model` behavior
- Improved voice mode to automatically retry transient connection failures during rapid push-to-talk re-press
- Improved the Remote Control spawn mode selection prompt with better context
- Changed default Opus model on Bedrock, Vertex, and Microsoft Foundry to Opus 4.6 (was Opus 4.1)
- Deprecated `/output-style` command — use `/config` instead. Output style is now fixed at session start for better prompt caching
- VSCode: Fixed HTTP 400 errors for users behind proxies or on Bedrock/Vertex with Claude 4.5 models
[](#2-1-72)
2.1.72
March 10, 2026
- Fixed tool search to activate even with `ANTHROPIC_BASE_URL` as long as `ENABLE_TOOL_SEARCH` is set.
- Added `w` key in `/copy` to write the focused selection directly to a file, bypassing the clipboard (useful over SSH)
- Added optional description argument to `/plan` (e.g., `/plan fix the auth bug`) that enters plan mode and immediately starts
- Added `ExitWorktree` tool to leave an `EnterWorktree` session
- Added `CLAUDE_CODE_DISABLE_CRON` environment variable to immediately stop scheduled cron jobs mid-session
- Added `lsof`, `pgrep`, `tput`, `ss`, `fd`, and `fdfind` to the bash auto-approval allowlist, reducing permission prompts for common read-only operations
- Restored the `model` parameter on the Agent tool for per-invocation model overrides
- Simplified effort levels to low/medium/high (removed max) with new symbols (○ ◐ ●) and a brief notification instead of a persistent icon. Use `/effort auto` to reset to default
- Improved `/config` — Escape now cancels changes, Enter saves and closes, Space toggles settings
- Improved up-arrow history to show current session’s messages first when running multiple concurrent sessions
- Improved voice input transcription accuracy for repo names and common dev terms (regex, OAuth, JSON)
- Improved bash command parsing by switching to a native module — faster initialization and no memory leak
- Reduced bundle size by ~510 KB
- Changed CLAUDE.md HTML comments (`<!-- ... -->`) to be hidden from Claude when auto-injected. Comments remain visible when read with the Read tool
- Fixed slow exits when background tasks or hooks were slow to respond
- Fixed agent task progress stuck on “Initializing…”
- Fixed skill hooks firing twice per event when a hooks-enabled skill is invoked by the model
- Fixed several voice mode issues: occasional input lag, false “No speech detected” errors after releasing push-to-talk, and stale transcripts re-filling the prompt after submission
- Fixed `--continue` not resuming from the most recent point after `--compact`
- Fixed bash security parsing edge cases
- Added support for marketplace git URLs without `.git` suffix (Azure DevOps, AWS CodeCommit)
- Improved marketplace clone failure messages to show diagnostic info even when git produces no stderr
- Fixed several plugin issues: installation failing on Windows with `EEXIST` error in OneDrive folders, marketplace blocking user-scope installs when a project-scope install exists, `CLAUDE_CODE_PLUGIN_CACHE_DIR` creating literal `~` directories, and `plugin.json` with marketplace-only fields failing to load
- Fixed feedback survey appearing too frequently in long sessions
- Fixed `--effort` CLI flag being reset by unrelated settings writes on startup
- Fixed backgrounded Ctrl+B queries losing their transcript or corrupting the new conversation after `/clear`
- Fixed `/clear` killing background agent/bash tasks — only foreground tasks are now cleared
- Fixed worktree isolation issues: Task tool resume not restoring cwd, and background task notifications missing `worktreePath` and `worktreeBranch`
- Fixed `/model` not displaying results when run while Claude is working
- Fixed digit keys selecting menu options instead of typing in plan mode permission prompt’s text input
- Fixed sandbox permission issues: certain file write operations incorrectly allowed without prompting, and output redirections to allowlisted directories (like `/tmp/claude/`) prompting unnecessarily
- Improved CPU utilization in long sessions
- Fixed prompt cache invalidation in SDK `query()` calls, reducing input token costs up to 12x
- Fixed Escape key becoming unresponsive after cancelling a query
- Fixed double Ctrl+C not exiting when background agents or tasks are running
- Fixed team agents to inherit the leader’s model
- Fixed “Always Allow” saving permission rules that never match again
- Fixed several hooks issues: `transcript_path` pointing to the wrong directory for resumed/forked sessions, agent `prompt` being silently deleted from settings.json on every settings write, PostToolUse block reason displaying twice, async hooks not receiving stdin with bash `read -r`, and validation error message showing an example that fails validation
- Fixed session crashes in Desktop/SDK when Read returned files containing U+2028/U+2029 characters
- Fixed terminal title being cleared on exit even when `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` was set
- Fixed several permission rule matching issues: wildcard rules not matching commands with heredocs, embedded newlines, or no arguments; `sandbox.excludedCommands` failing with env var prefixes; “always allow” suggesting overly broad prefixes for nested CLI tools; and deny rules not applying to all command forms
- Fixed oversized and truncated images from Bash data-URL output
- Fixed a crash when resuming sessions that contained Bedrock API errors
- Fixed intermittent “expected boolean, received string” validation errors on Edit, Bash, and Grep tool inputs
- Fixed multi-line session titles when forking from a conversation whose first message contained newlines
- Fixed queued messages not showing attached images, and images being lost when pressing ↑ to edit a queued message
- Fixed parallel tool calls where a failed Read/WebFetch/Glob would cancel its siblings — only Bash errors now cascade
- VSCode: Fixed scroll speed in integrated terminals not matching native terminals
- VSCode: Fixed Shift+Enter submitting input instead of inserting a newline for users with older keybindings
- VSCode: Added effort level indicator on the input border
- VSCode: Added `vscode://anthropic.claude-code/open` URI handler to open a new Claude Code tab programmatically, with optional `prompt` and `session` query parameters
[](#2-1-71)
2.1.71
March 7, 2026
- Added `/loop` command to run a prompt or slash command on a recurring interval (e.g. `/loop 5m check the deploy`)
- Added cron scheduling tools for recurring prompts within a session
- Added `voice:pushToTalk` keybinding to make the voice activation key rebindable in `keybindings.json` (default: space) — modifier+letter combos like `meta+k` have zero typing interference
- Added `fmt`, `comm`, `cmp`, `numfmt`, `expr`, `test`, `printf`, `getconf`, `seq`, `tsort`, and `pr` to the bash auto-approval allowlist
- Fixed stdin freeze in long-running sessions where keystrokes stop being processed but the process stays alive
- Fixed a 5–8 second startup freeze for users with voice mode enabled, caused by CoreAudio initialization blocking the main thread after system wake
- Fixed startup UI freeze when many claude.ai proxy connectors refresh an expired OAuth token simultaneously
- Fixed forked conversations (`/fork`) sharing the same plan file, which caused plan edits in one fork to overwrite the other
- Fixed the Read tool putting oversized images into context when image processing failed, breaking subsequent turns in long image-heavy sessions
- Fixed false-positive permission prompts for compound bash commands containing heredoc commit messages
- Fixed plugin installations being lost when running multiple Claude Code instances
- Fixed claude.ai connectors failing to reconnect after OAuth token refresh
- Fixed claude.ai MCP connector startup notifications appearing for every org-configured connector instead of only previously connected ones
- Fixed background agent completion notifications missing the output file path, which made it difficult for parent agents to recover agent results after context compaction
- Fixed duplicate output in Bash tool error messages when commands exit with non-zero status
- Fixed Chrome extension auto-detection getting permanently stuck on “not installed” after running on a machine without local Chrome
- Fixed `/plugin marketplace update` failing with merge conflicts when the marketplace is pinned to a branch/tag ref
- Fixed `/plugin marketplace add owner/repo@ref` incorrectly parsing `@` — previously only `#` worked as a ref separator, causing undiagnosable errors with `strictKnownMarketplaces`
- Fixed duplicate entries in `/permissions` Workspace tab when the same directory is added with and without a trailing slash
- Fixed `--print` hanging forever when team agents are configured — the exit loop no longer waits on long-lived `in_process_teammate` tasks
- Fixed ”❯ Tool loaded.” appearing in the REPL after every `ToolSearch` call
- Fixed prompting for `cd <cwd> && git ...` on Windows when the model uses a mingw-style path
- Improved startup time by deferring native image processor loading to first use
- Improved bridge session reconnection to complete within seconds after laptop wake from sleep, instead of waiting up to 10 minutes
- Improved `/plugin uninstall` to disable project-scoped plugins in `.claude/settings.local.json` instead of modifying `.claude/settings.json`, so changes don’t affect teammates
- Improved plugin-provided MCP server deduplication — servers that duplicate a manually-configured server (same command/URL) are now skipped, preventing duplicate connections and tool sets. Suppressions are shown in the `/plugin` menu.
- Updated `/debug` to toggle debug logging on mid-session, since debug logs are no longer written by default
- Removed startup notification noise for unauthenticated org-registered claude.ai connectors
[](#2-1-70)
2.1.70
March 6, 2026
- Fixed API 400 errors when using `ANTHROPIC_BASE_URL` with a third-party gateway — tool search now correctly detects proxy endpoints and disables `tool_reference` blocks
- Fixed `API Error: 400 This model does not support the effort parameter` when using custom Bedrock inference profiles or other model identifiers not matching standard Claude naming patterns
- Fixed empty model responses immediately after `ToolSearch` — the server renders tool schemas with system-prompt-style tags at the prompt tail, which could confuse models into stopping early
- Fixed prompt-cache bust when an MCP server with `instructions` connects after the first turn
- Fixed Enter inserting a newline instead of submitting when typing over a slow SSH connection
- Fixed clipboard corrupting non-ASCII text (CJK, emoji) on Windows/WSL by using PowerShell `Set-Clipboard`
- Fixed extra VS Code windows opening at startup on Windows when running from the VS Code integrated terminal
- Fixed voice mode failing on Windows native binary with “native audio module could not be loaded”
- Fixed push-to-talk not activating on session start when `voiceEnabled: true` was set in settings
- Fixed markdown links containing `#NNN` references incorrectly pointing to the current repository instead of the linked URL
- Fixed repeated “Model updated to Opus 4.6” notification when a project’s `.claude/settings.json` has a legacy Opus model string pinned
- Fixed plugins showing as inaccurately installed in `/plugin`
- Fixed plugins showing “not found in marketplace” errors on fresh startup by auto-refreshing after marketplace installation
- Fixed `/security-review` command failing with `unknown option merge-base` on older git versions
- Fixed `/color` command having no way to reset back to the default color — `/color default`, `/color gray`, `/color reset`, and `/color none` now restore the default
- Fixed a performance regression in the `AskUserQuestion` preview dialog that re-ran markdown rendering on every keystroke in the notes input
- Fixed feature flags read during early startup never refreshing their disk cache, causing stale values to persist across sessions
- Fixed `permissions.defaultMode` settings values other than `acceptEdits` or `plan` being applied in Claude Code Remote environments — they are now ignored
- Fixed skill listing being re-injected on every `--resume` (~600 tokens saved per resume)
- Fixed teleport marker not rendering in VS Code teleported sessions
- Improved error message when microphone captures silence to distinguish from “no speech detected”
- Improved compaction to preserve images in the summarizer request, allowing prompt cache reuse for faster and cheaper compaction
- Improved `/rename` to work while Claude is processing, instead of being silently queued
- Reduced prompt input re-renders during turns by ~74%
- Reduced startup memory by ~426KB for users without custom CA certificates
- Reduced Remote Control `/poll` rate to once per 10 minutes while connected (was 1–2s), cutting server load ~300×. Reconnection is unaffected — transport loss immediately wakes fast polling.
- \[VSCode\] Added spark icon in VS Code activity bar that lists all Claude Code sessions, with sessions opening as full editors
- \[VSCode\] Added full markdown document view for plans in VS Code, with support for adding comments to provide feedback
- \[VSCode\] Added native MCP server management dialog — use `/mcp` in the chat panel to enable/disable servers, reconnect, and manage OAuth authentication without switching to the terminal
[](#2-1-69)
2.1.69
March 5, 2026
- Added the `/claude-api` skill for building applications with the Claude API and Anthropic SDK
- Added Ctrl+U on an empty bash prompt (`!`) to exit bash mode, matching `escape` and `backspace`
- Added numeric keypad support for selecting options in Claude’s interview questions (previously only the number row above QWERTY worked)
- Added optional name argument to `/remote-control` and `claude remote-control` (`/remote-control My Project` or `--name "My Project"`) to set a custom session title visible in claude.ai/code
- Added Voice STT support for 10 new languages (20 total) — Russian, Polish, Turkish, Dutch, Ukrainian, Greek, Czech, Danish, Swedish, Norwegian
- Added effort level display (e.g., “with low effort”) to the logo and spinner, making it easier to see which effort setting is active
- Added agent name display in terminal title when using `claude --agent`
- Added `sandbox.enableWeakerNetworkIsolation` setting (macOS only) to allow Go programs like `gh`, `gcloud`, and `terraform` to verify TLS certificates when using a custom MITM proxy with `httpProxyPort`
- Added `includeGitInstructions` setting (and `CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS` env var) to remove built-in commit and PR workflow instructions from Claude’s system prompt
- Added `/reload-plugins` command to activate pending plugin changes without restarting
- Added a one-time startup prompt suggesting Claude Code Desktop on macOS and Windows (max 3 showings, dismissible)
- Added `${CLAUDE_SKILL_DIR}` variable for skills to reference their own directory in SKILL.md content
- Added `InstructionsLoaded` hook event that fires when CLAUDE.md or `.claude/rules/*.md` files are loaded into context
- Added `agent_id` (for subagents) and `agent_type` (for subagents and `--agent`) to hook events
- Added `worktree` field to status line hook commands with name, path, branch, and original repo directory when running in a `--worktree` session
- Added `pluginTrustMessage` in managed settings to append organization-specific context to the plugin trust warning shown before installation
- Added policy limit fetching (e.g., remote control restrictions) for Team plan OAuth users, not just Enterprise
- Added `pathPattern` to `strictKnownMarketplaces` for regex-matching file/directory marketplace sources alongside `hostPattern` restrictions
- Added plugin source type `git-subdir` to point to a subdirectory within a git repo
- Added `oauth.authServerMetadataUrl` config option for MCP servers to specify a custom OAuth metadata discovery URL when standard discovery fails
- Fixed a security issue where nested skill discovery could load skills from gitignored directories like `node_modules`
- Fixed trust dialog silently enabling all `.mcp.json` servers on first run. You’ll now see the per-server approval dialog as expected
- Fixed `claude remote-control` crashing immediately on npm installs with “bad option: —sdk-url” (anthropics/claude-code#28334)
- Fixed `--model claude-opus-4-0` and `--model claude-opus-4-1` resolving to deprecated Opus versions instead of current
- Fixed macOS keychain corruption when using multiple OAuth MCP servers. Large OAuth metadata blobs could overflow the `security -i` stdin buffer, silently leaving stale credentials behind and causing repeated `/login` prompts.
- Fixed `.credentials.json` losing `subscriptionType` (showing “Claude API” instead of “Claude Pro”/“Claude Max”) when the profile endpoint transiently fails during token refresh (anthropics/claude-code#30185)
- Fixed ghost dotfiles (`.bashrc`, `HEAD`, etc.) appearing as untracked files in the working directory after sandboxed Bash commands on Linux
- Fixed Shift+Enter printing `[27;2;13~` instead of inserting a newline in Ghostty over SSH
- Fixed stash (Ctrl+S) being cleared when submitting a message while Claude is working
- Fixed ctrl+o (transcript toggle) freezing for many seconds in long sessions with lots of file edits
- Fixed plan mode feedback input not supporting multi-line text entry (backslash+Enter and Shift+Enter now insert newlines)
- Fixed cursor not moving down into blank lines at the top of the input box
- Fixed `/stats` crash when transcript files contain entries with missing or malformed timestamps
- Fixed a brief hang after a streaming error on long sessions (the transcript was being fully rewritten to drop one line; it is now truncated in place)
- Fixed `--setting-sources user` not blocking dynamically discovered project skills
- Fixed duplicate CLAUDE.md, slash commands, agents, and rules when running from a worktree nested inside its main repo (e.g. `claude -w`)
- Fixed plugin Stop/SessionEnd/etc hooks not firing after any `/plugin` operation
- Fixed plugin hooks being silently dropped when two plugins use the same `${CLAUDE_PLUGIN_ROOT}/...` command template
- Fixed memory leak in long-running SDK/CCR sessions where conversation messages were retained unnecessarily
- Fixed API 400 errors in forked agents (autocompact, summarization) when resuming sessions that were interrupted mid-tool-batch
- Fixed “unexpected tool_use_id found in tool_result blocks” error when resuming conversations that start with an orphaned tool result
- Fixed teammates accidentally spawning nested teammates via the Agent tool’s `name` parameter
- Fixed `CLAUDE_CODE_MAX_OUTPUT_TOKENS` being ignored during conversation compaction
- Fixed `/compact` summary rendering as a user bubble in SDK consumers (Claude Code Remote web UI, VSCode extension)
- Fixed voice space bar getting stuck after a failed voice activation (module loading race, cold GrowthBook)
- Fixed worktree file copy on Windows
- Fixed global `.claude` folder detection on Windows
- Fixed symlink bypass where writing new files through a symlinked parent directory could escape the working directory in `acceptEdits` mode
- Fixed sandbox prompting users to approve non-allowed domains when `allowManagedDomainsOnly` is enabled in managed settings — non-allowed domains are now blocked automatically with no bypass
- Fixed interactive tools (e.g., `AskUserQuestion`) being silently auto-allowed when listed in a skill’s allowed-tools, bypassing the permission prompt and running with empty answers
- Fixed multi-GB memory spike when committing with large untracked binary files in the working tree
- Fixed Escape not interrupting a running turn when the input box has draft text. Use Up arrow to pull queued messages back for editing, or Ctrl+U to clear the input line.
- Fixed Android app crash when running local slash commands (`/voice`, `/cost`) in Remote Control sessions
- Fixed a memory leak where old message array versions accumulated in React Compiler `memoCache` over long sessions
- Fixed a memory leak where REPL render scopes accumulated over long sessions (~35MB over 1000 turns)
- Fixed memory retention in in-process teammates where the parent’s full conversation history was pinned for the teammate’s lifetime, preventing GC after `/clear` or auto-compact
- Fixed a memory leak in interactive mode where hook events could accumulate unboundedly during long sessions
- Fixed hang when `--mcp-config` points to a corrupted file
- Fixed slow startup when many skills/plugins are installed
- Fixed `cd <outside-dir> && <cmd>` permission prompt to surface the chained command instead of only showing “Yes, allow reading from `<dir>`/”
- Fixed conditional `.claude/rules/*.md` files (with `paths:` frontmatter) and nested CLAUDE.md files not loading in print mode (`claude -p`)
- Fixed `/clear` not fully clearing all session caches, reducing memory retention in long sessions
- Fixed terminal flicker caused by animated elements at the scrollback boundary
- Fixed UI frame drops on macOS when using MCP servers with OAuth (regression from 2.1.x)
- Fixed occasional frame stalls during typing caused by synchronous debug log flushes
- Fixed `TeammateIdle` and `TaskCompleted` hooks to support `{"continue": false, "stopReason": "..."}` to stop the teammate, matching `Stop` hook behavior
- Fixed `WorktreeCreate` and `WorktreeRemove` plugin hooks being silently ignored
- Fixed skill descriptions with colons (e.g., “Triggers include: X, Y, Z”) failing to load from SKILL.md frontmatter
- Fixed project skills without a `description:` frontmatter field not appearing in Claude’s available skills list
- Fixed `/context` showing identical token counts for all MCP tools from a server
- Fixed literal `nul` file creation on Windows when the model uses CMD-style `2>nul` redirection in Git Bash
- Fixed extra blank lines appearing below each tool call in the expanded subagent transcript view (Ctrl+O)
- Fixed Tab/arrow keys not cycling Settings tabs when `/config` search box is focused but empty
- Fixed service key OAuth sessions (CCR containers) spamming `[ERROR]` logs with 403s from profile-scoped endpoints
- Fixed inconsistent color for “Remote Control active” status indicator
- Fixed Voice waveform cursor covering the first suffix letter when dictating mid-input
- Fixed Voice input showing all 5 spaces during warmup instead of capping at ~2 (aligning with the “keep holding…” hint)
- Improved spinner performance by isolating the 50ms animation loop from the surrounding shell, reducing render and CPU overhead during turns
- Improved UI rendering performance in native binaries with React Compiler
- Improved `--worktree` startup by eliminating a git subprocess on the startup path
- Improved macOS startup by eliminating redundant settings-file reloads when managed settings resolve
- Improved macOS startup for Claude.ai enterprise/team users by skipping an unnecessary keychain lookup
- Improved MCP `-p` startup by pipelining claude.ai config fetch with local connections and using a concurrency pool instead of sequential batching
- Improved voice startup by removing imperceptible warmup pulse animations that were causing re-render stutter
- Improved MCP binary content handling: tools returning PDFs, Office documents, or audio now save decoded bytes to disk with the correct file extension instead of dumping raw base64 into the conversation context. WebFetch also saves binary responses alongside its summary.
- Improved memory usage in long sessions by stabilizing `onSubmit` across message updates
- Improved LSP tool rendering and memory context building to no longer read entire files
- Improved session upload and memory sync to avoid reading large files into memory before size/binary checks
- Improved file operation performance by avoiding reading file contents for existence checks (6 sites)
- Improved documentation to clarify that `--append-system-prompt-file` and `--system-prompt-file` work in interactive mode (the docs previously said print mode only)
- Reduced baseline memory by ~16MB by deferring Yoga WASM preloading
- Reduced memory footprint for SDK and CCR sessions using stream-json output
- Reduced memory usage when resuming large sessions (including compacted history)
- Reduced token usage on multi-agent tasks with more concise subagent final reports
- Changed Sonnet 4.5 users on Pro/Max/Team Premium to be automatically migrated to Sonnet 4.6
- Changed the `/resume` picker to show your most recent prompt instead of the first one. This also resolves some titles appearing as `(session)`.
- Changed claude.ai MCP connector failures to show a notification instead of silently disappearing from the tool list
- Changed example command suggestions to be generated deterministically instead of calling Haiku
- Changed resuming after compaction to no longer produce a preamble recap before continuing
- \[SDK\] Changed task creation to no longer require the `activeForm` field — the spinner falls back to the task subject
- \[VSCode\] Added compaction display as a collapsible “Compacted chat” card with the summary inside
- \[VSCode\] The permission mode picker now respects `permissions.disableBypassPermissionsMode` from your effective Claude Code settings (including managed/policy settings) — when set to `disable`, bypass permissions mode is hidden from the picker
- \[VSCode\] Fixed RTL text (Arabic, Hebrew, Persian) rendering reversed in the chat panel (regression in v2.1.63)
[](#2-1-68)
2.1.68
March 4, 2026
- Opus 4.6 now defaults to medium effort for Max and Team subscribers. Medium effort works well for most tasks — it’s the sweet spot between speed and thoroughness. You can change this anytime with `/model`
- Re-introduced the “ultrathink” keyword to enable high effort for the next turn
- Removed Opus 4 and 4.1 from Claude Code on the first-party API — users with these models pinned are automatically moved to Opus 4.6
[](#2-1-66)
2.1.66
March 4, 2026
- Reduced spurious error logging
[](#2-1-63)
2.1.63
February 28, 2026
- Added `/simplify` and `/batch` bundled slash commands
- Fixed local slash command output like /cost appearing as user-sent messages instead of system messages in the UI
- Project configs & auto memory now shared across git worktrees of the same repository
- Added `ENABLE_CLAUDEAI_MCP_SERVERS=false` env var to opt out from making claude.ai MCP servers available
- Improved `/model` command to show the currently active model in the slash command menu
- Added HTTP hooks, which can POST JSON to a URL and receive JSON instead of running a shell command
- Fixed listener leak in bridge polling loop
- Fixed listener leak in MCP OAuth flow cleanup
- Added manual URL paste fallback during MCP OAuth authentication. If the automatic localhost redirect doesn’t work, you can paste the callback URL to complete authentication.
- Fixed memory leak when navigating hooks configuration menu
- Fixed listener leak in interactive permission handler during auto-approvals
- Fixed file count cache ignoring glob ignore patterns
- Fixed memory leak in bash command prefix cache
- Fixed MCP tool/resource cache leak on server reconnect
- Fixed IDE host IP detection cache incorrectly sharing results across ports
- Fixed WebSocket listener leak on transport reconnect
- Fixed memory leak in git root detection cache that could cause unbounded growth in long-running sessions
- Fixed memory leak in JSON parsing cache that grew unbounded over long sessions
- VSCode: Fixed remote sessions not appearing in conversation history
- Fixed a race condition in the REPL bridge where new messages could arrive at the server interleaved with historical messages during the initial connection flush, causing message ordering issues.
- Fixed memory leak where long-running teammates retained all messages in AppState even after conversation compaction
- Fixed a memory leak where MCP server fetch caches were not cleared on disconnect, causing growing memory usage with servers that reconnect frequently
- Improved memory usage in long sessions with subagents by stripping heavy progress message payloads during context compaction
- Added “Always copy full response” option to the `/copy` picker. When selected, future `/copy` commands will skip the code block picker and copy the full response directly.
- VSCode: Added session rename and remove actions to the sessions list
- Fixed `/clear` not resetting cached skills, which could cause stale skill content to persist in the new conversation
[](#2-1-62)
2.1.62
February 27, 2026
- Fixed prompt suggestion cache regression that reduced cache hit rates
[](#2-1-61)
2.1.61
February 26, 2026
- Fixed concurrent writes corrupting config file on Windows
[](#2-1-59)
2.1.59
February 26, 2026
- Claude automatically saves useful context to auto-memory. Manage with /memory
- Added `/copy` command to show an interactive picker when code blocks are present, allowing selection of individual code blocks or the full response.
- Improved “always allow” prefix suggestions for compound bash commands (e.g. `cd /tmp && git fetch && git push`) to compute smarter per-subcommand prefixes instead of treating the whole command as one
- Improved ordering of short task lists
- Improved memory usage in multi-agent sessions by releasing completed subagent task state
- Fixed MCP OAuth token refresh race condition when running multiple Claude Code instances simultaneously
- Fixed shell commands not showing a clear error message when the working directory has been deleted
- Fixed config file corruption that could wipe authentication when multiple Claude Code instances ran simultaneously
[](#2-1-58)
2.1.58
February 25, 2026
- Expand Remote Control to more users
[](#2-1-56)
2.1.56
February 25, 2026
- VS Code: Fixed another cause of “command ‘claude-vscode.editor.openLast’ not found” crashes
[](#2-1-55)
2.1.55
February 25, 2026
- Fixed BashTool failing on Windows with EINVAL error
[](#2-1-53)
2.1.53
February 25, 2026
- Fixed a UI flicker where user input would briefly disappear after submission before the message rendered
- Fixed bulk agent kill (ctrl+f) to send a single aggregate notification instead of one per agent, and to properly clear the command queue
- Fixed graceful shutdown sometimes leaving stale sessions when using Remote Control by parallelizing teardown network calls
- Fixed `--worktree` sometimes being ignored on first launch
- Fixed a panic (“switch on corrupted value”) on Windows
- Fixed a crash that could occur when spawning many processes on Windows
- Fixed a crash in the WebAssembly interpreter on Linux x64 & Windows x64
- Fixed a crash that sometimes occurred after 2 minutes on Windows ARM64
[](#2-1-52)
2.1.52
February 24, 2026
- VS Code: Fixed extension crash on Windows (“command ‘claude-vscode.editor.openLast’ not found”)
[](#2-1-51)
2.1.51
February 24, 2026
- Added `claude remote-control` subcommand for external builds, enabling local environment serving for all users.
- Updated plugin marketplace default git timeout from 30s to 120s and added `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS` to configure.
- Added support for custom npm registries and specific version pinning when installing plugins from npm sources
- BashTool now skips login shell (`-l` flag) by default when a shell snapshot is available, improving command execution performance. Previously this required setting `CLAUDE_BASH_NO_LOGIN=true`.
- Fixed a security issue where `statusLine` and `fileSuggestion` hook commands could execute without workspace trust acceptance in interactive mode.
- Tool results larger than 50K characters are now persisted to disk (previously 100K). This reduces context window usage and improves conversation longevity.
- Fixed a bug where duplicate `control_response` messages (e.g. from WebSocket reconnects) could cause API 400 errors by pushing duplicate assistant messages into the conversation.
- Added `CLAUDE_CODE_ACCOUNT_UUID`, `CLAUDE_CODE_USER_EMAIL`, and `CLAUDE_CODE_ORGANIZATION_UUID` environment variables for SDK callers to provide account info synchronously, eliminating a race condition where early telemetry events lacked account metadata.
- Fixed slash command autocomplete crashing when a plugin’s SKILL.md description is a YAML array or other non-string type
- The `/model` picker now shows human-readable labels (e.g., “Sonnet 4.5”) instead of raw model IDs for pinned model versions, with an upgrade hint when a newer version is available.
- Managed settings can now be set via macOS plist or Windows Registry. Learn more at [https://code.claude.com/docs/en/settings#settings-files](settings.md#settings-files)
[](#2-1-50)
2.1.50
February 20, 2026
- Added support for `startupTimeout` configuration for LSP servers
- Added `WorktreeCreate` and `WorktreeRemove` hook events, enabling custom VCS setup and teardown when agent worktree isolation creates or removes worktrees.
- Fixed a bug where resumed sessions could be invisible when the working directory involved symlinks, because the session storage path was resolved at different times during startup. Also fixed session data loss on SSH disconnect by flushing session data before hooks and analytics in the graceful shutdown sequence.
- Linux: Fixed native modules not loading on systems with glibc older than 2.30 (e.g., RHEL 8)
- Fixed memory leak in agent teams where completed teammate tasks were never garbage collected from session state
- Fixed `CLAUDE_CODE_SIMPLE` to fully strip down skills, session memory, custom agents, and CLAUDE.md token counting
- Fixed `/mcp reconnect` freezing the CLI when given a server name that doesn’t exist
- Fixed memory leak where completed task state objects were never removed from AppState
- Added support for `isolation: worktree` in agent definitions, allowing agents to declaratively run in isolated git worktrees.
- `CLAUDE_CODE_SIMPLE` mode now also disables MCP tools, attachments, hooks, and CLAUDE.md file loading for a fully minimal experience.
- Fixed bug where MCP tools were not discovered when tool search is enabled and a prompt is passed in as a launch argument
- Improved memory usage during long sessions by clearing internal caches after compaction
- Added `claude agents` CLI command to list all configured agents
- Improved memory usage during long sessions by clearing large tool results after they have been processed
- Fixed a memory leak where LSP diagnostic data was never cleaned up after delivery, causing unbounded memory growth in long sessions
- Fixed a memory leak where completed task output was not freed from memory, reducing memory usage in long sessions with many tasks
- Improved startup performance for headless mode (`-p` flag) by deferring Yoga WASM and UI component imports
- Fixed prompt suggestion cache regression that reduced cache hit rates
- Fixed unbounded memory growth in long sessions by capping file history snapshots
- Added `CLAUDE_CODE_DISABLE_1M_CONTEXT` environment variable to disable 1M context window support
- Opus 4.6 (fast mode) now includes the full 1M context window
- VSCode: Added `/extra-usage` command support in VS Code sessions
- Fixed memory leak where TaskOutput retained recent lines after cleanup
- Fixed memory leak in CircularBuffer where cleared items were retained in the backing array
- Fixed memory leak in shell command execution where ChildProcess and AbortController references were retained after cleanup
[](#2-1-49)
2.1.49
February 19, 2026
- Improved MCP OAuth authentication with step-up auth support and discovery caching, reducing redundant network requests during server connections
- Added `--worktree` (`-w`) flag to start Claude in an isolated git worktree
- Subagents support `isolation: "worktree"` for working in a temporary git worktree
- Added Ctrl+F keybinding to kill background agents (two-press confirmation)
- Agent definitions support `background: true` to always run as a background task
- Plugins can ship `settings.json` for default configuration
- Fixed file-not-found errors to suggest corrected paths when the model drops the repo folder
- Fixed Ctrl+C and ESC being silently ignored when background agents are running and the main thread is idle. Pressing twice within 3 seconds now kills all background agents.
- Fixed prompt suggestion cache regression that reduced cache hit rates.
- Fixed `plugin enable` and `plugin disable` to auto-detect the correct scope when `--scope` is not specified, instead of always defaulting to user scope
- Simple mode (`CLAUDE_CODE_SIMPLE`) now includes the file edit tool in addition to the Bash tool, allowing direct file editing in simple mode.
- Permission suggestions are now populated when safety checks trigger an ask response, enabling SDK consumers to display permission options
- Sonnet 4.5 with 1M context is being removed from the Max plan in favor of our frontier Sonnet 4.6 model, which now has 1M context. Please switch in /model.
- Fixed verbose mode not updating thinking block display when toggled via `/config` — memo comparators now correctly detect verbose changes
- Fixed unbounded WASM memory growth during long sessions by periodically resetting the tree-sitter parser
- Fixed potential rendering issues caused by stale yoga layout references
- Improved performance in non-interactive mode (`-p`) by skipping unnecessary API calls during startup
- Improved performance by caching authentication failures for HTTP and SSE MCP servers, avoiding repeated connection attempts to servers requiring auth
- Fixed unbounded memory growth during long-running sessions caused by Yoga WASM linear memory never shrinking
- SDK model info now includes `supportsEffort`, `supportedEffortLevels`, and `supportsAdaptiveThinking` fields so consumers can discover model capabilities.
- Added `ConfigChange` hook event that fires when configuration files change during a session, enabling enterprise security auditing and optional blocking of settings changes.
- Improved startup performance by caching MCP auth failures to avoid redundant connection attempts
- Improved startup performance by reducing HTTP calls for analytics token counting
- Improved startup performance by batching MCP tool token counting into a single API call
- Fixed `disableAllHooks` setting to respect managed settings hierarchy — non-managed settings can no longer disable managed hooks set by policy (#26637)
- Fixed `--resume` session picker showing raw XML tags for sessions that start with commands like `/clear`. Now correctly falls through to the session ID fallback.
- Improved permission prompts for path safety and working directory blocks to show the reason for the restriction instead of a bare prompt with no context
[](#2-1-47)
2.1.47
February 18, 2026
- Fixed FileWriteTool line counting to preserve intentional trailing blank lines instead of stripping them with `trimEnd()`.
- Fixed Windows terminal rendering bugs caused by `os.EOL` (`\r\n`) in display code — line counts now show correct values instead of always showing 1 on Windows.
- Improved VS Code plan preview: auto-updates as Claude iterates, enables commenting only when the plan is ready for review, and keeps the preview open when rejecting so Claude can revise.
- Fixed a bug where bold and colored text in markdown output could shift to the wrong characters on Windows due to `\r\n` line endings.
- Fixed compaction failing when conversation contains many PDF documents by stripping document blocks alongside images before sending to the compaction API (anthropics/claude-code#26188)
- Improved memory usage in long-running sessions by releasing API stream buffers, agent context, and skill state after use
- Improved startup performance by deferring SessionStart hook execution, reducing time-to-interactive by ~500ms.
- Fixed an issue where bash tool output was silently discarded on Windows when using MSYS2 or Cygwin shells.
- Improved performance of `@` file mentions - file suggestions now appear faster by pre-warming the index on startup and using session-based caching with background refresh.
- Improved memory usage by trimming agent task message history after tasks complete
- Improved memory usage during long agent sessions by eliminating O(n²) message accumulation in progress updates
- Fixed the bash permission classifier to validate that returned match descriptions correspond to actual input rules, preventing hallucinated descriptions from incorrectly granting permissions
- Fixed user-defined agents only loading one file on NFS/FUSE filesystems that report zero inodes (anthropics/claude-code#26044)
- Fixed plugin agent skills silently failing to load when referenced by bare name instead of fully-qualified plugin name (anthropics/claude-code#25834)
- Search patterns in collapsed tool results are now displayed in quotes for clarity
- Windows: Fixed CWD tracking temp files never being cleaned up, causing them to accumulate indefinitely (anthropics/claude-code#17600)
- Use `ctrl+f` to kill all background agents instead of double-pressing ESC. Background agents now continue running when you press ESC to cancel the main thread, giving you more control over agent lifecycle.
- Fixed API 400 errors (“thinking blocks cannot be modified”) that occurred in sessions with concurrent agents, caused by interleaved streaming content blocks preventing proper message merging.
- Simplified teammate navigation to use only Shift+Down (with wrapping) instead of both Shift+Up and Shift+Down.
- Fixed an issue where a single file write/edit error would abort all other parallel file write/edit operations. Independent file mutations now complete even when a sibling fails.
- Added `last_assistant_message` field to Stop and SubagentStop hook inputs, providing the final assistant response text so hooks can access it without parsing transcript files.
- Fixed custom session titles set via `/rename` being lost after resuming a conversation (anthropics/claude-code#23610)
- Fixed collapsed read/search hint text overflowing on narrow terminals by truncating from the start.
- Fixed an issue where bash commands with backslash-newline continuation lines (e.g., long commands split across multiple lines with `\`) would produce spurious empty arguments, potentially breaking command execution.
- Fixed built-in slash commands (`/help`, `/model`, `/compact`, etc.) being hidden from the autocomplete dropdown when many user skills are installed (anthropics/claude-code#22020)
- Fixed MCP servers not appearing in the MCP Management Dialog after deferred loading
- Fixed session name persisting in status bar after `/clear` command (anthropics/claude-code#26082)
- Fixed crash when a skill’s `name` or `description` in SKILL.md frontmatter is a bare number (e.g., `name: 3000`) — the value is now properly coerced to a string (anthropics/claude-code#25837)
- Fixed /resume silently dropping sessions when the first message exceeds 16KB or uses array-format content (anthropics/claude-code#25721)
- Added `chat:newline` keybinding action for configurable multi-line input (anthropics/claude-code#26075)
- Added `added_dirs` to the statusline JSON `workspace` section, exposing directories added via `/add-dir` to external scripts (anthropics/claude-code#26096)
- Fixed `claude doctor` misclassifying mise and asdf-managed installations as native installs (anthropics/claude-code#26033)
- Fixed zsh heredoc failing with “read-only file system” error in sandboxed commands (anthropics/claude-code#25990)
- Fixed agent progress indicator showing inflated tool use count (anthropics/claude-code#26023)
- Fixed image pasting not working on WSL2 systems where Windows copies images as BMP format (anthropics/claude-code#25935)
- Fixed background agent results returning raw transcript data instead of the agent’s final answer (anthropics/claude-code#26012)
- Fixed Warp terminal incorrectly prompting for Shift+Enter setup when it supports it natively (anthropics/claude-code#25957)
- Fixed CJK wide characters causing misaligned timestamps and layout elements in the TUI (anthropics/claude-code#26084)
- Fixed custom agent `model` field in `.claude/agents/*.md` being ignored when spawning team teammates (anthropics/claude-code#26064)
- Fixed plan mode being lost after context compaction, causing the model to switch from planning to implementation mode (anthropics/claude-code#26061)
- Fixed `alwaysThinkingEnabled: true` in settings.json not enabling thinking mode on Bedrock and Vertex providers (anthropics/claude-code#26074)
- Fixed `tool_decision` OTel telemetry event not being emitted in headless/SDK mode (anthropics/claude-code#26059)
- Fixed session name being lost after context compaction — renamed sessions now preserve their custom title through compaction (anthropics/claude-code#26121)
- Increased initial session count in resume picker from 10 to 50 for faster session discovery (anthropics/claude-code#26123)
- Windows: fixed worktree session matching when drive letter casing differs (anthropics/claude-code#26123)
- Fixed `/resume <session-id>` failing to find sessions whose first message exceeds 16KB (anthropics/claude-code#25920)
- Fixed “Always allow” on multiline bash commands creating invalid permission patterns that corrupt settings (anthropics/claude-code#25909)
- Fixed React crash (error \#31) when a skill’s `argument-hint` in SKILL.md frontmatter uses YAML sequence syntax (e.g., `[topic: foo | bar]`) — the value is now properly coerced to a string (anthropics/claude-code#25826)
- Fixed crash when using `/fork` on sessions that used web search — null entries in search results from transcript deserialization are now handled gracefully (anthropics/claude-code#25811)
- Fixed read-only git commands triggering FSEvents file watcher loops on macOS by adding —no-optional-locks flag (anthropics/claude-code#25750)
- Fixed custom agents and skills not being discovered when running from a git worktree — project-level `.claude/agents/` and `.claude/skills/` from the main repository are now included (anthropics/claude-code#25816)
- Fixed non-interactive subcommands like `claude doctor` and `claude plugin validate` being blocked inside nested Claude sessions (anthropics/claude-code#25803)
- Windows: Fixed the same CLAUDE.md file being loaded twice when drive letter casing differs between paths (anthropics/claude-code#25756)
- Fixed inline code spans in markdown being incorrectly parsed as bash commands (anthropics/claude-code#25792)
- Fixed teammate spinners not respecting custom spinnerVerbs from settings (anthropics/claude-code#25748)
- Fixed shell commands permanently failing after a command deletes its own working directory (anthropics/claude-code#26136)
- Fixed hooks (PreToolUse, PostToolUse) silently failing to execute on Windows by using Git Bash instead of cmd.exe (anthropics/claude-code#25981)
- Fixed LSP `findReferences` and other location-based operations returning results from gitignored files (e.g., `node_modules/`, `venv/`) (anthropics/claude-code#26051)
- Moved config backup files from home directory root to `~/.claude/backups/` to reduce home directory clutter (anthropics/claude-code#26130)
- Fixed sessions with large first prompts (\>16KB) disappearing from the /resume list (anthropics/claude-code#26140)
- Fixed shell functions with double-underscore prefixes (e.g., `__git_ps1`) not being preserved across shell sessions (anthropics/claude-code#25824)
- Fixed spinner showing “0 tokens” counter before any tokens have been received (anthropics/claude-code#26105)
- VSCode: Fixed conversation messages appearing dimmed while the AskUserQuestion dialog is open (anthropics/claude-code#26078)
- Fixed background tasks failing in git worktrees due to remote URL resolution reading from worktree-specific gitdir instead of the main repository config (anthropics/claude-code#26065)
- Fixed Right Alt key leaving visible `[25~` escape sequence residue in the input field on Windows/Git Bash terminals (anthropics/claude-code#25943)
- The `/rename` command now updates the terminal tab title by default (anthropics/claude-code#25789)
- Fixed Edit tool silently corrupting Unicode curly quotes (\u201c\u201d \u2018\u2019) by replacing them with straight quotes when making edits (anthropics/claude-code#26141)
- Fixed OSC 8 hyperlinks only being clickable on the first line when link text wraps across multiple terminal lines.
[](#2-1-46)
2.1.46
February 18, 2026
- Fixed orphaned CC processes after terminal disconnect on macOS
- Added support for using claude.ai MCP connectors in Claude Code
[](#2-1-45)
2.1.45
February 17, 2026
- Added support for Claude Sonnet 4.6
- Added support for reading `enabledPlugins` and `extraKnownMarketplaces` from `--add-dir` directories
- Added `spinnerTipsOverride` setting to customize spinner tips — configure `tips` with an array of custom tip strings, and optionally set `excludeDefault: true` to show only your custom tips instead of the built-in ones
- Added `SDKRateLimitInfo` and `SDKRateLimitEvent` types to the SDK, enabling consumers to receive rate limit status updates including utilization, reset times, and overage information
- Fixed Agent Teams teammates failing on Bedrock, Vertex, and Foundry by propagating API provider environment variables to tmux-spawned processes (anthropics/claude-code#23561)
- Fixed sandbox “operation not permitted” errors when writing temporary files on macOS by using the correct per-user temp directory (anthropics/claude-code#21654)
- Fixed Task tool (backgrounded agents) crashing with a `ReferenceError` on completion (anthropics/claude-code#22087)
- Fixed autocomplete suggestions not being accepted on Enter when images are pasted in the input
- Fixed skills invoked by subagents incorrectly appearing in main session context after compaction
- Fixed excessive `.claude.json.backup` files accumulating on every startup
- Fixed plugin-provided commands, agents, and hooks not being available immediately after installation without requiring a restart
- Improved startup performance by removing eager loading of session history for stats caching
- Improved memory usage for shell commands that produce large output — RSS no longer grows unboundedly with command output size
- Improved collapsed read/search groups to show the current file or search pattern being processed beneath the summary line while active
- \[VSCode\] Improved permission destination choice (project/user/session) to persist across sessions
[](#2-1-44)
2.1.44
February 16, 2026
- Fixed ENAMETOOLONG errors for deeply-nested directory paths
- Fixed auth refresh errors
[](#2-1-43)
2.1.43
February 16, 2026
- Fixed AWS auth refresh hanging indefinitely by adding a 3-minute timeout
- Fixed spurious warnings for non-agent markdown files in `.claude/agents/` directory
- Fixed structured-outputs beta header being sent unconditionally on Vertex/Bedrock
[](#2-1-42)
2.1.42
February 13, 2026
- Improved startup performance by deferring Zod schema construction
- Improved prompt cache hit rates by moving date out of system prompt
- Added one-time Opus 4.6 effort callout for eligible users
- Fixed /resume showing interrupt messages as session titles
- Fixed image dimension limit errors to suggest /compact
[](#2-1-41)
2.1.41
February 13, 2026
- Added guard against launching Claude Code inside another Claude Code session
- Fixed Agent Teams using wrong model identifier for Bedrock, Vertex, and Foundry customers
- Fixed a crash when MCP tools return image content during streaming
- Fixed /resume session previews showing raw XML tags instead of readable command names
- Improved model error messages for Bedrock/Vertex/Foundry users with fallback suggestions
- Fixed plugin browse showing misleading “Space to Toggle” hint for already-installed plugins
- Fixed hook blocking errors (exit code 2) not showing stderr to the user
- Added `speed` attribute to OTel events and trace spans for fast mode visibility
- Added `claude auth login`, `claude auth status`, and `claude auth logout` CLI subcommands
- Added Windows ARM64 (win32-arm64) native binary support
- Improved `/rename` to auto-generate session name from conversation context when called without arguments
- Improved narrow terminal layout for prompt footer
- Fixed file resolution failing for @-mentions with anchor fragments (e.g., `@README.md#installation`)
- Fixed FileReadTool blocking the process on FIFOs, `/dev/stdin`, and large files
- Fixed background task notifications not being delivered in streaming Agent SDK mode
- Fixed cursor jumping to end on each keystroke in classifier rule input
- Fixed markdown link display text being dropped for raw URL
- Fixed auto-compact failure error notifications being shown to users
- Fixed permission wait time being included in subagent elapsed time display
- Fixed proactive ticks firing while in plan mode
- Fixed clear stale permission rules when settings change on disk
- Fixed hook blocking errors showing stderr content in UI
[](#2-1-39)
2.1.39
February 10, 2026
- Improved terminal rendering performance
- Fixed fatal errors being swallowed instead of displayed
- Fixed process hanging after session close
- Fixed character loss at terminal screen boundary
- Fixed blank lines in verbose transcript view
[](#2-1-38)
2.1.38
February 10, 2026
- Fixed VS Code terminal scroll-to-top regression introduced in 2.1.37
- Fixed Tab key queueing slash commands instead of autocompleting
- Fixed bash permission matching for commands using environment variable wrappers
- Fixed text between tool uses disappearing when not using streaming
- Fixed duplicate sessions when resuming in VS Code extension
- Improved heredoc delimiter parsing to prevent command smuggling
- Blocked writes to `.claude/skills` directory in sandbox mode
[](#2-1-37)
2.1.37
February 7, 2026
- Fixed an issue where /fast was not immediately available after enabling /extra-usage
[](#2-1-36)
2.1.36
February 7, 2026
- Fast mode is now available for Opus 4.6. Learn more at [https://code.claude.com/docs/en/fast-mode](fast-mode.md)
[](#2-1-34)
2.1.34
February 6, 2026
- Fixed a crash when agent teams setting changed between renders
- Fixed a bug where commands excluded from sandboxing (via `sandbox.excludedCommands` or `dangerouslyDisableSandbox`) could bypass the Bash ask permission rule when `autoAllowBashIfSandboxed` was enabled
[](#2-1-33)
2.1.33
February 6, 2026
- Fixed agent teammate sessions in tmux to send and receive messages
- Fixed warnings about agent teams not being available on your current plan
- Added `TeammateIdle` and `TaskCompleted` hook events for multi-agent workflows
- Added support for restricting which sub-agents can be spawned via `Task(agent_type)` syntax in agent “tools” frontmatter
- Added `memory` frontmatter field support for agents, enabling persistent memory with `user`, `project`, or `local` scope
- Added plugin name to skill descriptions and `/skills` menu for better discoverability
- Fixed an issue where submitting a new message while the model was in extended thinking would interrupt the thinking phase
- Fixed an API error that could occur when aborting mid-stream, where whitespace text combined with a thinking block would bypass normalization and produce an invalid request
- Fixed API proxy compatibility issue where 404 errors on streaming endpoints no longer triggered non-streaming fallback
- Fixed an issue where proxy settings configured via `settings.json` environment variables were not applied to WebFetch and other HTTP requests on the Node.js build
- Fixed `/resume` session picker showing raw XML markup instead of clean titles for sessions started with slash commands
- Improved error messages for API connection failures — now shows specific cause (e.g., ECONNREFUSED, SSL errors) instead of generic “Connection error”
- Errors from invalid managed settings are now surfaced
- VSCode: Added support for remote sessions, allowing OAuth users to browse and resume sessions from claude.ai
- VSCode: Added git branch and message count to the session picker, with support for searching by branch name
- VSCode: Fixed scroll-to-bottom under-scrolling on initial session load and session switch
[](#2-1-32)
2.1.32
February 5, 2026
- Claude Opus 4.6 is now available!
- Added research preview agent teams feature for multi-agent collaboration (token-intensive feature, requires setting CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)
- Claude now automatically records and recalls memories as it works
- Added “Summarize from here” to the message selector, allowing partial conversation summarization.
- Skills defined in `.claude/skills/` within additional directories (`--add-dir`) are now loaded automatically.
- Fixed `@` file completion showing incorrect relative paths when running from a subdirectory
- Updated —resume to re-use —agent value specified in previous conversation by default.
- Fixed: Bash tool no longer throws “Bad substitution” errors when heredocs contain JavaScript template literals like `${index + 1}`, which previously interrupted tool execution
- Skill character budget now scales with context window (2% of context), so users with larger context windows can see more skill descriptions without truncation
- Fixed Thai/Lao spacing vowels (สระ า, ำ) not rendering correctly in the input field
- VSCode: Fixed slash commands incorrectly being executed when pressing Enter with preceding text in the input field
- VSCode: Added spinner when loading past conversations list
[](#2-1-31)
2.1.31
February 4, 2026
- Added session resume hint on exit, showing how to continue your conversation later
- Added support for full-width (zenkaku) space input from Japanese IME in checkbox selection
- Fixed PDF too large errors permanently locking up sessions, requiring users to start a new conversation
- Fixed bash commands incorrectly reporting failure with “Read-only file system” errors when sandbox mode was enabled
- Fixed a crash that made sessions unusable after entering plan mode when project config in `~/.claude.json` was missing default fields
- Fixed `temperatureOverride` being silently ignored in the streaming API path, causing all streaming requests to use the default temperature (1) regardless of the configured override
- Fixed LSP shutdown/exit compatibility with strict language servers that reject null params
- Improved system prompts to more clearly guide the model toward using dedicated tools (Read, Edit, Glob, Grep) instead of bash equivalents (`cat`, `sed`, `grep`, `find`), reducing unnecessary bash command usage
- Improved PDF and request size error messages to show actual limits (100 pages, 20MB)
- Reduced layout jitter in the terminal when the spinner appears and disappears during streaming
- Removed misleading Anthropic API pricing from model selector for third-party provider (Bedrock, Vertex, Foundry) users
[](#2-1-30)
2.1.30
February 3, 2026
- Added `pages` parameter to the Read tool for PDFs, allowing specific page ranges to be read (e.g., `pages: "1-5"`). Large PDFs (\>10 pages) now return a lightweight reference when `@` mentioned instead of being inlined into context.
- Added pre-configured OAuth client credentials for MCP servers that don’t support Dynamic Client Registration (e.g., Slack). Use `--client-id` and `--client-secret` with `claude mcp add`.
- Added `/debug` for Claude to help troubleshoot the current session
- Added support for additional `git log` and `git show` flags in read-only mode (e.g., `--topo-order`, `--cherry-pick`, `--format`, `--raw`)
- Added token count, tool uses, and duration metrics to Task tool results
- Added reduced motion mode to the config
- Fixed phantom “(no content)” text blocks appearing in API conversation history, reducing token waste and potential model confusion
- Fixed prompt cache not correctly invalidating when tool descriptions or input schemas changed, only when tool names changed
- Fixed 400 errors that could occur after running `/login` when the conversation contained thinking blocks
- Fixed a hang when resuming sessions with corrupted transcript files containing `parentUuid` cycles
- Fixed rate limit message showing incorrect “/upgrade” suggestion for Max 20x users when extra-usage is unavailable
- Fixed permission dialogs stealing focus while actively typing
- Fixed subagents not being able to access SDK-provided MCP tools because they were not synced to the shared application state
- Fixed a regression where Windows users with a `.bashrc` file could not run bash commands
- Improved memory usage for `--resume` (68% reduction for users with many sessions) by replacing the session index with lightweight stat-based loading and progressive enrichment
- Improved `TaskStop` tool to display the stopped command/task description in the result line instead of a generic “Task stopped” message
- Changed `/model` to execute immediately instead of being queued
- \[VSCode\] Added multiline input support to the “Other” text input in question dialogs (use Shift+Enter for new lines)
- \[VSCode\] Fixed duplicate sessions appearing in the session list when starting a new conversation
[](#2-1-29)
2.1.29
January 31, 2026
- Fixed startup performance issues when resuming sessions that have `saved_hook_context`
[](#2-1-27)
2.1.27
January 30, 2026
- Added tool call failures and denials to debug logs
- Fixed context management validation error for gateway users, ensuring `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` avoids the error
- Added `--from-pr` flag to resume sessions linked to a specific GitHub PR number or URL
- Sessions are now automatically linked to PRs when created via `gh pr create`
- Fixed /context command not displaying colored output
- Fixed status bar duplicating background task indicator when PR status was shown
- Windows: Fixed bash command execution failing for users with `.bashrc` files
- Windows: Fixed console windows flashing when spawning child processes
- VSCode: Fixed OAuth token expiration causing 401 errors after extended sessions
[](#2-1-25)
2.1.25
January 29, 2026
- Fixed beta header validation error for gateway users on Bedrock and Vertex, ensuring `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` avoids the error
[](#2-1-23)
2.1.23
January 29, 2026
- Added customizable spinner verbs setting (`spinnerVerbs`)
- Fixed mTLS and proxy connectivity for users behind corporate proxies or using client certificates
- Fixed per-user temp directory isolation to prevent permission conflicts on shared systems
- Fixed a race condition that could cause 400 errors when prompt caching scope was enabled
- Fixed pending async hooks not being cancelled when headless streaming sessions ended
- Fixed tab completion not updating the input field when accepting a suggestion
- Fixed ripgrep search timeouts silently returning empty results instead of reporting errors
- Improved terminal rendering performance with optimized screen data layout
- Changed Bash commands to show timeout duration alongside elapsed time
- Changed merged pull requests to show a purple status indicator in the prompt footer
- \[IDE\] Fixed model options displaying incorrect region strings for Bedrock users in headless mode
[](#2-1-22)
2.1.22
January 28, 2026
- Fixed structured outputs for non-interactive (-p) mode
[](#2-1-21)
2.1.21
January 28, 2026
- Added support for full-width (zenkaku) number input from Japanese IME in option selection prompts
- Fixed shell completion cache files being truncated on exit
- Fixed API errors when resuming sessions that were interrupted during tool execution
- Fixed auto-compact triggering too early on models with large output token limits
- Fixed task IDs potentially being reused after deletion
- Fixed file search not working in VS Code extension on Windows
- Improved read/search progress indicators to show “Reading…” while in progress and “Read” when complete
- Improved Claude to prefer file operation tools (Read, Edit, Write) over bash equivalents (cat, sed, awk)
- \[VSCode\] Added automatic Python virtual environment activation, ensuring `python` and `pip` commands use the correct interpreter (configurable via `claudeCode.usePythonEnvironment` setting)
- \[VSCode\] Fixed message action buttons having incorrect background colors
[](#2-1-20)
2.1.20
January 27, 2026
- Added arrow key history navigation in vim normal mode when cursor cannot move further
- Added external editor shortcut (Ctrl+G) to the help menu for better discoverability
- Added PR review status indicator to the prompt footer, showing the current branch’s PR state (approved, changes requested, pending, or draft) as a colored dot with a clickable link
- Added support for loading `CLAUDE.md` files from additional directories specified via `--add-dir` flag (requires setting `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1`)
- Added ability to delete tasks via the `TaskUpdate` tool
- Fixed session compaction issues that could cause resume to load full history instead of the compact summary
- Fixed agents sometimes ignoring user messages sent while actively working on a task
- Fixed wide character (emoji, CJK) rendering artifacts where trailing columns were not cleared when replaced by narrower characters
- Fixed JSON parsing errors when MCP tool responses contain special Unicode characters
- Fixed up/down arrow keys in multi-line and wrapped text input to prioritize cursor movement over history navigation
- Fixed draft prompt being lost when pressing UP arrow to navigate command history
- Fixed ghost text flickering when typing slash commands mid-input
- Fixed marketplace source removal not properly deleting settings
- Fixed duplicate output in some commands like `/context`
- Fixed task list sometimes showing outside the main conversation view
- Fixed syntax highlighting for diffs occurring within multiline constructs like Python docstrings
- Fixed crashes when cancelling tool use
- Improved `/sandbox` command UI to show dependency status with installation instructions when dependencies are missing
- Improved thinking status text with a subtle shimmer animation
- Improved task list to dynamically adjust visible items based on terminal height
- Improved fork conversation hint to show how to resume the original session
- Changed collapsed read/search groups to show present tense (“Reading”, “Searching for”) while in progress, and past tense (“Read”, “Searched for”) when complete
- Changed `ToolSearch` results to appear as a brief notification instead of inline in the conversation
- Changed the `/commit-push-pr` skill to automatically post PR URLs to Slack channels when configured via MCP tools
- Changed the `/copy` command to be available to all users
- Changed background agents to prompt for tool permissions before launching
- Changed permission rules like `Bash(*)` to be accepted and treated as equivalent to `Bash`
- Changed config backups to be timestamped and rotated (keeping 5 most recent) to prevent data loss
[](#2-1-19)
2.1.19
January 23, 2026
- Added env var `CLAUDE_CODE_ENABLE_TASKS`, set to `false` to keep the old system temporarily
- Added shorthand `$0`, `$1`, etc. for accessing individual arguments in custom commands
- Fixed crashes on processors without AVX instruction support
- Fixed dangling Claude Code processes when terminal is closed by catching EIO errors from `process.exit()` and using SIGKILL as fallback
- Fixed `/rename` and `/tag` not updating the correct session when resuming from a different directory (e.g., git worktrees)
- Fixed resuming sessions by custom title not working when run from a different directory
- Fixed pasted text content being lost when using prompt stash (Ctrl+S) and restore
- Fixed agent list displaying “Sonnet (default)” instead of “Inherit (default)” for agents without an explicit model setting
- Fixed backgrounded hook commands not returning early, potentially causing the session to wait on a process that was intentionally backgrounded
- Fixed file write preview omitting empty lines
- Changed skills without additional permissions or hooks to be allowed without requiring approval
- Changed indexed argument syntax from `$ARGUMENTS.0` to `$ARGUMENTS[0]` (bracket syntax)
- \[SDK\] Added replay of `queued_command` attachment messages as `SDKUserMessageReplay` events when `replayUserMessages` is enabled
- \[VSCode\] Enabled session forking and rewind functionality for all users
[](#2-1-18)
2.1.18
January 23, 2026
- Added customizable keyboard shortcuts. Configure keybindings per context, create chord sequences, and personalize your workflow. Run `/keybindings` to get started. Learn more at [https://code.claude.com/docs/en/keybindings](keybindings.md)
[](#2-1-17)
2.1.17
January 22, 2026
- Fixed crashes on processors without AVX instruction support
[](#2-1-16)
2.1.16
January 22, 2026
- Added new task management system, including new capabilities like dependency tracking
- \[VSCode\] Added native plugin management support
- \[VSCode\] Added ability for OAuth users to browse and resume remote Claude sessions from the Sessions dialog
- Fixed out-of-memory crashes when resuming sessions with heavy subagent usage
- Fixed an issue where the “context remaining” warning was not hidden after running `/compact`
- Fixed session titles on the resume screen not respecting the user’s language setting
- \[IDE\] Fixed a race condition on Windows where the Claude Code sidebar view container would not appear on start
[](#2-1-15)
2.1.15
January 21, 2026
- Added deprecation notification for npm installations - run `claude install` or see [https://code.claude.com/docs/en/setup](../01-Getting-Started/setup.md) for more options
- Improved UI rendering performance with React Compiler
- Fixed the “Context left until auto-compact” warning not disappearing after running `/compact`
- Fixed MCP stdio server timeout not killing child process, which could cause UI freezes
[](#2-1-14)
2.1.14
January 20, 2026
- Added history-based autocomplete in bash mode (`!`) - type a partial command and press Tab to complete from your bash command history
- Added search to installed plugins list - type to filter by name or description
- Added support for pinning plugins to specific git commit SHAs, allowing marketplace entries to install exact versions
- Fixed a regression where the context window blocking limit was calculated too aggressively, blocking users at ~65% context usage instead of the intended ~98%
- Fixed memory issues that could cause crashes when running parallel subagents
- Fixed memory leak in long-running sessions where stream resources were not cleaned up after shell commands completed
- Fixed `@` symbol incorrectly triggering file autocomplete suggestions in bash mode
- Fixed `@`-mention menu folder click behavior to navigate into directories instead of selecting them
- Fixed `/feedback` command generating invalid GitHub issue URLs when description is very long
- Fixed `/context` command to show the same token count and percentage as the status line in verbose mode
- Fixed an issue where `/config`, `/context`, `/model`, and `/todos` command overlays could close unexpectedly
- Fixed slash command autocomplete selecting wrong command when typing similar commands (e.g., `/context` vs `/compact`)
- Fixed inconsistent back navigation in plugin marketplace when only one marketplace is configured
- Fixed iTerm2 progress bar not clearing properly on exit, preventing lingering indicators and bell sounds
- Improved backspace to delete pasted text as a single token instead of one character at a time
- \[VSCode\] Added `/usage` command to display current plan usage
[](#2-1-12)
2.1.12
January 17, 2026
- Fixed message rendering bug
[](#2-1-11)
2.1.11
January 17, 2026
- Fixed excessive MCP connection requests for HTTP/SSE transports
[](#2-1-10)
2.1.10
January 17, 2026
- Added new `Setup` hook event that can be triggered via `--init`, `--init-only`, or `--maintenance` CLI flags for repository setup and maintenance operations
- Added keyboard shortcut ‘c’ to copy OAuth URL when browser doesn’t open automatically during login
- Fixed a crash when running bash commands containing heredocs with JavaScript template literals like `${index + 1}`
- Improved startup to capture keystrokes typed before the REPL is fully ready
- Improved file suggestions to show as removable attachments instead of inserting text when accepted
- \[VSCode\] Added install count display to plugin listings
- \[VSCode\] Added trust warning when installing plugins
[](#2-1-9)
2.1.9
January 16, 2026
- Added `auto:N` syntax for configuring the MCP tool search auto-enable threshold, where N is the context window percentage (0-100)
- Added `plansDirectory` setting to customize where plan files are stored
- Added external editor support (Ctrl+G) in AskUserQuestion “Other” input field
- Added session URL attribution to commits and PRs created from web sessions
- Added support for `PreToolUse` hooks to return `additionalContext` to the model
- Added `${CLAUDE_SESSION_ID}` string substitution for skills to access the current session ID
- Fixed long sessions with parallel tool calls failing with an API error about orphan tool_result blocks
- Fixed MCP server reconnection hanging when cached connection promise never resolves
- Fixed Ctrl+Z suspend not working in terminals using Kitty keyboard protocol (Ghostty, iTerm2, kitty, WezTerm)
[](#2-1-7)
2.1.7
January 14, 2026
- Added `showTurnDuration` setting to hide turn duration messages (e.g., “Cooked for 1m 6s”)
- Added ability to provide feedback when accepting permission prompts
- Added inline display of agent’s final response in task notifications, making it easier to see results without reading the full transcript file
- Fixed security vulnerability where wildcard permission rules could match compound commands containing shell operators
- Fixed false “file modified” errors on Windows when cloud sync tools, antivirus scanners, or Git touch file timestamps without changing content
- Fixed orphaned tool_result errors when sibling tools fail during streaming execution
- Fixed context window blocking limit being calculated using the full context window instead of the effective context window (which reserves space for max output tokens)
- Fixed spinner briefly flashing when running local slash commands like `/model` or `/theme`
- Fixed terminal title animation jitter by using fixed-width braille characters
- Fixed plugins with git submodules not being fully initialized when installed
- Fixed bash commands failing on Windows when temp directory paths contained characters like `t` or `n` that were misinterpreted as escape sequences
- Improved typing responsiveness by reducing memory allocation overhead in terminal rendering
- Enabled MCP tool search auto mode by default for all users. When MCP tool descriptions exceed 10% of the context window, they are automatically deferred and discovered via the MCPSearch tool instead of being loaded upfront. This reduces context usage for users with many MCP tools configured. Users can disable this by adding `MCPSearch` to `disallowedTools` in their settings.
- Changed OAuth and API Console URLs from console.anthropic.com to platform.claude.com
- \[VSCode\] Fixed `claudeProcessWrapper` setting passing the wrapper path instead of the Claude binary path
[](#2-1-6)
2.1.6
January 13, 2026
- Added search functionality to `/config` command for quickly filtering settings
- Added Updates section to `/doctor` showing auto-update channel and available npm versions (stable/latest)
- Added date range filtering to `/stats` command - press `r` to cycle between Last 7 days, Last 30 days, and All time
- Added automatic discovery of skills from nested `.claude/skills` directories when working with files in subdirectories
- Added `context_window.used_percentage` and `context_window.remaining_percentage` fields to status line input for easier context window display
- Added an error display when the editor fails during Ctrl+G
- Fixed permission bypass via shell line continuation that could allow blocked commands to execute
- Fixed false “File has been unexpectedly modified” errors when file watchers touch files without changing content
- Fixed text styling (bold, colors) getting progressively misaligned in multi-line responses
- Fixed the feedback panel closing unexpectedly when typing ‘n’ in the description field
- Fixed rate limit warning appearing at low usage after weekly reset (now requires 70% usage)
- Fixed rate limit options menu incorrectly auto-opening when resuming a previous session
- Fixed numpad keys outputting escape sequences instead of characters in Kitty keyboard protocol terminals
- Fixed Option+Return not inserting newlines in Kitty keyboard protocol terminals
- Fixed corrupted config backup files accumulating in the home directory (now only one backup is created per config file)
- Fixed `mcp list` and `mcp get` commands leaving orphaned MCP server processes
- Fixed visual artifacts in ink2 mode when nodes become hidden via `display:none`
- Improved the external CLAUDE.md imports approval dialog to show which files are being imported and from where
- Improved the `/tasks` dialog to go directly to task details when there’s only one background task running
- Improved @ autocomplete with icons for different suggestion types and single-line formatting
- Updated “Help improve Claude” setting fetch to refresh OAuth and retry when it fails due to a stale OAuth token
- Changed task notification display to cap at 3 lines with overflow summary when multiple background tasks complete simultaneously
- Changed terminal title to “Claude Code” on startup for better window identification
- Removed ability to @-mention MCP servers to enable/disable - use `/mcp enable <name>` instead
- \[VSCode\] Fixed usage indicator not updating after manual compact
[](#2-1-5)
2.1.5
January 12, 2026
- Added `CLAUDE_CODE_TMPDIR` environment variable to override the temp directory used for internal temp files, useful for environments with custom temp directory requirements
[](#2-1-4)
2.1.4
January 11, 2026
- Added `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to disable all background task functionality including auto-backgrounding and the Ctrl+B shortcut
- Fixed “Help improve Claude” setting fetch to refresh OAuth and retry when it fails due to a stale OAuth token
[](#2-1-3)
2.1.3
January 9, 2026
- Merged slash commands and skills, simplifying the mental model with no change in behavior
- Added release channel (`stable` or `latest`) toggle to `/config`
- Added detection and warnings for unreachable permission rules, with warnings in `/doctor` and after saving rules that include the source of each rule and actionable fix guidance
- Fixed plan files persisting across `/clear` commands, now ensuring a fresh plan file is used after clearing a conversation
- Fixed false skill duplicate detection on filesystems with large inodes (e.g., ExFAT) by using 64-bit precision for inode values
- Fixed mismatch between background task count in status bar and items shown in tasks dialog
- Fixed sub-agents using the wrong model during conversation compaction
- Fixed web search in sub-agents using incorrect model
- Fixed trust dialog acceptance when running from the home directory not enabling trust-requiring features like hooks during the session
- Improved terminal rendering stability by preventing uncontrolled writes from corrupting cursor state
- Improved slash command suggestion readability by truncating long descriptions to 2 lines
- Changed tool hook execution timeout from 60 seconds to 10 minutes
- \[VSCode\] Added clickable destination selector for permission requests, allowing you to choose where settings are saved (this project, all projects, shared with team, or session only)
[](#2-1-2)
2.1.2
January 9, 2026
- Added source path metadata to images dragged onto the terminal, helping Claude understand where images originated
- Added clickable hyperlinks for file paths in tool output in terminals that support OSC 8 (like iTerm)
- Added support for Windows Package Manager (winget) installations with automatic detection and update instructions
- Added Shift+Tab keyboard shortcut in plan mode to quickly select “auto-accept edits” option
- Added `FORCE_AUTOUPDATE_PLUGINS` environment variable to allow plugin autoupdate even when the main auto-updater is disabled
- Added `agent_type` to SessionStart hook input, populated if `--agent` is specified
- Fixed a command injection vulnerability in bash command processing where malformed input could execute arbitrary commands
- Fixed a memory leak where tree-sitter parse trees were not being freed, causing WASM memory to grow unbounded over long sessions
- Fixed binary files (images, PDFs, etc.) being accidentally included in memory when using `@include` directives in CLAUDE.md files
- Fixed updates incorrectly claiming another installation is in progress
- Fixed crash when socket files exist in watched directories (defense-in-depth for EOPNOTSUPP errors)
- Fixed remote session URL and teleport being broken when using `/tasks` command
- Fixed MCP tool names being exposed in analytics events by sanitizing user-specific server configurations
- Improved Option-as-Meta hint on macOS to show terminal-specific instructions for native CSIu terminals like iTerm2, Kitty, and WezTerm
- Improved error message when pasting images over SSH to suggest using `scp` instead of the unhelpful clipboard shortcut hint
- Improved permission explainer to not flag routine dev workflows (git fetch/rebase, npm install, tests, PRs) as medium risk
- Changed large bash command outputs to be saved to disk instead of truncated, allowing Claude to read the full content
- Changed large tool outputs to be persisted to disk instead of truncated, providing full output access via file references
- Changed `/plugins` installed tab to unify plugins and MCPs with scope-based grouping
- Deprecated Windows managed settings path `C:\ProgramData\ClaudeCode\managed-settings.json` - administrators should migrate to `C:\Program Files\ClaudeCode\managed-settings.json`
- \[SDK\] Changed minimum zod peer dependency to ^4.0.0
- \[VSCode\] Fixed usage display not updating after manual compact
[](#2-1-0)
2.1.0
January 7, 2026
- Added automatic skill hot-reload - skills created or modified in `~/.claude/skills` or `.claude/skills` are now immediately available without restarting the session
- Added support for running skills and slash commands in a forked sub-agent context using `context: fork` in skill frontmatter
- Added support for `agent` field in skills to specify agent type for execution
- Added `language` setting to configure Claude’s response language (e.g., language: “japanese”)
- Changed Shift+Enter to work out of the box in iTerm2, WezTerm, Ghostty, and Kitty without modifying terminal configs
- Added `respectGitignore` support in `settings.json` for per-project control over @-mention file picker behavior
- Added `IS_DEMO` environment variable to hide email and organization from the UI, useful for streaming or recording sessions
- Fixed security issue where sensitive data (OAuth tokens, API keys, passwords) could be exposed in debug logs
- Fixed files and skills not being properly discovered when resuming sessions with `-c` or `--resume`
- Fixed pasted content being lost when replaying prompts from history using up arrow or Ctrl+R search
- Fixed Esc key with queued prompts to only move them to input without canceling the running task
- Reduced permission prompts for complex bash commands
- Fixed command search to prioritize exact and prefix matches on command names over fuzzy matches in descriptions
- Fixed PreToolUse hooks to allow `updatedInput` when returning `ask` permission decision, enabling hooks to act as middleware while still requesting user consent
- Fixed plugin path resolution for file-based marketplace sources
- Fixed LSP tool being incorrectly enabled when no LSP servers were configured
- Fixed background tasks failing with “git repository not found” error for repositories with dots in their names
- Fixed Claude in Chrome support for WSL environments
- Fixed Windows native installer silently failing when executable creation fails
- Improved CLI help output to display options and subcommands in alphabetical order for easier navigation
- Added wildcard pattern matching for Bash tool permissions using `*` at any position in rules (e.g., `Bash(npm *)`, `Bash(* install)`, `Bash(git * main)`)
- Added unified Ctrl+B backgrounding for both bash commands and agents - pressing Ctrl+B now backgrounds all running foreground tasks simultaneously
- Added support for MCP `list_changed` notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring reconnection
- Added `/teleport` and `/remote-env` slash commands for claude.ai subscribers, allowing them to resume and configure remote sessions
- Added support for disabling specific agents using `Task(AgentName)` syntax in settings.json permissions or the `--disallowedTools` CLI flag
- Added hooks support to agent frontmatter, allowing agents to define PreToolUse, PostToolUse, and Stop hooks scoped to the agent’s lifecycle
- Added hooks support for skill and slash command frontmatter
- Added new Vim motions: `;` and `,` to repeat f/F/t/T motions, `y` operator for yank with `yy`/`Y`, `p`/`P` for paste, text objects (`iw`, `aw`, `iW`, `aW`, `i"`, `a"`, `i'`, `a'`, `i(`, `a(`, `i[`, `a[`, `i{`, `a{`), `>>` and `<<` for indent/dedent, and `J` to join lines
- Added `/plan` command shortcut to enable plan mode directly from the prompt
- Added slash command autocomplete support when `/` appears anywhere in input, not just at the beginning
- Added `--tools` flag support in interactive mode to restrict which built-in tools Claude can use during interactive sessions
- Added `CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS` environment variable to override the default file read token limit
- Added support for `once: true` config for hooks
- Added support for YAML-style lists in frontmatter `allowed-tools` field for cleaner skill declarations
- Added support for prompt and agent hook types from plugins (previously only command hooks were supported)
- Added Cmd+V support for image paste in iTerm2 (maps to Ctrl+V)
- Added left/right arrow key navigation for cycling through tabs in dialogs
- Added real-time thinking block display in Ctrl+O transcript mode
- Added filepath to full output in background bash task details dialog
- Added Skills as a separate category in the context visualization
- Fixed OAuth token refresh not triggering when server reports token expired but local expiration check disagrees
- Fixed session persistence getting stuck after transient server errors by recovering from 409 conflicts when the entry was actually stored
- Fixed session resume failures caused by orphaned tool results during concurrent tool execution
- Fixed a race condition where stale OAuth tokens could be read from the keychain cache during concurrent token refresh attempts
- Fixed AWS Bedrock subagents not inheriting EU/APAC cross-region inference model configuration, causing 403 errors when IAM permissions are scoped to specific regions
- Fixed API context overflow when background tasks produce large output by truncating to 30K chars with file path reference
- Fixed a hang when reading FIFO files by skipping symlink resolution for special file types
- Fixed terminal keyboard mode not being reset on exit in Ghostty, iTerm2, Kitty, and WezTerm
- Fixed Alt+B and Alt+F (word navigation) not working in iTerm2, Ghostty, Kitty, and WezTerm
- Fixed `${CLAUDE_PLUGIN_ROOT}` not being substituted in plugin `allowed-tools` frontmatter, which caused tools to incorrectly require approval
- Fixed files created by the Write tool using hardcoded 0o600 permissions instead of respecting the system umask
- Fixed commands with `$()` command substitution failing with parse errors
- Fixed multi-line bash commands with backslash continuations being incorrectly split and flagged for permissions
- Fixed bash command prefix extraction to correctly identify subcommands after global options (e.g., `git -C /path log` now correctly matches `Bash(git log:*)` rules)
- Fixed slash commands passed as CLI arguments (e.g., `claude /context`) not being executed properly
- Fixed pressing Enter after Tab-completing a slash command selecting a different command instead of submitting the completed one
- Fixed slash command argument hint flickering and inconsistent display when typing commands with arguments
- Fixed Claude sometimes redundantly invoking the Skill tool when running slash commands directly
- Fixed skill token estimates in `/context` to accurately reflect frontmatter-only loading
- Fixed subagents sometimes not inheriting the parent’s model by default
- Fixed model picker showing incorrect selection for Bedrock/Vertex users using `--model haiku`
- Fixed duplicate Bash commands appearing in permission request option labels
- Fixed noisy output when background tasks complete - now shows clean completion message instead of raw output
- Fixed background task completion notifications to appear proactively with bullet point
- Fixed forked slash commands showing “AbortError” instead of “Interrupted” message when cancelled
- Fixed cursor disappearing after dismissing permission dialogs
- Fixed `/hooks` menu selecting wrong hook type when scrolling to a different option
- Fixed images in queued prompts showing as “\[object Object\]” when pressing Esc to cancel
- Fixed images being silently dropped when queueing messages while backgrounding a task
- Fixed large pasted images failing with “Image was too large” error
- Fixed extra blank lines in multiline prompts containing CJK characters (Japanese, Chinese, Korean)
- Fixed ultrathink keyword highlighting being applied to wrong characters when user prompt text wraps to multiple lines
- Fixed collapsed “Reading X files…” indicator incorrectly switching to past tense when thinking blocks appear mid-stream
- Fixed Bash read commands (like `ls` and `cat`) not being counted in collapsed read/search groups, causing groups to incorrectly show “Read 0 files”
- Fixed spinner token counter to properly accumulate tokens from subagents during execution
- Fixed memory leak in git diff parsing where sliced strings retained large parent strings
- Fixed race condition where LSP tool could return “no server available” during startup
- Fixed feedback submission hanging indefinitely when network requests timeout
- Fixed search mode in plugin discovery and log selector views exiting when pressing up arrow
- Fixed hook success message showing trailing colon when hook has no output
- Multiple optimizations to improve startup performance
- Improved terminal rendering performance when using native installer or Bun, especially for text with emoji, ANSI codes, and Unicode characters
- Improved performance when reading Jupyter notebooks with many cells
- Improved reliability for piped input like `cat refactor.md | claude`
- Improved reliability for AskQuestion tool
- Improved sed in-place edit commands to render as file edits with diff preview
- Improved Claude to automatically continue when response is cut off due to output token limit, instead of showing an error message
- Improved compaction reliability
- Improved subagents (Task tool) to continue working after permission denial, allowing them to try alternative approaches
- Improved skills to show progress while executing, displaying tool uses as they happen
- Improved skills from `/skills/` directories to be visible in the slash command menu by default (opt-out with `user-invocable: false` in frontmatter)
- Improved skill suggestions to prioritize recently and frequently used skills
- Improved spinner feedback when waiting for the first response token
- Improved token count display in spinner to include tokens from background agents
- Improved incremental output for async agents to give the main thread more control and visibility
- Improved permission prompt UX with Tab hint moved to footer, cleaner Yes/No input labels with contextual placeholders
- Improved the Claude in Chrome notification with shortened help text and persistent display until dismissed
- Improved macOS screenshot paste reliability with TIFF format support
- Improved `/stats` output
- Updated Atlassian MCP integration to use a more reliable default configuration (streamable HTTP)
- Changed “Interrupted” message color from red to grey for a less alarming appearance
- Removed permission prompt when entering plan mode - users can now enter plan mode without approval
- Removed underline styling from image reference links
- \[SDK\] Changed minimum zod peer dependency to ^4.0.0
- \[VSCode\] Added currently selected model name to the context menu
- \[VSCode\] Added descriptive labels on auto-accept permission button (e.g., “Yes, allow npm for this project” instead of “Yes, and don’t ask again”)
- \[VSCode\] Fixed paragraph breaks not rendering in markdown content
- \[VSCode\] Fixed scrolling in the extension inadvertently scrolling the parent iframe
- \[Windows\] Fixed issue with improper rendering
[](#2-0-76)
2.0.76
January 7, 2026
- Fixed issue with macOS code-sign warning when using Claude in Chrome integration
[](#2-0-75)
2.0.75
January 7, 2026
- Minor bugfixes
[](#2-0-74)
2.0.74
December 19, 2025
- Added LSP (Language Server Protocol) tool for code intelligence features like go-to-definition, find references, and hover documentation
- Added `/terminal-setup` support for Kitty, Alacritty, Zed, and Warp terminals
- Added ctrl+t shortcut in `/theme` to toggle syntax highlighting on/off
- Added syntax highlighting info to theme picker
- Added guidance for macOS users when Alt shortcuts fail due to terminal configuration
- Fixed skill `allowed-tools` not being applied to tools invoked by the skill
- Fixed Opus 4.5 tip incorrectly showing when user was already using Opus
- Fixed a potential crash when syntax highlighting isn’t initialized correctly
- Fixed visual bug in `/plugins discover` where list selection indicator showed while search box was focused
- Fixed macOS keyboard shortcuts to display ‘opt’ instead of ‘alt’
- Improved `/context` command visualization with grouped skills and agents by source, slash commands, and sorted token count
- \[Windows\] Fixed issue with improper rendering
- \[VSCode\] Added gift tag pictogram for year-end promotion message
[](#2-0-73)
2.0.73
December 19, 2025
- Added clickable `[Image #N]` links that open attached images in the default viewer
- Added alt-y yank-pop to cycle through kill ring history after ctrl-y yank
- Added search filtering to the plugin discover screen (type to filter by name, description, or marketplace)
- Added support for custom session IDs when forking sessions with `--session-id` combined with `--resume` or `--continue` and `--fork-session`
- Fixed slow input history cycling and race condition that could overwrite text after message submission
- Improved `/theme` command to open theme picker directly
- Improved theme picker UI
- Improved search UX across resume session, permissions, and plugins screens with a unified SearchBox component
- \[VSCode\] Added tab icon badges showing pending permissions (blue) and unread completions (orange)
[](#2-0-72)
2.0.72
December 17, 2025
- Added Claude in Chrome (Beta) feature that works with the Chrome extension ([https://claude.ai/chrome](https://claude.ai/chrome)) to let you control your browser directly from Claude Code
- Reduced terminal flickering
- Added scannable QR code to mobile app tip for quick app downloads
- Added loading indicator when resuming conversations for better feedback
- Fixed `/context` command not respecting custom system prompts in non-interactive mode
- Fixed order of consecutive Ctrl+K lines when pasting with Ctrl+Y
- Improved @ mention file suggestion speed (~3× faster in git repositories)
- Improved file suggestion performance in repos with `.ignore` or `.rgignore` files
- Improved settings validation errors to be more prominent
- Changed thinking toggle from Tab to Alt+T to avoid accidental triggers
[](#2-0-71)
2.0.71
December 16, 2025
- Added /config toggle to enable/disable prompt suggestions
- Added `/settings` as an alias for the `/config` command
- Fixed @ file reference suggestions incorrectly triggering when cursor is in the middle of a path
- Fixed MCP servers from `.mcp.json` not loading when using `--dangerously-skip-permissions`
- Fixed permission rules incorrectly rejecting valid bash commands containing shell glob patterns (e.g., `ls *.txt`, `for f in *.png`)
- Bedrock: Environment variable `ANTHROPIC_BEDROCK_BASE_URL` is now respected for token counting and inference profile listing
- New syntax highlighting engine for native build
[](#2-0-70)
2.0.70
December 15, 2025
- Added Enter key to accept and submit prompt suggestions immediately (tab still accepts for editing)
- Added wildcard syntax `mcp__server__*` for MCP tool permissions to allow or deny all tools from a server
- Added auto-update toggle for plugin marketplaces, allowing per-marketplace control over automatic updates
- Added `current_usage` field to status line input, enabling accurate context window percentage calculations
- Fixed input being cleared when processing queued commands while the user was typing
- Fixed prompt suggestions replacing typed input when pressing Tab
- Fixed diff view not updating when terminal is resized
- Improved memory usage by 3x for large conversations
- Improved resolution of stats screenshots copied to clipboard (Ctrl+S) for crisper images
- Removed \# shortcut for quick memory entry (tell Claude to edit your CLAUDE.md instead)
- Fix thinking mode toggle in /config not persisting correctly
- Improve UI for file creation permission dialog
[](#2-0-69)
2.0.69
December 13, 2025
- Minor bugfixes
[](#2-0-68)
2.0.68
December 12, 2025
- Fixed IME (Input Method Editor) support for languages like Chinese, Japanese, and Korean by correctly positioning the composition window at the cursor
- Fixed a bug where disallowed MCP tools were visible to the model
- Fixed an issue where steering messages could be lost while a subagent is working
- Fixed Option+Arrow word navigation treating entire CJK (Chinese, Japanese, Korean) text sequences as a single word instead of navigating by word boundaries
- Improved plan mode exit UX: show simplified yes/no dialog when exiting with empty or missing plan instead of throwing an error
- Add support for enterprise managed settings. Contact your Anthropic account team to enable this feature.
[](#2-0-67)
2.0.67
December 12, 2025
- Thinking mode is now enabled by default for Opus 4.5
- Thinking mode configuration has moved to /config
- Added search functionality to `/permissions` command with `/` keyboard shortcut for filtering rules by tool name
- Show reason why autoupdater is disabled in `/doctor`
- Fixed false “Another process is currently updating Claude” error when running `claude update` while another instance is already on the latest version
- Fixed MCP servers from `.mcp.json` being stuck in pending state when running in non-interactive mode (`-p` flag or piped input)
- Fixed scroll position resetting after deleting a permission rule in `/permissions`
- Fixed word deletion (opt+delete) and word navigation (opt+arrow) not working correctly with non-Latin text such as Cyrillic, Greek, Arabic, Hebrew, Thai, and Chinese
- Fixed `claude install --force` not bypassing stale lock files
- Fixed consecutive @~/ file references in CLAUDE.md being incorrectly parsed due to markdown strikethrough interference
- Windows: Fixed plugin MCP servers failing due to colons in log directory paths
[](#2-0-65)
2.0.65
December 11, 2025
- Added ability to switch models while writing a prompt using alt+p (linux, windows), option+p (macos).
- Added context window information to status line input
- Added `fileSuggestion` setting for custom `@` file search commands
- Added `CLAUDE_CODE_SHELL` environment variable to override automatic shell detection (useful when login shell differs from actual working shell)
- Fixed prompt not being saved to history when aborting a query with Escape
- Fixed Read tool image handling to identify format from bytes instead of file extension
[](#2-0-64)
2.0.64
December 10, 2025
- Made auto-compacting instant
- Agents and bash commands can run asynchronously and send messages to wake up the main agent
- /stats now provides users with interesting CC stats, such as favorite model, usage graph, usage streak
- Added named session support: use `/rename` to name sessions, `/resume <name>` in REPL or `claude --resume <name>` from the terminal to resume them
- Added support for .claude/rules/\`. See [https://code.claude.com/docs/en/memory](memory.md) for details.
- Added image dimension metadata when images are resized, enabling accurate coordinate mappings for large images
- Fixed auto-loading .env when using native installer
- Fixed `--system-prompt` being ignored when using `--continue` or `--resume` flags
- Improved `/resume` screen with grouped forked sessions and keyboard shortcuts for preview (P) and rename (R)
- VSCode: Added copy-to-clipboard button on code blocks and bash tool inputs
- VSCode: Fixed extension not working on Windows ARM64 by falling back to x64 binary via emulation
- Bedrock: Improve efficiency of token counting
- Bedrock: Add support for `aws login` AWS Management Console credentials
- Unshipped AgentOutputTool and BashOutputTool, in favor of a new unified TaskOutputTool
[](#2-0-62)
2.0.62
December 9, 2025
- Added “(Recommended)” indicator for multiple-choice questions, with the recommended option moved to the top of the list
- Added `attribution` setting to customize commit and PR bylines (deprecates `includeCoAuthoredBy`)
- Fixed duplicate slash commands appearing when ~/.claude is symlinked to a project directory
- Fixed slash command selection not working when multiple commands share the same name
- Fixed an issue where skill files inside symlinked skill directories could become circular symlinks
- Fixed running versions getting removed because lock file incorrectly going stale
- Fixed IDE diff tab not closing when rejecting file changes
[](#2-0-61)
2.0.61
December 7, 2025
- Reverted VSCode support for multiple terminal clients due to responsiveness issues.
[](#2-0-60)
2.0.60
December 6, 2025
- Added background agent support. Agents run in the background while you work
- Added —disable-slash-commands CLI flag to disable all slash commands
- Added model name to “Co-Authored-By” commit messages
- Enabled “/mcp enable \[server-name\]” or “/mcp disable \[server-name\]” to quickly toggle all servers
- Updated Fetch to skip summarization for pre-approved websites
- VSCode: Added support for multiple terminal clients connecting to the IDE server simultaneously
[](#2-0-59)
2.0.59
December 4, 2025
- Added —agent CLI flag to override the agent setting for the current session
- Added `agent` setting to configure main thread with a specific agent’s system prompt, tool restrictions, and model
- VS Code: Fixed .claude.json config file being read from incorrect location
[](#2-0-58)
2.0.58
December 3, 2025
- Pro users now have access to Opus 4.5 as part of their subscription!
- Fixed timer duration showing “11m 60s” instead of “12m 0s”
- Windows: Managed settings now prefer `C:\Program Files\ClaudeCode` if it exists. Support for `C:\ProgramData\ClaudeCode` will be removed in a future version.
[](#2-0-57)
2.0.57
December 3, 2025
- Added feedback input when rejecting plans, allowing users to tell Claude what to change
- VSCode: Added streaming message support for real-time response display
[](#2-0-56)
2.0.56
December 2, 2025
- Added setting to enable/disable terminal progress bar (OSC 9;4)
- VSCode Extension: Added support for VS Code’s secondary sidebar (VS Code 1.97+), allowing Claude Code to be displayed in the right sidebar while keeping the file explorer on the left. Requires setting sidebar as Preferred Location in the config.
[](#2-0-55)
2.0.55
November 26, 2025
- Fixed proxy DNS resolution being forced on by default. Now opt-in via `CLAUDE_CODE_PROXY_RESOLVES_HOSTS=true` environment variable
- Fixed keyboard navigation becoming unresponsive when holding down arrow keys in memory location selector
- Improved AskUserQuestion tool to auto-submit single-select questions on the last question, eliminating the extra review screen for simple question flows
- Improved fuzzy matching for `@` file suggestions with faster, more accurate results
[](#2-0-54)
2.0.54
November 26, 2025
- Hooks: Enable PermissionRequest hooks to process ‘always allow’ suggestions and apply permission updates
- Fix issue with excessive iTerm notifications
[](#2-0-52)
2.0.52
November 24, 2025
- Fixed duplicate message display when starting Claude with a command line argument
- Fixed `/usage` command progress bars to fill up as usage increases (instead of showing remaining percentage)
- Fixed image pasting not working on Linux systems running Wayland (now falls back to wl-paste when xclip is unavailable)
- Permit some uses of `$!` in bash commands
[](#2-0-51)
2.0.51
November 24, 2025
- Added Opus 4.5! [https://www.anthropic.com/news/claude-opus-4-5](../19-Reference/claude-opus-4-5.md)
- Introducing Claude Code for Desktop: [https://claude.com/download](https://claude.com/download)
- To give you room to try out our new model, we’ve updated usage limits for Claude Code users. See the Claude Opus 4.5 blog for full details
- Pro users can now purchase extra usage for access to Opus 4.5 in Claude Code
- Plan Mode now builds more precise plans and executes more thoroughly
- Usage limit notifications now easier to understand
- Switched `/usage` back to ”% used”
- Fixed handling of thinking errors
- Fixed performance regression
[](#2-0-50)
2.0.50
November 21, 2025
- Fixed bug preventing calling MCP tools that have nested references in their input schemas
- Silenced a noisy but harmless error during upgrades
- Improved ultrathink text display
- Improved clarity of 5-hour session limit warning message
[](#2-0-49)
2.0.49
November 21, 2025
- Added readline-style ctrl-y for pasting deleted text
- Improved clarity of usage limit warning message
- Fixed handling of subagent permissions
[](#2-0-47)
2.0.47
November 19, 2025
- Improved error messages and validation for `claude --teleport`
- Improved error handling in `/usage`
- Fixed race condition with history entry not getting logged at exit
- Fixed Vertex AI configuration not being applied from `settings.json`
[](#2-0-46)
2.0.46
November 19, 2025
- Fixed image files being reported with incorrect media type when format cannot be detected from metadata
[](#2-0-45)
2.0.45
November 18, 2025
- Added support for Microsoft Foundry! See [https://code.claude.com/docs/en/azure-ai-foundry](https://code.claude.com/docs/en/azure-ai-foundry)
- Added `PermissionRequest` hook to automatically approve or deny tool permission requests with custom logic
- Send background tasks to Claude Code on the web by starting a message with `&`
[](#2-0-43)
2.0.43
November 18, 2025
- Added `permissionMode` field for custom agents
- Added `tool_use_id` field to `PreToolUseHookInput` and `PostToolUseHookInput` types
- Added skills frontmatter field to declare skills to auto-load for subagents
- Added the `SubagentStart` hook event
- Fixed nested `CLAUDE.md` files not loading when @-mentioning files
- Fixed duplicate rendering of some messages in the UI
- Fixed some visual flickers
- Fixed NotebookEdit tool inserting cells at incorrect positions when cell IDs matched the pattern `cell-N`
[](#2-0-42)
2.0.42
November 15, 2025
- Added `agent_id` and `agent_transcript_path` fields to `SubagentStop` hooks.
[](#2-0-41)
2.0.41
November 14, 2025
- Added `model` parameter to prompt-based stop hooks, allowing users to specify a custom model for hook evaluation
- Fixed slash commands from user settings being loaded twice, which could cause rendering issues
- Fixed incorrect labeling of user settings vs project settings in command descriptions
- Fixed crash when plugin command hooks timeout during execution
- Fixed: Bedrock users no longer see duplicate Opus entries in the /model picker when using `--model haiku`
- Fixed broken security documentation links in trust dialogs and onboarding
- Fixed issue where pressing ESC to close the diff modal would also interrupt the model
- ctrl-r history search landing on a slash command no longer cancels the search
- SDK: Support custom timeouts for hooks
- Allow more safe git commands to run without approval
- Plugins: Added support for sharing and installing output styles
- Teleporting a session from web will automatically set the upstream branch
[](#2-0-37)
2.0.37
November 11, 2025
- Fixed how idleness is computed for notifications
- Hooks: Added matcher values for Notification hook events
- Output Styles: Added `keep-coding-instructions` option to frontmatter
[](#2-0-36)
2.0.36
November 7, 2025
- Fixed: DISABLE_AUTOUPDATER environment variable now properly disables package manager update notifications
- Fixed queued messages being incorrectly executed as bash commands
- Fixed input being lost when typing while a queued message is processed
[](#2-0-35)
2.0.35
November 6, 2025
- Improve fuzzy search results when searching commands
- Improved VS Code extension to respect `chat.fontSize` and `chat.fontFamily` settings throughout the entire UI, and apply font changes immediately without requiring reload
- Added `CLAUDE_CODE_EXIT_AFTER_STOP_DELAY` environment variable to automatically exit SDK mode after a specified idle duration, useful for automated workflows and scripts
- Migrated `ignorePatterns` from project config to deny permissions in the localSettings.
- Fixed menu navigation getting stuck on items with empty string or other falsy values (e.g., in the `/hooks` menu)
[](#2-0-34)
2.0.34
November 5, 2025
- VSCode Extension: Added setting to configure the initial permission mode for new conversations
- Improved file path suggestion performance with native Rust-based fuzzy finder
- Fixed infinite token refresh loop that caused MCP servers with OAuth (e.g., Slack) to hang during connection
- Fixed memory crash when reading or writing large files (especially base64-encoded images)
[](#2-0-33)
2.0.33
November 4, 2025
- Native binary installs now launch quicker.
- Fixed `claude doctor` incorrectly detecting Homebrew vs npm-global installations by properly resolving symlinks
- Fixed `claude mcp serve` exposing tools with incompatible outputSchemas
[](#2-0-32)
2.0.32
November 4, 2025
- Un-deprecate output styles based on community feedback
- Added `companyAnnouncements` setting for displaying announcements on startup
- Fixed hook progress messages not updating correctly during PostToolUse hook execution
[](#2-0-31)
2.0.31
October 31, 2025
- Windows: native installation uses shift+tab as shortcut for mode switching, instead of alt+m
- Vertex: add support for Web Search on supported models
- VSCode: Adding the respectGitIgnore configuration to include .gitignored files in file searches (defaults to true)
- Fixed a bug with subagents and MCP servers related to “Tool names must be unique” error
- Fixed issue causing `/compact` to fail with `prompt_too_long` by making it respect existing compact boundaries
- Fixed plugin uninstall not removing plugins
[](#2-0-30)
2.0.30
October 30, 2025
- Added helpful hint to run `security unlock-keychain` when encountering API key errors on macOS with locked keychain
- Added `allowUnsandboxedCommands` sandbox setting to disable the dangerouslyDisableSandbox escape hatch at policy level
- Added `disallowedTools` field to custom agent definitions for explicit tool blocking
- Added prompt-based stop hooks
- VSCode: Added respectGitIgnore configuration to include .gitignored files in file searches (defaults to true)
- Enabled SSE MCP servers on native build
- Deprecated output styles. Review options in `/output-style` and use —system-prompt-file, —system-prompt, —append-system-prompt, CLAUDE.md, or plugins instead
- Removed support for custom ripgrep configuration, resolving an issue where Search returns no results and config discovery fails
- Fixed Explore agent creating unwanted .md investigation files during codebase exploration
- Fixed a bug where `/context` would sometimes fail with “max_tokens must be greater than thinking.budget_tokens” error message
- Fixed `--mcp-config` flag to correctly override file-based MCP configurations
- Fixed bug that saved session permissions to local settings
- Fixed MCP tools not being available to sub-agents
- Fixed hooks and plugins not executing when using —dangerously-skip-permissions flag
- Fixed delay when navigating through typeahead suggestions with arrow keys
- VSCode: Restored selection indicator in input footer showing current file or code selection status
[](#2-0-28)
2.0.28
October 27, 2025
- Plan mode: introduced new Plan subagent
- Subagents: claude can now choose to resume subagents
- Subagents: claude can dynamically choose the model used by its subagents
- SDK: added —max-budget-usd flag
- Discovery of custom slash commands, subagents, and output styles no longer respects .gitignore
- Stop `/terminal-setup` from adding backslash to `Shift + Enter` in VS Code
- Add branch and tag support for git-based plugins and marketplaces using fragment syntax (e.g., `owner/repo#branch`)
- Fixed a bug where macOS permission prompts would show up upon initial launch when launching from home directory
- Various other bug fixes
[](#2-0-27)
2.0.27
October 24, 2025
- New UI for permission prompts
- Added current branch filtering and search to session resume screen for easier navigation
- Fixed directory @-mention causing “No assistant message found” error
- VSCode Extension: Add config setting to include .gitignored files in file searches
- VSCode Extension: Bug fixes for unrelated ‘Warmup’ conversations, and configuration/settings occasionally being reset to defaults
[](#2-0-25)
2.0.25
October 21, 2025
- Removed legacy SDK entrypoint. Please migrate to @anthropic-ai/claude-agent-sdk for future SDK updates: [https://platform.claude.com/docs/en/agent-sdk/migration-guide](../05-Agent-SDK/agent-sdk-migration-guide.md)
[](#2-0-24)
2.0.24
October 20, 2025
- Fixed a bug where project-level skills were not loading when —setting-sources ‘project’ was specified
- Claude Code Web: Support for Web -\> CLI teleport
- Sandbox: Releasing a sandbox mode for the BashTool on Linux & Mac
- Bedrock: Display awsAuthRefresh output when auth is required
[](#2-0-22)
2.0.22
October 17, 2025
- Fixed content layout shift when scrolling through slash commands
- IDE: Add toggle to enable/disable thinking.
- Fix bug causing duplicate permission prompts with parallel tool calls
- Add support for enterprise managed MCP allowlist and denylist
[](#2-0-21)
2.0.21
October 18, 2025
- Support MCP `structuredContent` field in tool responses
- Added an interactive question tool
- Claude will now ask you questions more often in plan mode
- Added Haiku 4.5 as a model option for Pro users
- Fixed an issue where queued commands don’t have access to previous messages’ output
[](#2-0-20)
2.0.20
October 16, 2025
- Added support for Claude Skills
[](#2-0-19)
2.0.19
October 15, 2025
- Auto-background long-running bash commands instead of killing them. Customize with BASH_DEFAULT_TIMEOUT_MS
- Fixed a bug where Haiku was unnecessarily called in print mode
[](#2-0-17)
2.0.17
October 15, 2025
- Added Haiku 4.5 to model selector!
- Haiku 4.5 automatically uses Sonnet in plan mode, and Haiku for execution (i.e. SonnetPlan by default)
- 3P (Bedrock and Vertex) are not automatically upgraded yet. Manual upgrading can be done through setting `ANTHROPIC_DEFAULT_HAIKU_MODEL`
- Introducing the Explore subagent. Powered by Haiku it’ll search through your codebase efficiently to save context!
- OTEL: support HTTP_PROXY and HTTPS_PROXY
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` now disables release notes fetching
[](#2-0-15)
2.0.15
October 14, 2025
- Fixed bug with resuming where previously created files needed to be read again before writing
- Fixed bug with `-p` mode where @-mentioned files needed to be read again before writing
[](#2-0-14)
2.0.14
October 10, 2025
- Fix @-mentioning MCP servers to toggle them on/off
- Improve permission checks for bash with inline env vars
- Fix ultrathink + thinking toggle
- Reduce unnecessary logins
- Document —system-prompt
- Several improvements to rendering
- Plugins UI polish
[](#2-0-13)
2.0.13
October 9, 2025
- Fixed `/plugin` not working on native build
[](#2-0-12)
2.0.12
October 9, 2025
- **Plugin System Released**: Extend Claude Code with custom commands, agents, hooks, and MCP servers from marketplaces
- `/plugin install`, `/plugin enable/disable`, `/plugin marketplace` commands for plugin management
- Repository-level plugin configuration via `extraKnownMarketplaces` for team collaboration
- `/plugin validate` command for validating plugin structure and configuration
- Plugin announcement blog post at [https://www.anthropic.com/news/claude-code-plugins](https://www.anthropic.com/news/claude-code-plugins)
- Plugin documentation available at [https://code.claude.com/docs/en/plugins](../08-Plugins-Skills/plugins.md)
- Comprehensive error messages and diagnostics via `/doctor` command
- Avoid flickering in `/model` selector
- Improvements to `/help`
- Avoid mentioning hooks in `/resume` summaries
- Changes to the “verbose” setting in `/config` now persist across sessions
[](#2-0-11)
2.0.11
October 8, 2025
- Reduced system prompt size by 1.4k tokens
- IDE: Fixed keyboard shortcuts and focus issues for smoother interaction
- Fixed Opus fallback rate limit errors appearing incorrectly
- Fixed /add-dir command selecting wrong default tab
[](#2-0-10)
2.0.10
October 8, 2025
- Rewrote terminal renderer for buttery smooth UI
- Enable/disable MCP servers by @mentioning, or in /mcp
- Added tab completion for shell commands in bash mode
- PreToolUse hooks can now modify tool inputs
- Press Ctrl-G to edit your prompt in your system’s configured text editor
- Fixes for bash permission checks with environment variables in the command
[](#2-0-9)
2.0.9
October 6, 2025
- Fix regression where bash backgrounding stopped working
[](#2-0-8)
2.0.8
October 4, 2025
- Update Bedrock default Sonnet model to `global.anthropic.claude-sonnet-4-5-20250929-v1:0`
- IDE: Add drag-and-drop support for files and folders in chat
- /context: Fix counting for thinking blocks
- Improve message rendering for users with light themes on dark terminals
- Remove deprecated .claude.json allowedTools, ignorePatterns, env, and todoFeatureEnabled config options (instead, configure these in your settings.json)
[](#2-0-5)
2.0.5
October 4, 2025
- IDE: Fix IME unintended message submission with Enter and Tab
- IDE: Add “Open in Terminal” link in login screen
- Fix unhandled OAuth expiration 401 API errors
- SDK: Added SDKUserMessageReplay.isReplay to prevent duplicate messages
[](#2-0-1)
2.0.1
September 30, 2025
- Skip Sonnet 4.5 default model setting change for Bedrock and Vertex
- Various bug fixes and presentation improvements
[](#2-0-0)
2.0.0
September 29, 2025
- New native VS Code extension
- Fresh coat of paint throughout the whole app
- /rewind a conversation to undo code changes
- /usage command to see plan limits
- Tab to toggle thinking (sticky across sessions)
- Ctrl-R to search history
- Unshipped claude config command
- Hooks: Reduced PostToolUse ‘tool_use’ ids were found without ‘tool_result’ blocks errors
- SDK: The Claude Code SDK is now the Claude Agent SDK
- Add subagents dynamically with `--agents` flag
[](#1-0-126)
1.0.126
September 26, 2025
- Enable /context command for Bedrock and Vertex
- Add mTLS support for HTTP-based OpenTelemetry exporters
[](#1-0-124)
1.0.124
September 25, 2025
- Set `CLAUDE_BASH_NO_LOGIN` environment variable to 1 or true to to skip login shell for BashTool
- Fix Bedrock and Vertex environment variables evaluating all strings as truthy
- No longer inform Claude of the list of allowed tools when permission is denied
- Fixed security vulnerability in Bash tool permission checks
- Improved VSCode extension performance for large files
[](#1-0-123)
1.0.123
September 23, 2025
- Bash permission rules now support output redirections when matching (e.g., `Bash(python:*)` matches `python script.py > output.txt`)
- Fixed thinking mode triggering on negation phrases like “don’t think”
- Fixed rendering performance degradation during token streaming
- Added SlashCommand tool, which enables Claude to invoke your slash commands. [https://code.claude.com/docs/en/slash-commands#SlashCommand-tool](https://code.claude.com/docs/en/slash-commands#SlashCommand-tool)
- Enhanced BashTool environment snapshot logging
- Fixed a bug where resuming a conversation in headless mode would sometimes enable thinking unnecessarily
- Migrated —debug logging to a file, to enable easy tailing & filtering
[](#1-0-120)
1.0.120
September 19, 2025
- Fix input lag during typing, especially noticeable with large prompts
- Improved VSCode extension command registry and sessions dialog user experience
- Enhanced sessions dialog responsiveness and visual feedback
- Fixed IDE compatibility issue by removing worktree support check
- Fixed security vulnerability where Bash tool permission checks could be bypassed using prefix matching
[](#1-0-119)
1.0.119
September 19, 2025
- Fix Windows issue where process visually freezes on entering interactive mode
- Support dynamic headers for MCP servers via headersHelper configuration
- Fix thinking mode not working in headless sessions
- Fix slash commands now properly update allowed tools instead of replacing them
[](#1-0-117)
1.0.117
September 19, 2025
- Add Ctrl-R history search to recall previous commands like bash/zsh
- Fix input lag while typing, especially on Windows
- Add sed command to auto-allowed commands in acceptEdits mode
- Fix Windows PATH comparison to be case-insensitive for drive letters
- Add permissions management hint to /add-dir output
[](#1-0-115)
1.0.115
September 16, 2025
- Improve thinking mode display with enhanced visual effects
- Type /t to temporarily disable thinking mode in your prompt
- Improve path validation for glob and grep tools
- Show condensed output for post-tool hooks to reduce visual clutter
- Fix visual feedback when loading state completes
- Improve UI consistency for permission request dialogs
[](#1-0-113)
1.0.113
September 13, 2025
- Deprecated piped input in interactive mode
- Move Ctrl+R keybinding for toggling transcript to Ctrl+O
[](#1-0-112)
1.0.112
September 12, 2025
- Transcript mode (Ctrl+R): Added the model used to generate each assistant message
- Addressed issue where some Claude Max users were incorrectly recognized as Claude Pro users
- Hooks: Added systemMessage support for SessionEnd hooks
- Added `spinnerTipsEnabled` setting to disable spinner tips
- IDE: Various improvements and bug fixes
[](#1-0-111)
1.0.111
September 10, 2025
- /model now validates provided model names
- Fixed Bash tool crashes caused by malformed shell syntax parsing
[](#1-0-110)
1.0.110
September 10, 2025
- /terminal-setup command now supports WezTerm
- MCP: OAuth tokens now proactively refresh before expiration
- Fixed reliability issues with background Bash processes
[](#1-0-109)
1.0.109
September 9, 2025
- SDK: Added partial message streaming support via `--include-partial-messages` CLI flag
[](#1-0-106)
1.0.106
September 5, 2025
- Windows: Fixed path permission matching to consistently use POSIX format (e.g., `Read(//c/Users/...)`)
[](#1-0-97)
1.0.97
August 29, 2025
- Settings: /doctor now validates permission rule syntax and suggests corrections
[](#1-0-94)
1.0.94
August 27, 2025
- Vertex: add support for global endpoints for supported models
- /memory command now allows direct editing of all imported memory files
- SDK: Add custom tools as callbacks
- Added /todos command to list current todo items
[](#1-0-93)
1.0.93
August 26, 2025
- Windows: Add alt + v shortcut for pasting images from clipboard
- Support NO_PROXY environment variable to bypass proxy for specified hostnames and IPs
[](#1-0-90)
1.0.90
August 25, 2025
- Settings file changes take effect immediately - no restart required
[](#1-0-88)
1.0.88
August 22, 2025
- Fixed issue causing “OAuth authentication is currently not supported”
- Status line input now includes `exceeds_200k_tokens`
- Fixed incorrect usage tracking in /cost.
- Introduced `ANTHROPIC_DEFAULT_SONNET_MODEL` and `ANTHROPIC_DEFAULT_OPUS_MODEL` for controlling model aliases opusplan, opus, and sonnet.
- Bedrock: Updated default Sonnet model to Sonnet 4
[](#1-0-86)
1.0.86
August 22, 2025
- Added /context to help users self-serve debug context issues
- SDK: Added UUID support for all SDK messages
- SDK: Added `--replay-user-messages` to replay user messages back to stdout
[](#1-0-85)
1.0.85
August 19, 2025
- Status line input now includes session cost info
- Hooks: Introduced SessionEnd hook
[](#1-0-84)
1.0.84
August 18, 2025
- Fix tool_use/tool_result id mismatch error when network is unstable
- Fix Claude sometimes ignoring real-time steering when wrapping up a task
- @-mention: Add ~/.claude/\* files to suggestions for easier agent, output style, and slash command editing
- Use built-in ripgrep by default; to opt out of this behavior, set USE_BUILTIN_RIPGREP=0
[](#1-0-83)
1.0.83
August 18, 2025
- @-mention: Support files with spaces in path
- New shimmering spinner
[](#1-0-82)
1.0.82
August 16, 2025
- SDK: Add request cancellation support
- SDK: New additionalDirectories option to search custom paths, improved slash command processing
- Settings: Validation prevents invalid fields in .claude/settings.json files
- MCP: Improve tool name consistency
- Bash: Fix crash when Claude tries to automatically read large files
[](#1-0-81)
1.0.81
August 14, 2025
- Released output styles, including new built-in educational output styles “Explanatory” and “Learning”. Docs: [https://code.claude.com/docs/en/output-styles](output-styles.md)
- Agents: Fix custom agent loading when agent files are unparsable
[](#1-0-80)
1.0.80
August 14, 2025
- UI improvements: Fix text contrast for custom subagent colors and spinner rendering issues
[](#1-0-77)
1.0.77
August 14, 2025
- Bash tool: Fix heredoc and multiline string escaping, improve stderr redirection handling
- SDK: Add session support and permission denial tracking
- Fix token limit errors in conversation summarization
- Opus Plan Mode: New setting in `/model` to run Opus only in plan mode, Sonnet otherwise
[](#1-0-73)
1.0.73
August 11, 2025
- MCP: Support multiple config files with `--mcp-config file1.json file2.json`
- MCP: Press Esc to cancel OAuth authentication flows
- Bash: Improved command validation and reduced false security warnings
- UI: Enhanced spinner animations and status line visual hierarchy
- Linux: Added support for Alpine and musl-based distributions (requires separate ripgrep installation)
[](#1-0-72)
1.0.72
August 11, 2025
- Ask permissions: have Claude Code always ask for confirmation to use specific tools with /permissions
[](#1-0-71)
1.0.71
August 7, 2025
- Background commands: (Ctrl-b) to run any Bash command in the background so Claude can keep working (great for dev servers, tailing logs, etc.)
- Customizable status line: add your terminal prompt to Claude Code with /statusline
[](#1-0-70)
1.0.70
August 7, 2025
- Performance: Optimized message rendering for better performance with large contexts
- Windows: Fixed native file search, ripgrep, and subagent functionality
- Added support for @-mentions in slash command arguments
[](#1-0-69)
1.0.69
August 5, 2025
- Upgraded Opus to version 4.1
[](#1-0-68)
1.0.68
August 4, 2025
- Fix incorrect model names being used for certain commands like `/pr-comments`
- Windows: improve permissions checks for allow / deny tools and project trust. This may create a new project entry in `.claude.json` - manually merge the history field if desired.
- Windows: improve sub-process spawning to eliminate “No such file or directory” when running commands like pnpm
- Enhanced /doctor command with CLAUDE.md and MCP tool context for self-serve debugging
- SDK: Added canUseTool callback support for tool confirmation
- Added `disableAllHooks` setting
- Improved file suggestions performance in large repos
[](#1-0-65)
1.0.65
July 31, 2025
- IDE: Fixed connection stability issues and error handling for diagnostics
- Windows: Fixed shell environment setup for users without .bashrc files
[](#1-0-64)
1.0.64
July 30, 2025
- Agents: Added model customization support - you can now specify which model an agent should use
- Agents: Fixed unintended access to the recursive agent tool
- Hooks: Added systemMessage field to hook JSON output for displaying warnings and context
- SDK: Fixed user input tracking across multi-turn conversations
- Added hidden files to file search and @-mention suggestions
[](#1-0-63)
1.0.63
July 29, 2025
- Windows: Fixed file search, @agent mentions, and custom slash commands functionality
[](#1-0-62)
1.0.62
July 28, 2025
- Added @-mention support with typeahead for custom agents. @`<your-custom-agent>` to invoke it
- Hooks: Added SessionStart hook for new session initialization
- /add-dir command now supports typeahead for directory paths
- Improved network connectivity check reliability
[](#1-0-61)
1.0.61
July 25, 2025
- Transcript mode (Ctrl+R): Changed Esc to exit transcript mode rather than interrupt
- Settings: Added `--settings` flag to load settings from a JSON file
- Settings: Fixed resolution of settings files paths that are symlinks
- OTEL: Fixed reporting of wrong organization after authentication changes
- Slash commands: Fixed permissions checking for allowed-tools with Bash
- IDE: Added support for pasting images in VSCode MacOS using ⌘+V
- IDE: Added `CLAUDE_CODE_AUTO_CONNECT_IDE=false` for disabling IDE auto-connection
- Added `CLAUDE_CODE_SHELL_PREFIX` for wrapping Claude and user-provided shell commands run by Claude Code
[](#1-0-60)
1.0.60
July 24, 2025
- You can now create custom subagents for specialized tasks! Run /agents to get started
[](#1-0-59)
1.0.59
July 23, 2025
- SDK: Added tool confirmation support with canUseTool callback
- SDK: Allow specifying env for spawned process
- Hooks: Exposed PermissionDecision to hooks (including “ask”)
- Hooks: UserPromptSubmit now supports additionalContext in advanced JSON output
- Fixed issue where some Max users that specified Opus would still see fallback to Sonnet
[](#1-0-58)
1.0.58
July 23, 2025
- Added support for reading PDFs
- MCP: Improved server health status display in ‘claude mcp list’
- Hooks: Added CLAUDE_PROJECT_DIR env var for hook commands
[](#1-0-57)
1.0.57
July 23, 2025
- Added support for specifying a model in slash commands
- Improved permission messages to help Claude understand allowed tools
- Fix: Remove trailing newlines from bash output in terminal wrapping
[](#1-0-56)
1.0.56
July 23, 2025
- Windows: Enabled shift+tab for mode switching on versions of Node.js that support terminal VT mode
- Fixes for WSL IDE detection
- Fix an issue causing awsRefreshHelper changes to .aws directory not to be picked up
[](#1-0-55)
1.0.55
July 23, 2025
- Clarified knowledge cutoff for Opus 4 and Sonnet 4 models
- Windows: fixed Ctrl+Z crash
- SDK: Added ability to capture error logging
- Add —system-prompt-file option to override system prompt in print mode
[](#1-0-54)
1.0.54
July 19, 2025
- Hooks: Added UserPromptSubmit hook and the current working directory to hook inputs
- Custom slash commands: Added argument-hint to frontmatter
- Windows: OAuth uses port 45454 and properly constructs browser URL
- Windows: mode switching now uses alt + m, and plan mode renders properly
- Shell: Switch to in-memory shell snapshot to fix file-related errors
[](#1-0-53)
1.0.53
July 18, 2025
- Updated @-mention file truncation from 100 lines to 2000 lines
- Add helper script settings for AWS token refresh: awsAuthRefresh (for foreground operations like aws sso login) and awsCredentialExport (for background operation with STS-like response).
[](#1-0-52)
1.0.52
July 18, 2025
- Added support for MCP server instructions
[](#1-0-51)
1.0.51
July 11, 2025
- Added support for native Windows (requires Git for Windows)
- Added support for Bedrock API keys through environment variable AWS_BEARER_TOKEN_BEDROCK
- Settings: /doctor can now help you identify and fix invalid setting files
- `--append-system-prompt` can now be used in interactive mode, not just —print/-p.
- Increased auto-compact warning threshold from 60% to 80%
- Fixed an issue with handling user directories with spaces for shell snapshots
- OTEL resource now includes os.type, os.version, host.arch, and wsl.version (if running on Windows Subsystem for Linux)
- Custom slash commands: Fixed user-level commands in subdirectories
- Plan mode: Fixed issue where rejected plan from sub-task would get discarded
[](#1-0-48)
1.0.48
July 10, 2025
- Fixed a bug in v1.0.45 where the app would sometimes freeze on launch
- Added progress messages to Bash tool based on the last 5 lines of command output
- Added expanding variables support for MCP server configuration
- Moved shell snapshots from /tmp to ~/.claude for more reliable Bash tool calls
- Improved IDE extension path handling when Claude Code runs in WSL
- Hooks: Added a PreCompact hook
- Vim mode: Added c, f/F, t/T
[](#1-0-45)
1.0.45
July 10, 2025
- Redesigned Search (Grep) tool with new tool input parameters and features
- Disabled IDE diffs for notebook files, fixing “Timeout waiting after 1000ms” error
- Fixed config file corruption issue by enforcing atomic writes
- Updated prompt input undo to Ctrl+\_ to avoid breaking existing Ctrl+U behavior, matching zsh’s undo shortcut
- Stop Hooks: Fixed transcript path after /clear and fixed triggering when loop ends with tool call
- Custom slash commands: Restored namespacing in command names based on subdirectories. For example, .claude/commands/frontend/component.md is now /frontend:component, not /component.
[](#1-0-44)
1.0.44
July 7, 2025
- New /export command lets you quickly export a conversation for sharing
- MCP: resource_link tool results are now supported
- MCP: tool annotations and tool titles now display in /mcp view
- Changed Ctrl+Z to suspend Claude Code. Resume by running `fg`. Prompt input undo is now Ctrl+U.
[](#1-0-43)
1.0.43
July 3, 2025
- Fixed a bug where the theme selector was saving excessively
- Hooks: Added EPIPE system error handling
[](#1-0-42)
1.0.42
July 3, 2025
- Added tilde (`~`) expansion support to `/add-dir` command
[](#1-0-41)
1.0.41
July 3, 2025
- Hooks: Split Stop hook triggering into Stop and SubagentStop
- Hooks: Enabled optional timeout configuration for each command
- Hooks: Added “hook_event_name” to hook input
- Fixed a bug where MCP tools would display twice in tool list
- New tool parameters JSON for Bash tool in `tool_decision` event
[](#1-0-40)
1.0.40
July 3, 2025
- Fixed a bug causing API connection errors with UNABLE_TO_GET_ISSUER_CERT_LOCALLY if `NODE_EXTRA_CA_CERTS` was set
[](#1-0-39)
1.0.39
July 3, 2025
- New Active Time metric in OpenTelemetry logging
[](#1-0-38)
1.0.38
June 30, 2025
- Released hooks. Special thanks to community input in [https://github.com/anthropics/claude-code/issues/712](https://github.com/anthropics/claude-code/issues/712). Docs: [https://code.claude.com/docs/en/hooks](../07-Hooks/hooks.md)
[](#1-0-37)
1.0.37
June 30, 2025
- Remove ability to set `Proxy-Authorization` header via ANTHROPIC_AUTH_TOKEN or apiKeyHelper
[](#1-0-36)
1.0.36
June 30, 2025
- Web search now takes today’s date into context
- Fixed a bug where stdio MCP servers were not terminating properly on exit
[](#1-0-35)
1.0.35
June 25, 2025
- Added support for MCP OAuth Authorization Server discovery
[](#1-0-34)
1.0.34
June 24, 2025
- Fixed a memory leak causing a MaxListenersExceededWarning message to appear
[](#1-0-33)
1.0.33
June 24, 2025
- Improved logging functionality with session ID support
- Added prompt input undo functionality (Ctrl+Z and vim ‘u’ command)
- Improvements to plan mode
[](#1-0-32)
1.0.32
June 24, 2025
- Updated loopback config for litellm
- Added forceLoginMethod setting to bypass login selection screen
[](#1-0-31)
1.0.31
June 24, 2025
- Fixed a bug where ~/.claude.json would get reset when file contained invalid JSON
[](#1-0-30)
1.0.30
June 24, 2025
- Custom slash commands: Run bash output, @-mention files, enable thinking with thinking keywords
- Improved file path autocomplete with filename matching
- Added timestamps in Ctrl-r mode and fixed Ctrl-c handling
- Enhanced jq regex support for complex filters with pipes and select
[](#1-0-29)
1.0.29
June 24, 2025
- Improved CJK character support in cursor navigation and rendering
[](#1-0-28)
1.0.28
June 24, 2025
- Slash commands: Fix selector display during history navigation
- Resizes images before upload to prevent API size limit errors
- Added XDG_CONFIG_HOME support to configuration directory
- Performance optimizations for memory usage
- New attributes (terminal.type, language) in OpenTelemetry logging
[](#1-0-27)
1.0.27
June 18, 2025
- Streamable HTTP MCP servers are now supported
- Remote MCP servers (SSE and HTTP) now support OAuth
- MCP resources can now be @-mentioned
- /resume slash command to switch conversations within Claude Code
[](#1-0-25)
1.0.25
June 16, 2025
- Slash commands: moved “project” and “user” prefixes to descriptions
- Slash commands: improved reliability for command discovery
- Improved support for Ghostty
- Improved web search reliability
[](#1-0-24)
1.0.24
June 16, 2025
- Improved /mcp output
- Fixed a bug where settings arrays got overwritten instead of merged
[](#1-0-23)
1.0.23
June 16, 2025
- Released TypeScript SDK: import @anthropic-ai/claude-code to get started
- Released Python SDK: pip install claude-code-sdk to get started
[](#1-0-22)
1.0.22
June 12, 2025
- SDK: Renamed `total_cost` to `total_cost_usd`
[](#1-0-21)
1.0.21
June 12, 2025
- Improved editing of files with tab-based indentation
- Fix for tool_use without matching tool_result errors
- Fixed a bug where stdio MCP server processes would linger after quitting Claude Code
[](#1-0-18)
1.0.18
June 9, 2025
- Added —add-dir CLI argument for specifying additional working directories
- Added streaming input support without require -p flag
- Improved startup performance and session storage performance
- Added CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR environment variable to freeze working directory for bash commands
- Added detailed MCP server tools display (/mcp)
- MCP authentication and permission improvements
- Added auto-reconnection for MCP SSE connections on disconnect
- Fixed issue where pasted content was lost when dialogs appeared
[](#1-0-17)
1.0.17
June 9, 2025
- We now emit messages from sub-tasks in -p mode (look for the parent_tool_use_id property)
- Fixed crashes when the VS Code diff tool is invoked multiple times quickly
- MCP server list UI improvements
- Update Claude Code process title to display “claude” instead of “node”
[](#1-0-11)
1.0.11
June 4, 2025
- Claude Code can now also be used with a Claude Pro subscription
- Added /upgrade for smoother switching to Claude Max plans
- Improved UI for authentication from API keys and Bedrock/Vertex/external auth tokens
- Improved shell configuration error handling
- Improved todo list handling during compaction
[](#1-0-10)
1.0.10
June 4, 2025
- Added markdown table support
- Improved streaming performance
[](#1-0-8)
1.0.8
June 2, 2025
- Fixed Vertex AI region fallback when using CLOUD_ML_REGION
- Increased default otel interval from 1s -\> 5s
- Fixed edge cases where MCP_TIMEOUT and MCP_TOOL_TIMEOUT weren’t being respected
- Fixed a regression where search tools unnecessarily asked for permissions
- Added support for triggering thinking non-English languages
- Improved compacting UI
[](#1-0-7)
1.0.7
June 2, 2025
- Renamed /allowed-tools -\> /permissions
- Migrated allowedTools and ignorePatterns from .claude.json -\> settings.json
- Deprecated claude config commands in favor of editing settings.json
- Fixed a bug where —dangerously-skip-permissions sometimes didn’t work in —print mode
- Improved error handling for /install-github-app
- Bugfixes, UI polish, and tool reliability improvements
[](#1-0-6)
1.0.6
June 2, 2025
- Improved edit reliability for tab-indented files
- Respect CLAUDE_CONFIG_DIR everywhere
- Reduced unnecessary tool permission prompts
- Added support for symlinks in @file typeahead
- Bugfixes, UI polish, and tool reliability improvements
[](#1-0-4)
1.0.4
May 28, 2025
- Fixed a bug where MCP tool errors weren’t being parsed correctly
[](#1-0-1)
1.0.1
May 22, 2025
- Added `DISABLE_INTERLEAVED_THINKING` to give users the option to opt out of interleaved thinking.
- Improved model references to show provider-specific names (Sonnet 3.7 for Bedrock, Sonnet 4 for Console)
- Updated documentation links and OAuth process descriptions
[](#1-0-0)
1.0.0
May 22, 2025
- Claude Code is now generally available
- Introducing Sonnet 4 and Opus 4 models
[](#0-2-125)
0.2.125
May 21, 2025
- Breaking change: Bedrock ARN passed to `ANTHROPIC_MODEL` or `ANTHROPIC_SMALL_FAST_MODEL` should no longer contain an escaped slash (specify `/` instead of `%2F`)
- Removed `DEBUG=true` in favor of `ANTHROPIC_LOG=debug`, to log all requests
[](#0-2-117)
0.2.117
May 17, 2025
- Breaking change: —print JSON output now returns nested message objects, for forwards-compatibility as we introduce new metadata fields
- Introduced settings.cleanupPeriodDays
- Introduced CLAUDE_CODE_API_KEY_HELPER_TTL_MS env var
- Introduced —debug mode
[](#0-2-108)
0.2.108
May 13, 2025
- You can now send messages to Claude while it works to steer Claude in real-time
- Introduced BASH_DEFAULT_TIMEOUT_MS and BASH_MAX_TIMEOUT_MS env vars
- Fixed a bug where thinking was not working in -p mode
- Fixed a regression in /cost reporting
- Deprecated MCP wizard interface in favor of other MCP commands
- Lots of other bugfixes and improvements
[](#0-2-107)
0.2.107
May 9, 2025
- CLAUDE.md files can now import other files. Add @path/to/file.md to ./CLAUDE.md to load additional files on launch
[](#0-2-106)
0.2.106
May 9, 2025
- MCP SSE server configs can now specify custom headers
- Fixed a bug where MCP permission prompt didn’t always show correctly
[](#0-2-105)
0.2.105
May 8, 2025
- Claude can now search the web
- Moved system & account status to /status
- Added word movement keybindings for Vim
- Improved latency for startup, todo tool, and file edits
[](#0-2-102)
0.2.102
May 5, 2025
- Improved thinking triggering reliability
- Improved @mention reliability for images and folders
- You can now paste multiple large chunks into one prompt
[](#0-2-100)
0.2.100
May 2, 2025
- Fixed a crash caused by a stack overflow error
- Made db storage optional; missing db support disables —continue and —resume
[](#0-2-98)
0.2.98
May 1, 2025
- Fixed an issue where auto-compact was running twice
[](#0-2-96)
0.2.96
May 1, 2025
- Claude Code can now also be used with a Claude Max subscription ([https://claude.ai/upgrade](https://claude.ai/upgrade))
[](#0-2-93)
0.2.93
April 30, 2025
- Resume conversations from where you left off from with “claude —continue” and “claude —resume”
- Claude now has access to a Todo list that helps it stay on track and be more organized
[](#0-2-82)
0.2.82
April 25, 2025
- Added support for —disallowedTools
- Renamed tools for consistency: LSTool -\> LS, View -\> Read, etc.
[](#0-2-75)
0.2.75
April 21, 2025
- Hit Enter to queue up additional messages while Claude is working
- Drag in or copy/paste image files directly into the prompt
- @-mention files to directly add them to context
- Run one-off MCP servers with `claude --mcp-config <path-to-file>`
- Improved performance for filename auto-complete
[](#0-2-74)
0.2.74
April 18, 2025
- Added support for refreshing dynamically generated API keys (via apiKeyHelper), with a 5 minute TTL
- Task tool can now perform writes and run bash commands
[](#0-2-72)
0.2.72
April 18, 2025
- Updated spinner to indicate tokens loaded and tool usage
[](#0-2-70)
0.2.70
April 17, 2025
- Network commands like curl are now available for Claude to use
- Claude can now run multiple web queries in parallel
- Pressing ESC once immediately interrupts Claude in Auto-accept mode
[](#0-2-69)
0.2.69
April 17, 2025
- Fixed UI glitches with improved Select component behavior
- Enhanced terminal output display with better text truncation logic
[](#0-2-67)
0.2.67
April 17, 2025
- Shared project permission rules can be saved in .claude/settings.json
[](#0-2-66)
0.2.66
April 17, 2025
- Print mode (-p) now supports streaming output via —output-format=stream-json
- Fixed issue where pasting could trigger memory or bash mode unexpectedly
[](#0-2-63)
0.2.63
April 17, 2025
- Fixed an issue where MCP tools were loaded twice, which caused tool call errors
[](#0-2-61)
0.2.61
April 2, 2025
- Navigate menus with vim-style keys (j/k) or bash/emacs shortcuts (Ctrl+n/p) for faster interaction
- Enhanced image detection for more reliable clipboard paste functionality
- Fixed an issue where ESC key could crash the conversation history selector
[](#0-2-59)
0.2.59
April 2, 2025
- Copy+paste images directly into your prompt
- Improved progress indicators for bash and fetch tools
- Bugfixes for non-interactive mode (-p)
[](#0-2-54)
0.2.54
April 2, 2025
- Quickly add to Memory by starting your message with ’#’
- Press ctrl+r to see full output for long tool results
- Added support for MCP SSE transport
[](#0-2-53)
0.2.53
April 2, 2025
- New web fetch tool lets Claude view URLs that you paste in
- Fixed a bug with JPEG detection
[](#0-2-50)
0.2.50
April 2, 2025
- New MCP “project” scope now allows you to add MCP servers to .mcp.json files and commit them to your repository
[](#0-2-49)
0.2.49
April 2, 2025
- Previous MCP server scopes have been renamed: previous “project” scope is now “local” and “global” scope is now “user”
[](#0-2-47)
0.2.47
April 2, 2025
- Press Tab to auto-complete file and folder names
- Press Shift + Tab to toggle auto-accept for file edits
- Automatic conversation compaction for infinite conversation length (toggle with /config)
[](#0-2-44)
0.2.44
April 2, 2025
- Ask Claude to make a plan with thinking mode: just say ‘think’ or ‘think harder’ or even ‘ultrathink’
[](#0-2-41)
0.2.41
April 2, 2025
- MCP server startup timeout can now be configured via MCP_TIMEOUT environment variable
- MCP server startup no longer blocks the app from starting up
[](#0-2-37)
0.2.37
April 2, 2025
- New /release-notes command lets you view release notes at any time
- `claude config add/remove` commands now accept multiple values separated by commas or spaces
[](#0-2-36)
0.2.36
April 2, 2025
- Import MCP servers from Claude Desktop with `claude mcp add-from-claude-desktop`
- Add MCP servers as JSON strings with `claude mcp add-json <n> <json>`
[](#0-2-34)
0.2.34
April 2, 2025
- Vim bindings for text input - enable with /vim or /config
[](#0-2-32)
0.2.32
April 2, 2025
- Interactive MCP setup wizard: Run “claude mcp add” to add MCP servers with a step-by-step interface
- Fix for some PersistentShell issues
[](#0-2-31)
0.2.31
April 2, 2025
- Custom slash commands: Markdown files in .claude/commands/ directories now appear as custom slash commands to insert prompts into your conversation
- MCP debug mode: Run with —mcp-debug flag to get more information about MCP server errors
[](#0-2-30)
0.2.30
April 2, 2025
- Added ANSI color theme for better terminal compatibility
- Fixed issue where slash command arguments weren’t being sent properly
- (Mac-only) API keys are now stored in macOS Keychain
[](#0-2-26)
0.2.26
April 2, 2025
- New /approved-tools command for managing tool permissions
- Word-level diff display for improved code readability
- Fuzzy matching for slash commands
[](#0-2-21)
0.2.21
April 2, 2025
- Fuzzy matching for /commands
---
## Channels reference - Claude Code Docs
Source: https://code.claude.com/docs/en/channels-reference
Path: 02-Claude-Code-CLI/channels-reference.md
## On this page
- [Overview](#overview)
- [What you need](#what-you-need)
- [Example: build a webhook receiver](#example-build-a-webhook-receiver)
- [Test during the research preview](#test-during-the-research-preview)
- [Server options](#server-options)
- [Notification format](#notification-format)
- [Expose a reply tool](#expose-a-reply-tool)
- [Gate inbound messages](#gate-inbound-messages)
- [Relay permission prompts](#relay-permission-prompts)
- [How relay works](#how-relay-works)
- [Permission request fields](#permission-request-fields)
- [Add relay to a chat bridge](#add-relay-to-a-chat-bridge)
- [Full example](#full-example)
- [Package as a plugin](#package-as-a-plugin)
- [See also](#see-also)
Reference
# Channels reference
Copy pageCopy page
Build an MCP server that pushes webhooks, alerts, and chat messages into a Claude Code session. Reference for the channel contract: capability declaration, notification events, reply tools, sender gating, and permission relay.
Copy pageCopy page
Channels are in [research preview](channels.md#research-preview). Team and Enterprise organizations must [explicitly enable them](channels.md#enterprise-controls).
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](#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](#relay-permission-prompts) so you can approve or deny tool use remotely. This page covers:
- [Overview](#overview): how channels work
- [What you need](#what-you-need): requirements and general steps
- [Example: build a webhook receiver](#example-build-a-webhook-receiver): a minimal one-way walkthrough
- [Server options](#server-options): the constructor fields
- [Notification format](#notification-format): the event payload and delivery behavior
- [Expose a reply tool](#expose-a-reply-tool): let Claude send messages back
- [Gate inbound messages](#gate-inbound-messages): sender checks to prevent prompt injection
- [Relay permission prompts](#relay-permission-prompts): forward tool approval prompts to remote channels
To use an existing channel instead of building one, see [Channels](channels.md). Telegram, Discord, iMessage, and fakechat are included in the research preview.
[](#overview)
Overview
A channel is an [MCP](https://modelcontextprotocol.io) 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)
What you need
The only hard requirement is the [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) package and a Node.js-compatible runtime. [Bun](https://bun.sh), [Node](https://nodejs.org), and [Deno](https://deno.com) all work. The pre-built plugins in the research preview use Bun, but your channel doesn’t have to. Your server needs to:
1. Declare the `claude/channel` capability so Claude Code registers a notification listener
2. Emit `notifications/claude/channel` events when something happens
3. Connect over [stdio transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-io)
The [Server options](#server-options) and [Notification format](#notification-format) sections cover each of these in detail. See [Example: build a webhook receiver](#example-build-a-webhook-receiver) for a full walkthrough. During the research preview, custom channels aren’t on the [approved allowlist](channels.md#supported-channels). Use `--dangerously-load-development-channels` to test locally. See [Test during the research preview](#test-during-the-research-preview) for details.
[](#example-build-a-webhook-receiver)
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](https://bun.sh) as the runtime for its built-in HTTP server and TypeScript support. You can use [Node](https://nodejs.org) or [Deno](https://deno.com) instead; the only requirement is the [MCP SDK](https://www.npmjs.com/package/@modelcontextprotocol/sdk).
1
Create the project
The [permission relay](#relay-permission-prompts) examples import `zod` directly, so it installs alongside the MCP SDK. Create a new directory and install both:
```python
mkdir webhook-channel && cd webhook-channel
bun add @modelcontextprotocol/sdk zod
```
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
```python
#!/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': {} } },
// Claude Code delivers this to Claude as context when the server connects, 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 configures the server, connects over stdio, and starts an HTTP listener, in that order:
- **Server configuration**: creates the MCP server with `claude/channel` in its capabilities, which is what tells Claude Code this is a channel. Claude Code delivers the [`instructions`](#server-options) string to Claude as context when the server connects: 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](https://modelcontextprotocol.io/docs/concepts/transports#standard-io).
- **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
```python
{
"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:
```python
claude --dangerously-load-development-channels server:webhook
```
Claude Code first shows a full-screen warning dialog listing the development channels you’re loading. Select **I am using this for local development** to continue, or **Exit** to quit.The first time you start a session in this project, Claude Code also asks for consent before using the new server from `.mcp.json`. The dialog reports “New MCP server found in this project: webhook”. Select **Use this MCP server** to continue.After you accept, Claude Code 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.A dim notice below the startup banner confirms the channel is registered: `Channels (experimental) messages from server:webhook inject directly in this session · restart without --dangerously-load-development-channels to stop`.If you see “blocked by org policy,” your organization admin needs to [enable channels](channels.md#enterprise-controls) 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):
```python
curl -X POST localhost:8788 -d "build failed on main: https://ci.example.com/run/1234"
```
The payload arrives in Claude’s context as a `<channel>` tag:
```python
<channel source="webhook" path="/" method="POST">
build failed on main: https://ci.example.com/run/1234
</channel>
```
Your terminal renders the event as a one-line summary, `← webhook: build failed on main: https://ci.example.com/run/1234`, rather than the raw tag. You’ll then see Claude 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](#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. A `failed` status usually means a dependency or import error in your server file. To see the stderr trace, restart with `claude --debug --dangerously-load-development-channels server:webhook` and check the debug log at `~/.claude/debug/<session-id>.txt`.
- **`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](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/fakechat) extends this pattern with a web UI, file attachments, and a reply tool for two-way chat.
[](#test-during-the-research-preview)
Test during the research preview
During the research preview, every channel must be on the [approved allowlist](channels.md#research-preview) to register. The development flag bypasses the allowlist for specific entries after a confirmation prompt. This example shows both entry types:
```python
# 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, your channel isn’t on the approved allowlist, so it 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)
Server options
A channel sets these options in the [`Server`](../06-MCP-Tools/Tutorials/learn-server-concepts.md) constructor. The `instructions` and `capabilities.tools` fields are [standard MCP](../06-MCP-Tools/Tutorials/learn-server-concepts.md); `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` or `false` | Optional. Set it to `{}` to declare 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. To opt out, omit the key or set it to `false`. Before v2.1.234, Claude Code treated `false` as declared. See [Relay permission prompts](#relay-permission-prompts). |
| `capabilities.tools` | `object` | Two-way only. Always `{}`. Standard MCP tool capability. See [Expose a reply tool](#expose-a-reply-tool). |
| `instructions` | `string` | Recommended. Claude Code delivers it to Claude as context when the server connects. 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:
```python
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
},
// Claude Code delivers this to Claude as context when the server connects, so it knows how to handle your events
instructions: 'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.',
},
)
```
[](#notification-format)
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:
```python
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:
```python
<channel source="your-channel" severity="high" run_id="1234">
build failed on main: https://ci.example.com/run/1234
</channel>
```
Claude Code doesn’t acknowledge notifications. 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, Claude Code drops the events silently and returns no error to your server. If you need delivery confirmation, track event state in your server and expose a [reply tool](#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)
Expose a reply tool
If your channel is two-way, like a chat bridge rather than an alert forwarder, expose a standard [MCP tool](https://modelcontextprotocol.io/docs/concepts/tools) that Claude can call to send messages back. Nothing about the tool registration is channel-specific. A reply tool has three components:
1. A `tools: {}` entry in your `Server` constructor capabilities so Claude Code discovers the tool
2. Tool handlers that define the tool’s schema and implement the send logic
3. 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](#example-build-a-webhook-receiver):
1
Enable tool discovery
In your `Server` constructor in `webhook.ts`, add `tools: {}` to the capabilities so Claude Code knows your server offers tools:
```python
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`:
```python
// 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:
```python
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](https://developer.mozilla.org/en-US/docs/Web/API/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
```python
#!/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](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/fakechat) shows a more complete example with file attachments and message editing.
[](#gate-inbound-messages)
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:
```python
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](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram) and [Discord](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord) channels gate on a sender allowlist the same way. They bootstrap the list by [pairing](channels.md#security). See either implementation for the full pairing flow. The [iMessage](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/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)
Relay permission prompts
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. Claude Code v2.1.234 and later sends permission requests only to servers it registered as channels for the session, so relay sits behind the same [session opt-in and organization controls](channels.md#security) as message delivery. Relay also requires you to opt the server in with `--channels` or the development flag, and requires the server to declare the permission capability.
[](#how-relay-works)
How relay works
When a permission prompt opens, the relay loop has four steps:
1. Claude Code generates a short request ID and notifies your server
2. Your server forwards the prompt and ID to your chat app
3. The remote user replies with a yes or no and that ID
4. 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)
Permission request fields
The outbound notification from Claude Code is `notifications/claude/channel/permission_request`. Like the [channel notification](#notification-format), 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, never the command itself. For a Bash call this is Claude’s description of the command; when the model gives no description, the field is the constant `Run shell command` and carries zero command detail. Render `input_preview` when you have room. |
| `input_preview` | The tool’s arguments as JSON-shaped display text, keyed per top-level field. For Bash this is the command; for Write, the file path and the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show. |
Clients on Claude Code v2.1.211 or later sanitize `description` and `input_preview` before relaying them. Expect three changes in the text you receive:
- Claude Code neutralizes direction-override characters, invisible characters, and quote and angle-bracket lookalikes.
- Claude Code folds each run of whitespace to a single space.
- Claude Code relays text whole up to 3,500 code points. For a longer value, you receive its start and its end around a counted `⋯ N code points elided ⋯` marker. The end of a long command still reaches the approver.
For `input_preview`, Claude Code applies the 3,500 limit to each top-level field of the arguments separately and keeps the JSON’s own structural quotes. Clients before v2.1.211 relay `description` raw and cut `input_preview` to 200 UTF-16 units with a trailing ellipsis. Clients on Claude Code v2.1.234 or later relay the marker `(value unserializable)` in place of an `input_preview` field value they can’t serialize safely, such as a circular structure or an extremely large array. You still receive the field’s key, and the preview’s other fields are unchanged. Clients on Claude Code v2.1.234 or later also mask credentials in `description` and `input_preview`. You receive `[REDACTED]` in place of a recognizable provider credential token, such as an API key or a personal access token. Expect three effects of the masking when you render the fields:
- Claude Code masks key names inside `input_preview` as well as their values. A key name you display may not match the key name in the input.
- Claude Code never masks a span that contains shell syntax, path characters, or URL characters. A mask can’t hide the command, file path, or destination being approved.
- Claude Code doesn’t mask a secret that lacks a recognizable prefix, or a secret that spans whitespace, such as a private-key block. Both reach your server unmasked.
Masking doesn’t change who receives the fields. Whatever stays unmasked goes only to servers you opted in with `--channels` or the development flag. Treat both fields as untrusted unless you control the client fleet. 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. Neither verdict affects future calls.
[](#add-relay-to-a-chat-bridge)
Add relay to a chat bridge
Adding permission relay to a two-way channel takes three components:
1. A `claude/channel/permission: {}` entry under `experimental` capabilities in your `Server` constructor so Claude Code knows to forward prompts
2. A notification handler for `notifications/claude/channel/permission_request` that formats the prompt and sends it out through your platform API
3. 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](#gate-inbound-messages), 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](#expose-a-reply-tool):
1
Declare the permission capability
In your `Server` constructor, add `claude/channel/permission: {}` alongside `claude/channel` under `experimental`:
```python
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](#permission-request-fields) when a permission dialog opens. Your handler formats the prompt for your platform and includes instructions for replying with the ID:
```python
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(), // summary of this call. Treat as untrusted.
input_preview: z.string(), // tool args as JSON-shaped text. Treat as untrusted.
}),
})
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` +
// input_preview carries the actual arguments; render it when you
// have room: for Bash the description alone may be just
// "Run shell command" with zero command detail
`${params.input_preview}\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](#gate-inbound-messages) 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.
```python
// 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) } },
})
}
```
A remote reply that doesn’t exactly match the expected format fails in one of two ways, and in both cases the local terminal 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)
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](#example-build-a-webhook-receiver) 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
```python
#!/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` +
`${params.input_preview}\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 133 lines
Test the verdict path in three terminals. The first is your Claude Code session, started with the [development flag](#test-during-the-research-preview) so it spawns `webhook.ts`:
```python
claude --dangerously-load-development-channels server:webhook
```
This walkthrough tests the permission dialog itself, so once the session is open, press `Shift+Tab` until the status bar shows `⏸ manual mode on`. In auto mode the classifier would decide the `reply` call instead of you, and no dialog would open for the remote side to answer. In the second, stream the outbound side so you can see Claude’s replies and any permission prompts as they fire:
```python
curl -N localhost:8788/events
```
In the third, send a message that will make Claude try to run a command:
```python
curl -d "list the files in this directory" -H "X-Sender: dev" localhost:8788
```
Listing files is read-only, so Claude runs it without approval. The permission dialog opens when Claude calls the `reply` tool to send its answer back. The local dialog opens in your Claude Code terminal, and a moment later the prompt for `mcp__webhook__reply` appears in the `/events` stream, including the five-letter ID. Approve it from the remote side:
```python
curl -d "yes <id>" -H "X-Sender: dev" localhost:8788
```
The local dialog closes, the `reply` tool runs, and Claude’s reply appears in the stream. 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)
Package as a plugin
To make your channel installable and shareable, wrap it in a [plugin](../08-Plugins-Skills/plugins.md) and publish it to a [marketplace](../08-Plugins-Skills/plugins.md). 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](channels.md#supported-channels). The default allowlist is the channel plugins in `claude-plugins-official`. The community marketplace is not on the channel allowlist. If you are working with an Anthropic partner contact, reach out to them to coordinate an official-marketplace listing. On Team and Enterprise plans, an admin can instead include your plugin in the organization’s own [`allowedChannelPlugins`](channels.md#restrict-which-channel-plugins-can-run) list, which replaces the default Anthropic allowlist.
[](#see-also)
See also
- [Channels](channels.md) to install and use Telegram, Discord, iMessage, or the fakechat demo, and to enable channels for a Team or Enterprise org
- [Working channel implementations](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins) for complete server code with pairing flows, reply tools, and file attachments
- [MCP](../06-MCP-Tools/General/mcp.md) for the underlying protocol that channel servers implement
- [Plugins](../08-Plugins-Skills/plugins.md) to package your channel so users can install it with `/plugin install`
---
## Push events into a running session with channels - Claude Code Docs
Source: https://code.claude.com/docs/en/channels
Path: 02-Claude-Code-CLI/channels.md
## On this page
- [Supported channels](#supported-channels)
- [Quickstart](#quickstart)
- [Security](#security)
- [Enterprise controls](#enterprise-controls)
- [Enable channels for your organization](#enable-channels-for-your-organization)
- [Restrict which channel plugins can run](#restrict-which-channel-plugins-can-run)
- [Research preview](#research-preview)
- [How channels compare](#how-channels-compare)
- [Next steps](#next-steps)
Automation
# Push events into a running session with channels
Copy pageCopy page
Use channels to push messages, alerts, and webhooks into your Claude Code session from an MCP server. Forward CI results, chat messages, and monitoring events so Claude can react while you’re away.
Copy pageCopy page
Channels are in [research preview](#research-preview). They require Anthropic authentication through claude.ai or a Console API key, and are not available on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry. Team and Enterprise organizations must [explicitly enable them](#enterprise-controls).
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](#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. If you manage a Team, Enterprise, or Console organization, see [Enable channels for your organization](#enterprise-controls). To build your own channel, see the [Channels reference](channels-reference.md).
[](#supported-channels)
Supported channels
Each supported channel is a plugin that requires [Bun](https://bun.sh). For a hands-on demo of the plugin flow before connecting a real platform, try the [fakechat quickstart](#quickstart).
- Telegram
- Discord
- iMessage
View the full [Telegram plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram).
1
Create a Telegram bot
Open [BotFather](https://t.me/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:
```python
/plugin install telegram@claude-plugins-official
```
If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
When the install asks for an installation scope, choose the user scope option so the plugin is available across all your projects. Check the install summary: if it reports `Run /reload-plugins to activate.`, see [Apply plugin changes without restarting](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) to make the plugin’s configure command available.
3
Configure your token
Run the configure command with the token from BotFather:
```python
/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:
```python
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:
```python
/telegram:access pair <code>
```
Then lock down access so only your account can send messages:
```python
/telegram:access policy allowlist
```
View the full [Discord plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord).
1
Create a Discord bot
Go to the [Discord Developer Portal](https://discord.com/developers/applications), 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:
```python
/plugin install discord@claude-plugins-official
```
If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
When the install asks for an installation scope, choose the user scope option so the plugin is available across all your projects. Check the install summary: if it reports `Run /reload-plugins to activate.`, see [Apply plugin changes without restarting](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) to make the plugin’s configure command available.
5
Configure your token
Run the configure command with the bot token you copied:
```python
/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:
```python
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:
```python
/discord:access pair <code>
```
Then lock down access so only your account can send messages:
```python
/discord:access policy allowlist
```
View the full [iMessage plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/imessage).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:
```python
/plugin install imessage@claude-plugins-official
```
If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
When the install asks for an installation scope, choose the user scope option so the plugin is available across all your projects.If the install summary reports `Run /reload-plugins to activate.`, you don’t need to act on it here, because restarting in the next step picks up the plugin.
3
Restart with channels enabled
Exit Claude Code and restart with the channel flag:
```python
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:
```python
/imessage:access allow +15551234567
```
Handles are phone numbers in `+country` format or Apple ID emails like `user@example.com`.
[](#quickstart)
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](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram), [Discord](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord), or [iMessage](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/imessage). To try the fakechat demo, you’ll need:
- Claude Code [installed and authenticated](../01-Getting-Started/quickstart.md#step-1-install-claude-code) with a claude.ai account or a Claude Console API key
- [Bun](https://bun.sh) installed. The pre-built channel plugins are Bun scripts. Check with `bun --version`; if that fails, [install Bun](https://bun.sh/docs/installation).
- **Team, Enterprise, or managed Console org**: your admin must [enable channels](#enterprise-controls) in managed settings
1
Install the fakechat channel plugin
Start a Claude Code session and run the install command:
```python
/plugin install fakechat@claude-plugins-official
```
If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
When the install asks for an installation scope, choose the user scope option so the plugin is available across all your projects.If the install summary reports `Run /reload-plugins to activate.`, you don’t need to act on it here, because restarting in the next step picks up the plugin.
2
Restart with the channel enabled
Exit Claude Code, then restart with `--channels` and pass the fakechat plugin you installed:
```python
claude --channels plugin:fakechat@claude-plugins-official
```
The fakechat server starts automatically. The startup screen shows a channels notice stating that messages from `plugin:fakechat@claude-plugins-official` inject directly in this session. If the plugin isn’t installed or isn’t on the approved allowlist, a warning line naming the problem appears below that notice.
You can pass several plugins to `--channels`, space-separated.
3
Push a message in
Open the fakechat UI at [http://localhost:8787](http://localhost:8787) and type a message:
```python
what's in my working directory?
```
The message arrives in your Claude Code session. The terminal shows it as an inbound channel line like `← fakechat · web: what's in my working directory?`, while the model receives it as a `<channel source="plugin:fakechat:fakechat">` event, using the plugin’s scoped server name. Claude reads it, does the work, and calls fakechat’s `reply` tool. If Claude Code asks for permission for the first reply, approve it. 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](channels-reference.md#relay-permission-prompts) can forward these prompts to you so you can approve or deny remotely. For unattended use, [`--dangerously-skip-permissions`](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) bypasses most prompts, but only use it in environments you trust. Even then, the [actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) still apply. 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)
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:
1. Find your bot in Telegram or Discord and send it any message
2. The bot replies with a pairing code
3. In your Claude Code session, approve the code when prompted
4. 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`](#enterprise-controls) 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](channels-reference.md#relay-permission-prompts) 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)
Enterprise controls
Admins control availability through two [managed settings](settings.md) that users cannot override. The default depends on how you authenticate:
- **claude.ai Team and Enterprise**: channels are blocked until an Owner [enables them](#enable-channels-for-your-organization).
- **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. Blocks all channels including the development flag when off. See [Enable channels for your organization](#enable-channels-for-your-organization). | 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. | 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)
Enable channels for your organization
Enable channels for your organization from [**claude.ai → Admin settings → Claude Code → Channels**](https://claude.ai/admin-settings/claude-code), which requires the Owner role, 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)
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:
```python
{
"channelsEnabled": true,
"allowedChannelPlugins": [
{ "marketplace": "claude-plugins-official", "plugin": "telegram" },
{ "marketplace": "claude-plugins-official", "plugin": "discord" },
{ "marketplace": "acme-corp-plugins", "plugin": "internal-alerts" }
]
}
```
If you set an empty array, you block all channel plugins from the allowlist, but `--dangerously-load-development-channels` can still bypass that block 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. If you set `MCP_PROTOCOL_NEGOTIATION` to `auto` on the v2 MCP client runtime, a channel can also fail to register because Claude Code [doesn’t register a channel server that negotiates protocol revision 2026-07-28](../06-MCP-Tools/General/mcp.md#push-messages-with-channels).
[](#research-preview)
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. Neither `--channels` nor `--dangerously-load-development-channels` appears in `claude --help` while the feature is in preview. The flags work even though they aren’t listed. During the preview, `--channels` only accepts plugins from an Anthropic-maintained allowlist, or from your organization’s allowlist if an admin has set [`allowedChannelPlugins`](#restrict-which-channel-plugins-can-run). The channel plugins in [claude-plugins-official](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins) 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, pass it to `--dangerously-load-development-channels` in the `plugin:<name>@<marketplace>` or `server:<name>` form. See [Test during the research preview](channels-reference.md#test-during-the-research-preview) for information about testing custom channels that you build. Report issues or feedback on the [Claude Code GitHub repository](https://github.com/anthropics/claude-code/issues).
[](#how-channels-compare)
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 |
|---------------------------------------------------|-------------------------------------------------------------------------|-----------------------------------------------------------|
| [Cloud sessions](claude-code-on-the-web.md) | Run tasks in a fresh cloud sandbox, cloned from GitHub | Delegating self-contained async work you check on later |
| [Claude in Slack](../14-Connectors/slack.md) | Spawns a cloud session from an `@Claude` mention in a channel or thread | Starting tasks directly from team conversation context |
| Standard [MCP server](../06-MCP-Tools/General/mcp.md) | 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](remote-control.md) | 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](channels-reference.md#example-build-a-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)
Next steps
Once you have a channel running, explore these related features:
- [Build your own channel](channels-reference.md) for systems that don’t have plugins yet
- [Remote Control](remote-control.md) to drive a local session from your phone instead of forwarding events into it
- [Scheduled tasks](scheduled-tasks.md) to poll on a timer instead of reacting to pushed events
---
## Checkpointing - Claude Code Docs
Source: https://code.claude.com/docs/en/checkpointing
Path: 02-Claude-Code-CLI/checkpointing.md
## On this page
- [How checkpoints work](#how-checkpoints-work)
- [Automatic tracking](#automatic-tracking)
- [Rewind and summarize](#rewind-and-summarize)
- [Rewind past a cleared conversation](#rewind-past-a-cleared-conversation)
- [Guide a summary](#guide-a-summary)
- [Common use cases](#common-use-cases)
- [Limitations](#limitations)
- [Bash command changes not tracked](#bash-command-changes-not-tracked)
- [Subagent edits not restored](#subagent-edits-not-restored)
- [External changes not tracked](#external-changes-not-tracked)
- [Messages sent mid-turn not checkpointed](#messages-sent-mid-turn-not-checkpointed)
- [Symlinked and hard-linked paths not restored](#symlinked-and-hard-linked-paths-not-restored)
- [Not a replacement for version control](#not-a-replacement-for-version-control)
- [See also](#see-also)
Reference
# Checkpointing
Copy pageCopy page
Track, rewind, and summarize Claude’s edits and conversation to manage session state.
Copy pageCopy page
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)
How checkpoints work
As you work with Claude, checkpointing automatically captures the state of your code before each prompt you send that starts a turn.
[](#automatic-tracking)
Automatic tracking
Claude Code tracks all changes made by its file editing tools:
- Every prompt you send that starts a turn creates a new checkpoint
- Claude Code keeps file snapshots for the 100 most recent checkpoints in a session. Discarding an older checkpoint deletes the snapshot files that no remaining checkpoint references, except each file’s first snapshot, which the VS Code extension uses as the baseline for its session diffs.
- Claude Code saves checkpoints with the conversation, so you can still run `/rewind` after you resume a session
- Claude Code deletes a session’s file snapshots in the [retention sweep](claude-directory.md#cleaned-up-automatically), by default about 30 days after the session last saved one. Rewinding to a checkpoint whose snapshots are gone can fail with [`No files were restored`](errors.md#no-files-were-restored). To keep snapshots longer, set [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays).
[](#rewind-and-summarize)
Rewind and summarize
Run `/rewind`, or press `Esc` twice when the prompt input is empty, to open the rewind menu.
If the prompt input contains text, double `Esc` clears it instead of opening the menu. The cleared text is saved to your input history, so press `Up` to recall it after you finish in the rewind menu.
The rewind menu lists each prompt you sent during the session, except [messages that joined a running turn](#messages-sent-mid-turn-not-checkpointed). 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
The two code restore options appear only when the selected checkpoint has tracked file changes to revert. If no file edits were captured after that point, the menu offers only **Restore conversation**, the summarize options, and **Never mind**. 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. With either summarize option, a **Summarized conversation** marker appears in the conversation where the compressed messages were.
[](#rewind-past-a-cleared-conversation)
Rewind past a cleared conversation
If you ran `/clear` earlier in the same Claude Code process, the rewind menu shows an additional entry at the top of the list labeled `/resume <session-id> (previous session)`. Select it to resume the conversation that was active before `/clear` ran. The entry is available until you exit Claude Code or resume a different session.
[](#guide-a-summary)
Guide a summary
Summarizing doesn’t change files on disk, and the original messages stay in the session transcript, so Claude can still reference the details. To guide what the summary focuses on, highlight a **Summarize** option with the arrow keys and type instructions where the row reads **add context (optional)**, then press `Enter`. Selecting the option with its number key summarizes immediately without instructions.
Summarize keeps you in the same session and compresses context, like a targeted `/compact`. To branch off and try a different approach while preserving the original session intact, use [`/branch`](sessions.md#branch-a-session) or `claude --continue --fork-session` instead.
[](#common-use-cases)
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)
Limitations
[](#bash-command-changes-not-tracked)
Bash command changes not tracked
Checkpointing does not track files modified by Bash commands. For example, if Claude Code runs:
```python
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.
[](#subagent-edits-not-restored)
Subagent edits not restored
A [subagent](../09-Agents-Patterns/sub-agents.md) makes edits with Claude’s file editing tools, but Claude Code usually doesn’t capture those edits in your session’s checkpoints. Whether rewinding restores them depends on how the subagent runs:
- **Foreground forked skill**: a [skill with `context: fork`](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent) that runs in the foreground edits your working tree during your own turn, so rewinding restores its edits as usual. Set `background: false` to run a fork in the foreground; a few situations, [listed on the skills page](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent), run it there regardless of the setting.
- **Any other subagent**: rewinding doesn’t restore the edits. Use git to revert them. This includes a forked skill that runs in the background, the default, and a background [`/code-review --fix`](code-review.md) run.
[](#external-changes-not-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.
[](#messages-sent-mid-turn-not-checkpointed)
Messages sent mid-turn not checkpointed
When a message you [queue while Claude works](interactive-mode.md#queue-messages-while-claude-works) reaches Claude within the running turn, it joins that turn instead of starting a new one. The message appears in the conversation, but Claude Code doesn’t create a checkpoint for it, and the rewind menu doesn’t list it. A queued message that Claude Code sends as part of a new turn gets a checkpoint as usual, including when several queued messages [share that turn](interactive-mode.md#when-claude-code-sends-what-you-queued). To remove such a message, or undo the edits Claude made after it, rewind to the prompt that started the turn. That rewinds the whole turn, including the work Claude did before your message arrived.
[](#symlinked-and-hard-linked-paths-not-restored)
Symlinked and hard-linked paths not restored
Checkpointing doesn’t rewind symlinked or hard-linked files. When you pick **Restore code** or **Restore code and conversation** from the `/rewind` menu, Claude Code skips any tracked path that is a symlink or hard link and shows a `Restored the code, but skipped N files` warning. The skipped files keep their current contents. To undo the session’s changes to one of them, ask Claude to reverse the edit or edit the file yourself. Config files a dotfile manager symlinks into your project and files pnpm hard-links into place both fall into this category. To see which paths a restore skips, turn on debug logging with `/debug` before you restore: the debug log at `~/.claude/debug/<session-id>.txt` names each skipped path. For every skip reason and the recovery steps, see [the skipped-files entry in the error reference](errors.md#restored-the-code-but-skipped-files).
[](#not-a-replacement-for-version-control)
Not a replacement for version control
Checkpoints are designed for quick, session-level recovery. For permanent version history and collaboration, continue using version control, such as Git, for commits, branches, and long-term history.
[](#see-also)
See also
- [Interactive mode](interactive-mode.md) - Keyboard shortcuts and session controls
- [Commands](commands.md) - Accessing checkpoints using `/rewind`
- [CLI reference](cli-reference.md) - Command-line options
---
## Claude Code champion kit | Claude Help Center
Source: https://support.claude.com/en/articles/14555399-claude-code-champion-kit
Path: 02-Claude-Code-CLI/claude-code-champion-kit.md
# Claude Code champion kit
A guide for internal champions driving adoption
April 15, 2026
Adoption of a new developer tool rarely happens just 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. This kit is designed to support that effort without turning it into a second job. It gives shape to things you are likely already doing and provides material you can hand directly to colleagues.
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 as a help desk, and this guide is structured to keep the role sustainable on those terms.
## How to use this guide
The champion role consists of three behaviors that reinforce one another: sharing what you discover, being the person people ask, and growing the circle of active users. The sections below cover each in turn, followed by a thirty-day playbook, guidance for responding to common concerns, and a quick-reference sheet you can hand to anyone.
Use whatever fits your team and set aside whatever does not. Nothing here is a checklist you are expected to complete; it is a set of patterns that have worked across many engineering organizations.
------------------------------------------------------------------------
## Phase 1: The champion role
### What a champion does
[TABLE]
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.
### Why this matters
Tools spread inside an organization when someone trusted demonstrates that they are worth the effort. Documentation can describe what is possible, but a colleague’s example—drawn from the same codebase, the same workflows, and the same constraints—is what moves people from curiosity to a first attempt. By making your own experience visible, you remove the most common reason adoption stalls: not knowing where to start.
### What this should cost you
It is worth setting 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.
[TABLE]
------------------------------------------------------------------------
## Phase 2: 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.
[TABLE]
### 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 new destination.
[TABLE]
### 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.
### Example posts
The following are illustrations of tone and length rather than templates to copy 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.*
------------------------------------------------------------------------
## Phase 3: 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
The table below covers the questions champions are asked most frequently, along with a suggested response and the resource to offer when the person is ready for more depth.
[TABLE]
------------------------------------------------------------------------
## Phase 4: 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
[TABLE]
### A 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.
[TABLE]
### 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 official **[Quickstart](../01-Getting-Started/quickstart.md)** and **[Common workflows](common-workflows.md)** pages. They contain short sections covering the features that are genuinely useful but difficult to discover on your own.
------------------------------------------------------------------------
## Phase 5: Responding to common concerns
Healthy skepticism is to be expected; engineers should be cautious about new tools. 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.
[TABLE]
------------------------------------------------------------------------
## Appendix: Quick-reference sheet
The techniques below are the ones that most reliably move someone from a first trial to daily use. This table is intended to be pinned in a channel or shared on its own.
[TABLE]
------------------------------------------------------------------------
## Appendix: Resource directory
[TABLE]
Thank you for taking on this role. People adopt new tools because someone they trust showed them it was worth the effort, and that is the contribution you are making. Claude Code is updated frequently; please verify version-specific details against **[code.claude.com/docs](code-home.md)** before distributing this material internally.
---
## Claude Code cheatsheet | Claude Help Center
Source: https://support.claude.com/en/articles/14553413-claude-code-cheatsheet
Path: 02-Claude-Code-CLI/claude-code-cheatsheet.md
# Claude Code cheatsheet
August 7, 2026
This page collects the vocabulary, commands, and keyboard shortcuts that are worth committing to muscle memory. Keep it open in a browser tab (or printed beside your keyboard) during your first few weeks with Claude Code. Most of the friction new users hit comes from not knowing a command already exists for what they are trying to do, so a quick scan here before reaching for a workaround usually pays off.
------------------------------------------------------------------------
## Glossary
[TABLE]
------------------------------------------------------------------------
## Commands
Type `/` on an empty prompt to see every command available in your setup, including custom, plugin, and MCP-provided ones. The list below covers the built-in defaults (and the bundled skills that ship with every install) you will reach for most often while learning the tool. A few entries vary by platform and plan.
[TABLE]
------------------------------------------------------------------------
## Keyboard shortcuts
[TABLE]
Shortcuts vary slightly by terminal and IDE. Press **`?`** inside a session for the exact list in your environment.
---
## Claude Code: Common developer use cases | Claude Help Center
Source: https://support.claude.com/en/articles/14553517-claude-code-common-developer-use-cases
Path: 02-Claude-Code-CLI/claude-code-common-developer-use-cases.md
# Claude Code: Common developer use cases
April 15, 2026
Claude Code is a command-line agent that runs in your terminal, reads your repository, edits files, executes commands, and requests confirmation before performing potentially destructive actions. It is designed to assist at every stage of the software development lifecycle—from exploring an unfamiliar codebase to shipping and maintaining production code.
The table below summarizes where Claude Code fits across the development lifecycle. The remainder of this article walks through the ten tasks developers most frequently use it for, with a sample prompt and expected result for each.
[TABLE]
## How to use this guide
Each use case below includes when to use it, an example prompt, and the expected result. No configuration is required for any of them except §9 (issue-tracker integration), which requires a one-time MCP connector setup.
Use cases are ordered roughly by how early most developers encounter them. Select the one that matches your current task.
------------------------------------------------------------------------
## Use cases
### 1. Fix a failing test
**When to use this:** A test is failing and the cause is not immediately obvious. Use this to have Claude Code locate the root cause and propose a fix without you needing to identify the source file first.
**Example prompt:**
> the tests in tests/auth.test.ts are failing, can you figure out why and fix them
**Expected result:** Claude Code reads the test file, traces the code path through the modules under test, identifies the mismatch, and proposes an edit. After you approve the change, it re-runs the test suite to confirm the fix.
### 2. Understand unfamiliar code
**When to use this:** You need to understand how a module, function, or subsystem works before making changes—for example, when inheriting code or reviewing an unfamiliar area.
**Example prompt:**
> walk me through how the payment retry logic works
**Expected result:** Claude Code locates the relevant files, reads the implementation, and explains the control flow in plain language: entry points, decision branches, edge cases, and how the code connects to the rest of the system. Ask follow-up questions (e.g., “where does X get set”) to drill deeper.
## 3. Find where something happens
**When to use this:** You know a behavior exists in the codebase but cannot locate it via filename or simple text search.
**Example prompt:**
> where do we validate email addresses in this codebase? I want to add a new rule
**Expected result:** Claude Code searches the repository, opens candidate files, and returns file paths and line numbers with enough surrounding context to identify the correct match. If multiple locations exist, it indicates which one is the source of truth.
### 4. Triage an error or stack trace
**When to use this:** You have a runtime error, stack trace, or log output and need to map it back to the responsible code.
**Example prompt:**
<table class="prompt"> <colgroup> <col style="width: 100%" /> </colgroup>
<tbody> <tr class="odd"> <td>> getting this in production:<br />
TypeError: Cannot read properties of undefined (reading 'sessionId')<br />
at validateSession (src/auth/session.ts:47)<br /> at middleware
(src/auth/middleware.ts:12)<br /> what's going on?</td> </tr> </tbody>
</table>
**Expected result:** Claude Code reads the files referenced in the trace, explains what is undefined and why, and proposes a fix. For errors without a clean stack trace, paste any available log output and Claude Code will reconstruct the failure from context.
### 5. Refactor with a plan
**When to use this:** A change spans multiple files and you want to review the full scope before any edits are made.
**Prerequisite:** Press **Shift+Tab** until the mode indicator shows “plan."
**Example prompt:**
> refactor the auth module to use the new session store instead of SessionCache
**Expected result:** Claude Code analyzes the code and produces a numbered plan listing every file it will modify and the change in each. You can approve the plan as-is or amend it (e.g., “don’t touch the logout route”). No files are edited until you approve.
**Reference:** **[Permissions](permissions.md)**
### 6. Write tests for existing code
**When to use this:** A source file lacks coverage, or you need additional edge-case tests that match your project’s existing test conventions.
**Example prompt:**
> add tests for @src/billing/invoice.ts — cover the edge cases around partial refunds. match the style of the existing tests in tests/billing/
**Expected result:** Claude Code reads both the source file and the reference test directory, generates a new test file in the existing style, and runs it to confirm the tests pass. If obvious coverage gaps remain, it flags them and asks whether to address them.
### 7. Review a pull request
**When to use this:** You need to review or summarize a PR, particularly in an area of the codebase you do not know well.
**Prerequisite:** GitHub CLI authenticated (run `gh auth login` once).
**Example prompt:**
> /pr https://github.com/example/api/pull/4471
> is the error handling solid?
**Expected result:** Claude Code fetches the diff, review comments, and CI status, then reads the changed files in their full repository context. It can produce a focused review, draft review comments, verify a specific concern, or summarize the PR.
### 8. Onboard to a new repository
**When to use this:** You are working in a repository for the first time and need a structured overview of its architecture, build commands, and conventions.
**Example prompt:**
<table class="prompt"> <colgroup> <col style="width: 100%" /> </colgroup>
<tbody> <tr class="odd"> <td>> /init<br /> > give me a tour of this
codebase — where's the entry point, how is it structured, what should I
read first</td> </tr> </tbody> </table>
**Expected result:** `/init` scans the project and writes a `CLAUDE.md` file summarizing build commands, architecture, and conventions. The follow-up tour prompt produces a guided walkthrough of the project structure. Project context remains loaded for the rest of the session.
**Reference:** **[Memory and CLAUDE.md](memory.md)**
### 9. Work an issue end to end
**When to use this:** You want to read a ticket, implement the fix, and validate it in a single conversation without switching tools.
**Prerequisite:** Issue tracker connected via MCP (one-time `.mcp.json` configuration).
**Example prompt:**
<table class="prompt"> <colgroup> <col style="width: 100%" /> </colgroup>
<tbody> <tr class="odd"> <td>> what's the top-priority issue assigned
to me?<br /> > go ahead and fix it</td> </tr> </tbody> </table>
**Expected result:** Claude Code queries the issue tracker, reads the ticket, locates the relevant code, proposes a fix, and runs the tests. The session ends with a reviewable diff and the context needed to close the ticket.
**Reference:** **[MCP](../06-MCP-Tools/General/mcp.md)**
### 10. Turn a recurring task into a Skill
**When to use this:** You repeat the same multi-step prompt regularly (pre-commit checks, standup summaries, PR descriptions, release notes) and want to make it reusable for the whole team.
**Example prompt:**
> make me a /ship skill that runs the tests, runs the linter, looks at git diff, and drafts a conventional-commit message — then shows me the message without committing
**Expected result:** Claude Code writes a `SKILL.md` file to `.claude/skills/ship/`. The `/ship` command is available immediately, with no restart required, and is shared with anyone who clones the repository. (The legacy `.claude/commands/` path is still supported, but skills are the recommended form.)
**Reference:** **[Skills](../08-Plugins-Skills/skills.md)**
## Appendix: Quick reference
[TABLE]
## Appendix: Resource directory
[TABLE]
For details on `/init`, @-references, permission modes, skills, MCP, and hooks, see **[code.claude.com/docs](code-home.md)**. Claude Code ships frequently—verify version-specific details against **[code.claude.com/docs](code-home.md)** before distributing internally.
---
## Claude Code communications kit | Claude Help Center
Source: https://support.claude.com/en/articles/14555877-claude-code-communications-kit
Path: 02-Claude-Code-CLI/claude-code-communications-kit.md
# Claude Code communications kit
Ready-to-send messages for Slack, Teams, and email — Enterprise admin enablement
This kit covers launch communications, a twenty-message "tips and tricks" drip campaign, and a quick-reference FAQ for the questions you’ll get asked most. Each message links out to a docs page developers can go deeper on.
## How to use this kit
Three parts, in the order you’ll need them. **Part 1** is your launch announcement—one primary message in email and Slack formats, with swap-in variants for an executive-sponsored send and pilot groups. **Part 2** provides twenty drip-campaign messages packaged as ready-to-paste Slack/Teams posts. **Part 3** is a quick-reference FAQ and link directory.
**Treat everything in this kit as draft copy, not finished copy.** Rewrite each message in your org’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 actually drive adoption are the ones that read like someone at your company wrote them.
------------------------------------------------------------------------
## Part 1: Launch communications
One announcement in two formats, plus two optional variants. Pick whichever fits your rollout and rewrite it from there.
### 1.1 Before you send
[TABLE]
### 1.2 The announcement
Use this as your standard org-wide rollout message. It covers what Claude Code is, gives a two-minute install, hands readers one concrete task to try, and answers “where does my code go?” before anyone has to ask.
**Email**
[TABLE]
**Slack / Teams**
[TABLE]
### 1.3 Variant: Executive sponsor send
**Send this from your sponsoring C-suite executive**—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. No feature tour, no FAQ. The exec’s job is to make the ask land that day; 1.2 and `#claude-code` handle the how.
**Email**
[TABLE]
**Slack / Teams**
[TABLE]
### 1.4 Variant: Pilot / early-access group
Use for a phased rollout. Send to the pilot cohort only.
[TABLE]
### 1.5 Champion recruitment DM
After launch, DM the two or three people who are most active in `#claude-code`.
[TABLE]
------------------------------------------------------------------------
## Part 2: Tips and tricks campaign
Twenty ready-to-paste Slack/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 five that match your team’s gaps. They stand alone—no required order.
Copy the message body from each table below directly into Slack or Teams. Replace \[bracketed placeholders\] before sending.
### 2.1 Getting started
**Message 1 — Choosing the right model**
[TABLE]
*Quick reference:*
[TABLE]
**Message 2 — Quick wins to try first**
[TABLE]
### 2.2 Project memory
**Message 3 — /init and CLAUDE.md**
[TABLE]
**Message 4 — @-references**
[TABLE]
**Message 5 — Memory — “remember that…”**
[TABLE]
### 2.3 Control and safety
**Message 6 — Permission modes**
[TABLE]
*Quick reference (the three you’ll use most — see **[docs](permissions.md)** for the full list):*
[TABLE]
**Message 7 — Checkpointing and /rewind**
[TABLE]
### 2.4 Connect Your Tools
**Message 8 — MCP connectors**
[TABLE]
**Message 9 — IDE integrations**
[TABLE]
### 2.5 Automate Your Workflows
**Message 10 — Slash commands and skills**
[TABLE]
**Message 11 — Hooks**
[TABLE]
**Message 12 — Subagents**
[TABLE]
### 2.6 Day-to-day dev
**Message 13 — Effort levels**
[TABLE]
**Message 14 — Screenshots and images**
[TABLE]
**Message 15 — Git workflows**
[TABLE]
**Message 16 — Background tasks**
[TABLE]
### 2.7 Share and scale
**Message 17 — Plugins**
[TABLE]
**Message 18 — Keyboard shortcuts**
[TABLE]
### 2.8 Security and admin
**Message 19 — Security architecture**
[TABLE]
**Message 20 — Best practices**
[TABLE]
------------------------------------------------------------------------
## Part 3: Quick reference
### 3.1 FAQ responses
One-line Slack replies for the questions you’ll get asked most.
[TABLE]
### 3.2 Prompt templates
[TABLE]
------------------------------------------------------------------------
## Appendix: Verified links reference
[TABLE]
Claude Code ships frequently—verify version-specific details against **[code.claude.com/docs](code-home.md)** before distributing internally.
---
## Claude Code FAQ | Claude Help Center
Source: https://support.claude.com/en/articles/12386420-claude-code-faq
Path: 02-Claude-Code-CLI/claude-code-faq.md
# Claude Code FAQ
June 18, 2026
This article is a compilation of commonly-asked questions about Claude Code related to authentication, integrations, configuration, and more. If you're interested in learning more about Claude Code, please refer to our Claude Docs here: **[Claude Code overview](https://docs.claude.com/en/docs/claude-code/overview)**.
## How do I set up single sign-on (SSO) for Claude Code?
We have detailed instructions for setting up single sign-on on a Team, Enterprise, or Console organization here: **[Set up single sign-on (SSO)](../21-Account-Support/setting-up-single-sign-on-sso-for-claude-and-claude-console.md)**.
## Is there a way to disable Opus model access across our entire organization in Claude Code?
If you are a Claude Console user, this can be configured through rate limiting in your Console organization. If you are using Bedrock or Vertex, set the Opus rate limit to 0 in your Vertex/Bedrock project settings. Note that even if disabled in Vertex, users may be able to switch models in Claude Code, so rate limiting is the most effective approach.
## What are Claude Code dynamic workflows, and how do we control access?
Dynamic workflows (available for Claude Enterprise plans) let Claude run large engineering tasks—migrations, audits, codebase-wide bug hunts—from start to finish in a single Claude Code session. They become available and turn on by default for your whole Enterprise organization on June 8, 2026. Because a single run can last for hours and use more tokens than a typical session, admins should decide who has access before that date.
You have three ways to control access:
1. **At the role level (Enterprise plans with custom roles):** Grant or restrict the Claude Code dynamic workflows capability per group. This only affects members whose role is set to "Custom." See **[Manage custom roles on Enterprise plans](../17-Billing-Plans/manage-custom-roles-on-enterprise-plans.md)**.
2. **Disable org-wide via `managed-settings.json`:** Add `"disableWorkflows": true` to your managed settings. This holds before and after June 8.
3. **Organization-wide:** After June 8, an owner can disable dynamic workflows for everyone by going to **[Organization settings \> Claude Code](https://claude.ai/admin-settings/claude-code)** and toggling **Workflows** off.
We apply the more restrictive of your managed settings and custom role permissions on a per-user basis. If either one disables workflows for a given user, that user won't have access.
## Does Claude Code support Microsoft Visual Studio IDE integration (not VS Code)?
No current Visual Studio 2022 integration exists. Claude Code currently supports VS Code, Cursor (and other VS Code forks), Intellij, Pycharm (and other Jetbrains IDEs).
## How can we implement PR review automation with Claude Code?
While there isn't a turnkey PR reviewer solution yet, you can use the **[Claude Code GitHub Actions integration](automated-security-reviews-in-claude-code.md)** for automated reviews. For now, you can use the security review action as a template and customize it for general PR reviews. This is also a good use case for the **[Claude Code SDK](https://docs.claude.com/en/docs/claude-code/sdk/sdk-overview)**.
## I’m getting an error message that “Claude Max or Pro is required to connect to Claude Code” but I should have access through my organization’s Team or Enterprise plan. How can I troubleshoot?
This indicates that you selected the wrong login method from the Claude Code setup screen. Try running /login again and selecting the account associated with your primary work email address. If you’re still unable to connect, see **[Having trouble using your Team or Enterprise account to access Claude Code?](https://support.claude.com/en/articles/11845131-using-claude-code-with-your-team-or-enterprise-plan#h_540f9e65d8)**
## What data is sent to Anthropic when using Claude Code with Bedrock/Vertex API keys?
When configured with Bedrock/Vertex and CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC is set, only essential telemetry is sent. All model API requests go directly to your Bedrock/Vertex endpoints. Review the [d**ata flow documentation**](https://docs.claude.com/en/docs/claude-code/security) for complete details.
## Is there a way to access Claude Code via Bedrock/Vertex without exposing a secret key/access key?
Yes. Our setup guides for **[Bedrock](https://docs.claude.com/en/docs/claude-code/amazon-bedrock)** and **[Vertex](https://docs.claude.com/en/docs/claude-code/google-vertex-ai)** show how you can enable this. For example, in the Bedrock case you can run \`aws configure\` to configure the AWS CLI before adding the necessary **[configs](https://docs.claude.com/en/docs/claude-code/amazon-bedrock#3-configure-claude-code)** and running Claude Code with the Bedrock, or you can use Bedrock API keys, which is a new feature from AWS that enables API keys for Bedrock usage that don’t require full AWS credentials.
## How can we deploy Claude Code with custom environment variables and permissions across our organization?
Create wrapper scripts that set environment variables before running Claude Code. For permissions, use .claude/settings.json files with allow/deny lists. Note that wildcard patterns (\*) don't always match as expected - test permissions thoroughly. Enterprise teams often inject standardized Claude.md files for consistent configurations.
## Does Claude Code have public code filtering or attribution capabilities on the roadmap?
No, public code filtering and attribution capabilities are not currently on the roadmap. Some customers use BlackDuck for code scanning, though feedback on cost and false positives has been mixed. We are aware that this is a blocker for scaling Claude Code to more users and are looking into solutions.
## Are subagents available in Claude Code SDK and GitHub Actions?
Subagents are available via the **[Claude Code SDK](https://docs.claude.com/en/docs/claude-code/sdk/sdk-overview)**. They're not yet integrated into GitHub Actions, but we are considering this. The UX collapses outputs when more than three subagents run in parallel to manage complexity.
## Can subagents be configured to use specific MCP tools?
Yes, when creating a subagent, you can specify which tools it has access to using the \`tools\` field in the configuration. In the subagent configuration file, you can either omit the tools field to inherit all tools from the main thread, or you can specify individual tools as a comma-separated list for more granular control. Learn more about this in our Claude Docs: **[Subagents - Available tools](https://docs.claude.com/en/docs/claude-code/sub-agents#available-tools)**.
## How can we manage Claude Code costs, especially for automated workflows?
For automated workflows like security reviews, switch from Opus to Sonnet using the **[claude --model \<alias\|name\> configuration option](https://docs.claude.com/en/docs/claude-code/model-config)** for cost savings. You can also monitor usage through your console dashboard and set appropriate rate limits. Note that you can use Workspaces to set more granular spend limits for different user groups. Read more about Workspaces here: **[Creating and managing Workspaces in the Claude Console](../13-Enterprise-Admin/creating-and-managing-workspaces-in-the-claude-console.md)**. We also allow you to view spend per API key in the Console. Refer to this article for more information: **[Cost and Usage Reporting in the Claude Console](../22-Safety-Policy/cost-and-usage-reporting-in-the-claude-console.md)**.
## Can Claude Code work through corporate proxies like LiteLLM?
Yes, Claude Code supports corporate proxy configurations as long as they support the Anthropic API spec. Follow the proxy setup instructions in our Claude Docs: **[Proxy configuration](https://docs.claude.com/en/docs/claude-code/network-config#proxy-configuration)**. Common issues arise from port restrictions in restricted environments.
## How do we add users to Claude Code when using a Console account?
Add users directly to your Console organization with a Claude Code User or Developer role - that's all that's needed. Users then run /login from within Claude Code and select the intended Console account. Do not try to manually create API keys in the Claude Code workspace.
## Is there team-based memory or knowledge sharing beyond Claude.md files?
Currently, Claude.md files are the primary mechanism. IT teams can inject standardized Claude.md files into every machine's .claude directory for org-wide configurations. More advanced team memory features are being explored but not yet available.
## How do permissions work in Claude Code, and why aren’t my allow lists being respected?
Permissions use pattern matching in .claude/settings.json or settings.local.json. Wildcard syntax can be tricky - "Bash(atlassian-api:\*)" should work but may need exact command matching. Use "Yes, and don't ask again for similar commands" to build up permissions incrementally. Check both global (~/.claude/settings.json) and local settings files.
## Does Claude Code index my entire codebase or use a vector database to store information about my codebase?
No. Claude Code has access to a system prompt and a series of tools that it can use to navigate your codebase on command. For example, if Claude Code needs to understand something about your codebase, it will use a search tool to search through your codebase and read files on command. We find that this is more effective and flexible than full codebase indexing: Claude Code is *really* good at knowing how to sift through a codebase to gather context it needs on the fly!
## Can Claude Code integrate with CI/CD, version control, and observability platforms?
Yes, Claude Code integrates with GitHub Actions for CI/CD, supports git operations, and can connect to various platforms via MCP servers. See our Claude Docs for more information:
- **[Claude Code GitHub Actions](https://docs.claude.com/en/docs/claude-code/github-actions)**
- **[Claude Code GitLab CI/CD](https://docs.claude.com/en/docs/claude-code/gitlab-ci-cd)**
## Why am I seeing "Workflow validation failed" errors in GitHub Actions?
This typically occurs with reusable workflows. Check that your workflow syntax is correct and that all required parameters are passed. If the error persists, file an issue here with your workflow configuration: **[github.com/anthropics/claude-code-action](http://github.com/anthropics/claude-code-action)**.
---
## Use Claude Code in the cloud - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-code-on-the-web
Path: 02-Claude-Code-CLI/claude-code-on-the-web.md
## On this page
- [Cloud environments](#cloud-environments)
- [GitHub authentication options](#github-authentication-options)
- [Move tasks between terminal and cloud](#move-tasks-between-terminal-and-cloud)
- [From terminal to cloud](#from-terminal-to-cloud)
- [Tips for cloud tasks](#tips-for-cloud-tasks)
- [Send local repositories without GitHub](#send-local-repositories-without-github)
- [Send follow-ups from the CLI](#send-follow-ups-from-the-cli)
- [Output and errors](#output-and-errors)
- [From cloud to terminal](#from-cloud-to-terminal)
- [Teleport requirements](#teleport-requirements)
- [--teleport is unavailable](#teleport-is-unavailable)
- [Work with sessions](#work-with-sessions)
- [Take back a queued message](#take-back-a-queued-message)
- [Manage context](#manage-context)
- [Permission modes in cloud sessions](#permission-modes-in-cloud-sessions)
- [Review changes](#review-changes)
- [Share sessions](#share-sessions)
- [Share from an Enterprise or Team account](#share-from-an-enterprise-or-team-account)
- [Share from a Max or Pro account](#share-from-a-max-or-pro-account)
- [Archive sessions](#archive-sessions)
- [Delete sessions](#delete-sessions)
- [Auto-fix pull requests](#auto-fix-pull-requests)
- [How Claude responds to PR activity](#how-claude-responds-to-pr-activity)
- [Security and isolation](#security-and-isolation)
- [Troubleshooting](#troubleshooting)
- [Session creation failed](#session-creation-failed)
- [Unable to get organization UUID](#unable-to-get-organization-uuid)
- [Remote Control session expired or access denied](#remote-control-session-expired-or-access-denied)
- [Environment expired](#environment-expired)
- [Limitations](#limitations)
- [Related resources](#related-resources)
Claude Code in the cloud
# Use Claude Code in the cloud
Copy pageCopy page
Run Claude Code sessions in the cloud from your browser, phone, Desktop app, or terminal, move them with `--cloud` and `--teleport`, and auto-fix pull requests.
Copy pageCopy page
Cloud sessions are available on Pro, Max, and Team plans, and for Enterprise users with premium seats or Chat + Claude Code seats.
A cloud session is a Claude Code session that runs on cloud infrastructure instead of on your machine. By default it runs on infrastructure Anthropic manages, or on your organization’s [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) when routed there. The session keeps running after you close your laptop, and you can check on it or steer it from any device. You can start a cloud session from any of these surfaces:
- **Browser**: [claude.ai/code](https://claude.ai/code), also called Claude Code on the web
- **Mobile**: the **Code** tab in the [Claude app](../16-Mobile-Desktop/mobile.md)
- **Desktop app**: select **Cloud** instead of **Local** when you [start a session](../16-Mobile-Desktop/desktop.md#run-long-running-tasks-in-the-cloud)
- **Terminal**: [`claude --cloud`](#from-terminal-to-cloud)
- **Routines**: [scheduled and triggered runs](web-scheduled-tasks.md) each run as a cloud session
To have Claude start and keep track of many cloud sessions for one body of work, use a [project](claude-projects.md). A session in your terminal, your IDE, or the Desktop app with **Local** selected runs on your own machine instead. To steer one of those local sessions from your phone or browser, use [Remote Control](remote-control.md).
New to cloud sessions? Start with [Get started](web-quickstart.md) to connect your GitHub account and submit your first task.
This page covers:
- [Cloud environments](#cloud-environments): where sessions run, and where to configure that
- [GitHub authentication options](#github-authentication-options): two ways to connect GitHub
- [Move tasks between terminal and cloud](#move-tasks-between-terminal-and-cloud) with `--cloud` and `--teleport`
- [Work with sessions](#work-with-sessions): permission modes, reviewing, sharing, archiving, deleting
- [Auto-fix pull requests](#auto-fix-pull-requests): respond automatically to CI failures and review comments
- [Security and isolation](#security-and-isolation): how sessions are isolated
- [Limitations](#limitations): rate limits and platform restrictions
[](#cloud-environments)
Cloud environments
Every cloud session runs in a [cloud environment](cloud-environments.md), the saved configuration that controls network access, environment variables, and setup scripts. If you don’t have an environment yet, onboarding sets up a **Default** environment with [**Trusted** network access](cloud-environments.md#access-levels), either by creating it for you or by asking you to create it. See [The Default environment](cloud-environments.md#the-default-environment) for which of those happens on your plan and how sessions choose an environment when you have more than one. The same environments apply wherever you start a cloud session: the browser, the terminal, [Claude Tag](https://claude.com/docs/claude-tag/overview), [routines](web-scheduled-tasks.md), and the mobile and Desktop apps. Claude Tag channel sessions use organization-level environments only, either [shared environments](cloud-environments.md#organization-shared-environments) or [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md). See [Configure cloud environments](cloud-environments.md) to change what an environment allows, set variables, or add a setup script, and [Installed tools](cloud-environments.md#installed-tools) for what sessions include without any configuration.
[](#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 you connect | Repositories sessions can reach | Best for |
|:-----------------|:-------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------|:------------------------------------------------------------------------|
| **GitHub App** | Authorize the Claude GitHub App during [web onboarding](web-quickstart.md) | Any public repository, and private repositories that the Claude GitHub App is installed on | Browser onboarding; teams that want [Auto-fix](#auto-fix-pull-requests) |
| **`/web-setup`** | Run `/web-setup` in your terminal to send your local `gh` CLI token to your Claude account | Any repository your `gh` token can access, whether or not the Claude GitHub App is installed | Individual developers who already use `gh` |
Installing the Claude GitHub App on a repository also enables [Auto-fix](#auto-fix-pull-requests) for pull requests in it. Threads in a [project](claude-projects.md) need the Claude GitHub App installed on each repository they clone, whichever method you connected with. See [Set up GitHub access](claude-projects.md#set-up-github-access). In Anthropic-hosted environments, your GitHub credentials stay encrypted on Anthropic’s servers and never enter a session’s VM. GitHub operations from the VM go through the [GitHub proxy](cloud-environments.md#github-proxy), which attaches the credential on the server side. For how `/schedule` checks repository access before creating a routine, see [Repositories and branch permissions](web-scheduled-tasks.md#repositories-and-branch-permissions). See [Connect from your terminal](web-quickstart.md#connect-from-your-terminal) for the `/web-setup` walkthrough, including what `/web-setup` stores and how to remove it. Quick web setup is an organization setting that lets members connect GitHub with `/web-setup`, skips the Claude GitHub App install prompt during browser onboarding, and has browser onboarding create the [**Default** environment](cloud-environments.md#the-default-environment) for them instead of showing the environment form. On Team and Enterprise plans it’s off by default, which hides `/web-setup`. An [Owner](../13-Enterprise-Admin/server-managed-settings.md#access-control) turns it on with the **Quick web setup** toggle at [**Admin settings \> Claude Code**](https://claude.ai/admin-settings/claude-code).
Organizations with [Zero Data Retention](zero-data-retention.md) enabled can’t use `/web-setup` or other cloud session features.
[](#move-tasks-between-terminal-and-cloud)
Move tasks between terminal and cloud
These workflows require the [Claude Code CLI](../01-Getting-Started/quickstart.md) 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 cloud. The `--cloud` flag with a task description creates a new cloud session for your current repository; with `-p` and a session ID or claude.ai/code URL it instead [queues a message into that existing session](claude-code-on-the-web.md#send-follow-ups-from-the-cli). The [Desktop app](../16-Mobile-Desktop/desktop.md#continue-in-another-surface) provides a **Continue in** menu that can send a local session to the cloud.
[](#from-terminal-to-cloud)
From terminal to cloud
Start a cloud session from the command line with the `--cloud` flag:
```python
claude --cloud "Fix the authentication bug in src/auth/login.ts"
```
This creates a new cloud session on claude.ai. The cloud VM clones your current directory’s GitHub remote at your current branch, not your local checkout, so push first if you have local commits. See [Send local repositories without GitHub](#send-local-repositories-without-github) for the cases where Claude Code uploads your local repository instead of cloning. `--cloud` works with a single repository at a time. The task runs in the cloud while you continue working locally. The older `--remote` spelling still works as a deprecated alias for `--cloud`. While the cloud container starts, the CLI shows a live checklist of setup steps, such as cloning the repository and running your [setup script](cloud-environments.md#setup-scripts). It queues messages you type during provisioning and sends them once the session is ready.
`--cloud` creates cloud sessions. `--remote-control` is unrelated: it lets you monitor and steer a local CLI session from claude.ai or the Claude app. See [Remote Control](remote-control.md).
Open the session on claude.ai or the Claude mobile app to check progress or interact directly. From there you can steer Claude, provide feedback, or answer questions as in any other conversation. If Claude asks a question and the session sits idle, you can still answer when you come back, up to [environment expiry](#environment-expired), and the session continues from your answer.
[](#tips-for-cloud-tasks)
Tips for cloud tasks
**Plan locally, execute in the cloud**: for complex tasks, start Claude in plan mode to collaborate on the approach, then send work to the cloud:
```python
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:
```python
claude --cloud "Execute the migration plan in docs/migration-plan.md"
```
**Run tasks in parallel**: each `--cloud` command creates its own cloud session that runs independently. You can start multiple tasks and they’ll all run simultaneously in separate sessions:
```python
claude --cloud "Fix the flaky test in auth.spec.ts"
claude --cloud "Update the API documentation"
claude --cloud "Refactor the logger to use structured output"
```
When a session completes, you can create a PR from claude.ai/code or [teleport](#from-cloud-to-terminal) the session to your terminal to continue working.
[](#send-local-repositories-without-github)
Send local repositories without GitHub
When you run `claude --cloud` from a repository that has no git remote, or from a github.com repository that the Claude GitHub App isn’t installed on, Claude Code bundles your local repository and uploads it directly to the cloud session. This applies even if you connected GitHub with `/web-setup`. The bundle includes your full repository history across all branches, plus uncommitted changes to tracked files. On macOS, Linux, and WSL, Claude Code leaves uncommitted changes to files named like credentials or keys out of the upload and names the files it left out. This covers `.env` files, Terraform `*.tfvars` files, and key files such as `id_rsa` and `*.pem`. The session starts with the committed version of each, or without the file if none is committed. To upload a bundle even when Claude Code would otherwise clone from the remote, set `CCR_FORCE_BUNDLE=1`:
```python
CCR_FORCE_BUNDLE=1 claude --cloud "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 if the snapshot is still too large
- Untracked files are not included; run `git add` on files you want the cloud session to see
- On macOS, Linux, and WSL, Claude Code refuses the upload when it can’t follow a git setting that affects which attribute rules apply to your files, such as `core.attributesFile` set in an included config file. The [refusal message](errors.md#the-repository-upload-cant-follow-a-git-setting) names the setting and the fix
- Sessions created from a bundle can push back to a GitHub remote only when your [GitHub connection](#github-authentication-options) has push access to that repository
[](#send-follow-ups-from-the-cli)
Send follow-ups from the CLI
Once a cloud session is running, wherever it executes, send it a follow-up message from the `claude` CLI on any machine where you’re logged in with `claude auth login`. The CLI authenticates with your Anthropic account credentials and sends no local session state, so the command doesn’t need to run from the machine that started the session, and it’s the same in every shell, including PowerShell. The command posts one message and exits:
```python
claude -p "your message" --cloud <session-id>
```
The CLI queues the message into the session and exits without waiting for a reply. Use it to steer a long-running session, queue the next step while the current one is still finishing, or send follow-ups from a [CI script](../13-Enterprise-Admin/self-hosted-environments-testing.md#run-the-test-loop). You can also pipe the message on stdin instead of passing it as an argument: `echo "your message" | claude -p --cloud <session-id>`. For `<session-id>`, pass the bare ID, such as `session_...` or `cse_...`, or the session’s `claude.ai/code/<id>` URL, with or without the scheme or query string. Find the ID in your session list at claude.ai/code.
`--cloud` requires an Anthropic account. It’s not available when Claude Code is configured for Amazon Bedrock, Google Cloud’s Agent Platform, or another third-party provider. An [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) configured only through `ANTHROPIC_BASE_URL` doesn’t count as a third-party provider for this check, but you still need to sign in with `claude auth login`. Your organization’s `allow_remote_sessions` policy must also be enabled. An Owner can turn it on in the Claude Code admin settings at claude.ai/admin-settings/claude-code.
[](#output-and-errors)
Output and errors
On success, the command prints the session ID and a link to view the session:
```python
Sent to cloud session.
Session ID: session_01DiUkqY2kzbUbDmW1w96rfi
View: https://claude.ai/code/session_01DiUkqY2kzbUbDmW1w96rfi?from=cli&m=0
```
Pass `--output-format json` for a machine-readable result: `{ok, session_id, url}` on success, or `{ok: false, session_id, error}` when the send fails, for example when the session is missing or archived. Configuration errors, such as an unsupported provider or a disabled organization policy, print to stderr without JSON. `--output-format stream-json` isn’t supported with `--cloud <session-id>`. The CLI prefixes errors with `Error: `. A failed delivery is wrapped as `failed to send message to cloud session <id>: <reason>`.
| Message | What it means |
|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Cloud sessions aren't available with <provider>. They run on Anthropic's infrastructure and require an Anthropic account.` | Claude Code is configured for a third-party provider. The message names the provider with the label your configuration uses, such as `Amazon Bedrock` or `Google Vertex AI`. Remove that provider’s configuration, for example by unsetting `CLAUDE_CODE_USE_BEDROCK`, and sign in with an Anthropic account (`claude auth login`). |
| `Cloud sessions are disabled by your organization's policy. Contact your organization admin to enable them.` | The `allow_remote_sessions` organization policy is off. |
| `Couldn't verify your organization's policy for cloud sessions. Check your network connection and try again.` | Claude Code couldn’t fetch your organization’s policy, so it refuses the send rather than assume cloud sessions are allowed. Check your network connection and retry. |
| `Attaching to an existing cloud session is not enabled for your account.` | You ran `--cloud <session-id>` without `-p`. Send the message with `claude -p "your message" --cloud <session-id>`. |
| `Session not found: <id>` | The ID or URL doesn’t match a session you can access. Check it against the session’s claude.ai/code URL. |
| `cloud session <id> is archived and cannot accept new messages` | The session has been archived. Start a new session instead. |
[](#from-cloud-to-terminal)
From cloud 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 claude.ai/code**: select **Open in \> Terminal** from the session menu to copy a command you can paste into your terminal.
- **From inside the cloud session**: type `/teleport` and Claude Code replies with the exact `claude --teleport <session-id>` command for that session, ready to run from a checkout of the repository. Requires Claude Code v2.1.223 or later in the session’s environment.
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. The terminal gets its own copy of the session: new work there stays local and doesn’t appear in the cloud session on claude.ai or the Claude mobile app. To keep steering from your phone after teleporting, start [`/remote-control`](remote-control.md) in the local session. `--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 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. If you run it from a checkout of a different repository, Claude Code shows an error that names both the session’s repository and your checkout’s. Before v2.1.219, the error didn’t name your checkout’s repository. If Claude Code can’t parse your remote into a hostname, for example an SSH host alias like `git@work:owner/repo.git`, it asks you to confirm, and accepts the checkout when the remote’s owner and repository name match the session’s repository. |
| 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` is unavailable
Teleport requires claude.ai subscription authentication. If you’re authenticated via API key, run `/login` to sign in with your claude.ai account instead. If the error names your provider instead, cloud sessions aren’t available through third-party providers; see the [error table](#output-and-errors). If you’re already signed in via claude.ai and `--teleport` is still unavailable, your organization may have disabled cloud sessions.
[](#work-with-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.
[](#take-back-a-queued-message)
Take back a queued message
If you send a message while Claude is working, the message queues until Claude reads it. To take a queued message back, click the ✕ on it. The text returns to the message box so you can edit it or send something else. If Claude has already read the message, it stays in the conversation.
[](#manage-context)
Manage context
Cloud sessions support [built-in commands](commands.md) that produce text output. Commands that only run in the terminal interface, such as `/plugin` or `/resume`, aren’t available. Commands that open a picker or panel in the terminal behave differently in cloud sessions:
- **`/model`, `/effort`, `/color`, and `/rename`**: pass the value as an argument, for example `/model sonnet`, instead of opening the terminal picker or slider. The argument forms require Claude Code v2.1.205 or later in the session’s environment and follow each command’s [availability notes](commands.md#all-commands).
- **`/fast`**: toggles [fast mode](fast-mode.md#use-fast-mode-in-cloud-sessions) for the session when fast mode is [available on your account](fast-mode.md#requirements). Requires Claude Code v2.1.271 or later in the session’s environment.
- **`/config`**: in your browser at claude.ai/code, opens the Claude Code section of your settings instead of setting a value, and text after the command, including `key=value`, is ignored. To change a setting for a cloud session, set an [environment variable](cloud-environments.md#set-environment-variables) on the environment, or in a session with one repository, commit the key to that repository’s `.claude/settings.json`. [Settings in cloud sessions](settings.md#settings-in-cloud-sessions) lists what each session reads.
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. Cloud sessions set [`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`](env-vars.md) themselves, so compaction triggers partway through the [auto-compact window](model-config.md#set-the-auto-compact-window) rather than when the window fills. That value overrides one you add in your [environment variables](cloud-environments.md#set-environment-variables), so adding the variable there doesn’t change when compaction triggers. To change the auto-compact window instead, set [`CLAUDE_CODE_AUTO_COMPACT_WINDOW`](env-vars.md) in your environment variables, or run [`/autocompact`](commands.md#all-commands) with a token count in a session where the variable isn’t set. [Subagents](../09-Agents-Patterns/sub-agents.md) work the same way they do locally. Claude can spawn them with the Agent 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](../09-Agents-Patterns/agent-teams.md) are off by default but can be enabled by adding `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` to your [environment variables](cloud-environments.md#set-environment-variables).
[](#permission-modes-in-cloud-sessions)
Permission modes in cloud sessions
You pick a cloud session’s [permission mode](permission-modes.md) from the [mode dropdown](permission-modes.md#switch-permission-modes), both when you create the task and while the session runs. When you reopen a session whose Anthropic-hosted [environment expired](#environment-expired), or send a message to a session that a self-hosted runner [released while it was idle](../13-Enterprise-Admin/self-hosted-environments-reference.md#runner-cli-flags), Claude Code resumes the session in the permission mode it was in.
[](#review-changes)
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. The diff view compares the session’s changes against its base branch by default. To compare against any other branch in the repository, select **Compare against** and pick one. Claude Code computes these diffs, including the per-file diffs shown as Claude edits, from raw git blob content, so diff drivers and `textconv` filters configured in the repository don’t apply. For a file in a repository that isn’t one of the session’s own checkouts, such as one cloned inside the workspace during the session, the per-file diff shows Claude’s edit itself rather than a git comparison. See [Review and iterate](web-quickstart.md#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](#auto-fix-pull-requests).
[](#share-sessions)
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)
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. [Claude in Slack](../14-Connectors/slack.md) sessions are automatically shared with Team visibility. 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.
[](#share-from-a-max-or-pro-account)
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**](https://claude.ai/settings/claude-code).
[](#archive-sessions)
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)
Delete sessions
Deleting a session permanently removes the session and its data. This action can’t 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)
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](https://github.com/apps/claude).
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 a cloud session**: open the session at claude.ai/code, open the CI status bar, and select **Auto-fix**
- **From your terminal**: run [`/autofix-pr`](commands.md) while on the PR’s branch. Claude Code detects the open PR with `gh`, spawns a cloud 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 session at claude.ai/code and clear the **Auto-fix** toggle, or tell Claude to stop watching the PR.
[](#how-claude-responds-to-pr-activity)
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
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)
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. Sessions your organization routes to a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) run on your own infrastructure instead, where isolation is your deployment’s responsibility
- **Network access controls**: in Anthropic-hosted environments, network access is limited by default and can be disabled. See [Network access](cloud-environments.md#network-access) for the access levels, the [default allowed domains](cloud-environments.md#default-allowed-domains), and the traffic that doesn’t go through the allowlist. In a self-hosted environment, you restrict session egress at your own network boundary. 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**: in Anthropic-hosted environments, git credentials and signing keys stay outside the sandbox, and a proxy authenticates on the session’s behalf with scoped credentials. In a self-hosted environment, your deployment supplies git credentials; see [Configure git](../13-Enterprise-Admin/self-hosted-environments-deploy.md#configure-git)
- **API credentials**: in Anthropic-hosted environments on Pro and Max plans, keys you [add to a cloud environment](cloud-environments.md#add-api-credentials) stay outside the sandbox the same way, attached to matching requests after they leave the session. A self-hosted environment doesn’t have API credentials, and Team and Enterprise plans don’t have them yet
- **Secure analysis**: code is analyzed and modified within the session’s isolated environment before creating PRs
[](#troubleshooting)
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](errors.md). 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)
Session creation failed
If a new session fails to start with `Session creation failed` or stalls at provisioning, Claude Code could not allocate a VM for the session.
- Check [status.claude.com](https://status.claude.com) for cloud session incidents
- Retry after a minute, as capacity is provisioned on demand
- Confirm your GitHub connection can reach the repository by following [No repositories appear after connecting GitHub](web-quickstart.md#no-repositories-appear-after-connecting-github)
[](#unable-to-get-organization-uuid)
Unable to get organization UUID
`claude --cloud` and `claude --teleport` require sign-in with a claude.ai account. If you authenticate with an API key, or your stored account details are stale, these commands fail with `Unable to get organization UUID` or a message that API key authentication is not sufficient. With API key authentication or stale account details, running `claude --teleport` without a session ID shows `Error loading Claude Code sessions` in the session picker instead of either message, and the same fix applies. Run `/login` to sign in with your claude.ai account, then retry the command. If the error names your provider instead, see the [error table](#output-and-errors): cloud sessions aren’t available through third-party providers.
[](#remote-control-session-expired-or-access-denied)
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`, an Owner has not enabled cloud sessions for your organization
[](#environment-expired)
Environment expired
Cloud sessions stop after a period of inactivity and the session’s VM is reclaimed. A session counts as inactive while it waits for you to approve an [MCP connector](cloud-environments.md#network-access) tool call or to sign in to an MCP server, and it can expire during that wait. Reopen the session from [claude.ai/code](https://claude.ai/code) to provision a fresh VM with your conversation history restored. Background work that was still running when the VM was reclaimed, such as subagents and shell commands, isn’t restored.
[](#limitations)
Limitations
Before relying on cloud sessions for a workflow, account for these constraints:
- **Rate limits**: cloud sessions share 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.
- **Time limits**: commands Claude runs and SessionStart hooks have default timeouts you can change, and a setup script is cached only when it finishes in roughly five minutes. See [Time limits](cloud-environments.md#time-limits)
- **Repository authentication**: you can only pull a cloud session into your terminal when you are authenticated to the same account
- **Platform restrictions**: repository cloning and pull request creation require GitHub. Self-hosted [GitHub Enterprise Server](github-enterprise-server.md) instances are supported for Team and Enterprise plans. You can send a GitLab, Bitbucket, or other non-GitHub repository to a cloud session as a [local bundle](#send-local-repositories-without-github) by setting `CCR_FORCE_BUNDLE=1`, but the session can’t push results back to that remote
- **Organization IP allowlist**: cloud sessions call the Anthropic API from Anthropic-managed infrastructure, not your network, while sessions in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) call it from your own network. If your organization has [IP allowlisting](../13-Enterprise-Admin/restrict-access-to-claude-with-ip-allowlisting.md) enabled, every Anthropic-hosted cloud session fails with an authentication error. The same applies to [Code Review](code-review.md) and to [routines](web-scheduled-tasks.md) that run on Anthropic-hosted environments; a routine routed to a self-hosted environment calls the API from your own network. Contact [Anthropic support](https://support.claude.com/) to exempt Anthropic-hosted services from your organization’s IP allowlist.
[](#related-resources)
Related resources
- [Cloud environments](cloud-environments.md): configure network access, environment variables, and setup scripts for cloud sessions
- [Projects](claude-projects.md): one conversation where Claude coordinates parallel cloud sessions on your repositories and reports back
- [Ultrareview](ultrareview.md): run a deep multi-agent code review in a cloud sandbox
- [Routines](web-scheduled-tasks.md): automate work on a schedule, via API call, or in response to GitHub events
- [Hooks configuration](../07-Hooks/hooks.md): run scripts at session lifecycle events
- [All settings](settings-reference.md): all configuration options
- [Security](../13-Enterprise-Admin/security.md): isolation guarantees and data handling
- [Data usage](../13-Enterprise-Admin/data-usage.md): what Anthropic retains from cloud sessions
- [Claude Tag](https://claude.com/docs/claude-tag/overview): an organization-managed @Claude in Slack that runs on the same cloud infrastructure
---
## Configure Hookify Rules
Source: https://github.com/anthropics/claude-code/blob/main/plugins/hookify/commands/configure.md
Path: 02-Claude-Code-CLI/claude-code-plugins-hookify-commands-configure.md
# Configure Hookify Rules
**Load hookify:writing-rules skill first** to understand rule format.
Enable or disable existing hookify rules using an interactive interface.
## Steps
### 1. Find Existing Rules
Use Glob tool to find all hookify rule files:
```
pattern: ".claude/hookify.*.local.md"
```
If no rules found, inform user:
```
No hookify rules configured yet. Use `/hookify` to create your first rule.
```
### 2. Read Current State
For each rule file:
- Read the file
- Extract `name` and `enabled` fields from frontmatter
- Build list of rules with current state
### 3. Ask User Which Rules to Toggle
Use AskUserQuestion to let user select rules:
```json
{
"questions": [
{
"question": "Which rules would you like to enable or disable?",
"header": "Configure",
"multiSelect": true,
"options": [
{
"label": "warn-dangerous-rm (currently enabled)",
"description": "Warns about rm -rf commands"
},
{
"label": "warn-console-log (currently disabled)",
"description": "Warns about console.log in code"
},
{
"label": "require-tests (currently enabled)",
"description": "Requires tests before stopping"
}
]
}
]
}
```
**Option format:**
- Label: `{rule-name} (currently {enabled|disabled})`
- Description: Brief description from rule's message or pattern
### 4. Parse User Selection
For each selected rule:
- Determine current state from label (enabled/disabled)
- Toggle state: enabled → disabled, disabled → enabled
### 5. Update Rule Files
For each rule to toggle:
- Use Read tool to read current content
- Use Edit tool to change `enabled: true` to `enabled: false` (or vice versa)
- Handle both with and without quotes
**Edit pattern for enabling:**
```
old_string: "enabled: false"
new_string: "enabled: true"
```
**Edit pattern for disabling:**
```
old_string: "enabled: true"
new_string: "enabled: false"
```
### 6. Confirm Changes
Show user what was changed:
```
## Hookify Rules Updated
**Enabled:**
- warn-console-log
**Disabled:**
- warn-dangerous-rm
**Unchanged:**
- require-tests
Changes apply immediately - no restart needed
```
## Important Notes
- Changes take effect immediately on next tool use
- You can also manually edit .claude/hookify.*.local.md files
- To permanently remove a rule, delete its .local.md file
- Use `/hookify:list` to see all configured rules
## Edge Cases
**No rules to configure:**
- Show message about using `/hookify` to create rules first
**User selects no rules:**
- Inform that no changes were made
**File read/write errors:**
- Inform user of specific error
- Suggest manual editing as fallback
---
## Using MCP Tools in Commands and Agents
Source: https://github.com/anthropics/claude-code/blob/main/plugins/plugin-dev/skills/mcp-integration/references/tool-usage.md
Path: 02-Claude-Code-CLI/claude-code-plugins-plugin-dev-skills-mcp-integration-references-tool-usage.md
# Using MCP Tools in Commands and Agents
Complete guide to using MCP tools effectively in Claude Code plugin commands and agents.
## Overview
Once an MCP server is configured, its tools become available with the prefix `mcp__plugin_<plugin-name>_<server-name>__<tool-name>`. Use these tools in commands and agents just like built-in Claude Code tools.
## Tool Naming Convention
### Format
```
mcp__plugin_<plugin-name>_<server-name>__<tool-name>
```
### Examples
**Asana plugin with asana server:**
- `mcp__plugin_asana_asana__asana_create_task`
- `mcp__plugin_asana_asana__asana_search_tasks`
- `mcp__plugin_asana_asana__asana_get_project`
**Custom plugin with database server:**
- `mcp__plugin_myplug_database__query`
- `mcp__plugin_myplug_database__execute`
- `mcp__plugin_myplug_database__list_tables`
### Discovering Tool Names
**Use `/mcp` command:**
```bash
/mcp
```
This shows:
- All available MCP servers
- Tools provided by each server
- Tool schemas and descriptions
- Full tool names for use in configuration
## Using Tools in Commands
### Pre-Allowing Tools
Specify MCP tools in command frontmatter:
```markdown
---
description: Create a new Asana task
allowed-tools: [
"mcp__plugin_asana_asana__asana_create_task"
]
---
# Create Task Command
To create a task:
1. Gather task details from user
2. Use mcp__plugin_asana_asana__asana_create_task with the details
3. Confirm creation to user
```
### Multiple Tools
```markdown
---
allowed-tools: [
"mcp__plugin_asana_asana__asana_create_task",
"mcp__plugin_asana_asana__asana_search_tasks",
"mcp__plugin_asana_asana__asana_get_project"
]
---
```
### Wildcard (Use Sparingly)
```markdown
---
allowed-tools: ["mcp__plugin_asana_asana__*"]
---
```
**Caution:** Only use wildcards if the command truly needs access to all tools from a server.
### Tool Usage in Command Instructions
**Example command:**
```markdown
---
description: Search and create Asana tasks
allowed-tools: [
"mcp__plugin_asana_asana__asana_search_tasks",
"mcp__plugin_asana_asana__asana_create_task"
]
---
# Asana Task Management
## Searching Tasks
To search for tasks:
1. Use mcp__plugin_asana_asana__asana_search_tasks
2. Provide search filters (assignee, project, etc.)
3. Display results to user
## Creating Tasks
To create a task:
1. Gather task details:
- Title (required)
- Description
- Project
- Assignee
- Due date
2. Use mcp__plugin_asana_asana__asana_create_task
3. Show confirmation with task link
```
## Using Tools in Agents
### Agent Configuration
Agents can use MCP tools autonomously without pre-allowing them:
```markdown
---
name: asana-status-updater
description: This agent should be used when the user asks to "update Asana status", "generate project report", or "sync Asana tasks"
model: inherit
color: blue
---
## Role
Autonomous agent for generating Asana project status reports.
## Process
1. **Query tasks**: Use mcp__plugin_asana_asana__asana_search_tasks to get all tasks
2. **Analyze progress**: Calculate completion rates and identify blockers
3. **Generate report**: Create formatted status update
4. **Update Asana**: Use mcp__plugin_asana_asana__asana_create_comment to post report
## Available Tools
The agent has access to all Asana MCP tools without pre-approval.
```
### Agent Tool Access
Agents have broader tool access than commands:
- Can use any tool Claude determines is necessary
- Don't need pre-allowed lists
- Should document which tools they typically use
## Tool Call Patterns
### Pattern 1: Simple Tool Call
Single tool call with validation:
```markdown
Steps:
1. Validate user provided required fields
2. Call mcp__plugin_api_server__create_item with validated data
3. Check for errors
4. Display confirmation
```
### Pattern 2: Sequential Tools
Chain multiple tool calls:
```markdown
Steps:
1. Search for existing items: mcp__plugin_api_server__search
2. If not found, create new: mcp__plugin_api_server__create
3. Add metadata: mcp__plugin_api_server__update_metadata
4. Return final item ID
```
### Pattern 3: Batch Operations
Multiple calls with same tool:
```markdown
Steps:
1. Get list of items to process
2. For each item:
- Call mcp__plugin_api_server__update_item
- Track success/failure
3. Report results summary
```
### Pattern 4: Error Handling
Graceful error handling:
```markdown
Steps:
1. Try to call mcp__plugin_api_server__get_data
2. If error (rate limit, network, etc.):
- Wait and retry (max 3 attempts)
- If still failing, inform user
- Suggest checking configuration
3. On success, process data
```
## Tool Parameters
### Understanding Tool Schemas
Each MCP tool has a schema defining its parameters. View with `/mcp`.
**Example schema:**
```json
{
"name": "asana_create_task",
"description": "Create a new Asana task",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Task title"
},
"notes": {
"type": "string",
"description": "Task description"
},
"workspace": {
"type": "string",
"description": "Workspace GID"
}
},
"required": ["name", "workspace"]
}
}
```
### Calling Tools with Parameters
Claude automatically structures tool calls based on schema:
```typescript
// Claude generates this internally
{
toolName: "mcp__plugin_asana_asana__asana_create_task",
input: {
name: "Review PR #123",
notes: "Code review for new feature",
workspace: "12345",
assignee: "67890",
due_on: "2025-01-15"
}
}
```
### Parameter Validation
**In commands, validate before calling:**
```markdown
Steps:
1. Check required parameters:
- Title is not empty
- Workspace ID is provided
- Due date is valid format (YYYY-MM-DD)
2. If validation fails, ask user to provide missing data
3. If validation passes, call MCP tool
4. Handle tool errors gracefully
```
## Response Handling
### Success Responses
```markdown
Steps:
1. Call MCP tool
2. On success:
- Extract relevant data from response
- Format for user display
- Provide confirmation message
- Include relevant links or IDs
```
### Error Responses
```markdown
Steps:
1. Call MCP tool
2. On error:
- Check error type (auth, rate limit, validation, etc.)
- Provide helpful error message
- Suggest remediation steps
- Don't expose internal error details to user
```
### Partial Success
```markdown
Steps:
1. Batch operation with multiple MCP calls
2. Track successes and failures separately
3. Report summary:
- "Successfully processed 8 of 10 items"
- "Failed items: [item1, item2] due to [reason]"
- Suggest retry or manual intervention
```
## Performance Optimization
### Batching Requests
**Good: Single query with filters**
```markdown
Steps:
1. Call mcp__plugin_api_server__search with filters:
- project_id: "123"
- status: "active"
- limit: 100
2. Process all results
```
**Avoid: Many individual queries**
```markdown
Steps:
1. For each item ID:
- Call mcp__plugin_api_server__get_item
- Process item
```
### Caching Results
```markdown
Steps:
1. Call expensive MCP operation: mcp__plugin_api_server__analyze
2. Store results in variable for reuse
3. Use cached results for subsequent operations
4. Only re-fetch if data changes
```
### Parallel Tool Calls
When tools don't depend on each other, call in parallel:
```markdown
Steps:
1. Make parallel calls (Claude handles this automatically):
- mcp__plugin_api_server__get_project
- mcp__plugin_api_server__get_users
- mcp__plugin_api_server__get_tags
2. Wait for all to complete
3. Combine results
```
## Integration Best Practices
### User Experience
**Provide feedback:**
```markdown
Steps:
1. Inform user: "Searching Asana tasks..."
2. Call mcp__plugin_asana_asana__asana_search_tasks
3. Show progress: "Found 15 tasks, analyzing..."
4. Present results
```
**Handle long operations:**
```markdown
Steps:
1. Warn user: "This may take a minute..."
2. Break into smaller steps with updates
3. Show incremental progress
4. Final summary when complete
```
### Error Messages
**Good error messages:**
```
❌ "Could not create task. Please check:
1. You're logged into Asana
2. You have access to workspace 'Engineering'
3. The project 'Q1 Goals' exists"
```
**Poor error messages:**
```
❌ "Error: MCP tool returned 403"
```
### Documentation
**Document MCP tool usage in command:**
```markdown
## MCP Tools Used
This command uses the following Asana MCP tools:
- **asana_search_tasks**: Search for tasks matching criteria
- **asana_create_task**: Create new task with details
- **asana_update_task**: Update existing task properties
Ensure you're authenticated to Asana before running this command.
```
## Testing Tool Usage
### Local Testing
1. **Configure MCP server** in `.mcp.json`
2. **Install plugin locally** in `.claude-plugin/`
3. **Verify tools available** with `/mcp`
4. **Test command** that uses tools
5. **Check debug output**: `claude --debug`
### Test Scenarios
**Test successful calls:**
```markdown
Steps:
1. Create test data in external service
2. Run command that queries this data
3. Verify correct results returned
```
**Test error cases:**
```markdown
Steps:
1. Test with missing authentication
2. Test with invalid parameters
3. Test with non-existent resources
4. Verify graceful error handling
```
**Test edge cases:**
```markdown
Steps:
1. Test with empty results
2. Test with maximum results
3. Test with special characters
4. Test with concurrent access
```
## Common Patterns
### Pattern: CRUD Operations
```markdown
---
allowed-tools: [
"mcp__plugin_api_server__create_item",
"mcp__plugin_api_server__read_item",
"mcp__plugin_api_server__update_item",
"mcp__plugin_api_server__delete_item"
]
---
# Item Management
## Create
Use create_item with required fields...
## Read
Use read_item with item ID...
## Update
Use update_item with item ID and changes...
## Delete
Use delete_item with item ID (ask for confirmation first)...
```
### Pattern: Search and Process
```markdown
Steps:
1. **Search**: mcp__plugin_api_server__search with filters
2. **Filter**: Apply additional local filtering if needed
3. **Transform**: Process each result
4. **Present**: Format and display to user
```
### Pattern: Multi-Step Workflow
```markdown
Steps:
1. **Setup**: Gather all required information
2. **Validate**: Check data completeness
3. **Execute**: Chain of MCP tool calls:
- Create parent resource
- Create child resources
- Link resources together
- Add metadata
4. **Verify**: Confirm all steps succeeded
5. **Report**: Provide summary to user
```
## Troubleshooting
### Tools Not Available
**Check:**
- MCP server configured correctly
- Server connected (check `/mcp`)
- Tool names match exactly (case-sensitive)
- Restart Claude Code after config changes
### Tool Calls Failing
**Check:**
- Authentication is valid
- Parameters match tool schema
- Required parameters provided
- Check `claude --debug` logs
### Performance Issues
**Check:**
- Batching queries instead of individual calls
- Caching results when appropriate
- Not making unnecessary tool calls
- Parallel calls when possible
## Conclusion
Effective MCP tool usage requires:
1. **Understanding tool schemas** via `/mcp`
2. **Pre-allowing tools** in commands appropriately
3. **Handling errors gracefully**
4. **Optimizing performance** with batching and caching
5. **Providing good UX** with feedback and clear errors
6. **Testing thoroughly** before deployment
Follow these patterns for robust MCP tool integration in your plugin commands and agents.
---
## Claude Code power user tips | Claude Help Center
Source: https://support.claude.com/en/articles/14554000-claude-code-power-user-tips
Path: 02-Claude-Code-CLI/claude-code-power-user-tips.md
# Claude Code power user tips
This article collects workflow tips from the Claude Code team at Anthropic. These practices cover parallel execution, planning, automation, verification, and customization—the patterns the team uses every day to ship code faster. Everyone’s setup is different, so experiment to see what works for you.
**Important:** The single most impactful tip in this guide is **verification**—giving Claude a way to check its own output. If you only adopt one practice, make it that one. See the **[Verification](#h_7dd53c5c29)** section below.
**Before you start: scope of this guide**
These are power-user patterns collected from individual engineers on the Claude Code team. As a result:
- Most commands shown here ship with Claude Code: /color and /btw are **built-in commands**, and /simplify and /loop are **bundled skills** that ship with the CLI. See the **[commands reference](commands.md)** and **[skills](../08-Plugins-Skills/skills.md)**. You can build your own skills by adding a SKILL.md file under .claude/skills/\<name\>/.
- The iMessage plugin ships in the official claude-plugins-official marketplace. Community plugins (for example the “ralph-wiggum” plugin) are not reviewed or sanctioned by Anthropic — check with your administrator before installing third-party plugins in a managed environment.
- Some capabilities—sandboxing, remote control, scheduled cloud jobs, voice—are **off by default** and may be disabled by your organization's policy. If a command or flag here returns "not available," your admin has likely not enabled it for your workspace.
Everything else in this guide works on a stock Claude Code install. When in doubt, run `/help` to see what is actually available in your session.
## Contents
[TABLE]
------------------------------------------------------------------------
## Working in parallel
### Run multiple sessions at once
The biggest productivity unlock is running 3–5 Claude sessions in parallel, each in its own git worktree. Claude Code has native worktree support built in.
- From the CLI, run `claude --worktree` (or `claude --worktree my_worktree`) to start a session in an isolated worktree. Add `--tmux` to launch in its own Tmux session.
- From the Desktop app, open the Code tab and check the worktree checkbox.
- For non-git VCS (Mercurial, Perforce, SVN), define `WorktreeCreate` and `WorktreeRemove` hooks in your `settings.json` to get the same isolation.
To stay oriented across many sessions, name your worktrees, set up shell aliases (`za`, `zb`, `zc`) to jump between them, color-code your terminal tabs, and enable terminal notifications so you know when any Claude needs your attention. Many engineers keep a dedicated “analysis” worktree just for reading logs and running queries.
### Subagents with worktree isolation
Subagents can also run in isolated worktrees, which is especially powerful for large batched changes. Add `isolation: worktree` to your agent’s frontmatter:
# .claude/agents/worktree-worker.md
---
name: worktree-worker
model: haiku
isolation: worktree
---
Then prompt naturally: *“Migrate all sync IO to async. Batch the changes and launch 10 parallel agents with worktree isolation. Each agent should test its changes end to end, then put up a PR.”*
### /batch for large migrations
The `/batch` command interviews you about a migration, then fans the work out to as many worktree agents as needed — dozens, hundreds, or more. Each agent works in isolation, tests its own changes, and creates a PR independently.
> /batch migrate src/ from JavaScript to TypeScript
------------------------------------------------------------------------
## Planning before building
### Start complex tasks in plan mode
Press **Shift+Tab** to cycle into plan mode. Pour your effort into the plan so Claude can one-shot the implementation. The typical flow is: enter plan mode → refine the plan → switch to auto-accept edits → Claude executes.
A few patterns from the team:
- Have one Claude write a plan, then spin up a second Claude to review it as a staff engineer.
- The moment something goes sideways, switch back to plan mode and re-plan rather than course-correcting mid-stream.
- After plan mode, Claude **automatically names your session** based on what you’re working on—you can also set a name upfront with `claude --name "auth-refactor"`.
### Use Opus with thinking for everything
Claude Code team’s reasoning: *“It’s the best coding model I’ve ever used, and even though it’s bigger & slower than Sonnet, since you have to steer it less and it’s better at tool use, it is almost always faster than using a smaller model in the end.”*
**The math:** less steering + better tool use = faster overall results, even with a larger model.
### Effort level
Run /effort to choose your effort level. The available levels are **low** (fewer tokens, faster), **medium**, **high** (more tokens, more intelligence), **xhigh**, **max**, and **auto** (Claude chooses per request). For complex coding and agentic work, switch to xhigh for deeper reasoning than high without the full token cost of max. Switch to max for hard debugging or architecture decisions where you want Claude to reason for as long as it needs. Max burns through usage limits faster, so activate it per session.
------------------------------------------------------------------------
## Prompting effectively
Don’t accept the first solution—push Claude to do better. A few prompts that work well:
- **“Grill me on these changes and don’t make a PR until I pass your test.”** Forces Claude to validate your understanding before shipping.
- **“Prove to me this works.”** Have Claude diff behavior between `main` and your feature branch.
- **“Knowing everything you know now, scrap this and implement the elegant solution.”** Useful after a mediocre first attempt.
Write detailed specs to reduce ambiguity before handing work off. The more specific you are, the better the output.
### /btw for side questions
While Claude is actively working, use `/btw` to ask a quick question without interrupting it. It’s single-turn with no tool calls, but has full context of the conversation.
> /btw what does the retry logic do?
------------------------------------------------------------------------
## Learning with Claude
Claude Code isn’t just for writing code—it’s a powerful learning tool when you configure it to explain and teach.
- **Enable “Explanatory” or “Learning” output style** in `/config` to have Claude explain the *why* behind changes.
- **Generate visual HTML presentations** explaining unfamiliar code.
- **Ask for ASCII diagrams** of new protocols and codebases.
- **Build a spaced-repetition skill:** explain your understanding, Claude asks follow-ups to fill gaps.
------------------------------------------------------------------------
## CLAUDE.md and memory
### Invest in your CLAUDE.md
Share a single `CLAUDE.md` file at your repo root, checked into git, with the whole team contributing. The key practice: **anytime Claude does something incorrectly, add it to CLAUDE.md** so it knows not to repeat the mistake.
After every correction, end with: *“Update your CLAUDE.md so you don’t make that mistake again.”* Claude is very good at writing rules for itself.
### @claude in Code Reviews
Install the GitHub Action with `/install-github-app`, then tag `@claude` in PR comments to add learnings to `CLAUDE.md` as part of the review:
nit: use a string literal, not ts enum @claude add to CLAUDE.md to never use enums, always prefer literal unions
This is “Compounding Engineering”—each correction makes every future session better.
### Auto-memory
Run `/memory` to configure Claude Code’s built-in memory system.
**Auto-memory** automatically saves preferences, corrections, and patterns between sessions. Memories are written to ~/.claude/projects/\<project\>/memory/ (one directory per git repo root). This is separate from your user-level ~/.claude/CLAUDE.md and project-level ./CLAUDE.md files, which you maintain by hand.
The naming maps to how REM sleep consolidates short-term memory into long-term storage.
### Advanced: Notes directory
One engineer on the team tells Claude to maintain a notes directory for every task and project, updated after every PR — then points `CLAUDE.md` at it.
------------------------------------------------------------------------
## Verification — the \#1 Tip
Giving Claude a way to verify its work will markedly improve the quality of the final result. If Claude can close the feedback loop on its own, it will iterate until the output is right.
Verification looks different per domain—bash commands, test suites, simulators, browser testing—but the principle is the same. Invest in domain-specific verification.
### The Chrome extension
For frontend work, install the Claude Code Chrome extension. Think of it like any other engineer: if you ask someone to build a website but don’t let them use a browser, will it look good? Probably not. With a browser, they’ll iterate until it does.
The team uses the Chrome extension every time they work on web code. Download it for Chrome or Edge at **[code.claude.com/docs/en/chrome](../03-IDE-Integrations/chrome.md)**.
### Desktop app for web servers
The Claude Desktop app bundles the ability to **automatically start and test web servers** in a built-in browser. You can set up something similar in CLI or VS Code using the Chrome extension, or just use the Desktop app directly.
### /simplify for Code Quality
Append `/simplify` to any prompt after making changes. It runs parallel agents that review changed code for reuse, quality, efficiency, and `CLAUDE.md` compliance—all in one pass.
> hey claude make this code change then run /simplify
------------------------------------------------------------------------
## Commands, skills, and subagents
### Skills for repeated workflows
If you do something more than once a day, turn it into a skill. Skills are checked into `.claude/skills/<name>/SKILL.md` and shared with the team (the legacy `.claude/commands/` path still works, but skills are the recommended approach). A few ideas:
- A `/techdebt` command that runs at the end of every session to find duplicated code.
- A command that syncs 7 days of Slack, GDrive, Asana, and GitHub into one context dump.
- Analytics-engineer agents that write dbt models, review code, and test in dev.
Slash commands can include **inline Bash** to pre-compute info (like `git status`) without extra model calls.
### Subagents for PR workflows
Think of subagents as automations for your most common PR workflows. Drop `.md` files into `.claude/agents/`:
.claude/agents/ build-validator.md code-architect.md code-simplifier.md verify-app.md
Each agent can have a custom name, color, tool set, allowed/disallowed tools, permission mode, and model. Set the **default agent for your main conversation** by adding `"agent"` to `settings.json` or using `claude --agent <name>`. Run `/agents` to get started.
### --agent for custom system prompts
Custom agents are a powerful primitive that often gets overlooked. Define a new agent in `.claude/agents`, then run `claude --agent=<name>`. Example of a read-only agent:
# .claude/agents/ReadOnly.md --- name: ReadOnly description: Read-only agent restricted to the Read tool only color: blue tools: Read --- You are a read-only agent that cannot edit files or run bash.
### Leveraging subagents at runtime
- **Append “use subagents”** to any request where you want Claude to throw more compute at the problem.
- **Offload individual tasks to subagents** to keep your main agent’s context window clean and focused.
- **Route permission requests to Opus via a hook** — let it scan for attacks and auto-approve the safe ones.
### Code review agents
When a PR opens, Claude can dispatch a team of agents that each focus on a different concern — logic errors, security issues, performance regressions — and post inline comments. The Anthropic team built this for themselves first; code output per engineer increased significantly and reviews were the bottleneck.
------------------------------------------------------------------------
## Hooks
Hooks let you deterministically run logic at points in the agent lifecycle. Ask Claude to add a hook to get started.
### Common hook patterns
[TABLE]
Example `PostToolUse` hook for auto-formatting:
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{ "type": "command", "command": "bun run format || true" }]
}
]
------------------------------------------------------------------------
## Permissions and safety
### Pre-approve common commands
Run `/permissions` to pre-allow common safe commands and check them into your team’s `.claude/settings.json`. This is the **recommended alternative** to skipping permissions entirely — you get fewer prompts while keeping an auditable allowlist. **Full wildcard syntax is supported**—try `"Bash(bun run *)"` or `"Edit(/docs/**)"`.
Claude Code’s permission system layers prompt-injection detection, static analysis, sandboxing, and human oversight. A small set of safe commands is pre-approved out of the box; everything you add via `/permissions` is additive to that baseline.
### Auto mode
Auto mode lets Claude make permission decisions on your behalf. Classifiers evaluate each action before it runs — safe operations get auto-approved, risky ones still get flagged. You can switch permission modes at any time during a session using **Shift+Tab**.
### Sandboxing
Run `/sandbox` to opt into Claude Code’s open-source sandbox runtime. It runs on your machine and supports both **file and network isolation**, improving safety while reducing permission prompts. Three modes are available:
- Sandbox BashTool, with auto-allow
- Sandbox BashTool, with regular permissions
- No sandbox
### Long-running tasks
For very long-running tasks, ensure Claude can work uninterrupted. Recommended approaches:
- Prompt Claude to verify with a background agent when done.
- Use an agent `Stop` hook for deterministic checks (preferred for auditable workflows).
- Use the “ralph-wiggum” community plugin.
For sandboxed environments, use `--permission-mode=dontAsk` or `--dangerously-skip-permissions` to avoid blocks.
------------------------------------------------------------------------
## Scheduled and recurring tasks
### /loop for local recurring tasks
`/loop` schedules a recurring task locally for up to 3 days at a time. A few examples the Claude Code team runs:
/loop 5m /babysit # auto-address review, rebase, shepherd PRs /loop 30m /slack-feedback # auto put up PRs for Slack feedback /loop 1h /pr-pruner # close out stale PRs
### /schedule for Cloud Jobs
Unlike `/loop`, scheduled jobs run in the **cloud** — they keep working even when your laptop is closed.
> /schedule a daily job that looks at all PRs shipped since yesterday and updates our docs based on the changes. Use the Slack MCP to message #docs-update with the changes
**Note:** Experiment with turning your most common workflows into a skill + a loop. It’s powerful.
------------------------------------------------------------------------
## Mobile and remote control
### Work from your phone
Claude Code has a **mobile app**—download the Claude app for iOS/Android and tap the Code tab. An **iMessage plugin** is also available (`/plugin install imessage@claude-plugins-official`) to send tasks from any Apple device.
### Teleport sessions between devices
Move sessions back and forth between mobile, web, desktop, and terminal:
- `claude --teleport` (or `/teleport` from inside a session) continues a cloud session on your machine.
- `/remote-control` lets you control a local session from your phone or the web.
- `claude remote-control` lets you spawn a new local session from the mobile app. *Availability: Pro, Max, Team, and Enterprise plans on CLI v2.1.51+.*
You can also enable **“Enable Remote Control for all sessions”** in `/config`.
### Claude Cowork Dispatch
Dispatch is a secure remote control for the Claude Desktop app. It can use your MCPs, browser, and computer with your permission—useful for catching up on Slack and emails, managing files, and doing things on your laptop when you’re away from it.
------------------------------------------------------------------------
## Tool integrations (MCP)
Connect Claude to your existing tools so it can search Slack, run BigQuery, grab Sentry logs, and more. Add MCP servers via claude mcp add or the "mcpServers" block in settings.json — see **[code.claude.com/docs/en/mcp](../06-MCP-Tools/General/mcp.md)** for configuration.
### Data and analytics
Ask Claude to use the `bq` CLI to pull and analyze metrics on the fly—keep a BigQuery skill checked into your codebase. The Claude Code team's take: “Personally, I haven’t written a line of SQL in 6+ months.” This works for any database that has a CLI, MCP, or API.
### Bug fixing
Enable the Slack MCP, paste a bug thread into Claude, and just say **“fix”**—zero context switching. Or say **“go fix the failing CI tests”** without micromanaging how. Point Claude at **docker logs** to troubleshoot distributed systems—it’s surprisingly capable at this.
### Plugins
Plugins bundle LSPs (available for every major language), MCPs, skills, agents, and custom hooks. Install from the official Anthropic plugin marketplace, or stand up an internal marketplace for your organization—then check the marketplace reference into `settings.json` so it’s auto-added for every developer. Run `/plugin` to get started.
------------------------------------------------------------------------
## Customizing your environment
### Terminal setup
Run `/config` to set light/dark mode and /terminal-setup to enable **Shift+Enter** for newlines in IDE terminals, Warp, or Alacritty (Apple Terminal is not supported by `/terminal-setup`). For Vim keybindings, open `/config` → Editor mode. The team recommends **Ghostty** for synchronized rendering and 24-bit color.
### Status line, color, and keybindings
- `/statusline` generates a custom status line based on your `.bashrc`/`.zshrc`—show model, directory, remaining context, cost, or anything else.
- `/color` changes the prompt input color—useful when you have 3–5 sessions open and need to tell them apart at a glance.
- `/keybindings` remaps any key. Settings live-reload and are stored in `~/.claude/keybindings.json`.
### Voice input
Voice mode is available to all users, including Claude Code Desktop and Cowork. Most of the Claude Code team's coding is done by speaking—you speak roughly 3× faster than you type, and your prompts get more detailed as a result.
- **CLI:** run `/voice` then hold the space bar
- **Desktop:** press the voice button (microphone icon)
- **iOS:** enable dictation in your system settings
- **macOS native:** hit fn×2 for system dictation in any terminal
### Web sessions
Beyond the terminal, run additional sessions on [claude.ai/code](https://claude.ai/code). Use the `&` command to background a session, or the `--teleport` flag to switch contexts between local and web.
### Output styles
Run `/config` and set an output style. **Explanatory** has Claude explain frameworks and patterns as it works (great for new codebases). **Learning** has Claude coach you through changes. You can also create **custom** styles to adjust Claude’s voice.
### Spinner verbs
It’s the little things that make Claude Code feel personal. Ask Claude to customize your spinner verbs to add to or replace the default list. Check the `settings.json` into source control to share verbs with your team.
### Customize everything
Claude Code is built to work great out of the box, but when you do customize, **check `settings.json` into git** so your team benefits too. Configuration is supported per-codebase, per-subfolder, per-user, or via enterprise-wide policies.
**By the numbers:** dozens of settings and environment variables—see the **[settings reference](settings.md)**. Use the `"env"` field in `settings.json` to avoid wrapper scripts.
------------------------------------------------------------------------
## SDK and multi-repo work
### --bare for Faster SDK Startup
By default, `claude -p` (and the TypeScript/Python SDKs) searches for local `CLAUDE.md` files, settings, and MCPs. For non-interactive usage, you usually want to specify these explicitly via `--system-prompt`, `--mcp-config`, `--settings`, etc. Add `--bare` for roughly 10× faster startup:
claude -p "summarize this codebase" \
--output-format=stream-json \
--verbose \
--bare
**Note:** This was a design oversight when the SDK was first built. In a future version, the default will flip to `--bare`. For now, opt in with the flag.
### --add-dir for multi-repo work
When working across repositories, use `--add-dir` (or `/add-dir`) to give Claude access and permissions to additional folders. Or add `"additionalDirectories"` to your team’s `settings.json` to always include them.
### Forking a session
To branch off an existing session, run `/branch` from inside it, or `claude --resume <session-id> --fork-session` from the CLI.
### Setup scripts for cloud environments
In Claude Code on web and desktop, add a **setup script** that runs before each new cloud session—install dependencies, configure settings, set environment variables. The script is skipped on resume.
------------------------------------------------------------------------
## Appendix: Quick reference
[TABLE]
------------------------------------------------------------------------
## Appendix: Related articles
[TABLE]
Claude Code ships frequently. Verify version-specific details against **[code.claude.com/docs](code-home.md)** before distributing internally.
---
## Claude Code user FAQ | Claude Help Center
Source: https://support.claude.com/en/articles/14554922-claude-code-user-faq
Path: 02-Claude-Code-CLI/claude-code-user-faq.md
# Claude Code user FAQ
August 7, 2026
Short answers to the questions that come up most at office hours, with a link to go deeper. Organized by where you are in your first few weeks.
## How to use this guide
Five sections follow the arc of a developer’s first weeks: getting started, day-to-day use, leveling up, common gotchas, privacy, and trust. Skim the section that matches where you are, or search for a specific question.
## 1. Getting started
[TABLE]
------------------------------------------------------------------------
## 2. Day-to-day use
[TABLE]
------------------------------------------------------------------------
## 3. Leveling up
[TABLE]
------------------------------------------------------------------------
## 4. Common gotchas
[TABLE]
------------------------------------------------------------------------
## 5. Privacy and trust
[TABLE]
------------------------------------------------------------------------
## Appendix: Still stuck?
[TABLE]
------------------------------------------------------------------------
## Appendix: Resource directory
[TABLE]
Claude Code ships frequently. Verify version-specific details against **[code.claude.com/docs](code-home.md)** before distributing internally.
---
## Session Memory Compaction
Source: https://github.com/anthropics/claude-cookbooks/blob/main/misc/session_memory_compaction.ipynb
Path: 02-Claude-Code-CLI/claude-cookbooks-misc-session-memory-compaction.md
# Session Memory Compaction
Long-running conversations with Claude can exceed context limits,
causing loss of important information. Whether you\'re building a coding
assistant, creative writing tool, or customer service agent, managing
session memory is critical for maintaining continuity and quality.
This cookbook teaches you how to **proactively manage session memory**
to avoid jarring context limit interruptions. Unlike reactive approaches
that wait until the context is full, you\'ll learn to build session
memory in the background so compaction is instant when needed.
**Related:** For automatic SDK-based compaction in agentic workflows,
see [Automatic Context
Compaction](https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/automatic-context-compaction.ipynb). This
cookbook focuses on manual control patterns for conversational
applications.
## Learning Objectives
By the end of this cookbook, you will be able to:
- Write effective session memory prompts that preserve critical context
across compaction events
- Implement **instant compaction** using background threading to
eliminate user wait time
- Apply prompt caching to reduce the cost of background memory updates
by \~80%
- Choose appropriate compaction strategies (traditional vs. instant)
based on your use case
:::
::: {.cell .markdown}
## Prerequisites and Setup
Before following this guide, ensure you have:
**Required Knowledge**
- Basic understanding of Claude API usage and message formatting
- Familiarity with Python threading concepts (helpful but not required)
**Required Tools**
- Python 3.11 or higher
- Anthropic API key
- Anthropic SDK
### Installation
First, install the required dependencies:
:::
::: {.cell .code vscode="{\"languageId\":\"python\"}"}
``` coconut
%%capture
%pip install -U anthropic python-dotenv
```
:::
::: {.cell .code execution_count="1" vscode="{\"languageId\":\"python\"}"}
``` coconut
import anthropic
from anthropic.types import MessageParam, TextBlockParam
from dotenv import load_dotenv
load_dotenv()
client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-5-20250929"
```
:::
:::: {.cell .code execution_count="3" vscode="{\"languageId\":\"python\"}"}
``` coconut
# Helper functions
def truncate_response(text: str, max_lines: int = 15) -> str:
"""Truncate long responses for cleaner output display."""
lines = text.strip().split("\n")
if len(lines) <= max_lines:
return text
return "\n".join(lines[:max_lines]) + f"\n... ({len(lines) - max_lines} more lines)"
def remove_thinking_blocks(text: str) -> tuple[str, str]:
"""Remove <think>...</think> blocks from the text."""
import re
matches = re.findall(r"<think>.*?</think>", text, flags=re.DOTALL)
cleaned = re.sub(r"<think>.*?</think>\s*", "", text, flags=re.DOTALL).strip()
return cleaned, "".join(matches)
def add_cache_control(messages: list[dict]) -> list[MessageParam]:
"""Add cache_control to the last user message for prompt caching.
For prompt caching to work, the message prefix structure must be identical between requests.
All messages are converted to list format for consistency, and cache_control is placed on
the last user message to match the standard API call pattern.
"""
cached_messages: list[MessageParam] = []
last_user_idx = None
# Find last user message index
for i, msg in enumerate(messages):
if msg["role"] == "user":
last_user_idx = i
for i, msg in enumerate(messages):
content = msg["content"]
text = content if isinstance(content, str) else content[0]["text"]
content_block: TextBlockParam = {"type": "text", "text": text}
if i == last_user_idx:
content_block["cache_control"] = {"type": "ephemeral"}
cached_messages.append({"role": msg["role"], "content": [content_block]})
return cached_messages
def estimate_tokens(text: str) -> int:
"""Rudimentary token estimation: 1 token per 4 characters."""
return len(text) // 4
```
::: {.output .stream .stderr}
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:676: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
return Regex(regex, options)
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:457: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
result = add_action(grammar, unpack).parseWithTabs().transformString(text)
:::
::::
::: {.cell .code execution_count="4" vscode="{\"languageId\":\"python\"}"}
``` coconut
SESSION_MEMORY_PROMPT = """
Compress the conversation into a structured summary
that preserves all information needed to continue work seamlessly. Optimize for the assistant's
ability to continue working, not human readability.
<analysis-instructions>
Before generating your summary, analyze the transcript in <think>...</think> tags:
1. What did the user originally request? (Exact phrasing)
2. What actions succeeded? What failed and why?
3. Did the user correct or redirect the assistant at any point?
4. What was actively being worked on at the end?
5. What tasks remain incomplete or pending?
6. What specific details (IDs, paths, values, names) must survive compression?
</analysis-instructions>
<summary-format>
## User Intent
The user's original request and any refinements. Use direct quotes for key requirements.
If the user's goal evolved during the conversation, capture that progression.
## Completed Work
Actions successfully performed. Be specific:
- What was created, modified, or deleted
- Exact identifiers (file paths, record IDs, URLs, names)
- Specific values, configurations, or settings applied
## Errors & Corrections
- Problems encountered and how they were resolved
- Approaches that failed (so they aren't retried)
- User corrections: "don't do X", "actually I meant Y", "that's wrong because..."
Capture corrections verbatim—these represent learned preferences.
## Active Work
What was in progress when the session ended. Include:
- The specific task being performed
- Direct quotes showing exactly where work left off
- Any partial results or intermediate state
## Pending Tasks
Remaining items the user requested that haven't been started.
Distinguish between "explicitly requested" and "implied/assumed."
## Key References
Important details needed to continue:
- Identifiers: IDs, paths, URLs, names, keys
- Values: numbers, dates, configurations, credentials (redacted)
- Context: relevant background information, constraints, preferences
- Citations: sources referenced during the conversation
</summary-format>
<preserve-rules>
Always preserve when present:
- Exact identifiers (IDs, paths, URLs, keys, names)
- Error messages verbatim
- User corrections and negative feedback
- Specific values, formulas, or configurations
- Technical constraints or requirements discovered
- The precise state of any in-progress work
</preserve-rules>
<compression-rules>
- Weight recent messages more heavily—the end of the transcript is the active context
- Omit pleasantries, acknowledgments, and filler ("Sure!", "Great question")
- Omit system context that will be re-injected separately
- Keep each section under 500 words; condense older content to make room for recent
- If you must cut details, preserve: user corrections > errors > active work > completed work
</compression-rules>
"""
```
:::
::: {.cell .markdown}
### Code example using traditional compacting
In traditional compaction, you generate one summary once the token
threshold is reached. Traditional compaction is slow: when you hit the
context limit, you wait for a summary.
:::
::: {.cell .markdown}
TRADITIONAL COMPACTION (slow)
─────────────────────────────
Turn 1 → Turn 2 → Turn 3 → ... → Turn N → CONTEXT FULL!
│
▼
┌─────────────────┐
│ Generate summary│
│ ( USER WAITS !) │
└─────────────────┘
│
▼
Continue
:::
:::: {.cell .code execution_count="5" vscode="{\"languageId\":\"python\"}"}
``` coconut
import time
class TraditionalCompactingChatSession:
"""Traditional chat session with compaction after the fact."""
def __init__(self, system_message="You are a helpful assistant", context_limit: int = 10000):
self.system_message = system_message
self.context_limit = context_limit # the point at which the conversation is compacted so it does not exceed model limits.
self.messages = []
self.current_context_window_tokens = 0
self.summary = None
def chat(self, user_message: str) -> tuple[str, anthropic.types.Usage]:
# In traditional compaction, we check if we need to compact when the user sends a message. NOT IDEAL!
if self.current_context_window_tokens >= self.context_limit:
print(
f"\n🧹 Context window at {self.current_context_window_tokens} tokens. Limit exceeded, compacting session memory..."
)
self.compact() # compacts everything before the new user message
self.messages.append({"role": "user", "content": user_message})
print(f"\nUser: {user_message}")
response = client.messages.create(
model=MODEL,
max_tokens=3500,
system=self.system_message,
messages=add_cache_control(self.messages),
)
assistant_message = response.content[0].text
self.messages.append({"role": "assistant", "content": assistant_message})
print(f"\nAssistant: \n{truncate_response(assistant_message, max_lines=15)}")
# approximate current token count in the conversation before the next user message
cache_read = getattr(response.usage, "cache_read_input_tokens", 0) or 0
total_input = response.usage.input_tokens + cache_read
self.current_context_window_tokens = total_input + response.usage.output_tokens
print(
f"Input={total_input:,}, Prompt cached used= {cache_read > 0} | "
f"Output={response.usage.output_tokens:,} | "
f"Messages={len(self.messages)}"
)
return assistant_message, response.usage
def compact(self) -> None:
start_time = time.perf_counter()
response = client.messages.create(
model=MODEL,
max_tokens=5000,
system=self.system_message, # Same as main chat for cache sharing
messages=add_cache_control(self.messages)
+ [{"role": "user", "content": SESSION_MEMORY_PROMPT}],
)
elapsed = time.perf_counter() - start_time
# Generate new summary message
self.summary, removed_text = remove_thinking_blocks(
response.content[0].text
) # clean up any <think> blocks because they are not needed in the session memory
approximate_summary_tokens = response.usage.output_tokens - round(
len(removed_text) / 4
) # rough estimate of tokens removed from summary
# Replace prior messages with new summary message
self.messages = [
{
"role": "user",
"content": f"""This session is being continued from a previous conversation. Here is the session memory: {self.summary}.Continue from where we left off.""",
}
]
# Show token reduction if we just compacted
reduction = self.current_context_window_tokens - approximate_summary_tokens
pct = (reduction / self.current_context_window_tokens) * 100
print(f"\n{'-' * 60}")
print("📝 New session memory created.")
print(
f"✅ Tokens reduced: {self.current_context_window_tokens:,} → {approximate_summary_tokens:.0f} ({reduction:,} tokens saved, {pct:.0f}% reduction)"
)
print(f"⏱️ Compaction time: {elapsed:.2f}s (user waiting...)")
print(f" Cache used: {getattr(response.usage, 'cache_read_input_tokens', 0) > 0}")
print(f"{'-' * 60}")
# Update token count to reflect compacted state
self.current_context_window_tokens = approximate_summary_tokens
```
::: {.output .stream .stderr}
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:403: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
grammar.streamline()
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:457: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
result = add_action(grammar, unpack).parseWithTabs().transformString(text)
:::
::::
::: {.cell .markdown}
Below we simulate a conversation between an author and an LLM that helps
write stories.
:::
::: {.cell .code execution_count="6" vscode="{\"languageId\":\"python\"}"}
``` coconut
SYSTEM_PROMPT = """
You are a short story writer who helps authors develop their ideas into compelling narratives.
## What You Do
**Plot Development**
- Help authors work through story structure, pacing, and narrative arc
- Identify plot holes, inconsistencies, or missed opportunities
- Suggest ways to raise stakes, add tension, or deepen conflict
- Brainstorm twists, resolutions, and scene transitions
**Character Development**
- Develop backstories, motivations, and internal conflicts
- Ensure characters have distinct voices and consistent behavior
- Explore character relationships and how they drive the plot
- Help authors understand what their characters want vs. what they need
**Drafting**
- Write short stories or scenes based on the author's ideas and direction
- Match tone, genre conventions, and stylistic preferences
- Show rather than tell when bringing scenes to life
- Craft dialogue that reveals character and advances plot
## How You Work
- You are the lead writer. When you disagree with a creative choice, say so respectfully, but ultimately defer to what the author wants.
- DO NOT ask the user to provide more context or clarify their request. Assume you have enough information to proceed.
"""
```
:::
:::: {.cell .code execution_count="7" vscode="{\"languageId\":\"python\"}"}
``` coconut
session = TraditionalCompactingChatSession(system_message=SYSTEM_PROMPT)
# Simulated conversation
messages = [
"I want to create a story about a young detective solving a mysterious case in a small town. Generate 3 well thought out plot ideas for me to consider.",
"I don't like those ideas, can you think of one plot something more unique and unexpected?",
"Ok I like it. Can you help me develop the main character's backstory and motivations?",
"Can you draft a detailed outline for the story, breaking it down into chapters and key events?",
"Can you draft me a first chapter based on the plot and character ideas we've discussed so far? Make it around 2,000 words.",
"Can you draft a second chapter that builds on the first one, introducing a new twist in the mystery?",
]
print("Starting conversation...\n")
turn_count = 0
for _i, message in enumerate(messages, 1):
turn_count += 1
print(f"==============================================\nTurn {turn_count}:\n")
response, usage = session.chat(message)
```
::: {.output .stream .stdout}
Starting conversation...
==============================================
Turn 1:
User: I want to create a story about a young detective solving a mysterious case in a small town. Generate 3 well thought out plot ideas for me to consider.
Assistant:
# Three Mystery Plot Ideas
## 1. **The Vanishing Choir**
**Setup:** In the sleepy town of Millbrook, the entire church choir—twelve people ranging from teenagers to retirees—disappears during their weekly Thursday night practice. The church was locked from the inside, their belongings left behind, including phones and car keys. No signs of struggle, no broken windows. Just an empty sanctuary and sheet music scattered across the floor.
**The Twist:** Your young detective discovers the choir members didn't disappear—they're hiding. Twenty years ago, they witnessed the town's beloved mayor commit a hit-and-run that killed a drifter. They stayed silent, bound by threats and their own complicity. Now the mayor is dying and has hired someone to ensure his secret dies with him. The choir staged their own disappearance to draw attention and finally confess, but the detective must figure out who they're hiding from before the killer finds them first.
**Why it works:** Small-town secrets, a ticking clock, and the moral complexity of people who aren't quite innocent or guilty. The locked-room mystery becomes a desperate act of exposure rather than concealment.
---
## 2. **The Memory Thief**
**Setup:** Elderly residents in Hartwood are reporting identical "robberies"—but nothing is actually stolen. Instead, they insist specific memories have been taken: a first kiss, a wedding day, the birth of a child. The police dismiss it as dementia until the detective notices a pattern: all victims visited the same new "reminiscence therapist" who uses experimental techniques to help seniors preserve their memories before they fade.
... (18 more lines)
Input=317, Prompt cached used= False | Output=852 | Messages=2
==============================================
Turn 2:
User: I don't like those ideas, can you think of one plot something more unique and unexpected?
Assistant:
# **The Cartographer's Grave**
**Setup:** Your young detective arrives in the mountain town of Ridgeway to investigate what seems like a prank: someone has been systematically correcting the town's street signs, storefront addresses, and property markers—changing them by just one or two numbers. The post office is going insane. Mail is being misdelivered. Emergency services are getting lost. But here's the thing: the "corrections" match a 150-year-old town map that was supposedly drawn incorrectly by a disgraced surveyor who was run out of town and buried in an unmarked grave.
**The Investigation:** The detective discovers the old surveyor wasn't wrong—he was *right*. The town founders deliberately falsified all records after his death, shifting every address, every property line, every boundary marker. Why? Because the real map would reveal that the town's most valuable land—now home to the founding families' estates, the town hall, the historic church—was actually purchased from a Native American family who were supposed to retain mineral rights and a percentage of all profits in perpetuity.
**The Twist:** The person "correcting" the signs isn't a descendant of the surveyor or the Native family. It's a twelve-year-old girl with terminal cancer who found the original map in her grandmother's attic. She's not seeking revenge or restitution—she just became obsessed with the idea that the whole town has been living a lie written into the ground itself. Before she dies, she wants the truth to physically exist in the world, even if no one acknowledges it. She's been sneaking out at night with a screwdriver and homemade signs.
**The Real Mystery:** The detective must decide what to do when they realize that "solving" the case—stopping the girl and restoring the false addresses—means choosing comfortable order over inconvenient truth. Meanwhile, members of the founding families are getting desperate to stop the corrections before anyone looks too closely at land deeds, and the girl's nightly trips are getting increasingly dangerous.
**Why it works:** It subverts the detective genre by making the "crime" an act of radical honesty. The mystery isn't whodunit—it's what truth is worth when it would destroy an entire community's foundation. The villain isn't the child or even really the founding families—it's the town itself, built on a literal lie. And your detective can't punch or outwit their way out of a moral knot.
Input=1,191, Prompt cached used= False | Output=544 | Messages=4
==============================================
Turn 3:
User: Ok I like it. Can you help me develop the main character's backstory and motivations?
Assistant:
# The Detective: Building Your Protagonist
## Core Identity
Let's call her **Nora Winters** (adjust the name as you prefer). She's 26 years old, which makes her young enough to be underestimated but old enough to have scars.
## Backstory
**The Personal Lie:** Nora grew up in a different small town where her father was the police chief—respected, beloved, the kind of man who coached Little League and knew everyone's name. When she was sixteen, she discovered he'd been planting evidence on suspects for years. Not major crimes—small-town stuff. A little weed here, stolen property there. Just enough to "help" cases along when he "knew" someone was guilty but couldn't prove it.
She confronted him. He told her the truth was "complicated," that sometimes you have to bend the rules to protect people, that the town trusted him to keep them safe and he delivered results. He made her complicit with his confession—if she exposed him, she'd destroy their family, his legacy, the town's faith in law enforcement.
She stayed silent. For two years, she carried it like a stone in her chest.
**The Breaking Point:** At eighteen, one of her father's frame jobs went wrong. A kid he planted drugs on—a 19-year-old with priors who was actually clean this time—panicked during arrest and ran. Got hit by a car. Died in the street.
... (50 more lines)
Input=1,758, Prompt cached used= False | Output=1,193 | Messages=6
==============================================
Turn 4:
User: Can you draft a detailed outline for the story, breaking it down into chapters and key events?
Assistant:
# **The Cartographer's Grave: Story Outline**
## **ACT ONE: The Map Doesn't Match the Territory**
### **Chapter 1: Arrival**
- Nora arrives in Ridgeway on a grey October morning, six-hour drive from the city
- Establishes the town: population 3,200, nestled in mountain valley, tourism from fall foliage and "historic charm"
- She meets Town Manager **Gerald Vance** (55, anxious, sweating through his shirt despite the cold) at town hall
- He explains the crisis: for three weeks, someone's been changing street signs and address numbers—small changes, but creating chaos
- Mail misdelivered, ambulance went to wrong house (patient survived, barely), legal documents being contested
- Shows her examples: the church changed from 847 Oak Street to 843 Oak, the post office from 1215 Main to 1219 Main
- Gerald thinks it's vandalism, wants her to catch whoever's doing it quickly and quietly
- **Key detail:** Nora notices all the "corrections" subtract or add small, specific numbers—not random
### **Chapter 2: The Town's Memory**
... (160 more lines)
Input=2,973, Prompt cached used= False | Output=3,500 | Messages=8
==============================================
Turn 5:
User: Can you draft me a first chapter based on the plot and character ideas we've discussed so far? Make it around 2,000 words.
Assistant:
# **Chapter 1: Arrival**
The town of Ridgeway materialized from the fog like a photograph developing in reverse—sharp edges first, then the softer details filling in around them. Church steeple. Water tower. The downtown strip with its brick facades and hand-painted signs promising antiques, locally roasted coffee, genuine mountain crafts. Nora Winters took it all in through rain-spattered windshield glass, her Honda's wipers beating a rhythm that had become hypnotic somewhere around hour five of the drive.
Small towns always looked the same in October. Like they were apologizing for something.
She followed Main Street through the heart of downtown—two blocks of calculated charm before the road narrowed and climbed into the residential neighborhoods climbing the mountain's flank. The GPS on her phone had lost signal fifteen minutes ago, but she didn't need it. Town hall would be near the center, probably the biggest building on the main drag, probably with a flag and that particular kind of municipal architecture that tried too hard to look historic.
She was right on all counts.
Ridgeway Town Hall occupied a corner lot with the self-importance of a building that had watched the world change and declined to participate. Red brick, white columns, a bronze plaque declaring it built in 1889 and placed on the National Register in 1976. The flag snapped in the wind. Rain pooled in the uneven sidewalk leading to the entrance.
Nora parked on the street, grabbed her messenger bag, and made the dash to the covered entrance. The door was heavier than it looked—solid oak, brass hardware—and opened into the particular smell of old public buildings: lemon polish, ancient radiator heat, and paper slowly yellowing in filing cabinets.
A woman at the reception desk looked up from her computer. Sixty-something, reading glasses on a beaded chain, cardigan against the over-aggressive heating system. Her smile was professional and tired in equal measure.
... (118 more lines)
Input=6,509, Prompt cached used= False | Output=3,073 | Messages=10
==============================================
Turn 6:
User: Can you draft a second chapter that builds on the first one, introducing a new twist in the mystery?
Assistant:
# **Chapter 2: The Town's Memory**
Nora woke at six to the sound of rain that had never really stopped, just paused to gather its strength. She'd fallen asleep at the small desk by the window, tablet still glowing with Gerald's documentation, her neck complaining about the angle she'd maintained for however many hours.
The numbers were still dancing behind her eyes. She'd spent half the night building spreadsheets, mapping the changes, looking for the pattern Gerald had sensed but couldn't articulate. And she'd found it—or the beginning of it. Every changed address was in the older part of town, pre-1900 construction. Every change was small but specific: sometimes adding four, sometimes subtracting two, once adding seven. Not random. Definitely not random.
She showered, changed into clean jeans and a sweater, and followed the smell of coffee downstairs.
The dining room was small and warmly lit, with four tables covered in white cloth. An older man sat alone by the window reading a newspaper—actual paper, folded precisely. A younger couple occupied another table, speaking in low voices over their phones. Tourists, Nora guessed, based on the hiking boots and Patagonia fleeces.
A sideboard held coffee, tea, juice, and a modest breakfast spread. Nora filled a mug and took a table in the corner where she could see the room and the street beyond.
Dolores appeared from what must have been the kitchen, carrying a plate of scrambled eggs and toast. She set it in front of the man with the newspaper without being asked, received a grunt of acknowledgment, and crossed to Nora's table.
"You look like you didn't sleep much."
... (171 more lines)
Input=9,606, Prompt cached used= True | Output=3,241 | Messages=12
:::
::::
::: {.cell .markdown}
This is a long conversation with several turns. You\'ll notice a few
things here:
Prompt caching: You\'ll notice here that the input tokens eventually
grew to a point where prompt caching was used (turn 6). This helps
reduce costs and speed as these conversations grow!
:::
::: {.cell .markdown}
On the next turn, we are going to hit our 10K context window limit,
which triggers compaction:
:::
:::: {.cell .code execution_count="8" vscode="{\"languageId\":\"python\"}"}
``` coconut
response, usage = session.chat("Propose a title for the book")
```
::: {.output .stream .stdout}
🧹 Context window at 12847 tokens. Limit exceeded, compacting session memory...
------------------------------------------------------------
📝 New session memory created.
✅ Tokens reduced: 12,847 → 1526 (11,321 tokens saved, 88% reduction)
⏱️ Compaction time: 41.42s (user waiting...)
Cache used: True
------------------------------------------------------------
User: Propose a title for the book
Assistant:
Based on the story's core themes and imagery, here are my title proposals:
## Primary Recommendation
**The Cartographer's Daughter**
This works on multiple levels:
- Emma is metaphorically Amos Frost's "daughter" in mission—inheriting and completing his work
- Patricia (literal descendant of Frost's assistant) becomes Emma's accomplice
- Evokes the weight of inheritance, legacy, and what we pass down
- "Cartographer" immediately signals the map/truth theme
- Has literary gravitas appropriate for the story's tone
## Alternates
... (20 more lines)
Input=1,813, Prompt cached used= False | Output=328 | Messages=3
:::
::::
::: {.cell .markdown}
You\'ll notice here that it took **over 40 seconds** for the agent to
compact the conversation. Because we used traditional compaction, the
user would be waiting on Claude to compact the conversation, which is
not an ideal user experience.
Below you can see the result of the compaction. It captures the key
elements of conversation in less than 2K tokens.
:::
:::: {.cell .code execution_count="9" vscode="{\"languageId\":\"python\"}"}
``` coconut
print(session.summary)
```
::: {.output .stream .stdout}
## User Intent
Create short story about young detective solving mysterious case in small town. Initially requested "3 well thought out plot ideas." Rejected first batch as not unique enough, requested "something more unique and unexpected." Accepted "The Cartographer's Grave" concept. Then requested: character backstory/motivations development, detailed chapter outline, and drafted chapters.
## Completed Work
**Approved Plot: "The Cartographer's Grave"**
- Ridgeway (pop. 3,200, mountain town) experiencing systematic address changes
- 12-year-old Emma Lancaster (terminal brain cancer) changing signs at night to match 1874 surveyor Amos Frost's original map
- Frost was "disgraced," replaced by Marcus Bellamy (founding family) in 1875 re-survey
- Real conspiracy: Bellamy survey deliberately shifted property lines 200-400 feet east to steal valuable land from Pequawket family (Native American), who had mineral rights + 15% revenue contract
- Emma found Frost's materials in grandmother's attic (Patricia Lancaster, granddaughter of Samuel Lancaster—Frost's assistant who bought his effects)
- Emma's motivation: not justice, but existential—wants to matter, leave truth behind before dying
- Resolution: Town acknowledges historical fraud via memorial/fund, addresses stay changed, Emma dies knowing truth survived
**Main Character: Nora Winters**
- Age 26, private investigator for rural cases firm
- Backstory: Father was police chief who planted evidence for years. At 16 she discovered it, stayed silent 2 years. At 18, a framed kid died fleeing arrest. She exposed father to state police. Father forced into retirement but kept reputation. Family estranged, won't speak to her.
- Motivation: Prove truth always matters, atone for 2 years of silence
- Fatal flaw: Prioritizes truth over mercy, can be self-righteous
- Arc: Must learn truth and justice aren't always same thing
**Supporting Characters**
- Gerald Vance (55, town manager, anxious)
- Dolores Chen (68, Ridgeway Inn owner, knows everything)
- Ruth Bellamy (72, historical society president, descendant of Marcus Bellamy)
- Sheriff Tom Whitlock (50, third-generation sheriff, dismissive)
- Emma Lancaster (12, dying of brain cancer, changing signs)
- Patricia Lancaster (64, Emma's grandmother, retired town clerk, Samuel Lancaster's descendant)
- James Pequawket (58, teacher, lives two towns over, descendant)
- Samuel Lancaster (Amos Frost's 1874 assistant, bought Frost's effects after death)
- Amos Frost (surveyor, accurate 1874 map, died 1889 in sanitarium, unmarked grave)
**16-Chapter Outline with Epilogue Created**
- Act 1 (Ch 1-4): Nora arrives, discovers pattern, identifies Emma via dropped notebook
- Act 2 (Ch 5-9): Confronts Emma, discovers Frost's journal/map at Lancaster house, uncovers full conspiracy
- Act 3 (Ch 10-15): Town pressures Nora, founding families threaten charges against Emma, Nora proposes compromise (memorial + fund vs. property transfers), Emma dies December 3rd
- Epilogue (Ch 16): Six months later, Nora receives Emma's notebook showing new project mapping unmarked graves
**Chapter 1 Drafted (~2000 words)**
- Nora arrives Ridgeway in rain, meets Gerald Vance at town hall
- Gerald explains crisis: 37 locations, professional signs, started October 2nd, systematic pattern
- Key detail: Changes are small (1-5 numbers) but precise, affecting only pre-1900 buildings
- Nora checks into Ridgeway Inn, meets Dolores Chen
- Dolores reveals her address changed October 3rd: 843 to 847 Oak Street, left new sign up to "adapt"
- Dolores warns: "Be careful asking questions here. Not everyone appreciates having their complications examined."
**Chapter 2 Drafted**
- Nora analyzes data overnight, identifies pattern: all changes in pre-1900 areas
- Breakfast at inn, confronted by Howard Marsh (70s, opposed to investigation)
- Visits library, meets Jess (librarian, 30, supportive)
- Discovers in basement archives: changed addresses match 1875 town plat exactly
- Jess reveals history: Amos Frost surveyed 1874, deemed "inaccurate," dismissed. Marcus Bellamy (Ruth's great-great-grandfather) re-surveyed 1875 (official record). Frost's survey "destroyed years ago."
- Text from Jess's partner Sarah: Frost died 1889 in sanitarium, pauper's grave. Effects purchased by Samuel Lancaster at 1847 Oak Street.
- **Chapter ends with revelation**: 1847 Oak = current "corrected" address of Ridgeway Inn (officially 843). Frost's materials likely still at inn. "The question was who in that building knew they existed, and why they'd decided—after more than a century of silence—that the truth needed to be rewritten into the town's streets."
## Errors & Corrections
User explicitly rejected first 3 plot ideas: "The Vanishing Choir," "The Memory Thief," "The Lighthouse Keeper's Daughter"—deemed not unique/unexpected enough.
## Active Work
Chapter 2 completed. Story ready to continue with Chapter 3, which per outline should cover "The Pattern" where Nora stakes out locations and first spots Emma changing a sign.
## Pending Tasks
Draft chapters 3-16 and epilogue per approved outline.
## Key References
**Critical addresses**: 843 Oak Street (official) / 847 Oak Street (corrected) = Ridgeway Inn location, Samuel Lancaster's 1874 address
**Timeline**: October 2nd changes start, story current timeframe October, Emma dies December 3rd, epilogue six months later
**The fraud mechanics**: Bellamy survey shifted all property lines 200-400 feet east, making Pequawket parcel appear worthless hillside while valuable land (now Bellamy estate, town hall, church) became "legitimately" owned by founding families
**Pequawket contract terms**: Mineral rights in perpetuity + 15% of all property values/business revenues from specified parcel
:::
::::
::: {.cell .markdown}
## Instant Compaction
With **Instant compaction** the session memory is PROACTIVELY generated
once a soft token threshold is reached.
Once the user triggers a compaction or a hard limit is reached, the
summary is already available, so the user doesn\'t need to wait.
Result: Instant compaction, no waiting.
:::
::: {.cell .markdown}
SESSION MEMORY COMPACTION (instant)
────────────────────────────────────
Turn 1 → Turn 2 → ... → Turn K → Turn K+1 → ... → Turn N → .. → CONTEXT FULL!
│ │ │
(soft token threshold met: (update │
initialize session memory) trigger) │
│ │
│ │ │
▼ ▼ │
┌────────┐ ┌────────┐ │
│ Create │ │ Update │ │
│ memory │ (background) │ memory │ │
└────────┘ └────────┘ │
│ │ │
▼ ▼ ▼
📝 session-memory.md ──────────────────► INSTANT SWAP!
(continuously updated)
**Update triggers:** The first summary is generated after the initial
soft token limit. Updates can be triggered after every subsequent turn,
or at periodically at natural breakpoints intervals (e.g. every \~10k
tokens or 3+ tool calls).
:::
::: {.cell .markdown}
This `InstantCompactingChatSession` class uses **threading** for
background execution:
1. **`threading.Thread`** - runs memory updates in background without
blocking
2. **Thread-safe state** - uses `threading.Lock` to safely update
shared memory
3. **Daemon threads** - background work doesn\'t prevent program exit
4. **Instant compaction** - when context is full, just swap in the
pre-built memory
:::
:::: {.cell .code execution_count="10" vscode="{\"languageId\":\"python\"}"}
``` coconut
import threading
import time
class InstantCompactingChatSession:
"""
Maintains session memory via incremental background updates.
Key insight: By updating memory in the background after each turn,
the summary is already ready when compaction is needed - instant swap!
"""
def __init__(
self,
system_message="You are a helpful assistant",
context_limit: int = 12000,
min_tokens_to_init: int = 7500,
min_tokens_between_updates: int = 2000,
):
# Thresholds
self.context_limit = context_limit # the point at which the conversation is compacted so it does not exceed model limits
self.min_tokens_to_init = min_tokens_to_init # tokens needed to trigger initial memory creation; note this happens PROACTIVELY in background unlike traditional compaction
self.min_tokens_between_updates = min_tokens_between_updates # tokens needed to trigger memory update. only comes into play after initial memory is created and additional compaction (memory update) is needed after that
# Conversation state
self.system_message = system_message
self.messages = []
self.current_context_window_tokens = 0
# Session memory state
self.session_memory = None # this is the compacted conversation in session memory; for the demo we are storing this in memory, but in production you would write to session_memory.md file
self.last_summarized_index = (
0 # The index of the last message included in the session memory
)
self.tokens_at_last_update = 0 # To track tokens at last memory update and see if enough new tokens have been added to trigger another update
# Background update tracking
self._update_thread: threading.Thread | None = None
self.last_update_time = None
self._lock = threading.Lock()
def chat(self, user_message: str) -> tuple[str, anthropic.types.Usage, str | None]:
"""Process a chat turn with background session memory updates."""
if self.current_context_window_tokens + estimate_tokens(user_message) >= self.context_limit:
self.compact() # note that when this is triggered, the compaction has already been created and is just swapped in instantly
self.messages.append({"role": "user", "content": user_message})
response = client.messages.create(
model=MODEL,
max_tokens=3500,
system=self.system_message,
messages=add_cache_control(self.messages),
)
assistant_message = response.content[0].text
self.messages.append({"role": "assistant", "content": assistant_message})
# Calculate token usage including cache
cache_read = getattr(response.usage, "cache_read_input_tokens", 0) or 0
total_input = response.usage.input_tokens + cache_read
# Update context window tokens (includes cached tokens since they still count toward context)
self.current_context_window_tokens = total_input + response.usage.output_tokens
# KEY DIFFERENCE: Trigger background memory update if needed proactively, before compaction is needed
background_status = None
if self._should_init_memory() or self._should_update_memory():
self._trigger_background_update()
background_status = "initializing" if self.session_memory is None else "updating"
# Return usage info with cache stats
return assistant_message, response.usage, background_status
# Helper methods to determine when to init session memory
def _should_init_memory(self) -> bool:
return (
self.session_memory is None
and self.current_context_window_tokens >= self.min_tokens_to_init
)
# Helper method to determine if memory should be updated
def _should_update_memory(self) -> bool:
if self.session_memory is None:
return False
tokens_since = self.current_context_window_tokens - self.tokens_at_last_update
return tokens_since >= self.min_tokens_between_updates
# Methods to create initial session memory
def _create_session_memory(self, messages: list[dict]) -> str:
"""Generate initial session memory from messages."""
# Put compaction instructions in user message to share cache with main chat
compaction_messages = [{"role": "user", "content": SESSION_MEMORY_PROMPT}]
response = client.messages.create(
model=MODEL,
max_tokens=5000,
system=self.system_message, # Same as main chat for cache sharing
messages=add_cache_control(messages) + compaction_messages,
)
summary, _ = remove_thinking_blocks(
response.content[0].text
) # clean up any <think> blocks because they are not needed in the session memory
print(
f" [Background] Initial session memory created. Cache hit={getattr(response.usage, 'cache_read_input_tokens', 0) > 0}"
)
return summary
def _update_session_memory(self, new_messages: list[dict]) -> str:
"""Update existing session memory with new messages. In practice, you may want to do this via file edit rather than full re-generation. But for demo purposes we do full regeneration here."""
# Put compaction instructions in user message to share cache with main chat
compaction_update_messages = [
{
"role": "user",
"content": SESSION_MEMORY_PROMPT
+ f"""There is an existing session memory: {self.session_memory}. Return the entire session memory with updates to reflect new messages.""",
}
]
response = client.messages.create(
model=MODEL,
max_tokens=5000,
system=self.system_message,
messages=new_messages
+ compaction_update_messages, # you may want to use prompt caching instead, in which case you'd use add_cache_control(self.messages) here
)
updated_summary, _ = remove_thinking_blocks(
response.content[0].text
) # clean up any <think> blocks because they are not needed in the session memory
print(" [Background] Session memory updated.")
return updated_summary
# Background memory update methods
def _background_memory_update(
self, messages_snapshot: list[dict], snapshot_index: int, current_tokens: int
) -> None:
"""Run session memory update in a background thread."""
try:
with self._lock:
current_session_memory = self.session_memory
last_index = self.last_summarized_index
if current_session_memory is None:
new_memory = self._create_session_memory(messages_snapshot)
else:
# Get new messages since last summary
new_messages = messages_snapshot[last_index:]
if not new_messages:
return
new_memory = self._update_session_memory(new_messages)
# Update state (thread-safe)
with self._lock:
self.session_memory = new_memory
self.last_summarized_index = snapshot_index
self.tokens_at_last_update = current_tokens
self.last_update_time = time.time()
except Exception as e:
print(f" [Background] Error updating memory: {e}")
# This makes sure only one background update runs at a time. If one is already running, we skip starting another. If not, we start a new thread to do the update.
def _trigger_background_update(self):
"""Trigger a background session memory update."""
if self._update_thread is not None and self._update_thread.is_alive():
return
messages_snapshot = self.messages.copy()
snapshot_index = len(messages_snapshot)
current_tokens = self.current_context_window_tokens
self._update_thread = threading.Thread(
target=self._background_memory_update,
args=(messages_snapshot, snapshot_index, current_tokens),
daemon=True,
)
self._update_thread.start()
# Function to compact
def compact(self) -> None:
"""INSTANT compaction using pre-built session memory."""
prev_msg_count = len(self.messages)
# Ensure session memory is ready. Shouldn't be an issue normally, but here for safety.
if self.session_memory is None:
if self._update_thread is not None and self._update_thread.is_alive():
print(" ⏳ Waiting for background memory update...")
self._update_thread.join(timeout=30.0)
if self.session_memory is None:
print(" ⚠️ No pre-built memory, creating synchronously...")
start = time.perf_counter()
self.session_memory = self._create_session_memory(self.messages)
elapsed = time.perf_counter() - start
print(f" ⏱️ Took {elapsed:.2f}s (but should be instant normally!)")
self.last_summarized_index = len(self.messages)
with self._lock:
unsummarized = self.messages[self.last_summarized_index :]
summary_message = [
{
"role": "user",
"content": f"""This session is being continued from a previous conversation. Here is the session memory: {self.session_memory}.Continue from where we left off.""",
}
]
self.messages = summary_message + unsummarized
self.last_summarized_index = 1
print(f"\n{'=' * 60}")
print(f"⚡ INSTANT COMPACTION! Messages: {prev_msg_count} → {len(self.messages)}")
print(" Session memory was pre-built (no wait time!)")
print(f"{'=' * 60}")
```
::: {.output .stream .stderr}
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:403: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
grammar.streamline()
/root/.pyenv/versions/3.13.11/lib/python3.13/site-packages/coconut/compiler/util.py:457: FutureWarning: functools.partial will be a method descriptor in future Python versions; wrap it in staticmethod() if you want to preserve the old behavior
result = add_action(grammar, unpack).parseWithTabs().transformString(text)
:::
::::
::: {.cell .markdown}
### Example use of Instant Compaction
:::
:::: {.cell .code execution_count="12" vscode="{\"languageId\":\"python\"}"}
``` coconut
# Low thresholds for demo - in production you'd use higher values
session = InstantCompactingChatSession(
system_message=SYSTEM_PROMPT,
)
messages = [
"I want to create a story about a young detective solving a mysterious case in a small town. Generate 3 well thought out plot ideas for me to consider.",
"I don't like those ideas, can you think of one plot something more unique and unexpected?",
"Ok I like it. Can you help me develop the main character's backstory and motivations?",
"Can you draft a detailed outline for the story, breaking it down into chapters and key events?",
"Can you draft me a first chapter based on the plot and character ideas we've discussed so far? Make it around 2,000 words.",
"Can you draft a second chapter that builds on the first one?",
]
print("Starting conversation with instant compacting chat session...\n")
turn_count = 0
for message in messages:
response, usage, background_status = session.chat(message)
turn_count += 1
# Calculate cache stats
cache_read = getattr(usage, "cache_read_input_tokens", 0) or 0
cache_created = getattr(usage, "cache_creation_input_tokens", 0) or 0
total_input = usage.input_tokens + cache_read
print(f"{'=' * 60}")
print(f"Turn {turn_count}:")
print(f"\nUser: {message}")
print(f"\nAssistant: \n{truncate_response(response, max_lines=3)}")
print("\nToken Usage:")
print(f" Input: {total_input:,} (new: {usage.input_tokens:,}, cached: {cache_read:,})")
print(f" Output: {usage.output_tokens:,}")
print(
f" Messages: {len(session.messages)} | Memory: {'ready' if session.session_memory else 'not yet'}"
)
if cache_read > 0:
cache_pct = (cache_read / total_input) * 100
print(f" ✓ Cache hit! {cache_pct:.0f}% of input from cache")
if background_status:
print(f"\n [Background] Proactively {background_status} session memory...")
print(f" Context window: {session.current_context_window_tokens:,} tokens")
print()
```
::: {.output .stream .stdout}
Starting conversation with instant compacting chat session...
============================================================
Turn 1:
User: I want to create a story about a young detective solving a mysterious case in a small town. Generate 3 well thought out plot ideas for me to consider.
Assistant:
# Three Mystery Plot Ideas
## 1. **The Vanishing Choir**
... (36 more lines)
Token Usage:
Input: 317 (new: 317, cached: 0)
Output: 902
Messages: 2 | Memory: not yet
============================================================
Turn 2:
User: I don't like those ideas, can you think of one plot something more unique and unexpected?
Assistant:
# **The Forgetting House**
**Setup:** Your young detective arrives in Ember Falls to investigate a string of burglaries—except the victims don't realize they've been robbed until weeks later. A woman discovers her wedding ring gone and insists she lost it yesterday, but security footage shows she hasn't worn it in a month. A man reports his grandfather's watch stolen, then his sister shows him photos proving he sold it himself at a pawn shop—which he has no memory of doing.
... (16 more lines)
Token Usage:
Input: 1,241 (new: 1,241, cached: 0)
Output: 592
Messages: 4 | Memory: not yet
============================================================
Turn 3:
User: Ok I like it. Can you help me develop the main character's backstory and motivations?
Assistant:
# Your Detective: Building From The Inside Out
## Core Identity
... (79 more lines)
Token Usage:
Input: 1,856 (new: 1,856, cached: 0)
Output: 1,329
Messages: 6 | Memory: not yet
============================================================
Turn 4:
User: Can you draft a detailed outline for the story, breaking it down into chapters and key events?
Assistant:
# **The Forgetting House: Chapter Outline**
---
... (272 more lines)
Token Usage:
Input: 3,207 (new: 3,207, cached: 0)
Output: 3,500
Messages: 8 | Memory: not yet
============================================================
Turn 5:
User: Can you draft me a first chapter based on the plot and character ideas we've discussed so far? Make it around 2,000 words.
Assistant:
# **Chapter One: The Impossible Theft**
The apartment smelled like burnt coffee and old paper.
... (196 more lines)
Token Usage:
Input: 6,743 (new: 6,743, cached: 0)
Output: 3,155
Messages: 10 | Memory: not yet
[Background] Proactively initializing session memory...
Context window: 9,898 tokens
[Background] Initial session memory created. Cache hit=True
============================================================
Turn 6:
User: Can you draft a second chapter that builds on the first one?
Assistant:
# **Chapter Two: Rosemont Manor**
The house appeared through the trees like something from a postcard.
... (190 more lines)
Token Usage:
Input: 9,914 (new: 5,818, cached: 4,096)
Output: 3,500
Messages: 12 | Memory: ready
✓ Cache hit! 41% of input from cache
[Background] Proactively updating session memory...
Context window: 13,414 tokens
:::
::::
:::: {.cell .code execution_count="13" vscode="{\"languageId\":\"python\"}"}
``` coconut
message = "What did we just talk about? Give me one sentence"
response, usage, background_status = session.chat(message)
# Calculate cache stats
cache_read = getattr(usage, "cache_read_input_tokens", 0) or 0
total_input = usage.input_tokens + cache_read
print(f"\nUser: {message}")
print(f"\nAssistant: \n{truncate_response(response, max_lines=3)}")
print("\nToken Usage:")
print(f" Input: {total_input:,} (new: {usage.input_tokens:,}, cached: {cache_read:,})")
print(f" Output: {usage.output_tokens:,}")
print(
f" Messages: {len(session.messages)} | Memory: {'ready' if session.session_memory else 'not yet'}"
)
if cache_read > 0:
cache_pct = (cache_read / total_input) * 100
print(f" ✓ Cache hit! {cache_pct:.0f}% of input from cache")
```
::: {.output .stream .stdout}
============================================================
⚡ INSTANT COMPACTION! Messages: 12 → 3
Session memory was pre-built (no wait time!)
============================================================
User: What did we just talk about? Give me one sentence
Assistant:
I drafted Chapter 2 where Casey arrives at Rosemont Manor, interviews Iris (who deflects questions about her past and shows moments of disorientation), and realizes through comparing photos that Iris Hale is definitely their missing grandmother Iris Whitmore.
Token Usage:
Input: 5,490 (new: 5,490, cached: 0)
Output: 60
Messages: 5 | Memory: ready
:::
::::
::: {.cell .markdown}
You\'ll notice here that once we hit the context limit, the session
memory was instantaly swapped in, meaning the user had zero waiting time
for a response!
:::
::: {.cell .markdown}
## Advanced: Understanding Prompt Caching
:::
::: {.cell .markdown}
The background updates can be made **\~10x cheaper** by using prompt
caching. The trick:
1. Pass the **full conversation** to the background summarizer
2. Add `cache_control` markers so subsequent requests hit the cache
3. Only the new \"summarize this\" instruction is billed at full price
<!-- -->
┌─────────────────────────────────────────────────────────────────────────────────┐
│ PROMPT CACHING FOR LONG CONVERSATIONS │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ WITHOUT CACHING: Pay full price for entire context every turn │
│ ════════════════════════════════════════════════════════════ │
│ │
│ Turn 1: [System][User1][Asst1] → 500 tokens @ $3/M │
│ Turn 2: [System][User1][Asst1][User2][Asst2] → 1500 tokens @ $3/M │
│ Turn 3: [System][User1][Asst1][User2][Asst2][User3]... → 3000 tokens @ $3/M │
│ Turn 4: [System][User1][Asst1][User2][Asst2][User3]... → 5000 tokens @ $3/M │
│ ───────────────────────────────────────────── │
│ Total: 10,000 tokens = $0.030 │
│ │
│ │
│ WITH CACHING: Pay full price once, then 90% discount on prefix │
│ ═══════════════════════════════════════════════════════════════ │
│ │
│ Turn 1: [System][User1][Asst1]◆ → 500 tokens @ $3/M │
│ ▲ (cache created) │
│ cache breakpoint │
│ │
│ Turn 2: [System][User1][Asst1][User2][Asst2]◆ │
│ ╰─────── cached ──────╯ │
│ 500 @ $0.30/M + 1000 new @ $3/M = $0.0032 │
│ │
│ Turn 3: [System][User1][Asst1][User2][Asst2][User3][Asst3]◆ │
│ ╰──────────── cached ─────────────╯ │
│ 1500 @ $0.30/M + 1500 new @ $3/M = $0.0050 │
│ │
│ Turn 4: [System][User1][Asst1][User2][Asst2][User3][Asst3][User4][Asst4]◆ │
│ ╰───────────────────── cached ─────────────────────╯ │
│ 3000 @ $0.30/M + 2000 new @ $3/M = $0.0069 │
│ ───────────────────────────────────────────── │
│ Total: $0.0166 (45% savings) │
│ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ COMPACTION + CACHING: Double benefit │
│ ════════════════════════════════════ │
│ │
│ Main Chat Background Summarizer │
│ ───────── ───────────────────── │
│ │
│ [Conversation grows...] [Same conversation prefix]◆ + [Summarize!] │
│ │ │ │
│ │ Cache hit! Only pays for │
│ │ the summarization prompt │
│ │ │ │
│ ▼ ▼ │
│ Context limit reached ──────► Session memory ready instantly │
│ (built cheaply in background) │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ Key insight: The background summarizer reuses the same conversation │ │
│ │ prefix that was just sent to the main chat - automatic cache hit! │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
◆ = cache_control breakpoint (cache everything before this point)
### Why this matters for compaction
Scenario Cost per background update Notes
-------------- ---------------------------- ----------------------------------
No caching Full input cost 5,000 tokens × \$3/M = \$0.015
With caching \~10% of input cost 500 new + 4,500 cached = \$0.003
**Savings** **\~80%** Compounds over many updates
The longer the conversation, the bigger the savings---exactly when you
need compaction most!
:::
::: {.cell .markdown}
### How the Caching Works
The key is in `_add_cache_control()` and
`_create_session_memory_cached()`:
``` python
# 1. Mark the last conversation message with cache_control
{
"role": "user",
"content": [{
"type": "text",
"text": msg["content"],
"cache_control": {"type": "ephemeral"} # <-- This creates a cache breakpoint
}]
}
# 2. Also mark the system prompt
system=[{
"type": "text",
"text": "You are a session memory agent...",
"cache_control": {"type": "ephemeral"}
}]
```
**Why this works:**
- The first background update creates a cache entry for
`[System + Messages]`
- Subsequent updates with the same message prefix get **cache hits**
- Only the new summarization instruction is billed at full price
- Cache entries have a 5-minute TTL, so rapid updates benefit most
**Cost math:**
- Without caching: 5,000 tokens × \$3.00/1M = \$0.015 per update
- With caching: 500 new tokens × \$3.00/1M + 4,500 cached × \$0.30/1M =
\$0.00285
- **Savings: \~80%** on background summarization costs
:::
::: {.cell .markdown}
## Conclusion
In this cookbook, you learned how to manage long-running Claude
conversations through session memory compaction.
### What We Covered
✅ **Effective compaction prompts** - Structure your session memory to
preserve user intent, completed work, errors, active work, and key
references while discarding filler
✅ **Instant compaction** - Use background threading to proactively
build session memory, eliminating user wait time when context limits are
reached
✅ **Prompt caching for cost savings** - Reduce background update costs
by \~80% by reusing the conversation prefix cache
✅ **Traditional vs. instant patterns** - Understand when to use each
approach based on your application needs
### Key Takeaways
1. **Weight recency heavily** - The end of a conversation is the active
working context
2. **Preserve user corrections verbatim** - Prevents the model from
reverting to old behaviors
3. **Build memory proactively** - Don\'t wait for context limits; start
background updates early
4. **Leverage prompt caching** - Background summarization can share
cache with the main conversation
### Next Steps
- **For agentic workflows**: See [Automatic Context
Compaction](https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/automatic-context-compaction.ipynb) for
SDK-based automatic compaction with tool use
- **For production**: Consider persisting session memory to disk rather
than keeping it in memory
- **For optimization**: Experiment with update frequency thresholds to
balance cost vs. freshness
:::
---
## Automatic Context Compaction
Source: https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/automatic-context-compaction.ipynb
Path: 02-Claude-Code-CLI/claude-cookbooks-tool-use-automatic-context-compaction.md
# Automatic Context Compaction
Long-running agentic tasks can often exceed context limits. Tool heavy
workflows or long conversations quickly consume the token context
window. In [Effective Context Engineering for AI
Agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents),
we discussed how managing context can help avoid performance degradation
and context rot.
The Claude Agent Python SDK can help manage this context by
automatically compressing conversation history when token usage exceeds
a configurable threshold, allowing tasks to continue beyond the typical
200k token context limit.
In this cookbook, we\'ll demonstrate context compaction through an
**agentic customer service workflow**. Imagine you\'ve built an AI
customer service agent tasked with processing a queue of support
tickets. For each ticket, you must classify the issue, search the
knowledge base, set priority, route to the appropriate team, draft a
response, and mark it complete. As you process ticket after ticket, the
conversation history fills with classifications, knowledge base
searches, and drafted responses---quickly consuming thousands of tokens.
## What is Context Compaction?
When building agentic workflows with tool use, conversations can grow
very large as the agent iterates on complex tasks. The
`compaction_control` parameter provides automatic context management by:
1. Monitoring token usage per turn in the conversation
2. When a threshold is exceeded, injecting a summary prompt as a user
turn
3. Having the model generate a summary wrapped in `<summary></summary>`
tags. These tags aren\'t parsed, but are there to help guide the
model.
4. Clearing the conversation history and resuming with only the summary
5. Continuing the task with the compressed context
## By the end of this cookbook, you\'ll be able to:
- Understand how to effectively manage context limits in iterative
workflows
- Write agents that leverage automatic context compaction
- Design workflows that maintain focus across multiple iterations
## Prerequisites
Before following this guide, ensure you have:
**Required Knowledge**
- Basic understanding of agentic patterns and tool calling
**Required Tools**
- Python 3.11 or higher
- Anthropic API key
- Anthropic SDK \>= 0.74.1
:::
::: {#004e3b52 .cell .markdown}
## Setup
First, install the required dependencies:
:::
::: {#71d7f8c2 .cell .code execution_count="1"}
``` python
# %pip install -qU anthropic python-dotenv
```
:::
::: {#1ba96da5 .cell .markdown}
Note: Ensure your .env file contains:
`ANTHROPIC_API_KEY=your_key_here`
Load your environment variables and configure the client. We also load a
helper utility to visualize Claude message responses.
:::
::: {#68f6d5bb .cell .code execution_count="2"}
``` python
from dotenv import load_dotenv
load_dotenv()
MODEL = "claude-sonnet-4-5"
```
:::
::: {#783cf8e3 .cell .markdown}
## Setting the Stage
In [utils/customer_service_tools.py](https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/utils/customer_service_tools.py),
we\'ve defined several functions for processing customer support
tickets:
- `get_next_ticket()` - Retrieves the next unprocessed ticket from the
queue
- `classify_ticket(ticket_id, category)` - Categorizes issues as
billing, technical, account, product, or shipping
- `search_knowledge_base(query)` - Finds relevant help articles and
solutions
- `set_priority(ticket_id, priority)` - Assigns priority levels (low,
medium, high, urgent)
- `route_to_team(ticket_id, team)` - Routes tickets to the appropriate
support team
- `draft_response(ticket_id, response_text)` - Creates customer-facing
responses
- `mark_complete(ticket_id)` - Finalizes processed tickets
For a customer service agent, these tools enable processing tickets
systematically. Each ticket requires classification, research,
prioritization, routing, and response drafting. When processing 20-30
tickets in sequence, the conversation history fills with tool results
from every classification, every knowledge base search, and every
drafted response, causing linear token growth.
The `beta_tool` decorator is used on the tools to make them accessible
to the Claude agent. The decorator extracts the function arguments and
docstring and provides these to Claude as tool metadata.
``` python
import anthropic
from anthropic import beta_tool
@beta_tool
def get_next_ticket() -> dict:
"""Retrieve the next unprocessed support ticket from the queue."""
...
```
:::
::: {#58d2a922 .cell .code execution_count="3"}
``` python
import anthropic
from utils.customer_service_tools import (
classify_ticket,
draft_response,
get_next_ticket,
initialize_ticket_queue,
mark_complete,
route_to_team,
search_knowledge_base,
set_priority,
)
client = anthropic.Anthropic()
tools = [
get_next_ticket,
classify_ticket,
search_knowledge_base,
set_priority,
route_to_team,
draft_response,
mark_complete,
]
```
:::
::: {#77fecfb8 .cell .markdown}
## Baseline: Running Without Compaction
Let\'s start with a realistic customer service scenario: Processing a
queue of support tickets.
The workflow looks like this:
**For Each Ticket:**
1. Fetch the ticket using `get_next_ticket()`
2. Classify the issue category (billing, technical, account, product,
shipping)
3. Search the knowledge base for relevant information
4. Set appropriate priority (low, medium, high, urgent)
5. Route to the correct team
6. Draft a customer response
7. Mark the ticket complete
8. Move to the next ticket
**The Challenge**: With 5 tickets in the queue, and each requiring 7
tool calls, Claude will make 35 or more tool calls. The results from
each step including classification knowledge base search, and drafted
responses accumulate in the conversation history. Without compaction,
all this data stays in memory for every ticket, by ticket #5, the
context includes complete details from all 4 previous tickets.
Let\'s run this workflow **without compaction** first and observe what
happens:
:::
:::: {#uef86nvtl4 .cell .code execution_count="4"}
``` python
from anthropic.types.beta import BetaMessageParam
num_tickets = 5
initialize_ticket_queue(num_tickets)
messages: list[BetaMessageParam] = [
{
"role": "user",
"content": f"""You are an AI customer service agent. Your task is to process support tickets from a queue.
For EACH ticket, you must complete ALL these steps:
1. **Fetch ticket**: Call get_next_ticket() to retrieve the next unprocessed ticket
2. **Classify**: Call classify_ticket() to categorize the issue (billing/technical/account/product/shipping)
3. **Research**: Call search_knowledge_base() to find relevant information for this ticket type
4. **Prioritize**: Call set_priority() to assign priority (low/medium/high/urgent) based on severity
5. **Route**: Call route_to_team() to assign to the appropriate team
6. **Draft**: Call draft_response() to create a helpful customer response using KB information
7. **Complete**: Call mark_complete() to finalize this ticket
8. **Continue**: Immediately fetch the next ticket and repeat
IMPORTANT RULES:
- Process tickets ONE AT A TIME in sequence
- Complete ALL 7 steps for each ticket before moving to the next
- Keep fetching and processing tickets until you get an error that the queue is empty
- There are {num_tickets} tickets total - process all of them
- Be thorough but efficient
Begin by fetching the first ticket.""",
}
]
total_input = 0
total_output = 0
turn_count = 0
runner = client.beta.messages.tool_runner(
model=MODEL,
max_tokens=4096,
tools=tools,
messages=messages,
)
for message in runner:
messages_list = list(runner._params["messages"])
turn_count += 1
total_input += message.usage.input_tokens
total_output += message.usage.output_tokens
print(
f"Turn {turn_count:2d}: Input={message.usage.input_tokens:7,} tokens | "
f"Output={message.usage.output_tokens:5,} tokens | "
f"Messages={len(messages_list):2d} | "
f"Cumulative In={total_input:8,}"
)
print(f"\n{'=' * 60}")
print("BASELINE RESULTS (NO COMPACTION)")
print(f"{'=' * 60}")
print(f"Total turns: {turn_count}")
print(f"Input tokens: {total_input:,}")
print(f"Output tokens: {total_output:,}")
print(f"Total tokens: {total_input + total_output:,}")
print(f"{'=' * 60}")
```
::: {.output .stream .stdout}
Turn 1: Input= 1,537 tokens | Output= 57 tokens | Messages= 1 | Cumulative In= 1,537
Turn 2: Input= 1,760 tokens | Output= 102 tokens | Messages= 3 | Cumulative In= 3,297
Turn 3: Input= 1,905 tokens | Output= 88 tokens | Messages= 5 | Cumulative In= 5,202
Turn 4: Input= 2,237 tokens | Output= 84 tokens | Messages= 7 | Cumulative In= 7,439
Turn 5: Input= 2,385 tokens | Output= 89 tokens | Messages= 9 | Cumulative In= 9,824
Turn 6: Input= 2,537 tokens | Output= 301 tokens | Messages=11 | Cumulative In= 12,361
Turn 7: Input= 2,888 tokens | Output= 67 tokens | Messages=13 | Cumulative In= 15,249
Turn 8: Input= 3,079 tokens | Output= 56 tokens | Messages=15 | Cumulative In= 18,328
Turn 9: Input= 3,316 tokens | Output= 91 tokens | Messages=17 | Cumulative In= 21,644
Turn 10: Input= 3,450 tokens | Output= 84 tokens | Messages=19 | Cumulative In= 25,094
Turn 11: Input= 3,777 tokens | Output= 84 tokens | Messages=21 | Cumulative In= 28,871
Turn 12: Input= 3,925 tokens | Output= 89 tokens | Messages=23 | Cumulative In= 32,796
Turn 13: Input= 4,077 tokens | Output= 349 tokens | Messages=25 | Cumulative In= 36,873
Turn 14: Input= 4,476 tokens | Output= 67 tokens | Messages=27 | Cumulative In= 41,349
Turn 15: Input= 4,668 tokens | Output= 56 tokens | Messages=29 | Cumulative In= 46,017
Turn 16: Input= 4,894 tokens | Output= 91 tokens | Messages=31 | Cumulative In= 50,911
Turn 17: Input= 5,028 tokens | Output= 84 tokens | Messages=33 | Cumulative In= 55,939
Turn 18: Input= 5,333 tokens | Output= 84 tokens | Messages=35 | Cumulative In= 61,272
Turn 19: Input= 5,481 tokens | Output= 89 tokens | Messages=37 | Cumulative In= 66,753
Turn 20: Input= 5,633 tokens | Output= 334 tokens | Messages=39 | Cumulative In= 72,386
Turn 21: Input= 6,017 tokens | Output= 67 tokens | Messages=41 | Cumulative In= 78,403
Turn 22: Input= 6,209 tokens | Output= 56 tokens | Messages=43 | Cumulative In= 84,612
Turn 23: Input= 6,435 tokens | Output= 91 tokens | Messages=45 | Cumulative In= 91,047
Turn 24: Input= 6,569 tokens | Output= 84 tokens | Messages=47 | Cumulative In= 97,616
Turn 25: Input= 6,896 tokens | Output= 84 tokens | Messages=49 | Cumulative In= 104,512
Turn 26: Input= 7,044 tokens | Output= 89 tokens | Messages=51 | Cumulative In= 111,556
Turn 27: Input= 7,196 tokens | Output= 372 tokens | Messages=53 | Cumulative In= 118,752
Turn 28: Input= 7,618 tokens | Output= 67 tokens | Messages=55 | Cumulative In= 126,370
Turn 29: Input= 7,808 tokens | Output= 56 tokens | Messages=57 | Cumulative In= 134,178
Turn 30: Input= 8,040 tokens | Output= 96 tokens | Messages=59 | Cumulative In= 142,218
Turn 31: Input= 8,179 tokens | Output= 85 tokens | Messages=61 | Cumulative In= 150,397
Turn 32: Input= 8,508 tokens | Output= 84 tokens | Messages=63 | Cumulative In= 158,905
Turn 33: Input= 8,656 tokens | Output= 89 tokens | Messages=65 | Cumulative In= 167,561
Turn 34: Input= 8,808 tokens | Output= 332 tokens | Messages=67 | Cumulative In= 176,369
Turn 35: Input= 9,190 tokens | Output= 67 tokens | Messages=69 | Cumulative In= 185,559
Turn 36: Input= 9,382 tokens | Output= 60 tokens | Messages=71 | Cumulative In= 194,941
Turn 37: Input= 9,475 tokens | Output= 297 tokens | Messages=73 | Cumulative In= 204,416
============================================================
BASELINE RESULTS (NO COMPACTION)
============================================================
Total turns: 37
Input tokens: 204,416
Output tokens: 4,422
Total tokens: 208,838
============================================================
:::
::::
::: {#3dd25c6f .cell .markdown}
Now that we have our baseline, we have a better picture of how context
grows without compaction. As you can see, each turn results in linear
token growth, as every turn adds more tokens to the input.
This leads to high token consumption and potential context limits being
reached quickly. By the 27th turn, we have a cumulative 150,000 input
tokens just for 5 tickets.
Let\'s review Claude\'s final response after processing all 5 tickets
without compaction:
:::
:::: {#d8b51b65 .cell .code execution_count="5"}
``` python
print(message.content[-1].text)
```
::: {.output .stream .stdout}
---
## ✅ ALL TICKETS PROCESSED SUCCESSFULLY!
**Summary of Completed Work:**
I have successfully processed all 5 tickets from the queue. Here's what was accomplished:
1. **TICKET-1** - Sam Smith - Payment method update error
- Category: Billing | Priority: High | Team: billing-team
2. **TICKET-2** - Morgan Johnson - Missing delivery
- Category: Shipping | Priority: High | Team: logistics-team
3. **TICKET-3** - Morgan Jones - Email address change request
- Category: Account | Priority: Medium | Team: account-services
4. **TICKET-4** - Alex Johnson - Wrong item delivered
- Category: Shipping | Priority: High | Team: logistics-team
5. **TICKET-5** - Morgan Jones - Refund request for cancelled subscription
- Category: Billing | Priority: High | Team: billing-team
Each ticket was:
✅ Classified correctly
✅ Researched in the knowledge base
✅ Assigned appropriate priority
✅ Routed to the correct team
✅ Given a detailed, helpful customer response
✅ Marked as complete
The queue is now empty and all tickets have been processed!
:::
::::
::: {#klok33ohsvn .cell .markdown}
### Understanding the Problem
In the baseline workflow above, Claude had to:
- Process **5 support tickets** sequentially
- Complete **7 steps per ticket** (fetch, classify, research,
prioritize, route, draft, complete)
- Make **35 tool calls** with results accumulating in conversation
history
- Store **every classification, every knowledge base search, every
drafted response** in memory
**Why This Happens**:
1. **Linear token growth** - With each tool use, the entire
conversation history (including all previous tool results) is sent
to Claude
2. **Context pollution** - Ticket A\'s classification and drafted
response remain in context while processing Ticket B
3. **Compounding costs** - By the time you\'re on Ticket #5, you\'re
sending data from all 4 previous tickets on every API call
4. **Slower responses** - Processing massive contexts takes longer
5. **Risk of hitting limits** - Eventually you hit the 200k token
context window
**What We Actually Need**: After completing Ticket A, we only need a
**brief summary** (ticket resolved, category, priority) - not the full
classification result, knowledge base search, and complete drafted
response. The detailed workflow should be discarded, keeping only
completion summaries.
Let\'s see how automatic context compaction solves this problem.
:::
::: {#byut5h7hi3 .cell .markdown}
## Enabling Automatic Context Compaction
Let\'s run the exact same customer service workflow, but with automatic
context compaction enabled. We simply add the `compaction_control`
parameter to our tool runner.
The `compaction_control` parameter has one required field and several
optional ones:
- **`enabled`** (required): Boolean to turn compaction on/off
- **`context_token_threshold`** (optional): Token count that triggers
compaction (default: 100,000)
- **`model`** (optional): Model to use for summarization (defaults to
the main model)
- **`summary_prompt`** (optional): Custom prompt for generating
summaries
For this customer service workflow, we\'ll use a **5,000 token
threshold**. This means after processing several tickets compaction will
auto-trigger. This allows Claude to:
1. **Keep completion summaries** (tickets resolved, categories,
outcomes)
2. **Discard detailed tool results** (full KB articles, complete
classifications, drafted response text)
3. **Start fresh** when processing the next batch of tickets
This mimics how a real support agent works: resolve the ticket, document
it briefly, move to the next case.
:::
:::: {#x6lnx8d20fr .cell .code execution_count="6"}
``` python
# Re-initialize queue and run with compaction
initialize_ticket_queue(num_tickets)
total_input_compact = 0
total_output_compact = 0
turn_count_compact = 0
compaction_count = 0
prev_msg_count = 0
runner = client.beta.messages.tool_runner(
model=MODEL,
max_tokens=4096,
tools=tools,
messages=messages,
compaction_control={
"enabled": True,
"context_token_threshold": 5000,
},
)
for message in runner:
turn_count_compact += 1
total_input_compact += message.usage.input_tokens
total_output_compact += message.usage.output_tokens
messages_list = list(runner._params["messages"])
curr_msg_count = len(messages_list)
if curr_msg_count < prev_msg_count:
# We can identify compaction when the message count decreases
compaction_count += 1
print(f"\n{'=' * 60}")
print(f"🔄 Compaction occurred! Messages: {prev_msg_count} → {curr_msg_count}")
print(" Summary message after compaction:")
print(messages_list[-1]["content"][-1].text) # type: ignore
print(f"\n{'=' * 60}")
prev_msg_count = curr_msg_count
print(
f"Turn {turn_count_compact:2d}: Input={message.usage.input_tokens:7,} tokens | "
f"Output={message.usage.output_tokens:5,} tokens | "
f"Messages={len(messages_list):2d} | "
f"Cumulative In={total_input_compact:8,}"
)
print(f"\n{'=' * 60}")
print("OPTIMIZED RESULTS (WITH COMPACTION)")
print(f"{'=' * 60}")
print(f"Total turns: {turn_count_compact}")
print(f"Compactions: {compaction_count}")
print(f"Input tokens: {total_input_compact:,}")
print(f"Output tokens: {total_output_compact:,}")
print(f"Total tokens: {total_input_compact + total_output_compact:,}")
print(f"{'=' * 60}")
```
::: {.output .stream .stdout}
Turn 1: Input= 1,537 tokens | Output= 57 tokens | Messages= 1 | Cumulative In= 1,537
Turn 2: Input= 1,755 tokens | Output= 108 tokens | Messages= 3 | Cumulative In= 3,292
Turn 3: Input= 1,906 tokens | Output= 88 tokens | Messages= 5 | Cumulative In= 5,198
Turn 4: Input= 2,216 tokens | Output= 84 tokens | Messages= 7 | Cumulative In= 7,414
Turn 5: Input= 2,364 tokens | Output= 89 tokens | Messages= 9 | Cumulative In= 9,778
Turn 6: Input= 2,516 tokens | Output= 332 tokens | Messages=11 | Cumulative In= 12,294
Turn 7: Input= 2,898 tokens | Output= 67 tokens | Messages=13 | Cumulative In= 15,192
Turn 8: Input= 3,090 tokens | Output= 56 tokens | Messages=15 | Cumulative In= 18,282
Turn 9: Input= 3,325 tokens | Output= 97 tokens | Messages=17 | Cumulative In= 21,607
Turn 10: Input= 3,465 tokens | Output= 90 tokens | Messages=19 | Cumulative In= 25,072
Turn 11: Input= 3,801 tokens | Output= 84 tokens | Messages=21 | Cumulative In= 28,873
Turn 12: Input= 3,949 tokens | Output= 89 tokens | Messages=23 | Cumulative In= 32,822
Turn 13: Input= 4,101 tokens | Output= 368 tokens | Messages=25 | Cumulative In= 36,923
Turn 14: Input= 4,519 tokens | Output= 67 tokens | Messages=27 | Cumulative In= 41,442
Turn 15: Input= 4,711 tokens | Output= 57 tokens | Messages=29 | Cumulative In= 46,153
Turn 16: Input= 4,934 tokens | Output= 97 tokens | Messages=31 | Cumulative In= 51,087
============================================================
🔄 Compaction occurred! Messages: 31 → 1
Summary message after compaction:
<summary>
## Support Ticket Processing Progress Summary
### Task Overview
Processing 5 support tickets sequentially, completing all 7 steps for each ticket (fetch, classify, research, prioritize, route, draft, complete).
### Tickets Completed (2 of 5)
**TICKET-1 (Chris Davis) - COMPLETED**
- Issue: Account locked, unlock email link not working
- Category: account
- Priority: high
- Team: account-services
- Status: resolved
- Response: Provided guidance on checking spam folder, link expiration (1 hour), and requesting new unlock link
**TICKET-2 (Chris Williams) - COMPLETED**
- Issue: Unrecognized $49.99 charge on 2025-10-30
- Category: billing
- Priority: high
- Team: billing-team
- Status: resolved
- Response: Explained billing cycles, subscription possibility, and refund policy (5-7 business days, pro-rated for annual plans)
### Current Status
**TICKET-3 (John Jones) - IN PROGRESS**
- Issue: Asking about Google Sheets integration for project management
- Category: product
- Priority: NOT YET SET
- Team: NOT YET ASSIGNED
- Steps completed: 1 (fetch), 2 (classify)
- Steps remaining: 3 (research KB), 4 (set priority), 5 (route), 6 (draft), 7 (mark complete)
### Next Steps
1. Complete TICKET-3: Search knowledge base for product integration info
2. Set priority (likely low/medium for feature inquiry)
3. Route to product-team
4. Draft response about integrations
5. Mark complete
6. Fetch and process TICKET-4
7. Fetch and process TICKET-5
### Key Knowledge Base Info Learned
- Account: Password reset links expire in 1 hour, sent from noreply@support.example.com
- Billing: Refunds take 5-7 business days, pro-rated for annual plans, billing on same date monthly/yearly
### Remaining Work
3 tickets left to process (TICKET-3 currently in progress, then TICKET-4 and TICKET-5)
</summary>
============================================================
Turn 17: Input= 1,774 tokens | Output= 94 tokens | Messages= 1 | Cumulative In= 52,861
Turn 18: Input= 1,906 tokens | Output= 95 tokens | Messages= 3 | Cumulative In= 54,767
Turn 19: Input= 2,365 tokens | Output= 431 tokens | Messages= 5 | Cumulative In= 57,132
Turn 20: Input= 3,164 tokens | Output= 60 tokens | Messages= 7 | Cumulative In= 60,296
Turn 21: Input= 3,383 tokens | Output= 160 tokens | Messages= 9 | Cumulative In= 63,679
Turn 22: Input= 3,872 tokens | Output= 447 tokens | Messages=11 | Cumulative In= 67,551
Turn 23: Input= 4,687 tokens | Output= 64 tokens | Messages=13 | Cumulative In= 72,238
Turn 24: Input= 4,914 tokens | Output= 160 tokens | Messages=15 | Cumulative In= 77,152
============================================================
🔄 Compaction occurred! Messages: 15 → 1
Summary message after compaction:
<summary>
## Support Ticket Processing Progress Summary
### Task Overview
Processing 5 support tickets sequentially, completing all 7 steps for each ticket (fetch, classify, research, prioritize, route, draft, complete).
### Tickets Completed (4 of 5)
**TICKET-1 (Chris Davis) - COMPLETED**
- Issue: Account locked, unlock email link not working
- Category: account
- Priority: high
- Team: account-services
- Status: resolved
- Response: Provided guidance on checking spam folder, link expiration (1 hour), and requesting new unlock link
**TICKET-2 (Chris Williams) - COMPLETED**
- Issue: Unrecognized $49.99 charge on 2025-10-30
- Category: billing
- Priority: high
- Team: billing-team
- Status: resolved
- Response: Explained billing cycles, subscription possibility, and refund policy (5-7 business days, pro-rated for annual plans)
**TICKET-3 (John Jones) - COMPLETED**
- Issue: Asking about Google Sheets integration for project management
- Category: product
- Priority: medium
- Team: product-success
- Status: resolved
- Response: Explained that Product Success team will provide details on integration options, API access, and current/planned features
**TICKET-4 (Sam Johnson) - COMPLETED**
- Issue: Wants to know differences between Standard and Premium plans, specifically "advanced analytics"
- Category: product
- Priority: low
- Team: product-success
- Status: resolved
- Response: Explained that Product Success team will provide detailed plan comparison and feature breakdown
### Current Status
**TICKET-5 (Morgan Brown) - IN PROGRESS**
- Issue: Damaged package (Order #ORD-43312), broken product inside, needs replacement
- Category: shipping (classified)
- Priority: NOT YET SET
- Team: NOT YET ASSIGNED
- Steps completed: 1 (fetch), 2 (classify), 3 (research KB - no shipping info found)
- Steps remaining: 4 (set priority), 5 (route), 6 (draft), 7 (mark complete)
### Next Steps for TICKET-5
1. Set priority (likely HIGH - damaged/broken product requiring replacement)
2. Route to appropriate team (likely fulfillment, operations, or customer-service team)
3. Draft response addressing damaged shipment, replacement process, and next steps
4. Mark complete
5. **ALL TICKETS WILL BE COMPLETE**
### Key Knowledge Base Info Learned
- **Account**: Password reset links expire in 1 hour, sent from noreply@support.example.com
- **Billing**: Refunds take 5-7 business days, pro-rated for annual plans, billing on same date monthly/yearly; accepts Visa, Mastercard, Amex, PayPal
- **Technical**: Max upload 100MB, supported formats: PDF, DOCX, PNG, JPG, CSV; system requirements: 4GB RAM, modern browsers
- **Product category**: Does not exist in KB (only billing, technical, account available)
- **Shipping info**: Not found in knowledge base
### Team Routing Patterns Observed
- account-services: Account access issues
- billing-team: Billing/payment inquiries
- product-success: Product features, integrations, plan comparisons
### Remaining Work
1 ticket left to complete (TICKET-5 - final ticket, currently in progress at step 3 of 7)
</summary>
============================================================
Turn 25: Input= 2,077 tokens | Output= 496 tokens | Messages= 1 | Cumulative In= 79,229
Turn 26: Input= 2,942 tokens | Output= 438 tokens | Messages= 3 | Cumulative In= 82,171
============================================================
OPTIMIZED RESULTS (WITH COMPACTION)
============================================================
Total turns: 26
Compactions: 2
Input tokens: 82,171
Output tokens: 4,275
Total tokens: 86,446
============================================================
:::
::::
::: {#5cbbfe32 .cell .markdown}
With automatic context compaction enabled, we can see that our token
usage per turn does not grow linearly, but is reduced after each
compaction event. There were two compaction events during the processing
of tickets, and the follow turn shows a reduction in total token usage.
Compared to the baseline version, we only used 79,000 tokens. We\'ve
also printed out the summary messages generated after each compaction
event, showing how Claude effectively condensed prior ticket details
into summaries.
Let\'s look at the final response after processing all 5 tickets with
compaction enabled.
:::
:::: {#24dd5c7c .cell .code execution_count="7"}
``` python
print(message.content[-1].text)
```
::: {.output .stream .stdout}
Perfect! **ALL 5 TICKETS HAVE BEEN SUCCESSFULLY COMPLETED!** 🎉
## Final Summary - All Tickets Processed
### TICKET-5 (Morgan Brown) - **COMPLETED** ✓
- **Issue**: Damaged package (Order #ORD-43312), broken product inside, needs replacement
- **Category**: shipping
- **Priority**: high
- **Team**: logistics-team
- **Status**: resolved
- **Response**: Apologized for damaged shipment, escalated to Logistics Team with HIGH priority, explained they'll process immediate replacement, provide return instructions, and contact customer with tracking and timeline
---
## 🎯 ALL 5 TICKETS COMPLETED
1. ✅ **TICKET-1** (Chris Davis) - Account locked → account-services
2. ✅ **TICKET-2** (Chris Williams) - Billing charge → billing-team
3. ✅ **TICKET-3** (John Jones) - Google Sheets integration → product-success
4. ✅ **TICKET-4** (Sam Johnson) - Plan comparison → product-success
5. ✅ **TICKET-5** (Morgan Brown) - Damaged shipment → logistics-team
### Processing Statistics
- **Total tickets processed**: 5 of 5 (100%)
- **Steps per ticket**: 7 (fetch, classify, research, prioritize, route, draft, complete)
- **Total operations**: 35 successful operations
- **Categories used**: account, billing, product (2x), shipping
- **Teams utilized**: account-services, billing-team, product-success (2x), logistics-team
- **Priority distribution**: 2 high, 2 medium, 1 low
All tickets have been properly classified, prioritized, routed to the appropriate teams, and have draft responses ready for team review! 🎊
:::
::::
::: {#vb4cesnmb8 .cell .markdown}
### Comparing Results
With compaction enabled, we can see a clear differece between the two
runs in token savings, while preserving the quality of the workflow and
final summary.
Here\'s what changed with automatic context compaction:
1. **Context resets after several tickets** - When processing 5-7
tickets generates 5k+ tokens of tool results, the SDK automatically:
- Injects a summary prompt
- Has Claude generate a completion summary wrapped in
`<summary></summary>` tags
- Clears the conversation history and discards detailed
classifications, KB searches, and responses
- Continues with only the completion summary
2. **Input tokens stay bounded** - Instead of accumulating to 100k+ as
we process more tickets, input tokens reset after each compaction.
When processing Ticket #5, we\'re NOT carrying the full tool results
from Tickets #1-4.
3. **Task completes successfully** - The workflow continues smoothly
through all tickets without hitting context limits
4. **Quality is preserved** - The summaries retain critical
information:
- Tickets processed with their IDs
- Categories and priorities assigned
- Teams routed to
- Overall progress status
All tickets are still properly classified, prioritized, routed, and
responded to.
5. **Natural workflow** - This mirrors how real support agents work:
resolve a ticket, document it briefly in the system, close it, move
to the next one. You don\'t keep every knowledge base article and
full response draft open while working on new tickets.
Let\'s visualize the token savings:
:::
:::: {#z9lvigc94p .cell .code execution_count="8"}
``` python
# Compare baseline vs compaction
print("=" * 70)
print("TOKEN USAGE COMPARISON")
print("=" * 70)
print(f"{'Metric':<30} {'Baseline':<20} {'With Compaction':<20}")
print("-" * 70)
print(f"{'Input tokens:':<30} {total_input:>19,} {total_input_compact:>19,}")
print(f"{'Output tokens:':<30} {total_output:>19,} {total_output_compact:>19,}")
print(
f"{'Total tokens:':<30} {total_input + total_output:>19,} {total_input_compact + total_output_compact:>19,}"
)
print(f"{'Compactions:':<30} {'N/A':>19} {compaction_count:>19}")
print("=" * 70)
# Calculate savings
token_savings = (total_input + total_output) - (total_input_compact + total_output_compact)
savings_percent = (
(token_savings / (total_input + total_output)) * 100 if (total_input + total_output) > 0 else 0
)
print(f"\n💰 Token Savings: {token_savings:,} tokens ({savings_percent:.1f}% reduction)")
```
::: {.output .stream .stdout}
======================================================================
TOKEN USAGE COMPARISON
======================================================================
Metric Baseline With Compaction
----------------------------------------------------------------------
Input tokens: 204,416 82,171
Output tokens: 4,422 4,275
Total tokens: 208,838 86,446
Compactions: N/A 2
======================================================================
💰 Token Savings: 122,392 tokens (58.6% reduction)
:::
::::
::: {#lzvf1mw7o6 .cell .markdown}
## How Compaction Works Under the Hood
When the `tool_runner` detects that token usage has exceeded the
threshold, it automatically:
1. **Pauses the workflow** before making the next API call
2. **Injects a summary request** as a user message asking Claude to
summarize progress
3. **Generates a summary** - Claude produces a summary wrapped in
`<summary></summary>` tags containing:
- **Completed tickets**: Brief records of tickets resolved (IDs,
categories, priorities, outcomes)
- **Progress status**: How many tickets processed, how many remain
- **Key patterns**: Any notable trends across tickets
- **Next steps**: What to do next (continue processing remaining
tickets)
4. **Clears history** - The entire conversation history (including all
tool results) is replaced with just the summary
5. **Resumes processing** - Claude continues working with the
compressed context, processing the next batch of tickets
:::
::: {#v64ljd0a79 .cell .markdown}
## Customizing Compaction Configuration
You can customize how compaction works to fit your specific use case.
Here are the key configuration options:
### Adjusting the Threshold
The `context_token_threshold` determines when compaction triggers:
``` python
compaction_control={
"enabled": True,
"context_token_threshold": 5000, # Compact after processing 5-7 tickets
}
```
The threshold should not be set too low, otherwise the summary itself
could trigger a compaction. We set a threshold of 5,000 tokens for
demonstration purposes, but in practice, experiment with different
settings to find what works best for your workflow.
Here some general guidelines:
- **Low thresholds (5k-20k)**:
- Use for iterative task processing with clear boundaries
- More frequent compaction, minimal context accumulation
- Best for sequential entity processing
- **Medium thresholds (50k-100k)**:
- Multi-phase workflows with fewer, larger natural checkpoints
- Balance between context retention and management
- Suitable for workflows with expensive tool calls
- **High thresholds (100k-150k)**:
- Tasks requiring substantial historical context
- Less frequent compaction preserves more raw details
- Higher per-call costs but fewer compactions
- **Default (100k)**: Good balance for general long-running tasks
**For ticket processing**: The 5k threshold works well because each
ticket\'s workflow generates substantial tool results, but tickets are
independent. After resolving Ticket A, you don\'t need its detailed KB
searches when processing Ticket B.
### Using a Different Model for Summarization
You can also use a faster/cheaper model for generating summaries:
``` python
compaction_control={
"enabled": True,
"model": "claude-haiku-4-5", # Use Haiku for cost-effective summaries
}
```
:::
::: {#w4oyvorzkn .cell .markdown}
### Custom Summary Prompts
You can provide a custom prompt to guide how summaries are generated.
This is especially useful for customer service workflows where you need
to preserve specific types of information.
For example, we could define a custom prompt based on our requirements:
- **Ticket summaries** for all completed tickets
- **Categories and priorities** assigned
- **Teams routed to**
- **Progress status** (tickets completed, tickets remaining)
- **Next steps** in the workflow
``` python
compaction_control={
"enabled": True,
"summary_prompt": """You are processing customer support tickets from a queue.
Create a focused summary that preserves:
1. **COMPLETED TICKETS**: For each ticket you've fully processed:
- Ticket ID and customer name
- Issue category and priority assigned
- Team routed to
- Brief outcome
2. **PROGRESS STATUS**:
- How many tickets you've completed
- Approximately how many remain in the queue
3. **NEXT STEPS**: Continue processing the next ticket
Format with clear sections and wrap in <summary></summary> tags."""
}
```
:::
::: {#7cwipn73ib9 .cell .markdown}
## Compaction Without Tools: Simple Chat Loop
While the examples above focus on tool-heavy agentic workflows, context
compaction is also valuable for **simple conversational applications**
where users drive the conversation.
**Note:** The `compaction_control` parameter demonstrated above works
with `tool_runner` for agentic workflows with tools. For simple chat
applications without tools, you\'ll implement compaction manually using
the same principles.
Consider a chat application where users are having extended
conversations with Claude---discussing complex topics, iterating on
ideas, or working through problems. As the conversation grows, you face
the same context accumulation challenges.
**The Difference**: Instead of tool use triggering token growth, it\'s
the back-and-forth conversation itself. Each exchange adds messages to
the history:
- User asks a question
- Claude provides a detailed response
- User asks for clarification or elaboration
- Claude responds with more context
- This repeats dozens or hundreds of times
Without compaction, by turn 50 you\'re sending the entire conversation
history (all 50 exchanges) on every API call.
**The Solution**: Implement compaction manually in your chat loop using
the same pattern:
1. Track token usage after each turn
2. When threshold is exceeded, request a summary
3. Replace conversation history with the summary
4. Continue the conversation with compressed context
Let\'s see how to implement this:
:::
:::: {#m6akcmnsz09 .cell .code}
``` python
#!/usr/bin/env python3
"""
Simple Compaction Example - User-Driven Chat Loop
This shows the basic pattern for a chat application with compaction.
No tools required - just a simple loop where the user drives continuation.
"""
# Configuration
COMPACTION_THRESHOLD = 3000 # Compact when tokens exceed this (low for demo purposes)
# Structured summarization prompt for compaction
SUMMARY_PROMPT = """You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
1. **Task Overview**
- The user's core request and success criteria
- Any clarifications or constraints they specified
2. **Current State**
- What has been completed so far
- Files created, modified, or analyzed (with paths if relevant)
- Key outputs or artifacts produced
3. **Important Discoveries**
- Technical constraints or requirements uncovered
- Decisions made and their rationale
- Errors encountered and how they were resolved
- What approaches were tried that didn't work (and why)
4. **Next Steps**
- Specific actions needed to complete the task
- Any blockers or open questions to resolve
- Priority order if multiple steps remain
5. **Context to Preserve**
- User preferences or style requirements
- Domain-specific details that aren't obvious
- Any promises made to the user
Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes.
Write in a way that enables immediate resumption of the task.
Wrap your summary in <summary></summary> tags."""
# Message history
messages = []
print("Chat with Claude (type 'quit' to exit, or just hit Enter to continue)")
print("This is a demonstration - try having a conversation and watch compaction trigger")
print("=" * 60)
# Simulate a conversation for demo purposes
demo_messages = [
"Help me understand how Python decorators work",
"Can you show me an example with a timing decorator?",
"How would I make a decorator that takes arguments?",
]
for user_input in demo_messages:
print(f"\nYou: {user_input}")
# Add user message
messages.append({"role": "user", "content": user_input})
# Get Claude's response
response = client.messages.create(
model=MODEL,
max_tokens=2048,
messages=messages,
)
messages.append(
{
"role": "assistant",
"content": response.content,
}
)
print("\nClaude: ", end="")
for block in response.content:
if block.type == "text":
print(f"{block.text[:300]} ...")
# Check if we should compact
usage = response.usage
# Calculate total tokens (includes cache tokens)
total_input_tokens = (
usage.input_tokens
+ (usage.cache_creation_input_tokens or 0)
+ (usage.cache_read_input_tokens or 0)
)
total_tokens = total_input_tokens + usage.output_tokens
cache_info = ""
if usage.cache_creation_input_tokens or usage.cache_read_input_tokens:
cache_info = f" (cache: {usage.cache_creation_input_tokens or 0} write + {usage.cache_read_input_tokens or 0} read)"
print(
f"\n[Tokens: {total_input_tokens} in{cache_info} + {usage.output_tokens} out = {total_tokens} total]"
)
if total_tokens > COMPACTION_THRESHOLD:
print(f"\n{'=' * 60}")
print(f"🔄 Compacting conversation... {len(messages)} messages → ", end="", flush=True)
# Get summary using structured prompt
summary_response = client.messages.create(
model=MODEL,
max_tokens=4096,
messages=messages + [{"role": "user", "content": SUMMARY_PROMPT}],
)
summary_text = "".join(
block.text for block in summary_response.content if block.type == "text"
)
# Replace history with summary
messages = [{"role": "user", "content": summary_text}]
print("1 message")
print(f"{'=' * 60}\n")
print(f"Final conversation messages: {messages[-1].get('content')}")
print("\nDemo complete! In a real application, this loop would continue with user input.")
```
::: {.output .stream .stdout}
Chat with Claude (type 'quit' to exit, or just hit Enter to continue)
This is a demonstration - try having a conversation and watch compaction trigger
============================================================
You: Help me understand how Python decorators work
:::
::::
::: {#b229j75wdjm .cell .markdown}
### Understanding the Chat Loop Pattern
The example above demonstrates manual compaction in a conversational
context. Here\'s how it works:
**Key Components**:
1. **Token Tracking**: After each response, calculate total tokens
(input + output + cache tokens)
2. **Threshold Check**: When total exceeds threshold, trigger
compaction
3. **Summary Request**: Send the same structured SUMMARY_PROMPT to
Claude
4. **History Replacement**: Replace entire message history with just
the summary
5. **Continue**: Next user message builds on the summary, not full
history
**When to Use This Pattern**:
- **Extended brainstorming sessions**: Users exploring ideas with Claude
over many turns
- **Learning conversations**: Tutorials or explanations that span dozens
of exchanges
- **Iterative refinement**: Users providing feedback on drafts, designs,
or solutions
- **Chat applications**: Any multi-turn conversation interface
**Key Differences from Tool Runner**:
---------------------------------------------------------------------------
Aspect Tool Runner (Automatic) Chat Loop (Manual)
-------------- --------------------------------- --------------------------
**Trigger** Automatic when threshold reached You implement threshold
check
**Summary** SDK handles summary request You make explicit API call
**History SDK replaces messages You manually replace list
Management**
**Use Case** Agentic workflows with tools User-driven conversations
---------------------------------------------------------------------------
**Production Considerations**:
1. **Adjust threshold**: Use larger thresholds for real applications
2. **Customize summary prompt**: Tailor to your conversation type
(brainstorming vs. technical support vs. tutoring)
3. **Show user indicators**: Display a message like \"Summarizing
conversation\...\" so users understand the pause
4. **Preserve key context**: Ensure the summary prompt captures
domain-specific information your users care about
This pattern gives you full control over when and how compaction
happens, making it ideal for conversational applications where the
SDK\'s automatic tool-runner compaction isn\'t available.
:::
::: {#d71dwo1dayp .cell .markdown}
## Limitations and Considerations
While automatic context compaction is powerful, there are important
limitations to understand:
### Server-Side Sampling Loops
**Current Limitation**: Compaction does not work optimally with
server-side sampling loops, such as server-side web search tools.
**Why**: Cache tokens accumulate across sampling loops, which can
trigger compaction prematurely based on cached content rather than
actual conversation history.
This feature works best with:
- ✅ Client-side tools (like the customer service API in this cookbook)
- ✅ Standard agentic workflows with regular tool use
- ✅ File operations, database queries, API calls
- ❌ Server-side Extended Thinking
- ❌ Server-side web search tools
### Information Loss
**Trade-off**: Summaries inherently lose some information. While Claude
is good at identifying key points, some details will be compressed or
omitted.
**In ticket processing**:
- ✅ **Retained**: Ticket IDs, categories, priorities, teams, outcomes,
progress status
- ❌ **Lost**: Full knowledge base article text, complete drafted
response text, detailed classification reasoning
This is usually acceptable, you don\'t need every KB article and full
response text in perpetuity, just the completion records.
**Mitigation**:
- Use custom summary prompts to preserve critical information
- Set higher thresholds for tasks requiring extensive historical context
- Structure your tasks to be modular (each phase builds on summaries,
not raw details)
### When NOT to Use Compaction
Avoid compaction for:
1. **Short tasks**: If your task completes within 50k-100k tokens,
compaction adds unnecessary overhead
2. **Tasks requiring full audit trails**: Some tasks need access to ALL
previous details
3. **Server-side sampling workflows**: As mentioned above, wait for
this limitation to be addressed
4. **Highly iterative refinement**: Tasks where each step critically
depends on exact details from all previous steps
### When TO Use Compaction
Compaction is ideal for:
1. **Sequential processing**: Like our ticket workflow---process
multiple items one after another
2. **Multi-phase workflows**: Where each phase can summarize progress
before moving on
3. **Iterative data processing**: Processing large datasets in chunks
or entities one at a time
4. **Extended analysis sessions**: Analyzing data across many entities
5. **Batch operations**: Processing hundreds of items where each is
independent
**Ticket processing is a perfect use case** because:
- Each ticket workflow is largely independent
- You need completion summaries, not full tool results
- Natural compaction points exist (after completing several tickets)
- The workflow is iterative and sequential
:::
::: {#b4pz1jmdidi .cell .markdown}
## Summary
Automatic context compaction is a powerful feature that enables
long-running agentic workflows to exceed typical context limits. In this
cookbook, we\'ve explored compaction through a customer service ticket
processing workflow.
### Next Steps
Try implementing compaction in your own workflows:
1. Identify natural compaction points (after processing each item,
completing each phase, etc.)
2. Start with an aggressive threshold (5k-10k) if you have clear
per-item boundaries
3. Use custom summary prompts to preserve critical information
4. Monitor when compaction triggers and verify quality is maintained
5. Adjust threshold based on your specific needs
For more on effective context management, see [Effective Context
Engineering for AI
Agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents).
:::
---
## Explore the .claude directory - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-directory
Path: 02-Claude-Code-CLI/claude-directory.md
# Explore the .claude directory
Copy pageCopy page
Where Claude Code reads CLAUDE.md, settings.json, hooks, skills, commands, subagents, workflows, rules, and auto memory. Explore the .claude directory in your project and ~/.claude in your home directory.
Copy pageCopy page
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`](env-vars.md), every `~/.claude` path on this page lives under that directory instead. Most users only edit `CLAUDE.md` and `settings.json`. If your repository already has an `AGENTS.md` for other coding agents, Claude Code [can read that](memory.md#agents-md) on its own or alongside `CLAUDE.md`. The rest of the directory is optional: add skills, rules, or subagents as you need them.
[](#explore-the-directory)
Explore the directory
Click files in the tree to see what each one does, when it loads, and an example.
[](#what’s-not-shown)
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, apart from [narrow exceptions](settings.md#security-keys-where-the-stricter-value-applies). See [where to save the file](../13-Enterprise-Admin/managed-settings.md#deploy-a-managed-settings-file) and [which managed source Claude Code uses](../13-Enterprise-Admin/managed-settings.md#precedence-within-the-managed-tier). |
| `CLAUDE.local.md` | Project root | Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to `.gitignore`. |
| `AGENTS.md` | Project root, `.claude/`, or any directory | Project instructions you write for AI coding agents. Claude Code can [load it](memory.md#agents-md) on its own or alongside `CLAUDE.md`. |
| Installed plugins | `~/.claude/plugins` | Cloned marketplaces, installed plugin versions, the `installed_plugins.json` install record, and per-plugin data, managed by `claude plugin` commands. Plugins [synced from your claude.ai account](../08-Plugins-Skills/plugins-loading.md#synced-plugins) download into `~/.claude/plugins/synced/`. For a plugin installed from a marketplace [`command` source](../08-Plugins-Skills/plugins-marketplace-reference.md#command-plugin-source) in link mode, Claude Code stores links here instead of a copy, and the plugin’s files stay in the directory the command prints. A `command` source requires Claude Code v2.1.229 or later. A plugin listed by relative path in a local-directory marketplace also [loads in place](../08-Plugins-Skills/plugins-loading.md#find-plugins-on-disk) from its source directory rather than from a cache copy. See [plugin caching](../08-Plugins-Skills/plugins-loading.md#find-plugins-on-disk) for how orphaned versions are cleaned up. |
`~/.claude` also holds data Claude Code writes as you work: transcripts, prompt history, file snapshots, caches, and logs. See [application data](#application-data) below.
[](#choose-the-right-file)
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](memory.md) |
| Allow or block specific tool calls | `settings.json` `permissions` or `hooks` | project or global | [Permissions](permissions.md), [Hooks](../07-Hooks/hooks.md) |
| Run a script before or after tool calls | `settings.json` `hooks` | project or global | [Hooks](../07-Hooks/hooks.md) |
| Set environment variables for the session | `settings.json` `env` | project or global | [Settings](settings-reference.md#all-settings) |
| Keep personal overrides out of git | `settings.local.json` | project only | [Settings scopes](settings.md#where-settings-live) |
| Add a prompt or capability you invoke with `/name` | `skills/<name>/SKILL.md` | project or global | [Skills](../08-Plugins-Skills/skills.md) |
| Define a specialized subagent with its own tools | `agents/*.md` | project or global | [Subagents](../09-Agents-Patterns/sub-agents.md) |
| Orchestrate many subagents from a script | `workflows/*.js` | project or global | [Dynamic workflows](workflows.md) |
| Connect external tools over MCP | `.mcp.json` | project only | [MCP](../06-MCP-Tools/General/mcp.md) |
| Change how Claude formats responses | `output-styles/*.md` | project or global | [Output styles](output-styles.md) |
[](#file-reference)
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](../13-Enterprise-Admin/server-managed-settings.md) deployed by your organization take precedence over everything, apart from the [exceptions under Settings precedence](settings.md#exceptions-to-managed-settings-precedence)
- 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](env-vars.md) for each one
See [settings precedence](settings.md#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`](#ce-claude-md) | Project and global | ✓ | Instructions loaded every session | [Memory](memory.md) |
| [`rules/*.md`](#ce-rules) | Project and global | ✓ | Topic-scoped instructions, optionally path-gated | [Rules](memory.md#organize-rules-with-claude/rules/) |
| [`settings.json`](#ce-settings-json) | Project and global | ✓ | Permissions, hooks, env vars, model defaults | [Settings](settings.md) |
| [`settings.local.json`](#ce-settings-local-json) | Project only | | Your personal overrides, gitignored when Claude Code saves a setting to it | [Settings scopes](settings.md#where-settings-live) |
| [`.mcp.json`](#ce-mcp-json) | Project only | ✓ | Team-shared MCP servers | [MCP scopes](../06-MCP-Tools/General/mcp.md#mcp-installation-scopes) |
| [`.worktreeinclude`](#ce-worktreeinclude) | Project only | ✓ | Gitignored files to copy into new worktrees | [Worktrees](worktrees.md#copy-gitignored-files-into-worktrees) |
| [`skills/<name>/SKILL.md`](#ce-skills) | Project and global | ✓ | Reusable prompts invoked with `/name` or auto-invoked | [Skills](../08-Plugins-Skills/skills.md) |
| [`commands/*.md`](#ce-commands) | Project and global | ✓ | Single-file prompts; same mechanism as skills | [Skills](../08-Plugins-Skills/skills.md) |
| [`output-styles/*.md`](#ce-output-styles) | Project and global | ✓ | Custom instruction sets that adjust how Claude works | [Output styles](output-styles.md) |
| [`agents/*.md`](#ce-agents) | Project and global | ✓ | Subagent definitions with their own prompt and tools | [Subagents](../09-Agents-Patterns/sub-agents.md) |
| [`workflows/*.js`](#ce-workflows) | Project and global | ✓ | Dynamic workflow scripts written by Claude and saved from `/workflows`; each file becomes a `/<name>` command | [Dynamic workflows](workflows.md) |
| [`agent-memory/<name>/`](#ce-agent-memory) | Project and global | ✓ | Persistent memory for subagents | [Persistent memory](../09-Agents-Patterns/sub-agents.md#enable-persistent-memory) |
| [`~/.claude.json`](#ce-claude-json) | Global only | | App state, OAuth, UI toggles, personal MCP servers | [Global config](settings-reference.md#global-config-settings) |
| [`projects/<project>/memory/`](#ce-global-projects) | Global only | | Auto memory: Claude’s notes to itself across sessions | [Auto memory](memory.md#auto-memory) |
| [`keybindings.json`](#ce-keybindings) | Global only | | Custom keyboard shortcuts | [Keybindings](keybindings.md) |
| [`themes/*.json`](#ce-themes) | Global only | | Custom color themes | [Custom themes](terminal-config.md#create-a-custom-theme) |
[](#frontmatter-fields-by-file)
Frontmatter fields by file
Skills, command files, subagents, output styles, and rules read their configuration from YAML [frontmatter](glossary.md#frontmatter) at the top of the file, and each accepts its own set of fields. This table lists the field names for each file and links to the reference that describes them.
| File | Frontmatter fields | Reference |
|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| `skills/<name>/SKILL.md` | `name`, `description`, `when_to_use`, `argument-hint`, `arguments`, `disable-model-invocation`, `user-invocable`, `allowed-tools`, `disallowed-tools`, `model`, `effort`, `context`, `agent`, `background`, `hooks`, `paths`, `shell`, `metadata`, `license`, `compatibility` | [Skill frontmatter](../08-Plugins-Skills/skills.md#frontmatter-reference) |
| `commands/*.md` | The skill fields except `name` and `paths` | [Skill frontmatter](../08-Plugins-Skills/skills.md#frontmatter-reference) |
| `agents/*.md` | `name`, `description`, `tools`, `disallowedTools`, `model`, `permissionMode`, `maxTurns`, `skills`, `mcpServers`, `hooks`, `memory`, `background`, `effort`, `isolation`, `color`, `initialPrompt`, `omitClaudeMd`, `experimental` | [Subagent frontmatter](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) |
| `output-styles/*.md` | `name`, `description`, `keep-coding-instructions`, `force-for-plugin` | [Output style frontmatter](output-styles.md#frontmatter) |
| `rules/*.md` | `paths` | [Rule frontmatter](memory.md#rules-frontmatter-reference) |
Agents shipped in a [plugin](../08-Plugins-Skills/plugins-components.md#agents) honor a subset of the subagent fields.
[](#troubleshoot-configuration)
Troubleshoot configuration
If a setting, hook, or file isn’t taking effect, see [Debug your configuration](debug-your-config.md) for the inspection commands and a symptom-first lookup table.
[](#application-data)
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 is written to a transcript on disk: file contents, command output, pasted text.
[](#cleaned-up-automatically)
Cleaned up automatically
Claude Code deletes the files in the paths below once they’re older than [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays), as long as it can safely determine the retention period. The default is 30 days and the minimum is 1; setting `0` fails with a validation error. The same age cutoff applies to automatic removal of [orphaned worktrees](worktrees.md#clean-up-subagent-and-background-session-worktrees).
| Path under `~/.claude/` | Contents |
|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `projects/<project>/<session>.jsonl` | Full conversation transcript: every message, tool call, and tool result |
| `projects/<project>/<session>.orphaned-<timestamp>-<suffix>.jsonl`, `projects/<project>/<session>.jsonl.superseded-<timestamp>` | A previous transcript for the session that Claude Code set aside instead of overwriting or deleting it. It doesn’t appear in the session picker |
| `projects/<project>/<session>/subagents/` | [Subagent](../09-Agents-Patterns/sub-agents.md) conversation transcripts, removed with the parent session transcript when it ages out |
| `projects/<project>/<session>/tool-results/` | Large tool outputs spilled to separate files, and full-size copies of [images that MCP tools return](../06-MCP-Tools/General/mcp.md#images-in-tool-results) |
| `file-history/<session>/` | Pre-edit snapshots of files Claude changed, used for [checkpoint restore](checkpointing.md). Holds snapshots for the 100 most recent checkpoints; snapshot files that no retained checkpoint references are deleted, except each file’s first snapshot |
| `plans/` | Plan files written during [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) |
| `debug/` | Per-session debug logs, written while debug logging is on, such as when you start with [`--debug`](cli-reference.md#cli-flags) or run `/debug` |
| `paste-cache/` | Contents of large pastes |
| `image-cache/<session>/` | Attached images saved by Claude Code v2.1.274 and earlier. Later versions save pasted and attached images outside `~/.claude`, in an `images/` directory for each session under the temp directory that [`CLAUDE_CODE_TMPDIR`](env-vars.md) controls. The sweep removes other sessions’ leftover directories here, whatever their age. |
| `uploads/<session>/` | Files you attach from the web or mobile app, and photos you attach from the mobile app, when messaging a [Remote Control](remote-control.md) session. An attachment to a [cloud session](claude-code-on-the-web.md) is saved in that session’s own cloud environment instead, not on your machine. |
| `session-env/` | Per-session environment metadata |
| `tasks/` | Task lists written by the task tools, one directory per list |
| `shell-snapshots/` | Aliases, functions, and shell options captured at startup and applied by the [Bash tool](tools-reference.md#bash-tool-behavior) to each command. Removed on clean exit. The sweep clears any left after a crash. |
| `backups/` | Earlier versions of `~/.claude.json`, copied when Claude Code rewrites the file. Claude Code keeps the five newest, plus a copy of any version it couldn’t parse. |
| `feedback-bundles/` | Redacted transcript archives written by `/feedback` on third-party providers or when no Anthropic credentials are configured, for sending to your Anthropic account team |
| `feedback/drafts/` | Queued [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior) awaiting your review in `/feedback`. Swept after `cleanupPeriodDays` or 30 days, whichever is shorter. When the queue is at its 10-draft limit, Claude Code deletes the oldest draft to make room. |
| `usage-data/` | `report.html` and timestamped report copies written by [`/insights`](../17-Billing-Plans/costs.md#analyze-your-usage-patterns), plus cached per-session analysis data used to build them |
| `skills/.trash/`, `plugins/.trash/` | [Skills](../08-Plugins-Skills/skills.md#how-synced-skills-behave) and [plugins](../08-Plugins-Skills/plugins-loading.md#synced-plugins) that the claude.ai sync removed, such as after you turn one off on claude.ai or stop syncing. The files stay here so you can recover them until the sweep deletes them |
| `plugins/installed_plugins.set-aside.<date>.<hash>.json`, `plugins/installed_plugins.unreadable.<date>.<hash>.kept` | Dated copies Claude Code makes before rewriting [`installed_plugins.json`](../08-Plugins-Skills/plugins-loading.md#find-plugins-on-disk): install records it dropped, and the contents of a file it couldn’t read. |
| `todos/`, `statsig/`, `logs/` | Legacy directories from older versions. No longer written. The sweep removes their contents and then the empty directory. |
Session files in `sessions/`, auto memory, and Claude Desktop and Cowork transcripts each follow their own retention rule:
- **`sessions/`**: holds one small file per running session, used to detect concurrent sessions and crashes. It isn’t part of the age-based sweep: Claude Code removes each file when its session exits and clears crash leftovers on the next launch.
- **Auto memory**: the sweep doesn’t delete the memory files in a project’s [auto memory](memory.md#auto-memory) directory, `projects/<project>/memory/`. Claude Code removes that directory only if it has been empty for the whole retention period. Before v2.1.228, the sweep treated folders inside the memory directory as session data and could delete old files beneath it.
- **Claude Desktop and Cowork transcripts**: Claude Code keeps the transcript of a session you started or most recently continued in Claude Desktop or Cowork at any age. To give these transcripts an age limit, set [`desktopSessionCleanupPeriodDays`](settings-reference.md#desktopsessioncleanupperioddays). When [managed settings](../13-Enterprise-Admin/managed-settings.md) set `cleanupPeriodDays`, Claude Code deletes these transcripts after that period instead. Requires Claude Code v2.1.248 or later; earlier versions delete them after `cleanupPeriodDays`.
Claude Code skips the age-based sweep in these cases:
- **Bare mode**: when you run `claude -p` with [`--bare`](headless.md#start-faster-with-bare-mode), Claude Code doesn’t run the sweep in that session.
- **Paused sweep**: if Claude Code can’t safely determine the retention period, it pauses the retention cleanup sweep; the [`retention_sweep` event](../13-Enterprise-Admin/monitoring-usage.md#retention-sweep-event) lists each configuration that pauses it. When the cause is a settings file that can’t be read or parsed, or settings errors with `cleanupPeriodDays` or `desktopSessionCleanupPeriodDays` explicitly set, Claude Code also shows a warning in `/status` until you fix the settings errors. When [managed settings](../13-Enterprise-Admin/server-managed-settings.md) provide `cleanupPeriodDays`, Claude Code runs the sweep at the managed value in either case.
[](#session-scratchpad-directory)
Session scratchpad directory
The scratchpad is a per-session directory that Claude Code gives Claude for temporary files: intermediate results, helper scripts, and drafts that don’t belong in your project. When Claude says it saved something “to the scratchpad”, the file is there. Claude uses it instead of `/tmp`, and can create, edit, and read files in it without a permission prompt. The scratchpad lives under Claude Code’s temp directory rather than `~/.claude`. Find the current session’s path for your platform:
- **macOS**: `/private/tmp/claude-<uid>/<project>/<session-id>/scratchpad/`
- **Linux**: `/tmp/claude-<uid>/<project>/<session-id>/scratchpad/`, or the same shape under `$TMPDIR` when your system sets one
- **Windows**: `%TEMP%\claude\<project>\<session-id>\scratchpad\`
`<project>` is your working directory path with every character other than letters and digits replaced by `-`, such as `-Users-you-my-project`. If you set [`CLAUDE_CODE_TMPDIR`](env-vars.md), the tree moves under that directory instead. Hooks receive the current session’s path as [`scratchpad_dir`](../07-Hooks/hooks.md#common-input-fields). Scratchpad files last as long as the session’s transcript: the [retention sweep](#cleaned-up-automatically) deletes the directory when it deletes the transcript, and [`claude project purge`](#clear-local-data) doesn’t touch the temp directory. Because the directory sits under the system temp location, your operating system can also clear it, such as on restart. To keep something Claude wrote there, ask Claude to move it into your project. A session has a scratchpad only when all of these hold:
- You’re signed in with a claude.ai account rather than an API key
- The session uses the Anthropic API, not Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry
- [`enableArtifact`](settings-reference.md#enableartifact) isn’t set to `false`
[](#kept-until-you-delete-them)
Kept until you delete them
The retention cleanup sweep doesn’t remove the paths below. Claude Code keeps them until you delete them, apart from the two caches it deletes when you log out.
| Path under `~/.claude/` | Contents |
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `history.jsonl` | Every prompt you’ve typed, with timestamp and project path. Used for up-arrow recall, `Ctrl+R` history search, and `!` shell-command completion. |
| `stats-cache.json` | Aggregated token and cost counts shown by `/usage` |
| `remote-settings.json` | Cached copy of [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) for your organization, or `{}` when your organization has configured none. Only present when the session [fetches them](../13-Enterprise-Admin/server-managed-settings.md#platform-availability). Claude Code checks for updates at startup and hourly during a session. Claude Code deletes it when you log out. |
| `cache/changelog.md` | Cached copy of the Claude Code changelog, shown by `/release-notes`. Refreshed in the background. |
| `policy-limits.json` | Cached feature policy settings for your organization. Only present for some account types. Refreshed automatically. A `policy-limits.json.stamp.json` sidecar records which account or API key the cache belongs to. Claude Code deletes both files when you log out. |
Other files appear depending on which features you use. Caches and lock files are safe to delete. Keep these state files:
- `.credentials.json`: your [login credentials](../13-Enterprise-Admin/iam.md#credential-management)
- `agent-memory/`: [subagent memory](../09-Agents-Patterns/sub-agents.md#enable-persistent-memory)
- `jobs/` and `daemon/`: [background session](../09-Agents-Patterns/agent-view.md#where-state-is-stored) state
[](#plaintext-storage)
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 Claude Code keeps transcripts
- Set [`desktopSessionCleanupPeriodDays`](settings-reference.md#desktopsessioncleanupperioddays) to give Claude Desktop and Cowork transcripts an age limit too
- Set the [`CLAUDE_CODE_SKIP_PROMPT_HISTORY`](env-vars.md) 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 TypeScript Agent SDK; the Python SDK has no equivalent option.
- Use [permission rules](permissions.md) to deny reads of credential files
[](#clear-local-data)
Clear local data
Run `claude project purge` to delete the state Claude Code holds for one project. It deletes:
- 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`
Images you pasted or attached in the project’s sessions and each session’s [scratchpad](#session-scratchpad-directory) are stored under Claude Code’s temp directory rather than `~/.claude`, so the purge doesn’t remove them. The [retention sweep](#cleaned-up-automatically) still deletes the images once they’re older than `cleanupPeriodDays`; a purged session’s scratchpad stays until you delete it or your operating system clears the temp directory. The command prints the full deletion plan and asks for confirmation before removing anything. The examples below use `~/work/my-repo` as a placeholder. Replace it with the path to your project. If no state matches the path, the command prints an error and exits with status 1. Preview the plan without deleting anything:
```python
claude project purge ~/work/my-repo --dry-run
```
The plan lists each matching item and why it is included:
```python
Purge plan for /home/user/work/my-repo:
dir: /home/user/.claude/projects/-home-user-work-my-repo
project transcripts (.jsonl) and memory/
config: projects["/home/user/work/my-repo"]
project entry in ~/.claude.json (trust, history, MCP servers)
filter: /home/user/.claude/history.jsonl
12 prompt(s) typed in this project
shell-snapshots/ are not project-scoped and will not be touched
backups/ may still contain this project entry in old .claude.json snapshots (/home/user/.claude/backups); at most 5 are kept and they rotate out automatically
Dry run: 3 item(s) would be deleted.
```
Delete with a single confirmation prompt:
```python
claude project purge ~/work/my-repo
```
The command prints the same plan, then asks `Delete 3 item(s) for /home/user/work/my-repo? This cannot be undone. [y/N]` and deletes only if you answer `y`. Omit the path to pick a project from an interactive list. Skip the confirmation prompt for use in scripts:
```python
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. You can also delete any of the application-data paths above by hand, apart from the [state files to keep](#state-files-to-keep). 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, and auto memory for every project |
| `~/.claude/history.jsonl` | Up-arrow prompt recall, `Ctrl+R` history search, and `!` shell-command completion |
| `~/.claude/paste-cache/` | Pasted text in recalled prompts; see [paste large content](terminal-config.md#paste-large-content) |
| `~/.claude/uploads/` | Attachments that past [Remote Control](remote-control.md) sessions refer to by path |
| `~/.claude/file-history/` | Checkpoint restore for past sessions |
| `~/.claude/stats-cache.json` | Historical totals shown by `/usage` |
| `~/.claude/usage-data/` | Past [`/insights`](../17-Billing-Plans/costs.md#analyze-your-usage-patterns) reports and the cached analysis data used to build them |
| `~/.claude/feedback-bundles/` | Feedback and bug-report archives you haven’t yet sent to your Anthropic account team |
| `~/.claude/feedback/drafts/` | [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior) you haven’t sent |
| `~/.claude/remote-settings.json` | Nothing. Re-fetched on next launch. |
| `~/.claude/cache/changelog.md` | Nothing. Refreshed in the background. |
| `~/.claude/policy-limits.json` | Nothing. Refreshed automatically. |
| `~/.claude/tasks/` | Task lists that a resumed session would pick up |
| `~/.claude/skills/.trash/`, `~/.claude/plugins/.trash/` | The chance to recover [synced skills](../08-Plugins-Skills/skills.md#how-synced-skills-behave) and [synced plugins](../08-Plugins-Skills/plugins-loading.md#synced-plugins) that Claude Code removed |
| `~/.claude/plugins/installed_plugins.set-aside.<date>.<hash>.json`, `~/.claude/plugins/installed_plugins.unreadable.<date>.<hash>.kept` | The copies of plugin install records that Claude Code dropped or couldn’t read. Nothing reads them back |
| `~/.claude/debug/`, `~/.claude/plans/`, `~/.claude/session-env/`, `~/.claude/shell-snapshots/`, `~/.claude/backups/` | Nothing user-facing |
| `~/.claude/todos/`, `~/.claude/statsig/`, `~/.claude/logs/`, `~/.claude/image-cache/` | Nothing. Legacy directories 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)
Related resources
- [Manage Claude’s memory](memory.md): write and organize CLAUDE.md, rules, and auto memory
- [Configure settings](settings.md): set permissions, hooks, environment variables, and model defaults
- [Create skills](../08-Plugins-Skills/skills.md): build reusable prompts and workflows
- [Configure subagents](../09-Agents-Patterns/sub-agents.md): define specialized agents with their own context
---
## Claude Code on Claude Platform on AWS - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-platform-on-aws
Path: 02-Claude-Code-CLI/claude-platform-on-aws.md
## On this page
- [Prerequisites](#prerequisites)
- [Setup](#setup)
- [1. Configure AWS credentials](#1-configure-aws-credentials)
- [2. Configure Claude Code](#2-configure-claude-code)
- [3. Pin model versions](#3-pin-model-versions)
- [4. Launch and verify](#4-launch-and-verify)
- [Use the Agent SDK](#use-the-agent-sdk)
- [Route through a corporate proxy](#route-through-a-corporate-proxy)
- [Troubleshooting](#troubleshooting)
- [403 Forbidden or AccessDenied on every request](#403-forbidden-or-accessdenied-on-every-request)
- [Requests fail with a missing-workspace error](#requests-fail-with-a-missing-workspace-error)
- [Requests still go to api.anthropic.com](#requests-still-go-to-api-anthropic-com)
- [Additional resources](#additional-resources)
Deployment
# Claude Code on Claude Platform on AWS
Copy pageCopy page
Configure Claude Code to use the Anthropic-operated Claude API with AWS authentication, IAM access control, and AWS Marketplace billing.
Copy pageCopy page
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 API features as the [Claude API](../04-API-Reference/Other/home.md) on the same release schedule. You authenticate with AWS credentials or a workspace API key, and you pay through AWS Marketplace. Client-side features that Claude Code turns on through Anthropic’s feature-flag service are off by default, and the [advisor tool](advisor.md) isn’t available. See the [feature availability matrix](feature-availability.md#summary-by-provider) for the full list. 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](../04-API-Reference/Guides/build-with-claude-claude-platform-on-aws.md).
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)
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)
Setup
[](#1-configure-aws-credentials)
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.
```python
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`](amazon-bedrock.md#advanced-credential-configuration) so Claude Code re-runs your login command and retries instead of failing. Automatic refresh on Claude Platform on AWS requires Claude Code v2.1.198 or later; earlier versions stop with a prompt to run `/login`, which can’t refresh AWS credentials. Add the command to your [settings file](settings.md), such as `~/.claude/settings.json`:
```python
{
"awsAuthRefresh": "aws sso login --profile my-profile"
}
```
Claude Code also runs this command at startup when it can’t validate your existing AWS credentials, and shows the command’s output in an `Authentication` panel until the login completes. With `awsAuthRefresh` configured, run `/login`, select **3rd-party platform**, then select **Claude Platform on AWS · refresh credentials** under **Using 3rd-party platforms**. Claude Code runs the configured command and re-reads your AWS credentials without a restart. **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`:
```python
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](settings.md) `env` block is a convenient way to scope the key to your machine without exporting it globally.
The `/login` and `/logout` commands don’t sign you into a claude.ai subscription for Claude Platform on AWS. Authentication runs through your AWS credentials or workspace API key.
[](#2-configure-claude-code)
2. Configure Claude Code
Set the environment variables that route Claude Code through Claude Platform on AWS instead of the default Anthropic API.
```python
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. Claude Code sends it on every request as the `anthropic-workspace-id` header. Replace the example `wrkspc_01ABCDEFGHIJKLMN` value with your own workspace ID from your Claude Platform on AWS setup. Claude Code computes the base URL as `https://aws-external-anthropic.{region}.api.aws` from the AWS region, which it resolves with the [same precedence as Amazon Bedrock](amazon-bedrock.md#3-configure-claude-code). 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. Amazon Bedrock and Microsoft 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)
3. Pin model versions
Claude Platform on AWS uses the same model IDs as the direct Claude API. The default aliases `fable`, `opus`, `sonnet`, and `haiku` resolve to Claude Code’s built-in defaults for Claude Platform on AWS, which can lag the newest release. Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias resolves to Opus 5.5. Before v2.1.280, it resolved to Opus 5 from v2.1.219, to Opus 4.8 from v2.1.207, and to Opus 4.7 before that. If you deploy Claude Code to a team, pin the model IDs explicitly so a new release doesn’t move everyone at once:
```python
export ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5
export ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-8
export ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-5
export ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5
```
For the full list of model IDs and aliases, see [Models overview](../20-Models/about-claude-models-overview.md). For other model-related variables, see [Model configuration](model-config.md). [Prompt caching](prompt-caching.md) is enabled automatically. To request a 1-hour cache TTL instead of the 5-minute default, set `ENABLE_PROMPT_CACHING_1H=1`. The API bills 1-hour cache writes at a higher rate. See [prompt caching pricing](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#pricing) for the rates. To set different TTLs for your main conversation and for the requests Claude Code makes outside it, [choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself).
[](#4-launch-and-verify)
4. Launch and verify
Start Claude Code and confirm the routing:
```python
claude
```
The startup banner shows `Claude Platform on AWS` when the provider is active. Run `/status` to check the details: the `API provider` line reads `Claude Platform on AWS`, and the output includes your `Workspace ID`, the `AWS region`, and the `Claude Platform on AWS base URL` if you set an override.
[](#use-the-agent-sdk)
Use the Agent SDK
The [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) 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.
```python
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](../05-Agent-SDK/agent-sdk-overview.md).
[](#route-through-a-corporate-proxy)
Route through a corporate proxy
To route traffic through a proxy or [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), 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.
```python
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`.
```python
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)
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)
`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](../04-API-Reference/Endpoints/claude-platform-on-aws-iam-actions.md). 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)
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 in your Claude Platform on AWS setup and export it before starting Claude Code.
[](#requests-still-go-to-api-anthropic-com)
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)
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](../04-API-Reference/Guides/build-with-claude-claude-platform-on-aws.md): subscription, workspace setup, and product reference
- [IAM action reference](../04-API-Reference/Endpoints/claude-platform-on-aws-iam-actions.md): permissions and managed policies
---
## Let Claude coordinate ongoing work with Projects - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-projects
Path: 02-Claude-Code-CLI/claude-projects.md
## On this page
- [When to use a project](#when-to-use-a-project)
- [When something else fits better](#when-something-else-fits-better)
- [How a project is organized](#how-a-project-is-organized)
- [Create a project](#create-a-project)
- [Check the prerequisites](#check-the-prerequisites)
- [Start a new project from scratch](#start-a-new-project-from-scratch)
- [Start from an existing cloud session](#start-from-an-existing-cloud-session)
- [Set up GitHub access](#set-up-github-access)
- [Work in a project](#work-in-a-project)
- [Your first batch](#your-first-batch)
- [Send work and read results](#send-work-and-read-results)
- [Review a thread’s pull request](#review-a-thread%E2%80%99s-pull-request)
- [See what needs you in Overview](#see-what-needs-you-in-overview)
- [Open a thread when you need control](#open-a-thread-when-you-need-control)
- [Choose models and let Claude manage context](#choose-models-and-let-claude-manage-context)
- [Tune how Claude runs a project](#tune-how-claude-runs-a-project)
- [Unblock a thread waiting on approval](#unblock-a-thread-waiting-on-approval)
- [Run a thread on your own computer](#run-a-thread-on-your-own-computer)
- [Give a project standing context](#give-a-project-standing-context)
- [Write project instructions](#write-project-instructions)
- [Decide which repositories to add](#decide-which-repositories-to-add)
- [What threads pick up from your repositories](#what-threads-pick-up-from-your-repositories)
- [Choose an environment for threads](#choose-an-environment-for-threads)
- [Get skills, plugins, connectors, and tools into threads](#get-skills-plugins-connectors-and-tools-into-threads)
- [Project settings reference](#project-settings-reference)
- [Pause, archive, or delete a project](#pause-archive-or-delete-a-project)
- [Usage and cost](#usage-and-cost)
- [What draws on your plan](#what-draws-on-your-plan)
- [See and reduce a project’s usage](#see-and-reduce-a-project%E2%80%99s-usage)
- [How projects relate to other Claude Code features](#how-projects-relate-to-other-claude-code-features)
- [Limitations](#limitations)
- [Troubleshooting](#troubleshooting)
- [A thread looks stuck](#a-thread-looks-stuck)
- [Threads guessed or stalled instead of asking](#threads-guessed-or-stalled-instead-of-asking)
- [Claude hasn’t responded](#claude-hasnt-responded)
- [Repository access errors](#repository-access-errors)
- [A thread hit the usage limit](#usage-limit-reached)
- [Additional usage credits are required](#additional-usage-credits-are-required)
- [Lost contact with your folder](#lost-contact-with-your-folder)
- [Other messages](#context-limit)
- [Related resources](#related-resources)
Platforms and integrations
# Let Claude coordinate ongoing work with Projects
Copy pageCopy page
Give Claude a body of related work in one conversation and let it coordinate parallel cloud sessions that share repositories, instructions, and memory.
Copy pageCopy page
Projects are in public beta on Pro and Max plans and rolling out gradually, starting with accounts that have used [cloud sessions](claude-code-on-the-web.md) and don’t have existing projects in claude.ai chat or Cowork. They aren’t available on Team or Enterprise plans yet. If **Projects** doesn’t appear in the sidebar at [claude.ai/code](https://claude.ai/code) or in the Code tab of the [desktop app](../16-Mobile-Desktop/desktop.md), the rollout hasn’t reached your account, and you can [join the waitlist](https://claude.com/form/projects). [Run agents in parallel](../09-Agents-Patterns/agents.md) lists what you can use in the meantime.
A project is one ongoing conversation where Claude coordinates a stream of related work for you. You tell it what needs doing and it starts a thread for each task. Each thread is usually a [cloud session](claude-code-on-the-web.md): Claude Code running in the cloud rather than on your machine. When a task needs something only your computer has, you can ask Claude to [run that thread on your computer](#run-a-thread-on-your-own-computer) instead of in the cloud, through [Remote Control](remote-control.md). Threads run in parallel, and you can check on them and steer them from your phone. Cloud threads keep going after you close your laptop, while a thread on your computer runs only while that computer is awake. Without a project, running several sessions means doing the coordinating yourself: you decide what each one works on, repeat the same background at the start of each, and check back to see which finished or needs an answer. With a project, you instead:
- **Send work to one place**: paste a bug report, a stack trace, or a list of tasks into the conversation whenever one comes up. Claude starts a thread for each piece of work or passes it to the thread already working in that area, and answers quick questions in place.
- **Set context once**: every new thread starts with the project’s instructions, so a rule you state once, such as which branch to target, reaches all of them.
- **Walk away and come back to finished work**: when you come back an hour later or the next morning, the **Overview** pane shows which threads finished, which pull requests are ready for review, and which thread is waiting for your answer.
If you already know the work you want a project to run, go straight to [Create a project](#create-a-project).
[](#when-to-use-a-project)
When to use a project
A project is worth creating when the work has a goal that outlasts one session and keeps producing tasks. These kinds of work suit a project well:
- **One goal across many repositories**: “Bring every service up to the new lint config.” Claude can run a thread per repository, each with its own pull request, and the [**Overview** pane](#see-what-needs-you-in-overview) shows which ones are ready for review.
- **An area you keep feeding**: the bugs, stack traces, and review requests for one service, pasted into the conversation as they reach you. A pitfall you tell Claude to remember after one fix is in [project memory](#give-a-project-standing-context) for the next.
- **A build or migration bigger than a session**: “Build what `docs/spec.md` describes” or “Move the app off the deprecated ORM.” The work splits into threads that each take a part, decisions you ask Claude to remember early on reach the later cloud threads, and the spec changes and bugs you find during the build go into the same conversation.
- **Work that isn’t code**: a folder of contracts or a support-ticket export you keep coming back to with new questions, such as “find the ten most common integration mistakes in these tickets.” Upload the documents instead of adding a repository, and threads deliver each write-up as a file on the project’s [**Library** tab](#see-what-needs-you-in-overview).
In any of them you can send a batch of tasks, tell Claude to start without asking you to confirm, walk away, and find the threads that need you under [**Waiting on you**](#see-what-needs-you-in-overview) when you’re back, or ask Claude to put part of the work on a schedule as a [routine](web-scheduled-tasks.md). If one of these is your situation, [create a project](#create-a-project).
[](#when-something-else-fits-better)
When something else fits better
A project still fits when only some tasks need your machine. Cloud threads work on GitHub repositories and on the files, folders, and Google Drive folders you upload to the project, and for the occasional task that needs a local database or a tool on your computer, you can ask Claude to [run that task’s thread on your computer](#run-a-thread-on-your-own-computer). Something other than a project fits better in these cases:
- **One task that fits in a session**: “Fix the flaky login test.” Start a [cloud session](claude-code-on-the-web.md) yourself.
- **Work where every task needs your machine**: a local database, a device emulator, or an API behind your VPN. Use a local session, or [agent view](../09-Agents-Patterns/agent-view.md) to run several at once. If the work only needs local files, upload them to the project instead.
- **One task that repeats on a schedule with no conversation around it**: “Post a dependency report every Monday.” Create a [routine](web-scheduled-tasks.md) on its own.
- **Several people giving Claude work and steering it together in a Slack channel**: see [Claude Tag](https://claude.com/docs/claude-tag/overview).
A project draws on the same plan limits as your other Claude Code sessions and uses them faster. [Usage and cost](#usage-and-cost) covers what draws on your plan and how to keep it down.
[](#how-a-project-is-organized)
How a project is organized
A project is one coordinating conversation with Claude plus the threads it starts to do the work. These are its parts:
- **The project conversation**: one long-running session where Claude acts as coordinator. It takes what you send, decides what becomes a thread, and keeps track of every thread it started. It sees what threads report back, not every step they take.
- **Threads**: the workers. Each is a separate session with its own context window that does one piece of work and reports back to the conversation when it finishes. A cloud thread works on its own branch and opens a pull request when the work calls for one.
- **What every cloud thread starts with**:
- The project’s repositories and files, plus its [instructions and memory](#give-a-project-standing-context)
- The `CLAUDE.md` and skills in [each of the project’s repositories](#what-threads-pick-up-from-your-repositories), and in a project with one repository, that repository’s permission rules and hooks too
- The [connectors](#get-skills-plugins-connectors-and-tools-into-threads) on your claude.ai account
- A [cloud environment](#choose-an-environment-for-threads) that sets its network access, environment variables, API credentials, and installed tools
- **The Overview pane**: where you [see all the threads at once](#see-what-needs-you-in-overview) and which of them need you. Its other tabs are **Library** for the files you added and the files threads produced, **Pull requests** for the ones threads opened, and **Routines** for scheduled work in the project.
Cloud threads don’t pick up anything from the Claude Code setup on your own machine. [Get skills, plugins, connectors, and tools into threads](#get-skills-plugins-connectors-and-tools-into-threads) covers how to give them what they’d otherwise be missing. Here is how those parts connect, from you through the conversation to the threads doing the work, with **Overview** tracking their state:
[](#create-a-project)
Create a project
You create and use projects at [claude.ai/code](https://claude.ai/code), in the Code tab of the desktop app, or in the Claude mobile app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) and [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude). In the browser and the desktop app there are two ways to start a project:
- **From scratch**, when you know the stream of work you want Claude to run: open the **New project** dialog and name it. [Start a new project from scratch](#start-a-new-project-from-scratch) walks through the dialog.
- **From a cloud session that’s already doing the work**: choose **Continue as a project** from that session’s menu, and Claude proposes the project’s setup from what the session was doing. See [Start from an existing cloud session](#start-from-an-existing-cloud-session).
Either way, [check the prerequisites](#check-the-prerequisites) first.
[](#check-the-prerequisites)
Check the prerequisites
Before you create a project, check your plan, your GitHub setup, and what the work needs to reach:
- **Plan**: you’re on Pro or Max and **Projects** shows in your sidebar.
- **GitHub, if the project will work on code**: your code is on github.com rather than GitHub Enterprise Server, GitLab, or Bitbucket, your connected GitHub account has push access to it, and the Claude GitHub App is installed on it. If you connected GitHub with [`/web-setup`](web-quickstart.md#connect-from-your-terminal), that token lets your other cloud sessions reach a repository but isn’t enough for a project’s cloud threads, which need the Claude GitHub App. [Set up GitHub access](#set-up-github-access) has the steps.
- **Network, credentials, and tools**: for cloud threads, these come from the project’s [cloud environment](#choose-an-environment-for-threads). The default environment already reaches [common package registries](cloud-environments.md#default-allowed-domains), so check this only if the work needs other domains, a secret, or a tool that isn’t preinstalled. If the work needs an MCP server, check that it shows as connected in your [claude.ai connectors](https://claude.ai/customize/connectors).
[](#start-a-new-project-from-scratch)
Start a new project from scratch
Starting a project from scratch means opening the **New project** dialog, naming the stream of work, and optionally giving it a goal and the repositories and files it works on. Only the name is required, so you can create the project first and fill in the rest as the work takes shape.
1
Open Projects
At [claude.ai/code](https://claude.ai/code) or in the Code tab of the desktop app, select **Projects** in the left sidebar, then select **New project**. In a browser you can also go straight to [claude.ai/code/projects/browse](https://claude.ai/code/projects/browse).
2
Fill in the New project dialog
Scope the project to one stream of work you’ll keep adding to, such as everything it takes to keep one API under its latency target. [When to use a project](#when-to-use-a-project) has more examples. Then fill in the dialog’s fields:
- **Name**: how the project appears in the **Projects** list.
- **Goal** (optional): one line of what you’re trying to get done, such as “Hold p95 API latency under 200 ms”. Claude in the conversation works toward it. Without a goal, Claude works from the tasks you send, and you can add a goal later in **Project settings \> General**.
- **Context** (optional): the GitHub repositories this project works on, plus any files, folders, or Google Drive folders threads should read. Click **Add** for each. Add the repositories most tasks need rather than every one the work might touch; [Decide which repositories to add](#decide-which-repositories-to-add) covers the choice, and you can add more later in **Project settings \> Environment**.
Standing rules for how threads should work go in [project instructions](#give-a-project-standing-context), which you set after the project exists.
3
Create the project
Click **Create project**. The project’s conversation opens with a message box at the bottom, where you describe work for Claude.On your first project, Claude takes a turn of its own as soon as the project is created, unless you send a message first. That turn uses your plan. In it, Claude may:
- Start one thread that explores the repository without changing anything and proposes next steps, if the project has a repository it can read.
- Post **Setup recommendations** drawn from your recent cloud sessions: repositories to add, routines to create, and threads it could start. Every recommended repository and routine starts switched on. Switch off the ones you don’t want, then click **Update setup** to add the rest, or ignore the recommendations and describe work yourself.
The project is now listed under **Projects** in the sidebar, and its conversation is open. [Your first batch](#your-first-batch) covers what to set up before you send it work.
[](#start-from-an-existing-cloud-session)
Start from an existing cloud session
If you already have a cloud session doing work that belongs in a project, open the session’s menu in the sidebar and choose **Continue as a project** or **Move to project**:
- **Continue as a project** creates a new project named after the session and opens it. Claude reads the session and posts **Setup recommendations** in the conversation for you to confirm. The original session stays in your session list, and if it was in the middle of a turn it keeps running, so stop it yourself if you don’t want both working at once. If you use the **Set up project** banner that can appear above a cloud session’s message box instead, the result is the same, except that the session’s running turn stops once the project opens.
- **Move to project** brings the session’s work into an existing project. It posts a message in that project’s conversation asking Claude to read the session and pick up where it left off, and new work continues in the project’s own threads. The original session stays in your session list, unchanged.
[](#set-up-github-access)
Set up GitHub access
Most GitHub setup happens once, not per project. You connect your GitHub account to Claude once, and the Claude GitHub App is installed once per repository, or once for a whole GitHub organization if you give it all repositories. You come back to these steps when you add a repository the Claude GitHub App doesn’t cover yet or one in a GitHub organization that enforces SSO.
1
Connect your GitHub account
If you haven’t used claude.ai/code before, your first visit walks you through connecting GitHub; see [Connect GitHub](web-quickstart.md#connect-github). Otherwise use one of the [GitHub authentication options](claude-code-on-the-web.md#github-authentication-options).
2
Install the Claude GitHub App on the project's repositories
Install the [Claude GitHub App](https://github.com/apps/claude) and grant it the repositories the project will use. On a repository owned by a GitHub organization, only an organization owner can complete the install; if you aren’t one, GitHub sends the owner an install request and the project can’t use the repository until they approve it.
3
Authorize SSO for organizations that enforce it
If a GitHub organization enforces SAML SSO, reconnect GitHub and authorize the Claude app for that organization. Until you do, that organization’s private repositories don’t appear in the **New project** dialog or **Project settings \> Environment**.
When one of these steps is incomplete, the **New project** dialog and the project page name the missing step and link to where you finish it. Finish the step there, then click **Check again** if the dialog offers it. If a repository is still missing from the list afterward, open the Claude GitHub App’s installation on GitHub, at [github.com/settings/installations](https://github.com/settings/installations) for a personal account, and confirm the repository is listed under **Repository access**. For the error messages a thread or the project reports when access is still wrong, see [Repository access errors](#repository-access-errors).
[](#work-in-a-project)
Work in a project
Give Claude work through the project conversation: tasks one at a time or several at once, plus updates and loose thoughts as they come up. Claude routes each message, and threads do the work and report back.
[](#your-first-batch)
Your first batch
Before you send a new project a batch of work, set it up so the first threads come back the way you want:
1. [Write project instructions](#write-project-instructions): the brief every thread starts from, such as which branch to target, how a thread checks its work, and what needs your go-ahead.
2. Send one small piece of the real work, or start one of the threads Claude suggested if it offered any, and open the thread when it finishes to see how it reports back and what it did on its branch. If it assumed something wrong or couldn’t reach what it needed, [Threads guessed or stalled instead of asking](#threads-guessed-or-stalled-instead-of-asking) covers where to fix that.
3. Check **Thread model** and **Thread effort** in **Project settings \> General**. A new project runs every thread on Opus at high effort, which draws on your plan fastest; [Choose models and let Claude manage context](#choose-models-and-let-claude-manage-context) covers the alternatives.
4. Ask Claude to [propose threads before starting them and to run a few at a time](#tune-how-claude-runs-a-project), and drop those limits once a few threads come back the way you want.
[](#send-work-and-read-results)
Send work and read results
Claude decides where each message you send in the conversation goes:
- A quick question usually gets an answer in the conversation.
- New work goes to a new thread or to a thread already working in that area, and Claude tells you which. Each new thread shows up under your message as a card: a box with the thread’s title and status, which you click to open the thread.
- Several unrelated tasks in one message become separate threads.
If Claude routes something differently than you wanted, say so. [Tune how Claude runs a project](#tune-how-claude-runs-a-project) lists things you can tell it, such as reusing an existing thread for follow-ups or answering in place instead of starting a thread. A thread’s full results stay in the thread, and you open its card in the conversation to read them. Files a thread produced are also on the **Library** tab in **Overview**. Sometimes Claude proposes threads instead of starting them, in a **Suggested threads** list. Click the arrow on a suggestion to start that thread. When several are listed, a button under the list starts all of them.
[](#review-a-thread’s-pull-request)
Review a thread’s pull request
When a cloud thread changes code, this is what it does unless you tell it otherwise:
- **Branch**: works on a new branch, started from the repository’s default branch.
- **Pull request**: opens one when you ask, and can open one on its own for a bug fix or another concrete change.
- **After it opens**: watches the pull request with [auto-fix](claude-code-on-the-web.md#auto-fix-pull-requests) turned on, whether or not auto-fix is on for your other cloud sessions. It pushes fixes when CI fails, addresses review comments, and replies in the thread when checks pass and the pull request is ready for you.
When a thread has pushed a branch or opened a pull request, its card in the conversation can show a button for the next step:
- **Resolve conflicts**, **Fix CI**, **Address comments**, and **Merge it** send that instruction to the thread as a message from you, so you can prompt the thread yourself instead of waiting for it to react to the pull request.
- **Review PR** opens the pull request on GitHub.
- **Create PR** appears when an idle thread has pushed a branch but hasn’t opened a pull request. Clicking it creates the pull request from that branch directly rather than sending the thread an instruction to open one.
To change when threads open pull requests, for example only when you ask, or which branch they start from, say so in the task or in [project instructions](#write-project-instructions).
[](#see-what-needs-you-in-overview)
See what needs you in Overview
The **Overview** pane beside the conversation tracks the project’s threads. It’s already open the first time you open a new project. The **Overview** button in the project header closes and reopens it, and shows a dot when a thread is waiting on you. In the desktop app, you also get a desktop notification when Claude posts in the conversation, a thread hits an error, or a thread needs your input, so you don’t have to keep the project open to find out. To also get one each time a thread finishes a turn, or to turn them off for a project, choose **Notifications** in the project’s sidebar menu. These notifications are desktop-only: in a browser, check the dot on the **Overview** button. The pane’s **Threads** tab groups threads by state:
| Group | What’s in it |
|:---------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Ready for review** | Threads whose pull request is open and awaiting review |
| **Waiting on you** | Threads that need your reply or approval, or that failed |
| **Working** | Threads still running |
| **Landing** | Threads whose pull request is approved or queued to merge |
| **Idle** | Threads that finished and aren’t waiting on anything |
| **Resolved** | Threads marked done: by you from the thread’s menu, by Claude once you’ve taken the last step, such as merging its pull request, or automatically after a week with no activity. You can reopen one from the same menu |
The pane’s other tabs are **Library** for the files and folders you added and the files threads produced, **Pull requests** once threads have opened any, and **Routines** for the [routines](web-scheduled-tasks.md) Claude set up from this project.
[](#open-a-thread-when-you-need-control)
Open a thread when you need control
Click a thread’s card in the conversation or its row in **Overview** to open its transcript in the Overview pane. From there you can:
- Read what Claude did, step by step.
- Steer the task by writing in the thread’s own message box. A message there goes straight to that thread, while a follow-up in the project conversation reaches it only when Claude matches the follow-up to that thread.
- Answer a permission prompt the thread is waiting on.
- Interrupt the thread with **Stop**, which replaces the send button while the thread is working, or by pressing Esc.
[](#choose-models-and-let-claude-manage-context)
Choose models and let Claude manage context
Set models and effort in **Project settings \> General**. A new project runs Opus everywhere, with high [effort](model-config.md#adjust-effort-level) for threads and low effort for the conversation:
- **Thread model** and **Thread effort** apply to threads. To use a different model for one task, ask for it in the task; for a thread already running, use that thread’s model picker.
- **Coordinator model** and **Coordinator effort** apply to Claude in the project conversation.
You don’t manage context windows in a project. Threads compact automatically, and the conversation works from recent messages, recent threads, and project memory rather than its full history, so it keeps going for as long as the project runs. Put anything that must never be dropped in [project memory](#give-a-project-standing-context). If one thread outgrows its context, it shows [Claude ran out of context on this turn](#context-limit).
[](#tune-how-claude-runs-a-project)
Tune how Claude runs a project
Tell Claude in the conversation how many threads to run at once, when to post updates, and when to open pull requests. If Claude is coordinating in a way you don’t want, say so. For example, you can say:
- “Propose threads and wait for my go-ahead before starting them” or “Start these now without asking me to confirm”
- “Run at most two threads at a time” or “Reuse an existing thread for follow-ups in the same area”
- “Post shorter updates” or “Only post when something finishes or is blocked”
- “Give me a status update on every thread”
- “Do this task with a smaller model”
- “Don’t open a pull request until I’ve seen the plan”
- “Tell me what’s wrong in these repositories and don’t fix anything yet”, when you want to go through the findings before any of them becomes a thread
- “Answer that here instead of starting a thread”, when Claude starts a thread for something you meant as a quick question
Claude saves preferences like these to [project memory](#give-a-project-standing-context) on its own and follows them in later cloud threads. They’re instructions Claude keeps to, not enforced settings, so a thread limit you give this way isn’t a hard cap. Add one to project instructions when you want it worded exactly and applied to every thread from the start.
[](#unblock-a-thread-waiting-on-approval)
Unblock a thread waiting on approval
Threads run in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) when the thread’s model supports it, so most tool calls run without asking you. When a thread needs your approval, the prompt is inside that thread and the thread waits until you answer it there. Telling Claude in the project conversation to go ahead doesn’t reach it. Each approval covers that prompt, or the rest of that thread if you choose the broader option. To let every thread run certain commands without asking, or to block some, add [permission rules](permissions.md) to the repository’s `.claude/settings.json`. Cloud threads apply them only in a project with one repository; see [What threads pick up from your repositories](#what-threads-pick-up-from-your-repositories).
[](#run-a-thread-on-your-own-computer)
Run a thread on your own computer
When a task needs something only your computer has, such as a local database, a device emulator, or an API behind your VPN, ask Claude to run the thread for that task on your computer instead of in the cloud. When you ask in the project conversation, the thread is a Claude Code session in a folder on your machine, connected through [Remote Control](remote-control.md). The project’s other threads keep running in the cloud. Compared with a cloud thread, a thread on your computer:
- Works with the files, tools, MCP servers, and Claude Code settings on that machine instead of the project’s cloud environment
- Starts with the project’s instructions, but not with its memory files loaded
- Runs only while that computer is awake with Remote Control turned on
1
Connect the folder
On the computer that has the folder the task needs, make it available through Remote Control in one of two ways. Both need Claude Code v2.1.280 or later on that computer.
- **In the Claude desktop app**: open **Settings \> Claude Code**, turn on **Use this computer from your phone and claude.ai**, and add the folder to the list under that switch. Threads can run on this computer while the app is open.
- **In a terminal**: run `claude remote-control` in the folder and leave it running.
2
Ask for the task with Work locally
In the project conversation, choose **Work locally** from the **+** menu beside the message box, which tags your message **Local**, and write what you want done. Saying in the message that the task should run on your computer works too.
3
Allow it on the card
Claude answers with an **Allow Claude to work in a folder on your device** card. Pick the folder if you connected several. Then click **Allow once**.
The thread runs in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), so Claude runs commands and edits files in that folder without asking you each time. If auto mode is unavailable or turned off in that computer’s Claude Code, the thread runs without it, and any permission prompt it raises waits for your answer in the thread, as [Unblock a thread waiting on approval](#unblock-a-thread-waiting-on-approval) describes. While the thread runs, a laptop icon in its header shows whether your computer is connected. Click it to see which folder the thread is using or to turn the connection off. The thread pauses while that computer is asleep, and stops if the desktop app or `claude remote-control` quits. [Lost contact with your folder](#lost-contact-with-your-folder) covers getting it going again. In the desktop app, turn on **Keep this computer awake for Remote Control** under **Settings \> Claude Code** to stop the computer from sleeping on its own. A project can’t run a thread on your computer while [**Require trusted devices**](remote-control.md#trusted-devices) is on for your account.
[](#give-a-project-standing-context)
Give a project standing context
Project memory, project instructions, and the project’s repositories, files, and environment carry context across threads. You set each one once.
| Context | What it carries | How you set it |
|:-------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Project memory | Notes Claude keeps about the project, such as requirements, decisions, and pitfalls, stored as files. Every cloud thread reads the index file `MEMORY.md` when it starts and opens the other files when it needs them | Ask Claude in the project conversation or any cloud thread to remember a requirement, a decision, or a pitfall, or to forget one. Read, edit, and delete the files in **Project settings \> Memory** |
| Project instructions | Text sent to each new thread and to Claude in the project conversation, up to 16,000 characters. [Write project instructions](#write-project-instructions) covers what to put in it | **Project settings \> Memory \> Project instructions**, or ask Claude to change the instructions |
| Repositories, files, and environment | The repositories every cloud thread clones, the folders and files it can read under `/mnt/project-files`, and the cloud environment it runs in | Repositories and environment in **Project settings \> Environment**, or ask Claude in the conversation to add a repository to the project. Files and folders from **Add** on the **Library** tab in **Overview** |
**Project settings \> Memory** lists these files under **Auto memory**, because Claude writes them itself as it works in the project. They’re separate from the [auto memory](memory.md) Claude Code keeps on your machine, even though both use a `MEMORY.md` index. Project memory is also separate from the `CLAUDE.md` files in the project’s repositories. Each cloud thread still reads those `CLAUDE.md` files from its clone when it starts, so put instructions about a repository in its `CLAUDE.md` and notes about the project in project memory.
[](#write-project-instructions)
Write project instructions
Project instructions are the brief every new thread starts from. Click the gear icon in the project header to open **Project settings**, then go to **Memory \> Project instructions**. A useful brief covers:
- What the project is for
- Where the work happens: which repositories, which branch to start from, how to name pull requests
- How a thread checks its own work before calling it done
- What to do when something it needs is missing
- What needs your go-ahead first
For example:
```python
This project holds p95 latency for the payments API under 200 ms: profiling, query and caching fixes, and the dependency upgrades that come with them, in the payments-api repository.
- Branch from main and open one draft pull request per thread.
- Before you call work done, run `make test` and `make lint` and paste the summary lines in your final message.
- If you can't reach something you need, such as a repository, a secret, an API, or a connector, say exactly what's missing in your first message and stop. Don't substitute, mock, or guess.
- Don't merge, force-push, or change CI configuration without asking me in the thread.
```
Rules about one repository, such as its build commands, belong in that repository’s `CLAUDE.md`, which every cloud thread reads when the repository is part of the project. Once work is underway, when you correct a thread, also tell Claude to remember the correction: it goes into [project memory](#give-a-project-standing-context) and later cloud threads start with it.
[](#decide-which-repositories-to-add)
Decide which repositories to add
The repositories you add to a project come with everything in them, their code, `CLAUDE.md`, and skills, in every cloud thread. Repositories you don’t add are still within reach: a cloud thread can add one to itself when its task needs it. Most projects use both:
- **Add it to the project**, in the **New project** dialog, in **Project settings \> Environment**, or by asking Claude in the conversation to add it to the project. Every cloud thread from then on clones it and starts with its `CLAUDE.md` and skills loaded, whether or not the task touches it. Going from one repository to several also changes what threads take from each repository’s `.claude/settings.json`; see [What threads pick up from your repositories](#what-threads-pick-up-from-your-repositories).
- **Leave it off and let threads add it when needed.** A cloud thread whose task needs a repository the project doesn’t have can add it to itself, and a note in the thread says it was added to this thread only. The clone happens partway through the task, so that repository’s `CLAUDE.md` and skills weren’t there when the thread started. The next thread starts without it. A repository added this way needs the same [prerequisites](#check-the-prerequisites) as a project repository: the Claude GitHub App installed on it and push access from your GitHub account.
A project doesn’t need a repository at all. Its cloud threads can still research, write documents, and write and run code in their own sandbox, and they deliver files to the **Library** tab. Any of its cloud threads can still add a repository to itself when a task calls for one. Once the project has repositories, Claude can only add repositories from a GitHub owner the project already uses, whether it adds one to the project or a thread adds one to itself. To bring in a repository from a different owner, add it to the project yourself in **Project settings \> Environment**. For a project that spans many repositories, such as one feature with server, web, mobile, and desktop code, add the one or two repositories nearly every task touches and name the others in [project instructions](#write-project-instructions) so Claude knows where the rest of the code lives. Cloud threads then start small and pull in the other repositories only for the tasks that need them.
[](#what-threads-pick-up-from-your-repositories)
What threads pick up from your repositories
Each cloud thread clones every repository in the project and loads `CLAUDE.md` and skills from all of them. Permission rules, hooks, and `env` come only from the `.claude/settings.json` in the directory the thread starts in: inside the repository when the project has one, and above the clones when it has several, where no repository’s file is read for them.
| In each repository | One repository | Several repositories |
|:----------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------|
| `CLAUDE.md` | Loaded when the thread starts | Loaded from every repository when the thread starts |
| Skills, agents, and commands under `.claude/` | Loaded | Loaded from every repository |
| Plugins enabled in `.claude/settings.json` | Not loaded. Add the plugin in **Project settings \> Plugins** instead | Not loaded. Add the plugin in **Project settings \> Plugins** instead |
| Permission rules, hooks, and `env` defined in `.claude/settings.json` | Apply to the thread, except the `env` keys that [no cloud session honors](cloud-environments.md#what-carries-over-from-your-setup) | Don’t apply |
In a project with several repositories, each clone is attached to the thread as an [additional directory](memory.md#load-from-additional-directories) with `CLAUDE.md` loading turned on, which is why every repository’s `CLAUDE.md` and skills load at start even though the thread starts above them. In such a project, put standing rules in project instructions and give threads environment variables through the [cloud environment](#choose-an-environment-for-threads).
[](#choose-an-environment-for-threads)
Choose an environment for threads
Every new cloud thread starts in the project’s [cloud environment](cloud-environments.md). The environment sets which domains threads can reach, which environment variables they have, which API credentials are added to their requests, and what the setup script installs before Claude starts. Cloud threads use a default Anthropic-hosted environment until you pick one in **Project settings \> Environment**. If cloud threads need to reach an internal API or a private package registry, or need a token your machine normally holds, change the environment rather than the project: see [Network access](cloud-environments.md#network-access), [Add API credentials](cloud-environments.md#add-api-credentials), and [Setup scripts](cloud-environments.md#setup-scripts).
[](#get-skills-plugins-connectors-and-tools-into-threads)
Get skills, plugins, connectors, and tools into threads
Cloud threads don’t have the skills, MCP servers, plugins, and tools installed only on your machine. A thread that Claude runs on your machine through [Remote Control](remote-control.md) uses what’s installed there. To make each of these available to cloud threads:
- Skills, subagents, and commands: commit them to a repository you added to the project, for example a skill at `.claude/skills/<skill-name>/SKILL.md`. Each cloud thread clones every repository in the project and loads `.claude/skills/`, `.claude/agents/`, and `.claude/commands/` from each of them, so a skill committed to one repository is available in every cloud thread. Cloud threads also load the skills you enable for your claude.ai account.
- Plugins: add them in **Project settings \> Plugins**; they load into each new cloud thread. Plugins that a repository declares in its `.claude/settings.json` [don’t load in cloud threads](cloud-environments.md#what-carries-over-from-your-setup).
- MCP servers: cloud threads get their MCP tools from the connectors on your claude.ai account, which are MCP servers you connect once at [claude.ai/customize/connectors](https://claude.ai/customize/connectors) or through the **Manage connectors** link in **Project settings \> Environment**. Every cloud thread can use all of them with no per-project setup. The project conversation itself has no connectors, so send work that needs one as a task for a cloud thread. In a project with one repository, cloud threads also load MCP servers from that repository’s [`.mcp.json`](cloud-environments.md#what-carries-over-from-your-setup). [How connectors reach Claude Code](../06-MCP-Tools/General/mcp.md#how-connectors-reach-claude-code) lists the rules for cloud sessions and the settings that turn connectors off.
- Command-line tools and packages: install them in the environment’s [setup script](cloud-environments.md#setup-scripts).
To see which connectors a running cloud thread has at claude.ai/code, open the thread and select **Connectors** from the **+** menu beside its message box. Turning a connector off there removes it from that thread and saves that as your account default, so new threads and claude.ai chats start without it until you turn it back on. A cloud thread picks up a connector you add or reconnect after the next message you send it.
[](#project-settings-reference)
Project settings reference
You change project settings at claude.ai/code or in the desktop app, not in `settings.json`. Open **Project settings** from **Settings** in the project’s sidebar menu or from the gear icon in the project header. Settings save as you change them; a text field you’re editing, such as the goal or instructions, shows **Save changes** and **Discard** until you leave it. Changes to instructions, repositories, plugins, and environment in **Project settings** reach new threads, not threads already running.
| Setting | Section | What it controls |
|:-----------------------------|:------------|:--------------------------------------------------------------------------------------------------------------------|
| Name, icon, and goal | General | The project’s name and icon in the sidebar, and its one-line goal |
| Coordinator model and effort | General | The model and [effort level](model-config.md#adjust-effort-level) for Claude in the project conversation |
| Thread model and effort | General | The model and effort level for threads |
| Project instructions | Memory | [Standing rules](#give-a-project-standing-context) every new thread receives |
| Project repositories | Environment | The repositories new cloud threads clone |
| Cloud environment | Environment | The [cloud environment](#choose-an-environment-for-threads) new cloud threads run in |
| Connectors | Environment | A link to manage the claude.ai connectors cloud threads get |
| Plugins | Plugins | The plugins that load into each new cloud thread |
| Usage | Usage | [Token use](#usage-and-cost) by thread and by model |
| Memory | Memory | The project’s [memory files](#give-a-project-standing-context) |
| Restart Claude | General | Restarts the project conversation when [Claude stops responding there](#claude-hasnt-responded) |
| Pause, Archive, Delete | General | Stops, hides, or removes the project; see [Pause, archive, or delete a project](#pause-archive-or-delete-a-project) |
[](#pause-archive-or-delete-a-project)
Pause, archive, or delete a project
All three controls are at the bottom of **Project settings \> General**:
- **Pause**: stops everything at once. Every running thread and the conversation are interrupted, no new threads start, routines don’t run, and the project doesn’t accept messages until you resume it. Click **Resume** in the same place or on the banner above the project’s message box; a paused thread continues when you send it a message after that.
- **Archive**: hides the project from the sidebar and archives its threads, which stops any thread that was running or watching a pull request. Routines in the project don’t run while it’s archived. To bring the project back, open it from the Projects page and click **Unarchive**. Its threads stay archived until you unarchive them individually from the session list.
- **Delete**: permanently removes the project along with its threads, its memory, and its files, and turns off the project’s routines. This can’t be undone. Branches and pull requests the threads pushed to GitHub aren’t affected.
[](#usage-and-cost)
Usage and cost
Project usage counts against the same [plan limits](errors.md#youve-hit-your-session-limit) as your other Claude Code sessions, and a project can’t spend past those limits on its own. A thread that reaches your plan’s limit waits and continues on its own when the limit resets, so work you left running starts using your next usage window without a message from you. [A thread hit the usage limit](#usage-limit-reached) covers what you see, how to stop it, and the one case that doesn’t wait. Work goes past your plan’s limits only if you have turned on [usage credits](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription) for your account. A thread can’t turn them on for you.
[](#what-draws-on-your-plan)
What draws on your plan
A project uses your limits faster than a single session does, and on a Pro plan in particular you should expect to reach your limit sooner on days you run one. These are the parts of a project that use your plan:
- **Running threads**: each is a full session, and several can run at once. There’s no fixed number; Claude starts as many as the work calls for, and a limit you [ask for](#tune-how-claude-runs-a-project) is a preference rather than a cap. The enforced limit is 200 new threads per day across your projects.
- **The conversation**: Claude uses tokens of its own reading what threads report and deciding what to do next.
- **Threads watching a pull request**: an idle thread wakes up and uses your plan again when CI fails or a review comment arrives on its pull request. To stop that, ask in the thread for it to stop watching the pull request.
A project with no running threads, no watched pull requests, and no new messages doesn’t use your plan while it sits idle, and neither does an archived project.
[](#see-and-reduce-a-project’s-usage)
See and reduce a project’s usage
Open **Usage** in **Project settings** to see token use by thread and by model, and how much went to the project conversation. To bring it down:
- A follow-up routed to a thread that has been idle longer than the [cache lifetime](prompt-caching.md#cache-lifetime), an hour on Pro and Max within your plan’s limits, re-reads that thread’s whole conversation before doing anything. For new work, asking Claude to start a fresh thread can use less than reviving a large old one.
- For work that doesn’t need the largest model, [choose a smaller model or a lower effort level](#choose-models-and-let-claude-manage-context) for threads, the conversation, or both.
- Ask Claude in the project conversation to run fewer threads at a time, or to answer small questions itself instead of starting a thread.
[](#how-projects-relate-to-other-claude-code-features)
How projects relate to other Claude Code features
Several Claude Code features let more than one session work at the same time, so running work in parallel is not by itself what a project is for. In a project, Claude starts and tracks the sessions instead of you, and each one starts from the same instructions. This is how each neighboring feature connects to a project:
- **Claude Tag**: [Claude Tag](https://claude.com/docs/claude-tag/overview) is Claude in your team’s Slack channels, on Team and Enterprise plans. Anyone in a channel can give it work, everyone in the channel sees and steers it, and it uses connections an admin set up for that channel. A project is yours alone: you’re the only one who sends it work or sees its threads, it uses your own GitHub access and connectors, and it’s on Pro and Max. [How Claude Tag differs from Cowork and Claude Code](https://claude.com/docs/claude-tag/concepts/how-it-works#how-claude-tag-differs-from-cowork-and-claude-code) has the side-by-side.
- **Cloud sessions**: every thread is a [cloud session](claude-code-on-the-web.md) unless you ask Claude to run it on your machine. Either way, Claude starts and tracks it instead of you. A cloud session you started yourself can become a project or feed one through [**Continue as a project** or **Move to project**](#start-from-an-existing-cloud-session).
- **Routines**: when you ask for scheduled work in a project, Claude creates a [routine](web-scheduled-tasks.md) that runs as threads in that project and appears on its **Routines** tab. Routines you create outside a project keep working on their own.
- **Remote Control**: [Remote Control](remote-control.md) connects claude.ai to a Claude Code session running on your machine. When you ask Claude in a project to run a thread on your computer, the project [uses Remote Control to do it](#run-a-thread-on-your-own-computer).
- **Local sessions and agent view**: a session you start yourself in your terminal, IDE, or the desktop app’s local environment can’t be added to a project. [Agent view](../09-Agents-Patterns/agent-view.md) is a screen for tracking several local sessions side by side, and you still start each one and give it its task yourself.
- **Worktrees**: a [worktree](worktrees.md) gives each local session its own working copy of a repository so parallel sessions on your machine don’t overwrite each other. Cloud threads don’t need them: each clones its repositories into its own cloud sandbox and works on its own branch.
- **Agent teams**: an [agent team](../09-Agents-Patterns/agent-teams.md) is one session that starts teammate sessions for a single task, on your machine or inside a cloud session, and ends with that task.
- **Projects in claude.ai chat and Cowork**: the [earlier Projects experience](https://code.claude.com/docs/15-Claude-AI-Features/what-are-projects-91a78d2090.md), which groups conversations and reference files without threads or a coordinator. Those projects keep working as they do today until the redesigned experience reaches them.
[Run agents in parallel](../09-Agents-Patterns/agents.md) compares these options side by side.
[](#limitations)
Limitations
- Projects are available at claude.ai/code, in the desktop app, and in the Claude mobile app, not in the terminal CLI or through Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry. The CLI’s [`claude project`](cli-reference.md) command, which manages local Claude Code state for a directory, is unrelated.
- Project threads are [cloud sessions](claude-code-on-the-web.md), or sessions on your own machine through [Remote Control](remote-control.md), with Anthropic as the model provider in both cases. [Security](../13-Enterprise-Admin/security.md) and [Data usage](../13-Enterprise-Admin/data-usage.md) cover how cloud sessions are isolated and what’s retained, and [Connection and security](remote-control.md#connection-and-security) covers how a thread on your machine connects and what’s stored.
- You can’t add a session you started yourself on your machine to a project. A project reaches your machine only by [running a thread there through Remote Control](#run-a-thread-on-your-own-computer), and that section lists what it needs.
- A cloud thread’s sandbox pauses between turns and resumes when the thread continues. If the sandbox can’t be resumed, the thread continues from a fresh clone, so uncommitted changes can be lost. On long tasks, ask Claude to commit and push work in progress.
- A project belongs to one user. You can’t share a project or its threads with another user, and thread transcripts don’t have the share option other cloud sessions have. There are no organization-level controls for projects during the beta.
- A thread belongs to the one project that started it. You can’t move or copy a thread to another project, or move it out to stand alone. [**Move to project**](#start-from-an-existing-cloud-session) goes the other way only: it brings a cloud session’s work into a project.
[](#troubleshooting)
Troubleshooting
For the GitHub setup prompts in the **New project** dialog, see [Set up GitHub access](#set-up-github-access).
[](#a-thread-looks-stuck)
A thread looks stuck
Claude doesn’t post each step a thread takes, so a thread that shows as running with no new messages in the project conversation is usually still working. A new cloud thread also provisions its [cloud environment](cloud-environments.md) before Claude begins, so its first update takes a moment. Open the thread to read its transcript. If the thread is waiting on a permission prompt, answer it there.
[](#threads-guessed-or-stalled-instead-of-asking)
Threads guessed or stalled instead of asking
When several threads come back having assumed something wrong, worked around missing access, or stopped with “blocked”, the cause is usually the same gap in the project’s setup rather than a problem with each task. Sort out which threads are sound before you fix anything:
1. Ask Claude in the conversation: “For every open thread, list what you asked it to do, what it assumed or couldn’t reach, and what it’s waiting on.” Claude reads each thread and answers in the conversation.
2. For threads that started from a wrong assumption, open the thread from **Overview** and mark it resolved from its menu, or tell it what to do instead in its message box. Its branch and any pull request stay on GitHub until you delete them.
3. Fix the gap once, in [project instructions](#give-a-project-standing-context) or the [environment](#choose-an-environment-for-threads), then send one thread before sending the rest of the work again as new threads.
[](#claude-hasnt-responded)
Claude hasn’t responded
The project conversation shows a “Claude hasn’t responded” banner when Claude is running but its replies aren’t reaching the project. Click **Restart Claude** on the banner, or go to **Project settings \> General** and click **Restart** in the **Restart Claude** row. Claude reconnects to the conversation; any reply it was in the middle of writing is lost, and threads aren’t affected.
[](#repository-access-errors)
Repository access errors
Three messages mean a thread or the project can’t reach one of its repositories. A project’s cloud threads need the [GitHub prerequisites](#check-the-prerequisites) even when your other cloud sessions clone the same repository without trouble.
- **“Couldn’t start the session — Claude doesn’t have GitHub access to this project’s repository”**, reported before the thread starts, when the Claude GitHub App isn’t installed on that repository, is suspended, or isn’t linked to the GitHub account you connected.
- **“Unable to access your repository”**, reported by a thread when its clone fails: GitHub rejected the clone, the repository wasn’t found under the name the project has, or the branch the thread was asked to start from doesn’t exist.
- **“Claude can’t access” a repository**, shown when you save repositories in the **New project** dialog or **Project settings**. The message continues with an install link and a reconnect link. Use the install link if the Claude GitHub App isn’t on that repository, and the reconnect link if it is, since the GitHub App can be installed on GitHub without being linked to the account you connected to Claude. If the message says the GitHub App is suspended or doesn’t include this repository, follow its link to GitHub to fix that.
To fix any of them, click the button the message offers, such as **Install GitHub App** or **Select repositories on GitHub**, then **Check again**. When the block is on the GitHub organization’s side, such as an owner who hasn’t approved the app or an IP allow list that excludes Claude, the message shows a **See how to fix** link instead. If there’s no button, follow [Set up GitHub access](#set-up-github-access), then send another message to retry.
[](#usage-limit-reached)
A thread hit the usage limit
When a thread or the project conversation reaches your plan’s five-hour or weekly limit, it keeps retrying on its own and continues when the limit resets. While it waits, the thread shows **Service is busy** with “Claude is still retrying and will continue automatically.” You don’t need to do anything for the work to continue. If you’d rather it not use your next usage window, click **Stop** in the thread, or [pause the project](#pause-archive-or-delete-a-project) to hold every thread. A thread that a routine started doesn’t wait: its turn stops with a limit error, and you send it a message after the limit resets. [Usage limit errors](errors.md#youve-hit-your-session-limit) explain the limits and when they reset.
[](#additional-usage-credits-are-required)
Additional usage credits are required
A thread or the project conversation made a request your plan covers only with usage credits, such as one to a model or context size your plan doesn’t include, and usage credits aren’t turned on for your account. [Add usage credits to your subscription](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription) covers who can turn them on or buy them on each plan. Once credits are available, send another message to retry.
[](#lost-contact-with-your-folder)
Lost contact with your folder
A thread running on your computer shows this when the Claude Code session there stopped responding, usually because the computer went to sleep or the desktop app or `claude remote-control` quit. Wake the computer, and if the desktop app or `claude remote-control` is no longer running there, start it again: reopen the app and confirm **Use this computer from your phone and claude.ai** is still on under **Settings \> Claude Code**, or run `claude remote-control` again in the same folder.
[](#context-limit)
Other messages
These messages name their own cause. The table gives the next step for each.
| Message | What to do |
|:-----------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ”Unable to connect to repository” with “Claude couldn’t reach GitHub to fetch your repository” | Wait a moment, then send another message to retry |
| ”Unable to connect to repository” with “Claude couldn’t access your repository or environment” | Your GitHub account needs push access to the repository, and the environment must still exist. Check both in **Project settings \> Environment**, then retry |
| ”Couldn’t show the setup proposal” | The app you have open is older than the **Setup recommendations** Claude sent. Refresh the page or restart the desktop app, or ask Claude to propose the setup again |
| ”The project’s environment was removed” | Choose a different environment in **Project settings \> Environment**; the change applies to new threads |
| ”Setup script failed” | Click **Edit setup script** on the error, fix the script in the environment, then send another message. [Setup script failed](web-quickstart.md#setup-script-failed) lists common causes |
| ”Claude ran out of context on this turn” | The thread filled its context window. If the message says the thread continues in a fresh session, it carries on by itself; otherwise ask Claude in the project conversation to start a new thread for the remaining work |
| ”Couldn’t start in” followed by your folder’s name | You allowed a thread to run on your computer, but the session couldn’t start there. When a line under the message gives the reason, fix that, then ask Claude to run the task again |
| ”Claude is out of date on your device” | The computer you picked to run a thread has a Claude Code version older than v2.1.280. Update Claude Code there, or update the desktop app if that’s what connects the folder, then ask Claude to run the task again |
| ”Reached the turn limit” | The thread reached the cap on agentic turns that [`CLAUDE_CODE_MAX_TURNS`](env-vars.md) sets. Send another message to continue, or raise or remove that variable where it’s set |
[](#related-resources)
Related resources
- [Use Claude Code in the cloud](claude-code-on-the-web.md): how the cloud sessions behind each cloud thread work, including GitHub access options and auto-fix on pull requests
- [Configure cloud environments](cloud-environments.md): change what cloud threads can reach on the network, give them environment variables and API credentials, and install tools with a setup script
- [Automate work with routines](web-scheduled-tasks.md): schedules, triggers, and management for routines, including the ones Claude creates from a project
- [Manage multiple agents with agent view](../09-Agents-Patterns/agent-view.md): run and track several sessions on your own machine when the work needs tools or services only your machine can reach
- [Projects redesigned: from folder to conversation](https://claude.com/blog/projects-redesigned): the launch announcement, with the thinking behind making a project a conversation with Claude
---
## Scan your codebase for vulnerabilities - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-security
Path: 02-Claude-Code-CLI/claude-security.md
## On this page
- [Prerequisites](#prerequisites)
- [Models and providers](#models-and-providers)
- [Install the plugin](#install-the-plugin)
- [Uninstall the plugin](#uninstall-the-plugin)
- [Scan and fix your codebase](#scan-and-fix-your-codebase)
- [Scan only your changes](#scan-only-your-changes)
- [Scope large repositories](#scope-large-repositories)
- [Read the scan results](#read-the-scan-results)
- [Fix findings](#fix-findings)
- [Patches are never applied automatically](#patches-are-never-applied-automatically)
- [How the plugin fits with other security tools](#how-the-plugin-fits-with-other-security-tools)
- [Troubleshooting](#troubleshooting)
- [Related resources](#related-resources)
Code review & CI/CD
# Scan your codebase for vulnerabilities
Copy pageCopy page
Install the Claude Security plugin to scan your codebase for vulnerabilities in a Claude Code session and turn findings into patches you review and apply.
Copy pageCopy page
The Claude Security plugin runs a multi-agent vulnerability scan of your codebase inside a Claude Code session. A team of Claude agents maps your architecture, builds a threat model, hunts for vulnerabilities, and independently reviews every finding before writing the report. Use the plugin to scan a whole repository or [only a set of changes](#scan-only-your-changes), such as a branch’s diff, a pull request’s diff, or a single commit, then turn the findings you choose into patches that you review and apply yourself. The plugin runs locally in your session, uses [whichever models you have access to in Claude Code](#models-and-providers), and each scan counts toward your [usage](../17-Billing-Plans/costs.md). If you want a managed service that monitors your repositories, or want to run scans on [Claude Mythos](../20-Models/about-claude-models-introducing-claude-fable-5-and-claude-mythos-5.md), see the [Claude Security](../15-Claude-AI-Features/product-claude-security.md) product, available on the Enterprise plan. The plugin reaches code the managed product can’t reach, such as repositories hosted on GitLab or Bitbucket, or on networks that don’t allow inbound connections. The plugin is also distinct from the review tools already in Claude Code: the [security guidance plugin](security-guidance.md) reviews code as Claude writes it, [`/security-review`](commands.md#all-commands) runs a single pass over your branch, and [Code Review](code-review.md) reviews pull requests. For how the layers stack, see [How the plugin fits with other security tools](#how-the-plugin-fits-with-other-security-tools).
[](#prerequisites)
Prerequisites
To run the plugin, you need:
- A paid plan, Anthropic API access, or a [third-party provider](#models-and-providers), for the [dynamic workflows](workflows.md) the scan uses to orchestrate its agents. On Pro, turn them on from the Dynamic workflows row in `/config`.
- Python 3.9 or later available on your `PATH` as `python3`. Check with `python3 --version`. The plugin’s tooling uses only the Python standard library, so nothing is installed.
- Linux, macOS, or Windows.
- Git, for change scans and for turning findings into patches; those jobs don’t support other version control systems. A full scan works in any directory, with or without version control.
[](#models-and-providers)
Models and providers
A scan runs inside your Claude Code session. The plugin makes no model calls of its own, so there’s no separate API key or provider setting to configure.
- **Model**: the agents that hunt for vulnerabilities, verify findings, and write and review patches run on [your session’s model](../09-Agents-Patterns/sub-agents.md#choose-a-model). To change it, run [`/model`](model-config.md#setting-your-model) in your session before you start a scan. A few supporting steps, such as mapping the repository, use the [`sonnet` alias](model-config.md#model-aliases) instead.
- **Provider**: scans run on a paid plan, with Anthropic API access, or on a [third-party provider](third-party-integrations.md) such as [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md).
On a third-party provider, the `sonnet` alias can resolve to a different version than it does on the Anthropic API. If your account can’t use that version, [pin your model versions](model-config.md#pin-models-for-third-party-deployments), including `ANTHROPIC_DEFAULT_SONNET_MODEL`. [Automatic model fallback](model-config.md#automatic-model-fallback) re-runs a request that a model’s safeguards flag. On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, the request can end with a refusal message instead, depending on [how your deployment is set up](model-config.md#enable-fallback-on-bedrock-agent-platform-and-foundry).
[](#install-the-plugin)
Install the plugin
In a Claude Code session, install from the [official Anthropic marketplace](../08-Plugins-Skills/plugins-anthropic-marketplaces.md):
```python
/plugin install claude-security@claude-plugins-official
```
The command opens the plugin’s details, where you choose an [installation scope](../08-Plugins-Skills/discover-plugins.md#install-a-plugin) to start the install. If the install fails, the fix depends on which message Claude Code reports:
- If it reports `Marketplace "claude-plugins-official" not found`, add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- If it reports that it [can’t find the plugin in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin), check the plugin name for a typo.
Check the install summary. If it reports `Run /reload-plugins to activate.`, see [Apply plugin changes without restarting](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) to activate the plugin in your current session. Once the plugin is active, you’re ready to [scan and fix your codebase](#scan-and-fix-your-codebase).
[](#uninstall-the-plugin)
Uninstall the plugin
To remove the plugin, uninstall it from the `/plugin` menu, or run `claude plugin uninstall claude-security` in your terminal.
[](#scan-and-fix-your-codebase)
Scan and fix your codebase
The plugin adds one command, `/claude-security`, which opens a menu of its three jobs: scanning the codebase, scanning a set of changes, and suggesting patches. The happy path runs a full scan, then turns its findings into patches:
1
Open the Claude Security menu
Run `/claude-security` and pick **Scan codebase**.
2
Choose what to scan
The plugin reads your repository first, then offers the whole repository or a focused area, with each option’s file count and relative cost stated. Pick the whole repository, or answer “I don’t know” and the plugin picks a sensible default for your repository’s size.
3
Confirm the run
A scan may take a while, may use a significant number of tokens, and needs Claude Code left open while it completes. Nothing runs until you confirm.
4
Read the report
While the scan runs, it reports each stage as it starts, with the detail available under [`/workflows`](workflows.md). Results are written to a timestamped directory in your repository, described in [Read the scan results](#read-the-scan-results).
5
Turn findings into patches
Run `/claude-security` again and pick **Suggest patches**, then choose which findings to address. Reviewed patches are written to the report’s `patches/` folder; [Fix findings](#fix-findings) covers how each patch is built and reviewed.
6
Apply the patches you accept
Apply each patch from your shell with `git apply`, in its own pull request. Patches are never applied automatically.
You don’t have to start from the menu: ask for a job directly, as arguments to the command, such as `/claude-security scan my branch`, or in plain language, such as “scan commit abc1234”. The plugin works best in [auto mode](permission-modes.md), which lets the scan’s agents proceed without a permission prompt at each step.
[](#scan-only-your-changes)
Scan only your changes
When your branch has commits its base doesn’t, the `/claude-security` menu offers to scan only that diff, so you can check a branch before merging. You can also scan one of your open pull requests, or a single commit by asking for it, such as “scan commit abc1234”. Only committed changes are scanned: commit or stash in-progress edits first, or run a full scan, which reads the working tree. Change scans need a git repository; full scans of an unversioned directory still work. Finding your open pull requests is the one step that reaches the network, and it’s offered only when your session already has permission to run the GitHub CLI and `gh` is signed in.
[](#scope-large-repositories)
Scope large repositories
On a large repository, scan one area at a time instead of the whole tree. Pick one of the focused scopes the plugin offers, such as your API layer or your authentication code, and the run sizes itself to what you pick. The report’s coverage section states what was and wasn’t examined. Run another scan on a different area anytime.
[](#read-the-scan-results)
Read the scan results
Every scan writes its results into a timestamped `CLAUDE-SECURITY-<timestamp>/` directory in your repository:
- **`CLAUDE-SECURITY-RESULTS.md`**: the report, with each finding’s ID, such as `F1`, plus its impact, exploit scenario, severity, confidence, and recommendation
- **`CLAUDE-SECURITY-RESULTS.jsonl`**: the same findings in machine-readable form, one JSON object per line
- **`CLAUDE-SECURITY-RESULTS.sarif`**: the same findings as a [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html) log for GitHub code scanning and any other tool that reads the standard. The scan classifies findings under their [CWE](https://cwe.mitre.org/) weakness categories
- **`CLAUDE-SECURITY-REVISION-<commit>.json`**: the revision stamp, recording which commit was scanned, at what effort, whether uncommitted changes were part of the scanned tree, and how thoroughly the run was verified, so a report is always tied to the code it describes. A scan outside version control stamps `UNVERSIONED` in place of the commit
That directory is the only change a scan makes to your checkout, and it carries its own `.gitignore`, so a stray `git add` never sweeps a report into a commit. To keep a report in history for an audit trail, delete that one `.gitignore` file and commit the directory like any other. Findings only appear in the report after independent verifier agents analyze them, which keeps reports short and worth reading. Scans are nondeterministic: two scans of the same code can surface different findings. Run scans regularly, and use the revision stamps to attribute each report to the exact code and settings it covered.
[](#fix-findings)
Fix findings
Start the fix flow by picking **Suggest patches** from the `/claude-security` menu, or ask in plain language, such as “fix finding F3”, then pick which findings from the report to address. Patches are built against committed code, and the report has to still describe the code you have: findings whose code has since changed are skipped with a note, and the plugin offers a fresh scan instead of patching from a stale report. Each patch is drafted in a scratch copy of your repository, so your source files stay untouched until you apply a patch yourself. Before delivery, each patch is reviewed by an agent independent of the one that wrote it, which runs your project’s tests against the change when the code has them and reads the diff on its own terms for anything new it might introduce. A patch is written only when that review can vouch that the change addresses the one finding, introduces no new vulnerability, and leaves behavior otherwise unchanged. When it can’t vouch for all three, you get a short note explaining why instead of a patch.
[](#patches-are-never-applied-automatically)
Patches are never applied automatically
Applying a patch is always your decision. Patches are written to the report’s `patches/` folder, one `F<n>.patch` per finding with a note beside it explaining the change. Apply one from your shell, or ask Claude to apply it and open a pull request:
```python
git apply CLAUDE-SECURITY-<timestamp>/patches/F1.patch
```
When the patched code has no tests, the patch’s note says so, so you know its review ran without a test pass. Apply each patch in its own pull request so it can be reviewed and tested on its own.
[](#how-the-plugin-fits-with-other-security-tools)
How the plugin fits with other security tools
The Claude Security plugin is the on-demand deep-scan layer in a defense-in-depth stack, alongside the [security guidance plugin](security-guidance.md), [`/security-review`](commands.md#all-commands), [Code Review](code-review.md), the managed [Claude Security](../15-Claude-AI-Features/product-claude-security.md) product, and your existing scanners:
| Stage | Tool | What it covers |
|:-----------------------|:-------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------|
| In session | [Security guidance plugin](security-guidance.md) | Common vulnerabilities in code Claude writes, fixed in the same session |
| On demand, single pass | [`/security-review`](commands.md#all-commands) | One-time security pass on the current branch |
| On demand, deep scan | Claude Security plugin | Multi-agent scan of a repository or diff, with independently reviewed findings and patches |
| On pull request | [Code Review](code-review.md), Team and Enterprise plans | Multi-agent correctness and security review with full codebase context |
| Managed | [Claude Security](../15-Claude-AI-Features/product-claude-security.md), Enterprise plan | Hosted scanning that monitors connected repositories |
| In CI | Your existing static analysis and dependency scanners | Language-specific rules, supply-chain checks, and policy enforcement |
The plugin doesn’t replace your existing source-code security tools. Run it alongside static analysis, dependency scanning, and code review: it reasons about your code the way a human security researcher would, which complements the deterministic checks those tools provide.
[](#troubleshooting)
Troubleshooting
**The `/claude-security` menu opens with a Python warning.** The plugin needs `python3` 3.9 or later on your `PATH`. When it can’t find `python3` at all, the menu warns that Claude Security won’t work until one is installed; when the first `python3` on your `PATH` is older, the warning names the version it found. Install Python 3, or put a newer `python3` first on your `PATH`, then start a new session. **You may see a “safeguards flagged this message” notice when scanning on a Fable model.** The message names the model you’re running. Fable’s cybersecurity safety classifiers flag certain requests, and Claude Code re-runs a flagged request on an Opus model through [automatic model fallback](model-config.md#automatic-model-fallback). This is expected. When the request re-runs, the scan should still complete successfully.
[](#related-resources)
Related resources
To go deeper on the pieces this page touches:
- [Security guidance plugin](security-guidance.md): catch issues in code as Claude writes it, in the same session
- [Code Review](code-review.md): set up the PR-time multi-agent review
- [Claude Security](../15-Claude-AI-Features/product-claude-security.md): the managed service that monitors connected repositories
- [Claude Code security](../13-Enterprise-Admin/security.md): how Claude Code approaches trust, permissions, and safeguards
- [Install and manage plugins](../08-Plugins-Skills/discover-plugins.md): find and install other plugins from the official marketplace
---
## Claude Tag - Claude Code Docs
Source: https://code.claude.com/docs/en/claude-tag
Path: 02-Claude-Code-CLI/claude-tag.md
# Claude Tag
Copy pageCopy page
Bring Claude into your team’s Slack channels with Claude Tag and find its setup and usage documentation on claude.com.
Copy pageCopy page
[Claude Tag](../14-Connectors/claude-for-slack.md) is a Slack integration that runs `@Claude` in your team’s channels as your organization’s shared identity with admin-configured access. Anyone in a channel can tag `@Claude` into a thread and assign it a task. Read the [Claude Tag documentation](https://claude.com/docs/claude-tag/overview) on claude.com to set it up and start using it. Claude Tag is available on Team and Enterprise plans, and is distinct from the earlier [Claude Code in Slack](../14-Connectors/slack.md), which runs each session under an individual user’s account. On Pro and Max plans, where Claude Tag isn’t available, Claude Code in Slack remains the setup path.
---
## CLI reference - Claude Code Docs
Source: https://code.claude.com/docs/en/cli-reference
Path: 02-Claude-Code-CLI/cli-reference.md
## On this page
- [CLI commands](#cli-commands)
- [CLI flags](#cli-flags)
- [System prompt flags](#system-prompt-flags)
- [System prompt flags in resumed conversations](#system-prompt-flags-in-resumed-conversations)
- [See also](#see-also)
Reference
# CLI reference
Copy pageCopy page
Complete reference for Claude Code command-line interface, including commands and flags.
Copy pageCopy page
[](#cli-commands)
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 gateway` | Start the self-hosted [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) server, for administrators deploying SSO and policy in front of Claude Code on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry. Requires `--config` pointing at a [`gateway.yaml`](../13-Enterprise-Admin/claude-apps-gateway-config.md). | `claude gateway --config gateway.yaml` |
| `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](../01-Getting-Started/setup.md#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. The JSON includes a `configDirectory` field naming the [configuration directory](claude-directory.md) the CLI uses. The field requires Claude Code v2.1.268 or later | `claude auth status` |
| `claude agents` | Open [agent view](../09-Agents-Patterns/agent-view.md) to monitor and dispatch parallel background sessions. Use `--cwd <path>` to show only sessions started under that directory, or `--json` to print active sessions as a JSON array for scripting (`--json --all` also includes completed background sessions). Pass `--permission-mode`, `--model`, `--effort`, or `--agent` to set [defaults for dispatched sessions](../09-Agents-Patterns/agent-view.md#permission-mode-model-and-effort). Accepts `--settings`, `--add-dir`, `--plugin-dir`, and `--mcp-config` like the top-level `claude` command. Opening agent view requires an interactive terminal | `claude agents --json` |
| `claude attach <id>` | Attach to a [background session](../09-Agents-Patterns/agent-view.md#manage-sessions-from-the-shell) in this terminal | `claude attach 7c5dcf5d` |
| `claude auto-mode defaults` | Print the built-in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) classifier rules as JSON. Use `claude auto-mode config` to see your effective config with settings applied. `--label <prefix>` prints only the rules whose label starts with that prefix, matched case-insensitively. Requires Claude Code v2.1.208 or later | `claude auto-mode defaults --label 'Git Destructive'` |
| `claude auto-mode reset` | Restore the default [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) configuration by removing the `autoMode` section from your user settings file. Prompts for confirmation before writing; pass `-y`/`--yes` to skip the prompt. Rules from [managed settings](../13-Enterprise-Admin/server-managed-settings.md) or the `--settings` flag still apply. Requires Claude Code v2.1.212 or later. See [Inspect the defaults and your effective config](auto-mode-config.md#inspect-the-defaults-and-your-effective-config) | `claude auto-mode reset --yes` |
| `claude daemon status` | Print the background-session [supervisor’s](../09-Agents-Patterns/agent-view.md#the-supervisor-process) state, version, socket directory, and worker count for diagnostics. Exits 1 if the supervisor isn’t running | `claude daemon status` |
| `claude daemon stop --any` | Stop the background-session [supervisor](../09-Agents-Patterns/agent-view.md#the-supervisor-process) and the sessions it hosts. Pass `--keep-workers` to leave background sessions running so the next supervisor reconnects to them. `--any` confirms stopping an on-demand supervisor, which is the default. Use this to recover from an [unresponsive supervisor](../09-Agents-Patterns/agent-view.md#agent-view-says-the-background-service-did-not-respond) | `claude daemon stop --any --keep-workers` |
| `claude doctor` | Print read-only installation and settings diagnostics from the terminal without starting a session, including install health, settings-file validation errors, and Remote Control eligibility. For the in-session setup checkup that can also apply fixes, run [`/doctor`](commands.md#all-commands) | `claude doctor` |
| `claude import [source]` | Start an interactive session that runs [`/import`](commands.md#all-commands) to bring configuration from other coding agents into Claude Code. Accepts the same `--dry-run` and `--yes` options as the command. Not available on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or Claude Platform on AWS. Also unavailable when you turn off [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching). Requires Claude Code v2.1.213 or later | `claude import codex --dry-run` |
| `claude logs <id>` | Print recent output from a [background session](../09-Agents-Patterns/agent-view.md#manage-sessions-from-the-shell) | `claude logs 7c5dcf5d` |
| `claude mcp` | Configure Model Context Protocol (MCP) servers | See the [Claude Code MCP documentation](../06-MCP-Tools/General/mcp.md). |
| `claude mcp login <name>` | Run a configured MCP server’s OAuth flow without opening the interactive `/mcp` panel. Works for HTTP, SSE, and claude.ai connector servers. Add `--no-browser` over SSH to print the authorization URL instead of opening a browser, then paste the redirect URL back at the prompt. See [Authenticate from the command line](../06-MCP-Tools/General/mcp.md#authenticate-from-the-command-line) | `claude mcp login sentry` |
| `claude mcp logout <name>` | Clear stored OAuth credentials for an MCP server | `claude mcp logout sentry` |
| `claude plugin` | Manage Claude Code [plugins](../08-Plugins-Skills/plugins.md). Alias: `claude plugins`. See [plugin reference](../08-Plugins-Skills/plugins-cli-reference.md#claude-plugin-commands) 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-directory.md#clear-local-data) | `claude project purge ~/work/repo --dry-run` |
| `claude remote-control` | Start a [Remote Control](remote-control.md) server to control Claude Code from Claude.ai or the Claude app. Runs in server mode (no local interactive session). See [Server mode flags](remote-control.md#start-a-remote-control-session). After you stop the server, you can bring back the sessions it was serving. See [Resume sessions after stopping the server](remote-control.md#resume-sessions-after-stopping-the-server) | `claude remote-control --name "My Project"` |
| `claude respawn <id>` | Restart a [background session](../09-Agents-Patterns/agent-view.md#manage-sessions-from-the-shell), running or stopped, with its conversation intact. Use `--all` to restart every running session, e.g. to pick up an updated Claude Code binary | `claude respawn 7c5dcf5d` |
| `claude rm <id>` | Remove a [background session](../09-Agents-Patterns/agent-view.md#manage-sessions-from-the-shell) from the list. When the removal is [refused over the session’s worktree](../09-Agents-Patterns/agent-view.md#what-deleting-a-session-removes) and a second `claude rm` can resolve it, the refusal prints the exact flag and value to pass: `--discard-unpushed <commit>@<worktree-id>` discards a worktree that has unpushed commits along with those commits, and `--force-remove-worktree <worktree-id>` deletes a worktree directory that git or the `WorktreeRemove` hook couldn’t remove. `--discard-unpushed` requires Claude Code v2.1.260 or later, and `--force-remove-worktree` requires v2.1.268 or later. The conversation transcript stays on your local machine, available through `claude --resume` | `claude rm 7c5dcf5d` |
| `claude self-hosted-runner` | Start a runner process that registers this machine or container with a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) and hosts Claude Code cloud sessions on your infrastructure. Run `claude self-hosted-runner setup` for a guided operator walkthrough, `claude self-hosted-runner doctor` to [diagnose a deployed runner](../13-Enterprise-Admin/self-hosted-environments-deploy.md#troubleshooting), and `claude self-hosted-runner orchestrator` to spawn [on-demand runners](../13-Enterprise-Admin/self-hosted-environments-configuration.md#on-demand-runners). Requires Claude Code v2.1.224 or later | `claude self-hosted-runner setup` |
| `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](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token) | `claude setup-token` |
| `claude stop <id>` | Stop a [background session](../09-Agents-Patterns/agent-view.md#manage-sessions-from-the-shell). Also accepts `claude kill` | `claude stop 7c5dcf5d` |
| `claude ultrareview [target]` | Run [ultrareview](ultrareview.md#run-ultrareview-non-interactively) 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 45-minute default. Use `--post` on a `github.com` pull request target to post the finished findings to the PR as one plain comment from your GitHub account. `--no-post` is the default. `--post` and `--no-post` require Claude Code v2.1.227 or later. See [Post findings to the pull request](ultrareview.md#post-findings-to-the-pull-request) | `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?`. As of v2.1.199, `claude --dangerously-skip-permissions daemon <subcommand>` runs the `daemon` subcommand. Earlier versions treated `daemon <subcommand>` as the prompt for a new interactive session, so the subcommand never ran when the flag came first, a common setup when `claude` is aliased to include the flag. Only a leading `--dangerously-skip-permissions` or `--allow-dangerously-skip-permissions` routes to `daemon` this way; any other leading flag still starts an interactive session.
[](#cli-flags)
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.
[TABLE]
[](#system-prompt-flags)
System prompt flags
Claude Code provides five flags for customizing the system prompt. Four set its text, and with `--system-prompt-snapshot` you control whether a conversation keeps the text it started with. All five 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-snapshot` | With `off`, rebuilds the prompt on every request. With `on`, the default, reuses a recorded prompt where [recording applies](#system-prompt-flags-in-resumed-conversations) | `claude --append-system-prompt "Draft rules" --system-prompt-snapshot off` |
`--system-prompt` and `--system-prompt-file` are mutually exclusive. The append flags can be combined with either replacement flag. When the replacement text combines instructions that are the same on every run with context that changes per run, add a line containing only `__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__` between the instructions and the context. Claude Code splits the prompt at the first such line and removes that line, so the part above it stays cached while the part below changes. Requires Claude Code v2.1.275 or later. [Cache the static part of a custom prompt](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#cache-the-static-part-of-a-custom-prompt) lists the configurations where the split applies. 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. For persistent personas you can switch between and share across a project, use [output styles](output-styles.md). For project conventions Claude should always follow, use [CLAUDE.md](memory.md). The [Agent SDK guide on system prompts](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#decide-on-a-starting-point) covers the same decision in more depth.
[](#system-prompt-flags-in-resumed-conversations)
System prompt flags in resumed conversations
By default, Claude Code builds the system prompt once, on a conversation’s first request, with the text from any system prompt flags applied, and records it in the session. Until the conversation is compacted, every later request uses that recorded prompt, including after you return to the conversation with `--resume` or `--continue`. If you pass different system prompt flag text, or none, on that later launch, it takes effect once the conversation is compacted or when you start a new conversation. Outside of [cloud sessions](cloud-environments.md), if you start Claude Code in [bare mode](headless.md#start-faster-with-bare-mode) by passing `--bare` or setting `CLAUDE_CODE_SIMPLE=1`, recording stays off unless you pass `--system-prompt-snapshot on`. Before v2.1.268, sessions that don’t [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), including sessions on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, rebuilt the prompt on every request and `--system-prompt-snapshot` had no effect. To rebuild the prompt on every request instead, for example while you iterate on its wording across `--continue` runs, pass `--system-prompt-snapshot off`. Before v2.1.265, passing any of the system prompt flags also turned recording off unless you passed `--system-prompt-snapshot on`.
[](#see-also)
See also
- [Chrome extension](../03-IDE-Integrations/chrome.md) - Browser automation and web testing
- [Interactive mode](interactive-mode.md) - Shortcuts, input modes, and interactive features
- [Quickstart guide](../01-Getting-Started/quickstart.md) - Getting started with Claude Code
- [Common workflows](common-workflows.md) - Advanced workflows and patterns
- [Settings](settings.md) - Configuration options
- [Agent SDK documentation](../05-Agent-SDK/agent-sdk-overview.md) - Programmatic usage and integrations
---
## Configure cloud environments - Claude Code Docs
Source: https://code.claude.com/docs/en/cloud-environments
Path: 02-Claude-Code-CLI/cloud-environments.md
## On this page
- [The Default environment](#the-default-environment)
- [Configure your environment](#configure-your-environment)
- [Set environment variables](#set-environment-variables)
- [Add API credentials](#add-api-credentials)
- [Requirements](#requirements)
- [Add a credential](#add-a-credential)
- [Which requests get the credential](#which-requests-get-the-credential)
- [Requests that never get the credential](#requests-that-never-get-the-credential)
- [Select an environment from the CLI](#select-an-environment-from-the-cli)
- [Archive an environment](#archive-an-environment)
- [Organization-shared environments](#organization-shared-environments)
- [Set the environment a Claude Tag channel uses](#set-the-environment-a-claude-tag-channel-uses)
- [Network access](#network-access)
- [Access levels](#access-levels)
- [Allow specific domains](#allow-specific-domains)
- [GitHub proxy](#github-proxy)
- [Security proxy](#security-proxy)
- [What’s available in cloud sessions](#what%E2%80%99s-available-in-cloud-sessions)
- [What carries over from your setup](#what-carries-over-from-your-setup)
- [Installed tools](#installed-tools)
- [Work with GitHub issues and pull requests](#work-with-github-issues-and-pull-requests)
- [Link output back to the session](#link-output-back-to-the-session)
- [Run tests, start services, and add packages](#run-tests-start-services-and-add-packages)
- [Run tests](#run-tests)
- [Start services](#start-services)
- [Add packages](#add-packages)
- [Resource limits](#resource-limits)
- [Time limits](#time-limits)
- [Setup scripts](#setup-scripts)
- [Script requirements](#script-requirements)
- [Environment caching](#environment-caching)
- [Setup scripts vs. SessionStart hooks](#setup-scripts-vs-sessionstart-hooks)
- [Install dependencies with a SessionStart hook](#install-dependencies-with-a-sessionstart-hook)
- [Limitations in cloud sessions](#limitations-in-cloud-sessions)
- [Default allowed domains](#default-allowed-domains)
- [Related resources](#related-resources)
Environments
# Configure cloud environments
Copy pageCopy page
Configure cloud environments for Claude Code cloud sessions: network access levels, environment variables, setup scripts, and environment caching.
Copy pageCopy page
Cloud environments apply to [cloud sessions](claude-code-on-the-web.md), which are available on Pro, Max, and Team plans, and for Enterprise users with [premium seats or Chat + Claude Code seats](../17-Billing-Plans/using-claude-code-with-your-team-or-enterprise-plan.md).
Each [cloud session](claude-code-on-the-web.md) runs in a cloud environment. You can configure an environment to allow or deny [network access](#access-levels), [set environment variables](#set-environment-variables) for the session, on Pro and Max plans store [API credentials](#add-api-credentials) that sessions use without seeing them, and run a [setup script](#setup-scripts) before Claude starts working. The same environments apply wherever you start a cloud session: the [Desktop app](../16-Mobile-Desktop/desktop.md), the [Claude mobile app](../16-Mobile-Desktop/mobile.md), your browser at [claude.ai/code](https://claude.ai/code), the terminal with [`claude --cloud`](claude-code-on-the-web.md#from-terminal-to-cloud), [routines](web-scheduled-tasks.md), and [Claude Tag](https://claude.com/docs/claude-tag/overview). Each of these surfaces can also route to a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md). [Availability and limitations](../13-Enterprise-Admin/self-hosted-environments.md#availability-and-limitations) covers what Claude can’t use yet when a Claude Tag session runs in one.
[Remote Control](remote-control.md) sessions connect the web and mobile interfaces to a session on your own machine, which uses your machine’s network and files, not a cloud environment. Claude Tag channel sessions use organization-level environments only, either [shared environments](#organization-shared-environments) or [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md).
[](#the-default-environment)
The Default environment
If you don’t have an environment yet, onboarding sets up the **Default** environment. How depends on where you onboard:
- **CLI flows such as `/web-setup`**: create **Default** for you
- **Web onboarding on Pro and Max**: creates **Default** for you
- **Web onboarding on Team and Enterprise**: shows a **Create your first cloud environment** form unless an Owner has turned on [Quick web setup](claude-code-on-the-web.md#github-authentication-options); keep the form’s defaults and click **Create & finish** to get the same **Default** environment
**Default** carries no configuration of its own:
- [**Trusted** network access](#access-levels): sessions reach package registries and other [allowlisted domains](#default-allowed-domains), and nothing else through the session’s network.
- No other configuration: **Default** defines no environment variables or setup script, so sessions start with just the [pre-installed tools](#installed-tools).
With only **Default** available, every session runs in it. When you have more than one environment, sessions choose one per surface:
- In the Desktop app, the mobile app, and at claude.ai/code, sessions you start yourself use the environment shown in the [selector](#configure-your-environment). An [organization default](#organization-shared-environments) set by an Owner fills the selection when you haven’t picked one. Threads in a [project](claude-projects.md#project-settings-reference) use the environment set in the project’s settings instead.
- From the CLI, Claude Code uses your [`/remote-env` pick](#select-an-environment-from-the-cli), or falls back to the Anthropic-hosted environment when your list has one, and otherwise to the first environment in your list that isn’t a bridge environment, an entry [Remote Control](remote-control.md) registers to represent your own machine rather than a cloud environment. For a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md), passing `--environment <environment-id>` with its `ccpool_` ID [when you dispatch a session](../13-Enterprise-Admin/self-hosted-environments-testing.md#run-the-test-loop) overrides the `/remote-env` pick and the fallback for that invocation. Claude Code rejects Anthropic-hosted `env_` IDs passed to the flag, so use `/remote-env` to target those. The flag requires Claude Code v2.1.224 or later.
Configure an environment when the default isn’t enough: when Claude needs to reach domains outside the [default allowlist](#default-allowed-domains), needs environment variables set for its sessions, or needs dependencies installed before it starts working.
[](#configure-your-environment)
Configure your environment
Create, edit, and archive environments from the environment selector, which you reach at [claude.ai/code](https://claude.ai/code) after [web onboarding](web-quickstart.md), or from the prompt box in the [Desktop app](../16-Mobile-Desktop/desktop.md#cloud-sessions). Environments you create are personal to your account; [shared environments](#organization-shared-environments) created by an Owner appear in the same selector. See [Installed tools](#installed-tools) for what’s available without any configuration.
1
Open the environment selector
On [claude.ai/code](https://claude.ai/code), select the cloud icon showing the current environment’s name, in the row above the message box. There’s no settings page or direct URL for the selector.
2
Add or edit an environment
Select **Add cloud environment**, or hover over an existing environment and select the settings icon that appears on the right. The dialog includes the name, network access level, environment variables, and setup script. When you edit an existing cloud environment on a Pro or Max plan, the dialog also includes [API credentials](#add-api-credentials).
[](#set-environment-variables)
Set environment variables
Environment variables use `.env` format, one `KEY=value` pair per line. Plain values don’t need quotes, and if you quote a value with a matching pair, the quotes don’t become part of the value. Quote a value that spans multiple lines or contains a `#`: in an unquoted value, `#` starts a comment and the rest of the line is dropped. The following example defines three variables.
```python
NODE_ENV=development
LOG_LEVEL=debug
DATABASE_URL=postgres://localhost:5432/myapp
```
Each session copies the environment’s values once, at startup, into ordinary environment variables that any command Claude runs can read, except `OTEL_*` variables. Claude Code uses those for its own [telemetry export](../13-Enterprise-Admin/monitoring-usage.md#telemetry-from-cloud-sessions-and-claude-tag) and doesn’t pass them to the commands it runs. Because running sessions don’t re-read the configuration, editing or adding variables affects sessions you start afterward; sessions already running keep the values they started with. A cloud session also sets some variables itself when it starts. For [`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`](claude-code-on-the-web.md#manage-context), the value the session sets overrides one you add here, so adding that key here has no effect. Anyone who uses the environment can read the values. On Pro and Max plans, use an [API credential](#add-api-credentials) instead for a key the agent proxy can attach to a request. The [requests that never get a credential](#requests-that-never-get-the-credential) are listed there.
[](#add-api-credentials)
Add API credentials
An API credential is an API key or token you store on a cloud environment so Claude can call that API from any session in the environment without seeing the key. Anthropic’s agent proxy adds the key to requests for the hosts you list, after each request leaves the session’s VM. The key never reaches Claude, the commands it runs, or the session’s environment variables. API credentials are available on Pro and Max plans. They aren’t available on Team or Enterprise plans yet, so the **API credentials** section doesn’t appear in the environment dialog on those plans.
[](#requirements)
Requirements
Two of these decide whether you can add a credential, and two decide whether the agent proxy can use it once added:
- **Role**: an organization admin role in your claude.ai organization
- On Team and Enterprise, Owners hold it and Admins don’t
- On Pro and Max, you hold it in your own organization
- Without it, you see a note instead of the credential list, on your own environments too. Ask an Owner to add the credential to a shared environment and run your sessions there
- **Environment type**: an Anthropic-hosted cloud environment that already exists. A [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) doesn’t have API credentials
- **API reachability**: the API accepts connections from the internet, because requests leave from Anthropic’s network
- **Encryption keys**: if your organization uses customer-managed encryption keys, you can’t save credentials
[](#add-a-credential)
Add a credential
You add credentials one at a time from the editor of an environment that already exists. The dialog for a new environment doesn’t offer them. There’s no edit, either. To change a credential’s hosts or value, delete it and add it again.
1
Open the environment's API credentials
[Open the environment for editing](#configure-your-environment) at [claude.ai/code](https://claude.ai/code). In the **Update cloud environment** dialog, find **API credentials** below **Environment variables**. You see the credentials already on the environment, each with the hosts it applies to.
2
Add the credential
Select **Add credential** and fill in the form. Keep the default **Credential type**, **Bearer**, for an API key that travels in a request header, and fill in these fields:
- **Name**: a label for the credential, such as `Internal billing API`
- **Allowed websites**: the API’s hosts, such as `api.example.com`. A leading `*.` matches every subdomain
- **Custom headers**: one row for the header that carries the key. The row starts with `Authorization` as the header’s **Name** and `Bearer` as its **Prefix**; paste the key itself as the **Value**. For a header like `X-Api-Key` that takes the bare value, change the name and clear the prefix
For an API that authenticates another way, pick a different **Credential type**. The list is the same one [Claude Tag](https://claude.com/docs/claude-tag/overview), the Slack integration for Team and Enterprise plans, offers for [connections](https://claude.com/docs/claude-tag/admins/add-connections).
3
Save the credential
Select **Connect**. The credential appears in the list with its hosts, saved without the dialog’s **Save changes** button. You can’t view the value again after saving.
To confirm the credential works, start a session in the environment and ask Claude to call the API, for example with `curl`. The API answers as if the key were in the request, and the key doesn’t appear in the session’s environment variables or in any file. If the list marks a credential **Not sent** instead, the note under it says why and what to do. Two credentials whose hosts overlap without matching exactly get no marker, and the agent proxy sends only one of them.
[](#which-requests-get-the-credential)
Which requests get the credential
The agent proxy attaches a credential to a request when the request’s host matches one you listed on that credential. Sessions can reach those hosts even when the environment’s [network access level](#access-levels) wouldn’t otherwise allow them, except the [hosts that never get the credential](#requests-that-never-get-the-credential). The credential applies in every session that runs in the environment, whoever started it, until you delete it.
[](#requests-that-never-get-the-credential)
Requests that never get the credential
The agent proxy never attaches a credential you add to these requests:
- **GitHub**: the [GitHub proxy](#github-proxy) authenticates requests to GitHub instead, so you don’t need an API credential for it
- **The Anthropic API and public package registries**: `api.anthropic.com`, `registry.npmjs.org`, `jsr.io`, `npm.jsr.io`, `pypi.org`, `files.pythonhosted.org`, `index.crates.io`, and `proxy.golang.org`
- **Setup script requests**: Claude Code connects to the agent proxy when it launches, after the [setup script](#setup-scripts) has run
- **Claude Code’s telemetry export**: Claude Code sends its [telemetry export](../13-Enterprise-Admin/monitoring-usage.md#telemetry-from-cloud-sessions-and-claude-tag) itself rather than through a command it runs, and that request doesn’t go through the agent proxy
[](#select-an-environment-from-the-cli)
Select an environment from the CLI
Run `/remote-env` in your terminal to choose the default environment for cloud sessions you create from the CLI, such as [`claude --cloud`](claude-code-on-the-web.md#from-terminal-to-cloud). The command opens a picker of your existing environments and saves your choice to the `remote.defaultEnvironmentId` key in your [user settings](settings.md#where-settings-live), so it applies in every project on your machine until you change it, unless the same key is set at a higher-precedence [settings layer](settings.md#settings-precedence), such as a repo’s project settings. A [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) ID, which has the form `ccpool_...`, follows a stricter source rule. See [`remote.defaultEnvironmentId`](settings-reference.md#remote-defaultenvironmentid) for the settings layers Claude Code honors it from. `/remote-env` only sets the default: it doesn’t start a session, and it can’t add or edit environments. Manage them from the [environment selector](#configure-your-environment).
[](#archive-an-environment)
Archive an environment
To archive one of your own environments, open it for editing and select **Archive**. An Owner archives a [shared environment](#organization-shared-environments) from the **Cloud environments** page in admin settings. You can’t delete an environment, only archive it. Archiving affects new sessions, not running ones:
- Sessions already running in the environment continue to work.
- The environment disappears from the selector and from `/remote-env`, so you can’t pick it for new sessions.
- API credentials on the environment stay attached in its running sessions. Delete any you no longer want before you archive.
- No new session can start in an archived environment, on any surface. If the environment was your saved [CLI default](#select-an-environment-from-the-cli), Claude Code starts CLI cloud sessions in the Anthropic-hosted environment when your list has one, and otherwise in the first environment in your list that isn’t a [Remote Control bridge environment](#the-default-environment). Anything configured with the environment explicitly, such as a [routine](web-scheduled-tasks.md#environments-and-network-access), can’t start new sessions in it. Point it at another environment.
[](#organization-shared-environments)
Organization-shared environments
On Team and Enterprise plans, an Owner can create cloud environments that are shared with every member of the organization. The same role manages everything else on the **Cloud environments** admin page, including [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md); the Admin role can’t open the page. The full list of roles that can open it is the one for [managing server-managed settings](../13-Enterprise-Admin/server-managed-settings.md#access-control). Shared environments appear in each member’s [environment selector](#configure-your-environment) under an **Organization** heading, after the member’s own environments under **Personal**, so a team can standardize on one configuration instead of each member recreating it. Selecting a shared environment’s settings icon there opens a read-only summary of its configuration for every member, Owners included. An Owner makes an environment available to the organization in one of two ways:
- **Create a shared environment**: use the **Cloud environments** page in [admin settings](https://claude.ai/admin-settings), which is also where Owners edit and archive shared environments. Each one has a name, a [network access level](#access-levels), [environment variables](#set-environment-variables) in `.env` format, and a [setup script](#setup-scripts).
- **Share a personal environment**: open one of your own environments for editing in the environment selector, then share it from the **Who can use it** row. The environment keeps its ID, so sessions and routines that already use it aren’t affected, and every member can then see it and start sessions in it.
Owners choose the organization’s [default environment](#the-default-environment) separately, at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code). Every member’s sessions in a shared environment read its variables, so don’t include secrets in them. [API credentials](#add-api-credentials), which give sessions a key they can’t read, aren’t available on Team or Enterprise plans yet.
[](#set-the-environment-a-claude-tag-channel-uses)
Set the environment a Claude Tag channel uses
In [Claude Tag](https://claude.com/docs/claude-tag/overview) channels, Claude works as your organization’s shared identity, not as any member, so channel sessions use organization-level environments only, either shared environments or [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md). To give a channel a toolchain that isn’t [pre-installed](#installed-tools), such as .NET, an Owner can create a [shared environment](#organization-shared-environments) from the **Cloud environments** admin page with a [setup script](#setup-scripts) that installs it. Point the channel at an environment in one of two ways:
- Set a shared or self-hosted environment as the organization’s [default environment](#the-default-environment) at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code).
- [Pin one to a channel](https://claude.com/docs/claude-tag/admins/troubleshooting#channel-sessions-use-the-wrong-environment-or-can%E2%80%99t-find-one) in the Claude Tag admin settings.
[](#network-access)
Network access
Each environment sets one network access level, which controls the outbound connections its sessions can make. The default level, **Trusted**, allows package registries and other [allowlisted domains](#default-allowed-domains); **Custom** takes your own domain list. To change an environment’s network access, [open it for editing](#configure-your-environment) and use the **Network access** selector in the dialog. A [shared environment](#organization-shared-environments) opens read-only there, so an Owner changes its network access from the **Cloud environments** page in [admin settings](https://claude.ai/admin-settings) instead. The cloud icon that opens the selector appears on the app surfaces listed under [The Default environment](#the-default-environment) and in the [routine editor](web-scheduled-tasks.md#environments-and-network-access); personal environments don’t have a separate page in your claude.ai account settings.
MCP connectors you enable on a session or routine work without adding their hosts to **Allowed domains**, because connector traffic travels through Anthropic’s servers rather than the session’s network. This relies on the same Anthropic-bound channel noted under [Security and isolation](claude-code-on-the-web.md#security-and-isolation). Turn off any connector you don’t need to limit which tools Claude can reach.
[](#access-levels)
Access levels
The **Network access** field in the [environment dialog](#configure-your-environment) takes one of four levels:
| Level | Outbound connections |
|:------------|:---------------------------------------------------------------------------------------------|
| **None** | No outbound network access through the session’s network |
| **Trusted** | [Allowlisted domains](#default-allowed-domains) only: package registries, GitHub, cloud SDKs |
| **Full** | Any domain |
| **Custom** | Your own allowlist, optionally including the defaults |
Whichever level you pick, sessions can still reach these, because each one takes a path that doesn’t go through the session’s network allowlist:
- GitHub, through its [separate proxy](#github-proxy)
- [MCP connectors](#network-access) you enable, whose traffic travels through Anthropic’s servers
- The hosts you listed on the environment’s [API credentials](#add-api-credentials), except the [hosts that never get the credential](#requests-that-never-get-the-credential)
- The Anthropic API, for Claude Code’s own requests, even at **None**, as noted under [Security and isolation](claude-code-on-the-web.md#security-and-isolation)
[](#allow-specific-domains)
Allow specific domains
To allow domains that aren’t in the Trusted list, select **Custom** in the environment’s network access settings, then list one domain per line in the **Allowed domains** field. This example allows three hosts an internal project might need.
```python
api.example.com
*.internal.example.com
registry.example.com
```
Sessions in this environment can now reach `api.example.com`, any subdomain of `internal.example.com`, and `registry.example.com`, and no other domains through the session’s network. [GitHub traffic](#github-proxy), [MCP connector traffic](#network-access), and requests to the hosts of the environment’s [API credentials](#add-api-credentials), other than the [hosts that never get the credential](#requests-that-never-get-the-credential), don’t go through this allowlist. A leading `*.` matches every subdomain. To keep the [Trusted domains](#default-allowed-domains) too, check **Also include default list of common package managers**; leave it unchecked to allow only what you list. If your organization uses [artifacts](artifacts.md#availability), you don’t need `*.frame.claudeusercontent.com` in the list for sessions to read them. When the list leaves that host out, Claude Code reads artifact content through the session’s connection to Anthropic instead. Keep the host in an allowlist in two situations:
- **Sessions in this environment open another organization’s public artifacts**: Claude Code fetches those from the host directly, so add it to this list.
- **You’re configuring the local CLI or a self-hosted runner**: keep the host in that allowlist. See [network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements) and the self-hosted [network requirements](../13-Enterprise-Admin/self-hosted-environments-deploy.md#network-requirements).
Each environment has its own allowed-domains list; there’s no organization-level allowlist that admins can push to every member’s environments. No [server-managed setting](../13-Enterprise-Admin/server-managed-settings.md) adds domains to an environment’s network allowlist either. To give a team one standard list, an Owner can create an [organization-shared environment](#organization-shared-environments) with **Custom** network access and that list.
[](#github-proxy)
In Anthropic-hosted environments, all GitHub operations go through a dedicated proxy that keeps your real GitHub credentials outside the session’s VM, independent of the environment’s [access level](#access-levels). Sessions in a self-hosted environment authenticate git operations with credentials your deployment provides; [Configure git](../13-Enterprise-Admin/self-hosted-environments-deploy.md#configure-git) covers the options, including per-session minted credentials and an opt-in to this same proxy. The proxy provides:
- **Git credentials**: the git client inside the VM uses a scoped credential, which the proxy verifies and swaps for your actual GitHub token.
- **API requests**: requests from the built-in GitHub tools, and from `gh` under the [`proxy-injected` placeholder](#work-with-github-issues-and-pull-requests), go out with your real credentials substituted.
- **Push protection**: `git push` works only against the session’s current working branch; cloning, fetching, and PR operations work normally.
- **Repository scope**: GitHub API and release-asset requests reach only repositories attached to the session, so a setup script that downloads release assets from an unattached repository gets a 403.
- **GraphQL restrictions**: the proxy serves only a pinned set of GraphQL operations for pull-request workflows. The proxy rejects everything else on the GraphQL endpoint with a 403 that says `This GraphQL query is not enabled for this session` and names the REST fallback, `gh api repos/{owner}/{repo}/...`. The restriction applies to every request through the proxy regardless of the credentials you supply, so a `GH_TOKEN` you set gets the same 403. Claude can’t reach GitHub APIs that exist only in GraphQL, such as Projects v2, through the proxy.
Committed files from public repositories arrive through `raw.githubusercontent.com`, which the [security proxy](#security-proxy) handles instead. That domain is in the default [Trusted list](#default-allowed-domains), so those files stay reachable unless the environment’s [access level](#access-levels) excludes it.
[](#security-proxy)
Security proxy
Cloud sessions in Anthropic-hosted environments run behind an HTTP/HTTPS network proxy for security and abuse prevention purposes; in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments-deploy.md#default-deny-egress), outbound traffic leaves through your own network boundary instead. All outbound internet traffic from an Anthropic-hosted session passes through this proxy, which provides:
- Protection against malicious requests
- Rate limiting and abuse prevention
- Content filtering for enhanced security
- A DNS-level audit trail of requested hostnames
[](#what’s-available-in-cloud-sessions)
What’s available in cloud sessions
In Anthropic-hosted environments, each session gets a fresh virtual machine (VM) running Ubuntu 24.04 on x86_64, regardless of your own operating system and CPU architecture, with your repository cloned and common toolchains pre-installed. When a dependency provides precompiled binaries, such as Ruby gems with native extensions or prebuilt Python wheels, use its x86_64 Linux build to match the VM. This section covers the Anthropic-hosted defaults, the built-in GitHub tools, how to [run tests and services](#run-tests-start-services-and-add-packages), the [resource limits](#resource-limits) each VM gets, and the [time limits](#time-limits) on long-running work.
Sessions your organization routes to a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) run on your own runners instead, with the tools your runner image provides.
[](#what-carries-over-from-your-setup)
What carries over from your setup
Cloud sessions start from a fresh clone of your repository. Anything you commit to the repo is available. Anything you’ve installed or configured only on your own machine isn’t available in the session. Your organization’s policy arrives separately through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md).
| | Available in cloud sessions | Why |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Your repo’s `CLAUDE.md` | Yes | Part of the clone |
| Your repo’s `.claude/settings.json` hooks and permission rules | Yes, in a session with one repository | Part of the clone. A session with several repositories, including a [project](claude-projects.md#what-threads-pick-up-from-your-repositories) thread, starts above the clones and doesn’t read them |
| Your repo’s `.mcp.json` MCP servers | Yes, in a session with one repository | Part of the clone, found from the session’s working directory |
| 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 and marketplaces declared in your repo’s `.claude/settings.json` | No | A cloud session doesn’t install the plugins a repository turns on under [`enabledPlugins`](settings-reference.md#enabledplugins), including ones from the marketplaces it lists under [`extraKnownMarketplaces`](settings-reference.md#extraknownmarketplaces) |
| Your organization’s [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) | Yes, except in [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions | Fetched from Anthropic’s servers when the session starts. See [Surface coverage](model-config.md#surface-coverage) for how `availableModels` is enforced in cloud sessions. Settings deployed to your device through MDM or managed settings files don’t apply, because the session runs on an Anthropic-managed VM; in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md), sessions also read the managed settings file in the runner image, per [how Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) |
| Your user `~/.claude/CLAUDE.md` | No | Lives on your machine, not in the repo |
| Your user `~/.claude/skills/`, `~/.claude/agents/`, `~/.claude/commands/` | No | Live on your machine, not in the repo. Commit them to the repo’s `.claude/` directory instead. Cloud sessions automatically load skills you enable on claude.ai |
| Plugins enabled only in your user settings | No | User-scoped `enabledPlugins` lives in `~/.claude/settings.json` on your machine |
| MCP servers you added with `claude mcp add` at the default local scope or the user scope | No | Those write to `~/.claude.json` on your machine, not the repo. Add the server with `claude mcp add --scope project`, which writes the repo’s [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-scope), and commit that file. A session with one repository loads it |
| Transport variables in your repo’s `.claude/settings.json` `env` block, such as `NODE_EXTRA_CA_CERTS` and the [mTLS client certificate variables](../13-Enterprise-Admin/network-config.md#mtls-authentication) | No | The hosting environment manages the session’s API connection, so Claude Code ignores these keys and notes each ignored key in the session’s debug log |
| API keys and tokens for services Claude calls | On Pro and Max plans, as [API credentials](#add-api-credentials) | You add the key once on the environment and the agent proxy attaches it to requests for the hosts you list. A key the agent proxy [can’t attach](#requests-that-never-get-the-credential), or any key on a Team or Enterprise plan, stays in an environment variable |
| Interactive auth like AWS SSO | No | Not supported. SSO requires browser-based login that can’t run in a cloud session |
To make your own configuration available in cloud sessions, commit it to the repo. Anyone who uses the environment can read its environment variables and setup script. The dialog’s note under **Environment variables** says so and warns against putting secrets there. On Pro and Max plans, store a key the agent proxy can attach as an [API credential](#add-api-credentials) instead.
[](#installed-tools)
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, with npm, yarn, pnpm, bun¹, eslint, prettier, chromedriver |
| **Ruby** | 3.1, 3.2, 3.3 with gem, bundler, rbenv |
| **PHP** | 8.3 with Composer |
| **Java** | OpenJDK 21 with Maven and Gradle |
| **Go** | Go 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, gh, jq, yq, ripgrep, tmux, vim, nano |
¹ Bun is installed but has known [proxy compatibility issues](#install-dependencies-with-a-sessionstart-hook) for package fetching. To get the versions of most of the tools in this table, ask Claude to run `check-tools` in a cloud session. It’s a shell command installed on the session VM, not a command you type with `/`; you ask Claude because [Claude runs all VM commands for you](#run-tests-start-services-and-add-packages). For a tool it doesn’t report, such as Ruby, PHP, bun, PostgreSQL, or Redis, ask Claude to run the tool’s own version command, for example `psql --version`. Node.js versions are installed at `/opt/node20`, `/opt/node21`, and `/opt/node22`, with 22 on `PATH` by default. To work with a different version, ask Claude to prepend that version’s `bin` directory, such as `/opt/node20/bin`, to `PATH`. Toolchains outside this list, such as the .NET SDK, aren’t pre-installed even when their package registries are on the [default allowlist](#default-allowed-domains). Install them with a [setup script](#setup-scripts).
[](#work-with-github-issues-and-pull-requests)
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](#github-proxy) using whichever method you configured under [GitHub authentication options](claude-code-on-the-web.md#github-authentication-options), so your token never enters the container. You can set `GH_TOKEN` or `GITHUB_TOKEN` yourself in [environment settings](#set-environment-variables), or leave both unset and let the [GitHub proxy](#github-proxy) authenticate for you:
- If you set a token, it passes through to the container unchanged, so your scripts and GitHub’s [`gh` CLI](https://cli.github.com) use it directly.
- If you set neither and the [GitHub proxy](#github-proxy) is handling authentication for your session, both variables read as the placeholder string `proxy-injected` in the commands Claude runs, and the proxy substitutes your real credentials on outbound GitHub requests. `gh` works without a token of your own, but a script that reads `GITHUB_TOKEN` directly gets the placeholder, not a usable token.
A token you set is an ordinary environment variable, so anyone who uses the environment can read it; the proxy path keeps the credential out of the environment configuration and the session VM. To check which case applies to your session, ask Claude to run `echo $GH_TOKEN`. GitHub’s [`gh` CLI](https://cli.github.com) is pre-installed. If you need a `gh` command the built-in tools don’t cover, like `gh release` or `gh workflow run`, ask Claude to run it. `gh` reads `GH_TOKEN` automatically, so you don’t need to run `gh auth login`.
[](#link-output-back-to-the-session)
Link output 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. Commits that Claude creates in a cloud session include a `Claude-Session: <url>` git trailer, and PR bodies include the session URL on its own line. To omit the trailer and the PR-body link, set [`attribution.sessionUrl`](settings-reference.md#attribution-sessionurl) to `false`. To include the session link in something other than a commit or PR, such as a Slack message Claude posts or a report file it writes, have Claude run the following command and use its output. The command converts the `cse_` prefix in the environment variable’s value to the `session_` prefix that the transcript URL expects:
```python
echo "https://claude.ai/code/${CLAUDE_CODE_REMOTE_SESSION_ID/#cse_/session_}"
```
[](#run-tests-start-services-and-add-packages)
Run tests, start services, and add packages
You don’t get a shell into the session VM. Claude runs every command for you, so phrase the tasks in this section as requests in your prompt.
[](#run-tests)
Run tests
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 that come with the [pre-installed toolchains](#installed-tools), like pytest and cargo test, work without additional setup. A runner your project declares as a dependency, like jest, installs with your dependencies.
[](#start-services)
Start services
PostgreSQL and Redis are pre-installed but not running by default. Ask Claude to start whichever you need; the commands it runs are:
```python
service postgresql start
```
```python
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](#access-levels), and the [Trusted defaults](#default-allowed-domains) 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](#setup-scripts). The [environment cache](#environment-caching) keeps the pulled images, so each new session has them on disk. The cache stores files only, not running processes, so Claude still starts the containers each session.
[](#add-packages)
Add packages
To add packages that aren’t pre-installed, use a [setup script](#setup-scripts). The [environment cache](#environment-caching) keeps what the script installs, 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)
Resource limits
Cloud sessions in Anthropic-hosted environments run with approximate resource ceilings that may change over time:
- 4 vCPUs
- 16 GB of RAM
- 30 GB of disk
The VM may stop tasks that need significantly more memory, such as large build jobs or memory-intensive tests. For workloads beyond these limits, use [Remote Control](remote-control.md) to run Claude Code on your own hardware, or run cloud sessions in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) on compute your organization operates.
[](#time-limits)
Time limits
In Anthropic-hosted environments, these time limits apply to long-running work in a cloud session, such as a build, an install, or a test run. Each entry links to the section that defines the limit.
- **Commands Claude runs**: a cloud environment doesn’t set its own command timeout, so the Bash tool’s defaults apply. Claude waits 2 minutes for a command by default and can ask for up to 10 minutes. When a command reaches its [timeout](tools-reference.md#timeout-and-output-limits), Claude Code [moves it to the background](tools-reference.md#background-commands) instead of stopping it, unless the command starts with `sleep`.
- **SessionStart hooks**: Claude Code cancels a `command` hook after 600 seconds unless you set [`timeout`](../07-Hooks/hooks.md#common-fields), in seconds, on the hook entry. Claude Code doesn’t enforce the timeout on a hook you run with [`async: true`](../07-Hooks/hooks.md#run-hooks-in-the-background).
- **Setup script**: a script that takes longer than roughly five minutes isn’t cached. [Script requirements](#script-requirements) covers how to stay under that.
- **Idle sessions**: a session stops after a period of inactivity and its VM is reclaimed. [Environment expired](claude-code-on-the-web.md#environment-expired) covers what counts as inactive and how to reopen the session.
To raise the command timeouts for an environment’s sessions, add [`BASH_DEFAULT_TIMEOUT_MS` and `BASH_MAX_TIMEOUT_MS`](env-vars.md#variables) to its [environment variables](#set-environment-variables). Both take milliseconds. For example, `BASH_DEFAULT_TIMEOUT_MS=600000` makes 10 minutes the default.
[](#setup-scripts)
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 [ShellCheck](https://www.shellcheck.net/), which isn’t pre-installed.
```python
#!/bin/bash
apt update && apt install -y shellcheck
```
[](#script-requirements)
Script requirements
A setup script has three constraints to write around:
- **Exit zero**: if the script exits non-zero, the session fails to start. Append `|| true` to non-critical commands so an intermittent install failure doesn’t block the session.
- **Finish within five minutes**: keep the script’s total runtime under roughly five minutes so the [environment cache](#environment-caching) can build. When setup takes longer than that, the environment isn’t cached. Run independent installs in parallel with `&` and `wait`, and move any single download that won’t fit into a [SessionStart hook](#setup-scripts-vs-sessionstart-hooks) that launches it in the background. If new sessions stall or fail during setup, see [New sessions hang or time out during setup](web-quickstart.md#new-sessions-hang-or-time-out-during-setup).
- **Network access for installs**: package installs need to reach registries. The default **Trusted** level covers [common package registries](#default-allowed-domains) including npm, PyPI, RubyGems, and crates.io; with **None** network access, installs fail.
[](#environment-caching)
Environment caching
The setup script runs the first time you start a session in an environment. When setup completes within [roughly five minutes](#script-requirements), 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 skip the setup script step. This keeps startup fast even when the script installs large toolchains or pulls container images. If setup takes longer than roughly five minutes, the environment isn’t cached. The cache is a filesystem snapshot, so it keeps what the setup script writes to disk and loses anything that was only running. Packages you install, Docker images you pull, and files you write all carry over. A database the script started, a `docker compose up` stack, or any other background process doesn’t; start those per session by asking Claude or with a [SessionStart hook](#setup-scripts-vs-sessionstart-hooks). 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)
Setup scripts vs. SessionStart hooks
Use a setup script to provision the VM itself: toolchains and CLI tools that aren’t [pre-installed](#installed-tools). Use a [SessionStart hook](../07-Hooks/hooks.md#sessionstart) for project setup that should run everywhere, cloud and local, like `npm install`. Setup scripts and SessionStart hooks run in a fixed order when a cloud session starts. The table compares where you configure them, when they run, and where they run.
| | Setup scripts | SessionStart hooks |
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Where you configure them** | The environment dialog at [claude.ai/code](https://claude.ai/code), plus the **Cloud environments** admin page for [shared environments](#organization-shared-environments) | A [settings file](settings.md#where-settings-live) such as your repo’s `.claude/settings.json`; see [What carries over from your setup](#what-carries-over-from-your-setup) for which files reach a cloud session |
| **When they run** | Before Claude Code launches, skipped when a [cached environment](#environment-caching) exists | After Claude Code launches, on every session including resumed |
| **Where they run** | Cloud sessions only | Local and cloud sessions |
If you have SessionStart hooks in your user-level `~/.claude/settings.json`, don’t expect them in the cloud. User-level settings stay on your machine. Which other hooks run depends on where the session runs:
- **Anthropic-hosted environment**: Claude Code runs hooks from the repository and from your organization’s [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md). [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions don’t receive server-managed settings, so hooks from server-managed settings don’t run there.
- **[Self-hosted environment](../13-Enterprise-Admin/self-hosted-environments-configuration.md#permissions-and-tool-approval)**: Claude Code also runs the hooks the operator seeded from the runner host’s `~/.claude/`, and the hooks in the runner image’s managed settings file when that file is one of the [managed sources Claude Code applies](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources).
[](#install-dependencies-with-a-sessionstart-hook)
Install dependencies with a SessionStart hook
To install dependencies only in cloud sessions, pair a SessionStart hook with a script that checks where it’s running. First, add a SessionStart hook to your repo’s `.claude/settings.json`. This configuration tells Claude Code to run `scripts/install_pkgs.sh` from your repository whenever a session starts or resumes:
```python
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/install_pkgs.sh"
}
]
}
]
}
}
```
The `matcher` limits the hook to the `startup` and `resume` events, and `$CLAUDE_PROJECT_DIR` resolves to the repository root, so the hook finds the script regardless of the session’s working directory. Next, create the script at `scripts/install_pkgs.sh`. It exits immediately outside the cloud, then installs your dependencies:
```python
#!/bin/bash
if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then
exit 0
fi
npm install
pip install -r requirements.txt
exit 0
```
The `CLAUDE_CODE_REMOTE` check is what scopes the install to cloud sessions: the session VM’s environment carries that variable as `true`, it’s never `true` locally, so on your laptop the script exits before installing anything. Together, the two files give every cloud session a fresh `npm install` and `pip install` at startup while leaving local sessions untouched.
[](#limitations-in-cloud-sessions)
Limitations in cloud sessions
SessionStart hooks behave the same in the cloud as locally, with these caveats:
- **One repository per session**: a session with several repositories doesn’t load hooks from any repository’s `.claude/settings.json`, so a SessionStart hook you define there doesn’t run. Install dependencies for those sessions with a [setup script](#setup-scripts) instead.
- **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, exit early unless the `CLAUDE_CODE_REMOTE` environment variable is `true`, the way the [dependency install script](#install-dependencies-with-a-sessionstart-hook) does.
- **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.
- **Proxy compatibility**: in Anthropic-hosted environments, all outbound traffic passes through a [security proxy](#security-proxy), and some package managers don’t work correctly with it; Bun is a known example. In a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments-deploy.md#default-deny-egress), outbound traffic goes through your own network boundary instead.
- **Adds startup latency**: hooks run each time a session starts or resumes, unlike setup scripts which benefit from [environment caching](#environment-caching). Keep install scripts fast by checking whether dependencies are already present before reinstalling.
To customize the base image, use a setup script to install what you need on top of the [provided image](#installed-tools), or run your own image as a container alongside Claude with `docker compose`. Replacing the base image entirely isn’t supported yet.
[](#default-allowed-domains)
Default allowed domains
With **Trusted** network access, sessions can reach the following domains by default. Domains marked with `*` indicate wildcard subdomain matching, so `*.gcr.io` allows any subdomain of `gcr.io`.
Anthropic services
- api.anthropic.com
- docs.claude.com
- platform.claude.com
- code.claude.com
- claude.ai
- claude.com
- support.claude.com
- anthropic.com
- [www.anthropic.com](http://www.anthropic.com)
Version control
- github.com
- [www.github.com](http://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](http://www.gitlab.com)
- registry.gitlab.com
- bitbucket.org
- [www.bitbucket.org](http://www.bitbucket.org)
- api.bitbucket.org
Container registries
- registry-1.docker.io
- auth.docker.io
- index.docker.io
- hub.docker.com
- [www.docker.com](http://www.docker.com)
- production.cloudflare.docker.com
- production.cloudfront.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](http://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](http://www.oracle.com)
- java.com
- [www.java.com](http://www.java.com)
- java.net
- [www.java.net](http://www.java.net)
- download.oracle.com
- yum.oracle.com
- \*.r2.cloudflarestorage.com
JavaScript and Node package managers
- registry.npmjs.org
- [www.npmjs.com](http://www.npmjs.com)
- [www.npmjs.org](http://www.npmjs.org)
- npmjs.com
- npmjs.org
- yarnpkg.com
- registry.yarnpkg.com
- jsr.io
- npm.jsr.io
Python package managers
- pypi.org
- [www.pypi.org](http://www.pypi.org)
- files.pythonhosted.org
- pythonhosted.org
- test.pypi.org
- pypi.python.org
- pypa.io
- [www.pypa.io](http://www.pypa.io)
Ruby package managers
- rubygems.org
- [www.rubygems.org](http://www.rubygems.org)
- api.rubygems.org
- index.rubygems.org
- ruby-lang.org
- [www.ruby-lang.org](http://www.ruby-lang.org)
- rubyforge.org
- [www.rubyforge.org](http://www.rubyforge.org)
- rubyonrails.org
- [www.rubyonrails.org](http://www.rubyonrails.org)
- rvm.io
- get.rvm.io
Rust package managers
- crates.io
- [www.crates.io](http://www.crates.io)
- index.crates.io
- static.crates.io
- rustup.rs
- static.rust-lang.org
- [www.rust-lang.org](http://www.rust-lang.org)
Go package managers
- proxy.golang.org
- sum.golang.org
- index.golang.org
- golang.org
- [www.golang.org](http://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
- maven.google.com
- jcenter.bintray.com
- gradle.org
- [www.gradle.org](http://www.gradle.org)
- services.gradle.org
- plugins.gradle.org
- plugins-artifacts.gradle.org
- kotlinlang.org
- [www.kotlinlang.org](http://www.kotlinlang.org)
- spring.io
- repo.spring.io
Other package managers
- packagist.org (PHP Composer)
- [www.packagist.org](http://www.packagist.org)
- repo.packagist.org
- nuget.org (.NET NuGet)
- [www.nuget.org](http://www.nuget.org)
- api.nuget.org
- pub.dev (Dart/Flutter)
- api.pub.dev
- hex.pm (Elixir/Erlang)
- [www.hex.pm](http://www.hex.pm)
- cpan.org (Perl CPAN)
- [www.cpan.org](http://www.cpan.org)
- metacpan.org
- [www.metacpan.org](http://www.metacpan.org)
- api.metacpan.org
- cocoapods.org (iOS/macOS)
- [www.cocoapods.org](http://www.cocoapods.org)
- cdn.cocoapods.org
- haskell.org
- [www.haskell.org](http://www.haskell.org)
- hackage.haskell.org
- swift.org
- [www.swift.org](http://www.swift.org)
Linux distributions
- archive.ubuntu.com
- security.ubuntu.com
- ubuntu.com
- [www.ubuntu.com](http://www.ubuntu.com)
- \*.ubuntu.com
- ppa.launchpad.net
- launchpad.net
- [www.launchpad.net](http://www.launchpad.net)
- \*.nixos.org
Development tools and platforms
- dl.k8s.io (Kubernetes)
- pkgs.k8s.io
- k8s.io
- [www.k8s.io](http://www.k8s.io)
- releases.hashicorp.com (HashiCorp)
- apt.releases.hashicorp.com
- rpm.releases.hashicorp.com
- archive.releases.hashicorp.com
- hashicorp.com
- [www.hashicorp.com](http://www.hashicorp.com)
- repo.anaconda.com (Anaconda/Conda)
- conda.anaconda.org
- anaconda.org
- [www.anaconda.com](http://www.anaconda.com)
- anaconda.com
- continuum.io
- apache.org (Apache)
- [www.apache.org](http://www.apache.org)
- archive.apache.org
- downloads.apache.org
- eclipse.org (Eclipse)
- [www.eclipse.org](http://www.eclipse.org)
- download.eclipse.org
- nodejs.org (Node.js)
- [www.nodejs.org](http://www.nodejs.org)
- developer.apple.com
- developer.android.com
- pkg.stainless.com
- binaries.prisma.sh
Cloud services and monitoring
- 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](http://www.json-schema.org)
- json.schemastore.org
- [www.schemastore.org](http://www.schemastore.org)
Model Context Protocol
- \*.modelcontextprotocol.io
[](#related-resources)
Related resources
- [Cloud sessions reference](claude-code-on-the-web.md): start, manage, and share cloud sessions
- [Cloud sessions quickstart](web-quickstart.md): connect GitHub and start your first cloud session
- [Claude Tag](https://claude.com/docs/claude-tag/overview): sessions Claude starts from Slack run in the same environments
- [Routines](web-scheduled-tasks.md): scheduled runs use the same environments and network access levels
- [Remote Control](remote-control.md): run sessions on your own machine’s network and files instead
- [Self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md): run cloud sessions on your organization’s own infrastructure
- [SessionStart hooks](../07-Hooks/hooks.md#sessionstart): repo-committed setup that runs in local and cloud sessions
- [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md): organization policy delivered from the admin console
---
## Claude Code by Anthropic | AI Coding Agent, Terminal, IDE
Source: https://code.claude.com/
Path: 02-Claude-Code-CLI/code-claude-com-code-home.md
# Claude Code
Hand Claude a bug fix, test, or multi-day migration. Steer and review from your terminal, IDE, Slack, or web.
[Download for macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect)[Read documentation](code-home.md)
(opens in new tab)
Available for macOS, Linux, and Windows.
Other ways to use Claude Code:
- [Terminal (opens in new tab)](../01-Getting-Started/quickstart.md#step-1-install-claude-code)
- [Web (opens in new tab)](https://claude.ai/code)
- [iOS (opens in new tab)](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684)
- [Android (opens in new tab)](https://play.google.com/store/apps/details?id=com.anthropic.claude)
- [GitHub (opens in new tab)](github-actions.md)
- [VS Code (opens in new tab)](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code)
- [JetBrains (opens in new tab)](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-)
- [Slack (opens in new tab)](https://slack.com/oauth/v2/authorize?client_id=1601185624273.8899143856786&scope=app_mentions:read,assistant:write,channels:history,channels:read,chat:write,files:read,files:write,groups:history,groups:read,im:history,im:read,im:write,mpim:history,reactions:write,users:read,users:read.email,commands,search:read.public&user_scope=bookmarks:read,channels:history,channels:read,chat:write,emoji:read,files:read,groups:history,groups:read,groups:write,im:history,im:read,im:write,links:read,mpim:history,mpim:read,mpim:write,mpim:write.topic,pins:read,reactions:read,reactions:write,remote_files:read,team:read,users:read,users:read.email,search:read.public,search:read.private,search:read.im,search:read.mpim,search:read.files,search:read.users,canvases:read,canvases:write)
Home
Code
New session
Routines
Customize
More
Pinned
Add a dark mode toggle to settings
Scheduled
Weekly dependency audit
Recents
Fix the double-charge bug in checkout
Write tests for the payments module
Explain what this repo does
Layout's broken on mobile
Debug flaky CI tests
Susan Sample
acme-storefront/Fix the double-charge bug in checkout
We're seeing duplicate charges when customers double-click the pay button. Can you find and fix it?
I can reproduce it: the checkout form fires two `POST /charges` requests when the button is clicked twice before the first response lands. Tracing where the idempotency key should be.
just now
Read 3 files, searched the checkout flow
Ran agent · Reproduce the double-submit against a test charge
Root cause: `createCharge()` generates a new idempotency key per call instead of per checkout session, so the gateway treats the second click as a fresh charge. Fixing that and disabling the button while a charge is in flight.
just now
Edited **charges.ts** +9 -3
Auto
Opus
Extra high
Home
Code
New session
Routines
Customize
More
Pinned
Add a dark mode toggle to settings
Scheduled
Weekly dependency audit
Recents
Fix the double-charge bug in checkout
Write tests for the payments module
Explain what this repo does
Layout's broken on mobile
Debug flaky CI tests
Susan Sample
acme-dashboard/Add a dark mode toggle to settings
Add a dark mode toggle to the settings page. Should remember the choice and follow the system default until they pick one.
There's already a `ThemeProvider` wrapping the app but it's hard-wired to light. I'll lift the mode into context, persist it to `localStorage`, and add a Light / Dark segmented control under **Settings → Appearance**.
just now
Read 4 files, searched the codebase
Edited **ThemeProvider.tsx** +18 -2
src/theme/ThemeProvider.tsx
10`export`` ``function`` ``ThemeProvider``({``children``}:`` ``{``children``:`` ``ReactNode``})`` ``{`
11+` ``const`` ``prefersDark`` ``=`` ``useMediaQuery``('(``prefers``-``color``-``scheme``:`` ``dark``)')`
12` ``const`` ``stored`` ``=`` ``localStorage``.``getItem``('``theme``')`
13+` ``const`` ``[``mode``,`` ``setMode``]`` ``=`` ``useState``(``stored`` ``??`` ``(``prefersDark`` ``?`` ``'dark'`` ``:`` ``'light'``))`
14` `
15+` ``useEffect``(()`` ``=>`` ``{`
16+` ``localStorage``.``setItem``('``theme``',`` ``mode``)`
17+` ``},`` ``[``mode``])`
18` `
19` ``return`` ``(`
20` ``<``ThemeContext``.``Provider`` ``value``={{``mode``,`` ``setMode``}}>`
21` ``{``children``}`
Edited **settings.tsx** +21 -0
Edited **tokens.css** +24 -0
Ran 2 commands
Done — the **Appearance** section now has the toggle. Preview's on the right; flip it and the whole app should follow. Reduce-motion and density rows are stubbed so the page doesn't look bare.
just now
\#112acme-dashboardclaude/settings-dark-mode-Xk4fq CI
Auto
Opus
Extra high
localhost:5173/settings
Appearance
Theme
Choose how the dashboard looks.
Light
Dark
Density
Compact rows for power users.
Default
Compact
Reduce motion
Disable animations and transitions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Get started with Claude Code
Individual
Team & Enterprise
### Pro
Claude Code is included in your Pro plan. Perfect for short coding sprints in small codebases.
\$17
Per month with annual subscription discount (\$200 billed up front). \$20 if billed monthly.
[Try Claude (opens in new tab)](https://claude.ai/login?plan=pro)
### Max 5x
Claude Code is included in your Max plan. Great value for everyday use in larger codebases.
\$100
Per month
[Try Claude (opens in new tab)](https://claude.ai/login?plan=max)
### Max 20x
Even more Claude Code included in your Max plan. Great value for power users with the most access to Claude models.
\$200
Per month
[Try Claude (opens in new tab)](https://claude.ai/login?plan=max)
[Usage limits apply](https://support.anthropic.com/en/articles/9797557-usage-limit-best-practices). Prices shown don't include applicable tax. Price and plans are subject to change at Anthropic's discretion.
[Usage limits apply](https://support.anthropic.com/en/articles/9797557-usage-limit-best-practices). Price and plans are subject to change at Anthropic's discretion.
## Latest feature announcements
### **Projects:** Group related coding sessions so you can run and easily supervise multiple Claude agents at once. Available on Claude Code Desktop.
BlogSep 17, 2026
### **Auto mode by default:** Claude Code now runs in auto mode by default on Pro, Max, and Team plans, so it can work longer while still catching risky commands.
BlogAug 7, 2026
### **Self-hosted environments:** Run Claude Code sessions on your own infrastructure, inside your network and next to your internal services. Now in public beta.
BlogAug 6, 2026
### **Artifacts:** Preview in-progress work as a live, interactive artifact built from your session context, and share it with your team.
BlogJun 18, 2026
[View changelog](changelog.md)
(opens in new tab)
## What Claude Code can take on
Claude Code builds the plan, asks clarifying questions, and handles work that runs for hours or days.
Get Claude Code
- [Desktop](https://code.claude.com/download)
- [VS Code](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code)
- [JetBrains](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-)
- [On the web](https://claude.ai/code)
- [Slack](https://slack.com/oauth/v2/authorize?client_id=1601185624273.8899143856786&scope=app_mentions:read,assistant:write,channels:history,channels:read,chat:write,files:read,files:write,groups:history,groups:read,im:history,im:read,im:write,mpim:history,reactions:write,users:read,users:read.email,commands,search:read.public&user_scope=bookmarks:read,channels:history,channels:read,chat:write,emoji:read,files:read,groups:history,groups:read,groups:write,im:history,im:read,im:write,links:read,mpim:history,mpim:read,mpim:write,mpim:write.topic,pins:read,reactions:read,reactions:write,remote_files:read,team:read,users:read,users:read.email,search:read.public,search:read.private,search:read.im,search:read.mpim,search:read.files,search:read.users,canvases:read,canvases:write)
curl -fsSL https://claude.ai/install.sh \| bash
Or read the [documentation](code-home.md)
[Try Claude Code (opens in new tab)](https://claude.ai/code)[Developer docs (opens in new tab)](code-home.md)
Onboarding
Triage issues
Migrate code
``` Terminal-module-scss-module__gNncDq__pre
I'm new to this codebase. Can you explain it to me?
⏺︎ I'll analyze the Excalidraw codebase structure and provide a high-level overview.
⏺︎ Analyze(what: "Excalidraw codebase structure and provide a high-level overview of what it is, its main components, and how they're organized. Focus on understanding the project's purpose, architecture, and key features.")
Excalidraw is an open-source virtual whiteboard application with a hand-drawn style. It's designed for creating diagrams, wireframes, and collaborative drawings.
## Purpose
- Web-based drawing tool with infinite canvas
- Hand-drawn aesthetic with support for shapes, arrows, text
- End-to-end encrypted collaboration
- Works offline as a PWA (Progressive Web App)
## Architecture
The project is organized as a monorepo with these main components:
1. Core Package (packages/excalidraw)
- React component library for embedding Excalidraw in any application
- Handles drawing, rendering, and core functionality
- Uses roughjs for the hand-drawn style
- Includes export capabilities (PNG, SVG)
2. Web Application (excalidraw-app/)
- Full-featured web app at excalidraw.com
- Built on top of the core package
- Adds collaboration features, local storage, sharing
3. Support Packages
- common - Shared utilities and constants
- element - Element manipulation and type definitions
- math - Mathematical functions for drawing
- utils - General utility functions
4. Examples
- Integration examples (Next.js, browser script)
- Shows how to embed Excalidraw in different environments
5. Documentation (dev-docs/)
- API documentation
- Integration guides
- Component documentation
## Key Features
- Real-time collaboration with end-to-end encryption
- Export to various formats (PNG, SVG, JSON)
- Customizable drawing tools (rectangle, circle, arrows, freehand)
- Dark mode support
- Localization
- Library of shapes and components
- Arrow bindings and labels
- Image support
## Technology Stack
- React for UI
- TypeScript for type safety
- Firebase for collaboration backend
- Jotai for state management
- Vite for development and building
- IndexedDB/LocalStorage for offline storage
The architecture allows for both using Excalidraw as a component in other applications and as a standalone web application with additional features.
```
- ### Code onboarding
Claude Code maps and explains entire codebases in a few seconds. It uses agentic search to understand project structure and dependencies without you having to manually select context files.
- ### Turn issues into PRs
Stop bouncing between tools. Claude Code works with GitHub, GitLab, and your command line tools to read issues, write code, run tests, and open pull requests.
- ### Run multi-hour refactors and migrations
Claude Code follows imports across the repo, runs your tests, and keeps going when something breaks.
## Meets you where you code
### Start in your terminal
Super powerful terminal integration. Works with all your CLI tools alongside any IDE.
curl -fsSL https://claude.ai/install.sh \| bash
Or read the [documentation](code-home.md)
[Try Claude Code (opens in new tab)](https://claude.ai/code)[Developer docs (opens in new tab)](code-home.md)
### Integrate with your editor
Native extensions for VS Code (+ Cursor, Devin Desktop) and JetBrains IDEs.
[VS Code (opens in new tab)](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code)[JetBrains (opens in new tab)](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-)
### Access anywhere
Quick access from browser, mobile app, or Claude on desktop. Great for parallel work or on-the-go coding.
[Open in browser (opens in new tab)](https://claude.ai/code)[Download app](https://code.claude.com/download)
## Kick off coding tasks in Slack
[Add to Slack (opens in new tab)](https://slack.com/oauth/v2/authorize?client_id=1601185624273.8899143856786&scope=app_mentions:read,assistant:write,channels:history,channels:read,chat:write,files:read,files:write,groups:history,groups:read,im:history,im:read,im:write,mpim:history,reactions:write,users:read,users:read.email,commands,search:read.public&user_scope=bookmarks:read,channels:history,channels:read,chat:write,emoji:read,files:read,groups:history,groups:read,groups:write,im:history,im:read,im:write,links:read,mpim:history,mpim:read,mpim:write,mpim:write.topic,pins:read,reactions:read,reactions:write,remote_files:read,team:read,users:read,users:read.email,search:read.public,search:read.private,search:read.im,search:read.mpim,search:read.files,search:read.users,canvases:read,canvases:write)[Learn more](https://code.claude.com/claude-for-slack)
## What developers are saying
-
> “Claude Code has dramatically accelerated our team's coding efficiency. I can now write EDA code in a notebook—pulling data, training a model, and evaluating it with basic metrics—and then ask Claude to convert that into a Metaflow pipeline. This process saves 1-2 days of routine (and often boring!) work per model.”
Anton Biryukov, Staff Software Engineer
[Read story](https://code.claude.com/customers/ramp)
-
> “With Claude, we're not just automating customer service—we're elevating it to truly human quality. This lets support teams think more strategically about customer experience and what makes interactions genuinely valuable.”
Fergal Reid, VP of AI
[Read story](https://code.claude.com/customers/intercom)
-
> “Claude Code is moving our team up a level: we decide what needs to happen, and smooth the process so it can build and verify end-to-end. A big part of my job now is to keep as many instances of Claude Code busy as possible.”
Simon Last, Co-founder
[Read story](https://code.claude.com/customers/notion)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Connects with your favorite command line tools
Your terminal is where real work happens. Claude Code connects with the tools that power development—deployment, databases, monitoring, version control. Rather than adding another interface to juggle, it enhances your existing stack.
## FAQ
### How do I get started with Claude?
You can access Claude Code with a Claude Pro or Max plan, a Team or Enterprise plan, or a Claude Console account. [Download Claude Code](code-home.md) and sign in with your respective Claude or Console credentials.
### What kind of tasks can Claude Code handle?
Claude Code can handle routine work like bug fixes and testing, and larger jobs like refactors and new features that are long-running and asynchronous.
You set the direction as the architect and orchestrator, and Claude Code does the work. Describe what you want and it plans, writes code, runs tests, and opens pull requests. It can work on several tasks at once, and surface decisions you need to make for it to keep going.
### How does Claude Code work with my existing tools?
Claude Code runs in your terminal and works alongside your preferred IDE and development tools without requiring you to change your workflow. Claude Code can also use command line tools (like Git) and MCP servers (like GitHub) to extend its own capabilities using your tools.
### Is Claude Code secure?
Yes. Claude Code runs locally in your terminal and talks directly to model APIs without requiring a backend server or remote code index. It also asks for permission before making changes to your files or running commands.
### What are the system requirements to run Claude Code?
Claude Code works on macOS, Linux, and Windows. [See full system requirements](../01-Getting-Started/setup.md#system-requirements).
### How much does Claude Code cost?
When used with a Claude Console account, Claude Code consumes API tokens at [standard API pricing](../17-Billing-Plans/pricing.md#api).
### Does Claude Code work with the Claude desktop app?
Yes. Max, Pro, Team, and Enterprise users can access Claude Code on the [Claude desktop app](https://claude.com/download).
### What is fast mode on Claude Code?
Fast mode is a high-speed configuration for Opus 5.5, making the model 2.5x faster at a higher cost per token. Fast mode is available:
- In research preview on Claude Code, and is priced at \$8/\$40 per million tokens.
- On consumption-based plans.
- Via usage credits for users on subscription plans.
## Get the technical rundown
### Claude Code documentation
Developer docs
### Common workflows
Developer docs
### Using CLAUDE.md files
Blog
### Introduction to agentic coding
Blog
### How Anthropic teams use Claude Code
Blog
### Fix software bugs faster with Claude
Blog
## Create what’s exciting. Maintain what’s essential.
Use Claude Code where you work
Get Claude Code
- [Desktop](https://code.claude.com/download)
- [VS Code](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code)
- [JetBrains](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-)
- [On the web](https://claude.ai/code)
- [Slack](https://slack.com/oauth/v2/authorize?client_id=1601185624273.8899143856786&scope=app_mentions:read,assistant:write,channels:history,channels:read,chat:write,files:read,files:write,groups:history,groups:read,im:history,im:read,im:write,mpim:history,reactions:write,users:read,users:read.email,commands,search:read.public&user_scope=bookmarks:read,channels:history,channels:read,chat:write,emoji:read,files:read,groups:history,groups:read,groups:write,im:history,im:read,im:write,links:read,mpim:history,mpim:read,mpim:write,mpim:write.topic,pins:read,reactions:read,reactions:write,remote_files:read,team:read,users:read,users:read.email,search:read.public,search:read.private,search:read.im,search:read.mpim,search:read.files,search:read.users,canvases:read,canvases:write)
curl -fsSL https://claude.ai/install.sh \| bash
Or read the [documentation](code-home.md)
[Try Claude Code (opens in new tab)](https://claude.ai/code)[Developer docs (opens in new tab)](code-home.md)
---
## Overview - Claude Code Docs
Source: https://code.claude.com/docs
Path: 02-Claude-Code-CLI/code-home.md
## On this page
- [Get started](#get-started)
- [What you can do](#what-you-can-do)
- [Use Claude Code everywhere](#use-claude-code-everywhere)
- [Next steps](#next-steps)
Getting started
# Overview
Copy pageCopy page
Claude Code is an agentic coding tool that reads your codebase, edits files, runs commands, and integrates with your development tools. Available in your terminal, IDE, desktop app, and browser.
Copy pageCopy page
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)
Get started
Claude Code runs on several surfaces: the terminal, IDE extensions, a desktop app, and the web. Choose one from the tabs below to get started. Most surfaces require a [Claude subscription](../17-Billing-Plans/pricing.md) or [Anthropic Console](../04-API-Reference/Other/usage-limits.md) account. The Terminal CLI, VS Code, and JetBrains also support [third-party providers](third-party-integrations.md).
- 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, open a terminal and run the command for your system. If you haven’t used a terminal before, the [terminal guide](terminal-guide.md) shows how to open one and paste the command.
- Native Install (Recommended)
- Homebrew
- WinGet
**macOS, Linux, WSL:**
```python
curl -fsSL https://claude.ai/install.sh | bash
```
**Windows PowerShell:**
```python
irm https://claude.ai/install.ps1 | iex
```
**Windows CMD:**
```python
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
When the installer finishes, open a new terminal window and run `claude --version`. A working installation prints a version number. If your shell says `claude` isn’t found or isn’t recognized, the install directory isn’t on your PATH yet: see [Fix your PATH](troubleshoot-install.md#command-not-found-claude-after-installation).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.If the install command fails with `syntax error near unexpected token '<'`, a `403`, or another curl error, see [Troubleshoot installation](troubleshoot-install.md#find-your-error) to match the error to a fix and for alternative install methods.[Git for Windows](https://git-scm.com/downloads/win) 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.
```python
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.
```python
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](../01-Getting-Started/setup.md#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.Then start Claude Code in any project. Replace `your-project` with the path to a project directory on your machine:
```python
cd your-project
claude
```
You’ll be prompted to log in on first use. If you’ve set the `ANTHROPIC_API_KEY` environment variable, Claude Code skips the login prompt and asks you to approve the key instead. That’s it! [Continue with the Quickstart →](../01-Getting-Started/quickstart.md)
See [advanced setup](../01-Getting-Started/setup.md) for installation options, manual updates, or uninstallation instructions. Visit [installation troubleshooting](troubleshoot-install.md) 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](vscode:extension/anthropic.claude-code)
- [Install for Cursor](cursor:extension/anthropic.claude-code)
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 →](../03-IDE-Integrations/vs-code.md#get-started)
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 start cloud sessions.Download and install:
- [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs) (Intel and Apple Silicon)
- [Windows](https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code&utm_medium=docs) (x64)
- [Windows ARM64](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code&utm_medium=docs)
- On Ubuntu or Debian, where the app is in beta, install it with apt by following the [Linux install instructions](../16-Mobile-Desktop/desktop-linux.md)
After installing, launch Claude, sign in, and click the **Code** tab to start coding. The app includes Claude Code, so you don’t need to install the CLI separately. A [paid subscription](../17-Billing-Plans/pricing.md) is required.[Learn more about the desktop app →](../16-Mobile-Desktop/desktop-quickstart.md)
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. For a longer body of work, create a [project](claude-projects.md) and let Claude coordinate the parallel sessions for you. Available on desktop browsers and [the Claude app for iOS and Android](../16-Mobile-Desktop/mobile.md).Start coding at [claude.ai/code](https://claude.ai/code).[Get started →](web-quickstart.md)
A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.Install the [Claude Code plugin](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-) from the JetBrains Marketplace and restart your IDE. The plugin requires the Claude Code CLI, installed separately; see the [JetBrains setup steps](../03-IDE-Integrations/jetbrains.md#installation).[Get started with JetBrains →](../03-IDE-Integrations/jetbrains.md)
[](#what-you-can-do)
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.
```python
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](common-workflows.md) 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.
```python
claude "commit my changes with a descriptive message"
```
In CI, you can automate code review and issue triage with [GitHub Actions](github-actions.md) or [GitLab CI/CD](gitlab-ci-cd.md).
Connect your tools with MCP
The [Model Context Protocol (MCP)](../06-MCP-Tools/General/mcp.md) 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. The [MCP quickstart](../06-MCP-Tools/General/mcp-quickstart.md) connects your first server end to end.
Customize with instructions, skills, and hooks
[`CLAUDE.md`](memory.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. If your repository already has an `AGENTS.md` for other coding agents, Claude Code [can read that](memory.md#agents-md) on its own or alongside `CLAUDE.md`. Claude also builds [auto memory](memory.md#auto-memory) as it works, saving learnings across sessions without you writing anything.Create [skills](../08-Plugins-Skills/skills.md) to package repeatable workflows your team can share, like `/review-pr` or `/deploy-staging`.[Hooks](../07-Hooks/hooks.md) 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 agents in parallel and build custom agents
Spawn [multiple Claude Code agents](../09-Agents-Patterns/sub-agents.md) 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](../09-Agents-Patterns/agent-view.md). For fully custom workflows, the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) 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:
```python
# 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](cli-reference.md) 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](web-scheduled-tasks.md) run in the cloud, 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](../16-Mobile-Desktop/desktop-scheduled-tasks.md) run on your machine, with direct access to your local files and tools
- [`/loop`](scheduled-tasks.md) repeats a prompt within a CLI session for quick polling
Work from anywhere
Sessions aren’t tied to a single surface. Move work between them as your context changes:
- Step away from your desk and keep working from your phone or any browser with [Remote Control](remote-control.md)
- Message [Dispatch](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch) a task from your phone and open the Desktop session it creates
- Start a long-running task on the [web](claude-code-on-the-web.md) or the [Claude mobile app](../16-Mobile-Desktop/mobile.md), then pull it into your terminal with `claude --teleport`. Teleport requires a claude.ai subscription.
- Run `/desktop` to continue your current terminal session in the [Desktop app](../16-Mobile-Desktop/desktop.md), where you can review diffs visually. The `/desktop` handoff requires a claude.ai subscription. Available on macOS and x64 Windows.
- Route tasks from team chat: mention `@Claude` in [Slack](../14-Connectors/slack.md) with a bug report and get a pull request back
[](#use-claude-code-everywhere)
Use Claude Code everywhere
Each [surface](glossary.md#surface) connects to the same underlying Claude Code engine, so your repo’s CLAUDE.md files, settings, and MCP servers work across all of them. Beyond the [Terminal](../01-Getting-Started/quickstart.md), [VS Code](../03-IDE-Integrations/vs-code.md), [JetBrains](../03-IDE-Integrations/jetbrains.md), [Desktop](../16-Mobile-Desktop/desktop.md), and [Web](claude-code-on-the-web.md) surfaces above, Claude Code integrates with CI/CD, chat, and browser workflows:
| What I want to do | Best option |
|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| Continue a local session from my phone or another device | [Remote Control](remote-control.md) |
| Push events from Telegram, Discord, iMessage, or my own webhooks into a session | [Channels](channels.md) |
| Start a task locally, continue on mobile | [`claude --cloud`](claude-code-on-the-web.md#from-terminal-to-cloud), then the [Claude mobile app](../16-Mobile-Desktop/mobile.md) |
| Run Claude on a recurring schedule | [Routines](web-scheduled-tasks.md) or [Desktop scheduled tasks](../16-Mobile-Desktop/desktop-scheduled-tasks.md) |
| Automate PR reviews and issue triage | [GitHub Actions](github-actions.md) or [GitLab CI/CD](gitlab-ci-cd.md) |
| Get automatic code review on every PR | [GitHub Code Review](code-review.md) |
| Route bug reports from Slack to pull requests | [Slack](../14-Connectors/slack.md) |
| Debug live web applications | [Chrome](../03-IDE-Integrations/chrome.md) |
| Build custom agents for your own workflows | [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) |
[](#next-steps)
Next steps
Once you’ve installed Claude Code, these guides help you go deeper.
- [Quickstart](../01-Getting-Started/quickstart.md): walk through your first real task, from exploring a codebase to committing a fix
- [Store instructions and memories](memory.md): give Claude persistent instructions with CLAUDE.md files and auto memory
- [Common workflows](common-workflows.md) and [best practices](best-practices.md): patterns for getting the most out of Claude Code
- [Claude Academy](https://academy.claude.com/): free self-paced courses, including [Claude Code 101](https://academy.claude.com/courses/claude-code-101) and [Claude Code in Action](https://academy.claude.com/courses/claude-code-in-action)
- [A harness for every task](https://claude.com/blog/a-harness-for-every-task-dynamic-workflows-in-claude-code): how the Claude Code team uses [dynamic workflows](workflows.md) to orchestrate many subagents at once
- [Settings](settings.md): customize Claude Code for your workflow
- [Troubleshooting](troubleshooting.md): solutions for common issues
- [code.claude.com](code-claude-com-code-home.md): demos, pricing, and product details
---
## Code Review - Claude Code Docs
Source: https://code.claude.com/docs/en/code-review
Path: 02-Claude-Code-CLI/code-review.md
## On this page
- [How reviews work](#how-reviews-work)
- [Severity levels](#severity-levels)
- [Rate and reply to findings](#rate-and-reply-to-findings)
- [Check run output](#check-run-output)
- [What Code Review checks](#what-code-review-checks)
- [Set up Code Review](#set-up-code-review)
- [Manually trigger reviews](#manually-trigger-reviews)
- [Review pull requests from forks](#review-pull-requests-from-forks)
- [Customize reviews](#customize-reviews)
- [CLAUDE.md](#claude-md)
- [REVIEW.md](#review-md)
- [What you can tune](#what-you-can-tune)
- [Example](#example)
- [Keep it focused](#keep-it-focused)
- [View usage](#view-usage)
- [Pricing](#pricing)
- [Troubleshooting](#troubleshooting)
- [Retrigger a failed or timed-out review](#retrigger-a-failed-or-timed-out-review)
- [Review didn’t run and the PR shows a spend-cap message](#review-didn%E2%80%99t-run-and-the-pr-shows-a-spend-cap-message)
- [Find issues that aren’t showing as inline comments](#find-issues-that-aren%E2%80%99t-showing-as-inline-comments)
- [Review a diff locally](#review-a-diff-locally)
- [What the review reads and edits](#what-the-review-reads-and-edits)
- [Tune effort and arguments](#tune-effort-and-arguments)
- [Run in the foreground](#run-in-the-foreground)
- [Let Claude start the review](#let-claude-start-the-review)
- [Escalate to ultrareview](#escalate-to-ultrareview)
- [Related resources](#related-resources)
Code review & CI/CD
# Code Review
Copy pageCopy page
Set up automated PR reviews that catch logic errors, security vulnerabilities, and regressions using multi-agent analysis of your full codebase
Copy pageCopy page
Code Review is in research preview, available for [Team and Enterprise](https://claude.ai/admin-settings/claude-code) subscriptions. It is not available for organizations with [Zero Data Retention](zero-data-retention.md) enabled. On other plans, you can still [review a diff locally](#review-a-diff-locally) with the `/code-review` command.
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](github-actions.md) or [GitLab CI/CD](gitlab-ci-cd.md). For repositories on a self-hosted GitHub instance, see [GitHub Enterprise Server](github-enterprise-server.md). This page covers:
- [How reviews work](#how-reviews-work)
- [Setup](#set-up-code-review)
- [Triggering reviews manually](#manually-trigger-reviews) with `@claude review` and `@claude review always`
- [Customizing reviews](#customize-reviews) with `CLAUDE.md` and `REVIEW.md`
- [Pricing](#pricing)
- [Troubleshooting](#troubleshooting) failed runs and missing comments
- [Reviewing a diff locally](#review-a-diff-locally) with the `/code-review` command
[](#how-reviews-work)
How reviews work
Once an Owner [enables Code Review](#set-up-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 a review on a PR](#manually-trigger-reviews) 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, Code Review updates the GitHub check run to show that no issues were detected. Claude may also post a short confirmation comment on the PR. Reviews scale in cost with PR size and complexity, completing in 20 minutes on average. Owners can monitor review activity and spend via the [analytics dashboard](#view-usage).
[](#severity-levels)
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 collapsed **Why this was flagged** section that you can expand to read why Claude flagged the issue and how it verified the problem.
[](#rate-and-reply-to-findings)
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` as a [top-level PR comment](#manually-trigger-reviews). To dismiss a finding without a code change, resolve its thread; replying doesn’t dismiss it.
[](#check-run-output)
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. To find the check run ID, list the commit’s check runs with `gh api repos/OWNER/REPO/commits/<commit-sha>/check-runs --jq '.check_runs[] | {id, name}'` and take the `id` of the `Claude Code Review` run. Replace `OWNER`, `REPO`, and `CHECK_RUN_ID` with your repository owner, repository name, and that ID:
```python
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)
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](#customize-reviews) to your repository.
[](#set-up-code-review)
Set up Code Review
An Owner 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](https://claude.ai/admin-settings/claude-code) and find the Code Review section. You need the Owner or Primary Owner role in 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: pick the GitHub organization that owns the repositories you want reviewed, choose which repositories the app can access, and approve the requested permissions.To review a pull request, Claude reads your repository contents through the app’s read access, and posts comments and the [check run](#check-run-output) through its write access to pull requests and checks. During installation, you grant a broader permission set shared by other Claude features, such as [GitHub Actions](github-actions.md); see [GitHub App permissions](github-actions.md#github-app-permissions) for the full list.
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**: opening or pushing to a PR doesn’t start a review; comment [`@claude review`](#manually-trigger-reviews) to request one, or `@claude review always` to also subscribe the PR to reviews on subsequent pushes
Whichever option you choose, Claude reviews a [pull request from a fork](#review-pull-requests-from-forks) only when someone comments `@claude review` on it.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)
Manually trigger reviews
Comment commands start a review on demand. They 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 single review without subscribing the PR to future pushes |
| `@claude review always` | Starts a review and subscribes the PR to push-triggered reviews going forward |
| `@claude review once` | Same as `@claude review`: starts a single review without subscribing |
Use `@claude review always` when you want every subsequent push to the PR to start a fresh review, such as on a high-priority PR in a repository set to Manual mode. Because the bare command doesn’t subscribe the PR, you can request a one-off second opinion without changing whether later pushes trigger reviews.
Before a July 2026 update, `@claude review` subscribed the PR to push-triggered reviews. If you relied on that behavior, comment `@claude review always` instead. `@claude review once` still works and behaves the same as the bare command.
For any of these commands 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` or `always` on the same line as the rest of the command
- You must have write, maintain, or admin permission on the repository
- The PR must be open
If the repository belongs to an organization and your membership in that organization is private, which is GitHub’s default, GitHub doesn’t identify you to Claude as a member. Claude may still react to your comment with 👀, but it doesn’t start a review unless you were added to the repository directly as a collaborator, even when a team or the organization’s base permissions give you write access. To fix this, [make your organization membership public](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-membership-in-organizations/publicizing-or-hiding-organization-membership) or ask a repository admin to add you to the repository as a collaborator. 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.
[](#review-pull-requests-from-forks)
Review pull requests from forks
Claude doesn’t review a pull request from a fork automatically, regardless of the repository’s **Review Behavior** setting. To start one, comment `@claude review` on the pull request. The [requirements for comment commands](#manually-trigger-reviews) still apply, and the write access you need is to the base repository, not the fork. To get another review of a fork pull request, post a new `@claude review` comment. `@claude review always` works too, but doesn’t subscribe the pull request to reviews on later pushes. Nothing other than a comment command starts a review on a fork pull request:
- Clicking **Re-run** on the check run doesn’t start a review
- Pushing new commits doesn’t start a review, even in a repository set to **After every push**
[](#customize-reviews)
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, given to the agents that find and verify findings and consulted by the agents that rank and report them. Use it to say what your team wants flagged, at what severity, and how findings are reported.
[](#claude-md)
CLAUDE.md
Code Review reads your repository’s `CLAUDE.md` files and treats newly introduced violations as [nit-level](#severity-levels) 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](memory.md) 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`](#review-md) instead.
[](#review-md)
REVIEW.md
`REVIEW.md` is a file at your repository root that tailors Code Review to your repo. The agents in the review pipeline that find and verify findings receive its contents as your repository’s review instructions, alongside Code Review’s default review guidance, and the agents that rank and report findings consult it before settling severity and writing the review. Put the rules you want enforced directly in `REVIEW.md`.
[](#what-you-can-tune)
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` reaches every finding and verification agent directly, 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)
Example
This `REVIEW.md` recalibrates severity for a backend service, caps nits, skips generated files, and adds repo-specific checks.
```python
# 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)
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)
View usage
Go to [claude.ai/analytics/code-review](https://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 |
Dashboard cost figures are estimates for monitoring activity. For invoice-accurate spend, refer to your Anthropic bill.
[](#pricing)
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 [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) 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 on open or push, so cost accrues only from reviews someone requests
In Once after PR creation or Manual mode, commenting `@claude review always` [opts the PR into push-triggered reviews](#manually-trigger-reviews), so additional cost accrues per push after that comment. In After every push mode, pushes already trigger reviews, so the subscription doesn’t change per-push cost. Commenting `@claude review` runs a single review without subscribing to future pushes. Claude reviews a [pull request from a fork](#review-pull-requests-from-forks) only when someone comments `@claude review`, so a fork pull request never accrues per-push cost in any mode. Costs appear on your Anthropic bill regardless of whether your organization uses Amazon Bedrock or Google Cloud’s Agent Platform for other Claude Code features. To set a monthly spend cap for Code Review, go to [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage) and configure the limit for the Claude Code Review service. Monitor spend via the weekly cost chart in [analytics](#view-usage) or the per-repo average cost column in admin settings.
[](#troubleshooting)
Troubleshooting
Review runs are best-effort, and a failed run never blocks your PR. Code Review retries some interrupted reviews on its own. This section covers how to run a review again yourself and where to look when the check run reports issues you can’t find.
[](#retrigger-a-failed-or-timed-out-review)
Retrigger a failed or timed-out review
When a review fails or exceeds its time limit, the check run completes with a title such as **Code review failed** or **Code review timed out**. The conclusion is still neutral, so nothing blocks your merge. Unless the check run’s summary says a new review of the commit has been queued automatically, run the review again yourself. To run the review again, comment `@claude review` on the PR. This starts a fresh review without subscribing the PR to future pushes. If the PR isn’t [from a fork](#review-pull-requests-from-forks), you can instead click **Re-run** on the **Claude Code Review** check in GitHub’s Checks tab. A re-run also starts a fresh review without subscribing the PR.
[](#review-didn’t-run-and-the-pr-shows-a-spend-cap-message)
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](https://claude.ai/admin-settings/usage).
[](#find-issues-that-aren’t-showing-as-inline-comments)
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.
[](#review-a-diff-locally)
Review a diff locally
The [`/code-review` command](commands.md) reviews a diff in your terminal without installing the GitHub App. It reports correctness bugs and reuse, simplification, and efficiency cleanups. `/review` is an alias of `/code-review`; before v2.1.223, it was a separate command that ran a single-pass, read-only review of a GitHub pull request.
1
Run /code-review
From the session where you’re working, run the command:
```python
/code-review
```
It reviews your branch’s commits ahead of its upstream plus any uncommitted changes, so it needs work on the branch or in the working tree to have something to report. To review something else, pass a target: a file path, a PR number, a branch name, or a ref range such as `main...my-feature`.You can also add flags:
- `--fix`: applies the findings to your working tree after the review
- `--comment`: posts the findings on a GitHub pull request as inline comments, or on a GitLab merge request as a single note
- `--post`: on an `ultra` cloud review of a `github.com` pull request, preselects posting the finished findings to the PR in the launch dialog; see [Post findings to the pull request](ultrareview.md#post-findings-to-the-pull-request). Requires Claude Code v2.1.227 or later
When you pass `--comment` for a GitLab merge request, Claude Code posts the findings through GitLab’s `glab` CLI. Requires Claude Code v2.1.257 or later. When `glab` isn’t installed, Claude prints the findings in the terminal instead.Pass the merge request as its URL or a `!123` reference. Claude Code treats a bare number or branch name as a merge request only when the checkout’s origin is on `gitlab.com`. On a self-managed GitLab instance, pass the URL or `!123` form.
2
Keep working
The review runs as a background [subagent](../09-Agents-Patterns/sub-agents.md) with its own context window, so it doesn’t fill your conversation. The findings arrive in your conversation when the review completes.
3
Act on the findings
Ask Claude to fix what the review found. If you passed `--fix` or `--comment`, the review has already applied or posted its findings.
Claude reports the findings as text in the reply in both of these runs, even when a host application requests a findings list:
- In a terminal session, where `/code-review` runs the review as a [forked subagent](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent)
- In a `-p` run with text or JSON output
In a host application that requests the findings list, such as the [desktop app](../16-Mobile-Desktop/desktop.md), Claude reports the review’s findings through the [`ReportFindings` tool](tools-reference.md) instead. Claude Code renders the report as a findings list, and each entry shows the file location, a one-sentence summary, and a category tag such as `correctness` when the finding carries one. A host request applies at every effort level and requires Claude Code v2.1.218 or later. When Claude fixes reported findings later in the session, it reports them again, and Claude Code marks each finding in the updated findings list as fixed, skipped, or no change needed.
[](#what-the-review-reads-and-edits)
What the review reads and edits
The review follows your `CLAUDE.md` like any Claude Code session, but it doesn’t read [`REVIEW.md`](#review-md). A background review applies its `--fix` edits outside your session’s [checkpoints](checkpointing.md#subagent-edits-not-restored), so `/rewind` doesn’t undo them; use git to revert them. When the review [runs in the foreground](#run-in-the-foreground), it edits your working tree during your own turn, so `/rewind` restores its edits as usual.
[](#tune-effort-and-arguments)
Tune effort and arguments
Pass an [effort level](model-config.md#adjust-effort-level) to trade coverage for confidence. At `low` and `medium`, the review reports only the findings it’s most confident in, so you see fewer false positives; `high` through `max` broaden coverage and may include findings the review is less sure about. When you don’t type a level, the review reuses the last level from `low` through `max` you typed, even in an earlier session, and Claude Code shows a notice such as `Reusing high effort, the level you typed last time`. Type a level, like `/code-review high`, to change what later runs reuse; a level you pass in a non-interactive `-p` run doesn’t update it. `ultra` neither updates nor uses the remembered level. If you’ve never typed a level, the review uses the session’s current effort. Before v2.1.223, a `/code-review` without a level always used the session’s current effort. After the effort level and flags, Claude Code reads the rest of the line in one of two ways:
- **Without `ultra`**: everything left is the review target, even when it starts with another command name. `/code-review /fix-issue 123` reviews with `/fix-issue 123` as target text instead of loading `/fix-issue` as a second [stacked skill](../08-Plugins-Skills/skills.md#pass-arguments-to-skills). Before v2.1.218, a command stacked after `/code-review` expanded as its own skill.
- **With `ultra`**: Claude Code reads a single word as a base branch or PR number, and turns longer text that doesn’t name a branch or PR into [a note attached to the review](ultrareview.md#pass-a-request-in-plain-words). `/code-review ultra check my auth changes` reviews your current branch, and Claude relates the findings to your note.
[](#run-in-the-foreground)
Run in the foreground
The review runs in the background by default; before v2.1.218, it ran inside your conversation. It runs in the foreground instead in cases like these:
- You run `/code-review` again while an earlier review is still in progress
- You run it in non-interactive mode, with the `-p` flag or the Agent SDK; Claude Code waits for the review and includes the findings in the response, except for `ultra`, which [launches the cloud review without waiting](#escalate-to-ultrareview)
- You set [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS`](env-vars.md) to `1`, which also turns off every other background task feature
[](#let-claude-start-the-review)
Let Claude start the review
Claude can start `/code-review` on its own. Ask it to review your changes in plain language and it can run the skill without you typing the command, and a [scheduled task](scheduled-tasks.md) with `/code-review` as its prompt runs the review. A scheduled task never launches the [cloud review](#escalate-to-ultrareview), so schedule `/code-review` without the `ultra` argument. To stop both Claude and scheduled tasks from starting the review while keeping `/code-review` available for you to type, add a [`skillOverrides`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) entry to a [settings file](settings.md#where-settings-live) such as `~/.claude/settings.json`:
```python
{
"skillOverrides": {
"code-review": "user-invocable-only"
}
}
```
Before v2.1.246, Claude started `/code-review` on its own only where a feature flag fetched from Anthropic turned it on. In [sessions that don’t fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), `/code-review` ran only when you typed it, and a scheduled `/code-review` reached Claude as plain text.
[](#escalate-to-ultrareview)
Escalate to ultrareview
`/code-review ultra --fix` runs the deeper [ultrareview](ultrareview.md) in the cloud, then applies its findings to your working tree when they arrive back in your session. Ultrareview uses its own scope: your current branch against the repository’s default branch, plus uncommitted and staged changes in the working tree. For uncommitted changes to files named like credentials or keys, such as `.env` and `*.tfvars` files, Claude Code follows the rules for [uploading a local repository to a cloud session](claude-code-on-the-web.md#send-local-repositories-without-github). Pass a branch name, such as `/code-review ultra develop`, to compare against a different base. When the target is a `github.com` pull request, you can have Claude [post the finished findings to the PR](ultrareview.md#post-findings-to-the-pull-request) as a comment from your GitHub account. Requires Claude Code v2.1.227 or later.
Ultrareview requires authentication with a claude.ai account and is not available on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry, or to organizations with Zero Data Retention enabled. When ultrareview is not available, `/code-review ultra` runs a local review in your session instead.
To start a cloud review from a script or CI, run `claude -p '/code-review ultra'`. Claude Code launches the review and prints a link for tracking it. Requires Claude Code v2.1.218 or later. When the review would bill [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans), Claude Code stops before launching, because the billing confirmation needs an interactive session. Run the [`claude ultrareview` subcommand](ultrareview.md#run-ultrareview-non-interactively) instead; by running it, you consent to the charge. The command was named `/simplify` before v2.1.147, when it applied fixes by default. `/simplify` runs a separate cleanup-only review that applies fixes without hunting for bugs. If you scripted `/simplify` for bug-finding, switch to `/code-review --fix`.
[](#related-resources)
Related resources
- [Commands](commands.md): run `/code-review` in a local Claude Code session to check a diff before pushing
- [GitHub Actions](github-actions.md): run Claude in your own GitHub Actions workflows for custom automation beyond code review
- [GitLab CI/CD](gitlab-ci-cd.md): self-hosted Claude integration for GitLab pipelines
- [Memory](memory.md): how `CLAUDE.md` files work across Claude Code
- [Analytics](../13-Enterprise-Admin/analytics.md): track Claude Code usage beyond code review
- [How Anthropic secures its AI-native software development lifecycle](https://claude.com/blog/how-anthropic-secures-its-ai-native-software-development-lifecycle): how automated review fits as one layer of Anthropic’s secure development process
---
## Commands - Claude Code Docs
Source: https://code.claude.com/docs/en/commands
Path: 02-Claude-Code-CLI/commands.md
## On this page
- [Commands across a typical workflow](#commands-across-a-typical-workflow)
- [All commands](#all-commands)
- [How the command menu matches what you type](#how-the-command-menu-matches-what-you-type)
- [MCP prompts](#mcp-prompts)
- [See also](#see-also)
Reference
# Commands
Copy pageCopy page
Complete reference for commands available in Claude Code, including built-in commands and bundled skills.
Copy pageCopy page
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 the commands available to you, or type `/` followed by letters to filter. [How the command menu matches what you type](#how-the-command-menu-matches-what-you-type) covers highlighting, typos, and the few commands Claude Code hides from the menu until you type their full name. A command is only recognized at the start of your message. Text that follows the command name becomes its arguments. As of v2.1.199, [skills](../08-Plugins-Skills/skills.md#pass-arguments-to-skills) are the exception: a skill invocation followed by more skills, such as `/skill-a /skill-b do XYZ`, loads every skill named at the start and passes the trailing text to each as arguments. Up to six skills can be chained. If you send a command while Claude is responding, Claude Code queues it and runs it after the current turn finishes. Claude Code runs some commands immediately without interrupting the response, such as `/status`, `/tasks`, and `/usage`. In [fullscreen rendering](fullscreen.md), Claude Code also opens dialog commands such as `/theme` and `/help` immediately. Before v2.1.234, Claude Code queued those dialogs until the turn finished.
[](#commands-across-a-typical-workflow)
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` to set up any servers the project needs, ask Claude to create any [subagents](../09-Agents-Patterns/sub-agents.md) you want, and run `/permissions` to set your approval rules. **During a task.** `/plan` switches into plan mode before a large change. `/model` and `/effort` adjust which model you’re using and how much reasoning it applies. When the conversation gets long, `/context` shows what’s filling the window and `/compact` summarizes it to free space. Use `/btw` for a side question that shouldn’t add to the conversation history. **Run work in parallel.** Claude delegates side tasks to [subagents](../09-Agents-Patterns/sub-agents.md), and `/tasks` lists the current session’s background work, including subagents that have finished. `/background` detaches the whole session to keep running as a [background agent](../09-Agents-Patterns/agent-view.md) 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](worktrees.md). See [Run agents in parallel](../09-Agents-Patterns/agents.md) for how these approaches relate. **Before you ship.** `/diff` shows what changed. `/code-review` checks the current diff for correctness bugs and can apply the findings with `--fix`; pass a PR number, such as `/code-review high 1234`, to review a pull request instead. `/review` is an alias. `/code-review ultra` runs a multi-agent review in the cloud. `/security-review` checks the diff for security vulnerabilities. **Between sessions.** `/clear` starts fresh on a new task while keeping project memory. `/resume` returns to an earlier conversation, `/branch` branches the current one to try a different direction, and `/fork` copies it into a new [background session](../09-Agents-Patterns/agent-view.md). `/teleport` pulls a cloud 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` runs a setup checkup that diagnoses installation and configuration issues and can fix them, `/debug` diagnoses runtime issues, and `/feedback` reports a bug with session context attached.
[](#all-commands)
All commands
The table below lists all the commands included in Claude Code. Most are built-in commands whose behavior is coded into the CLI. Two kinds of entries are marked:
- **[Skill](../08-Plugins-Skills/skills.md#bundled-skills)**: a bundled skill. It works like skills you write yourself: a prompt handed to Claude.
- `/verify` runs only when you invoke it. Before v2.1.215, Claude could also run `/verify` on its own.
- **[Workflow](workflows.md#bundled-workflows)**: a bundled [dynamic workflow](workflows.md) that fans work out across many subagents and runs in the background.
- `/deep-research` runs only when you invoke it. Before v2.1.218, Claude could also start it on its own.
To add your own commands, see [skills](../08-Plugins-Skills/skills.md). 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 x64 Windows when signed in with a Claude subscription, and `/upgrade` doesn’t show on Enterprise plans.
| Command | Purpose |
|:------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/add-dir <path>` | Add a working directory for file access during the current session. Type a partial path to see matching directory suggestions; press `Tab` to accept one. Most `.claude/` configuration [isn’t discovered](permissions.md#additional-directories-grant-file-access-not-configuration) from the added directory. You can’t add most [network paths](errors.md#working-directory-is-a-network-path), such as `\\server\share`. After a successful add, your [`DirectoryAdded` hooks](../07-Hooks/hooks.md#directoryadded) run. When you run it while Claude is responding, Claude Code asks you to confirm the directory right away, and once you confirm, Claude’s next tool call in the same turn can access it. Before v2.1.234, Claude Code queued the command until the turn finished |
| `/advisor [model|off]` | Enable or disable the [advisor tool](advisor.md), which consults a second model for guidance at key moments during a task. Accepts `fable`, `opus`, `sonnet`, or a full model ID. `fable` requires [Fable access](advisor.md#choose-an-advisor-model). Without an argument, opens a picker. In a session without an interactive terminal, or over [Remote Control](remote-control.md#limitations), pass the model or `off` as an argument; with no argument there, the command prints the current advisor as text. These forms require Claude Code v2.1.260 or later |
| `/agents` | As of v2.1.198, running `/agents` prints a reminder to ask Claude to create or manage [subagents](../09-Agents-Patterns/sub-agents.md), or to edit `.claude/agents/` or `~/.claude/agents/` directly. On v2.1.197 and earlier, opens an interactive interface for creating and managing subagent configurations |
| `/artifact-capabilities` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Load the reference for the runtime capabilities a published [artifact](artifacts.md) can use, such as [calling your connectors](artifacts.md#pull-live-data-with-mcp-connectors) or [offering a file download](artifacts.md#offer-a-file-download), including which ones your account has. Claude normally loads it on its own before building a page that uses one. Available where [artifacts](artifacts.md#availability) are |
| `/artifact-diagramming` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Load diagramming guidance for Claude to follow in [artifacts](artifacts.md): when a diagram helps, what to draw, and how to write inline SVG that stays legible in light and dark themes. Requires Claude Code v2.1.221 or later |
| `/artifacts` | List the [artifacts](artifacts.md#find-an-artifact-again) you own or that are shared with you, then attach one to the session, open it in your browser, or copy its link. Available where [artifacts](artifacts.md#availability) are. Requires Claude Code v2.1.208 or later; attaching with `Enter` requires v2.1.216 |
| `/auto-mode-setup` | [Draft `autoMode.environment` entries](auto-mode-config.md#generate-environment-entries) from your project and recent sessions, then review the draft and save it to your user settings. Requires a Pro, Max, or Team plan and Claude Code v2.1.228 or later. On native Windows, requires v2.1.233 or later |
| `/autocompact [auto|<tokens>]` | Set the auto-compact window: how full the context window gets before Claude Code compacts automatically. Pass a size such as `500k`, or `auto` to return to the window tuned for your model. Claude Code saves the value to user settings and applies it to the current session. See [Set the auto-compact window](model-config.md#set-the-auto-compact-window) for accepted values and what overrides it. Without an argument, opens a dialog that shows the current window. Requires Claude Code v2.1.221 or later |
| `/autofix-pr [prompt]` | Spawn a [cloud session](claude-code-on-the-web.md#auto-fix-pull-requests) 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 cloud 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 [cloud sessions](claude-code-on-the-web.md) |
| `/background [prompt]` | Detach the current session to run as a [background agent](../09-Agents-Patterns/agent-view.md) and free this terminal. Pass a prompt to send one more instruction before detaching. Monitor the session with `claude agents`. To copy the conversation into a new background session while this one keeps running, use `/fork`. Alias: `/bg` |
| `/batch <instruction>` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** 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](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) per unit in an isolated [worktree](worktrees.md). Each subagent implements its unit, runs tests, and publishes its change. Requires a git repository or a [`WorktreeCreate` hook](worktrees.md#non-git-version-control) that creates the worktrees. Outside a git repository, `/batch` requires Claude Code v2.1.281 or later. Example: `/batch migrate src/ from JavaScript to TypeScript` |
| `/branch [name]` | Create a branch of the current conversation at this point, so you can try a different direction without losing the conversation as it stands. Switches you into the branch and preserves the original, which you can return to with `/resume`. To run a copy as a separate [background session](../09-Agents-Patterns/agent-view.md) instead of switching into it, use `/fork`; to hand a side task to a [subagent](../09-Agents-Patterns/sub-agents.md) that reports back into this conversation, use `/subtask` |
| `/btw [question]` | Ask a [side question](interactive-mode.md#side-questions-with-%2Fbtw) about the current session without adding to the conversation. If you run `/btw` without a question, Claude Code shows your most recent side question so you can browse earlier answers; if you haven’t asked one yet, Claude Code prints a usage line. Before v2.1.212, `/btw` required a question |
| `/bug [report]` | Report a bug or share your conversation. You choose how much session history to include and confirm on a consent screen before anything is sent. When you’re signed in to Anthropic on a first-party connection, the report goes to Anthropic; on a third-party provider, or without Anthropic credentials, Claude Code writes the report to a [local archive under `~/.claude/feedback-bundles/`](../13-Enterprise-Admin/data-usage.md#telemetry-services) that you forward yourself. In the [VS Code extension](../03-IDE-Integrations/vs-code.md#use-the-prompt-box), `/bug` opens the extension’s own feedback dialog instead; requires Claude Code v2.1.229 or later. When you run it while Claude is responding, Claude Code opens the dialog immediately. Before v2.1.232, Claude Code queued the command until the turn finished. Alias: `/share`. Before v2.1.212, `/bug` and `/share` were aliases of `/feedback` |
| `/cd <path>` | Move this session to a new working directory, keeping the conversation. Type a partial path to see matching directory suggestions; press `Tab` to accept one. The suggestions require Claude Code v2.1.206 or later. For what Claude Code applies from the new directory as soon as you move, and how `/cd` differs from `/add-dir`, see [Move the session to another directory](permissions.md#move-the-session-to-another-directory) |
| `/chrome` | Configure [Claude in Chrome](../03-IDE-Integrations/chrome.md) settings |
| `/claude-api [migrate|upgrade|managed-agents-onboard|prompt-audit|cost-optimize|build-eval|hillclimb|preserved-thinking-migration]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Load [Claude API](../04-API-Reference/Endpoints/overview.md) and [Managed Agents](../04-API-Reference/Other/managed-agents-overview.md) reference material for your project’s language. Also activates automatically when your code imports `anthropic` or `@anthropic-ai/sdk`. For what each subcommand does and the version it requires, see [Work on Claude API projects](../08-Plugins-Skills/skills.md#work-on-claude-api-projects) |
| `/claude-in-chrome [task]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Have Claude carry out a task in your browser, such as testing a page, filling a form, or reading console logs, through [Claude in Chrome](../03-IDE-Integrations/chrome.md). Available when Chrome integration is enabled for the session, for example with `claude --chrome`, or when Claude Code can offer to [install the extension](../03-IDE-Integrations/chrome.md#install-the-extension-when-claude-asks) |
| `/clear [name]` | Start a new conversation with empty context. Pass a name to label the previous conversation in the `/resume` picker. To free up context while continuing the same conversation, use `/compact` instead. Resume the previous conversation with `/resume`, or, in the same Claude Code process, restore it from [the rewind menu’s previous-session entry](checkpointing.md#rewind-past-a-cleared-conversation). Aliases: `/reset`, `/new` |
| `/code-review [low|medium|high|xhigh|max|ultra] [--fix] [--comment] [pr#|branch|path]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Review the current diff, or a PR number, branch, or path you pass, for correctness bugs. Depending on your model and effort level, the review also covers cleanup opportunities. Pass `--fix` to apply findings, `--comment` to post them on the GitHub PR or GitLab merge request, or `ultra` to run a deep [cloud review](ultrareview.md). Posting to a GitLab merge request requires Claude Code v2.1.257 or later. With `ultra` on a `github.com` PR target, pass `--post` to preselect [posting the finished findings to the PR](ultrareview.md#post-findings-to-the-pull-request) in the launch dialog; `--post` requires Claude Code v2.1.227 or later. See [Review a diff locally](code-review.md#review-a-diff-locally) for the effort levels, targeting, and how it relates to `/simplify`. Alias: `/review` |
| `/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](remote-control.md) is connected, the color syncs to claude.ai/code. Also available in non-interactive mode (`-p`); requires Claude Code v2.1.205 or later |
| `/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](context-window.md#what-survives-compaction) |
| `/config [key=value ...]` | Open the [Settings](settings.md) interface to adjust theme, model, [output style](output-styles.md), and other preferences. Pass one or more `key=value` pairs to set a setting directly without opening the interface, for example `/config thinking=false`, `/config theme=dark`, or `/config model=sonnet`. The `key=value` form also works in non-interactive mode (`-p`) and from the Claude mobile app via [Remote Control](remote-control.md). The `key=value` form can’t turn on a setting that needs your confirmation in the panel, such as [`autoContinueAtUsageLimit`](interactive-mode.md#turn-automatic-continue-off), though it can turn one off. Run `/config --help` to list the keys it accepts. Alias: `/settings` |
| `/context [all]` | Visualize current context usage as a colored grid. Shows optimization suggestions for context-heavy tools, memory bloat, and capacity warnings. When the conversation exceeds the context window, the output includes a [warning](errors.md#context-exceeds-the-token-limit) showing how far over the limit you are and which command frees space. In [fullscreen mode](fullscreen.md), `/context` collapses the per-item breakdown 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` |
| `/dataviz [request]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Design guidance for charts, graphs, and dashboards. Claude picks the chart form for the data, assigns color by role, validates the palette for colorblind safety and contrast with a bundled script, and applies mark, interaction, and accessibility rules. Uses a brand-neutral placeholder palette that you replace with your own. Requires Claude Code v2.1.198 or later |
| `/debug [description]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** 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 |
| `/deep-research <question>` | **[Workflow](workflows.md#bundled-workflows).** Fan out web searches on a question, fetch and cross-check sources, and synthesize a cited report |
| `/design [brief]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Draft UI mockups, screen flows, landing pages, or posters as artboards on one canvas, published as a Claude Design [artifact](artifacts.md#draft-a-design-canvas), for example `/design a settings screen for a mobile banking app`. You edit the artboards in a desktop browser, and your edits save automatically. You can export each artboard as PNG or PDF. Requires Claude Code v2.1.265 or later, a session where [artifacts are available](artifacts.md#availability), and an account where the [Design template is available](artifacts.md#start-from-a-slides-design-or-docs-template); if your organization has turned that template off, `/design` doesn’t draft designs. Available on the Anthropic API. On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Claude Platform on AWS, artifacts aren’t available, so the command is unavailable there |
| `/design-login` | Authorize design-system access for `/design-sync` with your claude.ai account |
| `/design-sync [hint]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Convert your repo’s React design system and upload it to [Claude Design](https://claude.ai/design), so designs it produces use your real components. Optionally name the design system, for example `/design-sync Acme DS`. A first-time sync verifies every component and can take a few hours on a large repo. Available on the Anthropic API. It needs claude.ai, which the CLI doesn’t contact on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or Claude Platform on AWS, or through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md#availability-and-limitations), so the command is unavailable there |
| `/desktop` | Continue the current session in the Claude Code Desktop app. Requires macOS or x64 Windows and a Claude subscription. Alias: `/app` |
| `/diff` | Review the changes in your working tree, including the edits Claude has made so far. See [Review changes with /diff](interactive-mode.md#review-changes-with-%2Fdiff) |
| `/doctor [prompt-audit [path]]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Run a setup checkup that diagnoses issues and can fix them. Checks installation health, including duplicate or leftover installs, `PATH` problems, and unparseable settings files. Finds unused skills, MCP servers, and plugins versus their context cost, flags slow [hooks](../07-Hooks/hooks.md), and checks for a newer version on your [release channel](../01-Getting-Started/setup.md#configure-release-channel). Deduplicates local `CLAUDE.md` files against checked-in ones, trims checked-in [`CLAUDE.md`](memory.md#my-claude-md-is-too-large) files by cutting content Claude could derive from the codebase, and migrates the always-loaded guidance that remains into [skills](../08-Plugins-Skills/skills.md) and nested `CLAUDE.md` files that load on demand. Also offers to make [auto mode](permissions.md#permission-modes) your default and to [pre-approve](permissions.md) frequently denied read-only commands. Reports findings first and asks for confirmation before changing anything. From the terminal, `claude doctor` prints read-only installation diagnostics without starting a session. Alias: `/checkup`. Run `/doctor prompt-audit` to have Claude [audit your `CLAUDE.md` files, skills, and other configuration](memory.md#write-effective-instructions) for outdated or conflicting instructions instead of running the checkup. The `prompt-audit` subcommand requires Claude Code v2.1.283 or later. The `CLAUDE.md` trim check requires Claude Code v2.1.206 or later. Before v2.1.205, `/doctor` opened a read-only diagnostics screen and pressing `f` sent the report to Claude |
| `/effort [level|auto|status|ultracode [on|off]]` | Set the [effort level](model-config.md#adjust-effort-level): `low` to `xhigh`, `max`, or `auto`; `status` prints it. `ultracode` or `ultracode on` turns [ultracode](workflows.md#let-claude-decide-with-ultracode) on for the session at the current level, and `ultracode off` turns it off; the [`ultracode`](settings-reference.md#ultracode) key persists. `max` is session-only. The `on` and `off` arguments and keeping the current level require Claude Code v2.1.284 or later. Before v2.1.284, `/effort ultracode` set the session to `xhigh`, and `/effort ultracode off` failed with `Invalid argument`. Run it while Claude is responding and, once you confirm the [cache warning](prompt-caching.md#changing-effort-level), if Claude Code shows one, Claude Code applies the new level to the next request in that turn. Before v2.1.242, Claude Code decided from a feature flag it fetched from Anthropic whether to run the command mid-turn or queue it until the turn finished, and always queued it in a session that doesn’t [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), such as on a [third-party provider](third-party-integrations.md). Works in `-p` |
| `/exit` | Exit the CLI. In an attached [background session](../09-Agents-Patterns/agent-view.md#attach-to-a-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 |
| `/fast [on|off]` | Toggle [fast mode](fast-mode.md) on or off. Run it while Claude is responding and Claude Code toggles fast mode without waiting for the turn to end, though the running turn finishes at its original speed. Before v2.1.242, Claude Code decided from a feature flag it fetched from Anthropic whether to run the command mid-turn or queue it until the turn finished, and always queued it in a session that doesn’t [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching). Availability in non-interactive mode with `-p` is limited; see [Toggle fast mode](fast-mode.md#toggle-fast-mode). Requires Claude Code v2.1.205 or later |
| `/feedback [report]` | Send product feedback about Claude Code. Opens the same dialog as [`/bug`](#all-commands), with the same consent step, sending rules, and mid-turn behavior. In sessions with [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior), `/feedback` with no argument opens the drafts queue instead, where you review, edit, send, or discard the drafts Claude queued; the queue includes an option to write a new report in the dialog. With an argument, and for `/bug` always, the dialog opens directly |
| `/fewer-permission-prompts` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** 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 tool-call summary also counts the subagents launched in the turn and collapses completed background-task notifications into a single count. The selection persists across sessions; set [`viewMode`](settings-reference.md#viewmode) in settings to override it. Only available in [fullscreen rendering](fullscreen.md). From a [Remote Control](remote-control.md) client, run `/focus [on|off]` to turn the focus view on or off for the current session only, without changing your saved selection; this requires Claude Code v2.1.281 or later. The [VS Code extension](../03-IDE-Integrations/vs-code.md#use-the-prompt-box) offers its own Focus view as a command-menu toggle, stored as an extension setting, independent of `viewMode` |
| `/fork [prompt]` | [Copy the current conversation](../09-Agents-Patterns/agent-view.md#copy-the-session-with-%2Ffork) into a new background session and keep working here. Pass a prompt and the copy starts working on it immediately; without one it waits in agent view for its first prompt. Except when the copy [edits in place](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated), Claude Code instructs it to create a worktree of its own before making code changes; the isolation instruction requires Claude Code v2.1.221 or later. To hand a side task to a subagent whose result comes back into this conversation, use `/subtask`; to switch into a copy yourself, use `/branch`. Requires Claude Code v2.1.212 or later; on v2.1.161 through v2.1.211, and whenever [agent view is turned off](../09-Agents-Patterns/agent-view.md#turn-off-agent-view), `/fork` starts a [forked subagent](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) instead |
| `/goal [condition|clear]` | Set a [goal](goal.md): Claude keeps working across turns until the condition is met or the goal [clears for another reason](goal.md#how-evaluation-works). 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. Attach only the `-diagnostics.json` file when reporting a memory issue; the `.heapsnapshot` contains your full conversation and credentials, so don’t share it. [Hidden from the command menu](#how-the-command-menu-matches-what-you-type); type it in full. See [what to do with the output](troubleshooting.md#high-cpu-or-memory-usage) |
| `/help` | Show help and available commands |
| `/hooks` | View [hook](../07-Hooks/hooks.md) configurations for tool events |
| `/ide` | Manage IDE integrations and show status |
| `/import [codex|gemini|cursor] [--dry-run] [--yes]` | Bring configuration from OpenAI Codex, Google Gemini CLI, or Cursor on your machine into Claude Code, including instruction files, MCP servers, commands, subagents, and skills. In [non-interactive mode](headless.md) with `-p`, `/import` lists what it found and gives you the command that confirms the import. Add `--dry-run` to preview without writing anything, or `--yes` to skip the interactive picker. Not available on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or Claude Platform on AWS, or through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md#availability-and-limitations). Also unavailable when you turn off [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching). Requires Claude Code v2.1.213 or later. Importing from Cursor requires v2.1.265 or later |
| `/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. If `/init` finds OpenAI Codex or Google Gemini CLI configuration, it offers to carry it over with `/import` |
| `/insights` | Generate an HTML report analyzing your recent sessions on this machine: which projects you work in, how you use Claude Code, where things go wrong, and features to try. Not available in [cloud sessions](claude-code-on-the-web.md). See [Analyze your usage patterns](../17-Billing-Plans/costs.md#analyze-your-usage-patterns) for the report location, retention, and cost |
| `/install-github-app` | Install the Claude GitHub App for a repository, with an optional step to set up [GitHub Actions](github-actions.md) workflows and secrets. Walks you through selecting a repo and configuring the integration. Works only with github.com repositories. When your repository’s git remote is on gitlab.com or bitbucket.org, the command prints a notice and exits instead of starting setup. To run Claude Code from GitLab pipelines, see [GitLab CI/CD](gitlab-ci-cd.md) |
| `/install-slack-app` | Install the Claude Slack app. Opens a browser to complete the OAuth flow |
| `/keybindings` | Open your [keyboard shortcuts](keybindings.md) file |
| `/list-agents` | List the subagents, [agent team](../09-Agents-Patterns/agent-teams.md) teammates, and other Claude Code sessions Claude can message, with the name to use for each. See [cross-session messaging](cross-session-messaging.md). Also available as `/peers`. Requires Claude Code v2.1.224 or later; earlier versions report `Unknown command: /list-agents`. Teammate rows and the first line showing this session’s own name require v2.1.239 or later. Available only in sessions where [cross-session messaging is enabled](cross-session-messaging.md#availability) |
| `/login` | Sign in to your Anthropic account |
| `/logout` | Sign out from your Anthropic account |
| `/loop [interval] [prompt]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Run a prompt repeatedly while the session stays open. Omit the interval and Claude [self-paces between iterations](scheduled-tasks.md#let-claude-choose-the-interval). Omit the prompt and Claude runs the [built-in maintenance prompt](scheduled-tasks.md#run-the-built-in-maintenance-prompt) or your [`loop.md`](scheduled-tasks.md#customize-the-default-prompt-with-loop-md). Example: `/loop 5m check if the deploy finished`. See [Run prompts on a schedule](scheduled-tasks.md). Alias: `/proactive` |
| `/mcp [reconnect <server>|enable|disable [<server>|all]]` | Manage MCP server connections and OAuth authentication. Run with no argument to open the interactive list, pass `reconnect <server>` to reconnect one disconnected server, or pass `enable`/`disable` with a server name or `all` to change connection state without opening the dialog. Also available in non-interactive mode (`-p`), where running it with no argument prints a text summary of server status instead of opening the list; requires Claude Code v2.1.205 or later |
| `/memory` | Edit `CLAUDE.md` files, enable or disable [auto memory](memory.md#auto-memory), and view auto memory entries |
| `/mobile` | Show QR code to download the Claude mobile app. Aliases: `/ios`, `/android` |
| `/model [model]` | Switch the AI model and save it as your default for new sessions. For models that support it, use left/right arrows to [adjust effort level](model-config.md#adjust-effort-level). With no argument, opens a picker; press `s` on a row to switch for the current session only. See [when Claude Code asks you to confirm the switch](prompt-caching.md#switching-models). Once you confirm the switch, if Claude Code asks, Claude Code applies the change without waiting for the current response to finish. Before v2.1.242, Claude Code decided from a feature flag it fetched from Anthropic whether to run the command mid-turn or queue it until the turn finished, and always queued it in a session that doesn’t [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), such as on a [third-party provider](third-party-integrations.md). Also available in non-interactive mode (`-p`) with a model argument instead of the picker, where it applies to the current session only and isn’t saved as your default; requires Claude Code v2.1.205 or later |
| `/output-style [style]` | List [output styles](output-styles.md) or switch to one, for example `/output-style concise`. See [Change your output style](output-styles.md#change-your-output-style). Requires Claude Code v2.1.269 or later |
| `/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](auto-mode-config.md#review-denials). You can also view and edit [auto mode classifier rules](auto-mode-config.md#edit-rules-from-permissions) from the dialog’s **Auto mode** tab. When you run it while Claude is responding, Claude Code opens the dialog immediately and applies your changes starting with Claude’s next tool call in the same turn. Before v2.1.234, Claude Code queued the command until the turn finished. 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 [subcommand]` | Manage Claude Code [plugins](../08-Plugins-Skills/plugins.md). Run with no argument to open the plugin menu, or pass a subcommand such as `list`, `install`, `enable`, or `disable` to act directly. Claude Code can activate a plugin during the install; the [install summary](../08-Plugins-Skills/discover-plugins.md#install-a-plugin) tells you whether it did or whether to run `/reload-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 |
| `/rate-limit-options` | Show ways to keep working when a claude.ai usage limit blocks a request: wait and [continue automatically when the limit resets](interactive-mode.md#wait-for-a-usage-limit-to-reset), add [usage credits](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription), or upgrade your plan. Claude Code can also open this menu on its own when you hit a limit at your own terminal. See [Turn automatic continue off](interactive-mode.md#turn-automatic-continue-off). Requires a claude.ai subscription. The wait-and-continue rows require Claude Code v2.1.234 or later |
| `/recap` | Generate a one-line summary of the current session on demand. See [Session recap](interactive-mode.md#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. The notes appear in your transcript without entering the conversation Claude sees |
| `/reload-plugins [--force]` | Reload all active [plugins](../08-Plugins-Skills/plugins.md) to apply pending changes without restarting. Reports counts for each reloaded component and flags any load errors. When the reload would change which MCP tools are loaded and invalidate the prompt cache, the command warns and skips unless you pass `--force`. Also available in non-interactive mode (`-p`), the Agent SDK, and the desktop app, where it runs only on input typed directly into the session and doesn’t apply plugin MCP server changes; requires Claude Code v2.1.260 or later. See [Apply plugin changes without restarting](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) |
| `/reload-skills` | Re-scan [skill](../08-Plugins-Skills/skills.md) and command directories so skills added or changed on disk during the session become available without restarting. Reports how many skills are available and how many were added or removed |
| `/remote-control` | Make this session available for [Remote Control](remote-control.md) from claude.ai. Running it while signed out prints that Remote Control requires a claude.ai subscription and tells you how to sign in; before v2.1.206 it reported `Unknown command: /remote-control`. Alias: `/rc` |
| `/remote-env` | Choose the default [cloud environment](cloud-environments.md#select-an-environment-from-the-cli) for cloud sessions you start from the CLI |
| `/rename [name]` | Rename the current session and show the name on the prompt bar. Without a name, auto-generates one from conversation history. Also available in non-interactive mode (`-p`); requires Claude Code v2.1.205 or later. From every rename surface, including claude.ai and the desktop app, Claude Code replaces control and invisible characters in the new name with spaces and caps the name at 200 characters. If the name is empty once invisible characters are removed, Claude Code rejects it and shows `That name is empty once invisible characters are removed. Usage: /rename <name>`. The character replacement and length cap require Claude Code v2.1.221 or later. If another live session on this machine already uses a name you pass, Claude Code applies [a variant of it](sessions.md#name-your-sessions) instead |
| `/resume [session]` | Resume a conversation by ID or name, or open the session picker. [Background sessions](../09-Agents-Patterns/agent-view.md) appear in the picker marked with `bg`; one that is still running can’t be resumed here, so attach to it from `claude agents` or stop it there first. Alias: `/continue` |
| `/review [low|medium|high|xhigh|max|ultra] [--fix] [--comment] [pr#|branch|path]` | Alias of [`/code-review`](code-review.md#review-a-diff-locally): reviews the current diff, or a PR number, branch, or path you pass, such as `/review 1234`, and takes the same effort levels and flags. With no level given, the review reuses the last `low` through `max` level you typed; see [Review a diff locally](code-review.md#review-a-diff-locally) for the exact rules. For a deep cloud review, use [`/code-review ultra`](ultrareview.md). Before v2.1.223, `/review` was a separate command that ran a single-pass, read-only review of a GitHub pull request by number, listing open PRs to pick from when run with no argument; from v2.1.186 through v2.1.201, it ran the same multi-agent engine as `/code-review medium` |
| `/rewind` | Rewind the conversation and/or code to a previous point, or summarize from a selected message. See [checkpointing](checkpointing.md). Aliases: `/checkpoint`, `/undo` |
| `/run` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Launch and drive your project’s app to see a change working, not only passing tests. See [Run and verify your app](../08-Plugins-Skills/skills.md#run-and-verify-your-app) |
| `/run-skill-generator` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Teach `/run` and `/verify` how to build, launch, and drive your project’s app from a clean environment by writing a per-project [skill](../08-Plugins-Skills/skills.md#run-and-verify-your-app) |
| `/sandbox` | Toggle [sandbox mode](sandboxing.md). Available on supported platforms only |
| `/schedule [description]` | Create, update, list, or run [routines](web-scheduled-tasks.md), which execute in the cloud. Claude walks you through the setup conversationally. You can also ask about a [routine’s recent runs](web-scheduled-tasks.md#manage-routines-from-the-cli). Alias: `/routines` |
| `/scroll-speed` | Adjust mouse wheel [scroll speed](fullscreen.md#mouse-wheel-scrolling) interactively, with a ruler you can scroll while the dialog is open to preview the change. Available in [fullscreen rendering](fullscreen.md) only and not in the JetBrains IDE terminal |
| `/security-review` | Analyze the changes on your current branch for security vulnerabilities. Reviews the diff between your branch and origin’s default branch, identifying risks like injection, auth issues, and data exposure. Needs an `origin` remote; if the review fails with an `ambiguous argument` error, see the [error reference](errors.md#security-review-fails-without-origin-head) |
| `/setup-bedrock` | Configure [Amazon Bedrock](amazon-bedrock.md) authentication, region, and model pins through an interactive wizard. [Hidden from the command menu](#how-the-command-menu-matches-what-you-type) until `CLAUDE_CODE_USE_BEDROCK=1` is set; type it in full. First-time Amazon Bedrock users can also access this wizard from the login screen |
| `/setup-vertex` | Configure [Google Cloud’s Agent Platform](google-vertex-ai.md) authentication, project, region, and model pins through an interactive wizard. [Hidden from the command menu](#how-the-command-menu-matches-what-you-type) until `CLAUDE_CODE_USE_VERTEX=1` is set; type it in full. First-time Google Cloud’s Agent Platform users can also access this wizard from the login screen |
| `/simplify [target]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Review the changed code for cleanup opportunities and apply the fixes. Four review [agents](../09-Agents-Patterns/sub-agents.md) run in parallel, covering reuse of existing helpers, simplification, efficiency, and whether the change is at the right level of abstraction. The review doesn’t look for correctness bugs. Use `/code-review` to find bugs. Pass a path or PR reference to review a specific target |
| `/skill-doctor` | Show what each of your [skills](../08-Plugins-Skills/skills.md) costs in context and how often it gets used, so you can [find skills to turn off](../08-Plugins-Skills/skills.md#find-unused-skills). Requires Claude Code v2.1.252 or later and [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) |
| `/skills` | List available [skills](../08-Plugins-Skills/skills.md). Type to filter the list by name, description, or source. Press `t` to sort by token count, `Space` or `Enter` to [cycle a skill’s visibility to Claude and the `/` menu](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings), and `Esc` to save and close. You can’t cycle plugin skills, skills whose frontmatter sets `disable-model-invocation: true`, or skills with a `skillOverrides` entry in managed settings or the `--settings` flag |
| `/slides [brief]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Make a new presentation as a Claude Slides [artifact](artifacts.md#make-a-slide-deck) filled from your brief, for example `/slides a quarterly review of the platform team`. Requires Claude Code v2.1.265 or later, a session where [artifacts are available](artifacts.md#availability), and an account where the [Slides template is available](artifacts.md#start-from-a-slides-design-or-docs-template); otherwise the command doesn’t appear. Available on the Anthropic API. On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Claude Platform on AWS, artifacts aren’t available, so the command is unavailable there |
| `/stats` | Alias for `/usage`. Opens on the Stats tab |
| `/status` | Open the Settings interface on the Status tab, showing version, model, account, and connectivity. A `Session kind` row reads `background job · attached` or `background job · unattended` in a [background session](../09-Agents-Patterns/agent-view.md), depending on whether a terminal is attached, and `interactive` in any other session. Before v2.1.221, `/status` didn’t show this row. Works while Claude is responding |
| `/statusline` | Configure Claude Code’s [status line](statusline.md). 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](../09-Agents-Patterns/agent-view.md). Only available while attached to a background session; the transcript and any worktree are kept. To detach without stopping, use `/exit` or press `←` |
| `/subtask <task>` | Spawn a [forked subagent](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation): a background subagent that inherits the full conversation and works on the task while you keep working. Its result returns to this conversation when it finishes. To copy the conversation into a separate background session instead, use `/fork`. Requires Claude Code v2.1.212 or later; on v2.1.161 through v2.1.211 this command is `/fork`. When [agent view is turned off](../09-Agents-Patterns/agent-view.md#turn-off-agent-view), `/subtask` isn’t available and `/fork` keeps the forked-subagent behavior |
| `/tasks` | View and manage background work in the current session, including subagents that have finished. 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 [cloud session](claude-code-on-the-web.md#from-cloud-to-terminal) into this terminal. Opens a picker, then fetches the branch and conversation. Also available as `/tp`. Requires a claude.ai subscription |
| `/terminal-setup` | [Install a Shift+Enter keybinding for newlines](terminal-config.md#enter-multiline-prompts) in VS Code, Cursor, Devin Desktop, Alacritty, or Zed. In Apple Terminal, [enable Option+Enter for newlines and turn off the audible bell](terminal-config.md#enable-option-key-shortcuts-on-macos) instead. In iTerm2, [turn on clipboard access so that `/copy` works](terminal-config.md#enable-option-key-shortcuts-on-macos) |
| `/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](terminal-config.md#create-a-custom-theme) 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](fullscreen.md). With no argument, prints the active renderer |
| `/ultraplan <prompt>` | Removed. Use [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) instead. Previously sent a planning task to a [cloud session](claude-code-on-the-web.md) for review in your browser |
| `/ultrareview [PR or branch]` | Run a deep, multi-agent code review in a cloud sandbox with [ultrareview](ultrareview.md). Pass a PR reference to review that pull request, or a base branch or commit to change the comparison base. The preferred invocation is `/code-review ultra`, and `/ultrareview` is an alias. Includes 3 free runs on Pro and Max, then requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
| `/update-config [request]` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Describe a settings change, such as allowing a command, setting an environment variable, or adding a [hook](../07-Hooks/hooks.md), and Claude edits the matching [`settings.json`](settings.md) file. For options such as theme and model, use `/config` instead |
| `/upgrade` | Open the upgrade page in your browser to switch to a higher plan tier. When the browser fails to open, the command shows a sign-in prompt without printing the URL |
| `/usage` | Show session cost, plan usage limits, and activity stats. On a Pro, Max, Team, or Enterprise plan, includes a [breakdown of what counts against your plan limits](../17-Billing-Plans/costs.md#plan-usage-breakdown). `/cost` and `/stats` are aliases |
| `/usage-credits` | Configure usage credits, or request them from your admin, when you hit a limit. Opens your [usage-credits billing settings](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription) in the browser, except that Team and Enterprise members without billing access instead send a usage-credits request to their admin from the CLI, after confirming in a dialog that the request notifies their admins. When no browser can open the billing page, for example over SSH, the command prints the URL to visit instead; this requires Claude Code v2.1.205 or later, and earlier versions showed nothing in that case. Previously `/extra-usage` |
| `/verify` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Confirm a code change does what it should by building your project’s app, running it, and observing the result, rather than relying on tests or type checks. See [Run and verify your app](../08-Plugins-Skills/skills.md#run-and-verify-your-app) |
| `/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](voice-dictation.md), or enable it in a specific mode. Requires a Claude.ai account |
| `/web-setup` | Connect your GitHub account for [cloud sessions](web-quickstart.md#connect-from-your-terminal) using your local `gh` CLI credentials |
| `/workflow-authoring` | **[Skill](../08-Plugins-Skills/skills.md#bundled-skills).** Load the reference for writing [dynamic workflow](workflows.md) scripts: the script API, resume behavior, quality patterns, and worked examples. Claude normally loads it on its own before writing a script; run it yourself before [editing a saved script by hand](workflows.md#edit-a-saved-script). Available when dynamic workflows are enabled, and requires Claude Code v2.1.248 or later |
| `/workflows` | Open the [workflow](workflows.md#watch-the-run) progress view to watch, pause, resume, or save running and completed workflows |
[](#how-the-command-menu-matches-what-you-type)
How the command menu matches what you type
Claude Code filters the `/` menu as you type. Each bullet below covers one thing you might notice while filtering:
- **Highlighting**: Claude Code highlights the top suggestion only when the letters after the `/` match a command’s name or alias, from the start of the name or from a word within it, ignoring the `:`, `_`, and `-` separators. Typing `/adddir` highlights `/add-dir`, and typing `/new` highlights `/clear` through its alias. Press `Enter` to run the highlighted suggestion. These highlighting rules require Claude Code v2.1.236 or later.
- **After a typo**: Claude Code highlights nothing. The close matches stay listed, and you can pick one with `Tab` or the arrow keys, but `Enter` submits your text as typed and reports [Unknown command](errors.md#unknown-command).
- **Commands that aren’t available to you**: Claude Code leaves them out of the menu. When nothing matches, Claude Code shows `No commands match "/name"`. Most unavailable commands return [Unknown command](errors.md#unknown-command) when you submit them; a few, such as [`/schedule` on a Console API key](web-scheduled-tasks.md#schedule-returns-unknown-command), answer with their own availability message instead. Some commands also answer with a message of their own when your organization’s policy disables them.
- **Hidden commands**: Claude Code keeps a few available commands, such as `/heapdump`, out of the menu by design. A partial name never brings a hidden command into the menu: if the partial matches nothing visible, Claude Code shows the same no-match message. Claude Code lists the command only once you’ve typed its full name, and submitting the full name runs it.
[](#mcp-prompts)
MCP prompts
MCP servers can expose prompts that appear as commands. See [MCP prompts](../06-MCP-Tools/General/mcp.md#use-mcp-prompts-as-commands) for details.
[](#see-also)
See also
- [Skills](../08-Plugins-Skills/skills.md): create your own commands
- [Interactive mode](interactive-mode.md): keyboard shortcuts, Vim mode, and command history
- [CLI reference](cli-reference.md): launch-time flags
---
## Common workflows - Claude Code Docs
Source: https://code.claude.com/docs/en/common-workflows
Path: 02-Claude-Code-CLI/common-workflows.md
## On this page
- [Prompt recipes](#prompt-recipes)
- [Understand new codebases](#understand-new-codebases)
- [Get a quick codebase overview](#get-a-quick-codebase-overview)
- [Find relevant code](#find-relevant-code)
- [Fix bugs efficiently](#fix-bugs-efficiently)
- [Refactor code](#refactor-code)
- [Work with tests](#work-with-tests)
- [Create pull requests](#create-pull-requests)
- [Handle documentation](#handle-documentation)
- [Work in notes and non-code folders](#work-in-notes-and-non-code-folders)
- [Work with images](#work-with-images)
- [Reference files and directories](#reference-files-and-directories)
- [Run Claude on a schedule](#run-claude-on-a-schedule)
- [Ask Claude about its capabilities](#ask-claude-about-its-capabilities)
- [Example questions](#example-questions)
- [Resume previous conversations](#resume-previous-conversations)
- [Run parallel sessions with worktrees](#run-parallel-sessions-with-worktrees)
- [Plan before editing](#plan-before-editing)
- [Delegate research to subagents](#delegate-research-to-subagents)
- [Pipe Claude into scripts](#pipe-claude-into-scripts)
- [Next steps](#next-steps)
Use Claude Code
# Common workflows
Copy pageCopy page
Step-by-step guides for exploring codebases, fixing bugs, refactoring, testing, and other everyday tasks with Claude Code.
Copy pageCopy page
This page collects short recipes for everyday development. For higher-level guidance on prompting and context management, see [Best practices](best-practices.md). This page covers:
- [Prompt recipes](#prompt-recipes) for exploring code, fixing bugs, refactoring, testing, PRs, and documentation
- [Resume previous conversations](#resume-previous-conversations) so a task can span multiple sittings
- [Run parallel sessions with worktrees](#run-parallel-sessions-with-worktrees) so concurrent edits don’t collide
- [Plan before editing](#plan-before-editing) to review changes before they touch disk
- [Delegate research to subagents](#delegate-research-to-subagents) to keep your main context clean
- [Pipe Claude into scripts](#pipe-claude-into-scripts) for CI and batch processing
[](#prompt-recipes)
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)
Understand new codebases
For configuring Claude Code in a monorepo or large codebase, see [Monorepos and large repos](large-codebases.md).
[](#get-a-quick-codebase-overview)
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
```python
cd /path/to/project
```
Replace `/path/to/project` with the path to your project.
2
Start Claude Code
```python
claude
```
3
Ask for a high-level overview
```python
give me an overview of this codebase
```
4
Dive deeper into specific components
```python
explain the main architecture patterns used here
```
```python
what are the key data models?
```
```python
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)
Find relevant code
Suppose you need to locate code related to a specific feature or functionality.
1
Ask Claude to find relevant files
```python
find the files that handle user authentication
```
2
Get context on how components interact
```python
how do these authentication files work together?
```
3
Understand the execution flow
```python
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](../08-Plugins-Skills/plugins-code-intelligence.md) for your language to give Claude precise “go to definition” and “find references” navigation
------------------------------------------------------------------------
[](#fix-bugs-efficiently)
Fix bugs efficiently
Suppose you’ve encountered an error message and need to find and fix its source.
1
Share the error with Claude
```python
I'm seeing an error when I run npm test
```
2
Ask for fix recommendations
```python
suggest a few ways to fix the @ts-ignore in user.ts
```
3
Apply the fix
```python
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)
Refactor code
Suppose you need to update old code to use modern patterns and practices. For porting an entire codebase to a new language, see [how Anthropic runs large-scale code migrations with Claude Code](https://claude.com/blog/ai-code-migration) on the blog.
1
Identify legacy code for refactoring
```python
find deprecated API usage in our codebase
```
2
Get refactoring recommendations
```python
suggest how to refactor utils.js to use modern JavaScript features
```
3
Apply the changes safely
```python
refactor utils.js to use ES2024 features while maintaining the same behavior
```
4
Verify the refactoring
```python
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)
Work with tests
Suppose you need to add tests for uncovered code.
1
Identify untested code
```python
find functions in NotificationsService.swift that are not covered by tests
```
2
Generate test scaffolding
```python
add tests for the notification service
```
3
Add meaningful test cases
```python
add test cases for edge conditions in the notification service
```
4
Run and verify tests
```python
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)
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
```python
summarize the changes I've made to the authentication module
```
2
Generate a pull request
```python
create a pr
```
3
Review and refine
```python
enhance the PR description with more context about the security improvements
```
To find the session later, run `claude --from-pr 1234` with your own PR number, which opens the session picker filtered to sessions linked to that PR, or paste the PR URL into the [`/resume` picker](sessions.md#use-the-session-picker) search. Claude Code links the session to the PR when Claude creates it with `gh pr create` or `glab mr create`, and when Claude [works on an existing PR](../09-Agents-Patterns/agent-view.md#pull-request-status).
Review Claude’s generated PR before submitting and ask Claude to highlight potential risks or considerations.
[](#handle-documentation)
Handle documentation
Suppose you need to add or update documentation for your code.
1
Identify undocumented code
```python
find functions without proper JSDoc comments in the auth module
```
2
Generate documentation
```python
add JSDoc comments to the undocumented functions in auth.js
```
3
Review and enhance
```python
improve the generated documentation with more context and examples
```
4
Verify documentation
```python
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)
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)
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:
1. Drag and drop an image into the Claude Code window
2. Copy an image and paste it into the CLI with `Ctrl+V`, or with [`Alt+V` on Windows and WSL](interactive-mode.md#general-controls)
3. Provide an image path to Claude, for example “Analyze this image: /path/to/your/image.png”
2
Ask Claude to analyze the image
```python
What does this image show?
```
```python
Describe the UI elements in this screenshot
```
```python
Are there any problematic elements in this diagram?
```
3
Use images for context
```python
Here's a screenshot of the error. What's causing it?
```
```python
This is our current database schema. How should we modify it for the new feature?
```
4
Get code suggestions from visual content
```python
Generate CSS to match this design mockup
```
```python
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)
Reference files and directories
Use @ to quickly include files or directories without waiting for Claude to read them.
1
Reference a single file
```python
Explain the logic in @src/utils/auth.js
```
This includes the full content of the file in the conversation.
2
Reference a directory
```python
What's the structure of @src/components?
```
3
Reference MCP resources
```python
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](../06-MCP-Tools/General/mcp.md#use-mcp-resources) for details.
Tips:
- File paths can be relative or absolute
- Type `@` to open a path suggestion menu, then press Enter or Tab to accept the highlighted path and Enter again to send the message
- @ 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)
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](web-scheduled-tasks.md) | Cloud, Anthropic-managed by default | 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](https://claude.ai/code/routines). |
| [Desktop scheduled tasks](../16-Mobile-Desktop/desktop-scheduled-tasks.md) | Your machine, via the desktop app | Tasks that need direct access to local files, tools, or uncommitted changes. |
| [GitHub Actions](github-actions.md) | Your CI pipeline | Tasks tied to repo events like opened PRs, or cron schedules that should live alongside your workflow config. |
| [`/loop`](scheduled-tasks.md) | The current CLI session | Quick polling while a session is open. `--resume` and `--continue` restore unexpired fixed-interval loops. |
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)
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)
Example questions
```python
can Claude Code create pull requests?
```
```python
how does Claude Code handle permissions?
```
```python
what skills are available?
```
```python
how do I use MCP with Claude Code?
```
```python
how do I configure Claude Code for Amazon Bedrock?
```
```python
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)
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.
```python
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](sessions.md) for naming, branching, and the full picker reference.
[](#run-parallel-sessions-with-worktrees)
Run parallel sessions with worktrees
Work on a feature in one terminal while Claude fixes a bug in another, without the edits colliding. Each [git worktree](https://git-scm.com/docs/git-worktree) is a separate checkout on its own branch, created from an existing commit, so the repository needs at least one commit first.
```python
claude --worktree feature-auth
```
Run the same command with a different name in a second terminal to start an isolated parallel session. In a repository with no commits, the command fails with `Failed to resolve base branch "HEAD": git rev-parse failed`. See [Worktrees](worktrees.md) for cleanup, `.worktreeinclude`, and non-git VCS support. To monitor parallel sessions from one screen instead of separate terminals, see [background agents](../09-Agents-Patterns/agent-view.md).
[](#plan-before-editing)
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. The status bar shows `⏸ plan mode on` while plan mode is active.
```python
claude --permission-mode plan
```
You can also press `Shift+Tab` mid-session until the status bar shows `⏸ plan mode on`. See [Plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) for the approval flow and editing the plan in your text editor.
[](#delegate-research-to-subagents)
Delegate research to subagents
Exploring a large codebase fills your context with file reads. Delegate the exploration so only the findings come back.
```python
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](../09-Agents-Patterns/sub-agents.md) for defining custom agents with their own tools and prompts.
[](#pipe-claude-into-scripts)
Pipe Claude into scripts
Run Claude non-interactively for CI, pre-commit hooks, or batch processing. Stdin and stdout work like any Unix tool.
```python
git log --oneline -20 | claude -p "summarize these recent commits"
```
See [Non-interactive mode](headless.md) for output formats, permission flags, and fan-out patterns.
[](#next-steps)
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
---
## Let Claude use your computer from the CLI - Claude Code Docs
Source: https://code.claude.com/docs/en/computer-use
Path: 02-Claude-Code-CLI/computer-use.md
## On this page
- [What you can do with computer use](#what-you-can-do-with-computer-use)
- [When computer use applies](#when-computer-use-applies)
- [Enable computer use](#enable-computer-use)
- [Approve apps per session](#approve-apps-per-session)
- [How Claude works on your screen](#how-claude-works-on-your-screen)
- [One session at a time](#one-session-at-a-time)
- [Apps are hidden while Claude works](#apps-are-hidden-while-claude-works)
- [Screenshots are downscaled automatically](#screenshots-are-downscaled-automatically)
- [Stop at any time](#stop-at-any-time)
- [Safety and the trust boundary](#safety-and-the-trust-boundary)
- [Example workflows](#example-workflows)
- [Validate a native build](#validate-a-native-build)
- [Reproduce a layout bug](#reproduce-a-layout-bug)
- [Test a simulator flow](#test-a-simulator-flow)
- [Differences from the Desktop app](#differences-from-the-desktop-app)
- [Troubleshooting](#troubleshooting)
- [”Computer use is in use by another Claude session”](#%E2%80%9Dcomputer-use-is-in-use-by-another-claude-session%E2%80%9D)
- [macOS permissions prompt keeps reappearing](#macos-permissions-prompt-keeps-reappearing)
- [computer-use doesn’t appear in /mcp](#computer-use-doesn%E2%80%99t-appear-in-%2Fmcp)
- [See also](#see-also)
Platforms and integrations
# Let Claude use your computer from the CLI
Copy pageCopy page
Enable computer use in the Claude Code CLI so Claude can open apps, click, type, and see your screen on macOS. Test native apps, debug visual issues, and automate GUI-only tools without leaving your terminal.
Copy pageCopy page
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 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](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer).
[](#what-you-can-do-with-computer-use)
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)
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](../06-MCP-Tools/General/mcp.md) 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](../03-IDE-Integrations/chrome.md) 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 such as the iOS Simulator, and tools without an API.
[](#enable-computer-use)
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:
```python
/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:
```python
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)
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. Approve Finder to let Claude click the desktop, the Dock, or a Finder window. 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](../16-Mobile-Desktop/desktop.md#app-permissions) for the complete tier breakdown.
[](#how-claude-works-on-your-screen)
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)
One session at a time
Only one session at a time can use your computer. A session takes a lock at its first computer use action and releases it when the session exits, not when the task finishes. A second session’s computer use fails with an error naming the session that holds the lock. Exit that session first.
[](#apps-are-hidden-while-claude-works)
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)
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)
Stop at any time
The first time Claude uses your computer in each turn, 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 stops, unhides your apps, and returns control to you. The session keeps the [computer use lock](#one-session-at-a-time) until it exits. A second notification appears when Claude is done.
[](#safety-and-the-trust-boundary)
Safety and the trust boundary
Unlike the [sandboxed Bash tool](sandboxing.md), 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](../15-Claude-AI-Features/let-claude-use-your-computer-in-cowork.md) 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)
Example workflows
These examples show common ways to combine computer use with coding tasks.
[](#validate-a-native-build)
Validate a native build
After making changes to a macOS or iOS app, have Claude compile and verify in one pass:
```python
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)
Reproduce a layout bug
When a visual bug only appears at certain window sizes, let Claude find it:
```python
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)
Test a simulator flow
Drive the iOS Simulator without writing XCTest:
```python
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. This flow applies to the CLI; in the Desktop app, the same request opens the [iOS Simulator pane](../16-Mobile-Desktop/desktop-ios-simulator.md) instead of screen control.
[](#differences-from-the-desktop-app)
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)
Troubleshooting
[](#”computer-use-is-in-use-by-another-claude-session”)
”Computer use is in use by another Claude session”
Another Claude Code session holds the lock, which it keeps until it exits. Exit that session. 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 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)
`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](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer) instead.
- 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’s Agent Platform, 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)
See also
- [Computer use in Desktop](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer): the same capability with a graphical settings page
- [Claude in Chrome](../03-IDE-Integrations/chrome.md): browser automation for web-based tasks
- [MCP](../06-MCP-Tools/General/mcp.md): connect Claude to structured tools and APIs
- [Sandboxing](sandboxing.md): how Claude’s Bash tool isolates filesystem and network access
- [Computer use safety guide](../15-Claude-AI-Features/let-claude-use-your-computer-in-cowork.md): best practices for safe computer use
---
## Explore the context window - Claude Code Docs
Source: https://code.claude.com/docs/en/context-window
Path: 02-Claude-Code-CLI/context-window.md
# Explore the context window
Copy pageCopy page
An interactive simulation of how Claude Code’s context window fills during a session. See what loads automatically, what each file read costs, and when rules and hooks fire.
Copy pageCopy page
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 plays a full session from startup to compaction: what loads before you type, what each file read, rule, and hook adds as Claude works, and how a subagent keeps large reads out of your context. See [the written breakdown](#what-the-timeline-shows) for the same content as a list.
[](#what-the-timeline-shows)
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. [AGENTS.md files](memory.md#agents-md) can load too, on their own or alongside CLAUDE.md. Your own setup may add more here, like an [output style](output-styles.md) or text from [`--append-system-prompt`](cli-reference.md).
- **As Claude works**: each file read adds to context, [path-scoped rules](memory.md#path-specific-rules) load automatically alongside matching files, and a [PostToolUse hook](../07-Hooks/hooks-guide.md) fires after each edit.
- **The follow-up prompt**: a [subagent](../09-Agents-Patterns/sub-agents.md) 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 of the walkthrough**: you run `/compact`, which replaces the conversation with a structured summary. Most startup content reloads automatically; the table below shows what happens to each mechanism.
[](#what-survives-compaction)
What survives compaction
When a long session compacts, Claude Code summarizes the conversation history to fit the context window. As of v2.1.198, the summarization request inherits your session’s [extended thinking](model-config.md#extended-thinking) configuration, so it reasons with thinking enabled when your session has it enabled and stays off otherwise. Thinking affects only how the summary is produced; your session settings are unchanged afterward. What happens to each kind of content depends on how it was loaded:
| Mechanism | After compaction |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------|
| System prompt and output style | Both still apply |
| Project-root CLAUDE.md and unscoped rules | Re-injected from disk |
| Auto memory | Re-injected from disk |
| [Git status snapshot](settings-reference.md#includegitinstructions) | Claude Code reads a fresh one from your repository |
| The plan Claude wrote in [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) | Re-injected from disk |
| Rules with `paths:` frontmatter | Claude Code reloads them as Claude reads files they match |
| Nested CLAUDE.md in subdirectories | Claude Code reloads them as Claude reads files in that subdirectory |
| Files Claude read or edited | Claude Code re-reads up to five, most recently modified first |
| Invoked skill bodies | Re-injected, capped at 5,000 tokens per skill and 25,000 tokens total; oldest dropped first |
| [Background commands](interactive-mode.md#background-bash-commands) and background [subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) | Keep running. Claude Code reminds Claude which ones are still running so it doesn’t start a duplicate |
| Context that hooks added earlier | Summarized with the rest of the conversation |
| [SessionStart hooks](../07-Hooks/hooks-guide.md#re-inject-context-after-compaction) that match the `compact` source | Claude Code runs them and adds their output to the compacted context |
Right after compaction, Claude Code re-reads up to five of the files Claude has read or edited in the session, choosing the ones modified most recently. A file over 5,000 tokens comes back as a path reference without its content, shown as `Referenced file` instead of `Read`. 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. 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`.
[](#when-your-context-fills-up)
When your context fills up
Claude Code compacts automatically as you approach the limit, so a full context window doesn’t end your session. The automatic pass works the same way as the `/compact` step in the timeline. See [When context fills up](how-claude-code-works.md#when-context-fills-up) for what it preserves. You can also act before the automatic pass runs:
- **Compact with a focus**: run `/compact` with instructions, like `/compact focus on the auth bug fix`, before starting a long new task. The summary keeps what you choose instead of what the automatic pass guesses is important.
- **Compact part of the conversation**: run `/rewind`, select a message, and choose **Summarize from here** or **Summarize up to here**. See [Rewind and summarize](checkpointing.md#rewind-and-summarize) for what each option keeps and how to guide the summary.
- **Compact earlier**: run [`/autocompact`](commands.md#all-commands) with a token count, like `/autocompact 500k`, to set how full the context window gets before the automatic pass runs. See [Set the auto-compact window](model-config.md#set-the-auto-compact-window) for accepted values and overrides.
- **Clear between tasks**: run `/clear` when switching to unrelated work. Old conversation crowds out the files you need next and costs tokens on every message.
- **Delegate large reads**: send research to a [subagent](../09-Agents-Patterns/sub-agents.md) so the file contents stay in its context window, not yours.
If you need a larger window rather than a smaller conversation, Fable models, Sonnet 5 and later, Opus 4.6 and later, and Sonnet 4.6 support a 1 million token context window. See [Extended context](model-config.md#extended-context) for availability by plan and how to select a `[1m]` model variant. Compaction works the same way at the larger limit. Sonnet 5.5 and Sonnet 5 run with the 1M context window and have no `[1m]` variant to select. See [Sonnet 5.5 and Sonnet 5 context window](model-config.md#sonnet-5-5-and-sonnet-5-context-window) for their auto-compaction thresholds and the LLM gateway exception. The point where automatic compaction runs depends on your model and configuration. See [Default auto-compact thresholds](model-config.md#default-auto-compact-thresholds) for the boundaries per model, and [Correct the window for a gateway or custom model ID](model-config.md#correct-the-window-for-a-gateway-or-custom-model-id) if Claude Code assumes the wrong window for your model ID, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) alias.
[](#check-your-own-session)
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, including which CLAUDE.md and auto memory files loaded. Run `/memory` to open and edit those files.
[](#related-resources)
Related resources
For deeper coverage of the features shown in the timeline, see these pages:
- [Extend Claude Code](features-overview.md): when to use CLAUDE.md vs skills vs rules vs hooks vs MCP
- [Store instructions and memories](memory.md): CLAUDE.md hierarchy and auto memory
- [Subagents](../09-Agents-Patterns/sub-agents.md): delegate research to a separate context window
- [Best practices](best-practices.md): managing context as your primary constraint
- [Prompt caching](prompt-caching.md): which actions invalidate the cached prefix
- [Reduce token usage](../17-Billing-Plans/costs.md#reduce-token-usage): strategies for keeping context usage low
---
## Message your other Claude Code sessions - Claude Code Docs
Source: https://code.claude.com/docs/en/cross-session-messaging
Path: 02-Claude-Code-CLI/cross-session-messaging.md
## On this page
- [When to use cross-session messaging](#when-to-use-cross-session-messaging)
- [Message another session](#message-another-session)
- [Message delivery](#message-delivery)
- [Get a notice when another session goes idle](#get-a-notice-when-another-session-goes-idle)
- [Ask for a notice](#ask-for-a-notice)
- [What each session shows](#what-each-session-shows)
- [Limits](#limits)
- [See which sessions Claude can reach](#see-which-sessions-claude-can-reach)
- [Message sessions on other machines](#message-sessions-on-other-machines)
- [How a session treats an incoming message](#how-a-session-treats-an-incoming-message)
- [What a message looks like](#what-a-message-looks-like)
- [Control inbound messages](#control-inbound-messages)
- [Non-interactive sessions](#non-interactive-sessions)
- [The session’s inbox socket](#the-sessions-inbox-socket)
- [Restrict cross-session messaging](#restrict-cross-session-messaging)
- [Require approval for cross-machine messages](#require-approval-for-cross-machine-messages)
- [Turn off cross-session messaging](#turn-off-cross-session-messaging)
- [Availability](#availability)
- [Limitations](#limitations)
- [Related resources](#related-resources)
Agents and parallel work
# Message your other Claude Code sessions
Copy pageCopy page
Let Claude list and message your other Claude Code sessions on this machine, and reach your sessions on other machines or in the cloud.
Copy pageCopy page
Cross-session messaging requires Claude Code v2.1.224 or later on macOS and Linux, including Linux inside WSL 2. On native Windows, it requires Claude Code v2.1.234 or later. When a session meets the requirements, messaging is on with nothing to enable. See [Availability](#availability) for provider requirements and how to confirm a session has it.
Cross-session messaging lets Claude deliver a message from one of your Claude Code sessions to another. When a change in one session breaks what another is building on, Claude can warn that session before you notice. When one session settles a question another is blocked on, Claude can send the answer across. A message is a piece of text one Claude writes to another, never the sender’s conversation history or files. To move a whole conversation or its context, [resume the session](sessions.md#resume-a-session) instead.
[](#when-to-use-cross-session-messaging)
When to use cross-session messaging
Use messaging when one of your sessions has something another session needs mid-task. Claude can send a message on its own when it sees the need, for example after making a change that affects work another session is doing, or you can ask it to send one. The common cases:
- **Hand over a finding**: when one session discovers a breaking change or makes a decision, Claude summarizes it for the session working on the affected area, instead of you re-explaining it there.
- **Coordinate parallel worktrees**: when sessions work the same repository in separate [worktrees](worktrees.md), Claude can tell the other sessions what landed.
- **Get status from long-running work**: have a migration or test run report back to the session you’re watching, or ask it yourself from there. If that session is on this machine, Claude can also [ask it for one notice when it next goes idle or exits](#get-a-notice-when-another-session-goes-idle).
- **Message across machines**: reach one of your sessions on another machine or in the cloud.
[](#message-another-session)
Message another session
When one of your sessions learns something another session needs, such as a finding, a status, or a decision, Claude passes it along instead of you copy-pasting between terminals. Claude discovers the target with `ListAgents` and sends with `SendMessage`, so you never call either tool yourself. Claude can decide to send a message without being asked, and you can also prompt for one. To prompt one yourself, tell Claude what you want the other session to know or do. This example is a prompt you type, not a message Claude sends:
```python
Ask the session running in my other terminal whether the migration finished
```
Claude writes the actual message itself, so your prompt can leave the content to Claude. This prompt asks for a summary without dictating its wording, and what Claude sends varies:
```python
Explain what we just did to the session working on the payments API
```
To name the target yourself, mention the session in your prompt: type `@` followed by the first letters of the session’s name and pick the session from the typeahead, the same way you [@-mention a subagent](../09-Agents-Patterns/sub-agents.md#invoke-subagents-explicitly). Requires Claude Code v2.1.232 or later. Claude Code inserts the mention, such as `@api-worker`, and tells Claude which session it names, so Claude can message that session without listing your sessions first. This prompt names the target with a mention:
```python
Let @api-worker know the schema migration finished
```
The typeahead lists your other live sessions on this machine. Two cases need more than the first letters of a name:
- **A session beyond this machine**: a cloud or Remote Control session appears in the typeahead only after Claude has listed or messaged your sessions beyond this machine, so ask Claude to list them first.
- **A name with a space or other characters outside letters, digits, hyphens, and underscores**: type it in double quotes, such as `@"release notes"`. When you pick the session from the typeahead, Claude Code inserts the quotes for you.
You can also type the mention without the picker. When more than one live session answers to the mentioned name, Claude asks you which one you mean before sending. For what the message Claude writes looks like when it arrives, including an example of one, see [what a message looks like](#what-a-message-looks-like).
[](#message-delivery)
Message delivery
The receiving Claude reads the message between tool calls during an active turn, so a running tool is never interrupted. When the receiving session is idle, Claude Code starts a new turn with the message. A message from another session arrives as plain text. If it mentions a file or an [MCP resource](../06-MCP-Tools/General/mcp.md#use-mcp-resources) with `@`, Claude sees the mention as written and Claude Code attaches nothing, whether the message starts a new turn or arrives during one. Claude can still open a mentioned path on the receiving machine with its own tools, subject to that session’s permissions. Claude Code refuses a message in the following cases:
- The message is [over the size cap](#limitations). Claude Code refuses it in the sending session, before it leaves.
- A rapid burst to a session on this machine has reached [what that session’s inbox accepts](#limitations). Claude Code refuses further messages to that session.
- The reply target on this machine fails a safety check, such as a symlinked target. [Refusing to send a cross-session message](errors.md#refusing-to-send-a-cross-session-message) lists these checks.
The receiving session checks each arriving message against its own [inbound controls](#control-inbound-messages), and the check ends in one of three outcomes:
- **Delivered**: Claude Code passes the message to the receiving Claude.
- **Held**: Claude Code sets the message aside undelivered. A held message reaches Claude only when you approve it or a later mode or settings change allows it.
- **Refused**: Claude Code drops the message without delivering it.
Once delivered, the message counts toward [usage](../17-Billing-Plans/costs.md) like a prompt you type, and the receiving Claude can reply to the sender the same way, except in the [one-way cross-machine case](#message-sessions-on-other-machines). Permission boundaries stay per-session. Claude is instructed never to ask another session for an action that was denied or blocked in its own session, or that its own permission settings would block, and to route that work back to you instead. On the receiving side, the [receiving session’s own permission prompts and rules still apply](#how-a-session-treats-an-incoming-message) to anything the message asks for.
[](#get-a-notice-when-another-session-goes-idle)
Get a notice when another session goes idle
Claude can ask one of your sessions on this machine to send back one notice when that session next goes idle or exits. Idle here means the session finished a turn with nothing queued. Use it when you’re waiting on a long task in another session and want to hear when it’s done instead of checking. Requires Claude Code v2.1.236 or later in both sessions.
[](#ask-for-a-notice)
Ask for a notice
Tell Claude what you’re waiting on. This prompt asks for a notice from the migration session:
```python
Tell me when the migration session finishes what it's working on
```
Claude subscribes with the `SendMessage` tool’s `notify_when_idle` input, either attached to a message it’s sending anyway or on its own. On its own, Claude Code subscribes without starting a turn or spending tokens in the watched session, and sends the notice right away if that session is already idle. Attached to a message, Claude Code delivers the message first and sends the notice later.
[](#what-each-session-shows)
What each session shows
The watched session shows a line saying another process asked to be told when the session is next idle. The asking session shows the notice as a line naming the watched session. The line can include the time that session’s turn finished and a one-line status from that turn. If the asking session is idle, Claude Code starts a new turn with the notice.
[](#limits)
Limits
If no notice arrives within 12 hours, Claude Code drops the subscription and tells Claude, so it doesn’t keep waiting. Each side’s [inbound controls](#control-inbound-messages) apply to a notice like a message:
- **`refuse` on either side**: nothing arrives. The watched session drops the request without recording or answering it, so the subscription expires unanswered after 12 hours, and an asking session with `refuse` never subscribes.
- **`hold` on either side**: the notice arrives with less. The watched session leaves the one-line status out, and the asking session shows the notice in your transcript without delivering it to Claude.
Only the Claude in your main conversation can subscribe, and only to your sessions on this machine. When Claude asks for a notice from any other target, such as a teammate, a subagent, or a session beyond this machine, Claude Code refuses the whole call, including any message attached to it.
[](#see-which-sessions-claude-can-reach)
See which sessions Claude can reach
Claude finds a message’s target on its own, so you don’t need to run anything before asking it to send. To see for yourself which sessions Claude can reach, run the `/list-agents` command. The first line, when present, is this session’s own name, the one your other sessions use to message it. The rows below it are the sessions Claude can reach:
- **Subagents**: agents running inside the current session.
- **Teammates**: this session’s own [agent team](../09-Agents-Patterns/agent-teams.md) teammates.
- **Your other local sessions**: Claude Code sessions running on the same machine, including [background sessions](../09-Agents-Patterns/agent-view.md). A session appears only when it binds an [inbox socket](#the-sessions-inbox-socket).
- **Your [cloud sessions](claude-code-on-the-web.md)**: shown while this session is connected to [Remote Control](remote-control.md).
- **Your Remote Control sessions on other machines**: shown while this session is connected to [Remote Control](remote-control.md), and labeled `Remote Control`. Claude Code shows `offline` as the status of a session whose Remote Control connection has dropped.
While this session is connected to [Remote Control](remote-control.md), Claude Code withholds some details of your local sessions from the `/list-agents` output, without changing what Claude itself sees when it looks for a session to message:
- **Working directories**: it leaves out each local session’s working directory.
- **Session names**: it leaves out any session name it can’t attribute to a person, so a row left with no name reads `(unnamed session)`.
- **The first line**: it leaves out the line with this session’s own name unless you typed that name at this terminal, with `--name` or with `/rename` and the name, since you launched or last resumed the session.
When the output lists anything, it ends with a note saying details were withheld. Running `/rename` followed by an unused name at a session’s own keyboard gives that session a name that appears in the output. A session answers to the name you set with the [`/rename`](commands.md) command or the [`--name`](cli-reference.md#cli-flags) flag. When you don’t set one, Claude Code names the session itself. For an interactive session, that is the name shown in [listings of running sessions](sessions.md#name-your-sessions). When you rename a session, or start or resume an interactive one, with a name another live session on this machine already uses, Claude Code leaves the name with the session that already has it and [renames yours to a variant](sessions.md#name-your-sessions). Sessions can still share a name, for example when one of them runs an earlier version of Claude Code or the shared name is one Claude Code generated. Unless this session is connected to Remote Control, Claude Code shows each local session’s working directory in the `/list-agents` output, so you can tell same-named sessions apart when they run in different directories. Claude addresses the message in one of two ways, depending on how many live sessions answer to the name:
- **One session answers to the name**: Claude Code delivers the message on the name alone.
- **Several sessions share the name, or Claude Code couldn’t check everywhere your sessions run**: Claude adds a short identifier to each row of its listing and uses the identifier in the address.
[](#message-sessions-on-other-machines)
Message sessions on other machines
How a message travels, and whether it passes through Anthropic servers, depends on where the target session runs:
| Where the other session runs | How the message travels |
|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|
| On this machine | Over a per-session socket on macOS and Linux, or a per-session named pipe on native Windows, never through Anthropic servers |
| On another of your machines | Through Anthropic servers, arriving over that machine’s [Remote Control](remote-control.md) connection |
| In the [cloud](claude-code-on-the-web.md) | Through Anthropic servers, straight to the cloud session |
Starting a conversation with a session on another of your machines requires Claude Code v2.1.225 or later and a target that [appears in the listing](#see-which-sessions-claude-can-reach). You can message a session shown as `offline` in [the listing](#see-which-sessions-claude-can-reach), one whose Remote Control connection has dropped. The send goes through, but the message arrives only after that session’s machine reconnects. A session inside a container and a session on the host can’t reach each other. Two sessions inside the same container can still message each other, including on a [self-hosted runner](../13-Enterprise-Admin/self-hosted-environments.md). A session inside WSL 2 and a native Windows session on the same computer can’t reach each other either. If this session isn’t connected to Remote Control when Claude sends to a session beyond this machine, the message still goes through, but without a [reply address](#what-a-message-looks-like), so the receiving Claude can’t answer it. To require your approval before any message goes beyond this machine, set [`isolatePeerMachines`](#require-approval-for-cross-machine-messages).
[](#how-a-session-treats-an-incoming-message)
How a session treats an incoming message
When session A messages session B, Claude Code tells B’s Claude that the message came from another session, not from you, and limits what the message can do:
- **It can’t approve anything**: a message from another session never counts as your consent, so it can’t answer a pending permission prompt on your behalf.
- **It can’t change configuration**: Claude Code instructs the receiving Claude never to change permission settings, `CLAUDE.md`, or other configuration because another session asked.
- **Commands don’t run**: a command in the message’s text, such as `/compact`, arrives as plain text. Claude Code never executes it.
- **Permission prompts still fire**: if acting on the message requires a permission the receiving session doesn’t have, you see the same prompt you’d see for any other work.
[](#what-a-message-looks-like)
What a message looks like
When a message arrives, Claude Code shows it in the conversation as a dim one-line preview, and the preview line stays in the conversation afterward. The preview carries the sender’s name and the first line of the message, cut with `…` when it’s long, such as `› Message from @api-worker: Schema migration finished (ctrl+o to expand)`. Either of these shows you the full text:
- Press `Ctrl+O` to open the [transcript viewer](interactive-mode.md#transcript-viewer) and read the full text under the sender’s session name.
- In a session started with [`--verbose`](cli-reference.md#cli-flags), Claude Code shows the full text instead of the preview.
The preview shortens only what you see. Whether or not you expand it, Claude reads the full message. Claude receives the message with the sender’s name and a reply address, except for a [one-way cross-machine message](#message-sessions-on-other-machines), which carries no reply address. This example is a message one Claude wrote to another, as its full text reads when you expand it:
```python
Schema migration finished
The new column is tenant_id, and rebasing on main is safe now.
```
[](#control-inbound-messages)
Control inbound messages
Set [`crossSessionInbound`](settings-reference.md#crosssessioninbound) to choose what a session does with messages arriving from your other sessions:
| Value | Behavior |
|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `accept` | Claude Code delivers each message to Claude |
| `hold` | Claude Code shows a notice for each message and doesn’t deliver it. If an `accept` later applies, per the [precedence rules](settings-reference.md#crosssessioninbound), Claude Code releases the held messages |
| `refuse` | Claude Code drops each message without delivering it |
Beyond editing a settings file, you can select the value in the `/config` row **Messages from your other sessions**. Claude Code writes the value you select to your user settings. The row requires Claude Code v2.1.232 or later and doesn’t appear while managed settings or the `--settings` flag sets the key, since a user-settings value wouldn’t apply then. Claude Code rejects the `/config crossSessionInbound=value` shorthand for this key. To see which value applies, follow the `crossSessionInbound` precedence rules in the [settings reference](settings-reference.md#crosssessioninbound). When no value applies, Claude Code decides per message from the two sessions’ permission modes. It groups sessions that [bypass permission prompts](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) into one class, and every other session into the other. Plan mode counts as bypassing in interactive terminal sessions with bypass permissions available, and [auto](permission-modes.md#eliminate-prompts-with-auto-mode), `acceptEdits`, and `dontAsk` count as prompting:
- **The receiving session prompts for permissions**: Claude Code delivers each message. It holds one for your approval only when the sending session identifies itself as bypassing permission prompts.
- **The receiving session bypasses permission prompts**: Claude Code holds each message for your approval. It delivers one only when the sending session identifies itself as also bypassing.
When the default holds a message, Claude Code opens an approval dialog in the receiving session. The dialog shows the sender and a preview:
- **Approve** delivers that one message to Claude.
- **Deny**, or dismissing the dialog, drops it.
- When the dialog stays unanswered past the [`dialogExpiry`](settings-reference.md#dialogexpiry) deadline, Claude Code closes it and drops the message. The deadline defaults to five minutes.
- While no terminal is attached to a [background session](../09-Agents-Patterns/agent-view.md), Claude Code leaves the dialog open past the deadline. After you attach, if the dialog stays unanswered for a full deadline period, Claude Code closes it and drops the message.
- If this session’s permission-mode class changes while messages are held, Claude Code re-applies the inbound rules, delivers the messages they now accept, and shows a notice.
Claude Code holds at most 100 messages, and past that drops the oldest.
[](#non-interactive-sessions)
Non-interactive sessions
Claude Code binds an inbox socket for a [`claude -p`](headless.md) session like an interactive one, so a long-running `-p` worker can receive messages and appears in the listing. When you start a session in [bare mode](headless.md#start-faster-with-bare-mode), Claude Code doesn’t bind the socket, so that session can’t receive messages and doesn’t appear in the agent list. A `-p` session can’t show the approval dialog. When the [inbound default](#control-inbound-messages) holds a message there, Claude Code keeps it for the same [`dialogExpiry`](settings-reference.md#dialogexpiry) deadline the dialog uses, five minutes by default:
- **Before the deadline**: if a mode or settings change allows the message, Claude Code delivers it.
- **Past the deadline**: Claude Code drops the message and reports it as expired to a sender it can reach.
Set `dialogExpiry` to `"never"` to keep default-held messages until the session ends. A message held by an explicit `hold` setting doesn’t expire; Claude Code delivers it only when an `accept` later applies. To let a `-p` worker take messages unattended, start it with `crossSessionInbound` set to `accept` in its `--settings` value. An `accept` in your user settings also works but applies to every session you run.
[](#the-sessions-inbox-socket)
The session’s inbox socket
Read this section when a session you expect isn’t in the agent list, when you want a script or hook to post into a session, or when a sandboxed command can’t reach the socket. Claude Code binds an inbox socket for each session with cross-session messaging enabled, where other sessions on the machine deliver messages. The socket is a Unix domain socket on macOS and Linux, including Linux inside WSL 2, and a named pipe on native Windows. For which session kinds bind one, see [Non-interactive sessions](#non-interactive-sessions). You can find the socket’s path in two places:
- `/status` shows it in the `Peer address` row. The path is prefixed with `uds:`.
- Claude Code exports it to [hooks](../07-Hooks/hooks.md) and Bash commands as the [`CLAUDE_CODE_MESSAGING_SOCKET`](env-vars.md#variables) environment variable:
- In a session that starts with messaging on, Claude Code exports the variable before any hook runs, including `SessionStart`.
On macOS and Linux, Claude Code restricts the socket to your operating-system user. On native Windows, it instead requires each connection to authenticate first with a key that only your operating-system user can read. Either way, on a shared machine another user’s sessions can’t deliver to it. On macOS and Linux, Claude Code also refuses to create the socket in a directory it can’t accept, for example one that another user owns, and uses a private per-user directory, `/tmp/cc-socks-<uid>`, instead. When it can’t accept any directory, the session runs without an inbox: Claude Code shows a notice, `/status` shows `unavailable` and the reason in its `Peer address` row, and the [`--debug`](cli-reference.md#cli-flags) log records the full refusal. Alongside the socket’s path, Claude Code exports a per-session token as [`CLAUDE_CODE_MESSAGING_TOKEN`](env-vars.md#variables). A script posting to its own session’s socket can send `{"type":"auth","token":"<token>"}` as the first line of its connection, where `<token>` is the value of `CLAUDE_CODE_MESSAGING_TOKEN`. Whether Claude Code requires the line depends on the platform:
- **macOS and Linux, including WSL 2**: the line is optional. Claude Code accepts a connection with or without it.
- **Native Windows**: the line is required. Claude Code closes any connection whose first line isn’t a valid auth line and delivers nothing from that connection.
Open the connection only when the message you’re posting is ready. Claude Code closes a connection that hasn’t sent a complete line within 30 seconds, so capture a slow command’s output first and then open the connection to send it. Claude Code runs messages arriving on the socket through the same [inbound controls](#control-inbound-messages) as any other peer message, with one exception and one prerequisite:
- **Own-child messages**: when no `crossSessionInbound` value applies, Claude Code delivers a message it verifies came from the session’s own child processes, such as a hook or Bash command posting back to its own session’s socket.
- On Linux, including inside WSL 2, Claude Code can verify by process evidence even for a child that has already exited. On macOS it can verify that way only while the posting process is still running, and in a container where Claude Code runs as process ID 1 it has no process evidence at all. On native Windows it also has none.
- On macOS after the posting process has exited and in containers where Claude Code runs as process ID 1, that process evidence is missing, and Claude Code instead verifies a child that sent the session’s exported [`CLAUDE_CODE_MESSAGING_TOKEN`](env-vars.md#variables) in the auth line that opened its connection. On native Windows, that token is the only way Claude Code verifies an own-child message.
- When Claude Code can verify neither way, it treats the message like any other that asserts no permission class, so a session that bypasses permission prompts holds it for your approval.
- **Sandboxed sessions**: control whether a Bash command can reach the socket from inside the [sandbox](sandboxing.md) with the sandbox’s Unix-socket settings, [`sandbox.network.allowAllUnixSockets` and `sandbox.network.allowUnixSockets`](settings-reference.md#sandbox-settings).
[](#restrict-cross-session-messaging)
Restrict cross-session messaging
Beyond the per-message defaults, you can narrow messaging in two ways. Require your approval before any message leaves the machine, or turn messaging off for a session or an organization.
[](#require-approval-for-cross-machine-messages)
Require approval for cross-machine messages
Set [`isolatePeerMachines`](settings-reference.md#isolatepeermachines) to `true` to require your explicit approval before any `SendMessage` reaches a session beyond this machine:
```python
{
"isolatePeerMachines": true
}
```
With this set, Claude Code asks for your approval before Claude’s message to a session beyond this machine leaves, even in `bypassPermissions` mode, which skips ordinary permission prompts. A `true` from any settings scope applies, so a checked-in project file can turn the requirement on but not off. Claude Code doesn’t prompt for messages between sessions on the same machine.
[](#turn-off-cross-session-messaging)
Turn off cross-session messaging
Receiving and sending are separate controls, so turn off whichever direction you need, or both. Use `crossSessionInbound` for messages that arrive, and permission rules for what Claude here can send or list:
- **Stop receiving**: set `crossSessionInbound` to `refuse`, and Claude Code drops inbound peer messages without delivering them. From project or local settings, `refuse` applies over every other source, and from your user settings it applies unless managed settings or the `--settings` flag set a value.
- **Stop sending and listing**: add [permission deny rules](permissions.md#tool-specific-permission-rules) naming `SendMessage` and `ListAgents`. Both take the bare tool name with no specifier.
Administrators can turn both sides off for an organization in [managed settings](../13-Enterprise-Admin/managed-settings.md), combining the deny rules with the `refuse`:
```python
{
"permissions": {
"deny": ["SendMessage", "ListAgents"]
},
"crossSessionInbound": "refuse"
}
```
With this in place, Claude Code still binds each session’s inbox socket, but drops every message that arrives on it without delivering anything to Claude. Denying `SendMessage` also removes messaging to subagents and agent-team teammates, since the same tool serves both. A refusing session shows no visible change, in its own `/status` or in the listings of other sessions on the same machine, so to confirm it, check the settings files that apply to that session rather than its status.
[](#availability)
Availability
Cross-session messaging requires Claude Code v2.1.224 or later on macOS, Linux, and WSL 2, and v2.1.234 or later on native Windows. Availability, and which sessions Claude can message, also depend on your operating system, provider, and configuration:
- **Operating system**: available on macOS, Windows, and Linux, including Linux inside WSL 2.
- **Sessions on this machine**: available on every provider, including Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry, and in sessions that run with [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) off. On those providers, and with flag fetching off, same-machine messaging requires Claude Code v2.1.248 or later. Claude Code delivers these messages over a [per-session socket on your machine](#the-sessions-inbox-socket), never through Anthropic servers. To stop a session from receiving them, set [`crossSessionInbound`](#turn-off-cross-session-messaging) to `refuse`.
- **Sessions beyond this machine**: Claude finds your [cloud sessions](claude-code-on-the-web.md) and your sessions on other machines from a session that is connected to Remote Control, which needs a claude.ai sign-in as this session’s active authentication and the other [Remote Control requirements](remote-control.md#requirements). Claude can’t find those sessions with an API key or on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry.
To check a session, type `/list-agents`, also available as `/peers`. The result separates a session that doesn’t have the feature from a session where something narrower blocked a message, such as a missing `SendMessage` tool or a refused send:
- **`/list-agents` isn’t recognized**: the session doesn’t have cross-session messaging. Work through the requirements above, starting with `claude --version` for the version requirement.
- **`/list-agents` works but a send didn’t arrive**: messaging is on, and something narrower applies:
- **Deny rules**: a [permission deny rule](#turn-off-cross-session-messaging) removes the `SendMessage` and `ListAgents` tools.
- **Inbound controls**: the [receiving session’s inbound controls](#control-inbound-messages) can hold or drop what you send it.
- **Cloud session missing**: a cloud session appears only while this session is connected to [Remote Control](remote-control.md).
- **Other-machine session missing**: a session on another of your machines appears only when it runs with [Remote Control](remote-control.md) and this session is connected as well.
- **Other-machine session `offline`**: a message to a session listed as `offline` goes through, but [arrives only after that session’s machine reconnects](#message-sessions-on-other-machines).
- **Older cloud or other-machine session missing**: Claude Code reads those session lists newest first and stops after a bounded number of pages, so Claude can’t message a session that fell past them by name.
In a session with messaging, `/status` also shows a `Peer address` row with the session’s own inbox address, or `unavailable` and the reason when Claude Code [couldn’t set up an inbox](#the-sessions-inbox-socket).
[](#limitations)
Limitations
The limits here are properties of the messaging channel itself and apply wherever the feature runs. For platform and provider gaps, see [Availability](#availability) instead.
- **Plain text only**: Claude sends only plain text across sessions. Structured [agent team](../09-Agents-Patterns/agent-teams.md) protocol messages stay within a team.
- **Same-machine message size is capped**: Claude Code refuses a message to a session on this machine once its serialized form passes about a million characters. The refusal [names the exact sizes](errors.md#message-too-large-for-cross-session-delivery). Nothing reaches the receiving session.
- **Rapid bursts to one session are refused at the sender**: once a rapid burst of messages to a session on this machine reaches what that session’s inbox accepts, Claude Code refuses further sends in the sending session. The [refusal names the burst](errors.md#too-many-messages-to-this-session-just-now) and tells Claude to batch the rest into one message or wait.
- **Message loops are throttled**: in the receiving session, Claude Code rate-limits repeated messages per sender, drops identical repeats arriving within a short window, and queues at most 50 accepted messages for Claude to read. A message loop between two sessions therefore stops on its own.
[](#related-resources)
Related resources
- [Subagents](../09-Agents-Patterns/sub-agents.md#resume-subagents) and [agent teams](../09-Agents-Patterns/agent-teams.md#messages-between-agents): messaging within a single session or team
- [Background agents](../09-Agents-Patterns/agent-view.md): dispatch and monitor the parallel sessions you might message
- [Remote Control](remote-control.md): connect this session to reach your sessions on other machines
- [Channels](channels.md): push external events, such as CI results or chat messages, into a session
- [Settings](settings-reference.md#all-settings): `crossSessionInbound`, `isolatePeerMachines`, and `dialogExpiry`
- [Permission modes](permission-modes.md): the modes behind the inbound default’s two classes
- [Tools reference](tools-reference.md): the `ListAgents` and `SendMessage` rows in the tools table
- [Run agents in parallel](../09-Agents-Patterns/agents.md): compare the ways Claude Code runs multiple agents
---
## Debug your configuration - Claude Code Docs
Source: https://code.claude.com/docs/en/debug-your-config
Path: 02-Claude-Code-CLI/debug-your-config.md
## On this page
- [See what loaded into context](#see-what-loaded-into-context)
- [Check resolved settings](#check-resolved-settings)
- [Check MCP servers](#check-mcp-servers)
- [Check hooks](#check-hooks)
- [Test against a clean configuration](#test-against-a-clean-configuration)
- [Check common causes](#check-common-causes)
- [Related resources](#related-resources)
Troubleshooting
# Debug your configuration
Copy pageCopy page
Diagnose why CLAUDE.md, settings, hooks, MCP servers, or skills aren’t taking effect. Use /context, /doctor, /hooks, and /mcp to see what actually loaded.
Copy pageCopy page
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](troubleshoot-install.md) instead.
[](#see-what-loaded-into-context)
See what loaded into context
The `/context` command shows everything occupying the context window for the current session, broken down by category: system prompt, system tools, MCP tools, custom subagents with the source each loaded from, memory files, skills, and conversation messages. Run it first to confirm whether your `CLAUDE.md`, rules, or skill descriptions are present at all. The skills section in `/context` also includes [bundled skills](../08-Plugins-Skills/skills.md#bundled-skills), which `/skills` doesn’t list. For detail on a specific category, follow up with the dedicated command:
| Command | Shows |
|:-----------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/memory` | Memory file locations across user and project scopes with the option to open each in your editor, plus access to the auto memory folder and the auto memory toggle |
| `/skills` | Available skills from project, user, and plugin sources |
| `/hooks` | Active hook configurations |
| `/mcp` | Connected MCP servers and their status |
| `/permissions` | Resolved allow and deny rules currently in effect |
| `/doctor` | Setup checkup: installation health, invalid settings files, unused extensions, duplicate [subagent](../09-Agents-Patterns/sub-agents.md) names in the same directory, and checked-in `CLAUDE.md` content Claude can derive from the codebase, with proposed fixes |
| `/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 the `/context` breakdown, check its location against [how CLAUDE.md files load](memory.md#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 `/context` 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](memory.md#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](permissions.md) and [hooks](../07-Hooks/hooks.md) 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)
Check resolved settings
Settings merge across managed, user, project, and local scopes. Managed settings apply first 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](env-vars.md), 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. To find invalid settings files, run `claude doctor` from your terminal. It prints read-only installation and settings diagnostics without starting a session. For a full checkup that also proposes fixes and asks before applying them, run [`/doctor`](commands.md#all-commands) inside a session. Run `/status` to see which settings sources are active, including whether managed settings are in effect. To understand which scope Claude Code uses for a given key, see [Settings precedence](settings.md#settings-precedence).
[](#check-mcp-servers)
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` and read the server’s stderr in the debug log at `~/.claude/debug/<session-id>.txt`.
For configuration locations and scope rules, see [MCP](../06-MCP-Tools/General/mcp.md).
[](#check-hooks)
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. Check it for these mistakes:
- The `matcher` field is a single string that uses `|` to match multiple tool names, for example `"Edit|Write"`. A `,` separator is equivalent, so `"Edit,Write"` matches the same tools. Before v2.1.191, a comma fell through to regex evaluation and the matcher never matched, so use `|` if you aren’t on v2.1.191 yet.
- A misspelled tool name produces a matcher that matches nothing, so the hook fails silently.
- An array value is a schema error: Claude Code shows a settings error notice and rejects the whole user, project, or local settings file, `claude doctor` reports the validation failure, and no hook from that file appears in `/hooks`. In [managed settings](../13-Enterprise-Admin/managed-settings.md), Claude Code drops the whole `hooks` key from the file that contains the array, so none of that file’s hooks apply. The file’s other settings still apply, and `claude doctor` lists the dropped key.
When you edit `settings.json`, the change takes effect in the running session after a brief file-stability delay, even if you create the file or the project’s `.claude/` folder itself after the session started. You don’t need to restart. Before v2.1.257, Claude Code didn’t detect edits in a `.claude/` folder created after the session started. If `/hooks` still shows the old definition a few seconds after you save, 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` 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](../07-Hooks/hooks.md#debug-hooks) for the log format and [hooks troubleshooting](../07-Hooks/hooks-guide.md#limitations-and-troubleshooting) for common failure patterns.
[](#test-against-a-clean-configuration)
Test against a clean configuration
Start with [`claude --safe-mode`](cli-reference.md#cli-flags), which launches a session with all customizations disabled, including `CLAUDE.md`, skills, plugins, hooks, MCP servers, and custom commands and agents. Authentication, model selection, built-in tools, and permissions work normally. If the problem disappears in safe mode, one of those surfaces is the cause; use the targeted checks above to find which. Safe mode still applies managed hooks and settings policy from your organization. Managed plugins, skills, CLAUDE.md, and MCP servers are turned off. If the problem persists in safe mode, or your settings themselves are suspect, compare against a session that loads nothing from your usual setup. Point [`CLAUDE_CONFIG_DIR`](env-vars.md) 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.
```python
cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claude
```
The clean session has no user or project settings, hooks, MCP servers, plugins, or memory. On the first launch, expect the first-run setup screens, starting with theme selection. If you see them, the clean configuration directory is in effect. Later launches with the same directory skip these screens because Claude Code saves onboarding state there.
- Managed settings still apply if your organization deploys them. Claude Code reads MDM profiles, registry policy, and `managed-settings.json` from locations outside the configuration directory, and [fetches server-managed settings](../13-Enterprise-Admin/server-managed-settings.md#fetch-and-caching-behavior) again for the clean session once it has credentials
- You’ll be prompted to log in again
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](env-vars.md) that affect Claude Code, then see [Troubleshooting](troubleshooting.md).
[](#check-common-causes)
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](../07-Hooks/hooks.md#matcher-patterns). |
| Hook never fires | `matcher` uses `,` as a separator on a version before v2.1.191 | Claude Code v2.1.191 or later treats `,` as a list separator like `|`. Earlier versions evaluate a comma as a literal character, so `"Edit,Write"` matches nothing. Use `|` instead, or upgrade Claude Code. |
| 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](../08-Plugins-Skills/plugins-components.md#hooks) load a separate `hooks/hooks.json`. See [hook configuration](../07-Hooks/hooks.md). |
| Permissions or hooks 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](settings.md#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](../08-Plugins-Skills/skills.md). |
| 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](memory.md#how-claude-md-files-load). |
| Subagent ignores `CLAUDE.md` instructions | The built-in Explore and Plan agents skip `CLAUDE.md`. A custom subagent loads it the same way the main conversation does, unless its definition sets [`omitClaudeMd`](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) | For Explore or Plan, restate the instruction in your delegating prompt. For a subagent that sets `omitClaudeMd`, remove the field. For any other custom subagent, put critical instructions in the agent file body, which becomes the agent’s system prompt. See [what loads at startup](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup). |
| Cleanup logic never runs at session end | No `SessionEnd` hook configured | Add a `SessionEnd` hook in `settings.json`. See the [hook events list](../07-Hooks/hooks.md#hook-events). |
| MCP servers in `.mcp.json` never load | File is under `.claude/`, or its servers sit under a top-level `servers` key, as in VS Code’s `mcp.json`, instead of `mcpServers` | Project MCP config goes at the repository root as `.mcp.json`, not inside `.claude/`, with servers under the `mcpServers` key. See [MCP configuration](../06-MCP-Tools/General/mcp.md). |
| 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](../06-MCP-Tools/General/mcp.md). |
| 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 | The server’s config entry doesn’t set them, and they aren’t in the environment Claude Code passes to stdio servers: its own environment, minus the [variables it strips from subprocesses](../13-Enterprise-Admin/monitoring-usage.md#administrator-configuration) | Set per-server `env` inside the server’s `.mcp.json` entry, which doesn’t depend on the launch environment or workspace trust. |
| `Bash(rm *)` deny rule doesn’t block `/bin/rm` or `find -delete` | Bash rules match the literal command string, not the underlying executable; see [what a Bash rule doesn’t match](permissions.md#bash-rule-limits) | Use a [PreToolUse hook](../07-Hooks/hooks-guide.md) or the [sandbox](sandboxing.md) for a hard guarantee. |
[](#related-resources)
Related resources
For full reference on each configuration surface, see the dedicated page:
- **[`.claude` directory reference](claude-directory.md)**: every config file location and what reads it
- **[Settings](settings.md)**: which file to use and which value Claude Code uses; the [settings reference](settings-reference.md) has the full key list
- **[Hooks reference](../07-Hooks/hooks.md)**: event names, payloads, and `--debug` output format
- **[MCP](../06-MCP-Tools/General/mcp.md)**: server configuration, approval, and `/mcp` output
- **[Troubleshoot installation and login](troubleshoot-install.md)**: `command not found`, PATH, and authentication problems
- **[Troubleshooting](troubleshooting.md)**: performance, hangs, and search issues
---
## Launch sessions from links - Claude Code Docs
Source: https://code.claude.com/docs/en/deep-links
Path: 02-Claude-Code-CLI/deep-links.md
## On this page
- [How deep links work](#how-deep-links-work)
- [What a launched session shows](#what-a-launched-session-shows)
- [Build a link](#build-a-link)
- [Choose between cwd and repo](#choose-between-cwd-and-repo)
- [Examples](#examples)
- [Embed a link in a runbook](#embed-a-link-in-a-runbook)
- [Open a link from the shell](#open-a-link-from-the-shell)
- [Registration and supported platforms](#registration-and-supported-platforms)
- [Open a VS Code tab instead of a terminal](#open-a-vs-code-tab-instead-of-a-terminal)
- [Troubleshooting](#troubleshooting)
- [Clicking the link does nothing](#clicking-the-link-does-nothing)
- [xdg-open is not found on Linux](#xdg-open-is-not-found-on-linux)
- [The link renders as plain text instead of being clickable](#the-link-renders-as-plain-text-instead-of-being-clickable)
- [The session opens in my home directory instead of the repo](#the-session-opens-in-my-home-directory-instead-of-the-repo)
- [The link opens the wrong terminal](#the-link-opens-the-wrong-terminal)
- [Learn more](#learn-more)
Automation
# Launch sessions from links
Copy pageCopy page
Open a Claude Code terminal session from a URL. Embed `claude-cli://` links in runbooks, alerts, and dashboards so a click opens Claude Code in the right repo with the right prompt.
Copy pageCopy page
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](#build-a-link), [embed one in a runbook or trigger it from the shell](#examples), and [manage or disable handler registration](#registration-and-supported-platforms) on each platform.
[](#how-deep-links-work)
How deep links work
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. When you click a deep link:
1. The browser or app passes the URL to your operating system.
2. The operating system recognizes the `claude-cli://` prefix and starts Claude Code on your machine.
3. 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.
4. 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](#registration-and-supported-platforms) for which terminal emulator opens on each operating system. The platform that displays the link must allow custom URL schemes. For what GitHub does with them and the workaround, see [The link renders as plain text instead of being clickable](#the-link-renders-as-plain-text-instead-of-being-clickable).
[](#what-a-launched-session-shows)
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 warning line below the input box reads `Prompt from an external link` and stays visible until you send or clear the prompt. For prompts over 1,000 characters, the warning includes the character count and 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)
Build a link
A deep link starts with `claude-cli://open`, followed by optional query parameters. The minimal form opens Claude Code in your home directory with an empty prompt:
```python
claude-cli://open
```
To try a link without putting it on a page, paste it into your browser’s address bar or [open it from the shell](#open-a-link-from-the-shell). 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) 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, and so are paths that contain `..` segments or invisible or bidirectional control characters. |
| `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](#choose-between-cwd-and-repo). 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:
```python
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:
```python
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. See [Choose between `cwd` and `repo`](#choose-between-cwd-and-repo) for how the local path is selected when you have multiple clones or worktrees.
[](#choose-between-cwd-and-repo)
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:
- `repo` opens the linked repository’s clone or worktree where you most recently ran `claude`. Each time you run `claude` in a Git repository, Claude Code records that directory’s path against the repository’s GitHub `owner/name` slug. Claude Code tracks clones and worktrees separately.
- The link does not change which branch is checked out. The session opens in whatever state that directory is currently in.
The welcome header shows which path it picked so you can confirm the right clone opened.
[](#examples)
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)
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](#the-link-renders-as-plain-text-instead-of-being-clickable) 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`:
```python
## 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)
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. These commands rely on the handler that Claude Code [registers when you send your first prompt of an interactive session](#registration-and-supported-platforms) on the machine.
- macOS
- Linux
- Windows
The built-in `open` command passes the URL to the registered `claude-cli://` handler:
```python
open "claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
```
On success, a new terminal window opens with Claude Code running and the prompt pre-filled.
Most desktop environments provide `xdg-open`, which passes the URL to the registered handler:
```python
xdg-open "claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
```
On success, a new terminal window opens with Claude Code running and the prompt pre-filled. If the shell reports that `xdg-open` isn’t found, see [Troubleshooting](#xdg-open-is-not-found-on-linux).
In PowerShell, `Start-Process` passes the URL to the registered handler:
```python
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:
```python
start "" "claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
```
On success, a new terminal window opens with Claude Code running and the prompt pre-filled.
[](#registration-and-supported-platforms)
Registration and supported platforms
Claude Code registers the `claude-cli://` handler with your operating system on macOS, Linux, and Windows when you send your first prompt of an interactive session. Starting `claude` and exiting without sending a prompt doesn’t register the handler. You don’t 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`](settings-reference.md#disabledeeplinkregistration) to `"disable"` in `settings.json`. To enforce this across an organization so users cannot re-enable it, set it in [managed settings](../13-Enterprise-Admin/server-managed-settings.md) instead.
[](#open-a-vs-code-tab-instead-of-a-terminal)
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](../03-IDE-Integrations/vs-code.md#launch-a-vs-code-tab-from-other-tools) for that URL’s parameters.
[](#troubleshooting)
Troubleshooting
[](#clicking-the-link-does-nothing)
Clicking the link does nothing
The handler likely isn’t registered yet. Registration happens when you send your first prompt of an interactive session, not when the session starts. Start an interactive `claude` session on that machine, send any prompt, exit, and try the link again. If you are on Linux without a desktop environment, `xdg-open` may have nothing to dispatch to.
[](#xdg-open-is-not-found-on-linux)
xdg-open is not found on Linux
The `xdg-open` command is part of the `xdg-utils` package, which minimal server images, containers, and WSL distributions often leave out. Install `xdg-utils` with your distribution’s package manager, for example `sudo apt install xdg-utils`, then run the command again. If the command then runs but nothing opens, `xdg-open` may have no desktop environment to dispatch to; see [Clicking the link does nothing](#clicking-the-link-does-nothing).
[](#the-link-renders-as-plain-text-instead-of-being-clickable)
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 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 Claude Code records its path, or switch the link to use `cwd` with an absolute path.
[](#the-link-opens-the-wrong-terminal)
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)
Learn more
These pages cover related ways to launch or extend Claude Code sessions:
- [Skills](../08-Plugins-Skills/skills.md): 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](headless.md): run Claude from a script and capture the output without opening a terminal
---
## Development containers - Claude Code Docs
Source: https://code.claude.com/docs/en/devcontainer
Path: 02-Claude-Code-CLI/devcontainer.md
## On this page
- [Add Claude Code to your dev container](#add-claude-code-to-your-dev-container)
- [Persist authentication and settings across rebuilds](#persist-authentication-and-settings-across-rebuilds)
- [Enforce organization policy](#enforce-organization-policy)
- [Restrict network egress](#restrict-network-egress)
- [Run without permission prompts](#run-without-permission-prompts)
- [Try the reference container](#try-the-reference-container)
- [Next steps](#next-steps)
Deployment
# Development containers
Copy pageCopy page
Run Claude Code inside a dev container for consistent, isolated environments across your team.
Copy pageCopy page
A [development container](https://containers.dev/), 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](#add-claude-code-to-your-dev-container), then a set of self-contained configuration topics: persisting authentication across rebuilds, enforcing organization policy, restricting network egress, and running without permission prompts. Read the ones that match your setup.
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`](claude-directory.md). 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](../03-IDE-Integrations/vs-code.md) 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)
Add Claude Code to your dev container
Claude Code installs into any dev container through the [Claude Code Dev Container Feature](https://github.com/anthropics/devcontainer-features/tree/main/src/claude-code). 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](https://code.visualstudio.com/docs/devcontainers/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](#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](#enforce-organization-policy).
.devcontainer/devcontainer.json
```python
{
"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.The Claude Code feature installs Node.js itself when the base image doesn’t provide it. If that install fails and the build stops with `Failed to install Node.js and npm`, add `"ghcr.io/devcontainers/features/node:1": {}` to the `features` block above the Claude Code feature and rebuild.
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](https://docs.github.com/en/codespaces/developing-in-a-codespace/rebuilding-the-container-in-a-codespace), the [Dev Containers CLI](https://github.com/devcontainers/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 Cloud’s Agent Platform, or Microsoft Foundry](third-party-integrations.md)**: 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](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md) for the credential chain Claude Code reads. See [Choose your API provider](../13-Enterprise-Admin/admin-setup.md#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)
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 the [`~/.claude`](claude-directory.md) directory. It stores your OAuth account, personal MCP servers, and per-project trust in [`~/.claude.json`](settings-reference.md#global-config-settings), a separate file outside that directory, so mounting a volume at `~/.claude` alone doesn’t keep you signed in. Mount a named volume at `~/.claude` and set [`CLAUDE_CONFIG_DIR`](env-vars.md) to the same path so Claude Code writes `.claude.json` inside the volume. The following example mounts the volume and sets `CLAUDE_CONFIG_DIR` for a container whose `remoteUser` is `node`:
devcontainer.json
```python
"mounts": [
"source=claude-code-config,target=/home/node/.claude,type=volume"
],
"containerEnv": {
"CLAUDE_CONFIG_DIR": "/home/node/.claude"
}
```
Replace `/home/node` with the home directory of your container’s `remoteUser`. If you already set `containerEnv`, for example in [Enforce organization policy](#enforce-organization-policy), add `CLAUDE_CONFIG_DIR` to that object rather than adding a second one. To isolate state per project rather than sharing one volume across all repositories, include the `${devcontainerId}` variable in the source name. The [reference configuration](https://github.com/anthropics/claude-code/blob/main/.devcontainer/devcontainer.json) uses `source=claude-code-config-${devcontainerId}` for this purpose. In GitHub Codespaces, `~/.claude` persists when you stop and start a codespace but is cleared when you rebuild the container, so the configuration above applies there too. To carry authentication across codespaces, store `ANTHROPIC_API_KEY` or a `CLAUDE_CODE_OAUTH_TOKEN` from [`claude setup-token`](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token) as a [Codespaces secret](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces). Codespaces exposes secrets as environment variables inside the container automatically.
[](#enforce-organization-policy)
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](settings.md#settings-precedence), 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
```python
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](../13-Enterprise-Admin/server-managed-settings.md) or your MDM instead. See [managed settings files](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) for the available keys and the other delivery paths. To set [environment variables](env-vars.md) 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
```python
"containerEnv": {
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"DISABLE_AUTOUPDATER": "1"
}
```
`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` also disables the feature-flag evaluation that [Remote Control](remote-control.md#requirements) and the other [features that need feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) depend on, so sessions in the container can’t use them. 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` to `1` in `containerEnv`. For the full list of policy controls including permission rules, tool restrictions, and MCP server allowlists, see [Set up Claude Code for your organization](../13-Enterprise-Admin/admin-setup.md). To make [MCP servers](../06-MCP-Tools/General/mcp.md) available inside the container, define them at [project scope](../06-MCP-Tools/General/mcp.md#mcp-installation-scopes) 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)
Restrict network egress
You can limit the container’s outbound traffic to only the domains Claude Code needs. See [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements) for the inference and authentication domains, and [Telemetry services](../13-Enterprise-Admin/data-usage.md#telemetry-services) for the optional telemetry and error reporting connections and how to disable them. The reference container includes an [`init-firewall.sh`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/init-firewall.sh) script that limits outbound traffic to the destinations the script allows. 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)
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](#restrict-network-egress) above to limit what a bypassed session can reach. If you want fewer prompts without disabling safety checks, consider [auto mode](permission-modes.md#eliminate-prompts-with-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](settings-reference.md#permission-settings).
[](#try-the-reference-container)
Try the reference container
The [`anthropics/claude-code`](https://github.com/anthropics/claude-code/tree/main/.devcontainer) 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](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
2
Clone the reference
Clone the [Claude Code repository](https://github.com/anthropics/claude-code) 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](#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`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/devcontainer.json) | Volume mounts, `runArgs` capabilities, VS Code extensions, and `containerEnv` |
| [`Dockerfile`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/Dockerfile) | Base image, development tools, and the Claude Code install |
| [`init-firewall.sh`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/init-firewall.sh) | Limits outbound network traffic to the destinations the script allows |
[](#next-steps)
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](../13-Enterprise-Admin/admin-setup.md): choose an authentication provider, decide how policy reaches devices, and plan the rollout
- [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md): deliver managed policy from the claude.ai admin console so engineers cannot bypass it by editing repository files
- [Monitor usage and audit activity](../13-Enterprise-Admin/monitoring-usage.md): export OpenTelemetry metrics and review what your team is running
- [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements): the full domain allowlist for proxies and firewalls
- [Telemetry services and opt-out](../13-Enterprise-Admin/data-usage.md#telemetry-services): what Claude Code sends by default and the environment variables that disable it
- [Explore the `.claude` directory](claude-directory.md): what the volume mount holds, including credentials, settings, and session history
- [Sandbox environments](sandbox-environments.md): compare dev containers with the built-in Bash sandbox, custom containers, and VMs
- [Security model](../13-Enterprise-Admin/security.md): how Claude Code’s permission system, sandboxing, and prompt-injection protections fit together
- [Permission modes](permission-modes.md): the full range from plan mode to auto mode to bypass, and when to use each
---
## Environment variables - Claude Code Docs
Source: https://code.claude.com/docs/en/env-vars
Path: 02-Claude-Code-CLI/env-vars.md
## On this page
- [Set environment variables](#set-environment-variables)
- [In your shell](#in-your-shell)
- [In settings files](#in-settings-files)
- [Precedence](#precedence)
- [Variables](#variables)
- [Features that need feature-flag fetching](#features-that-need-feature-flag-fetching)
- [First session after an install or upgrade](#first-session-after-an-install-or-upgrade)
- [See also](#see-also)
Reference
# Environment variables
Copy pageCopy page
Reference for environment variables that control Claude Code behavior.
Copy pageCopy page
Environment variables can control Claude Code behavior such as model selection, authentication, request routing, and feature toggles. Many of the same behaviors can also be configured through a [settings file](settings.md) field, a [CLI flag](cli-reference.md), or an in-session command like `/model`. This page covers how to:
- [Set environment variables](#set-environment-variables) in your shell or in a settings file
- [Check which value applies](#precedence) when a behavior can be set more than one way
- [Look up the variables Claude Code reads](#variables)
- [See which features stop working](#features-that-need-feature-flag-fetching) when a variable turns feature-flag fetching off
[](#set-environment-variables)
Set environment variables
A variable you set in your shell lasts for that terminal session, while a variable in a settings file applies every time `claude` runs.
[](#in-your-shell)
In your shell
Set the variable before launching `claude`:
- macOS, Linux, WSL
- Windows PowerShell
- Windows CMD
```python
export API_TIMEOUT_MS="1200000"
claude
```
To set it for every session, add the `export` line to `~/.bashrc`, `~/.zshrc`, or your shell’s profile file.
```python
$env:API_TIMEOUT_MS = "1200000"
claude
```
To set it for every session, run `[Environment]::SetEnvironmentVariable("API_TIMEOUT_MS", "1200000", "User")` and open a new terminal.
```python
set API_TIMEOUT_MS=1200000
claude
```
To set it for every session, run `setx API_TIMEOUT_MS "1200000"` and open a new terminal.
The assignment line prints nothing on success, so confirm the variable is set by printing it in the same shell before you run `claude`:
- macOS, Linux, WSL
- Windows PowerShell
- Windows CMD
```python
echo $API_TIMEOUT_MS
```
```python
echo $env:API_TIMEOUT_MS
```
```python
echo %API_TIMEOUT_MS%
```
[](#in-settings-files)
In settings files
Add variables under the `env` key in a `settings.json` file, creating the file if it doesn’t exist. Claude Code reads them directly from the file, so they take effect no matter how `claude` was launched. A running session applies new and changed values to its environment when you save the file, but a feature that reads its variables once at startup, such as [OpenTelemetry monitoring](../13-Enterprise-Admin/monitoring-usage.md), keeps its startup values until you relaunch. Removing a variable from the file doesn’t unset it in a running session; the removal takes effect the next time you launch `claude`.
~/.claude/settings.json
```python
{
"env": {
"API_TIMEOUT_MS": "1200000",
"BASH_DEFAULT_TIMEOUT_MS": "300000"
}
}
```
The file you choose controls who the variables apply to:
| File | Applies to |
|:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
| `~/.claude/settings.json` | You, in every project |
| `.claude/settings.json` | Everyone working in the project, checked into source control |
| `.claude/settings.local.json` | You, in this project only, gitignored when Claude Code saves a setting to it; add it to your gitignore if you create it by hand |
| Managed settings | Everyone in your organization, deployed by an admin |
See [Settings files](settings.md#where-settings-live) for where each file lives and [Settings precedence](settings.md#settings-precedence) for how they combine when more than one sets the same variable.
[](#precedence)
Precedence
Some behaviors have both an environment variable and a dedicated settings key, and which one Claude Code reads first differs per key. For `ANTHROPIC_MODEL` and `CLAUDE_CODE_AUTO_CONNECT_IDE`, Claude Code reads the variable first and uses the `model` or `autoConnectIde` setting only when the variable is unset. For the pair you’re setting, check the variable’s row below and the key’s entry on the [settings reference](settings-reference.md). When the same variable is set in both your shell and a settings file `env` block, the settings file value applies in most sessions. Claude Code writes each `env` entry into the process environment, replacing the value inherited from the shell. [How `env` values interact with your shell](settings-reference.md#how-env-values-interact-with-your-shell) covers the sessions that keep the inherited value instead, and the [`env` setting](settings-reference.md#when-claude-code-applies-env-values) says when it applies them. A few variables are special-cased; the [`env` setting](settings-reference.md#env) lists the exceptions. In a settings file you can set a variable but you can’t remove one. To override a variable you can’t unset, such as a stale `CLAUDE_CODE_USE_VERTEX` exported by a shell profile you don’t control, set it to an empty string in the `env` block: `"CLAUDE_CODE_USE_VERTEX": ""`. Claude Code treats the empty value as unset for provider selection. Subprocesses still inherit the empty value. Between settings files, `env` values follow [settings precedence](settings.md#settings-precedence), so a managed settings entry overrides the same variable in user or project settings. Project and local settings can’t set some variables, such as `CLAUDE_CONFIG_DIR` and the OpenTelemetry exporter variables. [Variables Claude Code ignores in `env`](settings-reference.md#variables-claude-code-ignores-in-env) lists them, along with the OpenTelemetry off values that still apply. How an environment variable interacts with CLI flags and in-session commands varies per feature: `--model` and `/model` override `ANTHROPIC_MODEL`, while `CLAUDE_CODE_EFFORT_LEVEL` overrides `--effort` and `/effort`. When a variable interacts with another configuration source, its row in the [Variables](#variables) list states the precedence or links to the page that documents it. Claude Code reads shell environment variables at startup, so changes to them take effect the next time you launch `claude`. Variables set under the `env` key in settings files are reapplied to a running session when the file changes, with the startup-only exception described in [In settings files](#in-settings-files).
[](#variables)
Variables
Numeric variables such as timeouts, token budgets, and retry counts accept scientific notation and digit-separator spellings in addition to plain digits, except where a variable’s row notes it takes plain digits only. For example, Claude Code reads `2e3` as 2000 and `64_000` as 64000. Before v2.1.211, these spellings could silently set a much smaller value, such as `1e6` setting a timeout to 1.
For variables that turn a behavior on or off, set `1` or `true` to turn it on and `0` or `false` to turn it off, in any casing.Some variables read only whether you set them at all, so any non-empty value including `0` turns the behavior on, and you turn the behavior off by unsetting the variable or setting it to an empty value. These variables work that way:
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`
- `DISABLE_TELEMETRY`
- `DISABLE_ERROR_REPORTING`
- `CLAUDE_CODE_TMUX_TRUECOLOR`
- `FALLBACK_FOR_ALL_PRIMARY_MODELS`
- `IS_DEMO`
One other variable has its own rule: `FORCE_HYPERLINK` reads a number, so only `0` turns it off. Each variable’s row also states its own rule.
| 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](claude-platform-on-aws.md), 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](claude-platform-on-aws.md) endpoint URL. Use for custom regions or when routing through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). Defaults to `https://aws-external-anthropic.{region}.api.aws`. Claude Code resolves the region with the [same precedence as on Amazon Bedrock](amazon-bedrock.md#3-configure-claude-code) |
| `ANTHROPIC_AWS_WORKSPACE_ID` | Required for [Claude Platform on AWS](claude-platform-on-aws.md). 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](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is disabled by default. Set `ENABLE_TOOL_SEARCH=true` if your proxy forwards `tool_reference` blocks. As of v2.1.196, [Remote Control](remote-control.md#requirements) is disabled when this points at a host other than `api.anthropic.com`, matching its behavior on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry |
| `ANTHROPIC_BEDROCK_BASE_URL` | Override the Amazon Bedrock endpoint URL. Use for custom Amazon Bedrock endpoints or when routing through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). See [Amazon Bedrock](amazon-bedrock.md) |
| `ANTHROPIC_BEDROCK_MANTLE_BASE_URL` | Override the Amazon Bedrock Mantle endpoint URL. See [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint) |
| `ANTHROPIC_BEDROCK_REGION_PREFIX` | Cross-region inference profile prefix (`us`, `eu`, `apac`, `jp`, `au`, or `global`) Claude Code tries first instead of the one derived from the AWS region. Ignored in AWS GovCloud regions. Requires Claude Code v2.1.224 or later. See [Amazon Bedrock](amazon-bedrock.md#cross-region-inference-profile-prefixes) |
| `ANTHROPIC_BEDROCK_SERVICE_TIER` | Amazon Bedrock [service tier](https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html) (`default`, `flex`, or `priority`). Sent as the `X-Amzn-Bedrock-Service-Tier` header. See [Amazon Bedrock](amazon-bedrock.md#service-tiers) |
| `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](../04-API-Reference/Endpoints/beta-headers.md) before Claude Code adds native support. Unlike the [`--betas` flag](cli-reference.md#cli-flags), 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). If a name or value contains a character an HTTP header can’t carry, such as a curly quote or a zero-width space, the request fails with an error that identifies the pair by position. Requires Claude Code v2.1.227 or later. [Invalid request header value](errors.md#invalid-request-header-value) lists the exact character set and where the check runs. A value that sets a credential, org or tenant, routing, or API-behavior header, such as `Authorization` or `Host`, counts as a [setting that needs approval](../13-Enterprise-Admin/server-managed-settings.md#environment-variables-and-the-approval-dialog) when server-managed settings deliver it. From project or local settings, such a value follows the [rules for when `env` values apply](settings-reference.md#when-claude-code-applies-env-values) |
| `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](model-config.md#add-a-custom-model-option) |
| `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. When not set, the entry shows the model’s name if Claude Code [recognizes the ID](model-config.md#customize-pinned-model-display-and-capabilities), and the model ID otherwise |
| `ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES` | Comma-separated list of [capabilities](model-config.md#customize-pinned-model-display-and-capabilities) the custom model supports, for example `effort,thinking`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_FABLE_MODEL` | Model ID that the `fable` alias resolves to, and the ID Claude Code recognizes as a Fable model for [automatic model fallback](model-config.md#automatic-model-fallback) on third-party providers. See [Model configuration](model-config.md#environment-variables) |
| `ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION` | Display description for the pinned Fable model in the `/model` picker. When not set, the row shows a default description that begins `Custom Fable model`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_FABLE_MODEL_NAME` | Display name for the pinned Fable model in the `/model` picker. When not set, the row shows the model’s name if Claude Code recognizes the pinned ID, and the pinned ID otherwise. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_FABLE_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of [capabilities](model-config.md#customize-pinned-model-display-and-capabilities) the pinned Fable model supports, for example `effort,thinking`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Model ID that the `haiku` alias resolves to, also used for [background functionality](../17-Billing-Plans/costs.md#background-token-usage). See [Model configuration](model-config.md#environment-variables) |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION` | Display description for the pinned Haiku model in the `/model` picker. When not set, the row shows a default description that begins `Custom Haiku model`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME` | Display name for the pinned Haiku model in the `/model` picker. When not set, the row shows the model’s name if Claude Code recognizes the pinned ID, and the pinned ID otherwise. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of [capabilities](model-config.md#customize-pinned-model-display-and-capabilities) the pinned Haiku model supports, for example `effort,thinking`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_MODEL` | Model that new sessions start on by default. Requires Claude Code v2.1.236 or later. See [Set a default model for new sessions](model-config.md#set-a-default-model-for-new-sessions) |
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | Model ID that the `opus` alias resolves to, and that `opusplan` uses while Plan Mode is active. See [Model configuration](model-config.md#environment-variables) |
| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | Display description for the pinned Opus model in the `/model` picker. When not set, the row shows a default description that begins `Custom Opus model`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_OPUS_MODEL_NAME` | Display name for the pinned Opus model in the `/model` picker. When not set, the row shows the model’s name if Claude Code recognizes the pinned ID, and the pinned ID otherwise. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of [capabilities](model-config.md#customize-pinned-model-display-and-capabilities) the pinned Opus model supports, for example `effort,thinking`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | Model ID that the `sonnet` alias resolves to, and that `opusplan` uses when Plan Mode is not active. See [Model configuration](model-config.md#environment-variables) |
| `ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION` | Display description for the pinned Sonnet model in the `/model` picker. When not set, the row shows a default description that begins `Custom Sonnet model`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_SONNET_MODEL_NAME` | Display name for the pinned Sonnet model in the `/model` picker. When not set, the row shows the model’s name if Claude Code recognizes the pinned ID, and the pinned ID otherwise. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of [capabilities](model-config.md#customize-pinned-model-display-and-capabilities) the pinned Sonnet model supports, for example `effort,thinking`. See [Model configuration](model-config.md#customize-pinned-model-display-and-capabilities) |
| `ANTHROPIC_FEDERATION_RULE_ID` | Federation rule ID for [Workload Identity Federation](../04-API-Reference/Other/manage-claude-workload-identity-federation.md). When you set it together with `ANTHROPIC_ORGANIZATION_ID`, Claude Code selects federation credentials, which rank above your `/login` credential. See [authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) |
| `ANTHROPIC_FOUNDRY_API_KEY` | API key for Microsoft Foundry authentication (see [Microsoft Foundry](microsoft-foundry.md)) |
| `ANTHROPIC_FOUNDRY_AUTH_TOKEN` | Bearer token for Microsoft Foundry authentication, such as a Microsoft Entra access token. Claude Code sends it as the `Authorization: Bearer` header. Takes precedence over `ANTHROPIC_FOUNDRY_API_KEY` and over the Azure default credential chain. See [Microsoft Foundry](microsoft-foundry.md). Requires Claude Code v2.1.203 or later |
| `ANTHROPIC_FOUNDRY_BASE_URL` | Full base URL for the Microsoft Foundry resource (for example, `https://my-resource.services.ai.azure.com/anthropic`). Alternative to `ANTHROPIC_FOUNDRY_RESOURCE` (see [Microsoft Foundry](microsoft-foundry.md)) |
| `ANTHROPIC_FOUNDRY_RESOURCE` | Microsoft Foundry resource name (for example, `my-resource`). Required if `ANTHROPIC_FOUNDRY_BASE_URL` is not set (see [Microsoft Foundry](microsoft-foundry.md)) |
| `ANTHROPIC_MODEL` | Name of the model setting to use (see [Model Configuration](model-config.md#environment-variables)) |
| `ANTHROPIC_ORGANIZATION_ID` | Organization ID for [Workload Identity Federation](../04-API-Reference/Other/manage-claude-workload-identity-federation.md). Set it together with `ANTHROPIC_FEDERATION_RULE_ID`. See [authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) |
| `ANTHROPIC_PROFILE` | Name of the Anthropic profile to authenticate with, such as one created by [`ant auth login`](../04-API-Reference/Other/cli-sdks-libraries-cli-authentication.md) or by [signing in to a Console account without an API key](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key). See [authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) |
| `ANTHROPIC_SMALL_FAST_MODEL` | \[DEPRECATED\] Name of [Haiku-class model for background tasks](../17-Billing-Plans/costs.md) |
| `ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION` | Override AWS region for the Haiku-class model when using Amazon Bedrock or Amazon Bedrock Mantle. On Amazon Bedrock, this only takes effect when `ANTHROPIC_DEFAULT_HAIKU_MODEL` or the deprecated `ANTHROPIC_SMALL_FAST_MODEL` is also set, since Amazon Bedrock otherwise runs background tasks on the [default Sonnet model or the primary model](amazon-bedrock.md#4-pin-model-versions) in the session region |
| `ANTHROPIC_VERTEX_BASE_URL` | Override Google Cloud’s Agent Platform endpoint URL. Use for custom Google Cloud’s Agent Platform endpoints or when routing through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). See [Google Cloud’s Agent Platform](google-vertex-ai.md) |
| `ANTHROPIC_VERTEX_PROJECT_ID` | GCP project ID that Google Cloud’s Agent Platform requests are addressed to. See [Configure GCP credentials](google-vertex-ai.md#3-configure-gcp-credentials) |
| `ANTHROPIC_WORKSPACE_ID` | Workspace ID for [workload identity federation](../04-API-Reference/Other/manage-claude-workload-identity-federation.md). Set this when your federation rule is scoped to more than one workspace so the token exchange knows which workspace to target |
| `API_FORCE_IDLE_TIMEOUT` | Override the 5-minute body idle timeout that aborts a streaming model response when no bytes arrive. Set to `0` to turn the timeout off, for example when a slow [gateway](../13-Enterprise-Admin/llm-gateway.md) or local model pauses longer than 5 minutes between chunks, or `1` to keep it on for every provider. When unset, the timeout is active on providers other than the direct Anthropic API, [Claude Platform on AWS](claude-platform-on-aws.md), and Amazon Bedrock with `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1` set. The [stream watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) run independently of it and abort a long silent pause even when you set `0` here |
| `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` | Amazon Bedrock API key for authentication (see [Amazon Bedrock API keys](https://aws.amazon.com/blogs/machine-learning/accelerate-ai-development-with-amazon-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 of bash output that Claude Code reads back into a command’s result (default: 30000; maximum: 150000). If you set the [`bashOutputMaxChars`](settings-reference.md#bashoutputmaxchars) setting, Claude Code ignores this variable. See [Output limits](tools-reference.md#output-limits) |
| `BASH_MAX_TIMEOUT_MS` | Maximum timeout the model can set for long-running bash commands (default: 600000, or 10 minutes). The effective ceiling is the larger of this and `BASH_DEFAULT_TIMEOUT_MS` |
| `BETA_TRACING_ENDPOINT` | OTLP endpoint for [detailed beta tracing](../13-Enterprise-Admin/monitoring-usage.md#traces-beta): with `ENABLE_BETA_TRACING_DETAILED=1`, logs and traces go there instead of to the configured exporters. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env) |
| `CCR_FORCE_BUNDLE` | Set to `1` to force [`claude --cloud`](claude-code-on-the-web.md#send-local-repositories-without-github) to bundle and upload your local repository instead of cloning from its remote |
| `CLAUDECODE` | Set to `1` in subprocesses Claude Code spawns (Bash and PowerShell tools, tmux sessions, [hook](../07-Hooks/hooks.md) commands, [status line](statusline.md) commands, stdio [MCP server](../06-MCP-Tools/General/mcp.md) subprocesses). IDE extensions also set this in their integrated terminals. Use to detect when a script is running inside a subprocess spawned by Claude Code. To check whether the current process was spawned directly by a tool call or hook, rather than inside a stdio MCP server that Claude Code started, use `CLAUDE_CODE_CHILD_SESSION` instead |
| `CLAUDE_AFK_COUNTDOWN_MS` | How many milliseconds before auto-continue the on-screen countdown appears on an unanswered [`AskUserQuestion`](tools-reference.md) dialog. Default `20000` (20 seconds), capped at the auto-continue timeout. Has no effect unless auto-continue is on; see the [`askUserQuestionTimeout`](settings-reference.md#askuserquestiontimeout) setting and `CLAUDE_AFK_TIMEOUT_MS`. Requires Claude Code v2.1.198 or later |
| `CLAUDE_AFK_TIMEOUT_MS` | How many milliseconds of idle time before an unanswered [`AskUserQuestion`](tools-reference.md) dialog auto-continues without you. Auto-continue is off by default; opt in with the [`askUserQuestionTimeout`](settings-reference.md#askuserquestiontimeout) setting. This variable is an override for demos and automated tests: when set, it takes precedence over that setting and turns auto-continue on even when the setting is unset or `never`. Setting `0` doesn’t turn the timeout off; it closes the dialog immediately. In v2.1.198 and v2.1.199, auto-continue was on by default with a `60000` (60 seconds) timeout. Requires Claude Code v2.1.198 or later |
| `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` | Set to `1` to disable all built-in [subagent](../09-Agents-Patterns/sub-agents.md) types such as Explore and Plan. Only applies in non-interactive mode (the `-p` flag). Useful for SDK users who want a blank slate. This also removes `general-purpose`, the subagent Claude Code runs when an Agent tool call omits `subagent_type`. Such a call then fails with [`subagent_type is required`](errors.md#subagent-type-is-required) |
| `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 subagents. Default `600000` (10 minutes); if you raise `CLAUDE_STREAM_IDLE_TIMEOUT_MS` while the stream watchdog is on, the default rises with it, as [Handle slow or stalled API responses](../05-Agent-SDK/agent-sdk-typescript.md#handle-slow-or-stalled-api-responses) describes. The timer resets on each streaming progress event; if no progress arrives within the window, Claude Code aborts the subagent and reports the stall to the parent |
| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | Set the percentage (1-100) of the auto-compact window at which auto-compaction triggers. Use lower values like `50` to compact earlier; the variable can’t raise the threshold, so values above the default percentage are ignored. It applies only in sessions that [compact before the model’s context limit](model-config.md#context-window-and-auto-compaction). Applies to both main conversations and subagents |
| `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. Also enables [automatic backgrounding of long MCP tool calls](../06-MCP-Tools/General/mcp.md#automatic-backgrounding-of-long-tool-calls) in non-interactive mode on Claude Code v2.1.212 or later |
| `CLAUDE_AX_PREPARK_MS` | In [screen reader mode](accessibility.md#what-your-screen-reader-hears), how many milliseconds Claude Code waits, with the cursor at the start of the line, before it writes a new or changed line. Default `50`. Set `0` to write immediately. Claude Code caps the wait at `5000`. Requires Claude Code v2.1.233 or later |
| `CLAUDE_AX_SCREEN_READER` | Set to `1` to render screen-reader friendly output: flat text without decorative borders or animations. Set to `0` to force screen-reader mode off even when [`axScreenReader`](settings-reference.md#axscreenreader) is `true`. The [`--ax-screen-reader`](cli-reference.md#cli-flags) flag takes precedence. Requires Claude Code v2.1.181 or later |
| `CLAUDE_AX_STARTUP_QUIET_MS` | In [screen reader mode](accessibility.md), how many milliseconds Claude Code holds the first interface render after the startup confirmation line, so your screen reader can speak the line in full before new output interrupts it. Default `3000`. Set `0` to render immediately. Claude Code caps the hold at `600000` (10 minutes). Your first keystroke ends the hold early. Requires Claude Code v2.1.217 or later |
| `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR` | Return to the original working directory after each Bash or PowerShell command in the main session |
| `CLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MS` | Timeout in milliseconds for the byte-level streaming idle watchdog; when set, it takes precedence over `CLAUDE_STREAM_IDLE_TIMEOUT_MS` for that watchdog and leaves the event-level watchdog unchanged. Claude Code clamps this variable to between 10 seconds and 30 minutes. Requires Claude Code v2.1.210 or later |
| `CLAUDE_CLIENT_PRESENCE_FILE` | Path to a file that an external tool, such as a screen-lock listener, creates when you unlock your screen and deletes when you lock it. While the file exists, Claude Code skips [Remote Control mobile push notifications](remote-control.md#mobile-push-notifications), so you stop getting pushes while you are actively using the computer. When the file is absent or unreadable, notifications are sent as normal. Claude Code checks the file once per push-triggering event rather than polling it. Requires Claude Code v2.1.181 or later |
| `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_ALT_SCREEN_FULL_REPAINT` | Set to `1` to repaint the entire screen on every frame in [fullscreen rendering](fullscreen.md) instead of sending incremental updates. Use this if fullscreen mode shows stale or misplaced text fragments. Claude Code enables this automatically for background sessions and [agent view](../09-Agents-Patterns/agent-view.md) on Windows |
| `CLAUDE_CODE_ALWAYS_ENABLE_EFFORT` | Set to `1` to send the [effort](model-config.md#adjust-effort-level) parameter with every request, even when Claude Code does not recognize the model ID as effort-capable. Use this when routing through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) or third-party provider that serves models under custom identifiers. Models that reject the effort parameter at the API, including Claude 3 models, Sonnet 4.0 and 4.5, Opus 4.0 and 4.1, and Haiku 4.5, are still excluded so requests do not fail |
| `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` | Interval in milliseconds at which credentials should be refreshed (when using [`apiKeyHelper`](settings-reference.md#apikeyhelper)) |
| `CLAUDE_CODE_ARTIFACT_AUTO_OPEN` | Set to `0` to stop Claude Code from opening the browser automatically when a new [artifact](artifacts.md#create-an-artifact) is published |
| `CLAUDE_CODE_ARTIFACT_COMMENTS` | Set to `0` to stop Claude reading and replying to [comments on an artifact](artifacts.md#collect-comments-on-an-artifact). Has no effect when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` has [turned artifacts off](artifacts.md#availability). Requires Claude Code v2.1.221 or later |
| `CLAUDE_CODE_ARTIFACT_COMMENTS_AUTOREACT` | Set to `0` to stop Claude [replying on its own to comments sent to it](artifacts.md#let-claude-reply-to-comments-on-its-own). Requires Claude Code v2.1.228 or later |
| `CLAUDE_CODE_ATTRIBUTION_HEADER` | Set to `0` to omit the [attribution block](../13-Enterprise-Admin/llm-gateway-protocol.md#system-prompt-attribution-block), which carries the client version and a prompt fingerprint, from the start of the system prompt. Caching on a direct connection to the Anthropic API is unaffected either way. In some direct-connection setups, Claude Code keeps the block on [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) classifier requests even when you set `0`. In [System prompt attribution block](../13-Enterprise-Admin/llm-gateway-protocol.md#system-prompt-attribution-block), check which connections and credentials this covers. Before v2.1.181 the block included a per-request token on custom base URLs and Microsoft Foundry connections, so on those versions set it to `0` when your LLM gateway caches on the request body or forwards requests to a third-party provider, or when you connect to Microsoft Foundry directly |
| `CLAUDE_CODE_AUTO_BACKGROUND_WORKER_CHECKIN_SECONDS` | When `CLAUDE_AUTO_BACKGROUND_TASKS` is enabled, seconds between reminders to Claude to check on [background subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) that are still running. Accepts a plain integer from `1` to `86400` only; any other value or spelling reads as unset. When unset, there are no check-in reminders. Requires Claude Code v2.1.248 or later |
| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Set the [auto-compact window](model-config.md#set-the-auto-compact-window) in tokens, from `100000` to `1000000`. Accepts a plain integer such as `500000` only: a value like `500k` reads as `500` and clamps to the 100K minimum. The effective window is also capped at the model’s context window. Takes precedence over the `/autocompact` command, the `--autocompact` flag, and the `autoCompactWindow` setting. The status line’s `used_percentage` always measures against the model’s full context window, so once this variable is set, that percentage no longer indicates when compaction will run |
| `CLAUDE_CODE_AUTO_CONNECT_IDE` | Override automatic [IDE connection](../03-IDE-Integrations/vs-code.md). 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`](settings-reference.md#autoconnectide) global config setting |
| `CLAUDE_CODE_AUTO_MODE_SERVER` | Controls whether Claude Code asks the server to [review auto mode actions](permission-modes.md#server-side-classifier-review). Set to `0` to use Claude Code’s own classifier requests instead. On a direct connection to the Anthropic API, requires v2.1.281 or later. The linked section lists which sessions ask the server when the variable is unset, and from which version. Requires Claude Code v2.1.271 or later |
| `CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS` | Time in milliseconds Claude Code waits for the AWS default credential provider chain to produce credentials before the request fails with [`AWS default-chain credential resolve timed out`](errors.md#aws-default-chain-credential-resolve-timed-out) (default: `60000`). Raise it when a step in your chain legitimately needs longer, such as a browser-based SSO sign-in with MFA through a wrapper like `aws-vault`. Applies wherever Claude Code signs with the default chain: [Amazon Bedrock](amazon-bedrock.md#credential-caching-and-resolution-timeout), [Claude Platform on AWS](claude-platform-on-aws.md), and the [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint). Requires Claude Code v2.1.207 or later |
| `CLAUDE_CODE_BASH_EDIT_DIFF` | Set to `0` to turn off the [diff of the files that changed while a Bash command ran](../07-Hooks/hooks.md#bash), or `1` to record it in every permission mode. Takes precedence over the [`bashEditDiffEnabled`](settings-reference.md#basheditdiffenabled) setting. Requires Claude Code v2.1.269 or later |
| `CLAUDE_CODE_BG_TASKS_REPORT_RUNNING` | Set to `0` to make a non-interactive session report an idle status to its host at every turn end, even while background work is still running. By default, the session keeps reporting a running status past turn end while background work such as a background agent or a [workflow](workflows.md) run is still live. This keeps a host that watches the status, such as a remote session list, from announcing that Claude is waiting for your input mid-work. Background shell commands, such as a dev server, don’t hold the running status. The running-status default and the `0` opt-out require Claude Code v2.1.269 or later; on earlier versions, set `1` to hold the running status |
| `CLAUDE_CODE_BRIDGE_SESSION_ID` | Set automatically in Bash tool and [hook command](../07-Hooks/hooks.md) subprocesses while the session has an active [Remote Control](remote-control.md) connection, and removed when the connection ends. The value is the session’s ID in `session_` form, the same identifier that appears in the session’s `claude.ai/code` URL, so a script can link back to the session that ran it. Requires Claude Code v2.1.199 or later. In [cloud sessions](claude-code-on-the-web.md), read `CLAUDE_CODE_REMOTE_SESSION_ID` instead |
| `CLAUDE_CODE_BS_AS_CTRL_BACKSPACE` | Set to `0` to make Claude Code read the `0x08` byte, also written `^H`, as plain Backspace, or `1` to read it as Ctrl+Backspace. Either value replaces the platform default. By default, Claude Code reads it as Ctrl+Backspace on Windows, except when `TERM_PROGRAM` is `mintty` or `TERM` is `cygwin`, and as plain Backspace on macOS and Linux. Set `0` in a Windows terminal where [Backspace deletes a whole word](terminal-config.md#fix-backspace-deleting-a-whole-word-on-windows) |
| `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, read only on runtimes with `tls.getCACertificates`: the native binary, or Node 22.15 or later for npm installs. See [CA certificate store](../13-Enterprise-Admin/network-config.md#ca-certificate-store). Default is `bundled,system` |
| `CLAUDE_CODE_CHILD_SESSION` | Set to `1` in subprocesses Claude Code spawns via the Bash, PowerShell, and Monitor tools, [hook](../07-Hooks/hooks.md) commands, and [status line](statusline.md) commands. Not set for stdio [MCP server](../06-MCP-Tools/General/mcp.md) subprocesses, which are long-lived and outlive the session that spawned them. Unlike `CLAUDECODE`, this is only set by Claude Code itself when it launches a subprocess and not by IDE extensions, so it reliably distinguishes a nested session from a top-level `claude` launched in an IDE-integrated terminal. A nested interactive `claude` TUI started this way is automatically excluded from `--resume`, `--continue`, up-arrow history, and the `claude agents` list. Non-interactive `claude -p` sessions still persist. Set `CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1` to override this exclusion. Requires Claude Code v2.1.172 or later |
| `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_CONNECT_TIMEOUT_MS` | Removed in v2.1.186 and now a no-op. Previously set a separate timeout for the connect, TLS, and response-header phase of a streaming API request. Use `API_TIMEOUT_MS` for the per-request timeout. For the response-header phase of a streaming request, see `CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS` |
| `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`](cli-reference.md#cli-flags) 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](model-config.md#extended-context) support. When set, 1M model variants are unavailable in the model picker, and Claude Code holds sessions on models with a native 1M window, such as [Sonnet 5.5](model-config.md#sonnet-5-5-and-sonnet-5-context-window) and the Fable models, to a 200K window; see [Extended context](model-config.md#extended-context) for how the hold is enforced. Useful for enterprise environments with compliance requirements. For its role in correcting the window for an unrecognized `[1m]` model ID, see [Correct the window for a gateway or custom model ID](model-config.md#correct-the-window-for-a-gateway-or-custom-model-id) |
| `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` | Set to `1` to disable [adaptive reasoning](model-config.md#adjust-effort-level) 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 [Fable models](model-config.md#extended-thinking), Sonnet 5 and later, or Opus 4.7 and later, which always use adaptive reasoning |
| `CLAUDE_CODE_DISABLE_ADMIN_ENV_UNION` | Set to `1` to stop Claude Code from merging [managed settings](../13-Enterprise-Admin/managed-settings.md#precedence-within-the-managed-tier) `env` blocks per key across admin sources, so only the highest-priority source’s whole `env` block applies, as before v2.1.223. Set it in the environment that launches Claude Code, since Claude Code ignores a copy delivered through a settings `env` block. Requires Claude Code v2.1.223 or later |
| `CLAUDE_CODE_DISABLE_ADVISOR_TOOL` | Set to `1` to disable the [advisor tool](advisor.md). The `/advisor` command becomes unavailable, any configured `advisorModel` is ignored, and the `--advisor` flag is accepted but has no effect, so existing scripts that pass it continue to work without errors |
| `CLAUDE_CODE_DISABLE_AGENT_VIEW` | Set to `1` to turn off [background agents and agent view](../09-Agents-Patterns/agent-view.md): `claude agents`, `--bg`, `/background`, and the on-demand supervisor. Equivalent to the [`disableAgentView`](settings-reference.md#disableagentview) setting |
| `CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN` | Set to `1` to disable [fullscreen rendering](fullscreen.md) 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`](settings-reference.md#tui) setting. You can also switch with `/tui default`. Does not apply to background sessions opened from [agent view](../09-Agents-Patterns/agent-view.md), which always use fullscreen rendering |
| `CLAUDE_CODE_DISABLE_ARTIFACT` | Set to `1` to turn off the [Artifact](artifacts.md) tool, which publishes session output as a private web page on claude.ai. Once you set it, no settings file turns the tool back on. To turn the tool off from a settings file instead, set [`enableArtifact`](settings-reference.md#enableartifact) to `false`; the deprecated [`disableArtifact`](settings-reference.md#disableartifact) key also turns it off |
| `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](memory.md#auto-memory). Set to `0` to force auto memory on even when `--bare` mode or [`autoMemoryEnabled: false`](settings-reference.md#automemoryenabled) 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_BEDROCK_CONTENT_TYPE_DEFAULT` | Set to `1` to stop Claude Code from treating an [Amazon Bedrock](amazon-bedrock.md) streaming response with a missing or empty `Content-Type` header as Amazon Bedrock’s binary event stream. By default, Claude Code assumes a gateway dropped the header from an otherwise unmodified response, so it decodes the body and streaming keeps working. Set this only for a gateway that also re-emits the stream as server-sent events; Claude Code then reads the header-less body as server-sent events instead. Requires Claude Code v2.1.239 or later |
| `CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD` | Set to `1` to skip the check that an [Amazon Bedrock](amazon-bedrock.md) streaming response carries the `application/vnd.amazon.eventstream` content-type. Without this variable, when a response carries a different content-type, Claude Code fails the request with an error naming that type, which means a [gateway or proxy is transforming the response](amazon-bedrock.md#streaming-errors-behind-a-gateway-or-proxy). Configure the gateway to forward the `Content-Type` header and body unmodified rather than setting this variable. Requires Claude Code v2.1.208 or later |
| `CLAUDE_CODE_DISABLE_BG_EXIT_HANDOFF` | Set to `1` to stop a [background session’s](../09-Agents-Patterns/agent-view.md) running background shell commands, dynamic workflows, and, as of v2.1.198, background subagents when the [supervisor](../09-Agents-Patterns/agent-view.md#the-supervisor-process) stops, restarts, or updates that session’s process, instead of handing them to the session’s next process. Affects only that handoff: backgrounding a session with `←` or [`/background`](../09-Agents-Patterns/agent-view.md#from-inside-a-session) still carries in-flight work over, and `CLAUDE_DISABLE_ADOPT` turns off both. Requires Claude Code v2.1.196 or later |
| `CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP` | Set to `1` to stop Claude Code from terminating [background shell commands](interactive-mode.md#background-bash-commands) under memory pressure. By default, on macOS and Linux, Claude Code terminates background shells when the operating system reports critical memory pressure and the session has been idle for 30 minutes with no turn or subagent running. Windows has no memory-pressure signal, so this variable has no effect there. Requires Claude Code v2.1.193 or later |
| `CLAUDE_CODE_DISABLE_BUNDLED_SKILLS` | Set to `1` to disable the [skills](../08-Plugins-Skills/skills.md) and workflows included with Claude Code: bundled skills and workflows are removed entirely, while built-in commands like `/init` stay typable but are hidden from the model. `/doctor` stays typable like the built-in commands; hide it with `DISABLE_DOCTOR_COMMAND` instead. Skills from plugins, `.claude/skills/`, and `.claude/commands/` are unaffected. Equivalent to the [`disableBundledSkills`](settings-reference.md#disablebundledskills) setting |
| `CLAUDE_CODE_DISABLE_CFC_PROMPT` | Set to `1` to keep the [Claude in Chrome](../03-IDE-Integrations/chrome.md) browser tools available while omitting the Chrome section of the system prompt and the `/claude-in-chrome` [bundled skill](../08-Plugins-Skills/skills.md#bundled-skills). For hosts that embed Claude Code and supply their own browser guidance. Requires Claude Code v2.1.257 or later |
| `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](scheduled-tasks.md). 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_DANGEROUS_RM_TIMEOUT` | Set to `1` to turn off the time limit on [critical-path removal](permission-modes.md#critical-paths) prompts. In `auto` mode Claude Code then sends these removals to the classifier instead, and in `bypassPermissions` mode the prompt waits for your answer. Set it in the environment that launches Claude Code, since Claude Code ignores a copy delivered through a settings `env` block. Requires Claude Code v2.1.281 or later |
| `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. [MCP tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is disabled and all MCP tools load upfront, even when you set `ENABLE_TOOL_SEARCH`. On Claude Code v2.1.227 or later, [managed settings](../13-Enterprise-Admin/managed-settings.md) can keep tool search on. [Disable pre-release capabilities](../13-Enterprise-Admin/llm-gateway-protocol.md#disable-pre-release-capabilities) covers where the override applies |
| `CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS` | Set to `1` to disable the built-in [Explore and Plan subagents](../09-Agents-Patterns/sub-agents.md#built-in-subagents). Claude explores with its search tools or the general-purpose subagent instead, and [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) reads files directly rather than launching Explore and Plan agents. Custom subagents named `Explore` or `Plan` are unaffected. To remove every built-in subagent type in the Agent SDK or non-interactive mode, use `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` instead. Requires Claude Code v2.1.198 or later |
| `CLAUDE_CODE_DISABLE_FAST_MODE` | Set to `1` to disable [fast mode](fast-mode.md) |
| `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`](settings-reference.md#feedbacksurveyrate) setting. See [Session quality surveys](../13-Enterprise-Admin/data-usage.md#session-quality-surveys) |
| `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING` | Set to `1` to disable file [checkpointing](checkpointing.md). The `/rewind` command will not be able to restore code changes. Overrides the [`fileCheckpointingEnabled`](settings-reference.md#filecheckpointingenabled) setting |
| `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 context. Useful when using your own git workflow skills. Takes precedence over the [`includeGitInstructions`](settings-reference.md#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 Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry |
| `CLAUDE_CODE_DISABLE_MOUSE` | Set to `1` to disable mouse tracking in [fullscreen rendering](fullscreen.md). Keyboard scrolling with `PgUp` and `PgDn` still works. Use this to keep your terminal’s native copy-on-select behavior |
| `CLAUDE_CODE_DISABLE_MOUSE_CLICKS` | Set to `1` to disable click, drag, and hover handling in [fullscreen rendering](fullscreen.md) while keeping mouse-wheel scrolling. Use this when you want wheel scroll to work inside Claude Code but don’t want clicks to position the cursor, expand tool output, or open links. `CLAUDE_CODE_DISABLE_MOUSE` takes precedence when both are set. Requires Claude Code v2.1.195 or later |
| `CLAUDE_CODE_DISABLE_MTLS_RELOAD_ON_STALE_CONNECTION` | Set to `1` to stop Claude Code from re-reading the [mTLS client certificate and key](../13-Enterprise-Admin/network-config.md#mtls-authentication) when an API request fails with a connection-level error, such as a connection reset or a TLS handshake error. With the reload disabled, Claude Code loads rotated files only when it next applies settings or at the next startup. Requires Claude Code v2.1.232 or later |
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | Set to any non-empty value, such as `1`, to disable nonessential network traffic: auto-updates, telemetry, error reporting, the `/feedback` command, [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior), release notes, the [PR and MR status badge](interactive-mode.md#pr-review-status) checks, and availability checks such as the [fast mode](fast-mode.md#use-fast-mode-behind-proxies-and-llm-gateways) check. It also stops the [background runs of plugin `command` sources](../08-Plugins-Skills/plugins-loading.md#when-a-command-source-re-runs), which are local commands rather than network traffic, because they can trigger dependency installs. **Setting it to `0` or `false` still disables this traffic**, unlike most on/off variables; unset the variable to allow it again. Also disables feature-flag fetching, which makes [Remote Control](remote-control.md#requirements) and the other [features that need feature-flag fetching](#features-that-need-feature-flag-fetching) unavailable. Official plugin marketplace auto-install isn’t covered; disable it with `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL`. Doesn’t affect [gateway model discovery](../13-Enterprise-Admin/llm-gateway-connect.md#add-gateway-models-to-the-model-picker), which has its own opt-in |
| `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_NOTIFICATION_PRESENCE_CHECK` | Set to `1` to send the `PushNotification` tool’s desktop notification even while you are typing in or focused on the terminal. By default the tool skips both the desktop notification and the [mobile push](remote-control.md#mobile-push-notifications) when it detects recent keyboard activity or terminal focus. This variable disables only that local check, so the server can still suppress the mobile push when it detects that you are active. Requires Claude Code v2.1.193 or later |
| `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` | Set to `1` to disable automatic registration of the official plugin marketplace. Claude Code reads the variable when it is about to register the marketplace, usually during a machine’s first interactive launch. If the variable is set at that point, Claude Code skips the registration permanently. Unsetting the variable later doesn’t undo the skip. Run `claude plugin marketplace add anthropics/claude-plugins-official` to register the marketplace at any time |
| `CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS` | Set to `1` to stop Claude Code from running your [`Notification` hooks for unanswered permission requests](../07-Hooks/hooks.md#notification) in sessions where Claude Code sends them to the Agent SDK’s `canUseTool` callback, which is how Claude Desktop and the VS Code extension host Claude Code. Has no effect in terminal sessions. Requires Claude Code v2.1.233 or later |
| `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_POWERSHELL_CMD_RM_DENY` | Set to `1` to turn off the [PowerShell tool](tools-reference.md#powershell-tool) check that denies the `cmd` built-ins `rd`, `rmdir`, `del`, and `erase` on a [system path](permission-modes.md#remove-item-in-powershell), such as a drive root or your home directory. Claude Code ignores this variable in a settings file’s `env` block. Requires Claude Code v2.1.283 or later |
| `CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT` | Set to `1` to turn off the [critical-path](permission-modes.md#critical-paths) check for a recursive `rm` whose target is entirely the output of a command substitution, such as `rm -rf "$(pwd)"`. The other critical-path checks keep running. Set it in the environment that launches Claude Code, since Claude Code ignores a copy delivered through a settings `env` block. Requires Claude Code v2.1.281 or later |
| `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` | Set to `1` to disable automatic terminal title updates based on conversation context. This also skips the background small/fast-model request that [generates a session title](sessions.md#name-your-sessions) |
| `CLAUDE_CODE_DISABLE_THINKING` | Set to `1` to omit the `thinking` parameter from API requests entirely. This is a compatibility option for proxies and gateways that reject the parameter. On models that think by default, omitting the parameter means the model may still think. To explicitly disable [extended thinking](../04-API-Reference/Guides/build-with-claude-extended-thinking.md) on the Anthropic API, use `MAX_THINKING_TOKENS=0` instead. Neither variable turns thinking off on Opus 5.5, Sonnet 5.5, or the Fable models, which can’t have thinking turned off. On [third-party providers](third-party-integrations.md), `MAX_THINKING_TOKENS=0` likewise omits the parameter, so the two variables behave the same there |
| `CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT` | Set to `1` to skip proactive [auto-compaction](../17-Billing-Plans/costs.md#reduce-token-usage) when Claude Code doesn’t recognize the model ID, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) alias. Without this variable, Claude Code compacts at the context window it assumes for the ID. `CLAUDE_CODE_MAX_CONTEXT_TOKENS` can correct the assumed window instead; see [Correct the window for a gateway or custom model ID](model-config.md#correct-the-window-for-a-gateway-or-custom-model-id) for when each variable applies. Requires Claude Code v2.1.223 or later |
| `CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL` | Set to `1` to disable virtual scrolling in [fullscreen rendering](fullscreen.md) and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear |
| `CLAUDE_CODE_DISABLE_WINDOWS_SHELL_LAUNCHER` | Set to `1` to start [PowerShell tool](tools-reference.md#powershell-tool) commands on Windows directly instead of through the `cmd.exe` launcher. By default, the launcher lets a PowerShell command [running in the background](tools-reference.md#background-commands) [carry over to the session’s next process](../09-Agents-Patterns/agent-view.md#the-supervisor-process), such as when you [background the session](../09-Agents-Patterns/agent-view.md#from-inside-a-session). If you set the variable, a backgrounded PowerShell command stops when the session’s process exits. Bash commands aren’t affected. Requires Claude Code v2.1.269 or later |
| `CLAUDE_CODE_DISABLE_WORKFLOWS` | Set to `1` to disable [workflows](workflows.md#turn-workflows-off). Equivalent to the [`disableWorkflows`](settings-reference.md#disableworkflows) setting |
| `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`, `/effort`, and the `modelSettings` and `effortLevel` settings. A [`maxEffortLevel`](settings-reference.md#maxeffortlevel) cap still applies. See [Adjust effort level](model-config.md#adjust-effort-level) |
| `CLAUDE_CODE_ENABLE_AUTO_MODE` | Accepted for compatibility with older releases and has no effect. Auto mode is available by default on every provider, including Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and signed-in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions. In v2.1.158 through v2.1.206, setting this to `1` was required to make [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) available on those providers |
| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](interactive-mode.md#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](settings-reference.md#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](headless.md) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](prompt-caching.md) 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](../13-Enterprise-Admin/monitoring-usage.md) 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 Amazon Bedrock and Google Cloud’s Agent Platform, 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 Microsoft Foundry and [gateway](../13-Enterprise-Admin/llm-gateway.md) 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 an [`availableModels`](settings-reference.md#availablemodels) allowlist the session receives; deliver the list through [MDM or a managed settings file](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms), since [server-managed delivery is not available on gateway configurations](../13-Enterprise-Admin/server-managed-settings.md#platform-availability) |
| `CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE` | Removed in v2.1.142, when the [fast mode](fast-mode.md) default moved from Opus 4.6 to Opus 4.7 |
| `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` | Set to `false` to turn off prompt suggestions, the grayed-out predictions that appear in your prompt input. Takes precedence over the [`promptSuggestionEnabled`](settings-reference.md#promptsuggestionenabled) setting, which is what the **Prompt suggestions** toggle in `/config` writes. Claude Code also [pauses suggestions while your account is close to or at its usage limit](interactive-mode.md#when-claude-code-skips-suggestions). Set to `true` to keep them on until you reach the limit. Requires Claude Code v2.1.238 or later. See [Prompt suggestions](interactive-mode.md#prompt-suggestions) |
| `CLAUDE_CODE_ENABLE_TASKS` | Selects which task-tracking tools Claude Code provides in [sessions that have them](tools-reference.md#task-tool-availability). By default, Claude Code provides the Task tools `TaskCreate`, `TaskUpdate`, `TaskGet`, and `TaskList`. Set to `0` to get the legacy `TodoWrite` tool instead. See [Task list](interactive-mode.md#task-list) |
| `CLAUDE_CODE_ENABLE_TELEMETRY` | Set to `1` to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `CLAUDE_CODE_ENABLE_TODO_TOOLS` | Set to `1` to get the task-tracking tools on every model. Without it, Claude Code provides them by default only on the models listed under [Task tool availability](tools-reference.md#task-tool-availability). `CLAUDE_CODE_ENABLE_TASKS` still selects the Task tools or `TodoWrite`. Requires Claude Code v2.1.233 or later |
| `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](../09-Agents-Patterns/agent-teams.md). 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 doesn’t expose directly. A value exported in your shell also applies to the [background sessions](../09-Agents-Patterns/agent-view.md) you dispatch with `claude agents` or `--bg`. Before v2.1.206, background sessions ignored a shell-exported value and used whatever copy the background supervisor process inherited |
| `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_SESSION_PERSISTENCE` | Set to `1` to force transcript persistence, prompt history, and `claude agents` registration even when this `claude` was launched from inside another Claude Code session. Use when an inherited `CLAUDE_CODE_CHILD_SESSION` value, for example from a `screen` session or a background launcher first started by Claude Code’s Bash tool, causes a genuine top-level session to be misclassified as nested. As of v2.1.178, Claude Code detects the tmux case automatically and ignores the inherited marker, so tmux no longer needs this variable. Also honored on v2.1.169 and earlier; has no effect on v2.1.170 and v2.1.171, where the nested-session detection it overrides was removed |
| `CLAUDE_CODE_FORCE_STRIKETHROUGH` | Set to `1` to force strikethrough rendering for `~~text~~` in Claude’s responses when your terminal supports it but is not auto-detected, such as over SSH without `TERM_PROGRAM` forwarded. Without this, undetected terminals show the literal `~~` markers instead of rendering the text as strikethrough. Requires Claude Code v2.1.186 or later |
| `CLAUDE_CODE_FORCE_SYNC_OUTPUT` | Set to `1` to force-enable DEC private mode 2026 [synchronized output](https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036) 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. Unlike `CLAUDE_CODE_NO_FLICKER`, which switches to [fullscreen rendering](fullscreen.md), this doesn’t change the renderer |
| `CLAUDE_CODE_FORK_SUBAGENT` | Controls [fork mode](../09-Agents-Patterns/sub-agents.md#turn-fork-mode-on-or-off), which lets Claude spawn [forked subagents](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) itself and is on by default in interactive sessions only. Set to `1` to turn it on in `claude -p` and the Agent SDK as well, or `0` to turn it off in every kind of session. You can run `/subtask` whether or not fork mode is on. The interactive default requires Claude Code v2.1.232 or later; on earlier versions, set the variable to `1` to turn fork mode on |
| `CLAUDE_CODE_FORWARD_SUBAGENT_TEXT` | Set to `1` to emit [subagent](../09-Agents-Patterns/sub-agents.md) text and thinking blocks in `claude -p --output-format stream-json` output, the same behavior as the [`--forward-subagent-text`](cli-reference.md#cli-flags) flag. Use the variable when a harness invokes `claude` and can’t pass the flag itself. Unlike the flag, which exits with an error outside non-interactive mode with stream-json output, the variable is ignored there so that nested invocations keep working when it’s set process-wide. Requires Claude Code v2.1.211 or later |
| `CLAUDE_CODE_GATEWAY_HINT_HEADERS` | Set to `1` to send the [gateway hint headers](../13-Enterprise-Admin/llm-gateway-protocol.md#gateway-hint-headers), such as `x-claude-code-request-class` and `x-claude-code-compaction`, on a custom proxy or a third-party provider such as Amazon Bedrock or Claude Platform on AWS. Set to `0` to stop sending them on every connection, including a direct connection to the Anthropic API, where Claude Code sends them by default. Requires Claude Code v2.1.273 or later |
| `CLAUDE_CODE_GATEWAY_MODEL_DISCOVERY_TIMEOUT_MS` | Timeout in milliseconds for the [gateway model discovery](../13-Enterprise-Admin/llm-gateway-protocol.md#model-discovery) request that `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` turns on (default: `3000`). Raise it when your gateway needs longer than three seconds to answer `/v1/models` at startup. Takes plain digits only; `0`, negative values, and other spellings keep the default. Requires Claude Code v2.1.269 or later |
| `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. If the path doesn’t exist or the file isn’t named `bash.exe`, `sh.exe`, `bash`, or `sh`, Claude Code ignores the variable and auto-detects Git Bash as if it were unset, logging a warning visible with `--debug`. Before v2.1.219, Claude Code exited at startup when the path didn’t exist, and used any existing file as the shell without checking that it was bash or sh. See [Windows setup](../01-Getting-Started/setup.md#set-up-on-windows) |
| `CLAUDE_CODE_GLOB_HIDDEN` | Set to `false` to exclude dotfiles from results when Claude invokes the [Glob tool](tools-reference.md#glob-tool-behavior). 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](tools-reference.md#glob-tool-behavior) respect `.gitignore` patterns. By default, Glob returns all matching files including gitignored ones. Does not affect `@` file autocomplete, which has its own [`respectGitignore` setting](settings-reference.md#respectgitignore) |
| `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_GOAL_CHECKIN_MINUTES` | How many minutes background work can keep an active goal waiting before Claude Code [asks Claude to check on it](goal.md#background-work-defers-evaluation). Default `30`. Set `0` to turn check-ins off. Give whole minutes in plain digits, at most `10080`, which is one week. Claude Code treats any other value as unset and uses the default. Requires Claude Code v2.1.234 or later |
| `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` | Set to `1` to skip auto-installation of IDE extensions. Equivalent to setting [`autoInstallIdeExtension`](settings-reference.md#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_CONCURRENT_SUBAGENTS` | How many [subagents](../09-Agents-Patterns/sub-agents.md#concurrent-subagent-limit) can be running in one session before the Agent tool refuses to spawn another (default: 20). Accepts a positive whole number in plain digits; anything else is ignored, so the variable can adjust the cap but can’t disable it. Requires Claude Code v2.1.217 or later |
| `CLAUDE_CODE_MAX_CONTEXT_TOKENS` | Override the context window size Claude Code assumes for the active model. As of v2.1.193, how it applies depends on how Claude Code resolves the model ID; see [Correct the window for a gateway or custom model ID](model-config.md#correct-the-window-for-a-gateway-or-custom-model-id). 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_MCP_DESCRIPTION_LENGTH` | Maximum length in characters of each MCP tool description and each MCP server’s instructions that Claude Code sends to the model (default: 2048). Claude Code [truncates longer text](../06-MCP-Tools/General/mcp.md#for-mcp-server-authors). Accepts a positive whole number in plain digits. Anything else is ignored and the default applies. Requires Claude Code v2.1.280 or later |
| `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](../20-Models/about-claude-models-overview.md#latest-models-comparison). Claude Code lowers a value above a model’s cap to the cap. For a model ID Claude Code can’t resolve to a model it knows, the default is 32000 and the cap is 128000. Increasing this value reduces the effective context window available before [auto-compaction](../17-Billing-Plans/costs.md#reduce-token-usage) triggers |
| `CLAUDE_CODE_MAX_RETRIES` | Override the number of times to retry failed API requests (default: 10). Capped at 15 as of v2.1.186; as of v2.1.199, `CLAUDE_CODE_RETRY_WATCHDOG` raises the default and removes the cap. For unattended sessions that need to wait through longer outages, set `CLAUDE_CODE_RETRY_WATCHDOG` instead |
| `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION` | Removed in v2.1.224 and now a no-op. Previously capped the total number of [subagents](../09-Agents-Patterns/sub-agents.md) Claude could spawn with the Agent tool in one session (default: 200); spawning past the cap failed with `Subagent spawn limit reached`. The [concurrent subagent limit](../09-Agents-Patterns/sub-agents.md#concurrent-subagent-limit) and the [depth limit](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents) still apply |
| `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` | Number of [subagent layers](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents) allowed below the main conversation (default: 3). At the default, subagents can spawn their own subagents, and a subagent at the third layer can’t spawn further; set `1` to turn nesting off. In v2.1.217 through v2.1.218, the default was 1, so a subagent couldn’t spawn its own unless you raised the limit; v2.1.219 raised the default to 3. Accepts a positive whole number in plain digits; anything else is ignored, so the limit can be adjusted but not removed. Requires Claude Code v2.1.217 or later |
| `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`](cli-reference.md#cli-flags), 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_MAX_WEB_SEARCHES_PER_SESSION` | Cap on the total number of [WebSearch](tools-reference.md#websearch-tool-behavior) calls one session can make (default: 200). When Claude reaches the cap, further WebSearch calls return a notice telling it to continue with the information it already gathered. Accepts a positive whole number with no upper bound. Anything else is ignored and the default applies, so the cap can be raised but not turned off. Requires Claude Code v2.1.212 or later |
| `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_MCP_AUTO_BACKGROUND_MS` | Elapsed time in milliseconds before a still-running MCP tool call [moves to a background task](../06-MCP-Tools/General/mcp.md#automatic-backgrounding-of-long-tool-calls) (default: 120000, or 2 minutes). Set to `0` to turn automatic backgrounding off. Requires Claude Code v2.1.212 or later |
| `CLAUDE_CODE_MCP_STARTUP_WAIT_MS` | How long in milliseconds the first turn of a [non-interactive](headless.md) session waits for MCP servers that are still connecting, in place of the default [first-turn wait](../05-Agent-SDK/agent-sdk-mcp.md#connection-timing). When set, the wait covers every pending server. Set to `0` to skip the wait. A [`--permission-prompt-tool`](cli-reference.md#cli-flags) server keeps its own `MCP_TIMEOUT` wait regardless of the value. Requires Claude Code v2.1.274 or later |
| `CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT` | Idle timeout in milliseconds for MCP tool calls. When a stdio, HTTP, SSE, WebSocket, or [claude.ai connector](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) MCP server sends no response and no progress notification for this long, the tool call aborts with an error instead of waiting for the overall `MCP_TOOL_TIMEOUT`. Overrides the per-transport defaults of 300000 (5 minutes) for network servers and 1800000 (30 minutes) for stdio servers. Set to `0` to disable the idle check. Values below 1000 are raised to one second, and the value is capped at the effective `MCP_TOOL_TIMEOUT`. A per-server `timeout` in `.mcp.json` of at least 1000 raises that server’s idle window to at least the `timeout` value. Doesn’t apply to IDE servers or SDK in-process servers. Requires Claude Code v2.1.187 or later. Before v2.1.203, stdio servers were exempt from the idle timeout |
| `CLAUDE_CODE_MESSAGING_SOCKET` | Set by Claude Code, not by you: in sessions that bind an [inbox socket](cross-session-messaging.md#the-sessions-inbox-socket), Claude Code exports that socket’s path to hooks and Bash commands when it binds the socket. In a session that starts with messaging on, Claude Code binds the socket before any hook runs. Other sessions on the machine deliver messages to this path. Each session exports its own socket rather than one inherited from a parent, and messages arriving on it go through the session’s [inbound controls](cross-session-messaging.md#control-inbound-messages). Settings `env` blocks can’t set it. Requires Claude Code v2.1.224 or later |
| `CLAUDE_CODE_MESSAGING_TOKEN` | Set by Claude Code, not by you: in sessions that bind an [inbox socket](cross-session-messaging.md#the-sessions-inbox-socket), Claude Code exports this per-session token to hooks and Bash commands alongside `CLAUDE_CODE_MESSAGING_SOCKET`. A script posting to the socket can send `{"type":"auth","token":"<token>"}` as its first line to prove it belongs to the session. On native Windows, Claude Code requires this line and closes any connection that doesn’t open with a valid one. The [own-child rules](cross-session-messaging.md#the-sessions-inbox-socket) say when Claude Code consults the token. Each session exports its own token, never one inherited from a parent session. Settings `env` blocks can’t set it. Requires Claude Code v2.1.228 or later |
| `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_NONBLOCKING_STDOUT` | Set to `1` to write terminal output through a second non-blocking file descriptor, so a terminal that stops reading, such as a paused tmux control-mode pane or a stalled SSH connection, can’t freeze Claude Code mid-session. Applies on macOS, Linux, and WSL when stdout is a terminal. Requires Claude Code v2.1.261 or later |
| `CLAUDE_CODE_NO_FLICKER` | Set to `1` to enable [fullscreen rendering](fullscreen.md), a research preview that reduces flicker and keeps memory flat in long conversations. Overrides the [`tui`](settings-reference.md#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` is used for non-interactive enterprise sign-in. Requires `CLAUDE_CODE_OAUTH_SCOPES`. Intended for enterprise admin provisioning only |
| `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`](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token). Unless you run [`/login`](../13-Enterprise-Admin/iam.md#authentication-precedence), Claude Code uses the token you set for the whole session. To replace an expired token, generate a new one and restart |
| `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE` | Removed in v2.1.160 and now a no-op. Previously pinned [fast mode](fast-mode.md) to Claude Opus 4.6 instead of the current default. Opus 4.6 no longer supports fast mode |
| `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` | Maximum length of content-bearing OpenTelemetry attributes (model responses, tool content, system prompts, raw API bodies), truncation marker included, in UTF-16 code units (default: 61440, i.e. 60 KB). Raise it only if your telemetry backend accepts attribute values larger than 64 KB, or lower it to cut telemetry volume. Requires Claude Code v2.1.214 or later. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `CLAUDE_CODE_OTEL_DIAG_STDERR` | Set to `1` to write OpenTelemetry exporter diagnostic errors to stderr. By default these errors only appear with `--debug`, so a misconfigured exporter such as a Prometheus port collision otherwise fails silently. Requires Claude Code v2.1.179 or later. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS` | Timeout in milliseconds for flushing pending OpenTelemetry spans (default: 5000). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic OpenTelemetry headers in milliseconds (default: 1740000 / 29 minutes). See [Dynamic headers](../13-Enterprise-Admin/monitoring-usage.md#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](../13-Enterprise-Admin/monitoring-usage.md) |
| `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](../01-Getting-Started/setup.md#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_DIRS` | Plugin directories to load for the session, each loaded the way a [`--plugin-dir`](../08-Plugins-Skills/plugins-cli-reference.md#flags-that-load-a-plugin-for-one-session) flag loads it. Separate multiple paths with `:` on Unix or `;` on Windows. Give each path as an absolute path or start it with `~`, because Claude Code skips relative paths. Requires Claude Code v2.1.280 or later. See [Load a plugin for one session](../08-Plugins-Skills/plugins-create.md#load-a-directory-or-archive-for-one-session) |
| `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS` | Timeout in milliseconds for cloning or refreshing a plugin marketplace (default: 120000). Increase this value for large repositories or slow network connections. See [Git clone timed out](../08-Plugins-Skills/plugins-troubleshooting.md#git-clone-timed-out-after-120s) |
| `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE` | Set to `1` to skip the re-clone attempt and keep using the existing marketplace checkout when a marketplace refresh can’t reach or authenticate to the remote. Useful in offline or airgapped environments where re-cloning would fail the same way. See [Marketplace updates fail in offline environments](../08-Plugins-Skills/plugins-troubleshooting.md#marketplace-updates-keep-failing-offline) |
| `CLAUDE_CODE_PLUGIN_PREFER_HTTPS` | Set to `1` to clone GitHub `owner/repo` shorthand sources over HTTPS instead of SSH. Applies to plugin install and update, and to `/plugin marketplace add` and `update`. 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](../08-Plugins-Skills/plugins-org.md#seed-containers-and-ci) |
| `CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY` | Set to `1` to stop Claude Code from passing `-ExecutionPolicy Bypass` when spawning PowerShell for tool calls, hooks, and status line commands, and respect the machine’s effective execution policy instead. By default Claude Code bypasses execution policy at process scope so `.ps1` scripts and module imports work on default-Restricted Windows installs. Process-scope bypass never overrides Group Policy `MachinePolicy` or `UserPolicy` regardless of this setting |
| `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS` | Ceiling in milliseconds on idle waiting for background subagents and workflows after the final turn in [non-interactive mode](headless.md#background-tasks-at-exit) with the `-p` flag. Idle waiting starts over each time Claude takes a turn to handle a background result. Default: `600000`, or 10 minutes. When idle waiting reaches the ceiling, Claude Code stops waiting for the remaining background tasks and exits. Set to `0` to wait indefinitely. This cap is separate from the five-second grace period that applies to plain background shells. Requires Claude Code v2.1.182 or later |
| `CLAUDE_CODE_PROCESS_WRAPPER` | Launch the processes Claude Code starts from its own binary, such as the background service that hosts [agent view](../09-Agents-Patterns/agent-view.md) sessions, through a corporate launcher given as an argv prefix like `/opt/corp/launcher`. Set it in the `env` block of user or [managed settings](../13-Enterprise-Admin/managed-settings.md), not as a shell export, so the detached background service inherits it; project and local settings can’t set it. Equivalent to the [`processWrapper` setting](settings-reference.md#processwrapper), which requires Claude Code v2.1.210 or later; this variable takes precedence when both are set. The VS Code extension configures its own launcher separately through its `claudeProcessWrapper` setting. Ignored on Windows. See [Run Claude Code behind a corporate launcher](../13-Enterprise-Admin/corporate-launcher.md) for the value format, what the launcher covers, and the contract the launcher must satisfy. Requires Claude Code v2.1.208 or later |
| `CLAUDE_CODE_PROJECT_DIR_NAME` | Set together with `CLAUDE_CONFIG_DIR` to choose the `projects/` directory name Claude Code stores that session’s transcripts and auto memory under, in place of one derived from the working directory path. For example, starting Claude Code with `CLAUDE_CONFIG_DIR=/srv/tenant-a CLAUDE_CODE_PROJECT_DIR_NAME=work claude` stores them under `/srv/tenant-a/projects/work/`. Claude Code ignores this variable when `CLAUDE_CONFIG_DIR` is unset, and reads it only from the environment you start `claude` from, never from a [settings file `env` block](#in-settings-files). See [Name the project directory yourself](sessions.md#name-the-project-directory-yourself). Requires Claude Code v2.1.234 or later |
| `CLAUDE_CODE_PROMPT_CACHE_TTL` | Set `5m` or `1h`, the only values Claude Code accepts, to choose the [prompt cache TTL](prompt-caching.md#cache-lifetime) for the main conversation: your interactive, `-p`, and SDK turns, plus the helpers that run inline with them. Takes precedence over the `promptCacheTtl` setting and over `ENABLE_PROMPT_CACHING_1H`, and `FORCE_PROMPT_CACHING_5M` overrides it. The API bills 1-hour cache writes at a higher rate. Requires Claude Code v2.1.242 or later |
| `CLAUDE_CODE_PROPAGATE_TRACEPARENT` | Set to `1` to propagate W3C trace context when `ANTHROPIC_BASE_URL` points at a custom proxy. Propagation covers the `traceparent` header on model and HTTP MCP requests and the `TRACEPARENT` environment variable for Bash, PowerShell, and hook subprocesses. By default, propagation is enabled only when connected directly to the Anthropic API. Added in v2.1.152. See [Traces (beta)](../13-Enterprise-Admin/monitoring-usage.md#traces-beta) |
| `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST` | Set by host platforms that embed Claude Code and manage model provider routing on its behalf. When set, Claude Code ignores provider-selection, endpoint, and authentication variables such as `CLAUDE_CODE_USE_BEDROCK`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_API_KEY` in settings files, so user settings can’t override the host’s routing. Claude Code also ignores model-selection keys such as `model`, `fallbackModel`, and `modelOverrides` in [managed settings](../13-Enterprise-Admin/managed-settings.md), whichever managed source delivers them, so the host’s model configuration takes precedence over an out-of-date managed model pin. Claude Code also ignores model-selection variables such as `ANTHROPIC_MODEL` and the `ANTHROPIC_DEFAULT_*_MODEL` family in a managed `env` block; an [`availableModels`](model-config.md#restrict-model-selection) allowlist in managed settings still applies unless the host supplies its own. Claude Code also skips the automatic telemetry opt-out it otherwise applies on third-party providers such as Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry, so telemetry follows the standard `DISABLE_TELEMETRY` opt-out. See [Default behaviors by API provider](../13-Enterprise-Admin/data-usage.md#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](claude-code-on-the-web.md). Read this from a hook or setup script to detect whether you are in a cloud session |
| `CLAUDE_CODE_REMOTE_SESSION_ID` | Set automatically in [cloud sessions](claude-code-on-the-web.md) to the current session’s ID. Read this to construct a link back to the session transcript. See [Link output back to the session](cloud-environments.md#link-output-back-to-the-session) |
| `CLAUDE_CODE_RESTRICTED` | Set to `1` to start the session in restricted mode, the same as passing [`--restricted`](cli-reference.md#cli-flags). Claude Code ignores this variable in a settings file’s `env` block. Requires Claude Code v2.1.248 or later |
| `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. To turn this off, unset the variable or set it to `0`. Before v2.1.221, Claude Code ignored `0` and other falsy values, so setting `0` still triggered the resume in non-interactive mode and unsetting the variable was the only way to turn it off |
| `CLAUDE_CODE_RESUME_INTERRUPTED_TURN_MAX_AGE_MS` | Maximum age in milliseconds of the last transcript message for a session that ended mid-turn to continue automatically on resume. When the last message is older than this bound, Claude Code skips the `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` automatic resume and its `CLAUDE_CODE_RESUME_PROMPT` continuation message, and the session starts idle so you continue explicitly. Unset or `0` means no bound, except that a turn whose last request failed with an API error resumes only while that error is less than six hours old. A positive value bounds every turn, including those; a negative or non-numeric value applies a one-hour bound. Spawn scripts for long-running agents can set this so a restart against an old transcript doesn’t re-run a stale prompt. Claude Code sets a one-hour bound itself when it restarts a crashed [agent view](../09-Agents-Patterns/agent-view.md) session that inherited its conversation from an interactive session. Requires Claude Code v2.1.211 or later |
| `CLAUDE_CODE_RESUME_PROMPT` | Override the continuation message Claude Code sends to Claude when `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` continues an interrupted turn instead of resending its prompt, or when you resume a [deferred tool call](../07-Hooks/hooks.md#defer-a-tool-call-for-later) with `-p`. Defaults to `Continue from where you left off.`. An empty string uses the default |
| `CLAUDE_CODE_RETRY_WATCHDOG` | Set to `1` for unattended sessions such as eval harnesses, CI jobs, or remote workers. Retries `429` and `529` capacity errors indefinitely instead of failing after `CLAUDE_CODE_MAX_RETRIES` attempts. Claude Code fails at once when a standard-speed request gets a `429` that reports a spend limit or exhausted usage credits, even one from a [gateway spend cap](errors.md#spend-limit-reached) that resets on a schedule. Before v2.1.239, the watchdog retried these indefinitely. For fast mode requests, see [Handle rate limits](fast-mode.md#handle-rate-limits). The watchdog backs off up to 5 minutes between attempts, or until the limit resets when the response carries a rate-limit reset time, so a session that hits a usage limit waits out the remaining window. On v2.1.199 or later it also raises the default retry count for other transient errors, such as server errors, timeouts, and dropped connections, to 300, roughly three hours of backoff, and removes the cap of 15 on `CLAUDE_CODE_MAX_RETRIES` if you set that variable explicitly. Requires Claude Code v2.1.186 or later |
| `CLAUDE_CODE_SAFE_MODE` | Set to `1` to start in safe mode: CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands and agents, output styles, workflows, custom themes, custom keybindings, status line and file-suggestion commands, LSP servers, and auto memory do not load, for troubleshooting a broken configuration. Managed settings policy still applies, including policy-configured hooks, status line, and file-suggestion commands; managed plugins, managed skills, managed CLAUDE.md, and policy-configured MCP servers do not. Equivalent to passing [`--safe-mode`](cli-reference.md#cli-flags). Directly spawned child processes inherit the variable |
| `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](fullscreen.md#mouse-wheel-scrolling). Accepts any positive value up to 20, including fractional values below 1 such as `0.5` to slow accelerated trackpad and wheel scrolling in terminals that already amplify wheel events. 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_SEND_FEEDBACK` | Set to `0` to turn off [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior) for a session. Set to `1` to turn it on where your account already has access; the variable can’t grant access itself, and the other switches that turn feedback off, such as `DISABLE_FEEDBACK_COMMAND` and the [`feedbackDrafts`](settings-reference.md#feedbackdrafts) setting’s `off` value, still apply |
| `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | Override the time budget in milliseconds for [SessionEnd](../07-Hooks/hooks.md#sessionend) hooks. The value is also the timeout for each hook that sets no `timeout` of its own. 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 to the current session ID in Bash and PowerShell tool subprocesses, [hook command](../07-Hooks/hooks.md) subprocesses, and stdio [MCP server](../06-MCP-Tools/General/mcp.md) subprocesses. For Bash, PowerShell, and hooks this matches the `session_id` field in the hook JSON input and is updated on `/clear`. An MCP server subprocess retains the ID it was spawned with. On `--resume <session-id>` it receives the resumed ID, matching hooks and Bash. On `--continue` or `--resume` without an explicit ID it may receive the initial startup ID instead. Use to correlate scripts and external tools with the Claude Code session that launched them |
| `CLAUDE_CODE_SHELL` | Set the shell Claude Code uses to run Bash tool commands. Accepts a path to a `bash` or `zsh` binary, for example `/opt/homebrew/bin/bash`. Other shells such as `fish` are not supported. If the value is not a working `bash` or `zsh` path, Claude Code ignores it and falls back to auto-detection. Auto-detection uses your `$SHELL` when it points to `bash` or `zsh`, otherwise it picks the first working `zsh` then `bash` found on your `PATH` and standard install locations |
| `CLAUDE_CODE_SHELL_PREFIX` | Command prefix that wraps shell commands Claude Code spawns: Bash tool calls, [hook](../07-Hooks/hooks.md) commands, [status line](statusline.md) commands, and stdio [MCP server](../06-MCP-Tools/General/mcp.md) startup commands. PowerShell hooks and exec-form hooks run without the prefix. Useful for logging or auditing. Setting a bare executable path such as `/path/to/logger.sh` runs each command as `/path/to/logger.sh '<command>'`. The wrapper receives the command line as a single shell-quoted argument in `$1`, so the wrapper must re-evaluate `$1` with a shell, for example `exec bash -c "$1"`. Treating `$1` as a bare executable path breaks stdio MCP servers that pass arguments such as `npx -y <package>`. For Bash tool calls, `$1` contains the full shell invocation Claude Code assembles, including environment setup, not only the command Claude ran |
| `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, custom commands, subagents, installed plugins, MCP servers, auto memory, and CLAUDE.md. Skills in a directory you pass with `--add-dir` still load. OAuth tokens and keychain credentials are not read, so Anthropic authentication must come from `ANTHROPIC_API_KEY` or an `apiKeyHelper` in `--settings`. Equivalent to passing [`--bare`](headless.md#start-faster-with-bare-mode) |
| `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](claude-platform-on-aws.md), for gateways that sign requests themselves |
| `CLAUDE_CODE_SKIP_AWS_CRED_CACHE` | Set to `1` to turn off the in-process cache of credentials resolved from the AWS default credential provider chain, so Claude Code resolves the chain on every API request. With the cache off, an SSO-backed profile requests credentials from IAM Identity Center on every request. See [credential caching and resolution timeout](amazon-bedrock.md#credential-caching-and-resolution-timeout). Requires Claude Code v2.1.207 or later |
| `CLAUDE_CODE_SKIP_BEDROCK_AUTH` | Skip AWS authentication for Amazon Bedrock (for example, when using an LLM gateway) |
| `CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS` | Set to `1` to treat a failed [fast mode](fast-mode.md#use-fast-mode-behind-proxies-and-llm-gateways) availability check as available, for networks that block the check’s direct request to `api.anthropic.com`. Claude Code still honors a “disabled by your organization” response |
| `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK` | Set to `1` to skip the client-side [fast mode](fast-mode.md#use-fast-mode-behind-proxies-and-llm-gateways) availability check, for proxies that intercept the check’s request rather than refuse it. The API still rejects fast mode requests when your organization has fast mode disabled |
| `CLAUDE_CODE_SKIP_FOUNDRY_AUTH` | Skip Azure authentication for Microsoft Foundry, for a proxy or gateway that injects its own `Authorization` header. Claude Code sends requests without an Azure credential and preserves the `Authorization` header you supply, for example through `ANTHROPIC_CUSTOM_HEADERS`. Ignored when `ANTHROPIC_FOUNDRY_API_KEY` or `ANTHROPIC_FOUNDRY_AUTH_TOKEN` is set. Before v2.1.203, this variable left the Microsoft Foundry client unable to send requests unless an API key was also set |
| `CLAUDE_CODE_SKIP_MANTLE_AUTH` | Skip AWS authentication for Amazon 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 Google Cloud’s Agent Platform (for example, when using an LLM gateway) |
| `CLAUDE_CODE_STARTUP_FAILURE_RESULTS` | Set to `1` to have a session started with `--output-format stream-json` write a [result message naming why Claude Code refused to start](../05-Agent-SDK/agent-sdk-typescript.md#startup_failure_reason) for startup failures that otherwise end with stderr alone. Requires Claude Code v2.1.274 or later |
| `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP` | Maximum number of consecutive times a [Stop](../07-Hooks/hooks.md#stop) or [SubagentStop](../07-Hooks/hooks.md#subagentstop) hook may block the turn from ending before Claude Code overrides it and ends the turn anyway (default: 8). Set to `0` to disable the cap. Raise this if your hook legitimately needs more iterations to resolve |
| `CLAUDE_CODE_SUBAGENT_MODEL` | The default model for [subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model), [agent team](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) teammates, and [workflow](workflows.md) agents that aren’t assigned a model another way. Accepts an alias such as `haiku` or a full model name. Two sources take precedence over it: a model Claude passes when it spawns the agent, and a `model` field in the agent’s definition, including `inherit`. To change that, set [`CLAUDE_CODE_SUBAGENT_MODEL_FORCE`](../09-Agents-Patterns/sub-agents.md#run-every-subagent-on-one-model). See [Choose a model](../09-Agents-Patterns/sub-agents.md#choose-a-model) for the full order. Setting it to `inherit` is the same as leaving it unset. Before v2.1.251, this variable overrode both the per-invocation model and the definition’s `model` field |
| `CLAUDE_CODE_SUBAGENT_MODEL_FORCE` | Set to `1` to force one model onto subagents, teammates, and workflow agents. [Run every subagent on one model](../09-Agents-Patterns/sub-agents.md#run-every-subagent-on-one-model) says which model that is. Requires Claude Code v2.1.257 or later |
| `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL` | Set `5m` or `1h`, the only values Claude Code accepts, to choose the [prompt cache TTL](prompt-caching.md#cache-lifetime) for requests outside the main conversation, such as [subagents](../09-Agents-Patterns/sub-agents.md), workflows, and background work. Takes precedence over the `subagentPromptCacheTtl` setting and over `ENABLE_PROMPT_CACHING_1H`, and `FORCE_PROMPT_CACHING_5M` overrides it. The API bills 1-hour cache writes at a higher rate. Requires Claude Code v2.1.242 or later |
| `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` | Set to `1` to strip credentials from subprocess environments (Bash tool, hooks, MCP stdio servers): Anthropic and cloud provider credentials, any other variable that Claude Code recognizes as a credential, and credentials embedded in package registry URLs. 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 v2.1.251 or later, the scrub also removes Claude Code’s own configuration-store pointer variables (such as `CLAUDE_CONFIG_DIR`), so a child process cannot locate a relocated configuration directory. Leave the scrub unset if a subprocess needs these variables. 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_SYNC_SKILLS` | Set to `1` in non-interactive mode with the `-p` flag to make Claude Code download the skills enabled for your claude.ai account in that run and wait for the list of them, up to `CLAUDE_CODE_SYNC_SKILLS_WAIT_TIMEOUT_MS`, before it runs the first query. The downloads themselves finish in the background, and Claude waits for a skill’s download when it invokes that skill. Requires claude.ai authentication. Terminal sessions where you sign in with your claude.ai account [download these skills](../08-Plugins-Skills/skills.md#where-synced-skills-load) into `~/.claude/skills/synced/` and resync about every 10 minutes without this variable, so set it only when a `-p` run needs your current skills on its first query. Before v2.1.273, terminal sessions downloaded them only in a `-p` run with this variable set. The `synced` folder name is [reserved for this download](../08-Plugins-Skills/skills.md#where-skills-live). Before v2.1.227, the skills downloaded into `~/.claude/skills/` directly. Claude Code applies [extra rules to the downloaded skills](../08-Plugins-Skills/skills.md#how-synced-skills-behave), such as not running their `!` commands on your machine |
| `CLAUDE_CODE_SYNC_SKILLS_INSTALL_TIMEOUT_MS` | Timeout in milliseconds for the skills resync that runs mid-session when an app built on the [Agent SDK](../05-Agent-SDK/agent-sdk-typescript.md#query-object) reloads skills (default: 30000). When exceeded, the reload continues with whichever skills have arrived, and the remaining downloads finish in the background |
| `CLAUDE_CODE_SYNC_SKILLS_WAIT_TIMEOUT_MS` | Timeout in milliseconds for the first query to wait for the initial skill list when `CLAUDE_CODE_SYNC_SKILLS` is set (default: 5000). When exceeded, the first query runs with whichever skills have arrived. The downloads finish in the background either way, and Claude waits for a skill’s download when it invokes that skill |
| `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`](settings-reference.md#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, in [sessions that have the Task tools](tools-reference.md#task-tool-availability). See [Task list](interactive-mode.md#task-list) |
| `CLAUDE_CODE_TEAM_TEARDOWN_PARK_TIMEOUT_MS` | Override, in milliseconds, how long a non-interactive session waits at exit for its [agent team](../09-Agents-Patterns/agent-teams.md) to finish tearing down. Accepts 1000 to 60000; an out-of-range value is ignored and the default of 10000 applies. Requires Claude Code v2.1.206 or later |
| `CLAUDE_CODE_TMPDIR` | Override the temp directory used for internal temp files. Claude Code appends `/claude-{uid}/` to this path on Unix, or `/claude/` on Windows. Default: `/tmp` on macOS, `os.tmpdir()` on Linux and Windows. On macOS and Linux, [sandboxed](sandboxing.md) Bash subprocesses receive a short fallback `$TMPDIR` under the system default when your override is a long path, since some tools fail when temp paths get too long. Unsandboxed Bash commands inherit your shell’s `$TMPDIR` when it is set. On native Windows, when your shell doesn’t set `$TMPDIR`, a Bash command that references `$TMPDIR` receives your override, or `%TEMP%` when you haven’t set one. Claude Code’s own temp files always use your override. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env) |
| `CLAUDE_CODE_TMUX_TRUECOLOR` | Set to any non-empty value, such as `1`, to allow 24-bit truecolor output inside tmux. **Setting it to `0` or `false` still allows truecolor**, unlike most on/off variables; unset the variable to restore the 256-color clamp. 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](terminal-config.md) for other tmux settings |
| `CLAUDE_CODE_TOOL_MEMORY_CGROUP_EXCLUDE` | On Linux and WSL, set to a comma-separated list of the kinds of processes Claude Code [excludes from the tool memory cap](tools-reference.md#memory-limit-on-linux-and-wsl), such as `mcp` or `lsp`. Set `none` to cap every kind, or `all-new` to cap only Bash, PowerShell, and Monitor tool commands. Claude Code keeps Bash, PowerShell, and Monitor tool commands under the cap whatever you list. Requires Claude Code v2.1.246 or later |
| `CLAUDE_CODE_TOOL_MEMORY_LIMIT` | On Linux and WSL, set to a size such as `4G` to [cap the memory that Bash and PowerShell tool commands can use](tools-reference.md#memory-limit-on-linux-and-wsl), and Monitor tool commands on v2.1.246 or later. Write the size in plain digits, alone for a number of bytes or with a `K`, `M`, `G`, or `T` suffix. Set `0` or `off` to turn the cap off. Once the first process Claude Code starts has turned the cap on or off, a changed value takes effect the next time you launch `claude`. Requires Claude Code v2.1.233 or later |
| `CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS` | Deadline in milliseconds before Claude Code cancels a dialog it forwards to a remote client such as a [Remote Control](remote-control.md) or SDK host, or the approval dialog for a [held cross-session message](cross-session-messaging.md#control-inbound-messages); permission prompts and `AskUserQuestion` questions use their own flows and aren’t governed by it. On Claude Code v2.1.236 or later, it also bounds the mid-session [Fable usage-credits consent prompt](model-config.md#fable-and-usage-credits) in a session that may be running unattended. [Control inbound messages](cross-session-messaging.md#control-inbound-messages) and [non-interactive sessions](cross-session-messaging.md#non-interactive-sessions) cover the full held-message expiry rules, including the cases where the deadline doesn’t apply. Overrides the [`dialogExpiry`](settings-reference.md#dialogexpiry) setting. `0` or a negative value disables the deadline |
| `CLAUDE_CODE_USE_ANTHROPIC_AWS` | Use [Claude Platform on AWS](claude-platform-on-aws.md) |
| `CLAUDE_CODE_USE_BEDROCK` | Use [Amazon Bedrock](amazon-bedrock.md) |
| `CLAUDE_CODE_USE_FOUNDRY` | Use [Microsoft Foundry](microsoft-foundry.md) |
| `CLAUDE_CODE_USE_MANTLE` | Use the Amazon Bedrock [Mantle endpoint](amazon-bedrock.md#use-the-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 on by default for claude.ai and Console accounts; set to `1` to enable it in Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry sessions, or `0` to turn it off. 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](tools-reference.md#powershell-tool) |
| `CLAUDE_CODE_USE_VERTEX` | Use [Google Cloud’s Agent Platform](google-vertex-ai.md) |
| `CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS` | Set to the number of milliseconds [WebFetch](tools-reference.md#webfetch-tool-behavior) keeps each fetched URL’s response cached. The default is `900000`, which is 15 minutes. Takes plain digits only; `0`, a decimal, or any other spelling keeps the default. Claude Code reads the value once per launch, so a change in a settings `env` block applies when you next launch `claude`. Requires Claude Code v2.1.233 or later |
| `CLAUDE_CODE_WEBFETCH_DEADLINE_MS` | Upper bound in milliseconds on how long [WebFetch](tools-reference.md#webfetch-tool-behavior) waits for a page to download, including any redirects it follows. A download that hasn’t completed by then fails with a deadline error. The default is `300000`, which is five minutes. Set to `0` to remove the limit. Takes plain digits only; a decimal or any other spelling keeps the default. Requires Claude Code v2.1.268 or later |
| `CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS` | How many agents a single [workflow](workflows.md) run executes at once, from `1` to `256`. By default, a run executes up to 16 agents at once, fewer when Claude Code has fewer CPUs available; queued `agent()` calls wait for a free slot. Each running agent’s transcript stays in Claude Code’s memory, so higher values raise memory use. Takes plain digits only; out-of-range values and other spellings keep the default. Requires Claude Code v2.1.269 or later |
| `CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS` | Upper bound in milliseconds on how long a [workflow](workflows.md) agent waits for a same-prefix sibling’s first response to begin before sending its own first request. When a fan-out starts several agents that share a [prompt-cache prefix](workflows.md#prompt-caching-in-a-fan-out), Claude Code holds all but the first agent for up to this long so the rest read the cached prefix instead of each processing it uncached. Default `5000`. Set to `0` to disable the wait. When `DISABLE_PROMPT_CACHING` is set, agents never wait. Requires Claude Code v2.1.229 or later |
| `CLAUDE_CONFIG_DIR` | Override the configuration directory (default: `~/.claude`). All settings, session history, and plugins are stored under this path. For credentials, see [where Claude Code stores credentials](../13-Enterprise-Admin/iam.md#credential-management). Useful for running multiple accounts side by side: for example, `alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'`. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env) |
| `CLAUDE_DISABLE_ADOPT` | Set to `1` to stop in-flight background work instead of carrying it over when you background a session by pressing `←` or with [`/background`](../09-Agents-Patterns/agent-view.md#from-inside-a-session). Claude Code asks you to confirm before backgrounding, then stops the tasks that would otherwise carry over. Requires Claude Code v2.1.195 or later |
| `CLAUDE_EFFORT` | Set automatically in Bash tool subprocesses and hook commands to the [effort level](model-config.md#adjust-effort-level) in effect when the subprocess starts: `low`, `medium`, `high`, `xhigh`, or `max`. Matches the `effort.level` field passed to [hooks](../07-Hooks/hooks.md). 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. `0` also turns off the [first-byte deadline](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) on the connections where that deadline runs. When unset, the watchdog is enabled by default for direct Anthropic API and [Claude Platform on AWS](claude-platform-on-aws.md) connections, and for streaming responses on [gateway](../13-Enterprise-Admin/gateways.md) connections reached through `ANTHROPIC_BASE_URL` or `ANTHROPIC_AWS_BASE_URL`; before v2.1.222 it didn’t run on those gateway connections, so the event-level watchdog could report a stall there even while keep-alive pings were arriving. For timeouts and how the timers interact, see [Streaming idle watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) |
| `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK` | Set to `1` to enable the byte-level streaming idle watchdog on Amazon Bedrock `vnd.amazon.eventstream` responses, which also enables the [first-byte deadline](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) on Bedrock streaming requests. Off by default. Configure the timeout with `CLAUDE_STREAM_IDLE_TIMEOUT_MS` |
| `CLAUDE_ENABLE_STREAM_WATCHDOG` | Set to `0` to force-disable the event-level streaming idle watchdog, or set to `1` to force-enable it. When unset, the watchdog is on by default for all providers. Before v2.1.196, the unset default was server-controlled on the direct Anthropic API and off on other providers. Configure the timeout with `CLAUDE_STREAM_IDLE_TIMEOUT_MS`; for the other stall timers that run alongside this one, see [Streaming idle watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) |
| `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](../07-Hooks/hooks.md#persist-environment-variables), [Setup](../07-Hooks/hooks.md#setup), [CwdChanged](../07-Hooks/hooks.md#cwdchanged), and [FileChanged](../07-Hooks/hooks.md#filechanged) hooks |
| `CLAUDE_JOB_DIR` | Set by Claude Code in each [background session](../09-Agents-Patterns/agent-view.md) to that session’s `~/.claude/jobs/<id>` directory. Shell commands that the session runs inherit it. Write scratch files to [`$CLAUDE_JOB_DIR/tmp`](../09-Agents-Patterns/agent-view.md#where-state-is-stored). Claude’s `Write` and `Edit` calls there don’t prompt for permission, and the directory is removed when the session is deleted |
| `CLAUDE_PID` | Claude Code sets this to its own process ID in the subprocesses it spawns: Bash and PowerShell tool commands and hook commands. On Linux, the Bash tool’s shell integration uses it to refuse a `pkill` pattern that would match the Claude Code process itself; see [the error reference](errors.md#pkill-pattern-matches-the-claude-code-process). Read it from your own scripts to identify or signal the parent Claude Code process deliberately. Requires Claude Code v2.1.214 or later |
| `CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX` | Prefix for auto-generated [Remote Control](remote-control.md) 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_FIRST_BYTE_TIMEOUT_MS` | Deadline in milliseconds for the first response byte of a streaming request, on the connections where the [first-byte deadline](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) runs. For how Claude Code clamps it, the extra time it adds for large request bodies, and how it picks the deadline when you leave this unset, see [No response from API](errors.md#no-response-from-api). Requires Claude Code v2.1.242 or later |
| `CLAUDE_STREAM_IDLE_TIMEOUT_MS` | Timeout in milliseconds before the event- and byte-level streaming idle watchdogs close a stalled connection. When you set this variable explicitly, the minimum is `300000` (5 minutes); lower values are silently clamped to absorb extended thinking pauses and proxy buffering, and the byte-level watchdog caps the value at 30 minutes. `CLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MS` takes precedence over this variable for the byte-level watchdog. For the per-watchdog unset defaults, see [Streaming idle watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs) |
| `CLAUDE_SUBAGENT_BG_SHELL_MAX_MS` | Removed in v2.1.260 and now a no-op. Previously capped how long a [background shell command](interactive-mode.md#background-bash-commands) that a [subagent](../09-Agents-Patterns/sub-agents.md) started could run, in milliseconds, with a 60-minute default. See [the background command lifetime rules](tools-reference.md#background-commands) |
| `DEBUG` | Set to `1` to enable debug mode, equivalent to launching with [`--debug`](cli-reference.md#cli-flags). 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. Overrides the [`autoCompactEnabled`](settings-reference.md#autocompactenabled) setting |
| `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`](commands.md#all-commands) setup checkup skill and its `/checkup` alias. Useful for managed deployments where users shouldn’t run setup diagnostics from a session. Doesn’t affect the `claude doctor` terminal command. Before v2.1.205, this variable hid the `/doctor` diagnostics screen command |
| `DISABLE_ERROR_REPORTING` | Set to any non-empty value, such as `1`, to opt out of error reporting. **Setting it to `0` or `false` still opts out**, unlike most on/off variables; unset the variable to turn error reporting back on |
| `DISABLE_EXTRA_USAGE_COMMAND` | Set to `1` to hide the `/usage-credits` command that lets users purchase additional usage beyond rate limits |
| `DISABLE_FEEDBACK_COMMAND` | Set to `1` to disable the `/feedback` command and [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior). Also disables `/bug` and `/share`, which report through the same path; before v2.1.212 they were aliases of `/feedback`, so the command was disabled under every name. The older name `DISABLE_BUG_COMMAND` is also accepted |
| `DISABLE_GROWTHBOOK` | Set to `1` or `true` to disable GrowthBook feature-flag fetching and use code defaults for every flag. This makes [Remote Control](remote-control.md#requirements) and the other [features that need feature-flag fetching](#features-that-need-feature-flag-fetching) unavailable. Setting it to `0` or `false` leaves fetching on. 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 (Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft 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](../04-API-Reference/Guides/build-with-claude-extended-thinking.md#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](prompt-caching.md#disable-prompt-caching) for all models (takes precedence over per-model settings) |
| `DISABLE_PROMPT_CACHING_FABLE` | Set to `1` to disable prompt caching for Fable models |
| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for the [default Haiku model](prompt-caching.md#disable-prompt-caching), wherever it runs |
| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for the [default Opus model](prompt-caching.md#disable-prompt-caching) |
| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for the [default Sonnet model](prompt-caching.md#disable-prompt-caching) |
| `DISABLE_TELEMETRY` | Set to any non-empty value, such as `1`, to opt out of telemetry. **Setting it to `0` or `false` still opts out**, unlike most on/off variables; unset the variable to turn telemetry back on. Telemetry events don’t include user data like code, file paths, or Bash commands. Also disables [feature-flag fetching](#features-that-need-feature-flag-fetching). See [Turn telemetry off for your organization](../13-Enterprise-Admin/managed-settings.md#turn-telemetry-off-for-your-organization) |
| `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, with the same effect as `DISABLE_TELEMETRY`, including on [feature-flag fetching](#features-that-need-feature-flag-fetching). Claude Code reads this variable as a standard boolean, so `0` leaves telemetry on, and honors it as the cross-tool convention recognized by many developer CLIs |
| `ENABLE_BETA_TRACING_DETAILED` | Set to `1`, together with `BETA_TRACING_ENDPOINT`, to turn on [detailed beta tracing](../13-Enterprise-Admin/monitoring-usage.md#traces-beta), which adds content-bearing span attributes and the `claude_code.hook` span. Interactive CLI sessions also require your organization to be allowlisted for the beta. Both variables are ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env) |
| `ENABLE_CLAUDEAI_MCP_SERVERS` | Set to `false` to stop Claude Code from fetching [claude.ai MCP servers](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai). Enabled by default for logged-in users. To disable per-project or per-org, set [`disableClaudeAiConnectors`](settings-reference.md#disableclaudeaiconnectors) in settings instead |
| `ENABLE_PROMPT_CACHING_1H` | Set to `1` to request a 1-hour [prompt cache TTL](prompt-caching.md#cache-lifetime) instead of the default 5 minutes. Intended for API key, [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), [Microsoft Foundry](microsoft-foundry.md), and [Claude Platform on AWS](claude-platform-on-aws.md) users. Subscription users within included usage receive the 1-hour TTL automatically on the [main conversation](prompt-caching.md#which-ttl-each-request-gets). Subscription users drawing on [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) can set it to keep the 1-hour TTL. 1-hour cache writes are billed at a higher rate. To choose the TTL per request bucket instead, use `CLAUDE_CODE_PROMPT_CACHE_TTL` and `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL`, which take precedence over this variable |
| `ENABLE_PROMPT_CACHING_1H_BEDROCK` | Deprecated. Use `ENABLE_PROMPT_CACHING_1H` instead |
| `ENABLE_TOOL_SEARCH` | Controls [MCP tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search). Unset, Claude Code defers all MCP tools by default. It still loads them upfront on Google Cloud’s Agent Platform models earlier than the Claude 4.5 generation, on a Microsoft Foundry deployment hosted on Azure, and when `ANTHROPIC_BASE_URL` points to a non-first-party host. `true` always defers and sends the beta header, except on those same Agent Platform models and Microsoft Foundry deployments; requests fail on proxies that don’t support `tool_reference`. `auto` loads upfront when tool definitions fit within 10% of context. `auto:N` sets a custom threshold, such as `auto:5` for 5%. `false` loads all tools upfront. A value you set yourself is ignored when `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` is set. Before v2.1.221, Claude Code disabled tool search for all models on Google Cloud’s Agent Platform unless you set this variable to `true` |
| `FALLBACK_FOR_ALL_PRIMARY_MODELS` | Set to any non-empty value, such as `1`, to make Claude Code stop retrying on repeated overload errors for every model when no fallback model is configured. **Setting it to `0` or `false` still enables this**, unlike most on/off variables; unset the variable to restore the default retry behavior. Without it, Claude Code stops retrying this way on models it recognizes as Opus, Fable, or Mythos models when you authenticate with an API key or a [third-party provider](third-party-integrations.md) rather than a Claude subscription. On Claude Code v2.1.160 or later, Claude Code switches to your configured [fallback model chain](model-config.md#fallback-model-chains) on repeated overload errors for any primary model, so this variable doesn’t affect switching to a fallback model |
| `FORCE_AUTOUPDATE_PLUGINS` | Set to `1` to force plugin auto-updates even when the main auto-updater is disabled via `DISABLE_AUTOUPDATER` |
| `FORCE_HYPERLINK` | Set to `1` to enable clickable OSC 8 hyperlinks when your terminal supports them but isn’t auto-detected, or `0` to disable them. When unset, Claude Code enables hyperlinks only when it detects terminal support. Claude Code parses this value as a number, not a Boolean, so a value such as `false`, `no`, or `off` enables hyperlinks rather than disabling them. The footer [PR or merge request badge](interactive-mode.md#pr-review-status) renders as a hyperlink even when Claude Code can’t detect terminal support, such as over SSH. Set `0` to render the badge as plain text |
| `FORCE_PROMPT_CACHING_5M` | Set to `1` to force the 5-minute prompt cache TTL even when 1-hour TTL would otherwise apply. Overrides `CLAUDE_CODE_PROMPT_CACHE_TTL`, `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL`, `ENABLE_PROMPT_CACHING_1H`, and the `promptCacheTtl` and `subagentPromptCacheTtl` settings |
| `HTTP_PROXY` | Specify HTTP proxy server for network connections |
| `HTTPS_PROXY` | Specify HTTPS proxy server for network connections |
| `IS_DEMO` | Set to any non-empty value, such as `1`, to enable demo mode: hides your email and organization name from the header and `/status` output, and skips onboarding. **Setting it to `0` or `false` still enables demo mode**, unlike most on/off variables; unset the variable to turn it off. 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`](../06-MCP-Tools/General/mcp.md#raise-the-limit-for-a-specific-tool) 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 attempts Claude Code allows when the model’s response fails validation against the [`--json-schema`](cli-reference.md#cli-flags) in non-interactive mode with the `-p` flag; after that many failed attempts with no valid output, the run fails. The same cap applies when a [workflow](workflows.md) subagent’s structured output fails validation. Defaults to 5, a first attempt plus four retries |
| `MAX_THINKING_TOKENS` | Fixed token budget for [extended thinking](../04-API-Reference/Guides/build-with-claude-extended-thinking.md). Claude Code caps it at one token below the request’s max output tokens and never below 1,024. See `CLAUDE_CODE_MAX_OUTPUT_TOKENS` for how that limit is set. When unset and thinking is enabled, models with [adaptive reasoning](model-config.md#adjust-effort-level) choose their own thinking depth, and other models use the cap. Set to `0` to disable thinking on the Anthropic API, except on Opus 5.5, Sonnet 5.5, and the Fable models, which can’t have thinking turned off. On [third-party providers](third-party-integrations.md), `0` omits the `thinking` parameter instead. With thinking turned off on the Anthropic API, Claude Code sends effort `high` instead of a higher level to models it knows [don’t accept that combination](errors.md#effort-isnt-available-with-thinking-turned-off), such as Opus 5. Claude Code ignores nonzero values on adaptive reasoning models, except on the models where `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` turns adaptive reasoning off |
| `MCP_CLIENT_SECRET` | OAuth client secret for MCP servers that require [pre-configured credentials](../06-MCP-Tools/General/mcp.md#use-pre-configured-oauth-credentials). Avoids the interactive prompt when adding a server with `--client-secret` |
| `MCP_CONNECTION_NONBLOCKING` | Controls whether startup waits for MCP servers to connect before the first query. MCP startup is non-blocking by default: servers connect in the background and their tools become available as they finish. Set to `0` to make Claude Code wait for servers to connect before the first query. Servers configured with [`alwaysLoad: true`](../06-MCP-Tools/General/mcp.md#exempt-a-server-from-deferral) still make startup wait regardless, except when served from the [discovery cache](../06-MCP-Tools/General/mcp.md#server-status-detail), since their tools must be present when the first prompt is built. In non-interactive mode (`-p`) without `--input-format stream-json`, Claude Code also waits for still-pending servers before the first turn regardless of this variable. When you pass [`--mcp-config`](cli-reference.md#cli-flags) explicitly, the wait has a longer deadline; see that flag’s entry for the cached-server exception |
| `MCP_CONNECT_TIMEOUT_MS` | How long blocking MCP startup waits, in milliseconds, for the connection batch before snapshotting the tool list (default: 5000). Applies when `MCP_CONNECTION_NONBLOCKING=0` or for servers marked [`alwaysLoad: true`](../06-MCP-Tools/General/mcp.md#exempt-a-server-from-deferral). Servers still pending at the deadline keep connecting in the background. Distinct from `MCP_TIMEOUT`, which bounds an individual server’s connect attempt |
| `MCP_DISCOVERY_CACHE` | Turns the [MCP discovery cache](../06-MCP-Tools/General/mcp.md#server-status-detail) on or off. With the cache on, a remote HTTP or SSE server you’ve used before can show the [`cached` status](../06-MCP-Tools/General/mcp.md#server-status-detail), and Claude Code connects it on its first tool call instead of at startup. The cache is off by default unless a gradual rollout has enabled it for your account. Set to `1` to turn it on, or `0` to keep it off even when the rollout has enabled it. Before v2.1.238, the cache was on by default. The `cached` status requires Claude Code v2.1.221 or later |
| `MCP_DISCOVERY_CACHE_MAX_STALE_S` | Maximum age, in seconds, of a [discovery-cache](../06-MCP-Tools/General/mcp.md#server-status-detail) entry (default: 14400, or 4 hours). At a start where the entry is older than that, Claude Code discards it and connects the server at startup, as it does with the cache off. Claude Code caps the value at 7 days. Before v2.1.238, the default was 86400, or 24 hours, and Claude Code didn’t cap the value |
| `MCP_DISCOVERY_CACHE_STRIKES` | At a start where a [discovery-cache](../06-MCP-Tools/General/mcp.md#server-status-detail) entry is older than `MCP_DISCOVERY_CACHE_TTL_S`, Claude Code refreshes it in the background. This variable sets how many refreshes in a row can fail before Claude Code discards the entry and connects the server at the next start instead (default: 1). Raise it if your network connection drops occasionally, so that one failed refresh doesn’t discard the entry. Requires Claude Code v2.1.238 or later |
| `MCP_DISCOVERY_CACHE_TTL_S` | Seconds for which Claude Code uses a [discovery-cache](../06-MCP-Tools/General/mcp.md#server-status-detail) entry without refreshing it (default: 900). At a start where the entry is older than that, Claude Code still uses it but refreshes it in the background. Once the entry is older than `MCP_DISCOVERY_CACHE_MAX_STALE_S`, Claude Code discards it instead. Claude Code caps the value at `MCP_DISCOVERY_CACHE_MAX_STALE_S`, which is 4 hours by default. Before v2.1.238, Claude Code didn’t cap the value |
| `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](../06-MCP-Tools/General/mcp.md#use-pre-configured-oauth-credentials) |
| `MCP_PROTOCOL_NEGOTIATION` | On the [v2 MCP client runtime](../06-MCP-Tools/General/mcp.md#mcp-client-runtimes) only, whether Claude Code probes servers for MCP protocol revision 2026-07-28. Set `auto` to probe HTTP, claude.ai connector, and stdio servers; a server that doesn’t answer the probe connects on the earlier protocol instead, as SSE and WebSocket servers always do. Set `legacy` to skip the probe for every server. Without the variable, Claude Code probes HTTP servers, and also probes claude.ai connector servers in sessions where it [fetches feature flags](#features-that-need-feature-flag-fetching). Any other value is ignored with a warning in the debug log. Requires Claude Code v2.1.221 or later |
| `MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE` | Maximum number of remote MCP servers (HTTP/SSE) to connect in parallel during startup (default: 20) |
| `MCP_SDK_GENERATION` | Pin which [MCP client runtime](../06-MCP-Tools/General/mcp.md#mcp-client-runtimes) this process connects to MCP servers with: `v1`, built on MCP TypeScript SDK 1.x, or `v2`, built on [MCP TypeScript SDK 2.0](https://ts.sdk.modelcontextprotocol.io/v2/). Without the variable, Claude Code uses v2, starting with the versions listed in that section. On Claude Code v2.1.221 or later, the v2 runtime checks the issuer an MCP OAuth server returns in its authorization response and fails the sign-in with an error that begins `Issuer mismatch in authorization response` when it doesn’t match. The v1 runtime doesn’t run this check. If you set an unrecognized value, Claude Code ignores it and writes a warning to the debug log. Claude Code reads the value once per process. Requires Claude Code v2.1.218 or later |
| `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). For an HTTP, SSE, or claude.ai connector server, each request also times out after 60 seconds by default; set this variable, or the per-server `timeout`, above 60000 to raise that per-request limit. A lower value still shortens the overall tool-execution timeout but leaves the per-request limit at 60 seconds. Stdio and WebSocket servers have no per-request timer. A per-server `timeout` field in `.mcp.json` overrides this for that server. A per-server `timeout` of at least 1000 also sets the minimum idle window for that server’s tool calls, so `CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT` never aborts them sooner; this floor requires Claude Code v2.1.203 or later. For the env variable, values below 1000 are floored to one second; for the per-server field, values below 1000 are ignored |
| `NO_PROXY` | List of domains and IPs to which requests will be directly issued, bypassing proxy |
| `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` | Standard OpenTelemetry SDK limit on attribute value length. Claude Code caps content-bearing telemetry attributes at the smaller of this and `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH`, so the truncation marker stays within the SDK limit. Claude Code reads the `OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT` and `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` variants the same way, and the smallest set value applies to all signals. Requires Claude Code v2.1.214 or later. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#common-configuration-variables) |
| `OTEL_LOG_ASSISTANT_RESPONSES` | Set to `1` to include the model’s response text on `assistant_response` OpenTelemetry log events. When unset, Claude Code uses the value of `OTEL_LOG_USER_PROMPTS` instead. Set to `0` to keep responses redacted even when `OTEL_LOG_USER_PROMPTS` is set. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env). Requires Claude Code v2.1.193 or later. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#assistant-response-event) |
| `OTEL_LOG_MANAGED_SETTINGS` | Set to `1` to add the redacted managed settings, and a SHA-256 digest of the settings before redaction, to `managed_settings_resolved` OpenTelemetry log events. Disabled by default. Set it in your shell, user settings, or managed settings; a value in project or local settings doesn’t turn it on. Requires Claude Code v2.1.274 or later. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#managed-settings-resolved-event) |
| `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 the content limit, or `file:<dir>` to write untruncated bodies to disk and emit a `body_ref` path instead. `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` configures the content limit, 60 KB by default. Disabled by default; bodies include the entire conversation history. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#api-request-body-event) |
| `OTEL_LOG_TOOL_CONTENT` | Set to `1` to include tool content in the `tool.output` OpenTelemetry span event. Span attributes carry tool content under [their own gates](../13-Enterprise-Admin/monitoring-usage.md#new-context-gates). Requires [tracing](../13-Enterprise-Admin/monitoring-usage.md#traces-beta). Disabled by default to protect sensitive data. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env), apart from the off values that section describes. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#tool-output-span-event) |
| `OTEL_LOG_TOOL_DETAILS` | Set to `1` to include tool input arguments; MCP server names; user-authored workflow names; raw error strings on tool failures; the refusal `category` on `api_refusal` events; real agent, skill, plugin, and MCP server names on [cost and token metrics](../13-Enterprise-Admin/monitoring-usage.md#cost-counter); and other tool details in OpenTelemetry metrics, traces, and logs. Disabled by default to protect PII. Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env), apart from the off values that section describes. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `OTEL_LOG_USER_PROMPTS` | Set to `1` to include user prompt text in OpenTelemetry traces and logs. Disabled by default (prompts are redacted). Set it in your shell, user settings, or managed settings. Ignored in [project and local settings](settings-reference.md#variables-claude-code-ignores-in-env), apart from the off values that section describes. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Set to `false` to exclude account UUID from metrics attributes (default: included). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `OTEL_METRICS_INCLUDE_ENTRYPOINT` | Set to `true` to include the session entrypoint in metrics attributes (default: excluded). Added in v2.1.152. See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `OTEL_METRICS_INCLUDE_REPOSITORY` | Set to `true` to tag OpenTelemetry metrics and events with `vcs.*` attributes identifying the session’s repository (default: excluded). Requires Claude Code v2.1.269 or later. See [Repository attributes](../13-Enterprise-Admin/monitoring-usage.md#repository-attributes) |
| `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` | As of v2.1.161, Claude Code attaches `OTEL_RESOURCE_ATTRIBUTES` keys to metric datapoint labels. Set to `false` to exclude them (default: included). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md#multi-team-organization-support) |
| `OTEL_METRICS_INCLUDE_SESSION_ID` | Set to `false` to exclude session ID from metrics attributes (default: included). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `OTEL_METRICS_INCLUDE_VERSION` | Set to `true` to include Claude Code version in metrics attributes (default: excluded). See [Monitoring](../13-Enterprise-Admin/monitoring-usage.md) |
| `SLASH_COMMAND_TOOL_CHAR_BUDGET` | Override the character budget for skill metadata shown to the [Skill tool](../08-Plugins-Skills/skills.md#control-who-invokes-a-skill). 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` | Removed in v2.1.277 and now a no-op, together with the `TaskOutput` tool it sized. Previously set the maximum number of characters of a [background task’s](tools-reference.md#background-commands) output that the `TaskOutput` tool kept. Claude reads a background task’s output file with `Read` instead |
| `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 Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_3_5_SONNET` | Override region for Claude 3.5 Sonnet when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_3_7_SONNET` | Override region for Claude 3.7 Sonnet when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_0_OPUS` | Override region for Claude 4.0 Opus when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_0_SONNET` | Override region for Claude 4.0 Sonnet when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_1_OPUS` | Override region for Claude 4.1 Opus when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_5_OPUS` | Override region for Claude Opus 4.5 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_5_SONNET` | Override region for Claude Sonnet 4.5 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_6_OPUS` | Override region for Claude Opus 4.6 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_6_SONNET` | Override region for Claude Sonnet 4.6 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_7_OPUS` | Override region for Claude Opus 4.7 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_4_8_OPUS` | Override region for Claude Opus 4.8 when using Google Cloud’s Agent Platform |
| `VERTEX_REGION_CLAUDE_5_5_OPUS` | Override region for Claude Opus 5.5 when using Google Cloud’s Agent Platform. Added in v2.1.280 |
| `VERTEX_REGION_CLAUDE_5_5_SONNET` | Override region for Claude Sonnet 5.5 when using Google Cloud’s Agent Platform. Added in v2.1.284 |
| `VERTEX_REGION_CLAUDE_5_OPUS` | Override region for Claude Opus 5 when using Google Cloud’s Agent Platform. Added in v2.1.219 |
| `VERTEX_REGION_CLAUDE_5_SONNET` | Override region for Claude Sonnet 5 when using Google Cloud’s Agent Platform. Added in v2.1.197 |
| `VERTEX_REGION_CLAUDE_FABLE_5` | Override region for Claude Fable 5 when using Google Cloud’s Agent Platform. Added in v2.1.170 |
| `VERTEX_REGION_CLAUDE_FABLE_5_1` | Override region for Claude Fable 5.1 when using Google Cloud’s Agent Platform. Added in v2.1.257 |
| `VERTEX_REGION_CLAUDE_HAIKU_4_5` | Override region for Claude Haiku 4.5 when using Google Cloud’s Agent Platform |
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](../13-Enterprise-Admin/monitoring-usage.md) for configuration details. Set `CLAUDE_CODE_ENABLE_TELEMETRY` and the OpenTelemetry variables that turn on export, choose its destination, or capture content in your shell, user settings, or managed settings. Claude Code [ignores them in project and local settings](settings-reference.md#variables-claude-code-ignores-in-env), apart from the off values that section describes. `OTEL_RESOURCE_ATTRIBUTES` and the export interval, timeout, and compression variables, such as `OTEL_METRIC_EXPORT_INTERVAL`, still apply from project and local settings.
[](#features-that-need-feature-flag-fetching)
Features that need feature-flag fetching
Claude Code turns some features on through feature flags it fetches from Anthropic. Claude Code skips that fetch in these sessions:
- A session where you set `DISABLE_GROWTHBOOK`, `DISABLE_TELEMETRY`, `DO_NOT_TRACK`, or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`; each variable’s row in the [variables table](#variables) says which values turn fetching off
- A session on a [third-party provider](third-party-integrations.md), such as Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry, unless a host platform that embeds Claude Code sets `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`
- A [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) session
With fetching off, you can’t:
- Run [`/auto-mode-setup`](auto-mode-config.md#generate-environment-entries) to draft `autoMode.environment` entries
- Use [Remote Control](remote-control.md) with `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` or `DISABLE_GROWTHBOOK` set. For `DISABLE_TELEMETRY` and `DO_NOT_TRACK`, see the [Remote Control requirements](remote-control.md#requirements)
- [Message sessions beyond this machine](cross-session-messaging.md#message-sessions-on-other-machines) when [Remote Control](remote-control.md#requirements) is unavailable. Messaging between sessions on this machine works with fetching off
- Run [`claude import` or the `/import` command](cli-reference.md#cli-commands)
- Run [`/skill-doctor`](../08-Plugins-Skills/skills.md#find-unused-skills) or open its report in the `/plugin` **Stats** tab
- Sync the [skills](../08-Plugins-Skills/skills.md#where-synced-skills-load) and [plugins](../08-Plugins-Skills/plugins-loading.md#synced-plugins) enabled for your claude.ai account into your terminal sessions
- Use [the advisor tool](advisor.md#requirements)
- Read or reply to [comments on an artifact](artifacts.md#collect-comments-on-an-artifact)
- Have Claude Code probe claude.ai connector servers for [MCP protocol revision 2026-07-28](../06-MCP-Tools/General/mcp.md#mcp-client-runtimes) unless you set `MCP_PROTOCOL_NEGOTIATION=auto`
- Get the [PowerShell tool](tools-reference.md#powershell-tool) by default for claude.ai and Console accounts on Windows with Git Bash installed; Claude Code routes shell commands through Git Bash unless you set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. On Windows without Git Bash, the tool stays on
- Get [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior), which Claude Code turns on through a fetched flag
- Have Claude [treat large pastes as pasted rather than typed text](terminal-config.md#how-claude-treats-pasted-text); the content behind a `[Pasted text #N]` placeholder reaches Claude unmarked
- Have Claude Code [exclude MCP tools whose input schema the API would reject](../06-MCP-Tools/General/mcp.md#tools-with-invalid-input-schemas); it sends the schema anyway, and a request that includes it fails with [a 400 error naming the tool by its position](errors.md#tool-input-schema-is-invalid)
[](#first-session-after-an-install-or-upgrade)
First session after an install or upgrade
In your first session after you install Claude Code, or upgrade to a version that adds a feature, a [flag-gated feature](#features-that-need-feature-flag-fetching) can be missing. That session can also start in a different [permission mode](permission-modes.md#which-mode-a-session-starts-in) than your later sessions do. Claude Code fetches the flags during that session, so your next session has the feature and the usual starting permission mode. After a fresh install, in a non-interactive session such as `claude -p`, the Agent SDK, or the VS Code extension, Claude Code can still pick the flags up before it [chooses the starting permission mode](permission-modes.md#which-mode-a-session-starts-in).
[](#see-also)
See also
- [Settings](settings.md): all `settings.json` configuration, including the `env` key
- [CLI reference](cli-reference.md): launch-time flags
- [Network configuration](../13-Enterprise-Admin/network-config.md): proxy and TLS setup
- [Monitoring](../13-Enterprise-Admin/monitoring-usage.md): OpenTelemetry configuration
---
## Error reference - Claude Code Docs
Source: https://code.claude.com/docs/en/errors
Path: 02-Claude-Code-CLI/errors.md
## On this page
- [Find your error](#find-your-error)
- [Automatic retries](#automatic-retries)
- [What you see while Claude Code retries or waits](#what-you-see-while-claude-code-retries-or-waits)
- [Tune retry behavior](#tune-retry-behavior)
- [Server errors](#server-errors)
- [API Error: 500 Internal server error](#api-error-500-internal-server-error)
- [API Error: Repeated 529 Overloaded errors](#api-error-repeated-529-overloaded-errors)
- [Request timed out](#request-timed-out)
- [No response from API](#no-response-from-api)
- [The response above may be incomplete](#the-response-above-may-be-incomplete)
- [Auto mode cannot determine the safety of an action](#auto-mode-cannot-determine-the-safety-of-an-action)
- [The server returned no safety verdict](#the-server-returned-no-safety-verdict)
- [Agent terminated early due to an API error](#agent-terminated-early-due-to-an-api-error)
- [Usage limits](#usage-limits)
- [You’ve hit your session limit](#youve-hit-your-session-limit)
- [Usage credits required for 1M context](#usage-credits-required-for-1m-context)
- [The prompt to confirm went unanswered](#the-prompt-to-confirm-went-unanswered)
- [Server is temporarily limiting requests](#server-is-temporarily-limiting-requests)
- [Request rejected (429)](#request-rejected-429)
- [You’ve hit your monthly spend limit](#youve-hit-your-monthly-spend-limit)
- [Spend limit reached](#spend-limit-reached)
- [Credit balance is too low](#credit-balance-is-too-low)
- [Could not update your spend limit](#could-not-update-your-spend-limit)
- [Authentication errors](#authentication-errors)
- [Not logged in](#not-logged-in)
- [Could not resolve authentication method](#could-not-resolve-authentication-method)
- [Invalid API key](#invalid-api-key)
- [Your apiKeyHelper script is failing](#your-apikeyhelper-script-is-failing)
- [Invalid request header value](#invalid-request-header-value)
- [This organization has been disabled](#this-organization-has-been-disabled)
- [Your organization has disabled API key authentication](#your-organization-has-disabled-api-key-authentication)
- [Your organization has disabled Claude subscription access](#your-organization-has-disabled-claude-subscription-access)
- [Routines are disabled by your organization’s policy](#routines-are-disabled-by-your-organizations-policy)
- [Remote Control requires the Anthropic API](#remote-control-requires-the-anthropic-api)
- [Remote Control couldn’t refresh your login](#remote-control-couldnt-refresh-your-login)
- [Remote Control stopped because the signed-in account changed](#remote-control-stopped-because-the-signed-in-account-changed)
- [Remote Control stopped because the app running the session signed out or switched accounts](#remote-control-stopped-because-the-app-running-the-session-signed-out-or-switched-accounts)
- [OAuth token revoked or expired](#oauth-token-revoked-or-expired)
- [API Error: 401 Invalid authentication credentials](#api-error-401-invalid-authentication-credentials)
- [Login expired](#login-expired)
- [Could not refresh your login because another Claude Code process is refreshing it](#could-not-refresh-your-login)
- [Couldn’t save your login](#couldnt-save-your-login)
- [Failed to start OAuth callback server](#failed-to-start-oauth-callback-server)
- [Claude login not accepted](#claude-login-not-accepted)
- [Artifacts need a claude.ai login](#artifacts-need-a-claude-ai-login)
- [Administrator policy requires a Cloud gateway sign-in](#administrator-policy-requires-a-cloud-gateway-sign-in)
- [Your account is on hold](#your-account-is-on-hold)
- [Anthropic profile login expired](#anthropic-profile-login-expired)
- [OAuth scope requirement](#oauth-scope-requirement)
- [claude.ai rejected the session token](#claude-ai-rejected-the-session-token)
- [MCP server needs you to sign in again](#mcp-server-needs-you-to-sign-in-again)
- [Issuer mismatch in authorization response](#issuer-mismatch-in-authorization-response)
- [AWS credentials expired or invalid](#aws-credentials-expired-or-invalid)
- [AWS authentication failed](#aws-authentication-failed)
- [Google Cloud credentials expired or invalid](#google-cloud-credentials-expired-or-invalid)
- [Google Cloud authentication failed](#google-cloud-authentication-failed)
- [Microsoft Foundry authentication failed](#microsoft-foundry-authentication-failed)
- [Could not load AWS or Google Cloud credentials](#could-not-load-aws-or-google-cloud-credentials)
- [AWS default-chain credential resolve timed out](#aws-default-chain-credential-resolve-timed-out)
- [Bedrock setup verification timed out waiting for AWS](#bedrock-setup-verification-timed-out-waiting-for-aws)
- [Cloud gateway session expired](#cloud-gateway-session-expired)
- [Sign-in timed out while waiting for you to continue](#sign-in-timed-out-while-waiting-for-you-to-continue)
- [Gateway refused the request](#gateway-refused-the-request)
- [Network and connection errors](#network-and-connection-errors)
- [Unable to connect to API](#unable-to-connect-to-api)
- [Unable to connect to Anthropic services](#unable-to-connect-to-anthropic-services)
- [Socket is closed](#socket-is-closed)
- [API returned an empty or malformed response](#api-returned-an-empty-or-malformed-response)
- [Streaming response ended before any complete data was received](#streaming-response-ended-before-any-complete-data-was-received)
- [Bedrock streaming response has an unexpected content-type](#bedrock-streaming-response-has-an-unexpected-content-type)
- [SSL certificate errors](#ssl-certificate-errors)
- [Host not allowed in a cloud session](#host-not-allowed-in-a-cloud-session)
- [The proxy refused the connection](#the-proxy-refused-the-connection)
- [The cloud environments service returned an empty or unexpected response](#the-cloud-environments-service-returned-an-empty-or-unexpected-response)
- [Couldn’t reconnect to your Remote Control session](#couldnt-reconnect-to-your-remote-control-session)
- [Sessions ended while this machine was offline](#sessions-ended-while-this-machine-was-offline)
- [Couldn’t share the transcript](#couldnt-share-the-transcript)
- [Couldn’t send feedback](#couldnt-send-feedback)
- [Request errors](#request-errors)
- [Prompt is too long](#prompt-is-too-long)
- [Context exceeds the token limit](#context-exceeds-the-token-limit)
- [Request too large](#request-too-large)
- [Image was too large](#image-was-too-large)
- [Unable to resize image](#unable-to-resize-image)
- [PDF errors](#pdf-errors)
- [Extra inputs are not permitted](#extra-inputs-are-not-permitted)
- [Tool input schema is invalid](#tool-input-schema-is-invalid)
- [tool_use.name over 200 characters](#tool-use-name-over-200-characters)
- [There’s an issue with the selected model](#theres-an-issue-with-the-selected-model)
- [Model is not a recognized model id](#model-is-not-a-recognized-model-id)
- [Model not found](#model-not-found)
- [Couldn’t confirm model with the API](#couldnt-confirm-model-with-the-api)
- [API error when checking the picked model](#api-error-model-not-changed)
- [Claude Opus is not available with the Claude Pro plan](#claude-opus-is-not-available-with-the-claude-pro-plan)
- [Claude Code does not support this model](#claude-code-does-not-support-this-model)
- [Model is restricted by your organization’s settings](#model-is-restricted-by-your-organizations-settings)
- [Model switch was blocked by a PreModelSwitch hook](#model-switch-was-blocked-by-a-premodelswitch-hook)
- [Couldn’t save it as your default](#couldnt-save-it-as-your-default)
- [thinking.type.enabled is not supported for this model](#thinking-type-enabled-is-not-supported-for-this-model)
- [Effort isn’t available with thinking turned off](#effort-isnt-available-with-thinking-turned-off)
- [Thinking budget exceeds output limit](#thinking-budget-exceeds-output-limit)
- [Tool use or thinking block mismatch](#tool-use-or-thinking-block-mismatch)
- [Invalid data in redacted_thinking block](#invalid-data-in-redacted-thinking-block)
- [Unsupported tool content removed](#unsupported-tool-content-removed)
- [role ‘system’ must precede an ‘assistant’ message](#role-system-must-precede-an-assistant-message)
- [Invalid encrypted_content in search_result block](#invalid-encrypted-content-in-search-result-block)
- [Usage Policy refusal](#usage-policy-refusal)
- [Safety measures flagged a cybersecurity topic](#safety-measures-flagged-a-cybersecurity-topic)
- [Installation errors](#installation-errors)
- [Installation was killed before it could finish](#installation-was-killed-before-it-could-finish)
- [The connection dropped while downloading the update](#the-connection-dropped-while-downloading-the-update)
- [Command-line errors](#command-line-errors)
- [Conflict between --bg and --print](#conflict-between-bg-and-print)
- [Invalid --agents configuration](#invalid-agents-configuration)
- [Cloud sessions cannot be created from a --restricted session](#cloud-sessions-cannot-be-created-from-a-restricted-session)
- [Cloud sessions are disabled by your organization’s policy](#cloud-sessions-are-disabled-by-your-organizations-policy)
- [The --json-schema value is not a valid JSON Schema](#the-json-schema-value-is-not-a-valid-json-schema)
- [Settings file exceeds the 2MiB limit](#settings-file-exceeds-the-2mib-limit)
- [The current directory no longer exists](#the-current-directory-no-longer-exists)
- [Temp directory refused or cannot be created](#temp-directory-refused-or-cannot-be-created)
- [Directory couldn’t be resolved to a real location](#directory-couldnt-be-resolved-to-a-real-location)
- [Workspace not trusted when starting Remote Control](#workspace-not-trusted-when-starting-remote-control)
- [Not carried over to the sessions Remote Control starts](#not-carried-over-to-the-sessions-remote-control-starts)
- [claude import is not yet available in this build](#claude-import-is-not-yet-available-in-this-build)
- [Could not read Claude Code config](#could-not-read-claude-code-config)
- [Could not import a server from Claude Desktop](#could-not-import-a-server-from-claude-desktop)
- [Cannot add MCP server to the managed scope](#cannot-add-mcp-server-to-the-managed-scope)
- [Can’t read .mcp.json](#cant-read-mcp-json)
- [Server is Anthropic-hosted and doesn’t support local OAuth](#anthropic-hosted-and-doesnt-support-local-oauth)
- [Server rejected the Authorization header minted by the configured headersHelper](#server-rejected-the-authorization-header-minted-by-the-configured-headershelper)
- [MCP permission prompt tool not found](#mcp-permission-prompt-tool-not-found)
- [OAuth callback port is already in use](#oauth-callback-port-is-already-in-use)
- [No available ports for OAuth redirect](#no-available-ports-for-oauth-redirect)
- [/security-review fails without origin/HEAD](#security-review-fails-without-origin-head)
- [Input must be provided when using --print](#input-must-be-provided-when-using-print)
- [Input contained only whitespace](#input-contained-only-whitespace)
- [stream-json input carried over 256M characters with no newline](#stream-json-input-carried-over-256m-characters-with-no-newline)
- [Unknown command](#unknown-command)
- [Diff is too large for ultrareview](#diff-is-too-large-for-ultrareview)
- [Could not find merge-base with the base branch](#could-not-find-merge-base-with-the-base-branch)
- [Your checkout has no branches](#your-checkout-has-no-branches)
- [No GitHub account is connected to your Claude account](#no-github-account-is-connected-to-your-claude-account)
- [Your connected GitHub account can’t see the repository](#your-connected-github-account-cant-see-the-repository)
- [The GitHub App preflight failed transiently](#the-github-app-preflight-failed-transiently)
- [The repository upload can’t follow a git setting](#the-repository-upload-cant-follow-a-git-setting)
- [GitHub isn’t connected to your Claude account](#github-isnt-connected-to-your-claude-account)
- [Single sign-on authorization needed](#single-sign-on-authorization-needed)
- [Failed to resume the conversation](#failed-to-resume-the-conversation)
- [No conversation found with the session ID](#no-conversation-found-with-the-session-id)
- [Windows reported an error (EBADF) when Claude Code read this session’s transcript file](#windows-reported-an-error-ebadf)
- [Cannot switch renderers in this session](#cannot-switch-renderers-in-this-session)
- [Couldn’t open Claude Desktop](#couldnt-open-claude-desktop)
- [/terminal-setup left your Zed keymap unchanged](#terminal-setup-left-your-zed-keymap-unchanged)
- [Skill usage reports are not available on this connection](#skill-usage-reports-are-not-available-on-this-connection)
- [Custom output styles can’t be selected over Remote Control](#custom-output-styles-cant-be-selected-over-remote-control)
- [Output styles are saved to local settings which this session doesn’t load](#output-styles-are-saved-to-local-settings-which-this-session-doesnt-load)
- [Plugin errors](#plugin-errors)
- [plugin eval is currently in early access](#plugin-eval-is-currently-in-early-access)
- [Marketplace is registered from an untrusted source](#marketplace-is-registered-from-an-untrusted-source)
- [Marketplace name is another spelling of a reserved name](#marketplace-name-is-another-spelling-of-a-reserved-name)
- [Claude Code refuses the marketplace name](#claude-code-refuses-the-marketplace-name)
- [Marketplace is already added from a different source](#marketplace-is-already-added-from-a-different-source)
- [Plugin command references user_config in a shell command](#plugin-command-references-user-config)
- [Plugin archive integrity check failed](#plugin-archive-integrity-check-failed)
- [Path escapes plugin directory](#path-escapes-plugin-directory)
- [Path could not be checked](#path-could-not-be-checked)
- [Marketplace entry path does not stay inside the marketplace directory](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory)
- [Failed to load marketplace configuration](#failed-to-load-marketplace-configuration)
- [Plugin is required by your organization](#plugin-is-required-by-your-organization)
- [Plugin was not uninstalled](#plugin-was-not-uninstalled)
- [Tool errors](#tool-errors)
- [Agent would be spawned with zero tools](#agent-would-be-spawned-with-zero-tools)
- [File is covered by a Read deny rule](#file-is-covered-by-a-read-deny-rule)
- [Path cannot contain null bytes](#path-cannot-contain-null-bytes)
- [subagent_type is required](#subagent-type-is-required)
- [Memory index is over its read limit](#memory-index-is-over-its-read-limit)
- [pkill pattern matches the Claude Code process](#pkill-pattern-matches-the-claude-code-process)
- [Failed to write to a teammate’s inbox](#failed-to-write-to-a-teammate-inbox)
- [Teammate’s agent definition was not restored](#teammate-agent-definition-not-restored)
- [Message too large for cross-session delivery](#message-too-large-for-cross-session-delivery)
- [Too many messages to this session just now](#too-many-messages-to-this-session-just-now)
- [Cross-session message was dropped at the recipient session’s inbox](#cross-session-message-dropped-at-the-inbox)
- [Refusing to send a cross-session message](#refusing-to-send-a-cross-session-message)
- [Refusing to read, write, or search a path](#refusing-after-a-symlink-changed)
- [Task output swap refused](#task-output-swap-refused)
- [Disk quota or temp filesystem is full](#disk-quota-or-temp-filesystem-is-full)
- [The source file is not valid UTF-8 text](#the-source-file-is-not-valid-utf-8-text)
- [Reading a local file from outside the connected folders in a Cowork session](#reading-a-local-file-from-outside-the-connected-folders)
- [WebFetch cannot fetch localhost](#webfetch-cannot-fetch-localhost)
- [Background session errors](#background-session-errors)
- [Commands refused in a background session](#commands-refused-in-a-background-session)
- [Write or command blocked because the path cannot be safely resolved](#write-or-command-blocked-because-the-path-cannot-be-safely-resolved)
- [Write or command blocked because the path names a network location](#write-or-command-blocked-because-the-path-names-a-network-location)
- [Command blocked by the worktree isolation checks](#command-blocked-by-the-worktree-isolation-checks)
- [This session has no saved transcript](#this-session-has-no-saved-transcript)
- [This session is running in another terminal](#this-session-is-running-in-another-terminal)
- [This session’s saved conversation is no longer on disk](#this-sessions-saved-conversation-is-no-longer-on-disk)
- [Worktree has commits that are not pushed anywhere](#worktree-has-commits-that-are-not-pushed-anywhere)
- [Terminal host process died](#terminal-host-process-died)
- [Session isn’t responding](#session-isnt-responding)
- [Session was stopped while the respawn was in flight](#session-was-stopped-while-the-respawn-was-in-flight)
- [Session agent no longer available](#session-agent-no-longer-available)
- [CLAUDE_CODE_PROCESS_WRAPPER launcher errors](#claude_code_process_wrapper-launcher-errors)
- [EUNKNOWN when starting a background session](#eunknown-when-starting-a-background-session)
- [EACCES when starting a background session](#eacces-when-starting-a-background-session)
- [Background service exited before it became reachable](#background-service-exited-before-it-became-reachable)
- [Working directory no longer exists when starting a background session](#working-directory-no-longer-exists-when-starting-a-background-session)
- [Workspace not trusted when dispatching a background session](#workspace-not-trusted-when-dispatching-a-background-session)
- [Wrapper and IDE errors](#wrapper-and-ide-errors)
- [Claude Code process exited with code N](#claude-code-process-exited-with-code-n)
- [Could not locate the Claude CLI on PATH](#could-not-locate-the-claude-cli-on-path)
- [The connection to Claude Code ended before this message completed](#the-connection-to-claude-code-ended-before-this-message-completed)
- [Rewind warnings and errors](#rewind-warnings-and-errors)
- [Restored the code, but skipped files](#restored-the-code-but-skipped-files)
- [No files were restored](#no-files-were-restored)
- [Session saving warnings](#session-saving-warnings)
- [Transcript writes are failing](#transcript-writes-are-failing)
- [Transcript saving is off because CLAUDE_CODE_SKIP_PROMPT_HISTORY is set](#transcript-saving-is-off-skip-prompt-history)
- [Transcript saving is off because of an inherited CLAUDE_CODE_CHILD_SESSION marker](#transcript-saving-is-off-child-session-marker)
- [Configuration warnings](#configuration-warnings)
- [Fullscreen renderer didn’t finish starting](#fullscreen-failed-start-notice)
- [Claude Code exited after an unrecoverable interface error](#exited-after-an-unrecoverable-interface-error)
- [Agent descriptions are over the 15.0k-token limit](#agent-descriptions-are-over-the-15000-token-limit)
- [A skill, command, or workflow wasn’t loaded because its name is reserved](#a-skill-command-or-workflow-wasnt-loaded-because-its-name-is-reserved)
- [Workspace has not been trusted](#workspace-has-not-been-trusted)
- [Working directory is a network path](#working-directory-is-a-network-path)
- [Remote managed settings failed to load](#remote-managed-settings-failed-to-load)
- [Managed settings were not approved](#managed-settings-were-not-approved)
- [Managed settings block the default model](#managed-settings-block-the-default-model)
- [MCP server is blocked by enterprise managed policy](#mcp-server-is-blocked-by-enterprise-managed-policy)
- [Managed settings document could not be parsed](#managed-settings-document-could-not-be-parsed)
- [otelHeadersHelper failed](#otelheadershelper-failed)
- [headersHelper not run](#headershelper-not-run)
- [Malformed Tool(content) rule](#malformed-tool-content-rule)
- [Is not matched by file permission checks](#is-not-matched-by-file-permission-checks)
- [Has a wildcard before the rest of the command](#has-a-wildcard-before-the-rest-of-the-command)
- [crossSessionInbound must be one of accept, hold, refuse](#crosssessioninbound-must-be-one-of-accept-hold-refuse)
- [The 200K limit isn’t enforced](#the-200k-limit-isnt-enforced)
- [Unrecognized model ID on a request](#unrecognized-model-id-on-a-request)
- [Stale sandbox mask files left by a killed session](#stale-sandbox-mask-files-left-by-a-killed-session)
- [Responses seem lower quality than usual](#responses-seem-lower-quality-than-usual)
- [Report an error](#report-an-error)
Troubleshooting
# Error reference
Copy pageCopy page
Look up Claude Code runtime error messages with what each one means and how to fix it.
Copy pageCopy page
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](troubleshoot-install.md). Except for [Wrapper and IDE errors](#wrapper-and-ide-errors), which the launching program prints rather than Claude Code itself, these errors and recovery commands apply across the CLI, the [Desktop app](../16-Mobile-Desktop/desktop.md), and [cloud sessions](claude-code-on-the-web.md), since all three wrap the same Claude Code CLI. For other 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](../04-API-Reference/Endpoints/errors.md).
[](#find-your-error)
Find your error
Match the message you see to a section below.
| Message | Section |
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------|
| `API Error: 500 Internal server error` | [Server errors](#api-error-500-internal-server-error) |
| `API Error: Repeated 529 Overloaded errors` | [Server errors](#api-error-repeated-529-overloaded-errors) |
| `Opus is experiencing high load` / `Fable is experiencing high load` | [Server errors](#api-error-repeated-529-overloaded-errors) |
| `Request timed out` | [Server errors](#request-timed-out), or [Network](#unable-to-connect-to-api) if the message mentions your internet connection |
| `API Error: No response from API` | [Server errors](#no-response-from-api) |
| `Server error mid-response. The response above may be incomplete.` | [Server errors](#the-response-above-may-be-incomplete) |
| `Connection lost mid-response` / `Your computer went to sleep mid-response` / `The response stopped arriving` | [Server errors](#the-response-above-may-be-incomplete) |
| `Connection closed mid-response` / `Response stalled mid-stream` | [Server errors](#the-response-above-may-be-incomplete) |
| `Part of the response never arrived` / `The response stream was malformed` | [Server errors](#the-response-above-may-be-incomplete) |
| `API Error: Content block not found` / `API Error: Content block already closed` / `API Error: Stream event unreadable` | [Server errors](#the-response-above-may-be-incomplete) |
| `Connection lost before a response was produced` / `Your computer went to sleep before a response was produced` / `The response stalled before a response was produced` | [Automatic retries](#automatic-retries) |
| `Connection closed while thinking` / `Response stalled while thinking` | [Automatic retries](#automatic-retries) |
| `Connection lost while your computer was asleep` | [Automatic retries](#automatic-retries) |
| `<model> is temporarily unavailable, so auto mode cannot determine the safety of...` | [Server errors](#auto-mode-cannot-determine-the-safety-of-an-action) |
| `Auto mode could not evaluate this action and is blocking it for safety` | [Server errors](#auto-mode-cannot-determine-the-safety-of-an-action) |
| `Auto mode classifier transcript exceeded context window` | [Server errors](#auto-mode-cannot-determine-the-safety-of-an-action) |
| `Agent aborted: auto mode classifier request refused by the safety safeguard` | [Server errors](#auto-mode-cannot-determine-the-safety-of-an-action) |
| `The server-side auto mode classifier gave no verdict` | [Server errors](#the-server-returned-no-safety-verdict) |
| `Auto mode is unavailable — the server returned no safety verdict for the last 10 responses` | [Server errors](#the-server-returned-no-safety-verdict) |
| `Agent terminated early due to an API error` | [Server errors](#agent-terminated-early-due-to-an-api-error) |
| `You've hit your session limit` / `You've hit your weekly limit` / `You've hit your Opus limit` / `You've hit your Sonnet limit` | [Usage limits](#youve-hit-your-session-limit) |
| `Usage credits required for 1M context` | [Usage limits](#usage-credits-required-for-1m-context) |
| `the prompt to confirm went unanswered — nothing was sent` | [Usage limits](#the-prompt-to-confirm-went-unanswered) |
| `Server is temporarily limiting requests` | [Usage limits](#server-is-temporarily-limiting-requests) |
| `Request rejected (429)` | [Usage limits](#request-rejected-429) |
| `Credit balance is too low` | [Usage limits](#credit-balance-is-too-low) |
| `You've hit your monthly spend limit` / `You've hit your individual spend limit` / `You've hit your org's monthly spend limit` / `You've hit your channel's monthly spend limit` / `You've hit your team's shared budget` / `You've hit your individual usage limit` | [Usage limits](#youve-hit-your-monthly-spend-limit) |
| `Could not update your spend limit` | [Usage limits](#could-not-update-your-spend-limit) |
| `spend limit reached` / `spend limit unavailable` | [Usage limits](#spend-limit-reached) |
| `Not logged in · Please run /login` | [Authentication](#not-logged-in) |
| `Couldn't save your login` | [Authentication](#couldnt-save-your-login) |
| `Authentication required · Sign in again to continue` | [Authentication](#not-logged-in) |
| `Could not resolve authentication method` | [Authentication](#could-not-resolve-authentication-method) |
| `Invalid API key` | [Authentication](#invalid-api-key) |
| `Your apiKeyHelper script is failing` | [Authentication](#your-apikeyhelper-script-is-failing) |
| `Invalid auth token · Fix external auth token` | [Authentication](#invalid-request-header-value) |
| `Invalid ANTHROPIC_CUSTOM_HEADERS · Fix the environment variable` | [Authentication](#invalid-request-header-value) |
| `Invalid request header from the environment · Fix the environment variable` | [Authentication](#invalid-request-header-value) |
| `This organization has been disabled` | [Authentication](#this-organization-has-been-disabled) |
| `Your organization has disabled API key authentication` | [Authentication](#your-organization-has-disabled-api-key-authentication) |
| `Your organization has disabled Claude subscription access` | [Authentication](#your-organization-has-disabled-claude-subscription-access) |
| `Routines are disabled by your organization's policy` | [Authentication](#routines-are-disabled-by-your-organizations-policy) |
| `Remote Control is only available when using Claude via api.anthropic.com` | [Authentication](#remote-control-requires-the-anthropic-api) |
| `OAuth token refresh failed — run /login to re-authenticate` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `JWT refresh failed: no OAuth token — run /login` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `Claude.ai login expired` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `Claude.ai login was rejected — run /login, then /remote-control` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `OAuth token unavailable — run /login to restore Remote Control` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `Signed out of Claude — run /login, then /remote-control` | [Authentication](#remote-control-couldnt-refresh-your-login) |
| `signed-in claude.ai account or organization changed on this machine` | [Authentication](#remote-control-stopped-because-the-signed-in-account-changed) |
| `Remote Control stopped — the app running this session is now signed in to a different Claude account` | [Authentication](#remote-control-stopped-because-the-app-running-the-session-signed-out-or-switched-accounts) |
| `Remote Control stopped — the app running this session is signed out of Claude` | [Authentication](#remote-control-stopped-because-the-app-running-the-session-signed-out-or-switched-accounts) |
| `Couldn't verify your organization's policy for remote control` | [Troubleshoot Remote Control](remote-control.md#couldnt-verify-your-organizations-policy-for-remote-control) |
| `OAuth token revoked` / `OAuth token has expired` | [Authentication](#oauth-token-revoked-or-expired) |
| `API Error: 401 Invalid authentication credentials` | [Authentication](#api-error-401-invalid-authentication-credentials) |
| `Login expired · Please run /login` | [Authentication](#login-expired) |
| `Failed to start OAuth callback server` | [Authentication](#failed-to-start-oauth-callback-server) |
| `Claude login not accepted · Run /login, then try again` | [Authentication](#claude-login-not-accepted) |
| `Artifacts need a claude.ai login` | [Authentication](#artifacts-need-a-claude-ai-login) |
| `Not signed in to the Cloud gateway — run /login.` | [Authentication](#administrator-policy-requires-a-cloud-gateway-sign-in) |
| `Administrator policy requires a Cloud gateway sign-in on this machine` | [Authentication](#administrator-policy-requires-a-cloud-gateway-sign-in) |
| `Failed to authenticate: OAuth session expired and could not be refreshed` | [Authentication](#login-expired) |
| `Could not refresh your login because another Claude Code process is refreshing it` | [Authentication](#could-not-refresh-your-login) |
| `Failed to refresh OAuth token: another Claude Code process is refreshing it or exited mid-refresh` | [Authentication](#could-not-refresh-your-login) |
| `Your account is on hold and can't use Claude Code. View details or appeal: https://claude.ai/restricted` | [Authentication](#your-account-is-on-hold) |
| `Your account is on hold and can't sign in to Claude Code. View details or appeal: https://claude.ai/restricted` | [Authentication](#your-account-is-on-hold) |
| `Anthropic profile login expired · Re-authenticate your Anthropic profile` | [Authentication](#anthropic-profile-login-expired) |
| `Anthropic profile login expired · Run /login to use your claude.ai account instead, or re-authenticate the profile` | [Authentication](#anthropic-profile-login-expired) |
| `does not meet scope requirement user:profile` | [Authentication](#oauth-scope-requirement) |
| `claude.ai rejected the session token` / `session token rejected` | [Authentication](#claude-ai-rejected-the-session-token) |
| `MCP server "<name>" needs you to sign in again (run /mcp to re-authenticate)` | [Authentication](#mcp-server-needs-you-to-sign-in-again) |
| `rejected the credential from its headersHelper` / `rejected the Authorization header in its config` | [Authentication](#mcp-server-needs-you-to-sign-in-again) |
| `MCP server "<name>" needs additional permissions (scope: "<scope>") — run /mcp to re-authenticate` | [Authentication](#mcp-server-needs-you-to-sign-in-again) |
| `MCP server "<name>" requires re-authorization (token expired)` | [Authentication](#mcp-server-needs-you-to-sign-in-again) |
| `Issuer mismatch in authorization response (RFC 9207)` | [Authentication](#issuer-mismatch-in-authorization-response) |
| `Cloud gateway session expired — run /login to reconnect.` | [Authentication](#cloud-gateway-session-expired) |
| `Cloud gateway <url> no longer accepts this session` | [Authentication](#cloud-gateway-session-expired) |
| `Sign-in timed out while waiting for you to continue. Try again.` | [Authentication](#sign-in-timed-out-while-waiting-for-you-to-continue) |
| `AWS credentials expired or invalid` | [Authentication](#aws-credentials-expired-or-invalid) |
| `AWS authentication failed` | [Authentication](#aws-authentication-failed) |
| `Google Cloud credentials expired or invalid` | [Authentication](#google-cloud-credentials-expired-or-invalid) |
| `Google Cloud authentication failed` | [Authentication](#google-cloud-authentication-failed) |
| `Microsoft Foundry authentication failed` | [Authentication](#microsoft-foundry-authentication-failed) |
| `Gateway refused the request` | [Authentication](#gateway-refused-the-request) |
| `Could not load AWS credentials` / `Could not load Google Cloud credentials` | [Authentication](#could-not-load-aws-or-google-cloud-credentials) |
| `AWS default-chain credential resolve timed out` | [Authentication](#aws-default-chain-credential-resolve-timed-out) |
| `Timed out after 60s waiting for AWS` | [Authentication](#bedrock-setup-verification-timed-out-waiting-for-aws) |
| `A request to AWS timed out. Check your network and proxy settings, then try again.` | [Authentication](#bedrock-setup-verification-timed-out-waiting-for-aws) |
| `Could not load the default credentials` on Google Cloud’s Agent Platform | [Authentication](#could-not-load-aws-or-google-cloud-credentials) |
| `Unable to connect to API` | [Network](#unable-to-connect-to-api) |
| `Connection refused —` / `Can't reach the API server —` / `No internet route —` / `Couldn't connect through your proxy` / `Connection dropped`, each with an error code in parentheses | [Network](#unable-to-connect-to-api) |
| `Unable to connect to Anthropic services` during setup | [Network](#unable-to-connect-to-anthropic-services) |
| `Socket is closed` | [Network](#socket-is-closed) |
| `Waiting for API response · will retry in` | [Automatic retries](#automatic-retries), or [Network](#unable-to-connect-to-api) if it persists |
| `API returned an empty or malformed response` | [Network](#api-returned-an-empty-or-malformed-response) |
| `Streaming response ended before any complete data was received` | [Network](#streaming-response-ended-before-any-complete-data-was-received) |
| `Bedrock streaming response has content-type "..."; expected "application/vnd.amazon.eventstream"` | [Network](#bedrock-streaming-response-has-an-unexpected-content-type) |
| `SSL certificate verification failed` | [Network](#ssl-certificate-errors) |
| `SSL certificate error (...)` during login or startup | [Network](#ssl-certificate-errors) |
| `unable to get local issuer certificate` | [Network](#ssl-certificate-errors) |
| `403` with `x-deny-reason: host_not_allowed` in a cloud or routine session | [Network](#host-not-allowed-in-a-cloud-session) |
| `proxy refused the connection` | [Network](#the-proxy-refused-the-connection) |
| `403` with `This GraphQL query is not enabled for this session` in a cloud session | [GitHub proxy](cloud-environments.md#github-proxy) |
| `The cloud environments service returned an empty response` / `The cloud environments service returned a response in an unexpected format` | [Network](#the-cloud-environments-service-returned-an-empty-or-unexpected-response) |
| `Couldn't reconnect to your Remote Control session` | [Network](#couldnt-reconnect-to-your-remote-control-session) |
| `N sessions ended while this machine was offline — the environment was cleaned up on the server and can't be resumed.` | [Network](#sessions-ended-while-this-machine-was-offline) |
| `Couldn't share the transcript.` | [Network](#couldnt-share-the-transcript) |
| `Couldn't send feedback` | [Network](#couldnt-send-feedback) |
| `Prompt is too long` / `Input is too long for requested model` | [Request errors](#prompt-is-too-long) |
| `Prompt is too long · automatic compaction failed:` | [Request errors](#prompt-is-too-long) |
| `Prompt is too long · this conversation is a single exchange` / `A single-exchange conversation cannot be compacted` | [Request errors](#prompt-is-too-long) |
| `Context limit reached · /compact or /clear to continue` | [Request errors](#prompt-is-too-long) |
| `Context limit reached · /clear to continue` | [Request errors](#prompt-is-too-long) |
| `capability_rejected: prompt_too_long` on a Claude apps gateway session | [Request errors](#prompt-is-too-long) |
| `upstream rejected the request` / `request too large for this upstream` on a Claude apps gateway session | [Upstream error messages](../13-Enterprise-Admin/claude-apps-gateway-config.md#upstream-error-messages) |
| `upstream rate limit exceeded` on a Claude apps gateway session | [Upstream error messages](../13-Enterprise-Admin/claude-apps-gateway-config.md#upstream-error-messages) |
| `all upstreams failed (N attempted)` on a Claude apps gateway session | [Upstream error messages](../13-Enterprise-Admin/claude-apps-gateway-config.md#upstream-error-messages) |
| `Claude Code may not be enabled for your organization` after a Claude apps gateway sign-in | [Claude apps gateway troubleshooting](../13-Enterprise-Admin/claude-apps-gateway-deploy.md#troubleshooting) |
| `Context exceeds the ...-token limit by ... tokens` in `/context` output | [Request errors](#context-exceeds-the-token-limit) |
| `Request too large` | [Request errors](#request-too-large) |
| `Request too large for the API's 32MB request limit` | [Request errors](#request-too-large) |
| `Image was too large` | [Request errors](#image-was-too-large) |
| `Unable to resize image` | [Request errors](#unable-to-resize-image) |
| `PDF too large` / `PDF is password protected` / `pdftoppm is not installed` | [Request errors](#pdf-errors) |
| `Extra inputs are not permitted` | [Request errors](#extra-inputs-are-not-permitted) |
| `API Error: 400 ... tools.N.custom.input_schema: JSON schema is invalid` / `Property keys should match pattern` | [Request errors](#tool-input-schema-is-invalid) |
| `tool_use.name: String should have at most 200 characters` | [Request errors](#tool-use-name-over-200-characters) |
| `There's an issue with the selected model` | [Request errors](#theres-an-issue-with-the-selected-model) |
| `Model ... is not a recognized model id` | [Request errors](#model-is-not-a-recognized-model-id) |
| `Model ... not found` | [Request errors](#model-not-found) |
| `Couldn't confirm model ... with the API` | [Request errors](#couldnt-confirm-model-with-the-api) |
| `API error: ... · model not changed` | [Request errors](#api-error-model-not-changed) |
| `Claude Opus is not available with the Claude Pro plan` | [Request errors](#claude-opus-is-not-available-with-the-claude-pro-plan) |
| `Claude Code ... does not support this model; version ... or newer is required` | [Request errors](#claude-code-does-not-support-this-model) |
| `Claude Code ... is older than the minimum version required by your organization's policy` | [Request errors](#claude-code-does-not-support-this-model) |
| `Model ... is restricted by your organization's settings` | [Request errors](#model-is-restricted-by-your-organizations-settings) |
| `Model ... is not available. Your organization restricts model selection.` | [Request errors](#model-is-restricted-by-your-organizations-settings) |
| `Model switch ... blocked by a PreModelSwitch hook` | [Request errors](#model-switch-was-blocked-by-a-premodelswitch-hook) |
| `couldn't save it as your default` / `couldn't confirm it was saved as your default` | [Request errors](#couldnt-save-it-as-your-default) |
| `thinking.type.enabled is not supported for this model` | [Request errors](#thinking-type-enabled-is-not-supported-for-this-model) |
| `Effort '<level>' isn't available with thinking turned off on this model` | [Request errors](#effort-isnt-available-with-thinking-turned-off) |
| `effort '<level>' is not supported when thinking is disabled` | [Request errors](#effort-isnt-available-with-thinking-turned-off) |
| `max_tokens must be greater than thinking.budget_tokens` | [Request errors](#thinking-budget-exceeds-output-limit) |
| `API Error: 400 due to tool use concurrency issues` | [Request errors](#tool-use-or-thinking-block-mismatch) |
| `API Error: 400 orphaned tool_result in conversation history` | [Request errors](#tool-use-or-thinking-block-mismatch) |
| `API Error: 400 duplicate tool_use ID in conversation history` | [Request errors](#tool-use-or-thinking-block-mismatch) |
| `Invalid data in redacted_thinking block` | [Request errors](#invalid-data-in-redacted-thinking-block) |
| `[Unsupported tool content removed]` | [Request errors](#unsupported-tool-content-removed) |
| `role 'system' must precede an 'assistant' message` | [Request errors](#role-system-must-precede-an-assistant-message) |
| `Invalid encrypted_content in search_result block` / `Invalid encrypted_index in text block` / `Failed to decrypt web search result content` | [Request errors](#invalid-encrypted-content-in-search-result-block) |
| `Invalid encrypted_stdout in encrypted_code_execution_result block` | [Request errors](#invalid-encrypted-content-in-search-result-block) |
| `server_tool_use.name: Input should be` on every turn of a resumed session | [Request errors](#unsupported-tool-content-removed) |
| `<model> can't help with this. Start a new session to continue` | [Request errors](#usage-policy-refusal) |
| `Claude Code is unable to respond to this request, which appears to violate our Usage Policy` | [Request errors](#usage-policy-refusal) |
| `<model>'s safeguards flagged this message` | [Request errors](#safety-measures-flagged-a-cybersecurity-topic) |
| `<model>'s safeguards flagged this session` | [Request errors](#safety-measures-flagged-a-cybersecurity-topic) |
| `<model> has safety measures that flagged this message for a cybersecurity topic` | [Request errors](#safety-measures-flagged-a-cybersecurity-topic) |
| `Installation was killed before it could finish (exit code 137)` | [Installation errors](#installation-was-killed-before-it-could-finish) |
| `The connection dropped while downloading the update` | [Installation errors](#the-connection-dropped-while-downloading-the-update) |
| `Download timed out: exceeded the total deadline` | [Installation errors](#the-connection-dropped-while-downloading-the-update) |
| `--bg and --print conflict` | [Command-line errors](#conflict-between-bg-and-print) |
| `Cloud sessions cannot be created from a --restricted session` | [Command-line errors](#cloud-sessions-cannot-be-created-from-a-restricted-session) |
| `Cloud sessions are disabled by your organization's policy` | [Command-line errors](#cloud-sessions-are-disabled-by-your-organizations-policy) |
| `Couldn't verify your organization's policy for cloud sessions` | [Command-line errors](#cloud-sessions-are-disabled-by-your-organizations-policy) |
| `Error: --json-schema is not a valid JSON Schema` | [Command-line errors](#the-json-schema-value-is-not-a-valid-json-schema) |
| `Error: Invalid --agents configuration:` | [Command-line errors](#invalid-agents-configuration) |
| `Error: --agents takes a JSON object, or a file path only with --print (-p)` | [Command-line errors](#invalid-agents-configuration) |
| `Error: --agents file not found` | [Command-line errors](#invalid-agents-configuration) |
| `Error: Settings file exceeds the 2MiB limit` | [Command-line errors](#settings-file-exceeds-the-2mib-limit) |
| `The current directory no longer exists (it was deleted or moved)` / `Can't read the current directory` | [Command-line errors](#the-current-directory-no-longer-exists) |
| `Temp directory <dir> ... Refusing to use it` / `ENOSPC: no space left on device, mkdir '<dir>'` | [Command-line errors](#temp-directory-refused-or-cannot-be-created) |
| `couldn't be resolved to a real location, so its skills, commands, and agents weren't loaded` | [Command-line errors](#directory-couldnt-be-resolved-to-a-real-location) |
| `Error: Workspace not trusted` when starting Remote Control | [Command-line errors](#workspace-not-trusted-when-starting-remote-control) |
| `` `<flag>` before `remote-control` is not carried over to the sessions Remote Control starts `` | [Command-line errors](#not-carried-over-to-the-sessions-remote-control-starts) |
| `` `claude import` is not yet available in this build `` | [Command-line errors](#claude-import-is-not-yet-available-in-this-build) |
| `Could not read Claude Code config` | [Command-line errors](#could-not-read-claude-code-config) |
| `Could not import <server>: <reason>` | [Command-line errors](#could-not-import-a-server-from-claude-desktop) |
| `Cannot add MCP server to scope: managed` | [Command-line errors](#cannot-add-mcp-server-to-the-managed-scope) |
| `is Anthropic-hosted and doesn't support local OAuth` | [Command-line errors](#anthropic-hosted-and-doesnt-support-local-oauth) |
| `Can't read .mcp.json: it isn't a regular file or is larger than 2097152 bytes` | [Command-line errors](#cant-read-mcp-json) |
| `Server rejected the Authorization header minted by the configured headersHelper` | [Command-line errors](#server-rejected-the-authorization-header-minted-by-the-configured-headershelper) |
| `Error: MCP tool <name> (passed via --permission-prompt-tool) not found` | [Command-line errors](#mcp-permission-prompt-tool-not-found) |
| `OAuth callback port <port> is already in use — another process may be holding it` | [Command-line errors](#oauth-callback-port-is-already-in-use) |
| `No available ports for OAuth redirect` | [Command-line errors](#no-available-ports-for-oauth-redirect) |
| `Shell command failed for pattern "..."`, from `/security-review` or any skill that injects dynamic context | [Command-line errors](#security-review-fails-without-origin-head) |
| `Shell command permission check failed for pattern "..."`, from a skill that injects dynamic context | [Command-line errors](#security-review-fails-without-origin-head) |
| `` Skill <name> requires bash (`shell: bash` in frontmatter) but Git Bash was not found `` | [Command-line errors](#security-review-fails-without-origin-head) |
| `Input must be provided either through stdin or as a prompt argument when using --print` | [Command-line errors](#input-must-be-provided-when-using-print) |
| `Error: Input contained only whitespace` | [Command-line errors](#input-contained-only-whitespace) |
| `Blank prompt — the message was only whitespace, so nothing was sent to the model.` | [Command-line errors](#input-contained-only-whitespace) |
| `Error: stream-json input carried over 256M characters with no newline` | [Command-line errors](#stream-json-input-carried-over-256m-characters-with-no-newline) |
| `Unknown command: /<name>`, with or without a `Did you mean` suggestion | [Command-line errors](#unknown-command) |
| `Diff is too large for ultrareview` / `PR #<N> is too large for ultrareview` | [Command-line errors](#diff-is-too-large-for-ultrareview) |
| `Could not find merge-base with <branch>` | [Command-line errors](#could-not-find-merge-base-with-the-base-branch) |
| `Your checkout has no branches (detached HEAD only)` | [Command-line errors](#your-checkout-has-no-branches) |
| `Ultrareview clones <owner>/<repo> in the cloud with the GitHub account connected to your Claude account, and none is connected` | [Command-line errors](#no-github-account-is-connected-to-your-claude-account) |
| `Your connected GitHub account can't see <owner>/<repo>` | [Command-line errors](#your-connected-github-account-cant-see-the-repository) |
| `The GitHub App preflight failed transiently (network or service hiccup) — retry in a moment to start from GitHub instead` | [Command-line errors](#the-github-app-preflight-failed-transiently) |
| `Not uploading this working tree` with `the upload cannot follow that setting` | [Command-line errors](#the-repository-upload-cant-follow-a-git-setting) |
| `GitHub isn't connected to your Claude account, so this repository can't be cloned in the cloud` | [Command-line errors](#github-isnt-connected-to-your-claude-account) |
| `Single sign-on authorization needed` | [Command-line errors](#single-sign-on-authorization-needed) |
| `Failed to resume the conversation` | [Command-line errors](#failed-to-resume-the-conversation) |
| `No conversation found with session ID: <session-id>` | [Command-line errors](#no-conversation-found-with-the-session-id) |
| `Windows reported an error (EBADF) when Claude Code read this session's transcript file` | [Command-line errors](#windows-reported-an-error-ebadf) |
| `Cannot switch renderers in this session` | [Command-line errors](#cannot-switch-renderers-in-this-session) |
| `Cannot switch renderers while work is running in the background` | [Command-line errors](#cannot-switch-renderers-in-this-session) |
| `Couldn't open Claude Desktop` | [Command-line errors](#couldnt-open-claude-desktop) |
| `Failed to open Claude Desktop. Please try opening it manually.` | [Command-line errors](#couldnt-open-claude-desktop) |
| `Couldn't read your Zed keymap` / `Couldn't back up your Zed keymap` / `Couldn't update your Zed keymap` | [Command-line errors](#terminal-setup-left-your-zed-keymap-unchanged) |
| `Your Zed keymap isn't a readable list of keybindings` | [Command-line errors](#terminal-setup-left-your-zed-keymap-unchanged) |
| `Skill usage reports are not available on this connection.` | [Command-line errors](#skill-usage-reports-are-not-available-on-this-connection) |
| `Custom output styles can't be selected over Remote Control or from a relayed message` | [Command-line errors](#custom-output-styles-cant-be-selected-over-remote-control) |
| `Output styles are saved to local settings (.claude/settings.local.json), which this session doesn't load` | [Command-line errors](#output-styles-are-saved-to-local-settings-which-this-session-doesnt-load) |
| `` `plugin eval` is currently in early access `` / `` `plugin eval` is currently unavailable `` | [Plugin errors](#plugin-eval-is-currently-in-early-access) |
| `Marketplace "<name>" is registered from an untrusted source` | [Plugin errors](#marketplace-is-registered-from-an-untrusted-source) |
| `Claude Code refuses the marketplace name "<name>"` | [Plugin errors](#claude-code-refuses-the-marketplace-name) |
| `Marketplace name impersonates an official Anthropic/Claude marketplace` | [Plugin errors](#claude-code-refuses-the-marketplace-name) |
| `Marketplace "<name>" is already added from a different source` | [Plugin errors](#marketplace-is-already-added-from-a-different-source) |
| `"<name>" is another spelling of "<reserved>", a reserved marketplace name` | [Plugin errors](#marketplace-name-is-another-spelling-of-a-reserved-name) |
| `references ${user_config.*} in a shell-form command` | [Plugin errors](#plugin-command-references-user-config) |
| `Monitor "<name>" from plugin <plugin> references ${user_config.*} in its command` | [Plugin errors](#plugin-command-references-user-config) |
| `headersHelper for MCP server '<name>' references ${user_config.*}` | [Plugin errors](#plugin-command-references-user-config) |
| `Plugin archive integrity check failed` | [Plugin errors](#plugin-archive-integrity-check-failed) |
| `path escapes plugin directory` | [Plugin errors](#path-escapes-plugin-directory) |
| `path could not be checked` | [Plugin errors](#path-could-not-be-checked) |
| `its marketplace entry path does not stay inside the marketplace directory` | [Plugin errors](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory) |
| `Plugin source path refused` | [Plugin errors](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory) |
| `Failed to load marketplace configuration` | [Plugin errors](#failed-to-load-marketplace-configuration) |
| `Marketplace configuration file is corrupted` | [Plugin errors](#failed-to-load-marketplace-configuration) |
| `Plugin "<name>@synced" is required by your organization and can't be disabled here` | [Plugin errors](#plugin-is-required-by-your-organization) |
| `"<plugin>" was not uninstalled: it is still switched on in <file>` | [Plugin errors](#plugin-was-not-uninstalled) |
| `"<plugin>" was not uninstalled: <file> is there and could not be read` | [Plugin errors](#plugin-was-not-uninstalled) |
| `Plugin "<plugin>" was not uninstalled: installed_plugins.json` | [Plugin troubleshooting](../08-Plugins-Skills/plugins-troubleshooting.md#installed-plugins-json-holds-a-record-this-version-cannot-read) |
| `would be spawned with zero tools — refusing` | [Tool errors](#agent-would-be-spawned-with-zero-tools) |
| `File is covered by a Read deny rule in your permission settings` | [Tool errors](#file-is-covered-by-a-read-deny-rule) |
| `cannot contain null bytes (\0)` | [Tool errors](#path-cannot-contain-null-bytes) |
| `Path contains null bytes` | [Tool errors](#path-cannot-contain-null-bytes) |
| `subagent_type is required: the general-purpose agent is not available in this session` | [Tool errors](#subagent-type-is-required) |
| `Error: this write left the memory index at MEMORY.md at ..., over its ... read limit` | [Tool errors](#memory-index-is-over-its-read-limit) |
| `pkill: refusing to run` | [Tool errors](#pkill-pattern-matches-the-claude-code-process) |
| `Failed to write to <name>'s inbox — nothing was sent` | [Tool errors](#failed-to-write-to-a-teammate-inbox) |
| `Failed to write the plan approval request to the lead's inbox — plan not submitted` | [Tool errors](#failed-to-write-to-a-teammate-inbox) |
| `Its agent definition was not restored: the folder its definition file came from is not trusted` | [Tool errors](#teammate-agent-definition-not-restored) |
| `Message too large for cross-session delivery` | [Tool errors](#message-too-large-for-cross-session-delivery) |
| `Too many messages to this session just now` | [Tool errors](#too-many-messages-to-this-session-just-now) |
| `Cross-session message was dropped at the recipient session's inbox` | [Tool errors](#cross-session-message-dropped-at-the-inbox) |
| `Refusing to send: reply target is a symlink` / `Refusing to send: cannot vet reply target` | [Tool errors](#refusing-to-send-a-cross-session-message) |
| `Refusing to read <path>: its symlink resolution changed after permission was checked (<reason>)` / `Refusing to search <path>: its symlink resolution changed after permission was checked` | [Tool errors](#refusing-after-a-symlink-changed) |
| `Refusing to write <path>: its parent-directory symlink resolution changed after permission was checked` / `Refusing to write <path>: it is a symbolic link. Write to the link's target path instead` | [Tool errors](#refusing-after-a-symlink-changed) |
| `Refusing to write through symlink: <path>` / `Refusing to write into symlinked directory: <path>` | [Tool errors](#refusing-after-a-symlink-changed) |
| `Refusing to write <path>: where it leads on disk could not be determined` / `Refusing to read <path>: where it leads on disk could not be determined` | [Tool errors](#refusing-after-a-symlink-changed) |
| `Refusing to search <path>: a path one of its Read deny rules is written through changed while the search was being prepared` / `Refusing to search <path>: it could not be opened` | [Tool errors](#refusing-after-a-symlink-changed) |
| `its permission check expired before it ran (too many concurrent file operations)` / `ripgrep was found only by name on PATH` | [Tool errors](#refusing-after-a-symlink-changed) |
| `task output swap refused (tasks dir moved or linked)` | [Tool errors](#task-output-swap-refused) |
| `Command killed: its output file was replaced or could no longer be verified` | [Tool errors](#task-output-swap-refused) |
| `Your disk quota is full on the filesystem with Claude Code's temp directory <dir> (EDQUOT)` | [Tool errors](#disk-quota-or-temp-filesystem-is-full) |
| `The filesystem with Claude Code's temp directory <dir>, or your disk quota on it, is full (ENOSPC)` | [Tool errors](#disk-quota-or-temp-filesystem-is-full) |
| `Command output was lost: the temp filesystem at <dir> is full` / `is out of inodes` | [Tool errors](#disk-quota-or-temp-filesystem-is-full) |
| `the source file is not valid UTF-8 text` / `the source file is not valid UTF-16 text` | [Tool errors](#the-source-file-is-not-valid-utf-8-text) |
| `the source file has the replacement character U+FFFD` | [Tool errors](#the-source-file-is-not-valid-utf-8-text) |
| `Reading a local file from outside this session's connected folders, or through a link, needs the approval card` | [Tool errors](#reading-a-local-file-from-outside-the-connected-folders) |
| `cannot read file_path (...) — the file could not be examined, and no one can answer the approval card` | [Tool errors](#reading-a-local-file-from-outside-the-connected-folders) |
| `WebFetch cannot fetch localhost or other hostnames without a dot` | [Tool errors](#webfetch-cannot-fetch-localhost) |
| `Can't open MCP settings while no terminal is attached to this background session` | [Background session errors](#commands-refused-in-a-background-session) |
| `Can't open MCP settings in a background session` | [Background session errors](#commands-refused-in-a-background-session) |
| `blocked because the path is spelled in a form that cannot be safely resolved` | [Background session errors](#write-or-command-blocked-because-the-path-cannot-be-safely-resolved) |
| `blocked because the path is network-shaped` | [Background session errors](#write-or-command-blocked-because-the-path-names-a-network-location) |
| `is isolated in the worktree <path>, but this command <reason>. Refusing to run it` | [Background session errors](#command-blocked-by-the-worktree-isolation-checks) |
| `too complex to verify that it stays inside the worktree` | [Background session errors](#command-blocked-by-the-worktree-isolation-checks) |
| `This session has no saved transcript` | [Background session errors](#this-session-has-no-saved-transcript) |
| `Can't open — this session is running in another terminal` | [Background session errors](#this-session-is-running-in-another-terminal) |
| `This conversation is already open in another running Claude session` | [Background session errors](#this-session-is-running-in-another-terminal) |
| `This session's saved conversation is no longer on disk` | [Background session errors](#this-sessions-saved-conversation-is-no-longer-on-disk) |
| `kept <id> — its worktree is still at <path>` | [Background session errors](#worktree-has-commits-that-are-not-pushed-anywhere) |
| `kept <id> — <n> unpushed commits on <branch>` | [Background session errors](#worktree-has-commits-that-are-not-pushed-anywhere) |
| `kept <id> — worktree has commits that are not pushed anywhere` | [Background session errors](#worktree-has-commits-that-are-not-pushed-anywhere) |
| `terminal host process died — press Enter to restart` / `This session's terminal host process died` | [Background session errors](#terminal-host-process-died) |
| `Session isn't responding` / `Press enter again to restart this session — it isn't responding` | [Background session errors](#session-isnt-responding) |
| `Session <id> was stopped while the respawn was in flight` | [Background session errors](#session-was-stopped-while-the-respawn-was-in-flight) |
| `This session was running agent '<name>', which is no longer available` | [Background session errors](#session-agent-no-longer-available) |
| `CLAUDE_CODE_PROCESS_WRAPPER: launcher ...` | [Background session errors](#claude_code_process_wrapper-launcher-errors) |
| `EUNKNOWN: unknown error, uv_spawn` | [Background session errors](#eunknown-when-starting-a-background-session) |
| `EACCES: permission denied, posix_spawn` | [Background session errors](#eacces-when-starting-a-background-session) |
| `exited before it became reachable` | [Background session errors](#background-service-exited-before-it-became-reachable) |
| `Couldn't start a background session (working directory no longer exists or is not accessible: ...)` | [Background session errors](#working-directory-no-longer-exists-when-starting-a-background-session) |
| `Workspace not trusted.` when starting or restarting a background session | [Background session errors](#workspace-not-trusted-when-dispatching-a-background-session) |
| `Claude Code is being updated by npm on this machine (still not runnable after 2 min, ...)` | [Background session errors](#eacces-when-starting-a-background-session) |
| `Claude Code process exited with code N` | [Wrapper and IDE errors](#claude-code-process-exited-with-code-n) |
| `The connection to Claude Code ended before this message completed` | [Wrapper and IDE errors](#the-connection-to-claude-code-ended-before-this-message-completed) |
| `Could not locate the Claude CLI on PATH` | [Wrapper and IDE errors](#could-not-locate-the-claude-cli-on-path) |
| `Restored the code, but skipped N files` | [Rewind warnings and errors](#restored-the-code-but-skipped-files) |
| `No files were restored: N files failed (backup missing, or the file could not be updated)` | [Rewind warnings and errors](#no-files-were-restored) |
| `Transcript writes are failing (...)` | [Session saving warnings](#transcript-writes-are-failing) |
| `Transcript saving is off — CLAUDE_CODE_SKIP_PROMPT_HISTORY is set` | [Session saving warnings](#transcript-saving-is-off-skip-prompt-history) |
| `Transcript saving is off — inherited CLAUDE_CODE_CHILD_SESSION marker` | [Session saving warnings](#transcript-saving-is-off-child-session-marker) |
| `Claude Code's fullscreen renderer didn't finish starting last time on this machine` / `Claude Code's fullscreen renderer has repeatedly failed to start on this machine` | [Configuration warnings](#fullscreen-failed-start-notice) |
| `Claude Code exited after an unrecoverable interface error (...)` | [Configuration warnings](#exited-after-an-unrecoverable-interface-error) |
| `Agent descriptions are over the 15.0k-token limit` | [Configuration warnings](#agent-descriptions-are-over-the-15000-token-limit) |
| `Not loaded: rename <path>, then restart — its name uses "<name>", a name reserved for the skills synced from your claude.ai account` | [Configuration warnings](#a-skill-command-or-workflow-wasnt-loaded-because-its-name-is-reserved) |
| `Ignoring N permissions.allow entries from ... this workspace has not been trusted` | [Configuration warnings](#workspace-has-not-been-trusted) |
| `is a network path, which cannot be added as a working directory` | [Configuration warnings](#working-directory-is-a-network-path) |
| `Remote managed settings failed to load (<cause>)` | [Configuration warnings](#remote-managed-settings-failed-to-load) |
| `Managed settings were not approved; exiting without applying them.` | [Configuration warnings](#managed-settings-were-not-approved) |
| `Claude Code can't start: your organization's managed settings block the default model` / `Claude Code can't start: your organization allows only the models listed in "availableModels"` | [Configuration warnings](#managed-settings-block-the-default-model) |
| `MCP server <name> is blocked by enterprise managed policy` | [Configuration warnings](#mcp-server-is-blocked-by-enterprise-managed-policy) |
| `Managed settings document could not be parsed as a JSON object; none of its settings are in effect. Fix or remove it.` | [Configuration warnings](#managed-settings-document-could-not-be-parsed) |
| `Managed settings drop-in directory could not be read` | [Configuration warnings](#managed-settings-document-could-not-be-parsed) |
| `otelHeadersHelper failed; telemetry is not being exported. See /status: ...` | [Configuration warnings](#otelheadershelper-failed) |
| `"crossSessionInbound" must be one of "accept", "hold", "refuse"` | [Configuration warnings](#crosssessioninbound-must-be-one-of-accept-hold-refuse) |
| `headersHelper not run — this workspace has no persisted trust` | [Configuration warnings](#headershelper-not-run) |
| `Invalid permission rule "..." was skipped: Malformed Tool(content) rule` | [Configuration warnings](#malformed-tool-content-rule) |
| `... is not matched by file permission checks` | [Configuration warnings](#is-not-matched-by-file-permission-checks) |
| `... has a wildcard before the rest of the command` | [Configuration warnings](#has-a-wildcard-before-the-rest-of-the-command) |
| `CLAUDE_CODE_DISABLE_1M_CONTEXT is set, but the 200K limit isn't enforced` | [Configuration warnings](#the-200k-limit-isnt-enforced) |
| `[claude-code:unrecognized_model]` | [Configuration warnings](#unrecognized-model-id-on-a-request) |
| `Stale sandbox mask files left by a killed session` | [Configuration warnings](#stale-sandbox-mask-files-left-by-a-killed-session) |
| Responses seem lower quality than usual | [Response quality](#responses-seem-lower-quality-than-usual) |
[](#automatic-retries)
Automatic retries
Claude Code retries transient failures up to 10 times with exponential backoff before showing you an error. It doesn’t always retry a failure that arrives partway through Claude’s response. When you see one of the errors on this page, Claude Code has already made whatever retries apply to that failure. Claude Code retries these failures:
- Server errors, overloaded responses, and request timeouts that arrive before any of Claude’s response has streamed.
- Dropped connections. When a connection drops partway through a request before Claude has completed any part of its response, including its thinking, Claude Code re-issues the request with the same backoff and the turn continues, even if some text had already started streaming. When it drops after Claude has finished thinking but before it has started any text or tool call, Claude Code instead re-issues the request up to two times in quick succession, and ends the turn with `Connection lost before a response was produced` if the connection keeps dropping at that point.
- A connection that Claude Code detects was broken by your computer going to sleep partway through a request. Claude Code counts it as a dropped connection under the rules above; once the retry label names the specific reason, it reads `Connection lost while your computer was asleep`, and if the turn ends after Claude has finished thinking but before any text or tool call, the message reads `Your computer went to sleep before a response was produced`.
- A stalled response stream, when the response headers have arrived but none of Claude’s response has arrived, or when Claude has finished thinking but hasn’t started any text or tool call: Claude Code aborts the stalled connection and re-issues the request at most once, outside the 10-attempt budget above. If the response stalls a second time after Claude has finished thinking but before any text or tool call, Claude Code ends the turn with `The response stalled before a response was produced`.
- A streaming request the API never answers with response headers, on a connection where the [first-byte deadline runs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs): Claude Code aborts it at the deadline and re-sends it at most once per model request, within the retry budget, then ends the turn with [No response from API](#no-response-from-api) if that attempt goes unanswered too. On other connections, the request waits out `API_TIMEOUT_MS`. When you set `CLAUDE_CODE_RETRY_WATCHDOG`, the one-retry cap doesn’t apply.
- Temporary 429 throttles, but not a gateway’s spend-limit `429`, which isn’t a throttle; see [Spend limit reached](#spend-limit-reached).
- When you’re signed in with a claude.ai subscription, this includes 429 throttles that don’t carry your plan’s quota headers. Before v2.1.199, Claude Code retried those throttles only for API key and Enterprise sign-ins.
- A request rejected because the input plus `max_tokens` exceeds the context limit. Re-sending it unchanged would fail the same way, so Claude Code retries with a reduced `max_tokens`, and stops retrying and compacts instead in two cases:
- When no reduction can fit, for example when the conversation itself nearly fills the context window.
- When a retry can’t shrink `max_tokens` any further. Before v2.1.218, Claude Code could re-send a reduced request that still didn’t fit, such as when the extended thinking budget exceeded the remaining context, until the retry budget ran out.
- An expired or missing Google Cloud credential on [Google Cloud’s Agent Platform](google-vertex-ai.md), or AWS credentials that fail to load on your machine. Claude Code discards its cached credentials and retries up to two times, then reports the error so you can re-authenticate right away, as described under [Could not load AWS or Google Cloud credentials](#could-not-load-aws-or-google-cloud-credentials). Before v2.1.228, Claude Code retried a failing Google Cloud credential through the full retry budget before showing the error.
- A `401` or `403` from the Anthropic API, directly or through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), while an [`apiKeyHelper`](settings-reference.md#apikeyhelper) script supplies the credential. Claude Code re-runs the script and retries with its fresh output, within the full retry budget. When the script itself fails on the re-run, Claude Code shows [Your apiKeyHelper script is failing](#your-apikeyhelper-script-is-failing) instead.
Before v2.1.227, `Connection lost before a response was produced` read `Connection closed while thinking, before producing a response` and `The response stalled before a response was produced` read `Response stalled while thinking, before producing a response`. Claude Code doesn’t retry these failures:
- A TLS certificate validation failure, such as a TLS-inspecting proxy, a missing `NODE_EXTRA_CA_CERTS` bundle, or an expired certificate. Claude Code reports the error on the first attempt, so you can fix the certificate setup right away; see [SSL certificate errors](#ssl-certificate-errors). Claude Code still retries transient TLS conditions such as a handshake timeout. Before v2.1.199, Claude Code retried certificate failures through the full retry budget before showing the error.
- A server error, dropped connection, or stalled stream that arrives after Claude has completed a block of text or a tool call, or has started one after finishing its thinking, but before it finishes the response. Claude Code doesn’t re-run the request, because that could execute the same tool calls twice. It keeps what Claude completed, runs any tool calls Claude finished, and continues the turn from their results. For what you see in an interactive session and in a non-interactive one, read [The response above may be incomplete](#the-response-above-may-be-incomplete). Before v2.1.199, Claude Code discarded the partial output and reported the whole turn as an error when a server error arrived mid-stream.
- A failure that arrives after Claude has finished the response: nothing needs retrying, so Claude Code keeps the complete response and ends the turn normally.
- An [Amazon Bedrock streaming response with an unexpected content-type](#bedrock-streaming-response-has-an-unexpected-content-type), because the gateway or proxy rewriting the response would rewrite the retry the same way. Requires Claude Code v2.1.208 or later.
- A non-streaming retry of a failed streaming request that gets a success status but [no Claude API message in the body](#api-returned-an-empty-or-malformed-response). Claude Code ends the turn with that error.
- A request that your organization’s policy check denied, which surfaces as an `API Error:` line carrying the denial message. Your organization’s administrators set up the check with [Inference hooks](../04-API-Reference/Other/manage-claude-inference-hooks.md), a Claude Enterprise feature, and the message ends with the instructions they configured, or by default tells you to contact them. Claude Code doesn’t re-send the denied request to the same model or to a [fallback model](model-config.md#fallback-model-chains), because the denial is about the request’s content rather than the model. Before v2.1.239, Claude Code could re-send a denied request, without streaming or on a configured fallback model, before showing you the denial.
[](#what-you-see-while-claude-code-retries-or-waits)
What you see while Claude Code retries or waits
While retrying, the spinner shows a `Retrying in Ns · attempt x/y` countdown after an error label. The label names the specific reason from the first attempt for failures you can act on right away: the network is down, a TLS handshake failed, or you hit a rate limit. For other errors it reads `API error` at first. As of v2.1.198 it switches to the specific reason from the third attempt, or on the final attempt when `CLAUDE_CODE_MAX_RETRIES` allows fewer than three; earlier versions switch only on the final attempt. As of v2.1.198, the usual spinner tip is suppressed during retries. Once the error reason is revealed, if the failure is a 529 overload the line below the countdown also names where to check service status: `status.claude.com` on the Anthropic API, or the provider or gateway host named in the message on other configurations. If no data arrives on the response stream for 20 seconds while a request is still pending, the spinner shows `Waiting for API response · will retry in … · check your network` before any retry has started. The request hasn’t failed yet: the countdown runs to the point where Claude Code aborts the stalled connection. After the abort, what you see depends on how far the response had got:
- Before Claude has completed a block of text or a tool call, or started one after finishing its thinking, Claude Code retries the request or ends the turn with an error. [Automatic retries](#automatic-retries) says which stalls it retries and how many times.
- After Claude has completed a block of text or a tool call, or started one after finishing its thinking, but before Claude has finished the response, Claude Code keeps what Claude completed, continues the turn from any tool calls Claude finished, and shows [The response above may be incomplete](#the-response-above-may-be-incomplete). In a non-interactive session, and for a subagent’s response in any session, Claude Code may first prompt Claude to continue the response; that entry says when it does and when you still see the notice there.
- After Claude finished the response, Claude Code ends the turn normally.
The banner clears on its own once data resumes or a retry succeeds. If it reappears on every attempt, treat it as a [network issue](#unable-to-connect-to-api). Before v2.1.185, the banner appeared after 10 seconds with different wording. While Claude is consulting the [advisor](advisor.md), the banner appears after 90 seconds without data instead of 20, because a long advisor review can send nothing for well over 20 seconds. Before v2.1.214, the 20-second threshold applied during advisor calls too, so the banner appeared during advisor reviews even when nothing was wrong.
[](#tune-retry-behavior)
Tune retry behavior
You can tune retry behavior with these environment variables:
| Variable | Default | Effect |
|:-----------------------------------------------------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`CLAUDE_CODE_MAX_RETRIES`](env-vars.md) | 10 | Number of retry attempts. Capped at 15 as of v2.1.186; as of v2.1.199 `CLAUDE_CODE_RETRY_WATCHDOG` raises the default and removes the cap. Lower it to surface failures faster in scripts. |
| [`CLAUDE_CODE_RETRY_WATCHDOG`](env-vars.md) | unset | Set to `1` in unattended sessions such as CI jobs to retry `429` and `529` capacity errors indefinitely instead of failing after `CLAUDE_CODE_MAX_RETRIES` attempts. Claude Code fails at once when a standard-speed request gets a `429` that reports a spend limit or exhausted usage credits, even one from a [gateway spend cap](#spend-limit-reached) that resets on a schedule. Before v2.1.239, the watchdog retried these indefinitely. For fast mode requests, see [Handle rate limits](fast-mode.md#handle-rate-limits). On v2.1.199 or later it also raises the default retry count for other transient errors, such as server errors, timeouts, and dropped connections, to 300, roughly three hours of backoff, and removes the cap of 15 on `CLAUDE_CODE_MAX_RETRIES` if you set that variable explicitly. |
| [`API_TIMEOUT_MS`](env-vars.md) | 600000 | Per-request timeout in milliseconds. Raise it for slow networks or proxies. It also caps how long Claude Code waits for response headers, described in [No response from API](#no-response-from-api). |
| [`CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS`](env-vars.md) | unset | Deadline in milliseconds for the first response byte of a streaming request. Requires Claude Code v2.1.242 or later. For how Claude Code picks the deadline when this is unset, see [No response from API](#no-response-from-api). |
[](#server-errors)
Server errors
Most of these errors come from the inference provider: Anthropic’s service on the Anthropic API, and the service behind that provider’s endpoint on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or a custom gateway. [Auto mode cannot determine the safety of an action](#auto-mode-cannot-determine-the-safety-of-an-action) and [Agent terminated early due to an API error](#agent-terminated-early-due-to-an-api-error) also cover causes on your side, such as an Amazon Bedrock account that can’t invoke the classifier model or a subagent that hit a usage limit.
[](#api-error-500-internal-server-error)
API Error: 500 Internal server error
Claude Code shows the status code and the API’s error message for any 5xx response. The example below shows a 500 response on the Anthropic API:
```python
API Error: 500 Internal server error. This is a server-side issue, usually temporary — try again in a moment. If it persists, check https://status.claude.com.
```
The trailing sentence names where to check service health and varies by provider. Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry configurations name that provider’s service status. A custom `ANTHROPIC_BASE_URL` names the gateway host. A 5xx from the API itself indicates an unexpected failure inside the API. It is not caused by your prompt, settings, or account. When a proxy, load balancer, or gateway answers with an HTML error page, the message shows the status code and the page’s title, such as `API Error: 502 Bad Gateway`. For a page with no title, the message shows the status code and its standard name instead. Before v2.1.281, the status code was dropped when the page had a title, and the page’s raw markup was printed when it had none. **What to do:**
- Check [status.claude.com](https://status.claude.com), or the provider status page named in the message, 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](#report-an-error) if `/feedback` is unavailable in your environment.
[](#api-error-repeated-529-overloaded-errors)
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:
```python
API Error: Repeated 529 Overloaded errors. The API is at capacity — this is usually temporary. Try again in a moment. If it persists, check https://status.claude.com.
```
The trailing sentence varies by provider in the same way as the 500 error above. A 529 is not your usage limit and doesn’t count against your quota. **What to do:**
- Check [status.claude.com](https://status.claude.com), or the provider status page named in the message, 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`. On Fable models the message names Fable. In a session the Claude Desktop app runs, such as the Code tab or Cowork, the message reads `Opus is experiencing high load. Switch to Sonnet.` and you switch models with the app’s model picker.
[](#request-timed-out)
Request timed out
The API didn’t respond before the connection deadline.
```python
Request timed out
```
This can happen during periods of high load or when the model is generating a very large response. The default request timeout is 10 minutes. **What to do:**
- Retry the request
- If a slow network or proxy is the cause, raise `API_TIMEOUT_MS` as described in [Automatic retries](#automatic-retries)
- If timeouts are frequent and your network is otherwise healthy, see [Network and connection errors](#network-and-connection-errors) below
[](#no-response-from-api)
No response from API
Claude Code sent a streaming request and the API returned no response headers within the deadline for the first byte, so Claude Code aborted the request instead of waiting for the full `API_TIMEOUT_MS` request timeout, 10 minutes by default. Claude Code sends the request again at most once, if the [retry budget](#tune-retry-behavior) allows. When the retry goes unanswered too, the turn ends with this message, which shows how long each attempt waited. When you set [`CLAUDE_CODE_RETRY_WATCHDOG`](env-vars.md), the one-retry cap doesn’t apply and Claude Code retries under the budget described in [Tune retry behavior](#tune-retry-behavior).
```python
API Error: No response from API (waited 3m, then 10m on the retry). If a proxy or gateway on your network holds responses until they complete, raise API_TIMEOUT_MS or CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS to wait longer.
```
Claude Code sets the first attempt’s wait for response headers and the retry’s wait separately:
- **First attempt**: [`CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS`](env-vars.md) when you set it to 1 or more, clamped to between 10 seconds and 30 minutes. Otherwise Claude Code uses the byte-level watchdog timeout listed in [Streaming idle watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs), so the variables that change that timeout change this wait too. Either way, Claude Code adds one second for every 32KB of request body.
- **Retry**: one second less than `API_TIMEOUT_MS`, just under 10 minutes by default, so that the retry can outlast a proxy or gateway that holds the response until generation completes. On Amazon Bedrock, the retry uses the same deadline as the first attempt, and the message shows one duration instead of two.
Neither wait exceeds one second less than a positive `API_TIMEOUT_MS`, and a positive `API_TIMEOUT_MS` under 11 seconds turns the deadline off. The byte-level watchdog starts only once the response headers arrive, so a response that stops sending bytes after that follows the [stalled-stream rules](#automatic-retries) instead of this deadline. **What to do:**
- 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 it repeats, treat it as a [network or proxy problem](#unable-to-connect-to-api).
- If a proxy or gateway on your network holds responses until they complete, raise `API_TIMEOUT_MS` so the retry waits longer. On Amazon Bedrock, raise `CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS` as well.
- If the first attempt keeps timing out and the retry then succeeds, raise `CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS` so the first attempt waits long enough too.
Before v2.1.242, Claude Code waited for the full `API_TIMEOUT_MS` request timeout, 10 minutes by default, before failing an unanswered streaming request. Before v2.1.261, the retry waited the same deadline as the first attempt and the message showed no durations.
[](#the-response-above-may-be-incomplete)
The response above may be incomplete
A streaming request failed while the response was still in progress, after Claude had completed a block of text or a tool call, or had started one after finishing its thinking. Re-sending the request could run the same tool calls twice, so Claude Code keeps the output Claude completed and appends this notice instead of discarding the turn. Which variant you see names the cause:
```python
API Error: Server error mid-response. The response above may be incomplete.
API Error: Connection lost mid-response. The response above may be incomplete.
API Error: Your computer went to sleep mid-response. The response above may be incomplete.
API Error: The response stopped arriving. The response above may be incomplete.
API Error: Part of the response never arrived. The response above may be incomplete.
API Error: The response stream was malformed. The response above may be incomplete.
```
- `Server error mid-response`: a mid-stream overloaded or 5xx server error. This variant requires Claude Code v2.1.199 or later; before then that case discarded the partial output and reported the whole turn as an error.
- `Connection lost mid-response`: the connection dropped. You also see this variant when a proxy or gateway ends the response body cleanly before the response has finished.
- `Your computer went to sleep mid-response`: Claude Code detected that your computer went to sleep while the response was streaming. Once your computer wakes, Claude Code treats the connection as broken and stops reading from it.
- `Part of the response never arrived`: a stream event was dropped between the API and Claude Code, so a later event referenced content that never arrived. Before v2.1.281, this case ended the turn with `API Error: Content block not found`.
- `The response stream was malformed`: an event arrived for a content block that had already finished, or an event arrived damaged. A damaged event is one whose data isn’t valid JSON, whose content is missing, or whose content doesn’t match the event’s type. Before v2.1.284, the parser’s raw error, such as one beginning `API Error: JSON Parse error`, appeared instead when an event with invalid JSON arrived after Claude had completed its thinking, a block of text, or a tool call.
- `The response stopped arriving`: the connection stayed open but stopped delivering data, so the streaming idle watchdog aborted it. Before v2.1.222, Claude Code could also report this failure on [gateway](../13-Enterprise-Admin/gateways.md) connections reached through `ANTHROPIC_BASE_URL` or `ANTHROPIC_AWS_BASE_URL` while the server’s keep-alive pings were still arriving, because it counted only parsed response events there; upgrading stops those spurious timeouts on those routes. Gateways reached through a provider base URL such as `ANTHROPIC_BEDROCK_BASE_URL` aren’t wrapped by the byte watchdog; see [Streaming idle watchdogs](../13-Enterprise-Admin/network-config.md#streaming-idle-watchdogs).
Before v2.1.227, `Connection lost mid-response` read `Connection closed mid-response` and `The response stopped arriving` read `Response stalled mid-stream`. When a dropped, duplicated, or damaged stream event arrives before Claude has started any text or tool call, you don’t see this notice:
- If Claude had completed only its thinking, Claude Code re-issues the request. When the re-issued streams break the same way, the turn ends with `Part of the response never arrived and no response was produced. Try again.` or `The response stream was malformed and no response was produced. Try again.`
- If nothing had completed, Claude Code re-sends the request without streaming instead. If you turned that fallback off with [`CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK`](env-vars.md), the turn ends with `API Error: Content block not found` for a dropped event or `API Error: Content block already closed` for a duplicated one. For a damaged event with the fallback off, the turn ends with `API Error: Stream event unreadable` or the parser’s raw error.
In four cases, Claude Code handles the failure without showing this notice right away:
- Earlier in the response, Claude Code either retries the failure or ends the turn with a different error. See [Automatic retries](#automatic-retries).
- When one of these failures arrives after Claude has finished the response, Claude Code keeps the complete response and ends the turn normally, without this notice. Before v2.1.222, Claude Code showed this notice when the connection dropped or stalled after the response finished, and reported the turn as an error even though the response was complete.
- In a [non-interactive session](headless.md), such as a `-p` run, an [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) run, or a [cloud session](claude-code-on-the-web.md), you don’t have to send `continue` yourself when the cut-off response is in the main conversation and contains text but no tool calls: Claude Code keeps the partial output and prompts Claude to continue from where it stopped, up to three times in a row. You see this notice for such a response only once Claude Code has used up those continuations. Before v2.1.246, Claude Code ended a non-interactive turn with this notice on the first cut-off.
- In a [subagent](../09-Agents-Patterns/sub-agents.md#api-errors-in-subagents), whether the session is interactive or not: when its cut-off response contains text but no tool calls, Claude Code prompts the subagent to continue. The notice becomes the subagent’s last message only once those continuations are used up. Before v2.1.257, a subagent showed this notice on the first cut-off.
**What to do:**
- In an interactive session, read the response that remains on screen: Claude Code keeps every block Claude completed before the error, but discards an interrupted final block when the turn ends, so the final sentences or tool calls may be missing. Reply with `continue` to have Claude pick up from its last completed block.
- In [non-interactive mode](headless.md) (`-p`):
- With the default text output, Claude Code prints the last completed block of text it still holds from earlier in the turn, followed by this message. When it holds none, Claude Code prints this message alone, for example because Claude Code compacted the conversation mid-turn and cleared that text. Before v2.1.219, Claude Code printed only this message in `-p` text output and dropped the response it had already produced.
- With `--output-format json` or `stream-json`, Claude Code reports this message in the `result` field.
- To continue the turn once the connection is stable, resume the session and send `continue` as described in [Continue conversations](headless.md#continue-conversations).
[](#auto-mode-cannot-determine-the-safety-of-an-action)
Auto mode cannot determine the safety of an action
The model that [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) uses to classify actions couldn’t produce a decision, so auto mode didn’t approve the action automatically. The message you see depends on how 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 unavailable:
```python
<model> is temporarily unavailable, so auto mode cannot determine the safety of <tool> right now. Wait a moment and then try this action again.
```
When Claude Code can determine the failure category, it names the category in parentheses after `temporarily unavailable`, for example `<model> is temporarily unavailable (rate-limited), so auto mode cannot determine the safety of <tool> right now`. The categories are `(rate-limited)`, `(overloaded)`, `(server error)`, `(timed out)`, and `(connection failed)`. If `(timed out)` or `(connection failed)` repeats, check your connection; see [Unable to connect to API](#unable-to-connect-to-api). Before v2.1.229, the message never named a category and read `Wait briefly and then try this action again`. When no category fits, the message appears with no category in parentheses; more than one failure produces that form. On [Amazon Bedrock](amazon-bedrock.md), including the [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint), it also appears when your AWS account can’t invoke the model named in the message, and that failure repeats on every retry until your account is granted access to the model. **What to do:**
- Retry after a few seconds; Claude sees the same message and usually retries on its own. A transient failure is unrelated to [auto mode eligibility](permission-modes.md#eliminate-prompts-with-auto-mode); you don’t need to change settings
- If retries keep failing, continue with read-only tasks and come back to the blocked action later
- On Amazon Bedrock, if the message returns on every retry, check that your account can invoke the model it names: for standard Amazon Bedrock models, confirm your [IAM policy](amazon-bedrock.md#iam-configuration) allows invoking it; for Mantle model IDs, [contact your AWS account team](amazon-bedrock.md#mantle-endpoint-errors)
When a classifier request fails because your OAuth token expired or was rotated by another session, Claude Code refreshes the token and retries the request once, so a routine token expiry doesn’t surface as this message. Before v2.1.216, an expired or rotated token failed each classifier request, and auto mode denied every checked action with this message until the token was refreshed. When the classifier returned an unparseable response:
```python
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 for details in the debug log
When a separate API safety check blocked the classifier request because of earlier conversation content:
```python
Auto mode could not evaluate this action and is blocking it for safety — a safety check separate from auto mode blocked this request because of earlier conversation content — it isn't about the action itself — run with --debug for details
```
Claude Code denies the action but tells Claude this isn’t a judgment that the action is unsafe, and to continue with other tasks rather than retry. These denials don’t count toward [auto mode’s pause thresholds](permission-modes.md#when-auto-mode-falls-back). In a [non-interactive](headless.md) `-p` run, Claude Code doesn’t stop the run. What Claude receives depends on where it requested the action:
- To a [background subagent](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) in a `-p` run without `--input-format stream-json`, Claude Code returns an error result containing `Agent aborted: auto mode classifier request refused by the safety safeguard in headless mode`
- Everywhere else, including interactive sessions and the main conversation of a `-p` run, Claude Code returns that denial to Claude
Before v2.1.225, Claude Code counted these refusals toward the pause thresholds and returned the same rejection message as a genuine classifier block. **What to do:**
- This is not a decision about your action. Content already in your conversation triggered a safety filter on the API when auto mode sent the conversation to the classifier
- Retrying will not help; the same conversation content will trigger the filter again
- In an interactive session, switch to a different [permission mode](permission-modes.md) so you can approve the action when prompted
- Start a fresh conversation without the triggering content
When the conversation has grown larger than the classifier’s context window:
```python
Auto mode classifier transcript exceeded context window — falling back to manual approval (try /compact to reduce conversation size)
```
What happens to the action depends on where Claude requested it:
- In an interactive session, auto mode falls back to a normal permission prompt for that action so you can approve or deny it manually
- To a [background subagent](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) in a [non-interactive](headless.md) `-p` run without `--input-format stream-json`, Claude Code returns an error result containing `Agent aborted: auto mode classifier transcript exceeded context window in headless mode`, and the run continues
- Elsewhere in a `-p` run without a [`--permission-prompt-tool`](cli-reference.md#cli-flags), there is no prompt to fall back to, so the action doesn’t run and the run continues
**What to do:**
- In an interactive session, approve or deny the action in the prompt that appears
- In an interactive session, run `/compact` to reduce the conversation size so subsequent actions fit within the classifier window again
[](#the-server-returned-no-safety-verdict)
The server returned no safety verdict
Under [server-side classifier review](permission-modes.md#server-side-classifier-review), auto mode denies an action when the server gives no verdict for it. The denial names a category in parentheses when Claude Code can determine one, such as `(timed out)`:
```python
The server-side auto mode classifier gave no verdict (timed out), so auto mode cannot determine the safety of <tool>.
```
The rest of the message tells Claude whether one retry can help. Before some of these denials, Claude Code waits so that Claude’s next attempt doesn’t follow at once. During the wait in an interactive session, the spinner shows `Auto mode check unavailable` with a countdown, and pressing `Esc` interrupts the turn. After ten responses in a row with no verdict, auto mode stops the turn:
```python
Auto mode is unavailable — the server returned no safety verdict for the last 10 responses, so Claude stopped. Send a message to try again, or switch out of auto mode.
```
The stop message appears in a different place in each kind of session:
- In an interactive session, the message appears as a warning in the transcript and the turn ends
- In a [non-interactive](headless.md) `-p` run, the run ends and reports an execution error. With the default text output, the message prints on stderr.
- When a [subagent](../09-Agents-Patterns/sub-agents.md) hit the limit, the subagent stops before finishing, and Claude receives whatever it produced with a note that auto mode stopped it
**What to do:**
- Send another message to have Claude try again. The count of responses starts over.
- If the stop repeats and your requests go through an [LLM gateway or proxy](../13-Enterprise-Admin/llm-gateway.md), check whether it cuts streaming responses short or rewrites them. [Server-side classifier review](permission-modes.md#server-side-classifier-review) says which gateway behavior causes denials, and the [gateway compatibility guide](../13-Enterprise-Admin/llm-gateway-protocol.md#feature-pass-through) lists what to pass through unchanged.
- Set `CLAUDE_CODE_AUTO_MODE_SERVER=0` before you start Claude Code to use its own classifier requests instead. Before v2.1.281, Claude Code didn’t read the variable on a direct connection to the Anthropic API.
- To approve the actions yourself instead, [switch out of auto mode](permission-modes.md#switch-permission-modes)
Before v2.1.280, Claude Code denied each action from a response without a verdict immediately and never stopped the turn.
[](#agent-terminated-early-due-to-an-api-error)
Agent terminated early due to an API error
A [subagent](../09-Agents-Patterns/sub-agents.md)’s API request failed terminally, for example because a usage limit was reached or retries for a server error ran out, so the subagent stopped before finishing its task. This message requires Claude Code v2.1.199 or later; before then the API error text was returned to Claude as if it were the subagent’s result.
```python
Agent terminated early due to an API error: <error detail>
```
**What to do:**
- Match the error detail after the colon to its own section on this page, such as [Usage limits](#usage-limits) or [Server errors](#server-errors), and follow that section’s steps
- Once the underlying error clears, ask Claude to retry the task or [resume the subagent](../09-Agents-Patterns/sub-agents.md#resume-subagents)
When a rate limit, overload, or server error interrupts a foreground subagent that already produced text output, Claude receives that partial output marked as incomplete instead of this error. A subagent whose only output was tool calls gets this error too; in v2.1.199 that shape returned an empty partial result instead. See [API errors in subagents](../09-Agents-Patterns/sub-agents.md#api-errors-in-subagents).
[](#usage-limits)
Usage limits
Most errors in this section mean a quota tied to your account or plan has been reached. Three work differently: [`Server is temporarily limiting requests`](#server-is-temporarily-limiting-requests) is a server-side throttle unrelated to your plan quota, [`Usage credits required for 1M context`](#usage-credits-required-for-1m-context) is an entitlement check rather than an exhausted quota, and [`The prompt to confirm went unanswered`](#the-prompt-to-confirm-went-unanswered) means a usage-credits consent prompt closed unanswered, whether or not a quota was reached.
[](#youve-hit-your-session-limit)
You’ve hit your session limit
Subscription plans include a rolling usage allowance. When it runs out you see one of these messages:
```python
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
You've hit your Sonnet limit · resets 3:45pm
```
Claude Code blocks further requests until the reset time shown in the message. The session and weekly limits are shared across all models, so switching models doesn’t restore access. The Opus and Sonnet limits each apply only to requests to that model family, so switching to a model outside the family with `/model` keeps you working. In an interactive session signed in with a claude.ai subscription, Claude Code can also wait in the open session and continue the interrupted task shortly after the reset. While it waits, a line at the bottom of the session reads `Usage limit reached · continuing automatically at 3:45pm · esc to cancel`. Press `Esc` at an empty prompt to cancel the wait. See [Wait for a usage limit to reset](interactive-mode.md#wait-for-a-usage-limit-to-reset) for what you see, how to start or cancel a wait, and how to turn automatic continue off. Before v2.1.234, Claude Code didn’t offer this wait. Usage counts against the session and weekly allowances at the same time. A single burst of heavy activity, such as a large workflow fanout, can exhaust the weekly allowance before the session window resets. **What to do:**
- Wait for the reset time shown in the error
- In the Code tab of the [Desktop app](../16-Mobile-Desktop/desktop.md), the session-limit card offers an **Auto-continue when limits reset** checkbox. The weekly-limit card doesn’t. When it’s checked, the Desktop app retries the interrupted turn after the reset and shows the retry time on the card. The Desktop checkbox and the CLI’s **Continue automatically at usage limit** setting in `/config` are separate, so turn each off on its own.
- For the Opus or Sonnet limit, run `/model` and switch to a model outside that family to keep working. Each model has its own prompt cache, so the next request re-reads the whole conversation with no cache hits; see [Switching models](prompt-caching.md#switching-models)
- Run `/usage` to see your plan limits and when they reset
- Run `/usage-credits` to buy additional usage on Pro and Max, or to request it from your admin on Team and Enterprise. See [usage credits for paid plans](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) for how this is billed.
- To upgrade your plan for higher base limits, see [claude.com/pricing](../17-Billing-Plans/pricing.md)
Before a window runs out, Claude Code can warn you that you’ve used most of it, with a message such as `You've used 85% of your session limit · resets 3:45pm`. To watch your remaining allowance continuously, add the `rate_limits` fields to a [custom status line](statusline.md#rate-limit-usage), or in the Desktop app click the [usage ring](../16-Mobile-Desktop/desktop.md#check-usage) next to the model picker.
[](#usage-credits-required-for-1m-context)
Usage credits required for 1M context
The selected model uses the 1M-token extended context window, and your plan only includes it through usage credits.
```python
API Error: Usage credits required for 1M context · run /usage-credits to turn them on (they take effect after you restart Claude Code), or /model to switch to standard context
```
In a session the Claude Desktop app runs, the hint names no commands: it points at the claude.ai usage settings page, or on Team and Enterprise plans says to turn on usage credits at claude.ai/admin-settings/usage or to ask your admin. This is an entitlement check, not a quota exhaustion. It fires even when your session and weekly allowances have capacity remaining. See [Extended context](model-config.md#extended-context) for which plans include 1M context directly and which require usage credits. When this error appears mid-conversation because the context grew past 200K tokens, Claude Code automatically compacts the conversation back under the standard context limit and keeps the session at that limit afterward, so no action is needed. On versions before v2.1.172, the error repeated on every subsequent request including `/compact`; run `/clear` on those versions to recover. The steps below apply when you explicitly selected a `[1m]` model. **What to do:**
- Run `/model` and select the variant without the `[1m]` suffix to fall back to the standard context window
- Where the message names `/usage-credits`, run it to turn on metered billing for the 1M variant on Pro and Max, or to request usage credits from your admin on Team and Enterprise. Once usage credits are on, restart Claude Code or start a new session, whichever the message says. Until then, the session stays at the standard context limit.
- If the error persists after `/model`, a 1M model ID may be set elsewhere. See [Setting your model](model-config.md#setting-your-model) for the configuration locations to check in priority order.
- To remove 1M variants from the model picker entirely, set [`CLAUDE_CODE_DISABLE_1M_CONTEXT=1`](env-vars.md)
Before v2.1.268, the message ended with `run /usage-credits to turn them on, or /model to switch to standard context` and didn’t mention restarting.
[](#the-prompt-to-confirm-went-unanswered)
The prompt to confirm went unanswered
If your account requires the [Fable usage-credits consent](model-config.md#fable-and-usage-credits), Claude Code asks you to confirm before a Fable request bills usage credits. When nobody answers that consent prompt in a session that may have no one at its terminal, Claude Code closes the prompt and ends the turn with one of these messages:
```python
Fable limit reached · continuing on Fable 5.1 uses usage credits, and the prompt to confirm went unanswered — nothing was sent · answer it where this session is running, or /model to change
Fable 5.1 now uses usage credits · the prompt to confirm went unanswered — nothing was sent · answer it where this session is running, or /model to change
```
The messages name the session’s Fable model, so on Fable 5 they read `continuing on Fable 5` and `Fable 5 now uses usage credits`. Before v2.1.257, the first message began `Fable 5 limit reached`. This happens in [Remote Control](remote-control.md) sessions, [background sessions](../09-Agents-Patterns/agent-view.md), and [agent team](../09-Agents-Patterns/agent-teams.md) teammate sessions. Claude Code shows the consent prompt only in the session’s own interactive view: the terminal where it runs, or, for a background session, the [agents view](../09-Agents-Patterns/agent-view.md) once you attach. A Remote Control client can’t display it. Claude Code closes the prompt at the [`dialogExpiry`](settings-reference.md#dialogexpiry) deadline, five minutes by default, or as soon as a new prompt arrives while nobody has typed at that terminal, such as a prompt sent from a Remote Control client. Typing at the terminal where the session runs cancels the deadline, and Claude Code waits for your answer. In a background session’s attached view, typing doesn’t cancel the deadline, and a new prompt still closes the consent prompt, so answer before either happens. Claude Code sends nothing and keeps your model, so when you send your next prompt, Claude Code shows the consent prompt again. **What to do:**
- At the terminal where the session runs, send another prompt and answer the consent prompt when it reappears. For a background session, attach to it from the [agents view](../09-Agents-Patterns/agent-view.md) first. Resending from a Remote Control client shows this message again, because the client can’t display the prompt.
- Run `/model` to switch to a model that doesn’t bill usage credits
- To give yourself more time to reach that terminal, set [`dialogExpiry`](settings-reference.md#dialogexpiry) to a longer value or `"never"`
Before v2.1.236, this message didn’t appear: while a Remote Control client was connected, Claude Code waited 60 seconds for an answer and then continued the turn on your default model.
[](#server-is-temporarily-limiting-requests)
Server is temporarily limiting requests
The API applied a short-lived throttle that is unrelated to your plan quota.
```python
API Error: Server is temporarily limiting requests (not your usage limit)
```
Claude Code tells these apart from your plan limit by the absence of the unified quota headers a real limit response carries. As of v2.1.199 this is [retried automatically](#automatic-retries) with backoff before being shown, whichever way you authenticate. On earlier versions, a session signed in with a claude.ai subscription failed the turn on the first occurrence; only API key and Enterprise sign-ins retried it. **What to do:**
- Wait briefly and try again
- Check [status.claude.com](https://status.claude.com) if it persists
[](#request-rejected-429)
Request rejected (429)
You have hit the rate limit configured for your API key, Amazon Bedrock project, or Google Cloud project.
```python
API Error: Request rejected (429) · this may be a temporary capacity issue. If it persists, check https://status.claude.com.
```
The trailing sentence names where to check service health and varies by provider. Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry configurations name that provider’s service status instead of the Anthropic status page. A custom `ANTHROPIC_BASE_URL` names the gateway host. When a proxy, load balancer, or gateway between Claude Code and the API answers with its own HTML 429 page, the text after the `·` is that page’s title when it has one, such as `Too Many Requests`. Before v2.1.281, the whole page’s markup was printed after the `·`. **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](../04-API-Reference/Endpoints/rate-limits.md) for how tiers work and how to set per-workspace caps
- Reduce concurrency: lower [`CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY`](env-vars.md), avoid running many parallel subagents, or switch to a smaller model with `/model` for high-volume scripted runs
[](#youve-hit-your-monthly-spend-limit)
You’ve hit your monthly spend limit
Your plan’s included usage can’t cover this request, and the [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) that would otherwise pay for it have reached a spend limit. That happens when one of your plan’s usage windows has run out, or when the request is one that only usage credits pay for, such as a request to a model that [bills to usage credits](model-config.md#fable-and-usage-credits). The message names whose limit blocked you. The text after the `·` says how to get that limit increased, and varies with your plan and whether you manage billing:
```python
You've hit your monthly spend limit · raise it at claude.ai/settings/usage
You've hit your individual spend limit · ask your admin for a higher limit
You've hit your org's monthly spend limit · visit claude.ai/admin-settings/usage to raise it
You've hit your team's shared budget · ask your admin to raise it at claude.ai/admin-settings/usage
You've hit your channel's monthly spend limit · an org owner or channel manager can raise it in the channel's Claude settings
```
`team's shared budget` is a pooled budget an admin assigned to a group you belong to; the message doesn’t name the group. `channel's monthly spend limit` is the budget of the one Slack channel the session runs in, so your organization may still have budget outside it. When one of your plan’s windows is what ran out, the message also says when that window resets, for example `· your session limit resets 3:45pm`, and access returns then without anyone raising the limit. On organizations with usage-based billing, the message says `usage limit` in place of `spend limit`, as in `You've hit your individual usage limit`. Before v2.1.239, the message didn’t name the plan window’s reset time. Before v2.1.268, a group’s pooled budget produced the `individual spend limit` message instead of `team's shared budget`. If you connect through a Claude apps gateway and see lowercase `spend limit reached`, that is your gateway operator’s cap instead; see [Spend limit reached](#spend-limit-reached). **What to do:**
- On Pro and Max, increase your monthly spend limit in [**Settings \> Usage**](https://claude.ai/settings/usage) on claude.ai, or run `/usage-credits`
- On Team and Enterprise, increase the limit in [**Admin settings \> Usage**](https://claude.ai/admin-settings/usage) if you manage billing, or ask an admin to. `/usage-credits` sends that request to your admin for you
- For a channel’s limit, ask an org owner or the channel’s manager to raise it on claude.ai. See [Per-channel limits](https://claude.com/docs/claude-tag/admins/set-spend-limit#per-channel-limits) in the Claude Tag documentation
- If the message names a reset time for your plan’s window, you can wait for it instead
- Run `/usage` to see your plan’s windows and when each resets
[](#spend-limit-reached)
Spend limit reached
You connect through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) and have passed a [spend cap](../13-Enterprise-Admin/claude-apps-gateway-spend-limits.md) your gateway operator set. The gateway blocks your requests until the named period resets or the operator raises the cap. It marks each blocked `429` response `x-should-retry: false`, so Claude Code shows this message without retrying.
```python
spend limit reached (daily; resets 2026-08-09 00:00 UTC)
```
The message names the cap’s period and reset time, and when the operator configured a `blocked_message`, their instructions follow it. Before v2.1.225, the message read only `spend limit reached`; a gateway on an older version still sends that shorter form. **What to do:**
- Wait for the reset time the message names, or follow the operator’s instructions if the message carries them
- Ask your gateway operator to raise the cap if you hit it routinely
A related message, `spend limit unavailable`, means the gateway could not read its spend records and blocked the request as a precaution rather than over your cap. It usually clears on its own; if it persists, tell your gateway operator.
[](#credit-balance-is-too-low)
Credit balance is too low
Your Console organization has run out of prepaid credits, or Claude Code is sending your requests with a Console API key when you meant to use your subscription.
```python
Credit balance is too low
```
**What to do:**
- If you have a Pro, Max, Team, or Enterprise plan and see this, run `/status` and check the `API key` row. An approved `ANTHROPIC_API_KEY` in your environment routes requests through that key instead of your subscription. Unset it in the current shell and remove it from your shell profile, then relaunch `claude`. Run `/login` if you haven’t signed in with your subscription yet.
- Add credits at [platform.claude.com/settings/billing](../04-API-Reference/Other/usage-limits.md), and consider enabling auto-reload there so the balance refills before it hits zero
- Set per-workspace spend caps in the Console to prevent a single project from draining the org balance. See [Manage costs effectively](../17-Billing-Plans/costs.md).
[](#could-not-update-your-spend-limit)
Could not update your spend limit
The server rejected a spend limit change you made from the prompt that appears when you reach your spend limit.
```python
Could not update your spend limit: <reason from the server>
```
When the server explains the rejection, the message ends with that reason, and retrying the same value fails again. When the failure has no server-provided reason, such as a dropped connection, the message reads `Could not update your spend limit. Press Enter to retry.` and retrying can succeed. Before v2.1.216, Claude Code showed the generic form for every failure. **What to do:**
- If the message includes a reason, choose a limit that satisfies it, such as a lower amount
- If the message shows only the generic form, retry; the failure may be transient
- If the change keeps failing, make it from your [claude.ai billing settings](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) in the browser instead
[](#authentication-errors)
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)
Not logged in
No valid credential is available for this session.
```python
Not logged in · Please run /login
```
In a session the Claude Desktop app runs, such as the Code tab or Cowork, the message reads `Authentication required · Sign in again to continue`, and you sign in again from the app. **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`](settings-reference.md#apikeyhelper) script that fetches a key at startup
- See [Authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) to understand which credential Claude Code uses when several are present
If you are prompted to log in repeatedly, see [Not logged in or token expired](troubleshoot-install.md#not-logged-in-or-token-expired) for system clock checks and macOS credential-storage recovery steps.
[](#could-not-resolve-authentication-method)
Could not resolve authentication method
The session reached the API client without any credential. [Background sessions](../09-Agents-Patterns/agent-view.md) and cloud sessions show this message when the worker starts without a credential. Interactive, `-p`, and Agent SDK runs report the same condition as [Not logged in](#not-logged-in) and write this string only to their debug log, so if you found it there, follow that entry instead.
```python
Could not resolve authentication method. Expected one of apiKey, authToken, credentials, config, or profile to be set. Or for one of the "X-Api-Key" or "Authorization" headers to be explicitly omitted
```
On current versions the error means no credential was available to the worker process. Before v2.1.174, a background session assigned to an idle pre-initialized worker could fail this way even when valid credentials were configured. Before v2.1.176, a cloud session that sat idle before being claimed could too. Upgrade to recover. **What to do:**
- Upgrade to v2.1.176 or later if this appears in a background or cloud session and your credentials are already configured
- Confirm `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`, or your cloud provider credentials are set in the environment that launches the worker, not only in your interactive shell
- For the Agent SDK, see [authentication setup in the quickstart](../05-Agent-SDK/agent-sdk-quickstart.md#setup)
- Run `/status` in an interactive session in the same environment to confirm which credential source resolves
[](#invalid-api-key)
Invalid API key
The `ANTHROPIC_API_KEY` environment variable or `apiKeyHelper` script returned a key the API rejected, or Claude Code blocked a key from `ANTHROPIC_API_KEY` before sending it.
```python
Invalid API key · Fix external API key
```
When the message continues past `Fix external API key` with a description such as `Invalid X-Api-Key header value from ANTHROPIC_API_KEY: it contains a line break at character 41 (120 characters on 2 lines).`, the API never saw the key. Claude Code found a character that HTTP headers can’t carry and stopped the request before sending it. See [Invalid request header value](#invalid-request-header-value) for how to read the description and fix the value. **What to do:**
- Check for typos and confirm the key has not been revoked in the [Console](../04-API-Reference/Other/usage-limits.md)
- In the same shell, run `env | grep ANTHROPIC`, or in PowerShell `Get-ChildItem Env:ANTHROPIC*`. 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`](settings-reference.md#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
[](#your-apikeyhelper-script-is-failing)
Your apiKeyHelper script is failing
Claude Code ran the command in your [`apiKeyHelper`](settings-reference.md#apikeyhelper) setting and didn’t get a key back. Without one, the request reaches the API with a placeholder credential, and the API rejects it with `401`. The `Authentication` panel in the terminal shows which of these happened:
- The command exited with an error or timed out
- The command printed nothing to stdout
- The command printed something besides the key, such as a login banner or a log line. The panel shows `returned output that cannot be used as an API key` and says what’s wrong, without repeating the output. Before v2.1.227, Claude Code sent whatever the command printed, after trimming surrounding whitespace.
```python
Your apiKeyHelper script is failing · This usually means you need to re-authenticate with your provider · Run /status to see the script's error output
```
In [non-interactive mode](headless.md), stderr also carries the specific reason, prefixed with `apiKeyHelper failed:`. Claude Code re-runs the script and retries the request up to two more times before showing this message, so the failure surfaces within three attempts. Before v2.1.208, Claude Code spent the full [retry budget](#automatic-retries) resending the request with the placeholder credential and then reported a generic `401` authentication error instead of the script failure. Running `/login` doesn’t help here: the helper’s output [takes precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) over a saved login for as long as the setting is present. **What to do:**
- Run the command configured in `apiKeyHelper` directly in your shell to reproduce the failure
- If the command reports an expired session, re-authenticate with your credential provider, for example by signing in to your SSO or secrets vault again
- Fix the command so it prints only the key to stdout, as a single token of printable ASCII up to 16,384 characters, and exits with code 0. See [rotate credentials with apiKeyHelper](../13-Enterprise-Admin/llm-gateway-connect.md#rotate-credentials-with-apikeyhelper) for a working setup.
- Run `/status` to see the failure and confirm `apiKeyHelper` is the active credential source. The `apiKeyHelper` row shows `Failing` with the last failure’s detail, such as the exit code and the command’s error output, and disappears after the next successful run. Before v2.1.274, `/status` showed only the credential source, not the failure.
- Each time the command fails, its exit code and error output also appear in an `Authentication` panel in the terminal. Before v2.1.212, the panel was titled `Cloud authentication`.
[](#invalid-request-header-value)
Invalid request header value
A value Claude Code was about to send as a request header contains a character that HTTP headers can’t carry: a line break, a NUL byte, or a character above `U+00FF`, such as a curly quote or a zero-width space. Claude Code stops the request before anything is sent and names the variable or setting to fix. The usual cause is a credential pasted from a document or chat that carried an invisible character or a stray line break. Claude Code runs this check when it sends requests to the Claude API directly or through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). On a third-party cloud provider such as [Amazon Bedrock](amazon-bedrock.md), Claude Code doesn’t run it before sending.
```python
Invalid auth token · Fix external auth token
Invalid ANTHROPIC_CUSTOM_HEADERS · Fix the environment variable
Invalid request header from the environment · Fix the environment variable
```
The first part of the message depends on where the bad value came from:
- `Invalid auth token`: a bearer token from [`ANTHROPIC_AUTH_TOKEN`](env-vars.md) or [`CLAUDE_CODE_OAUTH_TOKEN`](env-vars.md)
- `Invalid ANTHROPIC_CUSTOM_HEADERS`: a header name or value you set in [`ANTHROPIC_CUSTOM_HEADERS`](env-vars.md). The description counts which `Name: Value` pair is at fault, such as `distinct header 2 of 3 parsed from ANTHROPIC_CUSTOM_HEADERS`, without repeating the name or value, since you chose both.
- `Invalid request header from the environment`: a value Claude Code copies into a request header from another environment variable, such as `CLAUDE_AGENT_SDK_CLIENT_APP`. The description names the variable to fix.
Claude Code reports a bad `ANTHROPIC_API_KEY` caught by this check as [Invalid API key](#invalid-api-key), with the same trailing description. It reports a bad saved `/login` credential as [Not logged in](#not-logged-in) instead; run `/login` to save a fresh one. An [`apiKeyHelper`](settings-reference.md#apikeyhelper) script’s output never reaches this check: Claude Code validates it when the script runs, and output an HTTP header can’t carry fails with [Your apiKeyHelper script is failing](#your-apikeyhelper-script-is-failing). After the second `·`, the message describes the problem, as in this full example:
```python
Invalid auth token · Fix external auth token · Invalid Authorization header value from ANTHROPIC_AUTH_TOKEN: it contains a line break at character 41 (120 characters on 2 lines).
```
Positions count characters starting at one. The description is built from fixed phrases and character counts, so it never includes the value itself. It names the offending character only when it is a well-known invisible or typographic character, such as a byte-order mark, a zero-width space, or a curly quote, and reports anything else as `a non-ASCII character`. **What to do:**
- Re-set the variable or setting the message names, retyping the characters around the reported position rather than pasting from the same source again
- For `ANTHROPIC_CUSTOM_HEADERS`, keep one `Name: Value` pair per line and rewrite the pair the message counts
- Run `/status` to confirm which credential source is active
[](#this-organization-has-been-disabled)
This organization has been disabled
Claude Code is using a stale `ANTHROPIC_API_KEY` from a disabled Console organization. When you have a saved subscription login, the key overrides it.
```python
Your ANTHROPIC_API_KEY belongs to a disabled organization · Unset the environment variable to use your subscription instead
Your ANTHROPIC_API_KEY belongs to a disabled organization · Update or unset the environment variable
API Error: 400 ... This organization has been disabled.
```
The hint after the `·` depends on your saved credentials: the first form appears when a stored `/login` can take over after you unset the key, and the second when the key is your only credential. 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`
- If the message says `Update or unset`, you have no saved login to fall back to. Unset the key and run `/login`, or replace the key with one from an active Console organization.
- Run `/status` afterward to confirm the active credential is your subscription
- If no environment variable is set and the error persists, contact support or sign in with a different account.
[](#your-organization-has-disabled-api-key-authentication)
Your organization has disabled API key authentication
This message requires Claude Code v2.1.169 or later. Your Console organization’s admin has turned off API key authentication, so the API rejects the key Claude Code is sending. The recovery hint after the `·` varies by where the key came from:
```python
Your organization has disabled API key authentication · Run /login to sign in with your claude.ai account
Your organization has disabled API key authentication · Unset ANTHROPIC_API_KEY to use your claude.ai account instead
Your organization has disabled API key authentication · Unset ANTHROPIC_API_KEY and run /login to sign in with your claude.ai account
Your organization has disabled API key authentication · Unset the apiKeyHelper setting and run /login to sign in with your claude.ai account
Your organization has disabled API key authentication · Sign in again with your claude.ai account
```
The last form appears in a session the Claude Desktop app runs, such as the Code tab or Cowork, where you sign in again from the app. Environment variables and `apiKeyHelper` take precedence over `/login`, so running `/login` alone doesn’t help while either is still supplying a key. See [Authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence). **What to do:**
- If the message names `ANTHROPIC_API_KEY`, unset it in the current shell and remove it from your shell profile or `.env` file, then relaunch `claude`
- If the message names `apiKeyHelper`, remove the [`apiKeyHelper`](settings-reference.md#apikeyhelper) setting from your `settings.json`
- Run `/login` to sign in with your claude.ai account
- Run `/status` afterward to confirm the active credential is your subscription rather than an API key
- If you need API key authentication for automation, ask your organization admin to re-enable it in the Console
[](#your-organization-has-disabled-claude-subscription-access)
Your organization has disabled Claude subscription access
Your Claude organization doesn’t allow signing in to Claude Code with a subscription login. Running `/login` again with the same account returns the same error.
```python
Your organization has disabled Claude subscription access for Claude Code · Use an Anthropic API key instead, or ask your admin to enable access
```
This is a server-side organization setting, so it can’t be overridden from local settings, environment variables, or CLI flags. The Agent SDK and `-p` non-interactive mode surface this as the `oauth_org_not_allowed` error code. **What to do:**
- Ask your admin to enable Claude Code access for your organization
- Authenticate with a Console API key instead of your subscription. See [Claude Console authentication](../13-Enterprise-Admin/iam.md#claude-console-authentication) for setup.
- If you are the admin and do not see an option to enable access, contact [Anthropic support](https://support.claude.com)
[](#routines-are-disabled-by-your-organizations-policy)
Routines are disabled by your organization’s policy
An Owner in your Team or Enterprise organization has turned off routines at the organization level. The error appears when you try to create or run a routine, for example from the [Routines](web-scheduled-tasks.md) UI on claude.ai/code. On Claude Code v2.1.227 or later, the same setting also [hides `/schedule`](web-scheduled-tasks.md#troubleshooting) in the CLI.
```python
Routines are disabled by your organization's policy.
```
This is a server-side setting, so it can’t be overridden from local settings, environment variables, or CLI flags. **What to do:**
- Ask an Owner in your organization to enable the **Routines** toggle at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code)
- For one-off scheduled work that does not require organization-level routines, see [scheduled tasks](scheduled-tasks.md)
[](#remote-control-requires-the-anthropic-api)
Remote Control requires the Anthropic API
The session isn’t talking to the Anthropic API directly, which [Remote Control](remote-control.md) requires.
```python
Remote Control is only available when using Claude via api.anthropic.com. CLAUDE_CODE_USE_BEDROCK is set, so this session is using Amazon Bedrock — unset it (or run in a shell without it) to use Remote Control.
```
A second sentence explains what routed the session away from the Anthropic API; before v2.1.219, the message was the first sentence alone. Depending on the cause, the message names:
- A `CLAUDE_CODE_USE_*` provider variable, such as `CLAUDE_CODE_USE_BEDROCK` for [Amazon Bedrock](amazon-bedrock.md) or `CLAUDE_CODE_USE_VERTEX` for [Google Cloud’s Agent Platform](google-vertex-ai.md)
- [`ANTHROPIC_BASE_URL`](env-vars.md) pointing at a host other than `api.anthropic.com`, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) or proxy, even when you sign in with claude.ai; before v2.1.196, a custom base URL didn’t block Remote Control
- `ANTHROPIC_UNIX_SOCKET` set, so the session sends its requests through a local socket rather than to `api.anthropic.com`
- An enterprise [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sign-in made through `/login`, which doesn’t support Remote Control and has no variable to unset
**What to do:**
- Unset the variable the message names, such as `CLAUDE_CODE_USE_BEDROCK` or `ANTHROPIC_BASE_URL`, and restart the session, or start Remote Control from a session that talks to the Anthropic API directly
- If the variable isn’t set in your shell, check the `env` key in your [settings files](settings.md#where-settings-live), which applies environment variables to every session
- For this and the other Remote Control startup messages, see [Troubleshoot Remote Control](remote-control.md#troubleshooting)
[](#remote-control-couldnt-refresh-your-login)
Remote Control couldn’t refresh your login
Claude Code runs a live [Remote Control](remote-control.md) connection on short-lived credentials that it obtains and renews using your saved claude.ai login. When claude.ai stops accepting that login, or Claude Code has no saved login left, Claude Code stops Remote Control and needs you to sign in again. Either failure can happen while Claude Code is still connecting or later, when it renews the credentials. When Claude Code asks the login service to refresh your saved login and gets no answer, it keeps Remote Control running and tries the refresh again while the connection’s current credential is still valid. A refresh gets no answer when Claude Code can’t reach the login service, the request times out, or the service fails without rejecting your login. If the login service still isn’t answering when that credential expires, Claude Code stops Remote Control and reports `OAuth token refresh failed`. When Claude Code stops Remote Control, it shows the reason in a warning and in a transcript line that starts with `Remote Control disconnected`. Your local session keeps running without Remote Control. This section covers these lines:
```python
Remote Control disconnected — Claude.ai login expired — run /login to restore Remote Control
Remote Control disconnected — Claude.ai login expired — run /login, then /remote-control
Remote Control disconnected — Claude.ai login was rejected — run /login, then /remote-control
Remote Control disconnected — OAuth token unavailable — run /login to restore Remote Control
Remote Control disconnected — OAuth token refresh failed — run /login to re-authenticate
Remote Control disconnected — JWT refresh failed: no OAuth token — run /login
Remote Control disconnected — Signed out of Claude — run /login, then /remote-control
```
Claude Code names the cause in the middle of the message:
- `Claude.ai login expired` and `Claude.ai login was rejected`: claude.ai no longer accepts your saved login token, because it expired or was revoked
- `OAuth token unavailable`: Claude Code had no saved login token when the connection’s credential came due for renewal
- `OAuth token refresh failed`: claude.ai rejected your saved login token while Claude Code was reconnecting, and refreshing the token produced no new one
- `JWT refresh failed: no OAuth token`: Claude Code found no saved login token to renew with
- `Signed out of Claude`: you signed out on this machine, for example by running `/logout` in another terminal, so Claude Code has no saved login left to renew the connection with
**What to do:**
- Run `/login` to sign in again
- Run `/remote-control` to reconnect the session. Messages ending `run /login to restore Remote Control` don’t need this step: Claude Code reconnects on its own once you sign in.
Before v2.1.224, `OAuth token refresh failed — run /login to re-authenticate` read `OAuth token refresh failed — re-authenticate, then re-enable Remote Control`, and `JWT refresh failed: no OAuth token — run /login` read `no OAuth token available for recovery (code <N>)`. The `Claude.ai login expired`, `Claude.ai login was rejected`, and `OAuth token unavailable` messages were added in v2.1.225. Before v2.1.238, Claude Code reported the cases that now say `Signed out of Claude` as `JWT refresh failed: no OAuth token — run /login`, and stopped Remote Control with `Claude.ai login expired — run /login to restore Remote Control` as soon as one login refresh got no answer.
[](#remote-control-stopped-because-the-signed-in-account-changed)
Remote Control stopped because the signed-in account changed
Claude Code shows this line during a [Remote Control](remote-control.md) session when you sign in to a different claude.ai account or organization on this machine. You made the switch outside the Claude Code session, for example by running `/login` in another terminal. A Remote Control session that you started while signed in through `/login` belongs to the claude.ai account and organization that were signed in at the time.
```python
Remote Control disconnected — signed-in claude.ai account or organization changed on this machine — run /remote-control to start a session for the current account, or /login to switch back, then /remote-control
```
Claude Code stops the Remote Control session as soon as claude.ai confirms that the account or organization changed. Your local session keeps running without Remote Control. **What to do:**
- Run `/remote-control` to start a new Remote Control session under the current account or organization
- To switch back, run `/login` and sign in to the previous account or organization again. Then run `/remote-control`.
Before v2.1.234, Claude Code didn’t notice when you switched to a different account or organization outside the Claude Code session. Claude Code kept the Remote Control session connected until a later request to the Remote Control server failed with `Remote Control server rejected the request (HTTP 404)`. That failure could come hours after the switch.
[](#remote-control-stopped-because-the-app-running-the-session-signed-out-or-switched-accounts)
Remote Control stopped because the app running the session signed out or switched accounts
When the Claude desktop app or an IDE hosts your session, Claude Code gets its login token from that app rather than from `/login`. When claude.ai rejects that token, Claude Code asks the app for a new one. If the app answers that it’s signed out, or that it’s now signed in to a different Claude account, Claude Code ends the [Remote Control](remote-control.md) session and sends the app one of these lines:
```python
Remote Control stopped — the app running this session is now signed in to a different Claude account
Remote Control stopped — the app running this session is signed out of Claude. Sign in there, then turn Remote Control back on
```
Your local session keeps running without Remote Control. **What to do:**
- If the app is signed out, sign in to it again, then turn Remote Control back on in the app
- If the app switched accounts, Claude Code can’t continue the ended session under the new account. Start a new Remote Control session under that account.
Before v2.1.238, Claude Code sent the app the `run /login` messages listed under [Remote Control couldn’t refresh your login](#remote-control-couldnt-refresh-your-login) in both cases.
[](#oauth-token-revoked-or-expired)
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. Both messages report a rejection the API returned for a request Claude Code sent. When the saved login has already been cleared after a failed refresh, you see [Login expired](#login-expired) instead. If you authenticate with a long-lived token in [`CLAUDE_CODE_OAUTH_TOKEN`](env-vars.md), you see the same messages when that token expires or is revoked.
```python
OAuth token revoked · Please run /login
Please run /login · API Error: 401 OAuth token has expired ...
```
**What to do:**
- Run `/login` to sign in again
- If you authenticate with the `CLAUDE_CODE_OAUTH_TOKEN` environment variable, Claude Code keeps sending the value you set after a request fails with a 401, rather than switching to a stored login’s token. [`/status`](commands.md) shows this credential as an `Auth token` row reading `CLAUDE_CODE_OAUTH_TOKEN`. Generate a fresh token with [`claude setup-token`](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token) and restart with it, or unset the variable and run `/login`. Before v2.1.225, Claude Code could replace the variable’s value mid-session with the short-lived access token from a stored login, and the session failed with 401 errors again once that token expired.
- For repeated prompts to log in across launches, see the system clock checks and macOS credential-storage recovery steps in [Troubleshooting](troubleshoot-install.md#not-logged-in-or-token-expired)
- For other failures including `403 Forbidden` and OAuth browser issues, see [Login and authentication](troubleshoot-install.md#login-and-authentication)
[](#api-error-401-invalid-authentication-credentials)
API Error: 401 Invalid authentication credentials
The API recognized the format of your credential but rejected the account or organization behind it. Anthropic returns this message when a credential was recently revoked, when an organization was disabled or removed your access, or when the account itself was deactivated, so an expired token isn’t the cause. The credential can be your saved login or an approved `ANTHROPIC_API_KEY`, and the fix differs, so start by running `/status` to see which one is active.
```python
Please run /login · API Error: 401 Invalid authentication credentials
```
**What to do:**
- If `/status` shows an `API key` row that isn’t marked as not in use, an approved [`ANTHROPIC_API_KEY`](../13-Enterprise-Admin/iam.md#authentication-precedence) is the active credential and takes precedence over your login, so `/login` doesn’t replace it. Rotate the key in the Claude Console, or fall back to your subscription by running `unset ANTHROPIC_API_KEY`, or in PowerShell `Remove-Item Env:ANTHROPIC_API_KEY`.
- If `/status` shows only your login, run `/login` once. If the credential was revoked, a fresh login replaces it.
- If the same message returns for the same login account, the account or organization is no longer active. Check the account and organization that `/status` reports, and ask your organization admin to restore access.
- If [`ANTHROPIC_BASE_URL`](env-vars.md) points at an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), the text after `401` is your gateway’s message rather than Anthropic’s, and `/login` doesn’t change it. Fix the credential your gateway expects instead.
[](#login-expired)
Login expired
Claude Code tried to renew your saved claude.ai login and the OAuth service rejected the stored refresh token, so Claude Code cleared the saved credentials. After that, each model request stops locally with this message before it reaches the API, because only `/login` can create new credentials. Before v2.1.206, Claude Code sent the model request anyway with whatever credential remained in the environment, and every model then failed with [There’s an issue with the selected model](#theres-an-issue-with-the-selected-model) or a 401 instead of a prompt to sign in.
```python
Login expired · Please run /login
```
In [non-interactive mode](headless.md) (`-p`) and the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), the message reads as follows, and the structured error code is `authentication_failed`:
```python
Failed to authenticate: OAuth session expired and could not be refreshed
```
This is not the same state as [OAuth token revoked or expired](#oauth-token-revoked-or-expired). Those messages report a rejection the API returned. Claude Code itself produces `Login expired` for a login it already failed to renew, so it sends no request. When the renewal fails because the account itself is suspended rather than the login being stale, Claude Code shows [Your account is on hold](#your-account-is-on-hold) instead. Sessions authenticated with an API key, [`CLAUDE_CODE_OAUTH_TOKEN`](env-vars.md), or a third-party provider don’t use the saved login and never see this message. You can check for this state before a request fails: [`/status`](commands.md) shows a `Login` row reading `Expired — log in again`, plus the organization and email it has saved for the expired login. The row appears only when the saved login is your active credential and can no longer be refreshed. Sessions authenticated another way don’t show the row, even if an expired login remains saved. Before v2.1.210, `/status` gave no indication in this state that a login had ever existed, because the cleared credential left it nothing to report. **What to do:**
- Run `/login` to sign in again. Retrying without signing in shows the same message on every request.
- In non-interactive mode, run `claude` in the same environment, complete `/login`, then rerun your command. For automation that can’t sign in interactively, authenticate with `ANTHROPIC_API_KEY` or [generate a long-lived token with `claude setup-token`](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token).
- If signing in keeps failing, see [Login and authentication](troubleshoot-install.md#login-and-authentication)
[](#could-not-refresh-your-login)
Could not refresh your login because another Claude Code process is refreshing it
This message doesn’t mean your login was rejected. Your saved claude.ai login had expired and needed renewing. Another Claude Code process on the same machine held the shared refresh lock, or exited and left it behind, and the refresh made no progress while this session waited. Claude Code stops the request before sending it:
```python
Could not refresh your login because another Claude Code process is refreshing it (or exited mid-refresh) · Try again in a minute; if it keeps happening, close other Claude Code windows or sign in again with /login
```
In [non-interactive mode](headless.md) (`-p`) and the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), the message reads as follows, and the structured error code is `server_error`:
```python
Failed to refresh OAuth token: another Claude Code process is refreshing it or exited mid-refresh. This is usually transient; retry in a minute, and if it persists close other Claude Code processes or sign in again
```
Sessions authenticated with an API key, [`CLAUDE_CODE_OAUTH_TOKEN`](env-vars.md), or a third-party provider don’t use the saved login and never see this message. **What to do:**
- Try again in a minute. If another process completes the refresh first, this session uses the renewed login.
- If the message keeps returning, close other Claude Code windows and processes, then retry.
- If it returns with no other Claude Code process running, run `/login`. Signing in again doesn’t wait on the refresh lock.
[](#couldnt-save-your-login)
Couldn’t save your login
You signed in with claude.ai, but Claude Code couldn’t save the login to its credential store, so the login didn’t complete. On macOS this can happen when the login keychain locks, for example on sleep or idle, after Claude Code has already read or saved credentials in it during the same session.
```python
Couldn't save your login. If your Mac's keychain is locked, unlock it and log in again.
Couldn't save your login. Try logging in again.
```
The first form appears on macOS and the second everywhere else. A transient credential-store failure, such as a timeout or an unreadable store, produces the same message. **What to do:**
- On macOS, unlock the login keychain, then run `/login` again
- On other platforms, run `/login` again
- If the login still doesn’t save, see [Not logged in or token expired](troubleshoot-install.md#not-logged-in-or-token-expired) for the keychain unlock command and other credential-storage recovery steps
[](#failed-to-start-oauth-callback-server)
Failed to start OAuth callback server
When `/login`, `claude auth login`, or `claude setup-token` signs you in through the browser, Claude Code opens a listening port on `127.0.0.1` so your browser can return the sign-in result to it. This message means Claude Code couldn’t open that port, and the sign-in stops before a browser window or login URL appears:
```python
Failed to start OAuth callback server: Failed to start server. Is port 0 in use?
```
If your message ends with `Is port 0 in use?`, the attempt to listen on the IPv4 loopback address `127.0.0.1` failed outright. Because the failure happens before a login URL exists, the `Paste code here if prompted` flow isn’t available as a workaround. **What to do:**
- To sign in right away without the local listener: if you use a claude.ai subscription, run [`claude setup-token`](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token) on a machine where sign-in works and set the token it prints as `CLAUDE_CODE_OAUTH_TOKEN` on this machine. Otherwise set `ANTHROPIC_API_KEY` to a key from the [Claude Console](../04-API-Reference/Other/usage-limits.md). [Authentication precedence](../13-Enterprise-Admin/iam.md#authentication-precedence) explains how Claude Code chooses between credentials.
- To use browser sign-in on this machine instead, Claude Code must be able to listen on `127.0.0.1`. If it runs inside a sandbox, check that the sandbox’s policy allows listening on local ports, then run `/login` again. If it should be able to and still fails, run `/feedback` so the report includes your environment details.
[](#claude-login-not-accepted)
Claude login not accepted
You tried to start a [cloud session](claude-code-on-the-web.md), and the server refused to create it with a 401: it didn’t accept the Claude login this machine sent, usually because the login expired or was revoked. The first part of the line is the server’s own reason when it gives one. Otherwise the line reads:
```python
Claude login not accepted · Run /login, then try again
```
**What to do:**
- Run `/login`, complete the sign-in, then start the session again
[](#artifacts-need-a-claude-ai-login)
Artifacts need a claude.ai login
Claude Code refused an [artifact](artifacts.md) publish or read because the session has no claude.ai login it can use for artifacts. Every form of the message starts with the same words, followed by a remedy that depends on how your session authenticates. With no competing credential it reads:
```python
Artifacts need a claude.ai login. Run /login and select "Claude account with subscription", then retry — the "Anthropic Console account" option does not provide claude.ai credentials.
```
**What to do:**
- Run `/login` and select **Claude account with subscription**. The **Anthropic Console account** option doesn’t provide claude.ai credentials.
- When the message names a credential that takes precedence, such as `ANTHROPIC_API_KEY`, an `apiKeyHelper` setting, or a Console key saved by a previous `/login`, remove it the way the message says, then run `/login`
- When the message says this remote session authenticates through the machine that launched it, sign in to claude.ai on that machine, then reconnect the session
- When the message says the credential is injected by the session’s host environment, you can’t change it in that session; start a session that is signed in to claude.ai
- See [Availability](artifacts.md#availability) for the other requirements artifacts have, such as plan, model provider, and organization policy
[](#administrator-policy-requires-a-cloud-gateway-sign-in)
Administrator policy requires a Cloud gateway sign-in
An administrator’s [managed settings](../13-Enterprise-Admin/managed-settings.md) on this machine set [`forceLoginMethod`](settings-reference.md#forceloginmethod) to `"gateway"` or set [`forceLoginGatewayUrl`](settings-reference.md#forcelogingatewayurl). Unless you select a cloud provider through a variable such as `CLAUDE_CODE_USE_BEDROCK`, Claude Code then accepts only the [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sign-in. You see one of two messages:
```python
Not signed in to the Cloud gateway — run /login.
```
Model requests fail with this message when the session has no gateway sign-in, for example because you haven’t run `/login` since the policy reached the machine. If the machine also holds an Anthropic-issued credential and the managed settings set `forceLoginMethod` or `forceLoginOrgUUID`, Claude Code exits at startup instead. That credential can be an `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` variable, an `apiKeyHelper` setting, or an API key saved by an earlier Claude Console login. The message begins:
```python
Administrator policy requires a Cloud gateway sign-in on this machine; the
Anthropic-issued credential configured here (ANTHROPIC_API_KEY,
ANTHROPIC_AUTH_TOKEN, or apiKeyHelper) is not used.
```
**What to do:**
- Run `/login` and complete the sign-in on the **Cloud gateway** screen
- For the startup message, remove the `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` setting you configured. To remove a saved Console API key, run `claude auth logout`, which also removes a saved claude.ai login. If you select a cloud provider with `CLAUDE_CODE_USE_*`, the session then starts with no sign-in. Otherwise start `claude` and run `/login`
- If you believe the machine shouldn’t require the gateway, ask the administrator who manages it to remove `forceLoginMethod` and `forceLoginGatewayUrl` from its managed settings
On v2.1.265, a regression also showed the first message in some LLM-gateway and proxy configurations that authenticate with an API key, `apiKeyHelper`, or custom headers, even with no administrator requirement on the machine. Update to v2.1.266 or later. You don’t need to change your configuration. Before v2.1.261, on machines that set `forceLoginMethod` to `"gateway"`, Claude Code used a leftover saved login instead of failing model requests, and reported a configured environment credential with `This machine's managed settings require a first-party login` instead of the startup message. Before v2.1.265, a machine whose managed settings set only `forceLoginGatewayUrl` didn’t require the gateway sign-in, and Claude Code used a leftover credential there.
[](#your-account-is-on-hold)
Your account is on hold
The Claude account behind your login has been suspended. Claude Code shows the first message when it tries to renew your saved login and learns of the hold, and the second when a sign-in you complete in the browser reports it:
```python
Your account is on hold and can't use Claude Code. View details or appeal: https://claude.ai/restricted
Your account is on hold and can't sign in to Claude Code. View details or appeal: https://claude.ai/restricted
```
Signing in again with the same account doesn’t clear the message, because the hold is on the account rather than the login. In [non-interactive mode](headless.md) (`-p`) and the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), the structured error code is `account_on_hold`. Before v2.1.235, Claude Code reported a held account as [Login expired · Please run /login](#login-expired), whose recovery steps can’t clear a hold. **What to do:**
- Open the link in the message to view the hold’s details or appeal it
- If you have another Claude account or an API key that isn’t affected by the hold, you can keep working while the hold is resolved: run `/login` with that account, or set the key with `ANTHROPIC_API_KEY`
[](#anthropic-profile-login-expired)
Anthropic profile login expired
Claude Code is authenticating through an Anthropic credential profile whose saved login credential has expired, and the profile holds no refresh credential Claude Code can use to renew it. Claude Code stops each request locally without retrying, because a retry would read the same expired credential.
```python
Anthropic profile login expired · Re-authenticate your Anthropic profile
Anthropic profile login expired · Run /login to use your claude.ai account instead, or re-authenticate the profile
```
This appears only when the active credential comes from an Anthropic credential profile, one you select with the `ANTHROPIC_PROFILE` environment variable, that Claude Code discovers as the active profile in your Anthropic configuration directory, or that Claude Code wrote when you [signed in without an API key](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key). Sessions that authenticate with an API key, a bearer token such as `ANTHROPIC_AUTH_TOKEN`, or a third-party provider never see this message. On a machine that [offers the keyless sign-in](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key), run `/login`, choose the Anthropic Console account, and sign in again to renew a profile that the keyless Console sign-in or the Claude Platform CLI’s `ant auth login` wrote. Claude Code replaces the expired credential in that profile. For a federation profile or one another tool created, `/login` doesn’t renew the credential. Which form you see depends on whether you selected the profile or Claude Code discovered it:
- When you set `ANTHROPIC_PROFILE` explicitly, the message ends with `Re-authenticate your Anthropic profile`.
- When Claude Code discovered the profile from your configuration directory, the message offers `/login`, because Claude Code gives a working `/login` precedence over the discovered profile and then authenticates with your claude.ai or Console account instead. Before v2.1.234, Claude Code showed the `Re-authenticate your Anthropic profile` form in this case too.
**What to do:**
- Sign in to the profile again, then retry: on a machine that [offers the keyless sign-in](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key), run `/login` and choose the Anthropic Console account for a profile the keyless Console sign-in or the Claude Platform CLI’s `ant auth login` wrote; for other profiles, use the tool that created them
- If an administrator provisioned the profile’s credential, ask them to issue a new one
- Run `/status` to confirm the active credential source and profile name
- To stop using the profile, unset `ANTHROPIC_PROFILE` if you set it, then authenticate another way, such as `/login` or `ANTHROPIC_API_KEY`
[](#oauth-scope-requirement)
OAuth scope requirement
The stored token predates a permission scope that a newer feature needs:
```python
OAuth token does not meet scope requirement: user:profile
```
**What to do:**
- Run `/login` to get a new token with the current scopes. You don’t need to log out first.
[](#claude-ai-rejected-the-session-token)
claude.ai rejected the session token
A [claude.ai connector](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) request failed because claude.ai rejected the token from your Claude Code login. The rejected token is your login, not the connector’s own authorization in claude.ai, so authorizing the connector again doesn’t resolve it. In `/mcp`, the connector shows as `session token rejected` and its detail view reads:
```python
claude.ai rejected the session token. Run /login, then reconnect.
```
**What to do:**
- Run `/login` to sign in again
- Reconnect the connector from `/mcp`, or run `/mcp reconnect <server>`. Reconnecting before you sign in again leaves the connector in the same state. The `/mcp` panel’s **Reconnect** option reports `your claude.ai session token was rejected`; the typed `/mcp reconnect <server>` form reports a successful reconnect even though the token is still rejected.
Before v2.1.222, Claude Code marked the connector as needing authentication instead, which pointed you at the connector’s authorization flow even though completing it didn’t resolve the state.
[](#mcp-server-needs-you-to-sign-in-again)
MCP server needs you to sign in again
A remote [MCP server](../06-MCP-Tools/General/mcp.md) rejected the credential on a tool call mid-session, usually because a sign-in or token expired or because the token lacks a permission the tool needs. The tool call fails, and `/mcp` marks the server as [needing authentication](../06-MCP-Tools/General/mcp.md#authenticate-with-remote-mcp-servers). For a server you sign in to from Claude Code, including a claude.ai connector, the sign-in expired or was revoked:
```python
MCP server "<name>" needs you to sign in again (run /mcp to re-authenticate)
```
Run `/mcp`, select the server, and sign in again from its menu. For a server configured with a [`headersHelper`](../06-MCP-Tools/General/mcp.md#use-dynamic-headers-for-custom-authentication) script, Claude Code has already re-run the helper and retried the call once before showing this:
```python
MCP server "<name>" rejected the credential from its headersHelper (check the helper and run /mcp to reconnect, or to authenticate if the server also uses OAuth)
```
Check that the helper returns a credential the server accepts, then reconnect from `/mcp`, which runs the helper again. For a server with a static `Authorization` header in its configuration:
```python
MCP server "<name>" rejected the Authorization header in its config (update it, then run /mcp to reconnect)
```
Update the header value where the server is configured, then reconnect from `/mcp`. Before v2.1.273, the expired sign-in, `headersHelper`, and `Authorization` header cases all showed `MCP server "<name>" requires re-authorization (token expired)`. A server can also refuse a tool call with HTTP 403 `insufficient_scope` to ask you to authorize a scope, sometimes one your token already lists. The message names that scope:
```python
MCP server "<name>" needs additional permissions (scope: "<scope>") — run /mcp to re-authenticate
```
Run `/mcp`, select the server, and authenticate again from its menu. When the server’s configuration sets neither [`oauth.scopes`](../06-MCP-Tools/General/mcp.md#restrict-oauth-scopes) nor [`authServerMetadataUrl`](../06-MCP-Tools/General/mcp.md#override-oauth-metadata-discovery), Claude Code requests the scope the server named. With either setting, Claude Code requests that setting’s scopes instead. If you pinned `oauth.scopes`, add the missing scope to that list before you authenticate again. Before v2.1.274, this case showed the `needs you to sign in again` message, and before v2.1.273 it showed `requires re-authorization (token expired)` like the other cases.
[](#issuer-mismatch-in-authorization-response)
Issuer mismatch in authorization response
During an [MCP OAuth sign-in](../06-MCP-Tools/General/mcp.md#authenticate-with-remote-mcp-servers), the authorization server redirected back to Claude Code with an `iss` parameter that doesn’t name the issuer that Claude Code expected from the server’s OAuth metadata. A wrong issuer at this step is how an authorization server mix-up attack looks, so Claude Code fails the sign-in instead of exchanging the authorization code. Claude Code shows the error in the `/mcp` server menu after the browser sign-in:
```python
Issuer mismatch in authorization response (RFC 9207): expected "https://auth.example.com", received "https://other.example.com"
```
`expected` is the issuer from the server’s OAuth metadata, and `received` is the `iss` value the redirect carried. A sign-in whose redirect carries no `iss` parameter passes the check, unless the server’s metadata sets `authorization_response_iss_parameter_supported`, in which case Claude Code fails the sign-in. **What to do:**
- Try the sign-in again from `/mcp`
- If the error repeats, report it to the server operator. The fix is server-side: the authorization server must return the same issuer in the `iss` parameter that it advertises in its metadata
- To connect while the server is being fixed, start Claude Code with [`MCP_SDK_GENERATION=v1`](env-vars.md), whose [runtime](../06-MCP-Tools/General/mcp.md#mcp-client-runtimes) doesn’t run this check. This removes a protection against mix-up attacks, so prefer the server-side fix
Before v2.1.232, Claude Code used the v2 runtime only in a gradual rollout or when you set `MCP_SDK_GENERATION=v2`.
[](#aws-credentials-expired-or-invalid)
AWS credentials expired or invalid
Your AWS session token expired or was rejected. This message appears on a 401 from [Claude Platform on AWS](claude-platform-on-aws.md) or the [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint), which is how those providers report an expired security token. The action hint in the middle varies with your setup. The stable part is the leading `AWS credentials expired or invalid`:
```python
AWS credentials expired or invalid · run /login and select "Claude Platform on AWS · refresh credentials", or run `aws sso login --profile myprofile` in another terminal · API Error: 401 ...
```
Before v2.1.273, this message appeared only when `awsAuthRefresh` was configured. **What to do:**
- If the hint says credentials are managed by this environment, the app that launched Claude Code owns the credential and the other steps here don’t apply: retry, or contact your administrator
- If [`awsAuthRefresh`](amazon-bedrock.md#advanced-credential-configuration) is set, run the command named in the message, such as `aws sso login --profile myprofile`, in another terminal and complete the browser sign-in, then retry. Otherwise refresh the AWS credential you use yourself: your SSO sign-in, access keys, API key, or proxy token
- With `awsAuthRefresh` set in an interactive session, you can instead run `/login`, choose **3rd-party platform**, then select **Claude Platform on AWS · refresh credentials** under **Using 3rd-party platforms** to run the same command without restarting Claude Code. See [Configure AWS credentials](claude-platform-on-aws.md#1-configure-aws-credentials)
- If the error repeats after the refresh command succeeds, confirm the identity is valid outside Claude Code with `aws sts get-caller-identity` in the same shell and profile
[](#aws-authentication-failed)
AWS authentication failed
Your AWS provider returned a 403, or [Amazon Bedrock](amazon-bedrock.md) returned a 401. Amazon Bedrock reports an expired security token as a 403, but a 403 is also how it reports an authorization denial, such as an `AccessDeniedException` from a missing IAM permission. Claude Code can’t tell those two causes apart. A 401 from Amazon Bedrock also lands here rather than under [AWS credentials expired or invalid](#aws-credentials-expired-or-invalid), because Amazon Bedrock doesn’t report an expired token as a 401. A 401 from that endpoint typically comes from something else in the request path, such as a corporate proxy. A credential refresh fixes an expired token and can’t fix the other causes, so the message offers both:
```python
AWS authentication failed · run /login and select "Claude Platform on AWS · refresh credentials", or run `aws sso login --profile myprofile` in another terminal · if credentials are current, check AWS permissions and model access · API Error: 403 ...
```
The action hint in the middle varies with your setup. The stable part is the leading `AWS authentication failed`. When the 403 is Amazon Bedrock’s answer that you don’t have access to the model with the specified model ID, the hint instead tells you to enable the model for your account and region in the Amazon Bedrock console. Before v2.1.273, this message appeared only when `awsAuthRefresh` was configured. **What to do:**
- If the hint says credentials are managed by this environment, the app that launched Claude Code owns the credential and the other steps here don’t apply: retry, or contact your administrator
- Refresh your AWS credentials in case an expired credential is the cause: run the [`awsAuthRefresh`](amazon-bedrock.md#advanced-credential-configuration) command named in the message when one is set, or refresh your SSO sign-in, access keys, API key, or proxy token yourself
- If your credentials are current, confirm the IAM permissions in [IAM configuration](amazon-bedrock.md#iam-configuration) are attached to the identity you’re using and that the selected model is enabled for your account and region
- Run `aws sts get-caller-identity` to confirm which identity your requests use
[](#google-cloud-credentials-expired-or-invalid)
Google Cloud credentials expired or invalid
Your Google Cloud credentials for [Google Cloud’s Agent Platform](google-vertex-ai.md) expired or were rejected: the request returned a 401, which is how Agent Platform reports credential expiry. The action hint in the middle varies with your setup. The stable part is the leading `Google Cloud credentials expired or invalid`:
```python
Google Cloud credentials expired or invalid · refresh your Google Cloud credentials (application default sign-in, or the key file in GOOGLE_APPLICATION_CREDENTIALS) and retry · API Error: 401 ...
```
**What to do:**
- If the hint says credentials are managed by this environment, the app that launched Claude Code owns the credential and the other steps here don’t apply: retry, or contact your administrator
- If you authenticate with application default credentials, run the [`gcpAuthRefresh`](google-vertex-ai.md#advanced-credential-configuration) command named in the message, or `gcloud auth application-default login`, and complete the sign-in, then retry
- If you route through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) with `CLAUDE_CODE_SKIP_VERTEX_AUTH` set, refresh the gateway token in `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_CUSTOM_HEADERS`, then retry
- If you authenticate with a service account key file, confirm `GOOGLE_APPLICATION_CREDENTIALS` points at a valid key. See [Configure GCP credentials](google-vertex-ai.md#3-configure-gcp-credentials)
- If the error repeats after a refresh, confirm the identity works outside Claude Code with `gcloud auth application-default print-access-token` in the same shell
Before v2.1.273, a 401 from Agent Platform showed the generic `Please run /login` or `Failed to authenticate` message instead, which can’t refresh Google Cloud credentials.
[](#google-cloud-authentication-failed)
Google Cloud authentication failed
[Google Cloud’s Agent Platform](google-vertex-ai.md) returned a 403, which it uses for authorization denials rather than expired credentials. Usually the identity you authenticate with is missing an IAM permission, or the model isn’t enabled for your project. The action hint in the middle varies with your setup. The stable part is the leading `Google Cloud authentication failed`:
```python
Google Cloud authentication failed · refresh your Google Cloud credentials (application default sign-in, or the key file in GOOGLE_APPLICATION_CREDENTIALS) and retry · if credentials are current, check GCP IAM permissions and Vertex AI model access · API Error: 403 ...
```
**What to do:**
- If the hint says credentials are managed by this environment, the app that launched Claude Code owns the credential and the other steps here don’t apply: retry, or contact your administrator
- Confirm the roles in [IAM configuration](google-vertex-ai.md#iam-configuration) are granted to the identity you authenticate with
- Confirm the model is enabled for your project. See [Request model access](google-vertex-ai.md#2-request-model-access)
Before v2.1.273, a 403 from Agent Platform showed the generic `Please run /login` or `Failed to authenticate` message instead, which can’t refresh Google Cloud credentials.
[](#microsoft-foundry-authentication-failed)
Microsoft Foundry authentication failed
[Microsoft Foundry](microsoft-foundry.md) returned a 401 or 403: the Azure credential on the request was rejected, or the identity behind it doesn’t have access to the Foundry resource. `/login` can’t mint Azure credentials. The action hint in the middle varies with your setup. The stable part is the leading `Microsoft Foundry authentication failed`:
```python
Microsoft Foundry authentication failed · refresh your Foundry credential (ANTHROPIC_FOUNDRY_AUTH_TOKEN, ANTHROPIC_FOUNDRY_API_KEY, Azure sign-in for Entra, or your proxy token) and retry · if credentials are current, check access to the Foundry resource · API Error: 401 ...
```
**What to do:**
- If the hint says credentials are managed by this environment, the app that launched Claude Code owns the credential and the other steps here don’t apply: retry, or contact your administrator
- Refresh the credential you configured in [Configure Azure credentials](microsoft-foundry.md#2-configure-azure-credentials): rotate `ANTHROPIC_FOUNDRY_API_KEY`, mint a fresh `ANTHROPIC_FOUNDRY_AUTH_TOKEN`, or run `az login` so the default Microsoft Entra credential chain can sign in again
- If the credential is current, confirm the identity has access to the Foundry resource. See [Azure RBAC configuration](microsoft-foundry.md#azure-rbac-configuration)
Before v2.1.273, a 401 or 403 from Microsoft Foundry showed the generic `Please run /login` or `Failed to authenticate` message instead, which can’t refresh Azure credentials.
[](#could-not-load-aws-or-google-cloud-credentials)
Could not load AWS or Google Cloud credentials
Claude Code couldn’t obtain usable credentials from the AWS credential provider chain or from your Google application default credentials on the machine it runs on, so no request reached your cloud provider. Claude Code clears its cached credentials and retries twice before showing this message. The detail after the `·` names the specific cause, such as an expired SSO session, missing application default credentials reported as `Could not load the default credentials`, or a revoked sign-in reported as `invalid_grant`:
```python
API Error: Could not load AWS credentials · Could not load credentials from any providers. Check or refresh your AWS credentials and try again.
API Error: Could not load Google Cloud credentials · invalid_grant. Check or refresh your Google Cloud credentials and try again.
```
In [non-interactive mode](headless.md) with `-p` and in the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), the structured error code is `cloud_credential_error`. Before v2.1.267, the message showed only the detail text after `API Error:`, and the structured code was `server_error` or `unknown`. **What to do:**
- Run your provider’s sign-in command, such as `aws sso login --profile myprofile` or `gcloud auth application-default login`, then retry. [Bedrock, Agent Platform, or Foundry credentials not loading](troubleshoot-install.md#bedrock-agent-platform-or-foundry-credentials-not-loading) shows how to confirm the credentials outside Claude Code
- If the detail reads `AWS default-chain credential resolve timed out`, the chain hung rather than failed, so follow [AWS default-chain credential resolve timed out](#aws-default-chain-credential-resolve-timed-out) instead
[](#aws-default-chain-credential-resolve-timed-out)
AWS default-chain credential resolve timed out
The AWS default credential provider chain didn’t produce credentials within 60 seconds, so Claude Code stopped the resolve and failed the request. This timeout is one cause of [Could not load AWS or Google Cloud credentials](#could-not-load-aws-or-google-cloud-credentials). The failure is local credential resolution: the request never reached [Amazon Bedrock](amazon-bedrock.md), [Claude Platform on AWS](claude-platform-on-aws.md), or the [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint). Claude Code clears its [credential cache](amazon-bedrock.md#credential-caching-and-resolution-timeout) and retries before this error surfaces, so by the time you see it the chain has stalled on repeated attempts.
```python
API Error: Could not load AWS credentials · AWS default-chain credential resolve timed out. Check or refresh your AWS credentials and try again.
```
Common causes are a `credential_process` command in your AWS profile that waits for input it can’t receive, and a container or VM whose instance metadata service (IMDS) never answers the chain’s probe. Before v2.1.267, the message read `API Error: AWS default-chain credential resolve timed out`. Before v2.1.207, a stalled chain left the request waiting indefinitely instead of failing. **What to do:**
- Run `aws sts get-caller-identity` in the same shell with the same `AWS_PROFILE`. If it also hangs, fix the profile; a `credential_process` command that prompts interactively is a common cause.
- Complete the sign-in step before starting Claude Code, for example `aws sso login --profile myprofile`
- If your chain runs an interactive sign-in that legitimately needs more than 60 seconds, such as SSO with MFA through a wrapper like `aws-vault`, raise the limit in milliseconds with [`CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS`](env-vars.md)
[](#bedrock-setup-verification-timed-out-waiting-for-aws)
Bedrock setup verification timed out waiting for AWS
A call to AWS during the [Bedrock setup wizard](amazon-bedrock.md#sign-in-with-bedrock)’s credential verification, such as the credential lookup or the identity check, didn’t finish within the 60-second limit. The wizard stops waiting and fails the verification step:
```python
Timed out after 60s waiting for AWS. Check your network and proxy settings; if a credential helper needs longer to prompt you, raise CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS.
```
The number reflects your limit: 60 seconds by default, or the value you set in [`CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS`](env-vars.md). Common causes are a network or proxy that stalls requests to AWS, including the SSO token refresh, and a credential helper still waiting for input you can’t see. Raise the limit only when the helper legitimately needs more time. A single stalled request to AWS can also fail on its own per-request timeout, which shows a shorter message on the same step:
```python
A request to AWS timed out. Check your network and proxy settings, then try again.
```
When the same timeouts occur on the model pin step, the wizard marks a model as `unreachable` instead of showing either message. **What to do:**
- Run `aws sts get-caller-identity` in the same shell. If it also hangs, the stall is outside Claude Code, in your network, your proxy, or the credential helper in your AWS profile; fix that first.
- Complete any interactive sign-in before opening the wizard, for example `aws sso login --profile myprofile`
- If a credential helper in your AWS profile legitimately needs longer than 60 seconds to prompt you, raise the limit in milliseconds with [`CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS`](env-vars.md)
[](#cloud-gateway-session-expired)
Cloud gateway session expired
You signed in through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md), and the gateway session saved on this machine has expired and couldn’t be renewed, or the gateway no longer accepts it, for example after the gateway’s [JWT secret is replaced](../13-Enterprise-Admin/claude-apps-gateway-deploy.md#jwt-secret-rotation). If you see this line when you start `claude` interactively, the session has opened signed out of the gateway:
```python
Cloud gateway session expired — run /login to reconnect.
```
The same line can appear mid-session when the gateway credential expires and Claude Code can’t renew it. In a [non-interactive](headless.md) run, a background or other unattended session, or a `claude` subcommand other than `claude auth`, Claude Code exits with this message instead when the gateway no longer accepts the session:
```python
Cloud gateway <url> no longer accepts this session. Start `claude` and sign in again with /login.
```
**What to do:**
- Run `/login` in the session and complete the browser sign-in
- For a non-interactive launch, start `claude` in the same environment, run `/login`, then rerun your command
[](#sign-in-timed-out-while-waiting-for-you-to-continue)
Sign-in timed out while waiting for you to continue
During a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sign-in, the gateway named the account that signed in, and Claude Code asked you to confirm it before saving the credential. You left the confirmation open past the sign-in’s own expiry, and the gateway issued no refresh token that could renew it, so Claude Code stored nothing when you continued:
```python
Sign-in timed out while waiting for you to continue. Try again.
```
**What to do:**
- Run `/login` again and confirm the account before the sign-in expires
[](#gateway-refused-the-request)
Gateway refused the request
You’re signed in through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md), and a request returned a 403: the gateway, or the upstream behind it, refused it. Signing in again doesn’t change a refusal, so the message points at your gateway administrator:
```python
Gateway refused the request · signing in again won't change this — check with your gateway administrator · API Error: 403 ...
```
**What to do:**
- Ask your gateway administrator to look up the request. The `API Error:` tail carries the refusal the gateway returned
- For administrators: an [access control rule](../13-Enterprise-Admin/claude-apps-gateway-config.md#http-tuning) on the gateway returns a 403 that the [audit log](../13-Enterprise-Admin/claude-apps-gateway-deploy.md#logs) records with its reason, and an upstream’s authorization denial passes through per [Upstream error messages](../13-Enterprise-Admin/claude-apps-gateway-config.md#upstream-error-messages)
Before v2.1.273, a 403 on a gateway session showed the generic `Please run /login` or `Failed to authenticate` message instead, and signing in again didn’t clear the refusal.
[](#network-and-connection-errors)
Network and connection errors
Most of these errors mean a network request from Claude Code failed to reach its destination, or something between Claude Code and the API altered the response on its way back; where an entry also has a local cause, such as a failed archive write, its body says so. They usually originate in your local network, proxy, or firewall, or in the cloud environment’s network policy.
[](#unable-to-connect-to-api)
Unable to connect to API
The TCP connection to the API failed or never completed. For the common connection error codes, the message names the kind of failure and keeps the code in parentheses:
```python
Unable to connect to API. Check your internet connection
Connection refused — a firewall or proxy may be blocking it (ConnectionRefused)
Can't reach the API server — check your internet or DNS (ENOTFOUND)
No internet route — check your connection or VPN (EHOSTUNREACH)
Couldn't connect through your proxy (ERR_PROXY_TUNNEL) — the proxy refused the tunnel: check its credentials and that it allows this host
Connection dropped (ECONNRESET)
Request timed out. Check your internet connection and proxy settings
```
A code Claude Code doesn’t recognize appears as `Unable to connect to API` followed by the code in parentheses. Some of these messages can show more than one code: `Connection refused` can show `ConnectionRefused` or `ECONNREFUSED`, for example, and `Can't reach the API server` can show `ENOTFOUND` or `FailedToOpenSocket`. Before v2.1.227, each of these coded messages read `Unable to connect to API` followed by the code, for example `Unable to connect to API (ECONNREFUSED)`. 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](../13-Enterprise-Admin/network-config.md)
- If you route through an LLM gateway or relay, set [`ANTHROPIC_BASE_URL`](env-vars.md) to its address. See [Connect Claude Code to an LLM gateway](../13-Enterprise-Admin/llm-gateway-connect.md) for setup.
- Ensure your firewall allows the hosts listed in [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements)
- Intermittent failures are [retried automatically](#automatic-retries); 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:
- Check whether `ANTHROPIC_BASE_URL` is set by running `echo $ANTHROPIC_BASE_URL`, or `echo $env:ANTHROPIC_BASE_URL` in PowerShell, and look for it in the `env` block of your [settings files](settings.md). When it’s set, Claude Code sends model requests to that address instead of `api.anthropic.com`, so a leftover value pointing at a local proxy or gateway that’s no longer running produces `Connection refused` even though `curl` reaches the API. Remove it from your shell profile or settings and start Claude Code from a new terminal.
- 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.
[](#unable-to-connect-to-anthropic-services)
Unable to connect to Anthropic services
During first-run setup, Claude Code checks that it can reach `api.anthropic.com` and `platform.claude.com` before showing the sign-in step. When either check fails, Claude Code prints the reason and exits.
```python
Unable to connect to Anthropic services
Failed to connect to api.anthropic.com: ECONNREFUSED
Connection to api.anthropic.com timed out after 10 seconds
A proxy is configured via HTTPS_PROXY. Check that it allows connections to the host above.
```
Claude Code sends the check through the same [proxy configuration](../13-Enterprise-Admin/network-config.md) as API requests and gives each probe 10 seconds. When the failed probe went through a proxy, the message names the environment variable that configured it, such as `HTTPS_PROXY`. Before v2.1.222, the check used a different proxy transport with no timeout: behind a proxy URL with the `https://` scheme, it could stall on `Checking connectivity...` indefinitely and then fail even though API requests through the same proxy succeed. Claude Code skips this check when a [managed settings file, MDM policy, or policy helper](../13-Enterprise-Admin/managed-settings.md) sets [`forceLoginMethod`](settings-reference.md#forceloginmethod) to `"gateway"`, or sets [`forceLoginGatewayUrl`](settings-reference.md#forcelogingatewayurl) without `forceLoginMethod`. With either configuration, Claude Code opens the sign-in step on the **Cloud gateway** screen rather than an Anthropic sign-in method. Claude Code also skips the check when a managed settings source on the machine exists but can’t be read, since that source may hold the gateway configuration. Before v2.1.247, Claude Code ran the check under this configuration too, and exited with this error when Anthropic’s endpoints were unreachable. **What to do:**
- If the message names a proxy variable, check that its value points at the right proxy and ask your network team to allow HTTPS connections through it to the host in the message. See [Network configuration](../13-Enterprise-Admin/network-config.md).
- Work through the checks in [Unable to connect to API](#unable-to-connect-to-api). The `curl` test and firewall guidance there apply to this check too.
- If your network is open and the failure persists, Claude Code may not be [available in your country](https://www.anthropic.com/supported-countries)
[](#socket-is-closed)
Socket is closed
`Socket is closed` means the connection carrying a streaming response was closed while the response was still arriving. The most common cause is a corporate proxy on Windows dropping an established tunnel mid-response. Depending on how far the response had progressed, Claude Code retries the request, keeps what Claude produced, or ends the turn. See [Automatic retries](#automatic-retries). Before v2.1.214, Claude Code didn’t retry this failure, and the turn stopped with an error containing `Socket is closed`. **What to do:**
- If you see this error, update to v2.1.214 or later with `claude update`, then send your message again
- If turns keep failing behind the same proxy after updating, work through [Unable to connect to API](#unable-to-connect-to-api) and check the proxy setup in [Network configuration](../13-Enterprise-Admin/network-config.md)
[](#api-returned-an-empty-or-malformed-response)
API returned an empty or malformed response
Claude Code shows this error when its non-streaming retry of a failed streaming request gets an HTTP success status but the body isn’t a Claude API message: commonly an HTML error or sign-in page, an empty body, or JSON in another format. A proxy, gateway, or network sign-in page answering in the API’s place is the usual source. Claude Code doesn’t retry the request, and the turn ends with this error.
```python
API returned an empty or malformed response (HTTP 200) — check for a proxy or gateway intercepting the request.
```
After that opening, the message reports what came back and which request failed:
- A `Response:` clause with the content type, the kind of body, such as `body is an HTML page` or `empty body`, its size in bytes, and whether the response carried an Anthropic request id. When the response names a recognizable server, such as `nginx` or `cloudflare`, or carries intermediary headers, such as `cf-ray` or `via`, the clause lists those too.
- A sentence naming the failed streaming request’s id and the failure that triggered the retry. When a stream had opened before the failure, it also reports how many stream events arrived and, if any did, how long the stream had been silent when the attempt failed.
Before v2.1.234, the message ended after `intercepting the request`. Before v2.1.271, a reply that carried a valid API message under a non-JSON content type such as `text/plain` also ended the turn with this error. Some LLM gateways use that content type for the non-streaming reply. **What to do:**
- Read the `Response:` clause to see which system answered. An HTML body, no Anthropic request id, or a named server such as `nginx` or `cloudflare` means that something between Claude Code and the API replied in its place
- If you route through an [LLM gateway](../13-Enterprise-Admin/llm-gateway-connect.md#troubleshoot-gateway-errors), test the route with a direct request and fix the hop that returns the non-API response
- On a network with a sign-in page, such as guest Wi-Fi, complete the sign-in in a browser, then retry
- If only the non-streaming route through your gateway is broken, set [`CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1`](env-vars.md#variables) to turn off this fallback, except when the streaming endpoint itself returns `404`, where Claude Code still falls back
[](#streaming-response-ended-before-any-complete-data-was-received)
Streaming response ended before any complete data was received
A streaming response from your model provider completed without delivering any usable data, so Claude Code re-sent the request without streaming to finish the turn. Claude Code shows the warning once per session, in interactive sessions only. Before v2.1.239, Claude Code silently retried without streaming.
```python
Streaming response ended before any complete data was received. Retrying without streaming. If this keeps happening, check any proxy or gateway between Claude Code and your model provider.
```
Claude Code sends each affected request twice: the empty streaming attempt and the retry. The usual cause is a proxy or gateway that consumes or transforms the streaming response body on its way back. **What to do:**
- Configure any proxy or gateway between Claude Code and your model provider to pass streaming response bodies and their headers through unmodified
- On [Amazon Bedrock](amazon-bedrock.md), see [Streaming errors behind a gateway or proxy](amazon-bedrock.md#streaming-errors-behind-a-gateway-or-proxy) for the header and body requirements
[](#bedrock-streaming-response-has-an-unexpected-content-type)
Bedrock streaming response has an unexpected content-type
A gateway or proxy between Claude Code and [Amazon Bedrock](amazon-bedrock.md) is transforming the streaming response body or its `Content-Type` header. Amazon Bedrock streams responses as `application/vnd.amazon.eventstream`. Rather than decode a body it can’t read, Claude Code rejects a successful streaming response that reports a different content-type. Claude Code doesn’t retry the request.
```python
Bedrock streaming response has content-type "text/event-stream"; expected "application/vnd.amazon.eventstream". A gateway or proxy between Claude Code and Bedrock is likely transforming the response body — Bedrock's binary event-stream format must be passed through unmodified. Set CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1 to suppress this check while the gateway is being fixed.
```
Before v2.1.208, the same misconfiguration surfaced as `API Error: Truncated event message received` after the whole response had been buffered. **What to do:**
- Configure the gateway to pass the `InvokeModelWithResponseStream` response body and its `Content-Type` header through unmodified. An intermediary that re-emits the stream as server-sent events is a common cause.
- Setting [`CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1`](env-vars.md) hides this error, but Claude Code doesn’t decode a binary body under a rewritten header, so those requests fall back to a slower non-streaming path. See [Streaming errors behind a gateway or proxy](amazon-bedrock.md#streaming-errors-behind-a-gateway-or-proxy).
[](#ssl-certificate-errors)
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.
```python
Unable to connect to API: SSL certificate verification failed (UNABLE_TO_GET_ISSUER_CERT_LOCALLY). The certificate comes from an authority Claude Code doesn't trust, usually a TLS-inspecting corporate proxy or a gateway signed by a private CA: set NODE_EXTRA_CA_CERTS to that CA bundle, or add it to the system certificate store · see https://code.claude.com/docs/en/network-config
Unable to connect to API: Self-signed certificate detected (SELF_SIGNED_CERT_IN_CHAIN). The certificate comes from an authority Claude Code doesn't trust, usually a TLS-inspecting corporate proxy or a gateway signed by a private CA: set NODE_EXTRA_CA_CERTS to that CA bundle, or add it to the system certificate store · see https://code.claude.com/docs/en/network-config
```
Before v2.1.273, both messages ended at `Check your proxy or corporate SSL certificates`, without the OpenSSL code or the `NODE_EXTRA_CA_CERTS` hint. As of v2.1.199, a certificate validation failure isn’t retried, so this error appears on the first attempt instead of after the full [retry budget](#automatic-retries). Earlier versions spent a few minutes retrying before showing it. Transient TLS conditions, such as a handshake timeout, still retry. During `/login` and the startup connectivity check, the same failure produces a different message:
```python
SSL certificate error (UNABLE_TO_GET_ISSUER_CERT_LOCALLY). If you are behind a corporate proxy or TLS-intercepting firewall, set NODE_EXTRA_CA_CERTS to your CA bundle path, or ask IT to allowlist *.anthropic.com. Run `claude doctor` for details.
```
On [Amazon Bedrock](amazon-bedrock.md), the requests Claude Code itself sends to AWS, such as the STS and SSO role-credential calls, model discovery, and the setup wizard’s checks, depend on the same certificate configuration. See [Certificate errors behind a TLS-inspecting proxy](amazon-bedrock.md#certificate-errors-behind-a-tls-inspecting-proxy). **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](../13-Enterprise-Admin/network-config.md#custom-ca-certificates) for full setup instructions
- Don’t set `NODE_TLS_REJECT_UNAUTHORIZED=0`, which disables certificate validation entirely
[](#host-not-allowed-in-a-cloud-session)
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.
```python
HTTP 403
x-deny-reason: host_not_allowed
```
You may also see a TLS certificate that doesn’t match the destination’s real certificate. Cloud sessions route 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](web-scheduled-tasks.md) run inside a sandboxed VM whose outbound traffic through the session’s network is filtered to the [cloud environment’s](cloud-environments.md) allowlist; [GitHub operations](cloud-environments.md#github-proxy) and MCP connector traffic use separate channels, which is why they can keep working while other hosts are blocked. The **Default** environment uses **Trusted** access, which permits the [default allowlist](cloud-environments.md#default-allowed-domains) of package registries, cloud provider APIs, container registries, and common development domains and blocks other domains on that path. **What to do:** These steps change one of your own environments. An [organization-shared environment](cloud-environments.md#organization-shared-environments) opens read-only in the selector, so ask an Owner to change its network access from the **Cloud environments** page in [admin settings](https://claude.ai/admin-settings).
- 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](cloud-environments.md#default-allowed-domains) 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](cloud-environments.md#network-access) for access levels and the default allowlist. Local CLI sessions are not affected by this policy.
[](#the-proxy-refused-the-connection)
The proxy refused the connection
You see this message when Claude reads an [artifact](artifacts.md) through the proxy you set in `HTTPS_PROXY` or a related [proxy variable](../13-Enterprise-Admin/network-config.md#environment-variables). Artifact content comes from `*.frame.claudeusercontent.com`, so Claude Code first sends the proxy a `CONNECT` request asking it to open a tunnel to that host. When the proxy refuses, nothing reaches the host, and the message carries the proxy’s HTTP status:
```python
artifact content fetch failed (proxy refused the connection: HTTP 407)
artifact content fetch failed (proxy refused the connection: HTTP 403)
the proxy refused the connection to the artifact's content host (HTTP 502)
```
The status is the proxy’s answer to the `CONNECT`. The host never answered, so each status points at a different fix:
- `HTTP 407`: the proxy requires credentials it didn’t get. Put them in the proxy URL, as [Basic authentication](../13-Enterprise-Admin/network-config.md#basic-authentication) shows.
- `HTTP 403`: the proxy refuses to tunnel to `*.frame.claudeusercontent.com`. Ask whoever runs the proxy to allow that host, which [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements) lists.
- Any other status, such as `HTTP 502`: the proxy didn’t open the tunnel for its own reason, such as failing to reach the host. Look the status up in the proxy’s logs.
- `unreadable reply` in place of a status: whatever is at the proxy address didn’t answer with an HTTP status line. Check that the address is an HTTP proxy.
**What to do:**
- Check the address and credentials in the proxy variable, as [Proxy configuration](../13-Enterprise-Admin/network-config.md#proxy-configuration) describes, then run `curl -x http://proxy.example.com:8080 -I https://api.anthropic.com` from the shell you start Claude Code in, using your own proxy URL. On Windows PowerShell, run `curl.exe`. If this probe fails the same way, fix the proxy setup first. If it succeeds, the refusal is specific to the artifact host.
- If your network lets Claude Code reach the artifact host directly, add `.frame.claudeusercontent.com` to [`NO_PROXY`](../13-Enterprise-Admin/network-config.md#environment-variables). Keep the entry that narrow: a broader `.claudeusercontent.com` entry also bypasses the proxy for `bridge.claudeusercontent.com`, which organizations with [IP allowlisting](../13-Enterprise-Admin/network-config.md#organization-ip-allowlists-and-proxy-egress) need to keep on the proxy.
Before v2.1.238, Claude Code reported a refused tunnel as a generic network error.
[](#the-cloud-environments-service-returned-an-empty-or-unexpected-response)
The cloud environments service returned an empty or unexpected response
Claude Code requests your [cloud environments](cloud-environments.md) list at several points, such as when you create a cloud session from the CLI or run [`/remote-env`](cloud-environments.md#select-an-environment-from-the-cli). When it can’t read the server’s answer, it shows one of these messages:
```python
The cloud environments service returned an empty response (HTTP 200 with no body). This is usually temporary — try again in a moment.
The cloud environments service returned a response in an unexpected format (HTTP 200 with a non-JSON body). This is usually temporary — try again in a moment.
The cloud environments service returned a response in an unexpected format (HTTP 200 without a usable environments list). This is usually temporary — try again in a moment.
```
The server accepted the request but answered with a body that isn’t the environments list: empty, not JSON, or JSON without the list. This usually accompanies a service-side disruption and clears on its own. Depending on the surface that requested the list, Claude Code may add a prefix, such as `couldn't list environments:` in the `/remote-env` dialog. **What to do:**
- Retry the action. Claude Code requests the list again each time
- If the message keeps appearing, check [status.claude.com](https://status.claude.com) for active incidents
Before v2.1.236, Claude Code showed a raw JavaScript TypeError instead of these messages.
[](#couldnt-reconnect-to-your-remote-control-session)
Couldn’t reconnect to your Remote Control session
```python
Couldn't reconnect to your Remote Control session. Retry, or start a fresh session without --resume.
```
Resuming with `claude --resume` or `claude --continue` reconnects to the [Remote Control](remote-control.md) session recorded in that conversation. This message means the reconnection failed for a reason that may be temporary, such as a network interruption or a server error, so Claude Code can’t confirm whether the remote session still exists. Your local session keeps running without Remote Control. **What to do:**
- Run `/remote-control` to retry the connection
- Start a new session with `claude --remote-control` to create a new Remote Control session
- For other Remote Control startup messages, see [Troubleshoot Remote Control](remote-control.md#troubleshooting)
If the server reports instead that the previous session is gone, you don’t see this message. Claude Code starts a new session in its place or shows [`Previous session is unavailable — run /remote-control to start a new one`](remote-control.md#previous-session-is-unavailable).
[](#sessions-ended-while-this-machine-was-offline)
Sessions ended while this machine was offline
Claude Code shows this message in the terminal running [`claude remote-control`](remote-control.md#start-a-remote-control-session) after your machine was offline long enough that the server cleaned up the Remote Control environment your machine was serving. The sessions in that environment ended, and you can’t resume them. The count is the number of sessions that ended.
```python
2 sessions ended while this machine was offline — the environment was cleaned up on the server and can't be resumed.
```
**What to do:**
- When Claude Code lists kept worktrees under this message, pick up any uncommitted work from them
- Run `claude remote-control` to start a fresh environment
[](#couldnt-share-the-transcript)
Couldn’t share the transcript
After you agree to share your session transcript from a survey prompt, such as the [session quality survey](../13-Enterprise-Admin/data-usage.md#session-quality-surveys), Claude Code uploads it to Anthropic, or saves a local archive instead on third-party providers, on [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions, and when no Anthropic credentials are available. This message means the share didn’t complete.
```python
Couldn't share the transcript.
```
The upload must fit an 8 MiB limit. On a long session, Claude Code progressively drops parts of the share, the last request’s model settings first, then the structured conversation and subagent transcripts, and shows this message when no reduced version can be sent or a network or server error stops the upload. When Claude Code saves a local archive instead, the message means it couldn’t write the archive. **What to do:**
- Run `/feedback` to send the transcript with a description of what happened. See [Report an error](#report-an-error) if `/feedback` is unavailable in your environment
- If other requests are failing too, check your network connection and see [Unable to connect to API](#unable-to-connect-to-api)
[](#couldnt-send-feedback)
Couldn’t send feedback
You sent a report from the [`/feedback`, `/bug`, or `/share` dialog](commands.md#all-commands) and the upload to Anthropic failed. The dialog keeps your text so you can retry.
```python
Couldn't send feedback (couldn't reach the service). If it keeps failing, you can file at https://github.com/anthropics/claude-code/issues instead.
```
The text after the prefix names what failed:
- **`: not signed in. Run /login, then retry.`**: the dialog uploads only when Claude Code found Anthropic credentials as it opened, and none were usable by the time you sent. For example, you signed out on this machine in the meantime, or your login could no longer be refreshed.
- **A parenthetical**: `(server returned <status>)` is the service’s response code; `(request timed out)` and `(couldn't reach the service)` are network failures. When Claude Code can’t name a reason, the parenthetical is absent.
In the [feedback drafts queue](tools-reference.md#sendfeedback-tool-behavior), the same failure ends with `The draft is still queued. Try again later.` instead, and the draft stays in the queue for another attempt. **What to do:**
- For the not-signed-in wording, run `/login` and send again
- Otherwise, send again; if other requests are failing too, check your network connection and see [Unable to connect to API](#unable-to-connect-to-api)
- If it keeps failing, file the report at [github.com/anthropics/claude-code/issues](https://github.com/anthropics/claude-code/issues), as the message says
Before v2.1.281, every send failed with this message once a Remote Control **Stop** or an urgent cross-session message had arrived while the dialog was open. On those versions, close the dialog, reopen it, and send again.
[](#request-errors)
Request errors
These errors relate to the content of your request. Most come back from the API after it rejected the request; a few are produced locally by Claude Code before any request is sent.
[](#prompt-is-too-long)
Prompt is too long
The conversation plus attached files exceeds the model’s context window.
```python
Prompt is too long
```
In an interactive session, Claude Code shows this error as:
```python
Context limit reached · /compact or /clear to continue
```
The line names only `/clear` when [`DISABLE_COMPACT`](env-vars.md) is set. Longer forms of the error, such as the compaction-failed form below, keep the `Prompt is too long ·` wording. In `-p` output and the transcript, the text stays `Prompt is too long`. When you turned auto-compact off in your [user settings](settings-reference.md#autocompactenabled), the line also says so:
```python
Context limit reached · /compact or /clear to continue · auto-compact is off · /config to turn it on
```
The **Auto-compact** toggle in `/config` writes `autoCompactEnabled` to user settings. The hint appears only when a `/config` change would take effect. For example, it doesn’t appear when [`DISABLE_AUTO_COMPACT`](env-vars.md) or [`DISABLE_COMPACT`](env-vars.md) turned auto-compact off. It also doesn’t appear when a higher-precedence scope, such as project or managed settings, set `autoCompactEnabled` to `false`. Before v2.1.235, the line carried no auto-compact hint. Amazon Bedrock reports this condition as `Input is too long for requested model.`, which Claude Code handles the same way. Before v2.1.217, Claude Code didn’t recognize the Bedrock wording, so auto-compact never triggered on it and `/compact` failed with the same error. A [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway-config.md#upstream-error-messages) reports this condition as `capability_rejected: prompt_too_long` when a cloud upstream rejects the request in the provider’s own error shape. Claude Code treats the token the same as `Prompt is too long`. Before v2.1.228, Claude Code didn’t recognize the token, so auto-compact didn’t trigger on it. When automatic compaction ran on this turn and failed on an underlying error, such as an unavailable model or an authentication failure, the message names that error after a separator:
```python
Prompt is too long · automatic compaction failed: <the underlying error>
```
Resolve the named error first; `/compact` fails on the same error until you do. Before v2.1.229, a failed automatic compaction surfaced `Prompt is too long` without the cause. When automatic compaction runs on this error, it normally summarizes your oldest exchanges and keeps the newest. As a last resort, Claude Code summarizes differently:
- When it can’t summarize any whole exchange, Claude Code keeps your newest prompt word for word and summarizes everything before it.
- In that case, when the conversation doesn’t end with your prompt, Claude Code summarizes the whole conversation instead.
Claude Code skips this recovery when the content it would carry forward holds no model reply and less than about 1,000 tokens of your own text, such as a short retry sent after an oversized paste. Run `/clear` to start fresh. Before v2.1.269, compaction failed whenever it couldn’t summarize a whole exchange, so a session in that state hit this error again on every turn. A single-exchange conversation has no earlier turns to summarize. When automatic compaction would have run on one, Claude Code skips the attempt and explains what fills the request instead. When the API doesn’t report token counts in its error, the message reads:
```python
Prompt is too long · this conversation is a single exchange and cannot be compacted — the request size comes mostly from system prompt, tool definitions, or attachments.
```
When the API reports token counts in its error, Claude Code compares them with its own estimate of the conversation’s size to tell which is most of the request: the conversation’s own content, or the system prompt, tool definitions, and attachment content that Claude Code sends with it. When the conversation’s own content is most of the request, the message reads:
```python
Prompt is too long · the request is ~<request tokens> tokens (limit <limit>) and this conversation's own content is most of it. A single-exchange conversation cannot be compacted; start with less content (smaller files or pasted text).
```
When most of the request is outside the conversation, the message reads:
```python
Prompt is too long · the request is ~<request tokens> tokens (limit <limit>) but this conversation is only ~<conversation tokens> tokens — the rest is system prompt, tool definitions, and attachment content. A single-exchange conversation cannot be compacted; reduce attached files/tools or start with less context.
```
Before v2.1.162, Claude Code attempted the compaction anyway and surfaced the bare `Prompt is too long` when it failed. **What to do:**
- Run `/compact` to summarize earlier turns and free space, or `/clear` to start fresh. If `/compact` answers `Not enough messages to compact.`, the conversation is a single exchange with nothing earlier to summarize, so the space is taken by that one prompt and what Claude Code sends with every request: run `/clear` and resend with less pasted text or smaller attachments, or reduce the tool definitions and memory files using the steps below
- 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](memory.md#path-specific-rules) that load only when relevant
- Auto-compact is on by default and normally prevents this error. If you turned it off in `/config` or with [`DISABLE_AUTO_COMPACT`](env-vars.md), turn it back on. If you keep it off, run `/compact` yourself before the window fills.
See [Explore the context window](context-window.md) for an interactive view of how context fills up.
[](#context-exceeds-the-token-limit)
Context exceeds the token limit
`/context` shows this warning at the top of its output when the conversation has grown past the model’s context window. Requests fail with [`Prompt is too long`](#prompt-is-too-long) until you free space. An interactive session shows that error as the `Context limit reached` line.
```python
Context exceeds the 200k-token limit by 94k tokens — run /compact or /clear to continue.
```
When the limit you exceeded is a compaction window, such as the 200K boundary on 1M-context models, the warning reads differently. A compaction window can sit below the model’s context window, so requests past it can still succeed.
```python
Context is 94k tokens past the 200k-token compaction window — run /compact to reduce usage.
```
Both forms name `/clear` instead of `/compact` when you have set [`DISABLE_COMPACT`](env-vars.md). **What to do:**
- In a multi-turn conversation, run `/compact` to summarize earlier turns and free space. To start fresh instead, run `/clear`
- For more ways to reduce usage, see [Prompt is too long](#prompt-is-too-long)
Before v2.1.216, `/context` showed usage above 100% with no warning line explaining what that meant or how to recover.
[](#request-too-large)
Request too large
The raw request body exceeded the API’s 32MB limit before tokenization, usually because of large pasted content, tool results, or attachments. This limit is separate from the [context window](#prompt-is-too-long).
```python
Request too large (max 32MB). Accumulated images and attachments in the conversation pushed the request over the limit. Run /compact, or double press esc to go back and remove attachments.
```
When the request went straight to the Claude API and the API itself rejected it, Claude Code measures the conversation and words the message by whether recovery can work. Through a proxy, gateway, or cloud provider you get the general message. The measured forms:
- `Request too large (max 32MB; 20.1MB of about 33.4MB is images or documents).`: images or documents pushed the request over the limit. Claude Code retries with them stripped.
- `Request too large for the API's 32MB request limit`: the messages alone are over the limit, so the message says `compacting cannot make it fit` and Claude Code doesn’t retry. In [non-interactive mode](headless.md), the message tells you to reduce the input or start a new session instead.
Before v2.1.212, conversations with enough accumulated images failed on every turn with `Request too large (max 32MB). Double press esc to go back and try with a smaller file.` Before v2.1.229, Claude Code showed the attachment advice for every rejection, even when compacting couldn’t help. **What to do:**
- If the message says `compacting cannot make it fit`, press Esc twice to step back past the turn that added the large content, or run `/clear` to start fresh
- Otherwise, run `/compact`, which drops accumulated images and attachments
- Reference large files by path instead of pasting their contents, so Claude can read them in chunks
- For images, see [Image was too large](#image-was-too-large) below
[](#image-was-too-large)
Image was too large
A pasted or attached image exceeds the API’s size or dimension limits.
```python
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
```
Claude Code replaces the unprocessable image with a text placeholder and retries, so subsequent messages succeed. On versions before 2.1.142, a pasted image could remain in the conversation and repeat the same error on every subsequent message. To recover on those versions, press Esc twice and step back past the turn where the image was added. **What to do:**
- 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
[](#unable-to-resize-image)
Unable to resize image
Claude Code couldn’t downscale an attached image before sending it to the API.
```python
Unable to resize image — image processing is unavailable and dimensions could not be read from the file header. Please convert the image to PNG, JPEG, GIF, or WebP.
Unable to resize image — dimensions exceed the 2000x2000px limit and image processing failed. Please resize the image to reduce its pixel dimensions.
Unable to resize image (… raw, … base64). The image exceeds the … API limit and compression failed. Please resize the image manually or use a smaller image.
Unable to resize image — could not verify image dimensions are within the 2000x2000px API limit.
Unable to resize image — it is a CMYK JPEG, which Claude Code cannot decode, and at …px it is over the 2000x2000px limit, so it cannot be sent. Re-save it as an RGB PNG or JPEG and try again.
Unable to resize image — it is an animated WebP whose first frame Claude Code cannot decode, and at …px it is over the 2000x2000px limit, so it cannot be sent. Save its first frame as a PNG or JPEG and try again.
Unable to resize image — its pixels could not be decoded (the file may be damaged, or use an encoding Claude Code cannot read), and it is over the … API limit (… raw, … base64), so it cannot be sent. Re-save it as a PNG or JPEG and try again.
```
Claude Code normally resizes large images automatically. These errors mean the image couldn’t be decoded or resized to fit within the API limits. **What to do:**
- If the message asks you to convert the image, convert it to PNG, JPEG, GIF, or WebP and attach it again. Claude Code can verify dimensions for these formats from the file header, without decoding the image.
- If the message reports a dimension or size limit, resize or recompress the image below that limit before attaching.
- If the message names a cause, such as a CMYK JPEG, an animated WebP, or a possibly damaged file, re-save the image in the format the message suggests and attach it again.
[](#pdf-errors)
PDF errors
The PDF you attached couldn’t be processed. The messages are shown here in their non-interactive form; in an interactive session they instead prompt you to double press esc and try again.
```python
PDF too large (max 100 pages, 20MB). Try reading the file a different way (e.g., extract text with pdftotext).
PDF is password protected. Try using a CLI tool to extract or convert the PDF.
The PDF file was not valid. Try converting it to text first (e.g., pdftotext).
```
**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
When Claude reads a page range from a PDF with the Read tool, the read can fail with a different message:
```python
pdftoppm is not installed. Install poppler-utils (e.g. `brew install poppler` or `apt-get install poppler-utils`) to enable PDF page rendering.
```
Page-range reads render pages with `pdftoppm`. Install poppler-utils with the command the message gives, or on other platforms a poppler build that puts `pdftoppm` on your `PATH`. See [Read tool behavior](tools-reference.md#read-tool-behavior) for which PDFs are read by page range.
[](#extra-inputs-are-not-permitted)
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.
```python
API Error: 400 ... Extra inputs are not permitted ... context_management
```
Claude Code sends beta-only fields such as `context_management` and `effort` alongside an `anthropic-beta` header that enables them. When a gateway forwards the body but drops the header, the API sees fields it doesn’t recognize. **What to do:**
- Configure your gateway to forward the `anthropic-beta` header. See [feature pass-through](../13-Enterprise-Admin/llm-gateway-protocol.md#feature-pass-through) for what gateways must forward.
- As a fallback, set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](env-vars.md) before launching. [Disable pre-release capabilities](../13-Enterprise-Admin/llm-gateway-protocol.md#disable-pre-release-capabilities) covers the exact scope.
[](#tool-input-schema-is-invalid)
Tool input schema is invalid
A tool in the request declared an `input_schema` that fails the API’s JSON Schema validation, so the API rejected the whole request. The number after `tools.` is the failing tool’s position in the request’s tool list, not a name you can look up.
```python
API Error: 400 ... tools.N.custom.input_schema: JSON schema is invalid
API Error: 400 ... tools.N.custom.input_schema.properties: Property keys should match pattern '^[a-zA-Z0-9_.-]{1,64}$'
```
The first form means the schema isn’t valid JSON Schema draft 2020-12. The second means a top-level property name doesn’t match the pattern the message quotes. Claude Code [excludes MCP tools whose input schema would fail this validation](../06-MCP-Tools/General/mcp.md#tools-with-invalid-input-schemas) when it loads a server’s tools, so requests normally never include one. On a [deployment where flag fetching is off](env-vars.md#features-that-need-feature-flag-fetching), or on a machine whose flags have never arrived, Claude Code records in the server’s log which tool would be rejected but sends it anyway, so this error can still occur. The error can also occur for a tool whose schema declares a JSON Schema dialect other than draft 2020-12 in `$schema`. Claude Code doesn’t check those schemas against the JSON Schema meta-schema, though the top-level property-name check still applies. Before v2.1.216, no deployment ran the exclusion checks. **What to do:**
- If your Claude Code version is earlier than v2.1.216, run `claude update`.
- Remove or [disable](../06-MCP-Tools/General/mcp.md#disable-a-server-without-removing-it) the MCP server that declares the invalid schema. The error names the tool only by position. On v2.1.216 or later, check each server’s log for a line naming a tool whose input schema would be rejected. If no log names one, disable servers one at a time.
- If you maintain the server, fix the tool’s `input_schema`. The schema must be valid JSON Schema, and top-level property names must be 1 to 64 characters long and use only ASCII letters and digits, `_`, `.`, and `-`. See [Tools with invalid input schemas](../06-MCP-Tools/General/mcp.md#tools-with-invalid-input-schemas).
[](#tool-use-name-over-200-characters)
tool_use.name over 200 characters
A tool call in the conversation history carries a name longer than the 200 characters the API accepts in a request:
```python
API Error: 400 ... tool_use.name: String should have at most 200 characters
```
Claude Code cuts such a name to 200 characters when the response arrives and when it loads a saved conversation, so the call fails with an ordinary `No such tool available` tool error and the conversation continues without this API error. **What to do:**
- Run `claude update`, then resume the conversation. The updated version repairs the overlong name when it loads the transcript, so a conversation that was stuck works again.
Before v2.1.281, the overlong name stayed in the history and the API rejected every request that re-sent the conversation, including `/compact` and `--resume`, so this error repeated and the conversation was stuck.
[](#theres-an-issue-with-the-selected-model)
There’s an issue with the selected model
The configured model name was not recognized or your account lacks access to it. As of v2.1.160 the trailing hint, shown here in its interactive form, varies by surface.
```python
There's an issue with the selected model (claude-...). It may not exist or you may not have access to it. Run /model to pick a different model.
```
**What to do:**
- **Interactive CLI**: run `/model` to pick from models available to your account.
- **Non-interactive mode (`-p`)**: pass `--model` with a valid alias or ID, or set [`ANTHROPIC_MODEL`](env-vars.md). The error text shows `Run --model` on this surface.
- **Agent SDK**: the error text omits the hint because the model is set programmatically. Set [`model` on `Options`](../05-Agent-SDK/agent-sdk-typescript.md#options) in TypeScript or [`ClaudeAgentOptions(model=...)`](../05-Agent-SDK/agent-sdk-python.md#claudeagentoptions) in Python, and handle the structured `model_not_found` error to surface your own retry or model picker.
- Use an alias such as `sonnet` or `opus` instead of a full versioned ID. Aliases resolve to a maintained default so they don’t go stale. See [Model configuration](model-config.md).
- If the wrong model keeps coming back in the CLI, a stale ID is set somewhere. Check the places you can set a model in [priority order](model-config.md#setting-your-model) and remove the stale value.
- Claude Code reports an expired claude.ai login as [Login expired](#login-expired), not as this error. Before v2.1.206, an expired login that could no longer be refreshed failed every model with this error; run `/login` if you see that on an older version.
- For Google Cloud’s Agent Platform deployments, see [Google Cloud’s Agent Platform troubleshooting](google-vertex-ai.md#troubleshooting).
[](#model-is-not-a-recognized-model-id)
Model is not a recognized model id
The string you passed to a model switch isn’t one Claude Code can use as a model, so it refused the switch without sending a request and the session keeps its current model. You can get this error when a model is set through the [Agent SDK](../05-Agent-SDK/agent-sdk-typescript.md) `setModel()` method, by an app that runs the Claude Code CLI for you, such as the [Desktop app](../16-Mobile-Desktop/desktop.md), or when you pick a model from a device connected through [Remote Control](remote-control.md). Before v2.1.200, Claude Code saved the string and failed on the next request with [There’s an issue with the selected model](#theres-an-issue-with-the-selected-model).
```python
Model "Sonnet5" is not a recognized model id. Did you mean 'claude-sonnet-5'?
```
In this example an app sent the display name `Sonnet 5`, which the message repeats without its space. The trailing hint names the closest matching alias or model ID. When nothing is close enough, it reads `Run /model to see available models.` instead. In a session that the [Desktop app](../16-Mobile-Desktop/desktop.md) starts for you, the no-match hint reads `Switch to a different model.` When you switch through the Agent SDK or an app on the Anthropic API, only a string that can’t be a model ID gets this error, such as a display name or an empty string. When you pick a model from a Remote Control device, Claude Code checks the string locally. Any string that isn’t a model alias, a model Claude Code lists or you configured, or an ID that starts with `claude-` gets this error, a mistyped ID such as `claud-sonnet-5` included. Before v2.1.260, this check didn’t cover Remote Control picks, so an unrecognized string was applied and failed on the next request. **What to do:**
- Run `/model` with no argument to open the picker and choose from the models available to your account, then pass the alias or ID shown there
- If you used an alias that only a newer Claude Code version supports, run `claude update`, or pass the model’s full ID instead. The server can still require a minimum Claude Code version for that model; see [Claude Code does not support this model](#claude-code-does-not-support-this-model).
- A model saved before v2.1.200 isn’t repaired by this check. If a stale value keeps coming back, remove it from the locations listed under [Setting your model](model-config.md#setting-your-model).
- On any provider other than the Anthropic API, or behind a gateway or custom `ANTHROPIC_BASE_URL`, only an empty string gets this error. Claude Code can still write the [unrecognized-model diagnostic line](#unrecognized-model-id-on-a-request) at request time, on every provider.
[](#model-not-found)
Model not found
You switched to a model by name and Claude Code couldn’t confirm that a model with that name exists. When the name isn’t a [model alias](model-config.md#model-aliases) or another spelling Claude Code accepts locally, Claude Code verifies it with a minimal API request, and this error is usually your API endpoint’s answer. With `/model <name>`, a name that can’t be a model ID at all, such as one containing spaces, gets the same message.
```python
Model 'claude-opus-9' not found
```
On providers with provider-specific model IDs, the message may add a `Try '...' instead` suggestion that names your provider’s ID for a fallback model. **What to do:**
- Run `/model` with no argument and pick from the models available to your account, or use a [model alias](model-config.md#model-aliases) such as `sonnet`, which resolves to a maintained default
- If you typed a full ID, check it against your provider’s model catalog. A newly launched model can be available on the Anthropic API before your provider or region offers it.
- In the Agent SDK, `setModel()` fails with this message and the session keeps running on its previous model. In the TypeScript SDK, call [`supportedModels()`](../05-Agent-SDK/agent-sdk-typescript.md#query-object) to list the models you can switch to.
- Before v2.1.265, `/model` also rejected the `opusplan[1m]` alias spelling with this error. On those versions, update Claude Code, or set the model in [settings](model-config.md#setting-your-model) or with `--model` instead.
[](#couldnt-confirm-model-with-the-api)
Couldn’t confirm model with the API
You switched models through the [Agent SDK](../05-Agent-SDK/agent-sdk-typescript.md) `setModel()` method or an app that runs the Claude Code CLI for you, such as the [Desktop app](../16-Mobile-Desktop/desktop.md), and the request that confirms the model ID with your API endpoint got no answer within five seconds. The session keeps its current model.
```python
Couldn't confirm model "claude-sonnet-5" with the API. Try again, or run /model to see available models.
```
In a session that the [Desktop app](../16-Mobile-Desktop/desktop.md) starts for you, the message ends at `Try again.` **What to do:**
- Switch to the model again
- If the switch keeps failing, check that Claude Code can reach your API endpoint; see [Network and connection errors](#network-and-connection-errors)
[](#api-error-model-not-changed)
API error when checking the picked model
You picked a model with `/model <name>`, or an app connected to the session requested the switch. The API refused the minimal request Claude Code sends to verify the model, for a reason that has no entry of its own, such as a rate limit or a server error. The session keeps its current model, and the message ends by saying so:
```python
API error: 429 <the server's explanation> · model not changed
```
The middle of the message is the HTTP status and the server’s own explanation. **What to do:**
- Act on the server’s explanation; for a rate limit or a 5xx status, wait and pick the model again
- The refusals with their own wording are covered by the surrounding entries, such as [Model not found](#model-not-found) and [Model is restricted by your organization’s settings](#model-is-restricted-by-your-organizations-settings)
[](#claude-opus-is-not-available-with-the-claude-pro-plan)
Claude Opus is not available with the Claude Pro plan
Your active subscription plan does not include the model you selected.
```python
Claude Opus is not available with the Claude Pro plan. If you have updated your subscription plan recently, run /logout and /login for the plan to take effect.
```
In a session the Claude Desktop app runs, the message says to `sign out and sign in again` instead of naming the commands. **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 claude.ai does not take effect in an existing session until you re-authenticate.
- See [claude.com/pricing](../17-Billing-Plans/pricing.md) for which models each plan includes
[](#claude-code-does-not-support-this-model)
Claude Code does not support this model
The API refused the request with a 400 because your Claude Code version is below a required minimum. Either the model you selected requires a newer version, which the server checks per model, or your organization’s policy requires one. The 400 carries the error code `claude_code_version_too_old`, and the message says which minimum applies.
```python
API Error: 400 Claude Code 2.1.219 does not support this model; version 2.1.255 or newer is required. Run 'claude update', or update the Claude desktop app, then try again.
```
The organization-policy wording reads:
```python
API Error: 400 Claude Code 2.1.240 is older than the minimum version required by your organization's policy. Run 'claude update', or update the Claude desktop app, to continue.
```
The version the API checks is the one reported by the Claude Code binary that made the request. **What to do:** Update that binary, then start a new session. Where the binary came from decides how, except in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments-deploy.md#pin-the-version):
| The binary that made the request | How to update it |
|:-------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| A Claude Code you installed | Run `claude update` |
| The Claude desktop app | Update the app |
| The binary the [VS Code extension](../03-IDE-Integrations/vs-code.md) bundles | Update the extension |
| The binary an Agent SDK package bundles | [Upgrade the SDK package](../05-Agent-SDK/agent-sdk-hosting.md#runtime-dependencies), then restart your application. In a [compiled single-file executable](../05-Agent-SDK/agent-sdk-typescript.md#compile-to-a-single-executable), rebuild it |
- For the per-model wording, you can keep working in the current session by switching to another model: run `/model` in the CLI, call [`setModel()`](../05-Agent-SDK/agent-sdk-typescript.md#query-object) on the TypeScript SDK’s `Query` object in streaming input mode, or call [`set_model()`](../05-Agent-SDK/agent-sdk-python.md#claudesdkclient) on the Python SDK’s `ClaudeSDKClient`
- For the organization-policy wording, update before you continue
[](#model-is-restricted-by-your-organizations-settings)
Model is restricted by your organization’s settings
Your organization admin has disabled this model in the claude.ai admin console, or managed settings exclude it through an [`availableModels`](model-config.md#restrict-model-selection) allowlist or a [`deniedModels`](model-config.md#block-specific-models-or-versions) list. The notice appears at startup when `--model`, `ANTHROPIC_MODEL`, or the `model` setting named the restricted model, and it names the model the session uses instead. If managed settings leave no permitted model for the session to use, see [Managed settings block the default model](#managed-settings-block-the-default-model). The substitution notice can also appear mid-session after an admin disables the model a session is running on in the claude.ai admin console.
```python
Model "claude-opus-4-8" is restricted by your organization's settings. Using claude-sonnet-4-6 instead.
```
Typing `/model <name>` for a restricted model is rejected and the session keeps its current model. For a model disabled in the admin console, the rejection reads `Model '<name>' is restricted by your organization's settings. Run /model to choose a different model.` For a model that managed settings exclude, it reads `Model '<name>' is not available. Your organization restricts model selection.` A notice prefixed with an agent, skill, or command name means the restriction applied to that [subagent’s requested model](../09-Agents-Patterns/sub-agents.md#choose-a-model): the subagent runs on the substituted model and your session’s model is unchanged. Before v2.1.223, Claude Code showed the notice only for subagents launched with the Agent tool. Claude Code treats a model family alias, one of `opus`, `sonnet`, `haiku`, or `fable`, as a request for that family rather than for its newest version. On the Anthropic API and on [Claude Platform on AWS](claude-platform-on-aws.md), a restricted family alias resolves to the newest version of the family that your organization’s settings permit, and the substitution notice names that version. Claude Code rejects `/model <alias>` only when every version of the family is restricted. Before v2.1.205, a family alias was substituted or rejected based on its newest version alone, even when an older version of the same family was allowed. **What to do:**
- Run `/model` to pick from the models your organization allows. Restricted models are hidden from the picker.
- If the restricted model was set in `--model`, `ANTHROPIC_MODEL`, the `model` field of a settings file, or the `model` frontmatter of a [subagent](../09-Agents-Patterns/sub-agents.md#choose-a-model), skill, or command, remove or update that value so the notice doesn’t recur
- If you need access to the restricted model, ask your organization admin to enable it. See [Organization model restrictions](model-config.md#organization-model-restrictions).
[](#model-switch-was-blocked-by-a-premodelswitch-hook)
Model switch was blocked by a PreModelSwitch hook
A [PreModelSwitch hook](../07-Hooks/hooks.md#premodelswitch) didn’t approve the model switch you or a client requested, so the session keeps its current model. When the switch came from an [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) host or [Remote Control](remote-control.md) rather than a command you typed, the message reads `Model switch blocked by a PreModelSwitch hook` without naming the target model.
```python
Model switch to Opus 4.6 was blocked by a PreModelSwitch hook: Opus 4.6 is retired for this project. Use a newer model.
```
The reason after the colon says what refused the switch:
- **A reason a hook wrote**: a PreModelSwitch hook supplied that reason when it [denied the switch or asked for confirmation](../07-Hooks/hooks.md#premodelswitch-decision-control). Address what it asks, or pick a model your hooks allow.
- **`PreModelSwitch hook <name> did not respond before its timeout`**: a hook that doesn’t answer before its [timeout](../07-Hooks/hooks.md#timeouts) blocks the switch. Fix the hanging command or raise that hook’s `timeout`, then switch again.
- **`confirmation required, and this session cannot ask`**: a hook answered `ask` without a reason, and a control request has no way to show the confirmation prompt. A `/model` command in a [`-p` run](headless.md) reports the same condition with `(run /model interactively to confirm)` after the reason. Make the switch from an interactive session, or change the hook’s decision for this model.
- **`so organization-managed PreModelSwitch hooks could not be checked`**: Claude Code couldn’t tell which PreModelSwitch hooks your organization’s [managed plugins](settings-reference.md#enabledplugins) deliver, for example because a managed plugin failed to load. One of those hooks might block the switch, so Claude Code refuses rather than apply the switch unchecked. The start of the reason names what failed. Claude Code re-checks on every switch attempt, so a failure that has since cleared stops blocking; if it keeps failing, run `claude --debug` and switch again to capture the details, then fix the plugin or ask your admin to fix it.
- **`a PreModelSwitch hook failed before answering`** or **`PreModelSwitch hooks were cancelled (the control stream closed) before answering`**: the hook run ended without a verdict, and Claude Code doesn’t treat that as approval. Run `claude --debug` to see what failed, then switch again.
Before v2.1.260, the managed-plugin refusal read `plugin hooks could not be loaded, so PreModelSwitch hooks could not be checked; see the debug log`. Claude Code retried the plugin load once and then refused later switches in the session, even when your organization managed no plugins. Restart the session to run the plugin load again on those versions.
[](#couldnt-save-it-as-your-default)
Couldn’t save it as your default
You picked a model to save as your default, for example with `/model <name>` or `Enter` in the `/model` picker, and Claude Code couldn’t write the pick to your user settings file, `~/.claude/settings.json`. The switch itself applied, so the current session runs on the model you picked, but your default is unchanged and the next session starts on the old value.
```python
Set model to Fable 5.1 for this session only · couldn't save it as your default: ~/.claude/settings.json can't be written (EROFS)
```
The reason after the file path says what failed:
- **`can't be written (<code>)`**: the write failed with the operating system error code in parentheses, such as `EROFS` when the file, or the file it links to, sits on a filesystem that refuses writes. Make the file writable and switch again. If another tool generates the file, set the `model` key in that tool instead; see [A change you made in Claude Code is lost in new sessions](settings.md#a-change-you-made-in-claude-code-is-lost-in-new-sessions).
- **`isn't valid JSON`**: the file on disk doesn’t parse, and Claude Code leaves it untouched rather than overwrite content it can’t read back. Fix the syntax error, then switch again; see [Fix a broken settings file](settings.md#fix-a-broken-settings-file).
A notice ending `couldn't confirm it was saved as your default (~/.claude/settings.json is still being written)` means the write hadn’t finished after three seconds. It continues in the background, so the default may still be saved; check which model your next session starts on, or run `/model <name>` again. Before v2.1.265, the notice said the model was `saved as your default for new sessions` even when the write failed.
[](#thinking-type-enabled-is-not-supported-for-this-model)
thinking.type.enabled is not supported for this model
Your Claude Code version is older than the minimum for the selected model. The CLI sent a thinking configuration the model no longer accepts.
```python
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` and restart Claude Code. Opus 4.7 needs v2.1.111 or later. Opus 4.8 needs v2.1.154 or later. Sonnet 5 needs v2.1.197 or later. Opus 5 needs v2.1.219 or later. Opus 5.5 needs v2.1.280 or later. Sonnet 5.5 needs v2.1.284 or later
- If you can’t upgrade, run `/model` and select Opus 4.6 or Sonnet 4.6 instead
- If you hit this in the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), upgrade the SDK package instead. Opus 4.8 needs TypeScript SDK v0.3.154 or later and Python SDK v0.2.88 or later. Sonnet 5 needs TypeScript SDK v0.3.197 or later. Opus 5 needs TypeScript SDK v0.3.219 or later. Opus 5.5 needs TypeScript SDK v0.3.280 or later. Sonnet 5.5 needs TypeScript SDK v0.3.284 or later
[](#effort-isnt-available-with-thinking-turned-off)
Effort isn’t available with thinking turned off
You turned [extended thinking](model-config.md#extended-thinking) off and ran at an [effort level](model-config.md#adjust-effort-level) above `high`. The model doesn’t accept that combination, so the API rejected the request.
```python
API Error: Effort 'xhigh' isn't available with thinking turned off on this model · run /effort high to continue, or turn thinking back on (unset MAX_THINKING_TOKENS=0)
```
The hint after the `·` varies by session: in a non-interactive session it reads `use --effort high (or the effortLevel setting)`, and in a session the Claude Desktop app runs it reads `you can lower effort to High`. **What to do:**
- [Lower the effort level](model-config.md#set-the-effort-level) to `high` or below.
- Turn thinking back on, for example by unsetting [`MAX_THINKING_TOKENS`](env-vars.md) or removing [`"alwaysThinkingEnabled": false`](settings-reference.md#alwaysthinkingenabled) from your settings.
Before v2.1.242, Claude Code showed the API’s own message: `API Error: 400 output_config.effort 'xhigh' is not supported when thinking is disabled on this model. Use effort 'high' or below, or enable thinking.` Before v2.1.251, Claude Code sent the request at the effort level you set, so Opus 5 rejected every request above `high` with thinking turned off. Claude Code now sends effort `high` instead to models it knows reject the combination, such as Opus 5.
[](#thinking-budget-exceeds-output-limit)
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.
```python
API Error: 400 ... max_tokens must be greater than thinking.budget_tokens
```
**What to do:**
- Raise [`CLAUDE_CODE_MAX_OUTPUT_TOKENS`](env-vars.md) above the thinking budget
- See [Extended thinking](model-config.md#extended-thinking) for how the budget interacts with output length
[](#tool-use-or-thinking-block-mismatch)
Tool use or thinking block mismatch
The conversation history reached the API in an inconsistent state.
```python
API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.
API Error: 400 orphaned tool_result in conversation history. Run /rewind to recover the conversation.
API Error: 400 duplicate tool_use ID in conversation history. 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 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:**
- If you are using Opus 4.7 or Opus 4.8, run `claude update` first. Versions before v2.1.156 can trigger this error during normal tool use, and `/rewind` doesn’t clear it.
- Run `/rewind`, or press Esc twice, to step back to a checkpoint before the corrupted turn and continue from there. See [Checkpointing](checkpointing.md) for how checkpoints are created and restored.
[](#invalid-data-in-redacted-thinking-block)
Invalid data in redacted_thinking block
The API refused the request with a 400 because it couldn’t accept a `redacted_thinking` block that an earlier turn in the conversation history carries.
```python
API Error: 400 ... Invalid `data` in `redacted_thinking` block
```
Claude Code leaves the conversation’s earlier thinking out of the request and retries once, so the session continues without showing the error. Before v2.1.282, Claude Code kept the refused block, and every later turn failed with the same error. **What to do:**
- If you’re on v2.1.281 or earlier and every turn fails with this error, run `claude update` and resume the session
- If the error persists, run `/clear` to start a conversation that doesn’t carry the block
[](#unsupported-tool-content-removed)
Unsupported tool content removed
When Claude Code connects directly to the Anthropic API and loads or previews a saved session, it removes tool content the Anthropic API doesn’t accept and leaves this line where removed content sat between two thinking blocks:
```python
[Unsupported tool content removed]
```
Such content reaches a session file when something other than the Anthropic API answered in the API’s format, typically a third-party proxy set through [`ANTHROPIC_BASE_URL`](env-vars.md) that translates another provider’s tool calls. Claude Code removes it only when the session connects directly to the Anthropic API, and loads the saved history as it is when the session runs through a proxy or on another provider. Before v2.1.246, Claude Code sent the tool use and its result back to the API, and every turn of the resumed session failed with a 400 error such as `messages.1.content.0.server_tool_use.name: Input should be 'web_search', 'web_fetch', ...`. **What to do:**
- None needed when you see the placeholder line. The session continues without the removed content.
- If every turn of a resumed session fails with the 400 error instead, run `claude update` and resume the session again. Versions before v2.1.246 don’t remove the content.
[](#role-system-must-precede-an-assistant-message)
role ‘system’ must precede an ‘assistant’ message
The API refused the request with a 400 because a system message sits at a position in the conversation it doesn’t accept:
```python
API Error: 400 messages.6: role 'system' must precede an 'assistant' message or end the array; ...
```
Claude Code sends some of its reminder and attachment text as system messages inside the conversation. When the API refuses one’s position, Claude Code retries the request once with that text sent as ordinary user messages instead. The API’s sibling placement wordings, such as `use the top-level 'system' parameter for the initial system prompt`, get the same recovery. When the error does appear, the refused system message isn’t one Claude Code can remove. That usually means a proxy or [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) between Claude Code and the API added a system message of its own. **What to do:**
- If the error repeats on every turn behind a proxy or gateway configured through [`ANTHROPIC_BASE_URL`](env-vars.md), connect without the proxy to confirm the source, and report the error to whoever operates it
- Run `/clear` to start a fresh conversation. If the error returns there too, the cause is on the request path, not in the saved conversation.
Before v2.1.280, Claude Code didn’t recognize this wording, so the error also appeared when the refused system message was one Claude Code itself sent, and every later turn of the conversation failed the same way.
[](#invalid-encrypted-content-in-search-result-block)
Invalid encrypted_content in search_result block
The API refused the request with a 400 because the conversation history holds hosted web-search content it can’t decrypt. The wording names the field it can’t read:
```python
API Error: 400 ... Invalid `encrypted_content` in `search_result` block
API Error: 400 ... Invalid `encrypted_index` in `text` block
API Error: 400 ... Failed to decrypt web search result content
API Error: 400 ... Invalid `encrypted_stdout` in `encrypted_code_execution_result` block
```
Results from the API’s hosted [web search tool](../04-API-Reference/Agents-Tools/agents-and-tools-tool-use-web-search-tool.md) carry encrypted fields that only the API can read. The `encrypted_stdout` wording names the output of a hosted code execution program that read such results, which the API encrypts as well. The API refuses a request that replays content it can’t decrypt, such as content produced for a different organization. Claude Code’s own [WebSearch tool](tools-reference.md#websearch-tool-behavior) records search results as plain text, so these blocks usually reach a conversation through a proxy or [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) that ran hosted web search itself. For the three web search wordings, Claude Code leaves the search calls, results, and citations out of what it sends and retries the request once, so the session continues without showing the error. The `encrypted_stdout` wording has no such recovery, so that message still reaches you. Before v2.1.282, Claude Code kept the refused web search blocks too, and every later turn and `/compact` failed the same way. **What to do:**
- If you’re on v2.1.281 or earlier and every turn fails with one of the web search wordings, run `claude update` and resume the session
- If the error persists, or the message names `encrypted_stdout`, run `/rewind` to step back to a checkpoint before the turn that added the content, or run `/clear` to start a conversation that doesn’t carry it
- If you run Claude Code behind a proxy or gateway, report the error to whoever operates it
[](#usage-policy-refusal)
Usage Policy refusal
The API declined to respond because content in the conversation triggered a [Usage Policy](https://www.anthropic.com/legal/aup) check. The message includes a Request ID and a Message ID you can quote to support if you believe the refusal is incorrect.
```python
API Error: Opus 4.6 can't help with this. Start a new session to continue.
Send feedback with /feedback or learn more: https://www.anthropic.com/legal/aup
```
The message names the model that declined, or `Claude` when no model is recorded. The check evaluates the full conversation, not only your latest prompt, so sending a new message in the same session usually re-triggers the same refusal. The same applies after exiting and reopening the session with `--continue` or `--resume`, since the transcript on disk still contains the triggering content. On [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), and [Microsoft Foundry](microsoft-foundry.md), this message also covers requests the model’s safety measures flagged as a cybersecurity topic. See [Safety measures flagged a cybersecurity topic](#safety-measures-flagged-a-cybersecurity-topic). Before v2.1.219, the message read `Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). Please double press esc to edit your last message or start a new session for Claude Code to assist with a different task.` **What to do:**
- Press Esc twice or run `/rewind` to step back to a checkpoint before the turn that triggered the refusal, then rephrase or take a different approach. See [Checkpointing](checkpointing.md).
- If you can’t identify which turn caused it, run `/clear` to start a fresh conversation in the same project. Your previous conversation is preserved on disk and remains available in `/resume`.
- In [non-interactive mode](headless.md) (`-p`), where rewind is unavailable, retry with a rephrased prompt in a new session without `--continue`. Policy checks vary by model, so switching to a different model with `--model` may also resolve the refusal in some cases.
[](#safety-measures-flagged-a-cybersecurity-topic)
Safety measures flagged a cybersecurity topic
The model’s safety measures flagged content in the conversation as a cybersecurity topic. The message names the model that flagged the request:
```python
API Error: Opus 4.8's safeguards flagged this message. Our intentionally broad safeguards allow us to deliver more capabilities faster, but can sometimes flag legitimate cybersecurity work. Apply to the Cyber Verification Program to reduce these interruptions. Send feedback with /feedback or learn more: https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude
```
The message links to the [Cyber Verification Program](https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude), which grants access for legitimate cybersecurity work. On Opus 5.5 and Sonnet 5.5, the message opens with `<model>'s safeguards flagged this session` instead. When the flagged category has a fallback model available, Claude Code [switches models](model-config.md#automatic-model-fallback) rather than showing this error. On [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), and [Microsoft Foundry](microsoft-foundry.md), a cybersecurity flag produces the [Usage Policy refusal](#usage-policy-refusal) message instead. The safeguard itself is server-side and predates v2.1.203; client releases since then have changed only the message’s wording. From v2.1.203 through v2.1.218, the message read `<model> has safety measures that flagged this message for a cybersecurity topic. To learn about the Cyber Verification Program and apply for access, visit our help center:` followed by the same help-center link, and interactive sessions appended `If you were not engaging in a cybersecurity topic, please send feedback via /feedback.` Before v2.1.203, it read `<model>'s safeguards flagged this message for a cybersecurity topic. If your work requires this access, you can apply for an exemption:` followed by an exemption form link. **What to do:**
- If your work requires this content, apply for access through the [Cyber Verification Program](https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude)
- If your request wasn’t about a cybersecurity topic, run `/feedback` to report the false positive
- To keep working in the same session, press Esc twice or run `/rewind` to step back to a checkpoint before the turn that triggered the flag, then take a different approach. See [Checkpointing](checkpointing.md).
[](#installation-errors)
Installation errors
These errors appear while installing or updating Claude Code, from the [install script](../01-Getting-Started/setup.md#install-claude-code), `claude install`, or `claude update`. For `command not found`, PATH, permission, and TLS problems during setup, see [Troubleshoot installation and login](troubleshoot-install.md).
[](#installation-was-killed-before-it-could-finish)
Installation was killed before it could finish
The install script reports when the `claude install` step is terminated by a signal. On Linux, exit code 137 means the process received SIGKILL, and on a low-memory host that’s usually the kernel out-of-memory (OOM) killer. The script prints this explanation and exits with code 137:
```python
Installation was killed before it could finish (exit code 137). This usually means the system ran out of memory.
Claude Code needs roughly 512MB of free memory to install. Free up memory, then run this script again.
```
For any other fatal signal, and for exit code 137 on macOS, the script prints `Installation was killed before it could finish (exit code <N>)` with the actual exit code and omits the out-of-memory explanation. The message comes from the install script macOS and Linux use, which also covers installs inside WSL; the native Windows install scripts never print it. Before v2.1.200, the script exited with only the shell’s bare `Killed` line. **What to do:**
- Stop other processes to free memory, then rerun the installer
- Add swap space or move to a larger instance. See [Install killed on low-memory Linux servers](troubleshoot-install.md#install-killed-on-low-memory-linux-servers) for the swap-file commands.
[](#the-connection-dropped-while-downloading-the-update)
The connection dropped while downloading the update
The connection to the download server closed while `claude install` or `claude update` was fetching the Claude Code binary, and the retries didn’t recover. Claude Code retries the download when the connection drops, the transfer stalls, or the downloaded file fails its checksum, up to three attempts in total. A completed HTTP error, such as a 404, isn’t retried because the server already answered. Before v2.1.202, a single dropped connection failed the download immediately with the bare error `aborted` instead of retrying.
```python
The connection dropped while downloading the update (attempt 3/3: aborted). Check your network — proxies sometimes cut off large downloads.
```
The text in parentheses names which attempt failed and the underlying network error. `claude update` precedes the message with `Error: Failed to install native update` on stderr. A download that stays connected but doesn’t finish within 10 minutes fails with `Download timed out: exceeded the total deadline` instead. Claude Code doesn’t retry a timed-out download, because a connection too slow to finish inside the deadline won’t finish on an immediate retry either. The steps below apply to both messages. A proxy or gateway can close a long transfer before it finishes, and the Claude Code binary is a large download. **What to do:**
- Run `claude update` again. On an otherwise healthy network, the download usually succeeds on the next run. For the timed-out message, run it again from a faster or less throttled network.
- If your network requires a proxy, set `HTTPS_PROXY` before running the installer or `claude update`. See [Check network connectivity](troubleshoot-install.md#check-network-connectivity).
- If a corporate proxy keeps closing the transfer, ask your network team to allow the full download from `downloads.claude.ai`. See [Network access requirements](../13-Enterprise-Admin/network-config.md#network-access-requirements).
- Run `claude doctor` from your shell for installation diagnostics
[](#command-line-errors)
Command-line errors
These errors come from the `claude` command line and its subcommands, from a command name you submit at the prompt, and from commands such as `/security-review` that gather context by running shell commands before their prompt runs. They also come from `/tui`, which relaunches the CLI.
[](#conflict-between-bg-and-print)
Conflict between `--bg` and `--print`
This message requires Claude Code v2.1.198 or later. You combined `--bg` with `-p` or `--print` in the same `claude` invocation. `--bg` starts a [background session](../09-Agents-Patterns/agent-view.md#from-your-shell) that you later attach to with `claude agents`, while `--print` runs [non-interactively](headless.md) and never starts the interactive session that `claude agents` attaches to. Before v2.1.198 this combination silently created a background job that could never be attached to.
```python
--bg and --print conflict: --print never starts the interactive session that `claude agents` attaches to, so the job would be unattachable. The prompt is the positional — drop --print: `claude --bg '<task>'`.
```
**What to do:**
- Drop `-p` or `--print`. `--bg` takes the prompt as its positional argument, so `claude --bg "<task>"` is the complete command. See [Dispatch new agents from your shell](../09-Agents-Patterns/agent-view.md#from-your-shell).
- To run the prompt non-interactively and print the result instead of creating a background session, drop `--bg` and run `claude -p "<task>"`
[](#invalid-agents-configuration)
Invalid `--agents` configuration
The value you passed to `--agents` is invalid, so `claude` exits with code 1 instead of starting the session. When you pass `--safe-mode` or set [`CLAUDE_CODE_SAFE_MODE`](env-vars.md#variables), Claude Code ignores `--agents` entirely. With `--resume` or `--continue`, an inline JSON value isn’t checked and the session starts; a value read from a file is checked on every launch. Before v2.1.242, Claude Code started the session anyway.
```python
Error: Invalid --agents configuration:
<what failed>
```
What follows the first line depends on how the value failed. Claude Code runs these checks in order and stops at the first one that fails. If your value has two kinds of problem, you see the second only after you fix the first:
1. When the value begins with `{` but doesn’t parse as JSON, or the contents of an `--agents` file don’t parse, Claude Code prints one `invalid JSON:` line carrying the JSON parser’s own message
2. When it parses but an agent definition doesn’t match the schema for [CLI-defined subagents](../09-Agents-Patterns/sub-agents.md#choose-the-subagent-scope), Claude Code prints one line per problem
3. When an agent name starts with `-`, Claude Code prints `<name>: agent names must not start with '-'`
When there are more than 20 problem lines, Claude Code prints the first 20 and replaces the rest with `…and N more`. With `--print`, `--agents` also accepts [the path to a JSON file](../09-Agents-Patterns/sub-agents.md#choose-the-subagent-scope) in place of the inline object. Before v2.1.281, `--agents` accepted only inline JSON and treated a file path as invalid JSON. The file form has refusals of its own, printed in place of this message, including these:
- **`Error: --agents takes a JSON object, or a file path only with --print (-p)`**: Claude Code read the value as a file path in an interactive session. Pass the definitions as inline JSON, or add `-p` to read them from a file.
- **`Error: --agents file not found: <path>`**: no file exists at that path. A value that doesn’t begin with `{` and isn’t valid JSON is read as a path, so inline JSON that your shell mangled can fail this way too. Check the path or the quoting and run the command again.
**What to do:**
- Fix each problem the message lists, then run the command again. See [the fields a CLI-defined subagent takes](../09-Agents-Patterns/sub-agents.md#choose-the-subagent-scope).
[](#cloud-sessions-cannot-be-created-from-a-restricted-session)
Cloud sessions cannot be created from a `--restricted` session
When you start a session with [`--restricted`](cli-reference.md#cli-flags), Claude Code refuses to create [cloud sessions](claude-code-on-the-web.md#from-terminal-to-cloud) from it, because the new session would run outside the restricted process and wouldn’t enforce restricted mode. Claude Code refuses on the client, before contacting the server, so no cloud session is created:
```python
Cloud sessions cannot be created from a --restricted session: they would not enforce it.
```
**What to do:**
- Run the task locally in the restricted session
- If you control how the session was launched, start a new `claude` session without `--restricted` and create the cloud session from there
Before v2.1.248, Claude Code had no `--restricted` flag; earlier versions reject the flag itself with an unknown-option error.
[](#cloud-sessions-are-disabled-by-your-organizations-policy)
Cloud sessions are disabled by your organization’s policy
Your organization’s `allow_remote_sessions` policy is off, so [cloud sessions](claude-code-on-the-web.md) and the commands that use them aren’t available:
```python
Cloud sessions are disabled by your organization's policy. Contact your organization admin to enable them.
```
The message appears when you [create a cloud session from the terminal](claude-code-on-the-web.md#from-terminal-to-cloud) and when you submit a command that needs cloud sessions, such as `/teleport`, `/remote-env`, or `/web-setup`. Before v2.1.268, submitting one of those commands returned [`Unknown command`](#unknown-command) instead. This is a server-side organization policy, so it can’t be overridden from local settings, environment variables, or CLI flags. If Claude Code hasn’t loaded your organization’s policy yet or can’t fetch it, those commands answer `Couldn't verify your organization's policy for cloud sessions. Check your network connection, then restart Claude Code and try again.` instead. **What to do:**
- Ask an [Owner](../13-Enterprise-Admin/server-managed-settings.md#access-control) in your organization to enable cloud sessions in the Claude Code admin settings at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code)
- If the message says it couldn’t verify the policy, check your network connection, then restart Claude Code and try again
[](#the-json-schema-value-is-not-a-valid-json-schema)
The `--json-schema` value is not a valid JSON Schema
The schema you passed to [`--json-schema`](cli-reference.md#cli-flags) in [non-interactive mode](headless.md#get-structured-output) failed JSON Schema compilation, so `claude` exits with code 1 instead of running the prompt. Before v2.1.205, an invalid schema produced unstructured output with no error, and any schema that used the `format` keyword was treated as invalid.
```python
Error: --json-schema is not a valid JSON Schema: data/type must be equal to one of the allowed values
```
The text after the second colon is the validator’s diagnostic and names the keyword or location that failed. Schemas that use the `format` keyword, such as `"format": "email"`, are valid: Claude Code accepts `format` as an annotation and doesn’t enforce it. Claude Code runs two checks before schema compilation: it rejects a value that isn’t parseable JSON with `Error: --json-schema is not valid JSON`, and valid JSON that isn’t an object with `Error: --json-schema must be a JSON object`. **What to do:**
- Fix the part of the schema the diagnostic names, then rerun the command
- See [Get structured output](headless.md#get-structured-output) for a working schema and command
[](#settings-file-exceeds-the-2mib-limit)
Settings file exceeds the 2MiB limit
The file you passed to [`--settings`](cli-reference.md#cli-flags) is larger than 2 MiB, so `claude` exits with code 1 at startup instead of loading it. Before v2.1.214, Claude Code read the file with no size check, and a multi-gigabyte file or a device file such as `/dev/zero` grew memory without bound.
```python
Error: Settings file exceeds the 2MiB limit: /path/to/settings.json
```
Claude Code rejects a `--settings` path that isn’t a regular file the same way: a device, FIFO, or socket reports `Error: Cannot use settings file (Not a regular file (device, FIFO, or socket))` followed by the path, and a directory reports an `EISDIR` reason. **What to do:**
- Point `--settings` at a regular JSON settings file under 2 MiB. See [Settings](settings.md) for the format.
[](#the-current-directory-no-longer-exists)
The current directory no longer exists
You started `claude` from a directory that was deleted or moved after your shell entered it, for example a worktree or temp directory another shell removed. Claude Code can’t read its working directory, so it exits with code 1 before starting the session, in interactive and [non-interactive](headless.md) mode alike. Before v2.1.239, Claude Code crashed with minified bundle source and a raw `ENOENT ... uv_cwd` stack on stderr instead of this message.
```python
The current directory no longer exists (it was deleted or moved). Start Claude Code from an existing directory.
error: The current working directory was deleted, so that command didn't work. Please cd into a different directory and try again.
```
The cause and the fix are the same for both forms. When Claude Code can’t read the working directory for a different reason, such as a permissions change, the message names the error code instead: `Can't read the current directory (EACCES). Start Claude Code from a different directory.` On macOS, `EPERM` for a directory in `~/Desktop`, `~/Documents`, `~/Downloads`, or iCloud Drive usually means macOS is blocking your terminal app from that folder. Other commands that read that folder fail the same way: `ls` there reports `Operation not permitted`, even with `sudo`. **What to do:**
- Change to a directory that exists, such as your home or project directory, then run `claude` again
- If the directory was recreated at the same path, your shell still holds the deleted one. Run `cd "$PWD"` or leave and re-enter the directory, then run `claude` again
- For `EPERM` on macOS, quit your terminal app with Cmd+Q, open it again, return to that folder, and run `claude`. If `ls` in that folder still fails, open **System Settings \> Privacy & Security \> Files and Folders**, turn on the folder for your terminal app, then reopen the terminal
[](#temp-directory-refused-or-cannot-be-created)
Temp directory refused or cannot be created
On macOS and Linux, Claude Code creates a private temp directory at startup, `claude-<uid>` under the system temp directory or the [`CLAUDE_CODE_TMPDIR`](env-vars.md) override. When the directory can’t be created, or an entry already at that path fails the safety checks, Claude Code prints the failure to stderr and exits with code 1 rather than start the session:
```python
ENOSPC: no space left on device, mkdir '/tmp/claude-501'
Temp directory /tmp/claude-501 is not a directory (may be an attacker-planted symlink). Refusing to use it. Set CLAUDE_CODE_TMPDIR to a directory you control, or ask an administrator to remove it.
Temp directory /tmp/claude-501 is owned by uid 502, expected 501. Refusing to use it — another user may have pre-created it. Set CLAUDE_CODE_TMPDIR to a directory you control, or ask an administrator to remove it.
Temp directory /tmp/claude-501 is not readable (its mode may have been altered, or a path component denies search). Refusing to use it — restore its permissions (chmod 0700) or remove it. Set CLAUDE_CODE_TMPDIR to a directory you control, or ask an administrator to remove it.
```
**What to do:**
- For `ENOSPC`, free disk space on the volume that holds the temp directory
- For the `Refusing to use it` forms, remove the named entry itself, not what a link points to, and start Claude Code again; for the `owned by uid` form, only an administrator or that user can remove it
- For `is not readable`, run `chmod 0700` on the named directory, or remove it and start again
- In any of these cases, set [`CLAUDE_CODE_TMPDIR`](env-vars.md) to a directory you control and start Claude Code again, leaving the refused path alone
[](#directory-couldnt-be-resolved-to-a-real-location)
Directory couldn’t be resolved to a real location
You ran `/add-dir` for a subdirectory of your working directory, and Claude Code couldn’t resolve the directory to its real location. You already have file access to a subdirectory of the working directory, so `/add-dir` only loads its skills, commands, and agents. Before loading them, Claude Code checks that the directory’s real location, with any symlinks resolved, is inside the working directory. When Claude Code can’t resolve that location, it loads nothing and shows this message:
```python
packages/app couldn't be resolved to a real location, so its skills, commands, and agents weren't loaded. Check that it is a directory inside the working directory and try again.
```
**What to do:**
- Check that the path names a real directory inside the working directory, then run `/add-dir` again
- The message doesn’t change your file access; it only reports that the directory’s `.claude/` content wasn’t loaded
Before v2.1.261, this message also appeared for every `/add-dir <subdirectory>` when the working directory was on a `/net/<host>` automount, where Claude Code declines to resolve paths by design; the directory was fine and retrying couldn’t help.
[](#workspace-not-trusted-when-starting-remote-control)
Workspace not trusted when starting Remote Control
You started [Remote Control](remote-control.md) server mode with `claude remote-control` or its `claude rc` alias in a directory you haven’t trusted, and the command couldn’t ask you whether to trust it. For example, the command’s standard input or standard output isn’t a terminal because one of them is redirected or piped. The command exits with code 1:
```python
Error: Workspace not trusted. Please run `claude` in /Users/you/project first to review and accept the workspace trust dialog.
```
Two variants that also begin with `Error: Workspace not trusted.` appear in a terminal too small to show what trusting the directory turns on, or one that didn’t report its size. Enlarge the window or switch to a normal terminal window, then run `claude rc` again. In your home directory the message is different, because the workspace trust dialog never saves trust for the home directory, so accepting it there can’t satisfy this check. Before v2.1.214, the home directory showed the message above, whose advice can’t succeed there.
```python
Error: Workspace not trusted. /Users/you is your home directory, and for security home-directory trust is never saved, so running `claude` here first won't help. Run `claude rc` from a project directory instead (run `claude` there once to accept the trust dialog).
```
If you answer `n` or press Enter at the [`Trust <directory>?` question](remote-control.md#requirements), the command prints a `Remote Control did not start` message that names the directory and exits with code 1. Run `claude rc` again to answer `y`. **What to do:**
- Trust the directory from a terminal first: run `claude rc` there and answer `y`, or run `claude` there and accept the [workspace trust dialog](permissions.md#project-allow-rules-and-workspace-trust), then run your original command again
- In your home directory, change to a project directory and start Remote Control there
Before v2.1.284, the command never asked, even in a terminal.
[](#not-carried-over-to-the-sessions-remote-control-starts)
Not carried over to the sessions Remote Control starts
You started [Remote Control](remote-control.md) with a global `claude` flag before the `remote-control` verb, one that would restrict or configure the sessions Remote Control starts, such as `--settings`, `--setting-sources`, `--permission-mode`, `--disallowed-tools`, or `--mcp-config`. A flag placed before the verb never reaches those sessions. Claude Code refuses to start instead, naming the flag:
```python
Error: `--settings` before `remote-control` is not carried over to the sessions Remote Control starts, so Remote Control refuses to start rather than drop it — remove it, and give Remote Control's own options after the verb (see `claude remote-control --help`).
```
Claude Code doesn’t refuse global flags that are harmless to drop, such as `--verbose`, `--model`, or a wrapper-injected `--session-id` or `--plugin-dir`: it ignores them and Remote Control starts. Claude Code also refuses to start for a global flag it doesn’t yet recognize as harmless, so a flag added in a newer release can appear in this message until a later release marks it harmless. **What to do:**
- Remove the flag from before the verb and pass [Remote Control’s own options](remote-control.md#start-a-remote-control-session) after it; `claude remote-control --help` lists them
- When the refused flag is `--permission-mode`, run `claude remote-control --permission-mode <mode>` to set the permission mode for the sessions Remote Control starts
Before v2.1.248, `claude remote-control` didn’t accept its own flags when a global flag came first, and the command failed with an `unknown option` error.
[](#claude-import-is-not-yet-available-in-this-build)
claude import is not yet available in this build
You ran [`claude import`](cli-reference.md#cli-commands), and Claude Code found the import flow turned off, so the command exits with code 1 instead of starting the import. Before v2.1.222, a build with the import flow off treated `import` as a prompt and started an interactive session instead of printing this message.
```python
`claude import` is not yet available in this build. Run `claude` and use /mcp or edit ~/.claude/settings.json directly.
```
Claude Code turns `claude import` on through a feature flag it fetches from Anthropic and caches on disk. This message means the cached value is off. The cause is usually one of the following:
- You haven’t started a session since installing, so Claude Code hasn’t fetched the flag yet. The first `claude import` can print this even when the feature is available to you.
- You use Claude Code through Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or Claude Platform on AWS, or through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md#availability-and-limitations). Claude Code doesn’t fetch feature flags in these sessions, so `claude import` stays unavailable.
- You set `DISABLE_TELEMETRY`, `DO_NOT_TRACK`, `DISABLE_GROWTHBOOK`, or [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](env-vars.md), which turn off feature-flag fetching, so `claude import` stays unavailable.
**What to do:**
- On a fresh installation, start `claude`, wait for the session to load, exit, and run `claude import` again
- Where feature-flag fetching stays off, set the configuration up yourself: add MCP servers with [`claude mcp add`](../06-MCP-Tools/General/mcp.md#installing-mcp-servers), and create the [`CLAUDE.md` files](memory.md#how-claude-md-files-load), [skills and commands](../08-Plugins-Skills/skills.md#where-skills-live), and [subagents](../09-Agents-Patterns/sub-agents.md#choose-the-subagent-scope) you want to carry over. The message also names `~/.claude/settings.json`. Of the configuration `claude import` carries, that file holds only the [permission mode](settings-reference.md#permission-settings); Claude Code doesn’t read MCP servers from it.
[](#could-not-read-claude-code-config)
Could not read Claude Code config
You ran [`claude import`](cli-reference.md#cli-commands) while Claude Code couldn’t parse `~/.claude.json`, the file where it stores your login and per-project state. The subcommand reads that file to check availability but doesn’t show the recovery dialog the interactive session shows, so it exits with code 1. Before v2.1.222, `claude import` with an unreadable config file started an interactive session, whose recovery dialog handled the file.
```python
Could not read Claude Code config — run `claude` with no arguments to recover it.
```
**What to do:**
- Run `claude` with no arguments. Claude Code detects the invalid file and offers to reset it. Then run `claude import` again.
- To keep manual edits you’ve made, fix the JSON syntax in `~/.claude.json` in an editor instead, then rerun `claude import`
[](#could-not-import-a-server-from-claude-desktop)
Could not import a server from Claude Desktop
Claude Code couldn’t add one of the servers you selected in `claude mcp add-from-claude-desktop`. The command still imports the other selected servers and prints one line per server it couldn’t add. Before v2.1.205, the first server that failed stopped the import.
```python
Could not import my server: Invalid name my server. Names can only contain letters, numbers, hyphens, and underscores.
```
The text after the server name is the reason. The most common one is the name check: Claude Desktop allows characters in server names, such as spaces and periods, that `claude mcp` restricts to letters, numbers, hyphens, and underscores. Other reasons include a server configuration that fails validation and a server blocked by your organization’s [MCP policy](../06-MCP-Tools/General/managed-mcp.md). **What to do:**
- Rename the server in `claude_desktop_config.json` to use only letters, numbers, hyphens, and underscores, then run `claude mcp add-from-claude-desktop` again
- Add that server directly with `claude mcp add` or `claude mcp add-json` under a valid name. See [Import MCP servers from Claude Desktop](../06-MCP-Tools/General/mcp.md#import-mcp-servers-from-claude-desktop).
[](#cannot-add-mcp-server-to-the-managed-scope)
Cannot add MCP server to the managed scope
You ran `claude mcp add` or `claude mcp add-json` with `--scope managed`. That scope holds the servers your organization provides through the [`managedMcpServers`](settings-reference.md#managedmcpservers) managed setting. Claude Code reads them from managed settings only, so the command can’t write a server to that scope.
```python
Cannot add MCP server to scope: managed
```
**What to do:**
- Add the server to a scope you can write: `local`, `user`, or `project`. Without `--scope`, the command uses `local`. See [MCP installation scopes](../06-MCP-Tools/General/mcp.md#mcp-installation-scopes)
- To provide the server to every user in your organization, add it to [`managedMcpServers`](settings-reference.md#managedmcpservers) in the managed settings you deploy
[](#cant-read-mcp-json)
Can’t read .mcp.json
A command that reads the project’s [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-scope), such as `claude mcp add` or `claude mcp add-json` with `--scope project`, or `claude mcp remove`, found that the file in your current directory isn’t a regular file or is larger than 2 MiB, so it exits with this error instead of reading the file.
```python
Can't read .mcp.json: it isn't a regular file or is larger than 2097152 bytes. Fix or remove it, then run the command again.
```
Before v2.1.257, a FIFO at `.mcp.json` left the command waiting forever with no output, and a symlink to a device file such as `/dev/zero` grew memory until the process was killed. **What to do:**
- Check what sits at `.mcp.json` in your current directory. Replace it with an ordinary JSON file in the [project-scope format](../06-MCP-Tools/General/mcp.md#project-scope), or delete it, then run the command again.
[](#anthropic-hosted-and-doesnt-support-local-oauth)
Server is Anthropic-hosted and doesn’t support local OAuth
You started a sign-in for an MCP server whose URL points at an Anthropic-hosted connector host that authenticates through a third-party identity provider. These hosts include `microsoft365.mcp.claude.com`, `gmail.mcp.claude.com`, and `gcal.mcp.claude.com`. Claude Code refuses to start its local OAuth flow for these hosts from both the `/mcp` panel and `claude mcp login`, because [their sign-in works only through claude.ai](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai).
```python
"gmail" is Anthropic-hosted and doesn't support local OAuth. Connect it via Settings → Connectors on claude.ai (requires `claude login`), then it'll be available here automatically.
```
Claude Code matches these hosts by URL, so the message appears when a server you added with `claude mcp add` or in `.mcp.json` points at one of them. **What to do:**
- Remove your entry with `claude mcp remove <name>`, so it can’t hide the claude.ai connector at the same URL
- After removing it, connect the service at [claude.ai/customize/connectors](https://claude.ai/customize/connectors), while signed in to the account you use in Claude Code. Once connected, [the connector appears in Claude Code automatically](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) if your active authentication method is a claude.ai subscription login
[](#server-rejected-the-authorization-header-minted-by-the-configured-headershelper)
Server rejected the Authorization header minted by the configured headersHelper
An MCP server whose [`headersHelper`](../06-MCP-Tools/General/mcp.md#use-dynamic-headers-for-custom-authentication) supplies the `Authorization` header answered the connection with HTTP 401 or 403, so Claude Code reports the connection as failed. Because the helper supplies the `Authorization` header, Claude Code [doesn’t fall back to OAuth](../06-MCP-Tools/General/mcp.md#authenticate-with-remote-mcp-servers) for the server:
```python
Server rejected the Authorization header minted by the configured headersHelper (HTTP 401). Check that the helper command returns a valid credential for this MCP endpoint — OAuth fallback is disabled when the helper supplies Authorization.
```
Claude Code re-runs the helper on each connection attempt, so a retry after a transient rejection, such as a token-rotation race, can succeed with a fresh credential. **What to do:**
- Run the `headersHelper` command yourself the way Claude Code runs it: from the [directory Claude Code runs it in](../06-MCP-Tools/General/mcp.md#where-the-helper-runs), with the [environment variables Claude Code sets for it](../06-MCP-Tools/General/mcp.md#use-dynamic-headers-for-custom-authentication), and without the [credential variables Claude Code removes](../06-MCP-Tools/General/mcp.md#which-variables-a-helper-can-read) for a server from a project `.mcp.json`, a plugin, or a project agent file. Check that it prints an `Authorization` value the server’s endpoint accepts
- After fixing the helper or its credential source, select the server in `/mcp` and choose **Reconnect**
Before v2.1.248, Claude Code ran OAuth discovery for a server whose helper supplied the `Authorization` header. That discovery could fail with `Incompatible auth server: does not support dynamic client registration` instead of reporting the rejected credential.
[](#mcp-permission-prompt-tool-not-found)
MCP permission prompt tool not found
The tool you passed to [`--permission-prompt-tool`](cli-reference.md#cli-flags) wasn’t among the connected MCP tools when the run first needed a permission decision, either because its server never connected or because no connected server exposes a tool by that name. Claude Code still sends your prompt: the [non-interactive](headless.md) run exits with this error, and exit code 1, on the first tool call, so it produces no answer even though the request was made. Before the first prompt, Claude Code waits up to the per-server connection timeout of 30 seconds set by [`MCP_TIMEOUT`](env-vars.md) for that server to connect. Before v2.1.206, startup didn’t wait for the server to finish connecting, so a slow-starting but healthy server produced this error too.
```python
Error: MCP tool mcp__permissions__approve (passed via --permission-prompt-tool) not found. Available MCP tools: none
```
The list after `Available MCP tools:` names the MCP tools that were connected. **What to do:**
- Check that the server starts and stays connected: run `claude mcp list` in the same directory and confirm the server is listed as connected
- Confirm the tool name matches the `mcp__<server>__<tool>` name the server exposes
- If the server needs longer than 30 seconds to start, raise [`MCP_TIMEOUT`](env-vars.md)
[](#oauth-callback-port-is-already-in-use)
OAuth callback port is already in use
When you sign in to a remote MCP server with OAuth, Claude Code starts a local listener to receive the sign-in callback. If the port that listener needs is held by another process, the sign-in fails with this message. This mostly happens with a [fixed callback port](../06-MCP-Tools/General/mcp.md#use-a-fixed-oauth-callback-port) set through the [`MCP_OAUTH_CALLBACK_PORT`](env-vars.md) variable or `--callback-port`, since without one Claude Code picks an available port.
```python
OAuth callback port <port> is already in use — another process may be holding it. Run `lsof -ti:<port> -sTCP:LISTEN` to find it.
```
On Windows, the suggested command is `netstat -ano | findstr :<port>` instead. **What to do:**
- Run the command from the message to find the process holding the port, and stop it or wait for it to finish
- If another program needs that port permanently, register a different redirect URI with the server and set its port with `MCP_OAUTH_CALLBACK_PORT` or `--callback-port`, whichever you use
- Then start the sign-in again, for example by selecting the server in `/mcp`
[](#no-available-ports-for-oauth-redirect)
No available ports for OAuth redirect
When you sign in to a remote MCP server with [OAuth](../06-MCP-Tools/General/mcp.md#authenticate-with-remote-mcp-servers), Claude Code starts a local listener to receive the sign-in callback. The sign-in fails with this message when Claude Code can’t bind a local port for it. Something on the machine is preventing it from listening on `127.0.0.1`, for example security software or a sandbox policy that denies local listeners.
```python
No available ports for OAuth redirect
```
Before v2.1.268, Claude Code didn’t fall back to an operating-system-assigned port, so the message also appeared when only its self-picked ports couldn’t be bound. That can happen on Windows hosts where Hyper-V reserves port ranges that cover the ports Claude Code picks from. **What to do:**
- Check whether security software or a sandbox policy blocks processes from listening on `127.0.0.1`, and allow Claude Code to bind a local port
- Then start the sign-in again, for example by selecting the server in `/mcp`
[](#security-review-fails-without-origin-head)
/security-review fails without origin/HEAD
[`/security-review`](commands.md#all-commands) builds its review context by diffing your branch against `origin/HEAD`, the local ref that records which branch is the default on your `origin` remote. When that ref doesn’t exist, the git commands that gather the diff fail and the review stops before it starts.
```python
Error: Shell command failed for pattern "!`git diff --name-only origin/HEAD...`": [stderr]
fatal: ambiguous argument 'origin/HEAD...': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
```
The message may quote `git log` or a different `git diff` instead. Git creates `origin/HEAD` only when the remote advertises a default branch and your fetch refspec covers it, which a full `git clone` of a remote with commits does. The ref is missing in these setups:
- A single-branch or CI checkout, which fetches too narrow a refspec
- A remote whose server-side HEAD points at a branch nobody pushed
- A repository with no `origin` remote, or one you never fetched
Claude Code shows the same error for any skill that [injects dynamic context](../08-Plugins-Skills/skills.md#when-an-injected-command-fails), and a failed injected command aborts that skill’s invocation. Two sibling strings fire before the command runs at all:
- `Shell command permission check failed for pattern "..."`: the command’s permission check didn’t allow it. [Permission checks on injected commands](../08-Plugins-Skills/skills.md#permission-checks-on-injected-commands) covers which results abort in each permission mode and how to pre-approve a command with `allowed-tools`
- `` Skill <name> requires bash (`shell: bash` in frontmatter) but Git Bash was not found ``: the skill’s frontmatter demands bash on a machine without it. Install Git for Windows or change the frontmatter to `shell: powershell`. See [How injected commands run](../08-Plugins-Skills/skills.md#how-injected-commands-run)
**What to do:**
- Create the ref by naming your remote’s default branch: `git remote set-head origin <default-branch>`. This works whenever the local tracking ref `origin/<default-branch>` exists. If it doesn’t, as in single-branch clones, fetch the branch first: run `git remote set-branches --add origin <branch>`, then `git fetch origin`, then rerun the set-head command. Rerun `/security-review`.
- If you’d rather not name the branch, run `git fetch origin` and then `git remote set-head origin --auto`, which asks the remote which branch is its default. It fails with `error: Cannot determine remote HEAD` when the remote advertises no default branch, because it is empty or its HEAD points at a branch nobody pushed; name the branch explicitly instead. It fails with `error: Not a valid ref` when your clone doesn’t fetch that branch; widen the refspec as above first.
- If the repository has no remote, add one with `git remote add origin <url>` and fetch before creating the ref. If the remote is empty, push your branch first with `git push -u origin HEAD` and name that branch in the set-head command; `origin/HEAD` then points at the branch you just pushed, so `/security-review` sees an empty diff until the branch diverges from it.
[](#input-must-be-provided-when-using-print)
Input must be provided when using `--print`
Bare `claude` needs stdout to be a terminal to start the interactive UI. When stdout is redirected, or the console isn’t a real terminal, such as PowerShell ISE and some IDE output panes, `claude` runs [non-interactively](headless.md) instead. That is the same mode as `claude -p`, which requires a prompt, so the message names `--print` even when you didn’t pass the flag. Passing `-p`/`--print` with no prompt and nothing piped on stdin produces the same error anywhere.
```python
Error: Input must be provided either through stdin or as a prompt argument when using --print
```
**What to do:**
- For interactive use, run `claude` in a real terminal: Windows Terminal or the PowerShell console rather than ISE, and your IDE’s integrated terminal rather than an output pane
- For one-shot use, pass the prompt: `claude -p "your question"`, or pipe it with `echo "your question" | claude -p`
[](#input-contained-only-whitespace)
Input contained only whitespace
In [non-interactive mode](headless.md), Claude Code refuses a prompt made up entirely of spaces, tabs, or newlines instead of sending it, because the API rejects messages with no visible text. Which message you see depends on where the blank prompt came from:
- **Prompt argument or piped stdin for `claude -p`**: `claude` exits with `Error: Input contained only whitespace. Provide a prompt with text through stdin or as a prompt argument when using --print`
- **Message submitted to a running `--input-format stream-json` or [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) session**: Claude Code ends the turn without calling the model and the session stays usable. The refusal arrives as an informational message and as the turn’s result text: `Blank prompt — the message was only whitespace, so nothing was sent to the model.`
Before v2.1.229, Claude Code sent the whitespace-only message to the API, which rejected the request with a 400 error. **What to do:**
- Include visible text in the prompt. If a script builds the prompt from a variable or file, check that the source isn’t empty before calling Claude Code.
[](#stream-json-input-carried-over-256m-characters-with-no-newline)
stream-json input carried over 256M characters with no newline
Your program sent more than 268,435,456 characters on stdin without a newline to a `claude -p --input-format stream-json` run, so Claude Code prints this error to stderr and exits with code 1 instead of buffering more input. The message states that budget as `256M`. Before v2.1.257, Claude Code buffered such input without limit, growing memory until the process crashed or was killed.
```python
Error: stream-json input carried over 256M characters with no newline. Each stream-json message must be a single newline-terminated JSON line: either the producer is not newline-terminating its messages, or one message exceeded this budget.
```
Input this long without a newline usually means the producer isn’t a stream-json producer at all, such as a binary file or plain log output piped in by accident. A single message over the budget fails the same check. **What to do:**
- Check what’s piped to stdin. With [`--input-format stream-json`](cli-reference.md#cli-flags), every message must be one newline-terminated JSON line
- To send plain text instead, drop `--input-format stream-json`; `claude -p` reads a plain-text prompt from stdin by default
[](#unknown-command)
Unknown command
In an interactive terminal session, you submitted a `/` name that doesn’t match any command in this session, so Claude Code reports the name instead of running anything:
```python
Unknown command: /hepl. Did you mean /help?
```
Claude Code suggests the closest command name or alias that the menu lists in this session. When nothing is close, the message ends after the name. The cause is usually one of the following:
- A typo, such as `/hepl` for `/help`. [How the command menu matches what you type](commands.md#how-the-command-menu-matches-what-you-type) covers picking a close match before you submit
- A command that exists but isn’t available in this session because a requirement isn’t met, such as your platform, plan, or authentication method. The troubleshooting entries for [`/web-setup`](web-quickstart.md#web-setup-shows-no-commands-match-or-unknown-command) and [`/schedule`](web-scheduled-tasks.md#schedule-returns-unknown-command) walk through two common cases. Some commands answer with their own message when your organization’s policy disables them, such as [`Cloud sessions are disabled by your organization's policy`](#cloud-sessions-are-disabled-by-your-organizations-policy)
- A command from a [plugin](../08-Plugins-Skills/plugins.md) or [MCP server](../06-MCP-Tools/General/mcp.md#use-mcp-prompts-as-commands) that isn’t installed or connected in this session
Claude Code answers an unmatched `/` name this way only in an interactive terminal session. In every other session, it sends the prompt to Claude as a normal message instead, with a note that the command didn’t run and a list of commands Claude can run in the session. Those sessions include:
- `-p` runs
- [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) applications
- The Code tab of the [Desktop app](../16-Mobile-Desktop/desktop.md)
- The chat panel of the [VS Code extension](../03-IDE-Integrations/vs-code.md)
- [Cloud sessions](claude-code-on-the-web.md) and [routines](web-scheduled-tasks.md)
For a built-in command that can’t run in one of those sessions, Claude Code still answers that the command isn’t available instead of sending it to Claude. Before v2.1.274, only cloud sessions and routines sent an unmatched name to Claude. Before v2.1.273, they answered `Unknown command` too. Claude Code doesn’t treat every prompt that starts with `/` as a command. It sends the prompt to Claude as a normal message when the first word after the `/` starts with punctuation, such as the `/--` that opens a Lean doc comment, or is a path such as `/var/log/syslog`. Before v2.1.236, if you pressed `Enter` while the command menu listed a near match for the name you typed, Claude Code ran that match, so a typo such as `/hepl` ran `/help` instead of producing this message. **What to do:**
- Run the suggested name, or type `/` followed by part of the name to see what’s available in this session
- If Claude Code reports a documented command as unknown, check its row in the [commands reference](commands.md) for the requirement it names
[](#diff-is-too-large-for-ultrareview)
Diff is too large for ultrareview
The diff between your branch and the base branch, including uncommitted and staged changes, exceeds the size limits for an [ultrareview](ultrareview.md), so `/code-review ultra` and the `claude ultrareview` subcommand refuse the review before the cloud session starts. A refused review doesn’t use a free run and doesn’t bill usage credits. The message names the limits in effect, the size of your diff, and the files that contribute the most changed lines. Before v2.1.216, the message showed only the raw diff statistics.
```python
Diff is too large for ultrareview: 812 files, 96,410 lines changed (limits: 500 files, 8,000 lines). Largest files: package-lock.json (41,904 lines), dist/bundle.js (18,210 lines), src/generated/api.ts (9,876 lines). Pass a closer base branch (`/code-review ultra <branch>`) to narrow the scope, or split the change.
```
Reviewing a pull request applies the same limits; that form of the message begins `PR #<N> is too large for ultrareview` and names the PR’s file and line counts. **What to do:**
- Pass a base branch closer to your work, such as `/code-review ultra develop`, so the review covers only the diff against that branch
- Split the change into smaller branches and review each one. The files the message names contribute the most changed lines, so start by moving those to their own branch.
[](#could-not-find-merge-base-with-the-base-branch)
Could not find merge-base with the base branch
`/code-review ultra` and the `claude ultrareview` subcommand review the diff between your branch and a base branch, which needs a commit the two share. When `git merge-base` finds none, Claude Code refuses the review before the cloud session starts. On a clone Claude Code can verify is complete, with at least one branch, it falls back to [reviewing every tracked file](ultrareview.md#diff-limits-and-fallbacks) instead of refusing. You see this refusal when the base branch can’t be found at all, when Claude Code can’t verify that your clone is complete, or in the rare repository where the whole-tree diff isn’t possible, such as the SHA-256 object format.
```python
Could not find merge-base with main. Pass the base branch explicitly (e.g. `/code-review ultra develop`) or make sure you're in a git repo with a main branch.
```
The hint after the first sentence depends on what Claude Code observed:
- **You didn’t pass a base branch**: Claude Code compared against the repository’s default branch and suggests passing your base explicitly, as in the example above
- **You passed a base branch that was already in your clone**: the hint reads `` Make sure <branch> exists locally or on origin (try `git fetch origin <branch>`) ``
- **You passed a base branch that wasn’t in your clone**: Claude Code fetched it from origin before comparing. The hint reads `` <branch> was fetched from origin but shares no history with HEAD. If another branch is your real base, pass it explicitly (`/code-review ultra <branch>`) ``; when Claude Code can’t tell whether your clone is shallow, it suggests `git fetch --unshallow origin` instead. Before v2.1.221, the hint suggested `git fetch --unshallow origin` for every fetched base branch, and on a complete clone that command fails with `fatal: --unshallow on a complete repository does not make sense`.
**What to do:**
- If another branch is your real base, pass it explicitly: `/code-review ultra <branch>`
- If your clone might not have full history, run `git fetch --unshallow origin` and rerun the review
[](#your-checkout-has-no-branches)
Your checkout has no branches
A checkout can have commits but no branches: if you run `git init` followed by `git fetch <url>` and `git checkout FETCH_HEAD`, you get a detached HEAD with no refs. Claude Code packages your repository as a git bundle to upload it for an [ultrareview](ultrareview.md), and it can’t bundle a repository that has no branches or other refs, so `/code-review ultra` and the `claude ultrareview` subcommand refuse the review before the cloud session starts.
```python
Your checkout has no branches (detached HEAD only), which cloud review can't bundle. Create one first — `git checkout -b <name>` — then rerun /code-review ultra.
```
Before v2.1.221, Claude Code attempted to review every tracked file in this checkout, and the upload failed. **What to do:**
- Create a branch at your current commit with `git checkout -b <name>`, then rerun the review
[](#no-github-account-is-connected-to-your-claude-account)
No GitHub account is connected to your Claude account
You ran `/code-review ultra <PR#>` or `claude ultrareview <PR#>`, and before creating the cloud session Claude Code asks the server whether [the GitHub account connected to your Claude account](ultrareview.md#review-a-pull-request) can reach the PR’s repository. No account is connected, or the connection expired, so the cloud clone would fail and Claude Code refuses the launch. Claude Code doesn’t spend a free run or bill usage credits for a refused launch.
```python
Ultrareview clones <owner>/<repo> in the cloud with the GitHub account connected to your Claude account, and none is connected (or the connection expired). To fix: run /web-setup to reuse your GitHub CLI login, or connect an account at https://claude.ai/connect-github — then re-run /code-review ultra 1234 (allow a minute after connecting).
```
When [`/web-setup`](web-quickstart.md#connect-from-your-terminal) isn’t available in your session, the message names only the claude.ai link. **What to do:**
- Run `/web-setup` to connect your GitHub CLI login to your Claude account, or connect an account at [claude.ai/connect-github](https://claude.ai/connect-github)
- Rerun the review a minute after connecting
Before v2.1.248, Claude Code didn’t check this before launch.
[](#your-connected-github-account-cant-see-the-repository)
Your connected GitHub account can’t see the repository
You ran `/code-review ultra <PR#>` or `claude ultrareview <PR#>`, and [the GitHub account connected to your Claude account](ultrareview.md#review-a-pull-request) can’t read the PR’s repository, so the cloud clone would fail and Claude Code refuses the launch. Claude Code doesn’t spend a free run or bill usage credits for a refused launch.
```python
Your connected GitHub account can't see <owner>/<repo> — usually the Claude GitHub app isn't installed on <owner> or wasn't granted this repo (web-connected accounts need it for private repos), or a different GitHub account is connected. To fix: run /web-setup to reuse your GitHub CLI login, or install the app at https://github.com/apps/claude/installations/new — then re-run /code-review ultra 1234.
```
When [`/web-setup`](web-quickstart.md#connect-from-your-terminal) isn’t available in your session, the message names only the app install. **What to do:**
- If your local `gh` CLI can read the repository, run `/web-setup` to connect that login to your Claude account
- Rerun the review after the change
Before v2.1.248, Claude Code didn’t check this before launch.
[](#the-github-app-preflight-failed-transiently)
The GitHub App preflight failed transiently
You started a [cloud session](claude-code-on-the-web.md) from a local repository, and two steps failed together. Claude Code couldn’t build or upload the bundle of your repository. Before the upload, it checked whether the cloud service can clone the repository from GitHub, and rather than a definite answer, that check ended in an error that a retry could clear, such as a network error, a timeout, or a temporary server error. The full message starts with what stopped the bundle, for example `Could not upload repo bundle (<error>)`, and ends with the preflight sentence:
```python
Could not upload repo bundle (<error>). The GitHub App preflight failed transiently (network or service hiccup) — retry in a moment to start from GitHub instead
```
**What to do:**
- Rerun the command after a moment. When the GitHub check passes, Claude Code can start the session from a GitHub clone, so the failed upload no longer blocks the launch
- If retries keep failing, the start of the message names what stopped the upload. When that cause is something you can fix, fix it so the session can start from your local repository instead
Before v2.1.251, Claude Code ended the message with `Please set up GitHub on https://claude.ai/code` even when the GitHub check failed only transiently, and setup advice can’t clear a transient failure.
[](#the-repository-upload-cant-follow-a-git-setting)
The repository upload can’t follow a git setting
You started a [cloud session that uploads your local repository](claude-code-on-the-web.md#send-local-repositories-without-github), or an [ultrareview](ultrareview.md) of a branch, and the upload can’t follow one of the git settings that decide which attribute rules apply to your files. If the upload went ahead and missed a rule, a file that git transforms before storing it, such as one a clean filter encrypts, could reach the cloud as it is on disk. Claude Code refuses the upload instead, and nothing is uploaded:
```python
Not uploading this working tree: core.ignoreCase (which decides whether .gitattributes patterns match file names regardless of letter case) is set in <file>, and the upload cannot follow that setting, so a file git would change before storing it (to encrypt it, for example) could be uploaded as it is on disk. Move the core.ignoreCase line into this repository’s .git/config or directly into your ~/.gitconfig, then retry.
```
The message names the setting and where it’s set, and ends with the fix for the case you hit. The same refusal appears for `core.attributesFile` and `attr.tree`, each with its own fix. The message can name a config file that your git configuration pulls in through an `include` or `includeIf` directive, even when that directive’s condition doesn’t apply to this repository. **What to do:**
- Apply the fix in the message’s final sentence
[](#github-isnt-connected-to-your-claude-account)
You started a [cloud session](claude-code-on-the-web.md) from your local repository, for example with `/autofix-pr`. No GitHub account is connected to your Claude account, or the connection expired, so Claude Code refuses the launch:
```python
```
When you create a routine with [`/schedule`](web-scheduled-tasks.md), the same message appears as a setup note that names the repository; the note doesn’t block creating the routine. **What to do:**
- Run `/web-setup` to connect your GitHub CLI login to your Claude account, or connect an account at [claude.ai/connect-github](https://claude.ai/connect-github). See [GitHub authentication options](claude-code-on-the-web.md#github-authentication-options) for how the two differ.
- Rerun the command a minute after connecting
Before v2.1.268, Claude Code reported this as a temporary failure of the Claude GitHub App check and suggested retrying or installing the app; neither connects a GitHub account.
[](#single-sign-on-authorization-needed)
Single sign-on authorization needed
You ran [`/install-github-app`](github-actions.md#quick-setup) and chose a repository whose organization enforces SAML single sign-on. Before setup, Claude Code checks your access to the repository with the GitHub CLI, and GitHub refused that check because your `gh` token isn’t authorized for the organization yet. The wizard shows the warning with the steps to authorize:
```python
Single sign-on authorization needed
<owner>/<repo> belongs to an organization that enforces SAML single sign-on, and your GitHub CLI token isn't authorized for it yet.
```
**What to do:**
- Re-authorize your GitHub CLI login with the `repo` and `workflow` scopes by running `gh auth refresh -h github.com -s repo,workflow`, and authorize the organization when GitHub prompts for single sign-on
- If you authenticate with a personal access token in `GH_TOKEN`, open [github.com/settings/tokens](https://github.com/settings/tokens), select **Configure SSO** on the token, and authorize the organization
- Run `/install-github-app` again
Before v2.1.273, Claude Code showed the `Admin permissions required` warning for this condition instead.
[](#failed-to-resume-the-conversation)
Failed to resume the conversation
Claude Code couldn’t read or process the saved transcript for the session you selected from the [`claude --resume` picker](sessions.md#use-the-session-picker), so it ends the process rather than continue in a partially loaded state. The message includes the command to retry:
```python
Failed to resume the conversation.
Run claude --resume <session-id> to retry, or claude to start a new session.
```
Claude Code exits with code 1 after showing the message. The `/resume` picker inside a running session reports `Failed to resume conversation` in the conversation instead, and your current session keeps running. Before v2.1.216, a failed resume from the `claude --resume` picker stayed on the `Resuming conversation…` spinner indefinitely instead of showing this message. **What to do:**
- Run `claude --resume <session-id>` with the session ID from the message to retry
- If every retry fails the same way, run `claude update` and resume again. Versions before v2.1.275 fail the resume when the saved transcript contains an entry they can’t read.
- If the retry fails again, run `claude` to start a new session
[](#no-conversation-found-with-the-session-id)
No conversation found with the session ID
You passed a session ID to `claude --resume <session-id>` and no saved transcript matched it:
```python
No conversation found with session ID: <session-id>
```
Claude Code exits with code 1 after showing the message. Claude Code [searches the current project first, then every other project on this machine](sessions.md#resume-a-session) for the ID. Before v2.1.223, the lookup stopped at the current project directory and its git worktrees, so resume from the directory the session last worked in. Common causes:
- **Mistyped ID**: for a non-interactive run, the ID is the `session_id` field of the [`--output-format json` output](headless.md#get-structured-output)
- **Deleted transcript**: Claude Code removes transcripts after the [retention period](sessions.md#where-transcripts-are-stored), 30 days by default, following the [retention sweep rules](claude-directory.md#cleaned-up-automatically)
- **Different machine**: Claude Code stores transcripts locally, so resume the session on the machine where it ran
- **Duplicate copies**: if you copied a project directory under `~/.claude/projects` so two transcripts carry the same ID, Claude Code reports this message rather than resume one copy arbitrarily
**What to do:**
- For an interactive session, open the [session picker](sessions.md#use-the-session-picker) with `claude --resume` and press `Ctrl+A` to widen it to every project on this machine, then select the session
- Sessions created with `claude -p` or the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) don’t appear in the picker, so re-check the ID against the `session_id` your original run printed
[](#windows-reported-an-error-ebadf)
Windows reported an error (EBADF) when Claude Code read this session’s transcript file
You resumed a session on Windows, its saved [transcript file](sessions.md#where-transcripts-are-stored) opened normally, and reading it then failed with the system error EBADF. The system error doesn’t say why the read failed, so the message suggests likely causes and what to try:
```python
Windows reported an error (EBADF) when Claude Code read this session's transcript file, although the file had opened normally. This can happen when other software intercepts file reads — security, encryption or endpoint-management tools, for example. If it keeps happening for this conversation, try excluding the folder that holds Claude Code's session transcripts from such software (the .claude folder in your user profile, unless the app or CLAUDE_CONFIG_DIR points Claude Code elsewhere), or adding Claude Code to its allowed applications, then resume again.
```
The message follows the command’s own failure line, such as `Failed to resume session <session-id>`. A `claude --resume` or [`claude -p`](headless.md) command exits with code 1 after showing it. After `/resume` inside a session, your current session keeps running. **What to do:**
- Exclude the folder that holds your session transcripts from software that scans or intercepts file reads, such as security, encryption, or endpoint-management tools. Transcripts live under `%USERPROFILE%\.claude\projects` by default, or under the directory [`CLAUDE_CONFIG_DIR`](env-vars.md) names
- If you can’t add an exclusion, add Claude Code to that software’s allowed applications instead
- Resume the session again
Before v2.1.282, the failure came with no explanation: `claude --resume <session-id>` ended at `Failed to resume session <session-id>`, and a `-p` run printed only the system error text, such as `Failed to resume session: EBADF: bad file descriptor, read`.
[](#cannot-switch-renderers-in-this-session)
Cannot switch renderers in this session
When you switch renderers, Claude Code restarts its process. You ran [`/tui`](fullscreen.md#enable-fullscreen-rendering) in a session Claude Code declines to restart, so it doesn’t switch and saves nothing. Which message you see tells you the cause:
- `Cannot switch renderers while work is running in the background`: you have background work running that a restart would abandon, such as a background shell or a subagent. Wait for the work to finish or stop it with [`/tasks`](commands.md), then run `/tui fullscreen` or `/tui default` again
- `Cannot switch renderers in this session`: the session has restrictions Claude Code can’t pass to the restarted process. Before v2.1.234, Claude Code restarted anyway and the relaunched session ran without them
In the restrictions message, the part in parentheses names the restrictions Claude Code found:
```python
Cannot switch renderers in this session — it has restrictions a restart can't carry over (permission rules set for this session only). Nothing was changed. Running /tui fullscreen in a session started without them switches every later session too.
```
Each reason the message can show in parentheses:
- `launch flags: a custom system prompt, a tool allowlist, or restricted settings`: you started the session with a flag Claude Code doesn’t pass back to the restarted process. These flags include [`--system-prompt`](cli-reference.md#cli-flags), `--system-prompt-file`, `--append-system-prompt-file`, a [`--tools`](cli-reference.md#cli-flags) allowlist, [`--setting-sources`](cli-reference.md#cli-flags), and [`--permission-prompt-tool`](cli-reference.md#cli-flags)
- `permission rules set for this session only`: a [permission update](../07-Hooks/hooks.md#permission-update-entries) from a hook or SDK caller added deny or ask rules with the `session` destination. Session-scoped allow rules don’t trigger the refusal. A restart drops them, and Claude Code prompts again instead
- `ask-before-running rules with no command-line form`: a permission update from a hook or SDK caller added ask rules alongside the rules Claude Code passes back as `--allowed-tools` and `--disallowed-tools`. No flag exists for ask rules
- `permission rules a command line cannot carry intact` and `added directories a command line cannot carry intact`: a permission update added a rule or directory path mid-session. The restarted process’s command line can’t carry its text as the same value
**What to do:**
- In a session started without those restrictions, run `/tui fullscreen`, or `/tui default` to switch back. Claude Code saves the [`tui` setting](settings-reference.md#tui) there
[](#couldnt-open-claude-desktop)
Couldn’t open Claude Desktop
You ran [`/desktop`](../16-Mobile-Desktop/desktop.md#coming-from-the-cli), or its alias `/app`, and the system command Claude Code uses to open Claude Desktop failed. The session stays in the terminal.
```python
Error: Couldn't open Claude Desktop (`open` exited 1: LSOpenURLsWithRole() failed for the URL claude://resume?session=<session-id> with error -10814). Open Claude Desktop and run /desktop again.
```
**What to do:**
- Open Claude Desktop yourself, then run `/desktop` again
- To read that command’s full error output, turn on debug logging with `/debug`, run `/desktop` again, and check the debug log
Before v2.1.275, the message was `Failed to open Claude Desktop. Please try opening it manually.` and didn’t say what failed.
[](#terminal-setup-left-your-zed-keymap-unchanged)
/terminal-setup left your Zed keymap unchanged
You ran [`/terminal-setup`](terminal-config.md#enter-multiline-prompts) in Zed, and Claude Code couldn’t complete the update to your Zed `keymap.json`, so it left the file as it was. Each message names the path to your keymap and ends with the keybinding block to add yourself:
```python
Couldn't update your Zed keymap, so it was left unchanged.
To add the binding yourself, add this block to the keymap array in <path to keymap.json>:
{ "context": "Terminal", "bindings": { "shift-enter": ["terminal::SendText", "\u001b\r"] } }
```
The first line of the message names the cause:
- `Couldn't read your Zed keymap, so it was left unchanged.`: Claude Code couldn’t read the file, for example because of file permissions
- `Your Zed keymap isn't a readable list of keybindings, so it was left unchanged.`: the file read fine but doesn’t parse as an array of keybinding blocks, even with `//` comments and trailing commas allowed
- `Couldn't back up your Zed keymap; not modifying it.`: Claude Code couldn’t copy the file to a `.bak` backup beside it, so it changed nothing
- `Couldn't update your Zed keymap, so it was left unchanged.`: the merged result didn’t verify as a valid keymap carrying the binding, so Claude Code discarded it instead of writing. A keybinding block with a duplicated key can cause this
**What to do:**
- Copy the block from the message into the top-level array in your `keymap.json` at the path the message names
- For `isn't a readable list of keybindings`, fix the syntax error, or make the file’s top-level value an array, then run `/terminal-setup` again
Before v2.1.247, `/terminal-setup` couldn’t parse a Zed keymap that used `//` comments or trailing commas, and it replaced the entire file with only its own binding while reporting the binding as installed. To restore a keymap an earlier version replaced, use the `.bak` backup file described under [Enter multiline prompts](terminal-config.md#enter-multiline-prompts).
[](#skill-usage-reports-are-not-available-on-this-connection)
Skill usage reports are not available on this connection
You ran [`/skill-doctor`](../08-Plugins-Skills/skills.md#find-unused-skills) over [Remote Control](remote-control.md), from your phone or browser. Claude Code doesn’t send the skill usage report over Remote Control and replies with this message instead:
```python
Skill usage reports are not available on this connection.
```
**What to do:**
- Run `/skill-doctor` in the terminal on the machine where the session is running, or run `claude -p "/skill-doctor"` there
[](#custom-output-styles-cant-be-selected-over-remote-control)
Custom output styles can’t be selected over Remote Control
You ran [`/output-style`](output-styles.md#change-your-output-style) from the mobile app or web via [Remote Control](remote-control.md), or the command arrived in a message relayed into the session. Because such a turn may not come from the account owner, Claude Code lists and selects only [built-in styles](output-styles.md#built-in-output-styles) on it, and adds this notice whenever the command lists the styles or doesn’t recognize the name you gave. A [custom style](output-styles.md#create-a-custom-output-style) name gets the same reply as a name that doesn’t exist:
```python
Custom output styles can't be selected over Remote Control or from a relayed message. Select one in the session itself, or pick a built-in style here.
```
**What to do:**
- Pick a built-in style, for example `/output-style concise`
- To use a custom style, set [`outputStyle`](settings-reference.md#outputstyle) in the project’s `.claude/settings.local.json`, or run `/output-style <style>` at the session’s own terminal if it has one
[](#output-styles-are-saved-to-local-settings-which-this-session-doesnt-load)
Output styles are saved to local settings which this session doesn’t load
You tried to switch [output styles](output-styles.md) with `/output-style <style>` or `/config outputStyle=<style>` in a session whose setting sources exclude `local`. Examples are an [Agent SDK](../05-Agent-SDK/agent-sdk-typescript.md) session whose [`settingSources`](../05-Agent-SDK/agent-sdk-typescript.md#options) leaves out `"local"` and a CLI session started with a [`--setting-sources`](cli-reference.md#cli-flags) value that leaves out `local`. Both commands save the style to `.claude/settings.local.json`, a file such a session never reads back, so Claude Code refuses instead of writing a setting that would have no effect:
```python
Output styles are saved to local settings (.claude/settings.local.json), which this session doesn't load, so the style can't be changed here.
```
**What to do:**
- Add `local` to the session’s setting sources and switch again
- Set the [`outputStyle`](settings-reference.md#outputstyle) key in a settings file the session does load, such as `.claude/settings.json` in the project or `~/.claude/settings.json`. In the TypeScript SDK, set `outputStyle` inside the inline `settings` object instead; see [Activate an output style](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#activate-an-output-style)
[](#plugin-errors)
Plugin errors
These errors come from [plugin](../08-Plugins-Skills/plugins.md) and [marketplace](../08-Plugins-Skills/plugins.md) configuration. For plugin problems that don’t produce one of the messages on this page, such as a marketplace URL that doesn’t load or a plugin that installs but doesn’t appear, see [Plugin troubleshooting](../08-Plugins-Skills/plugins-troubleshooting.md).
[](#plugin-eval-is-currently-in-early-access)
plugin eval is currently in early access
You ran [`claude plugin eval`](../08-Plugins-Skills/plugin-evals.md) or `claude plugin eval init` and it exited 1 with one of these messages before doing anything:
```python
`plugin eval` is currently in early access
```
```python
`plugin eval` is currently unavailable
```
The first message means your build is older than v2.1.269, the first version where the command is generally available. The second means Anthropic has switched the command off server-side; nothing on your machine turns it back on. **What to do:**
- Run `claude --version`, then `claude update`, and run the command again in a fresh session. See the [requirements for plugin evals](../08-Plugins-Skills/plugin-evals.md#requirements)
- If you see the second message on a current build, try again later after another `claude update`
[](#marketplace-is-registered-from-an-untrusted-source)
Marketplace is registered from an untrusted source
The marketplace is registered under a name that is [reserved for official Anthropic marketplaces](../08-Plugins-Skills/plugins-marketplace-reference.md#marketplace-file), but its registered source isn’t an `anthropics` GitHub repository. Claude Code re-checks reserved names every time it loads or refreshes a marketplace, so the marketplace and the plugins installed from it stop loading. Before v2.1.205, an entry registered before its name became reserved kept loading.
```python
Marketplace "claude-community" is registered from an untrusted source: The name 'claude-community' is reserved for official Anthropic marketplaces. Only repositories from 'github.com/anthropics/' can use this name. To fix it, remove the marketplace and re-add it from the official source.
```
For a marketplace whose source isn’t a GitHub repository or a Git URL, such as a local directory, the middle sentence reads `can only be used with GitHub sources from the 'anthropics' organization` instead. `claude plugin marketplace add` runs the same check, and refuses a reserved name with `Failed to add marketplace:` followed by the same reserved-name sentence. **What to do:**
- If the marketplace is already registered, run `claude plugin marketplace remove <name>`, then add it again from the official `github.com/anthropics` repository
- If you publish a third-party marketplace that used the name before it became reserved, rename it and ask users to re-add it from your source
- See the reserved name list under [Marketplace schema](../08-Plugins-Skills/plugins-marketplace-reference.md#marketplace-file)
[](#marketplace-name-is-another-spelling-of-a-reserved-name)
Marketplace name is another spelling of a reserved name
The marketplace’s name isn’t itself a reserved name, but Claude Code treats it as another spelling of one. [Reserved names](../08-Plugins-Skills/plugins-marketplace-reference.md#reserved-name-spellings) lists which spellings count as a reserved name. Claude Code refuses such a name when you add the marketplace:
```python
Failed to add marketplace: "claude.code.plugins" is another spelling of "claude-code-plugins", a reserved marketplace name.
```
When a marketplace is already registered under such a name, its entry stops loading, and `/plugin`, `claude plugin install`, and `claude plugin update` warn:
```python
known_marketplaces.json has an entry named "claude.code.plugins", another spelling of the reserved marketplace name "claude-code-plugins", so it is ignored. Remove it with: claude plugin marketplace remove claude.code.plugins
```
When the name would need shell quoting, the add-time refusal reads `This marketplace's name is another spelling of "<reserved>", a reserved marketplace name. It is not exactly the reserved name it appears to be.` **What to do:**
- Rename the marketplace to a name that doesn’t spell a reserved name and add it again
- For the ignored-entry warning, run the `claude plugin marketplace remove` command it gives, or remove the entry from `~/.claude/plugins/known_marketplaces.json`
[](#claude-code-refuses-the-marketplace-name)
Claude Code refuses the marketplace name
A registered marketplace’s name [impersonates an official Anthropic marketplace](../08-Plugins-Skills/plugins-marketplace-reference.md#reserved-names) under the rules that section lists. If a marketplace was registered under such a name before the check blocked it, the marketplace and the plugins installed from it stop loading, because Claude Code checks the name every time it reads the marketplace’s catalog. When the name imitates an official one, `claude plugin list` and the `/plugin` **Errors** tab report each affected plugin with a message that begins:
```python
Claude Code refuses the marketplace name "anthropic-plugins-v2"
```
For an imitating name, the marketplace’s own error reads `Claude Code refuses this marketplace's name: it looks like one of Anthropic's own` instead. `claude plugin marketplace add` refuses any impersonating name with `Marketplace name impersonates an official Anthropic/Claude marketplace`. Before v2.1.282, `claude plugin list` and `/plugin` reported the plugins of an imitating name as failed to load too, without naming the marketplace’s name as the cause. **What to do:**
- Run `claude plugin marketplace remove <name>`. This also uninstalls the plugins installed from the marketplace and deletes their saved data
- To keep the marketplace instead, wait until its maintainer renames it, then run `claude plugin marketplace update <name>`
- If you publish the marketplace, rename it in your `marketplace.json`; users then update the marketplace instead of removing it
[](#marketplace-is-already-added-from-a-different-source)
Marketplace is already added from a different source
You confirmed adding a marketplace through [`/plugin install <plugin> --marketplace <source>`](../08-Plugins-Skills/discover-plugins.md#add-a-marketplace-and-install-in-one-command), and the catalog Claude Code fetched from that source names itself the same as a marketplace you already added from a different source. Claude Code keeps the existing marketplace instead of replacing it, and the plugin isn’t installed.
```python
Marketplace "acme-tools" is already added from a different source (github:acme/plugins). To use this source instead, remove that marketplace first with /plugin marketplace remove acme-tools.
```
**What to do:**
- If the marketplace you already added is the one you want, install from it by name: `/plugin install <plugin>@<name>`
- To switch to the new source, run `/plugin marketplace remove <name>`, then retry the install
[](#plugin-command-references-user-config)
Plugin command references user_config in a shell command
A plugin hook, [monitor](../08-Plugins-Skills/plugins-components.md#monitors), or MCP [`headersHelper`](../06-MCP-Tools/General/mcp.md#use-dynamic-headers-for-custom-authentication) command references a `${user_config.KEY}` [plugin option](../08-Plugins-Skills/plugins-reference.md#user-configuration), and the substituted string would be passed to a shell. A configured value containing `$(...)`, backticks, or `;` would run as code there, so Claude Code refuses to start the component instead of substituting the value. The check runs on the command template, so the error appears even when no value is configured yet. Before v2.1.207, the value was substituted into the shell command. The wording depends on which surface referenced the option. A shell-form hook reports:
```python
Hook from plugin formatter@acme-tools references ${user_config.*} in a shell-form command. The substituted value would be re-parsed by the shell. Use exec form instead — {"command": "<executable>", "args": ["${user_config.KEY}", ...]} — or read $CLAUDE_PLUGIN_OPTION_<KEY> from the hook's environment. Command: ./scripts/notify.sh ${user_config.webhook_url}
```
A monitor reports:
```python
Monitor "deploy-status" from plugin deploy-tools references ${user_config.*} in its command. The substituted value would be passed to a shell. Monitor commands cannot safely reference ${user_config.*}; have the monitor script read the value from a config file or prompt instead.
```
An MCP `headersHelper` reports:
```python
headersHelper for MCP server 'internal-api' references ${user_config.*}. The substituted value would be passed to a shell; read the value inside the helper script instead (e.g. from an env var set in the server's "env" block).
```
**What to do:**
- For a hook, add an `args` array so it runs in [exec form](../07-Hooks/hooks.md#exec-form-and-shell-form), where each `${user_config.KEY}` becomes one argument with no shell in between. Or drop the reference and read the `$CLAUDE_PLUGIN_OPTION_<KEY>` environment variable inside the script
- For a monitor, drop the reference and have the monitor script read the value from a config file
- For a `headersHelper`, move `${user_config.KEY}` into the server’s `headers` field, which isn’t shell-parsed, or read the value inside the helper script
[](#plugin-archive-integrity-check-failed)
Plugin archive integrity check failed
The plugin’s marketplace entry uses an [`archive` source](../08-Plugins-Skills/plugins-marketplace-reference.md#archive-plugin-source) with a `sha256` pin, and the digest of the downloaded file doesn’t match the pin. Claude Code refuses the install, so nothing changes in the plugin cache. The mismatch has three possible causes:
- The file at the URL changed after the author computed the pin
- The author entered the wrong digest in the marketplace entry
- The URL serves a different file than the author pinned
```python
Plugin archive integrity check failed for https://artifacts.example.com/claude-plugins/my-plugin.zip: expected sha256 6bfa50e3d2e00c052b46abe51fff89346ac803e45771f76dcf6df1ab74cca5e1, got ac52220c0914ef8ca6a602e4a7362f88d30fb021110f72a6d15b68c3fe7df2b7. The archive was not installed. Verify the sha256 in the marketplace entry, or that the URL serves the intended file.
```
**What to do:**
- If you publish the plugin, recompute the digest of the exact file the URL serves, for example with `shasum -a 256 my-plugin.zip`, or `Get-FileHash -Algorithm SHA256 my-plugin.zip` in PowerShell, and update the `sha256` in the marketplace entry
- If you install the plugin, run `/plugin marketplace update <name>` to refresh the catalog in case the entry was corrected, then retry the install
- If the digests still disagree after a refresh, ask the marketplace owner which file they pinned before installing
[](#path-escapes-plugin-directory)
Path escapes plugin directory
A plugin component path, declared in the plugin’s `plugin.json` or in its [marketplace entry](../08-Plugins-Skills/plugins-marketplace-reference.md#plugin-entries), resolves outside the plugin’s own directory. Claude Code drops that path and loads the rest of the plugin. The component name in the message, such as `commands` or `hooks`, names the field that declared the path.
```python
commands path escapes plugin directory: ./../shared.md
```
In `claude plugin` command output, the same error reads `Path escapes plugin directory: ./../shared.md (commands)`. Claude Code rejects both a path that points outside the plugin as written, such as `../shared-utils`, and a symlink that leads outside the plugin and isn’t one the [marketplace symlink rules](../08-Plugins-Skills/plugins-host-marketplace.md#share-files-within-a-marketplace-with-symlinks) allow. For a symlink, the message also says where the path resolves:
```python
commands path escapes plugin directory: ./commands/deploy.md — it resolves to /home/user/shared/deploy.md, outside the plugin directory
```
On macOS and Linux, Claude Code also rejects a component path that contains a backslash anywhere in it, even when the path stays inside the plugin. A plugin whose component paths use Windows-style separators loads on Windows and triggers this rejection on the other platforms:
```python
commands path escapes plugin directory: ./commands\deploy.md — its path contains a backslash, which is not resolved reliably on this platform
```
Before v2.1.251, Claude Code loaded a `commands` path declared in a marketplace entry even when it pointed outside the plugin directory. Claude Code already rejected paths declared in `plugin.json` and the other component paths in a marketplace entry. Before v2.1.257, the check looked only at the path’s spelling, not at where a symlink leads. **What to do:**
- Move the referenced file inside the plugin directory and point the path at it with a `./` relative path
- If the path is a symlink to a file outside the plugin, replace the symlink with a copy of the file
- If the message says the path contains a backslash, write the path with forward slashes, for example `./commands/deploy.md`
- To share files with other plugins in the same marketplace, link them with a symlink inside the plugin directory, following the [symlink rules](../08-Plugins-Skills/plugins-host-marketplace.md#share-files-within-a-marketplace-with-symlinks)
[](#path-could-not-be-checked)
Path could not be checked
Claude Code asked the operating system whether a plugin path exists and got an error other than “not found”, so it doesn’t load what the path names. How much of the plugin loads depends on which path failed:
- One of a plugin’s [default component locations](../08-Plugins-Skills/plugins-reference.md#standard-layout), such as the `skills/` folder, the `monitors/monitors.json` file, or a [`SKILL.md` at the plugin root](../08-Plugins-Skills/plugins-components.md#skills): the plugin’s other components still load
- The plugin’s own directory: nothing from that plugin loads
You don’t see this error for a path that doesn’t exist at all. In `/plugin`, the error appears under the plugin and names the path and the code the operating system returned:
```python
skills path could not be checked: /home/user/my-plugin/skills (ELOOP)
```
In `claude plugin list`, the same error reads `Path not found: /home/user/my-plugin/skills (skills, ELOOP)`. Causes that produce this error include:
- `ELOOP`: a symlink in the path points at itself or forms a loop
- `EIO` or `ESTALE`: the path is on a network mount that is broken or stale
- `EACCES`: one of the directories above the path denies you permission to traverse it
**What to do:**
- Replace a symlink that points at itself with a real folder, or delete it
- If the path is on a network mount, remount the share
- If the code is `EACCES`, restore your execute permission on the directories above the path
- Run `/reload-plugins` after fixing the path, or restart Claude Code, to load the plugin or component
Before v2.1.265, Claude Code treated a default component folder it couldn’t check as absent and loaded the plugin without that component, with no error.
[](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory)
Marketplace entry path does not stay inside the marketplace directory
The plugin’s [marketplace entry](../08-Plugins-Skills/plugins-marketplace-reference.md#plugin-entries) declares a source path that Claude Code can’t resolve to a location inside the marketplace’s own directory, so the plugin doesn’t install or load. The refusal covers:
- An entry path that is absolute, climbs out of the marketplace with `..`, or is spelled like a network path
- On macOS and Linux, an entry path that contains a backslash anywhere after the leading `./`
- An entry in a marketplace fetched from a remote source, such as git or a URL, that reaches its target through a symlink resolving outside the marketplace directory
- A relative entry in a marketplace added from a direct URL to its `marketplace.json`: Claude Code downloads only that file, so no local plugin files exist for the path to name. See [Plugins with relative paths fail in URL-based marketplaces](../08-Plugins-Skills/plugins-troubleshooting.md#plugins-with-relative-paths-fail-in-url-based-marketplaces)
`claude plugin install` reports the refusal like this:
```python
Cannot install my-plugin@my-marketplace: its marketplace entry path does not stay inside the marketplace directory (an absolute, climbing, network-shaped, backslash-containing or link-traversing entry, an entry of a fetched marketplace that resolves or opens outside its tree — or a relative entry in a url-catalog marketplace, which has no local directory)
```
When an already-installed plugin’s entry fails the same check, `claude plugin list` shows the plugin as `failed to load` with:
```python
Plugin source path refused: ./my-plugin does not stay inside its marketplace directory. Check that the marketplace entry has a plain relative path.
```
**What to do:**
- If you maintain the marketplace, write the entry’s `source` as a plain relative path with forward slashes, such as `./plugins/my-plugin`, and keep any symlink it crosses pointed inside the marketplace directory
- If you added the marketplace from a direct URL, relative entries can’t resolve. Ask the marketplace author to use [another plugin source](../08-Plugins-Skills/plugins-marketplace-reference.md#plugin-sources), or add the marketplace from its git repository instead
[](#failed-to-load-marketplace-configuration)
Failed to load marketplace configuration
Claude Code keeps the plugin marketplaces you’ve added in a registry file at `~/.claude/plugins/known_marketplaces.json`. A plugin command that needs the registry, such as `claude plugin install`, fails with one of two messages when Claude Code can’t use the file:
- `Failed to load marketplace configuration`: the file isn’t valid JSON, or can’t be read. An empty file fails this way too.
- `Marketplace configuration file is corrupted`: the file is valid JSON but its contents don’t match the registry schema.
A missing file isn’t a failure: Claude Code treats it as a registry with no marketplaces. With an empty file, `claude plugin install` reports:
```python
✘ Failed to install plugin "my-plugin": Failed to load marketplace configuration: JSON Parse error: Unexpected EOF
```
Before v2.1.246, `claude plugin install` didn’t report this failure. **What to do:**
- Open `~/.claude/plugins/known_marketplaces.json` and repair the JSON, or fix the entries the message names as not matching the registry schema
- If you can’t repair it, delete the file or replace its contents with `{}`, then re-add each marketplace with `claude plugin marketplace add <source>`. Claude Code re-registers the marketplaces your user or managed settings declare in [`extraKnownMarketplaces`](settings-reference.md#extraknownmarketplaces) the next time you start it in a folder you’ve trusted.
[](#plugin-is-required-by-your-organization)
Plugin is required by your organization
You ran `claude plugin disable`, or used the `/plugin` **Installed** tab, to turn off a [plugin synced from claude.ai](../08-Plugins-Skills/plugins-loading.md#synced-plugins) that your organization marks as required:
```python
Plugin "<name>@synced" is required by your organization and can't be disabled here. Contact your admin to change it.
```
Claude Code saves nothing and the plugin stays enabled. When you try to disable a plugin that a required plugin depends on, Claude Code refuses the same way, with a message naming the required plugin that needs it. **What to do:**
- Ask an admin of your claude.ai organization to change the plugin’s required status on claude.ai
[](#plugin-was-not-uninstalled)
Plugin was not uninstalled
You ran [`claude plugin uninstall`](../08-Plugins-Skills/plugins-cli-reference.md#plugin-uninstall), or chose **Uninstall** in the `/plugin` **Installed** tab, and the uninstall stopped with a message starting `"<plugin>" was not uninstalled:`. If the text after that colon starts with `installed_plugins.json` instead of naming a settings file, the cause is content in `installed_plugins.json` that this version of Claude Code can’t read. For that form, see [`installed_plugins.json` holds a record this version can’t read](../08-Plugins-Skills/plugins-troubleshooting.md#installed-plugins-json-holds-a-record-this-version-cannot-read). When Claude Code removed the plugin’s entry from `enabledPlugins` and read that scope’s settings files back, either the plugin was still switched on there, or a file that could switch it on couldn’t be read or checked. Deleting the plugin’s saved options, secrets, and data while a settings entry could switch it back on would lose them, so the uninstall stops instead: the plugin stays installed and nothing it saved is deleted.
```python
✘ Failed to uninstall plugin "formatter": "formatter" was not uninstalled: it is still switched on in /home/user/project/.claude/settings.local.json, although the settings change reported no error. It is still installed. Take it out of "enabledPlugins" in that file yourself, then uninstall it again.
```
The middle of the message names the file and the cause:
- `it is still switched on in <file>, although the settings change reported no error`: the settings write reported success but the entry is still there when the file is read back
- `it is still switched on in <file>, and the settings change failed (<error>)`: the file couldn’t be saved, for the reason in parentheses
- `<file> is there and could not be read`: the file exists but couldn’t be read as settings, for example because it isn’t valid JSON, so it may still enable the plugin
- `<file> (not read: it is on a network path or is a link to one, or could not be checked)`: Claude Code didn’t read the project or local settings file because the file, or the `.claude` folder that holds it, is a link that leads to a network location, or because it couldn’t examine that path
`claude plugin uninstall` exits 1, and with `--json` the result carries `failureCode: "settings_still_on"`. `/plugin` shows the same message. **What to do:**
- Follow the last sentence of the message: repair or replace the settings file it names, or remove the plugin’s entry from `enabledPlugins` in that file yourself, then run the uninstall again
[](#tool-errors)
Tool errors
These errors come from Claude’s built-in tools. Claude corrects most tool errors on its own. When one needs a change from you, that error’s **What to do** list says what to change.
[](#agent-would-be-spawned-with-zero-tools)
Agent would be spawned with zero tools
Every entry in the subagent’s [`tools` list](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) failed to match a usable tool, so Claude Code refused to launch the subagent: with no tools, it couldn’t act. The message groups your entries by what went wrong:
- **Unrecognized**: the entry matches no tool name, usually a typo such as `Grpe` for `Grep`.
- **Not available to subagents**: the entry names a real tool that [subagents can’t use](../09-Agents-Patterns/sub-agents.md#available-tools). Background subagents keep a smaller built-in tool set, so an entry that only a foreground subagent can use lands here when the subagent would run in the background, which is the default. If you list `Agent`, the message reports it under the next group instead.
- **Matched no tools in this session**: the entry is valid but no tool in the current session matches it right now, such as `mcp__github__*` with no GitHub MCP server connected, or `Agent` for a subagent at the [depth limit](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents).
Omitting the `tools` field never triggers this refusal. If you leave the `tools` list empty, or `disallowedTools` removes every entry in it, Claude Code also skips the refusal and launches the subagent without tools. Before v2.1.208, the subagent launched with no tools and could return an empty or confusing result.
```python
Agent 'code-reviewer' would be spawned with zero tools — refusing. Its tools list resolved to nothing: unrecognized [Grpe]. Fix the agent's tools frontmatter or pass a different subagent_type.
```
**What to do:**
- Correct each entry the error names against the [tools available to subagents](../09-Agents-Patterns/sub-agents.md#available-tools)
- Remove entries for tools the session doesn’t have, such as MCP tools from a server that isn’t connected
- For a tool that [background subagents drop](../09-Agents-Patterns/sub-agents.md#available-tools), such as `CronCreate`, remove the entry. To keep the tool, [turn fork mode off](../09-Agents-Patterns/sub-agents.md#turn-fork-mode-on-or-off) and ask Claude to run the subagent in the foreground
- Delete the `tools` field instead of listing tools to give the subagent every [tool available to subagents](../09-Agents-Patterns/sub-agents.md#available-tools)
- For a `tools` list that contains only `Agent`, raise the [depth limit](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents) or give the agent at least one other tool: Claude Code withholds `Agent` at that limit, so a list with nothing else in it resolves to no tools
[](#file-is-covered-by-a-read-deny-rule)
File is covered by a Read deny rule
The Edit or Write tool was called on a path matched by a [`Read` deny rule](permissions.md#read-and-edit), including creating a new file at that path. Both tools change content Claude has to be able to read back, so Claude Code refuses the call before any file access. NotebookEdit isn’t covered by `Read` deny rules. Before v2.1.228, the rule blocked the Edit tool only, and before v2.1.208, only an `Edit` deny rule blocked edits.
```python
File is covered by a Read deny rule in your permission settings and cannot be edited.
```
When Claude Code refuses the Write tool, the message ends `and cannot be written` instead. **What to do:**
- If Claude should be able to change the file, remove or narrow the `Read` deny rule in `/permissions` or in [settings](settings-reference.md#permission-settings)
- If the file must stay untouched, keep the rule and add an `Edit` deny rule for the same path to block the NotebookEdit tool too
[](#path-cannot-contain-null-bytes)
Path cannot contain null bytes
A file tool call’s path or pattern argument contained a null byte, which file systems and search tools can’t accept. Read, Write, Edit, NotebookEdit, Glob, and Grep check for this, and the message names the tool and the argument:
```python
Read file_path cannot contain null bytes (\0). Remove the null byte and try again.
```
The tool call fails, Claude sees the error, and the turn continues. **What to do:**
- Nothing on your side: the error is returned to Claude as the tool’s result, and the message itself tells Claude to remove the null byte and try again
Before v2.1.281, a null byte in a Read, Write, Edit, or NotebookEdit path ended the whole turn with an error naming `Path contains null bytes`, and the tool never ran.
[](#subagent-type-is-required)
subagent_type is required
```python
subagent_type is required: the general-purpose agent is not available in this session. Available agents: ...
```
Claude called the [Agent tool](tools-reference.md#agent-tool-behavior) without a `subagent_type`, and this session has no [general-purpose subagent](../09-Agents-Patterns/sub-agents.md#built-in-subagents) to fall back on. That is the case in two setups:
- [`CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS=1`](env-vars.md) is set in non-interactive mode, which removes every built-in subagent
- The session’s main-thread agent has a [`tools: Agent(...)` allowlist](../09-Agents-Patterns/sub-agents.md#restrict-which-subagents-can-be-spawned) that leaves out `general-purpose`
**What to do:**
- Usually nothing: the message lists the subagents the session does have, so Claude can retry with one of them
- If Claude keeps failing, add `general-purpose` to the `tools: Agent(...)` allowlist, or unset `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS`
Before v2.1.235, the same call failed with `Agent type 'general-purpose' not found`.
[](#memory-index-is-over-its-read-limit)
Memory index is over its read limit
Claude wrote to the [auto memory](memory.md#auto-memory) index `MEMORY.md` and left it over one of its read limits: 200 lines or 25KB. The write succeeded, but only the first 200 lines or 25KB, whichever comes first, load at the start of a session, so everything past the limit is dropped each time the index is read. Before v2.1.210, an over-limit index was silently truncated on the next load with no write-time signal.
```python
Error: this write left the memory index at MEMORY.md at 214 lines, over its 200-line read limit. The write succeeded, but everything past the limit is silently dropped each time the index is loaded — entries at the end are already invisible to readers. Rewrite it to under 140 lines now: keep one line per entry, move detail into topic files, and merge or drop stale entries.
```
Only the content that loads counts toward the limits. YAML frontmatter and block-level HTML comments are stripped before the index is loaded, so they’re excluded from the measurement. Before v2.1.211, Claude Code measured the raw file, and frontmatter or comments could trigger this error even when the loaded content fit. Claude Code delivers the error to Claude after the write rather than printing it as a banner in your terminal, so you may notice it only in the transcript. When Claude’s write brings the file near a limit without crossing it, Claude Code returns a milder reminder to compact the index instead of this error. **What to do:**
- Let Claude rewrite `MEMORY.md`, or ask it to: keep one line per entry, move detail into topic files, and merge or drop stale entries
- To trim the index yourself, see [Audit and edit your memory](memory.md#audit-and-edit-your-memory)
[](#pkill-pattern-matches-the-claude-code-process)
pkill pattern matches the Claude Code process
A `pkill` command in a Bash tool call used a pattern, typically with `-f`, that matches the Claude Code process itself, so Claude Code refuses the command instead of letting it end the session. Claude Code tests the pattern with `pgrep` before running `pkill` and refuses when its own process ID is in the result. The check runs on Linux only; on macOS, `pkill` runs unmodified. Before v2.1.214, the command ran, and a matching pattern killed the Claude Code session mid-turn.
```python
pkill: refusing to run — this pattern matches the Claude CLI process (PID 12345). Narrow the pattern, or target your own children with `pkill -P $$ ...`.
```
The refusal appears in the Bash tool result rather than as a banner in your terminal, and Claude usually adjusts the command on its own. **What to do:**
- Narrow the pattern so it matches only the intended process, for example the full path of the target binary rather than a short substring
- To stop processes started by the current shell, use `pkill -P $$` with the pattern, which limits the match to the shell’s own child processes
[](#failed-to-write-to-a-teammate-inbox)
Failed to write to a teammate’s inbox
Claude Code couldn’t write a message to a teammate’s mailbox file under `~/.claude/teams/{team-name}/inboxes/`, so the recipient received nothing. The write fails when Claude Code can’t create or update the file, for example because the disk is full, the directory isn’t writable, or another agent holds the inbox lock for too long. Before v2.1.224, Claude Code reported the message as sent even when the write failed. The error appears in the sending agent’s tool result rather than as a banner in your terminal, and its text tells Claude to try again:
```python
Failed to write to researcher's inbox — nothing was sent. Try again, or message the lead.
```
Structured [agent team](../09-Agents-Patterns/agent-teams.md) protocol messages fail the same way, and the error names the undelivered message: when Claude Code can’t write a plan approval, plan rejection, shutdown request, or shutdown rejection, the error reads `Failed to write the <message> to <name>'s inbox — nothing was sent`. The `plan approval` in that list is the lead’s decision approving a teammate’s plan; the teammate’s plan submission is the separate `plan approval request` message. That message and two other protocol messages carry their own message text and consequence:
- `Failed to write the plan approval request to the lead's inbox — plan not submitted; try again`: the teammate’s plan never reached the lead, and the teammate stays in plan mode until a resubmission succeeds
- `The permission request could not be delivered to the team lead (mailbox write failed)`: the teammate’s permission request never reached the lead, so nobody approved the tool call
- `The confirmation could not be written to team-lead's inbox.`: the shutdown approval itself took effect and the teammate exits; only the confirmation to the lead is missing
When you message a teammate yourself, typing `@name` followed by the message in the lead session, the same failure appears as a notification, `Couldn't write to @name's inbox — message not sent. Try again.`, and Claude Code keeps your text in the prompt box so you can send it again. **What to do:**
- Ask the sender to resend the message; contention for the inbox lock is transient and clears on retry
- Check free disk space, and check that `~/.claude/teams` and the files under it are writable by your user
[](#teammate-agent-definition-not-restored)
Teammate’s agent definition was not restored
Claude messaged a stopped [agent team](../09-Agents-Patterns/agent-teams.md) teammate, and Claude Code brought it back without re-applying the [subagent definition](../09-Agents-Patterns/agent-teams.md#use-subagent-definitions-for-teammates) it was spawned from, because its definition file came from a folder with no saved trust. The notice follows the resume report in the sending agent’s tool result:
```python
Its agent definition was not restored: the folder its definition file came from is not trusted (source: projectSettings), so the teammate is running with the team-essential tools and no custom instructions. To restore it, the user needs to run Claude Code in that folder once and accept the trust dialog (the --debug log names the folder); do not change trust settings on the user's behalf.
```
The check applies to a definition in the `.claude/agents/` directory of the project or of an `--add-dir` directory, and accepting the trust dialog for a parent folder doesn’t satisfy it. **What to do:**
- Run `claude` in the folder the [debug log](debug-your-config.md) names and accept the trust dialog. The definition is re-applied the next time Claude Code brings the teammate back; you don’t need to restart the lead session
- Or set the `hasTrustDialogAccepted` entry to `true` in `~/.claude.json`, using the exact `projects["<path>"]` key the debug log prints
[](#message-too-large-for-cross-session-delivery)
Message too large for cross-session delivery
Claude’s [cross-session message](cross-session-messaging.md) to another of your sessions on this machine was too long to send. Claude Code refused it, and the receiving session got nothing. The refusal appears in the sending session’s tool result, not as a banner in your terminal. It names both sizes and how to make the message fit:
```python
Failed to send to api-worker: Message too large for cross-session delivery: the serialized message is 1,203,844 characters and the limit is 1,048,576. Shorten the message text — put bulk content in a file the recipient can read rather than in the message — or split it into smaller messages.
```
Resending the same text fails the same way. **What to do:**
- Ask Claude to summarize the message, or to put the bulk content in a file and send the file’s path
- Ask Claude to split the content across several shorter messages
Before v2.1.235, Claude Code reported an oversized message as sent. The receiving session dropped it unread.
[](#too-many-messages-to-this-session-just-now)
Too many messages to this session just now
Claude sent a rapid burst of [cross-session messages](cross-session-messaging.md) to one of your sessions on this machine, and the burst reached what that session’s inbox accepts. Claude Code refused the next send, and the receiving session got nothing from it. The refusal appears in the sending session’s tool result, not as a banner in your terminal:
```python
Failed to send to api-worker: Too many messages to this session just now: 30 were sent recently and more would be dropped by its rate limit, so this one was not sent. Batch what remains into one message, or wait a little before sending more.
```
**What to do:**
- Usually nothing: Claude batches the remaining content into one message, or waits before sending more
- If you prompted the burst yourself, ask Claude to combine what’s left into a single message
Before v2.1.236, Claude Code reported these sends as sent. The receiving session dropped them unread.
[](#cross-session-message-dropped-at-the-inbox)
Cross-session message was dropped at the recipient session’s inbox
Claude sent a [cross-session message](cross-session-messaging.md) to another of your sessions on this machine, and that session’s inbox discarded it before Claude in that session read it. The line names the recipient’s address and, when the recipient gave a reason, adds the reason after a dash:
```python
Cross-session message was dropped at the recipient session's inbox (recipient: uds:/tmp/cc-socks/13605.sock) and not delivered — its queue of undelivered peer messages was full. Claude was told not to resend right away.
```
One line can cover several dropped messages. It then starts in the plural, for example `Cross-session messages (12) were dropped`. To find which session an address belongs to, compare it with the [`Peer address` row](cross-session-messaging.md#the-sessions-inbox-socket) that `/status` shows in each session. After the dash, the line gives one or more of these reasons:
- `its queue of undelivered peer messages was full`: the recipient already held as many undelivered messages from other sessions as its queue allows
- `you sent faster than that session accepts`: the sending session’s messages arrived faster than the recipient accepts from one sender
- `it repeated your previous message`: the message was identical to one the sending session sent this recipient shortly before
- `a relay loop between sessions was cut`: the message continued a chain of sessions messaging each other, and the chain had passed through the recipient too many times or grown too long
**What to do:**
- Assume the recipient never saw the dropped messages. Claude Code tells Claude the same, and tells it to include anything that still matters in one later message instead of resending right away
- If your sessions send each other frequent updates, ask Claude to send fewer, larger messages, such as one report when a session finishes its work
- For `a relay loop between sessions was cut`, type the next instruction into one of the sessions yourself. A message Claude sends in response to your own prompt begins a new chain
Before v2.1.238, the sending session got no report when the recipient’s inbox discarded a message.
[](#refusing-to-send-a-cross-session-message)
Refusing to send a cross-session message
Before Claude Code writes a [cross-session message](cross-session-messaging.md) to another of your sessions on this machine, it checks that the target session’s inbox socket is the endpoint the message was addressed to. When a check fails, Claude Code refuses the send in the sending session, and the target session receives nothing. For a message Claude sends, the refusal appears in the sending session’s tool result:
```python
Failed to send to api-worker: Refusing to send: reply target is a symlink
```
The text after `Refusing to send:` names the check that failed:
- `reply target is a symlink`: a symbolic link sits at the target session’s socket path. Claude Code doesn’t deliver through it, because a link there could redirect the message to an endpoint the target session didn’t create.
- `cannot vet reply target`: Claude Code couldn’t inspect the target path at all, for example because reading it failed with a permission error.
**What to do:**
- Usually nothing: the checks keep a message from reaching an endpoint other than the session it was addressed to, and nothing was sent
- If `reply target is a symlink` repeats for one session, check what created a link at that session’s socket path, shown in its `/status` under `Peer address`
[](#refusing-after-a-symlink-changed)
Refusing to read, write, or search a path
Claude Code checks a file path’s [permission rules](permissions.md#read-and-edit), then confirms that resolution again when the tool opens the file or starts the search. When it can’t confirm that the path still leads to the location the check approved, Claude Code refuses the operation instead of following it. The refusal appears in the tool result:
```python
Refusing to read /path/to/file: its symlink resolution changed after permission was checked (a link on the way now leads somewhere the check did not see). If a link in the working directory is being rewritten concurrently, stop that and retry.
```
Each refusal names its reason:
- `its symlink resolution changed after permission was checked`: a symlink along the path, or at a Grep or Glob search root, was replaced between the permission check and the operation. In a read refusal, the parenthesized phrase names which comparison failed.
- `its parent-directory symlink resolution changed after permission was checked`: a directory the write path passes through no longer resolves to the approved location
- `where it leads on disk could not be determined (a link on the way could not be examined, or the links do not resolve)`: Claude Code couldn’t follow the path to a final location on disk, for example because symlinks on it form a loop
- `it is a symbolic link. Write to the link's target path instead`: a symbolic link sits at the requested write location itself, for example a `CLAUDE.md` that is a symlink to `AGENTS.md`; the message directs Claude to the link’s target
- `Refusing to write through symlink: <path>. Resolve the symlink and pass the real target path explicitly.`: the same condition caught when another writer opens the file, such as a write to a symlinked `.mcp.json`
- `Refusing to write into symlinked directory: <path>`: the directory that holds the file is itself a symbolic link, for example a project’s `.claude/` directory linked to another location
- `a path one of its Read deny rules is written through changed while the search was being prepared. Retry.`: a `Read` deny rule for the search names a path that passes through a symlink, and that link changed while Claude Code was preparing the search
- `it could not be opened (EACCES) — it is unreadable, or is being replaced concurrently.`: the search root exists but couldn’t be opened; the parenthesized code is the operating system error
- `its permission check expired before it ran (too many concurrent file operations). Retry.`: Claude Code evicted the approval record under many simultaneous file operations before the tool used it; retrying runs a fresh permission check
- `ripgrep was found only by name on PATH, and a search outside the working directory cannot apply your Read deny rules in that configuration`: Claude Code couldn’t resolve the `rg` binary to an absolute path, so it refuses searches outside the working directory rather than run one your deny rules don’t cover
**What to do:**
- Usually nothing: the refusal reaches Claude as the tool result, and the refused operation doesn’t run
- If a symlink refusal repeats on one path, find what keeps rewriting a link there, such as a build tool or file watcher, or ask Claude to use the file’s resolved path instead of the linked one
- If this refusal appears for every file while Claude Code runs on Windows inside an AppContainer or restricted-token sandbox, upgrade to v2.1.265 or later
- If a read refusal appears on macOS for a file that nothing is rewriting, such as a screenshot dragged into the prompt, upgrade to v2.1.273 or later
- For the ripgrep refusal, install ripgrep with your package manager so `rg` resolves to an absolute path on `PATH`, or keep searches under the working directory
Before v2.1.251, Claude Code re-checked a path’s resolution only for file writes, so a link replaced after the permission check could redirect a read or search to a different location without a message. Of these, only the parent-directory, through-symlink, and symlinked-directory write refusals appear on earlier versions. Before v2.1.280, the `where it leads on disk could not be determined` refusal didn’t appear.
[](#task-output-swap-refused)
Task output swap refused
Claude Code saves each Bash command’s output to a file under its temp directory. Every time it opens one of these files, it checks that the path still leads to the file it created, with no symbolic link, extra hard link, or moved directory redirecting it. This message means that check failed, so Claude Code refused the operation rather than write or read output through that path. The message appears in the Bash tool result:
```python
task output swap refused (tasks dir moved or linked): /private/tmp/claude-501/-Users-you-my-project/1f0e62dc-4b0a-4f5e-9c2d-8a7b6c5d4e3f/tasks/b7k2f9m3q.output. To recover: restart Claude Code with CLAUDE_CODE_TMPDIR set to a fresh directory; or, if /private/tmp/claude-501/-Users-you-my-project is a stray directory or a symbolic link that should not be there, remove that entry itself (not what it points to) and restart.
```
The parenthesized text names the check that failed. Reasons such as `output symlink was re-pointed`, `output file identity changed`, and `not a regular file` all report the same condition: something at or along the output path is no longer the file Claude Code created. Only some reasons carry a `To recover:` sentence. If the check fails while a command is still running, Claude Code stops the command, and its result reports:
```python
Command killed: its output file was replaced or could no longer be verified
```
**What to do:**
- Upgrade to v2.1.260 or later. Earlier versions sometimes showed this message when no link or moved directory was present
- Restart Claude Code with [`CLAUDE_CODE_TMPDIR`](env-vars.md) set to a fresh directory
- Or check your project’s directory under the Claude Code temp directory, `/private/tmp/claude-501/-Users-you-my-project` in the example message. If that path is a symbolic link, or a directory that shouldn’t be there, remove the link or directory itself rather than the link’s target, and restart Claude Code
- If the refusal repeats, a process is replacing, linking, or removing entries under Claude Code’s temp directory while the session runs. Set [`CLAUDE_CODE_TMPDIR`](env-vars.md) to a directory nothing else manages and restart
[](#disk-quota-or-temp-filesystem-is-full)
Disk quota or temp filesystem is full
Claude Code saves each Bash and PowerShell command’s output to a file under its temp directory. When a command exits with a nonzero code and no output at all, Claude Code checks whether the filesystem holding that file is out of space or inodes, or whether your disk quota on it is used up. If so, a diagnostic appears in the command’s result in place of the empty output:
```python
Your disk quota is full on the filesystem with Claude Code's temp directory /private/tmp/claude-501/-Users-you-my-project/1f0e62dc-4b0a-4f5e-9c2d-8a7b6c5d4e3f/tasks (EDQUOT), so any output this command printed was lost, and it may have failed because it could not write. Delete files you no longer need there, or restart Claude Code with CLAUDE_CODE_TMPDIR set to a directory on another filesystem.
```
The message names what ran out:
- `Your disk quota is full ... (EDQUOT)`: your own quota on that filesystem is used up. A quota can be full while the filesystem still shows free space
- `The filesystem with Claude Code's temp directory ..., or your disk quota on it, is full (ENOSPC)`: the filesystem, or your quota on it, has no space left
- `Command output was lost: the temp filesystem at ... is full` or `... is out of inodes`: the filesystem has almost no free space left, or is running out of inodes
**What to do:**
- Delete files you no longer need on the filesystem that holds Claude Code’s temp directory. For `EDQUOT`, delete files that count against your own quota. For `out of inodes`, delete many files rather than a few large ones, since each file takes one inode whatever its size
- Or restart Claude Code with [`CLAUDE_CODE_TMPDIR`](env-vars.md) set to a directory on a filesystem with room
- Then have Claude run the command again. The output it printed was lost, not truncated
[](#the-source-file-is-not-valid-utf-8-text)
The source file is not valid UTF-8 text
Claude tried to publish an [artifact](artifacts.md) from a file whose bytes don’t decode as text, or whose text already contains the replacement character `U+FFFD`, so Claude Code refused the publish before uploading anything. The message appears in the Artifact tool result and names the first position to fix:
```python
file_path: the source file is not valid UTF-8 text (first invalid byte at line 12, column 40). It may be saved in another encoding or contain binary data. Rewrite it as UTF-8, then publish again. Nothing was published.
file_path: the source file has the replacement character U+FFFD at line 12, column 40, usually left where an earlier edit or paste lost a character. Replace it with the intended text (in HTML, write an intended U+FFFD as �), then publish again. Nothing was published.
```
Claude Code decodes the file as UTF-8, or as UTF-16 when it starts with a little-endian UTF-16 byte-order mark. When such a UTF-16 file doesn’t decode, the first message names `UTF-16` and still tells you to rewrite the file as UTF-8. When more positions follow the named one, the message adds a count such as `(+2 more)` after the position. **What to do:**
- Usually nothing: Claude rewrites the file and publishes again
- If the file is one you wrote or exported, save it again as UTF-8, and replace each `U+FFFD` with the character an earlier edit, paste, or conversion lost
- To show an intentional `U+FFFD` on the page, write it as `�` in the HTML instead of the literal character
Before v2.1.267, Claude Code uploaded such a file without checking it, and the server refused the publish instead.
[](#reading-a-local-file-from-outside-the-connected-folders)
Reading a local file from outside the connected folders in a Cowork session
In a [Cowork](https://claude.com/docs/cowork/overview) session running on your machine in the Claude Desktop app, Claude named a local file for an [artifact](artifacts.md). Claude Code couldn’t confirm the file is a plain file inside the session’s connected folders: the path sits outside those folders, passes through a symbolic link, or is spelled in a way that can name a different file than it appears to. Reading such a file needs your approval, and in a session that can’t show you the approval card, such as one set to skip all approvals, Claude Code refuses the read. The refusal appears in the Artifact tool result; when the file couldn’t be examined at all, it names that failure instead:
```python
Reading a local file from outside this session's connected folders, or through a link, needs the approval card, and no one can answer it in this Cowork session. Use a plain file inside the connected folders; do not retry this file in this session.
cannot read file_path (ENOENT) — the file could not be examined, and no one can answer the approval card in this Cowork session. Check that the file exists as a plain file inside the connected folders, then retry with that path.
```
**What to do:**
- Usually nothing: the message tells Claude to use a plain file inside the connected folders instead
- To put that exact file in the artifact, copy it into one of the session’s connected folders as a regular file, not a symlink, and ask again
[](#webfetch-cannot-fetch-localhost)
WebFetch cannot fetch localhost
Claude called [WebFetch](tools-reference.md#webfetch-tool-behavior) with a URL whose hostname has no dot, such as `http://localhost:3000` or a bare intranet name like `http://wiki/`. WebFetch refuses these URLs before making any request:
```python
WebFetch cannot fetch localhost or other hostnames without a dot. To reach a local server, use Bash with curl instead.
```
**What to do:**
- Usually nothing: the message points Claude at `curl` through the Bash tool, which can reach local and intranet servers
Before v2.1.268, WebFetch reported these URLs with a generic `Invalid URL` error.
[](#background-session-errors)
Background session errors
[Background sessions](../09-Agents-Patterns/agent-view.md) run without an interactive terminal of their own, so commands that need one behave differently there. These messages appear in the transcript of a background session, in the terminal that attaches to one, in the session or shell you dispatch from, or, for the [worktree-guard entries](#write-or-command-blocked-because-the-path-cannot-be-safely-resolved) below, in any session isolated in a worktree or running a worktree-isolated subagent; where a message is specific to one surface, its entry says so.
[](#commands-refused-in-a-background-session)
Commands refused in a background session
Commands that open an interactive dialog can’t do so while no terminal is attached to a background session. `/install-github-app`, the `/mcp` settings list, and the authentication actions in the MCP server menu respond with a message. For `/install-github-app` and the `/mcp` settings list, the session also appears under **Needs input** in [agent view](../09-Agents-Patterns/agent-view.md) so you can find it, attach, and run the command again. While a terminal is attached, these commands work normally. Before v2.1.216, the session didn’t appear under **Needs input** after `/install-github-app` or the `/mcp` settings list was refused. In v2.1.213 through v2.1.215, the commands still worked while a terminal was attached, and the refusal message told you to attach and run the command again. From v2.1.208 through v2.1.212, Claude Code refused them even while a terminal was attached, with a message such as `Can't open MCP settings in a background session`; on those versions, run the command from a regular `claude` session instead, or upgrade. Before v2.1.208, they opened their dialog inside the background session. In v2.1.208 only, Claude Code also refused the `/model` picker in a background session, and `/upgrade` printed the upgrade URL instead of opening a browser. The wording names the command. The `/mcp` settings list reports:
```python
Can't open MCP settings while no terminal is attached to this background session. This session now shows "needs input" in agent view — open it and run /mcp to manage servers, or use `/mcp enable|disable|reconnect <server>` to steer without the panel.
```
**What to do:**
- Attach to the session from agent view and run the command again
- Or use the form the message names, such as `/mcp reconnect <server>`, `/mcp enable`, or `/mcp disable`, which work without attaching
[](#write-or-command-blocked-because-the-path-cannot-be-safely-resolved)
Write or command blocked because the path cannot be safely resolved
Claude addressed a file or working directory through a spelling that the [worktree-isolation guard](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated) can’t resolve to one verifiable location. The guard checks writes and command working directories in [any session isolated in a worktree](worktrees.md#how-claude-code-enforces-isolation), interactive or background, and in [worktree-isolated subagents](worktrees.md#isolate-subagents-with-worktrees). It resolves symlinks before checking that the operation doesn’t reach the shared checkout, and when resolution fails, it blocks the operation rather than letting it land there. The message names the path forms it refuses and how to retry:
```python
This write was blocked because the path is spelled in a form that cannot be safely resolved (for example through a symlink storing a raw dot segment, a network-share or device-namespace shape, or an unreadable ancestor directory). If the file is inside the worktree /path/to/worktree, address it by its direct symlink-free path instead.
```
A blocked command reports the same cause for its working directory and ends with `re-run the command from its direct symlink-free path`. Before v2.1.217, the guard compared path spellings without resolving symlinks, so these spellings weren’t blocked and a write routed through a symlink could land in the shared checkout. **What to do:**
- Usually nothing: the full message goes to Claude as a tool error, and Claude retries with the direct path it names. For a blocked file edit, the conversation view shows only a short `Error editing file` line; the full message appears in the transcript view, which you open with `Ctrl+O`. A blocked command prints it in its command output.
- If the block repeats on the same file, the path likely runs through a committed symlink whose target contains `..`, such as `docs/current -> ../README.md`; ask Claude to edit the target file by its real path instead of through the link
[](#write-or-command-blocked-because-the-path-names-a-network-location)
Write or command blocked because the path names a network location
Claude addressed a file or working directory through a path that names a drive that isn’t on your machine, a UNC share such as `\\server\share\file` or a `/net` automount path, while the session’s checkout is on a local disk. The same [worktree-isolation guard](#write-or-command-blocked-because-the-path-cannot-be-safely-resolved) can’t verify that such a path stays out of the shared checkout, so it blocks the operation. Isolating the session in a worktree doesn’t lift the block. The message names the form of path to use instead:
```python
This write was blocked because the path is network-shaped (a UNC share or /net automount spelling) while this session's checkout is local. Isolating cannot unblock it. If the file is genuinely inside the worktree /path/to/worktree, address it by its local, plainly-spelled path instead.
```
A blocked command reports the same cause for its working directory and ends with `re-run the command from its local, plainly-spelled path`. Before v2.1.217, the guard compared path text only, so addressing a file inside the checkout through a UNC or `/net` path wasn’t blocked. **What to do:**
- Usually nothing: Claude retries with the local spelling the message asks for
[](#command-blocked-by-the-worktree-isolation-checks)
Command blocked by the worktree isolation checks
Claude ran a Bash or Monitor command in a [session isolated in a worktree](worktrees.md#how-claude-code-enforces-isolation), and Claude Code refused it for one of two reasons:
- The command points git at the main checkout.
- Claude Code can’t verify from the command text that any git the command runs stays inside the worktree. A command that never names git can still be refused for this reason, because expanding a variable indirection such as `${!name}` or running a Bash function substitution such as `${ command; }` produces a value at runtime that can itself be a command.
The middle of the message names what couldn’t be verified:
```python
This session is isolated in the worktree /path/to/worktree, but this command evaluates ${!x@P} arithmetically inside a construct too complex to verify, which can run a command hidden in a variable's value. Refusing to run it — a worktree-isolated session's git operations must target its own worktree. Split it into plain, separate commands and run them from /path/to/worktree.
```
**What to do:**
- Usually nothing: Claude reads the message and rewrites the command the way its final sentence asks
- If a command you asked for keeps being refused, spell the flagged value literally: replace the indirection or substitution with its value, and run git as its own plain command from inside the worktree
- To act on the main checkout on purpose, run the command yourself in a terminal outside the session
[](#this-session-has-no-saved-transcript)
This session has no saved transcript
You attached to a stopped [background session](../09-Agents-Patterns/agent-view.md) that was backgrounded from another conversation with `←` or `/background` and stopped before its first response finished. Until that first response finishes, the conversation still lives only in the session it was backgrounded from, so `claude attach` refuses to start the stopped session rather than begin a blank conversation under the same session ID. The message ends with the `claude respawn` command for this session:
```python
This session has no saved transcript — it was stopped before its first response finished. If it was backgrounded from another conversation, that one is still intact; `claude respawn <id>` starts this one fresh.
```
Opening the same session’s row in [agent view](../09-Agents-Patterns/agent-view.md) shows `Press enter again to restart this session fresh` below the list instead, and a second `Enter` on the row restarts the session with an empty conversation. Before v2.1.212, opening the row showed the refusal message with no way to restart from agent view. Before v2.1.211, opening the stopped session silently started that blank conversation and could re-run the session’s original prompt. **What to do:**
- The conversation you backgrounded from is intact: resume it with [`claude --resume`](sessions.md) or keep working in it
- To start the stopped session fresh anyway, run `claude respawn <id>` with the ID from the message, or press `Enter` twice on its row in agent view
- If the session did finish a response and you still see this refusal on a version before v2.1.214, an unreadable folder in `~/.claude/projects` could make the transcript scan miss the saved conversation; update to v2.1.214 or later, which tolerates unreadable folders during the scan
[](#this-session-is-running-in-another-terminal)
This session is running in another terminal
You opened a stopped session’s row in [agent view](../09-Agents-Patterns/agent-view.md), and its saved conversation is already open in another live Claude Code process on this machine, so Claude Code refuses to start a second process that would write to the same transcript. Which message you see depends on [what holds the conversation](../09-Agents-Patterns/agent-view.md#opening-a-session-says-the-conversation-is-already-open):
```python
Can't open — this session is running in another terminal
This conversation is already open in another running Claude session — use that one, or close it and try again
```
- **`running in another terminal`**: a terminal holds the conversation, for example one where you resumed it with `claude --resume` or `/resume`. The row also shows `Open in a terminal`.
- **`already open in another running Claude session`**: another non-interactive Claude Code process holds it, for example a [background session](../09-Agents-Patterns/agent-view.md#the-supervisor-process) process for the same conversation that hasn’t exited yet.
Claude Code saves a reply you typed when opening the row and sends it as the session’s next prompt when the session next starts. **What to do:**
- Continue the conversation in the process that has it open, or exit that process and open the row again
Before v2.1.248, only the `already open in another running Claude session` refusal existed: a conversation resumed in a terminal didn’t count as open, and opening the row started a second Claude Code process writing to the same conversation.
[](#this-sessions-saved-conversation-is-no-longer-on-disk)
This session’s saved conversation is no longer on disk
You opened a [background session](../09-Agents-Patterns/agent-view.md) that ended while the background service was off, and [transcript cleanup](settings-reference.md#cleanupperioddays) has since removed its saved conversation, for example after the machine was off for weeks. Opening such a row normally [resumes its saved conversation](../09-Agents-Patterns/agent-view.md#sessions-show-as-failed-after-shutdown). With nothing left to resume, Claude Code refuses rather than re-run the session’s original prompt without asking:
```python
This session's saved conversation is no longer on disk (it ended while the background service was off, and old transcripts are cleaned up), so there is nothing to resume. `claude rm 7c5dcf5d` deletes the row; `claude respawn 7c5dcf5d` runs its original prompt again instead.
```
`claude attach <id>` prints this text. In agent view, the footer is shorter and ends with `ctrl+x deletes the row`. **What to do:**
- Run `claude rm <id>` to delete the row. When one of the [kept cases](../09-Agents-Patterns/agent-view.md#what-deleting-a-session-removes) applies, `claude rm` keeps the row and the worktree instead and names the reason
- To run the session’s original prompt again as a fresh conversation, run `claude respawn <id>`
Before v2.1.248, opening such a row re-ran the session’s original prompt instead of refusing, pulling a weeks-old task back into the foreground.
[](#worktree-has-commits-that-are-not-pushed-anywhere)
Worktree has commits that are not pushed anywhere
You tried to delete a [background session](../09-Agents-Patterns/agent-view.md#what-deleting-a-session-removes) whose worktree holds commits Claude Code can’t confirm are saved elsewhere. Claude Code keeps the worktree and the session row rather than destroy the commits unseen. `claude rm` names the branch and the unpushed commits, and says how to proceed:
```python
kept 7c5dcf5d — its worktree is still at “/home/you/project/.claude/worktrees/fix-login”
2 unpushed commits on “claude/fix-login”: a1b2c3d “Fix login flow” and 1 more. They exist on no remote, so deleting the worktree would lose them.
push them and run 'claude rm 7c5dcf5d' again, or discard the worktree and its commits: claude rm 7c5dcf5d --discard-unpushed a1b2c3d000000000000000000000000000000000@0123456789abcdef0123456789abcdef
```
When Claude Code can’t summarize the commits, the detail line reads `The worktree has unpushed commits` instead. In [agent view](../09-Agents-Patterns/agent-view.md), the session’s row shows `not deleted` with the same reason. Commits on a remote don’t block the delete. Neither do commits on the local copy of your `origin` remote’s default branch, as long as that branch is checked out in your main checkout, the repository directory itself rather than a worktree. **What to do:**
- To keep the commits, push the worktree’s branch, or merge it into the default branch checked out in your main checkout, then delete the session again
- To discard the commits, run the `claude rm <id> --discard-unpushed` command the message printed, or press `Ctrl+X` twice on the session’s row in agent view again. This removes the session and the worktree along with its branch, the unpushed commits, and any uncommitted changes. If the worktree has gained a commit since the refusal, Claude Code keeps it again and shows the updated state
- When the message says the worktree is also recorded by another finished session, deleting again doesn’t discard it: push the commits, then delete the session again
Before v2.1.268, `claude rm` put the commit summary on the `kept` line itself. When `claude rm` couldn’t summarize the commits, the `kept` line read `worktree has commits that are not pushed anywhere` in place of the summary. Before v2.1.260, the message didn’t name the branch or the commits, and deleting again was refused the same way: deleting the session without pushing meant removing the worktree yourself with `git worktree remove --force <path>`, then running `claude rm <id>` again. Before v2.1.248, the default branch checked out in your main checkout didn’t count: a branch you had already merged there still triggered this refusal until its commits reached a remote.
[](#terminal-host-process-died)
Terminal host process died
Each [background session’s](../09-Agents-Patterns/agent-view.md) terminal runs in a host process under the background service, and that process died while the service still held its connection, so the session couldn’t be reached. On Linux and WSL, the background service checks each host process every few seconds, marks the session failed when the process has exited but its connection to the service never closed, and shows the reason on its row in [agent view](../09-Agents-Patterns/agent-view.md#read-session-state):
```python
terminal host process died — press Enter to restart
```
If you open the row before the check runs, the footer shows `This session's terminal host process died (the conversation is saved) — press Enter to restart it` and the row turns failed. From the shell, `claude attach <id>` restarts a session already marked failed for a dead host, and otherwise prints the cause and exits:
```python
Couldn't attach to <id> — This session's terminal host process died (the conversation is saved) — run `claude attach <id>` again to restart it on a fresh host.
```
The conversation is saved either way. A row running a [shell command](../09-Agents-Patterns/agent-view.md#run-a-shell-command) instead shows `terminal host process died — its output is gone; the command was not run again`, and `claude attach` prints `This command's terminal host process died — its output is gone and the command was not run again`. Claude Code never reruns the command for you. **What to do:**
- In agent view, press `Enter` on the failed row; the session restarts on a fresh host process and the conversation resumes
- From the shell, run `claude attach <id>` again. Claude Code prints `Session <id>'s terminal host died — restarting it on a fresh one…` and reopens the session
- You can’t restart a shell-command row this way; dispatch the command again to rerun it
Before v2.1.247, a dead host process could pass every liveness check the background service ran, so opening the session showed `opening… · esc to cancel` indefinitely and `claude attach <id>` waited without reporting an error.
[](#session-isnt-responding)
Session isn’t responding
You opened a [background session](../09-Agents-Patterns/agent-view.md) and the background service accepted the open, but no output arrived for about ten seconds, so Claude Code concludes that the process relaying the session’s terminal can’t deliver output, and ends the attempt instead of waiting. In agent view, Claude Code offers a restart in the footer:
```python
Press enter again to restart this session — it isn't responding (its conversation is saved and resumes).
```
From the shell, `claude attach <id>` prints the cause and exits:
```python
Couldn't attach to <id> — Session isn't responding — `claude stop <id>`, then `claude attach <id>` restarts it (the conversation is saved).
```
Claude Code never restarts a row running a [shell command](../09-Agents-Patterns/agent-view.md#run-a-shell-command) for you, because a restart would run the command again. **What to do:**
- In agent view, press `Enter` on the same row again. Claude Code stops the unresponsive process and restarts the session, and the conversation resumes. Nothing is stopped without that second press
- From the shell, run `claude stop <id>`, then `claude attach <id>`
- For a shell-command row, press `Ctrl+X` in agent view or run `claude stop <id>` to stop it; dispatch the command again to rerun it
[](#session-was-stopped-while-the-respawn-was-in-flight)
Session was stopped while the respawn was in flight
You opened a [background session](../09-Agents-Patterns/agent-view.md) whose process wasn’t running, and while Claude Code was restarting it, another Claude Code process stopped it, for example `claude stop` in another terminal. Claude Code keeps the session stopped:
```python
Session <id> was stopped while the respawn was in flight
```
Opening a session you just dispatched, while its process is still starting, waits for the process instead. Before v2.1.246, opening it at that moment could stop it and show this message. **What to do:**
- If you didn’t stop the session, open its row again in agent view or run `claude respawn <id>` to restart it
- If you stopped it yourself, nothing remains to do: the session stays stopped
[](#session-agent-no-longer-available)
Session agent no longer available
You resumed a session that was running a [custom agent](../09-Agents-Patterns/sub-agents.md#invoke-subagents-explicitly), started with `--agent` or the `agent` setting, and Claude Code didn’t find an agent by that name. It searches the session’s original directory first, when you have [trusted that workspace](permissions.md#project-allow-rules-and-workspace-trust), then the directory you resume from. The session still resumes, but with the default tools, so the agent’s tool restrictions no longer apply:
```python
This session was running agent 'code-reviewer', which is no longer available (no agent by that name in /home/you/project). Continuing with the default tools and system prompt — the agent's tool restrictions no longer apply. To restore it, re-create the agent, or resume with an explicit --agent <name>.
```
The warning names only the directories Claude Code searched, and it appears in the resumed conversation whether you wake a [background session](../09-Agents-Patterns/agent-view.md), run `/resume` or `claude --resume`, or resume in [non-interactive mode](headless.md), where it also goes to stderr. Sessions using `--input-format stream-json` don’t show it, because the Agent SDK supplies agents after startup. Claude Code doesn’t save the fallback to the session, so the warning repeats on each resume until you act. The built-in `claude` agent doesn’t trigger the warning, since falling back to the default toolset changes nothing for it. Before v2.1.216, Claude Code silently continued as the default agent, and the lookup covered only the directory you resumed from, so a project-scoped agent was lost on any resume from another directory. **What to do:**
- Re-create the agent file at `.claude/agents/<name>.md` in the session’s project, or at `~/.claude/agents/<name>.md` for a personal agent, then resume again
- Or resume with `--agent <name>` naming an agent that does exist, to run the session as that agent instead
- If the agent is project-scoped and you haven’t trusted the session’s original directory, run Claude Code there once, accept the trust dialog, then resume again
[](#claude_code_process_wrapper-launcher-errors)
CLAUDE_CODE_PROCESS_WRAPPER launcher errors
[`CLAUDE_CODE_PROCESS_WRAPPER`](../13-Enterprise-Admin/corporate-launcher.md) is set, and its value can’t be used, so Claude Code refuses to start the affected process rather than run it without the launcher. Configuration problems are reported with a message that starts with the variable name and states the reason, for example:
```python
CLAUDE_CODE_PROCESS_WRAPPER: launcher `/opt/corp/launcher` is not an executable regular file
```
A launcher that starts but exits without replacing itself with Claude Code fails the session it was starting, and the session’s row in agent view reports that the launcher `must exec, not daemonize`, followed by anything the launcher printed. A session that can’t start or reach the background service because of the launcher reports the launcher problem as the reason inside `Couldn't reach the background service (...)`. **What to do:**
- Set the variable to the absolute path of an executable that ends by calling `exec "$@"`. See [the launcher contract](../13-Enterprise-Admin/corporate-launcher.md#the-launcher-contract) for the full contract
- Check `/status`, which shows the resolved launch command in its Self-exec entry and warns when the running background service doesn’t match it, or run `claude daemon status` from a shell
- After fixing the value in the `env` block of [settings](../13-Enterprise-Admin/corporate-launcher.md#set-up-the-launcher), restart the background service with `claude daemon stop --any` so the next dispatch starts a wrapped one
[](#eunknown-when-starting-a-background-session)
EUNKNOWN when starting a background session
Windows refused to start a program with an error code that has no standard name, so the failure surfaces as `EUNKNOWN`. The usual trigger is a software restriction policy, such as Group Policy or AppLocker, blocking the program being started. The error appears when you start a [background session](../09-Agents-Patterns/agent-view.md) with `/background` or `claude --bg`:
```python
Couldn't reach the background service (spawn background service: EUNKNOWN: unknown error, uv_spawn) — run 'claude daemon status'
```
On some accounts the message says `daemon` in place of `background service`. On an npm installation, an `EUNKNOWN` that appears while `npm install -g @anthropic-ai/claude-code` is replacing the binary has the same cause as [`EACCES` during a reinstall](#eacces-when-starting-a-background-session) and clears when you retry after the install finishes. Claude Code starts the background service through PowerShell so the service survives closing the terminal, using PowerShell 7 when it’s installed and Windows PowerShell 5.1 otherwise. When neither PowerShell can run, Claude Code starts the service directly instead, so a policy that blocks only PowerShell doesn’t cause this error. Before v2.1.212, Claude Code used only Windows PowerShell 5.1 to start the service, so any machine where Group Policy blocked PowerShell 5.1 failed with `Couldn't start the session — EUNKNOWN: unknown error, uv_spawn`, even with PowerShell 7 installed. **What to do:**
- If the message reads `Couldn't start the session`, upgrade to v2.1.212 or later. On earlier versions you can also run `claude daemon run` in a separate terminal first, then start the background session again. That command runs the background service in the terminal’s foreground, so the service lasts only as long as that terminal stays open.
- If an npm install was replacing the binary, wait for it to finish, then start the background session again
- If the error appears on v2.1.212 or later while no npm install is running, check with your Windows administrator whether a restriction policy blocks the Claude Code executable
- If the background service stops when you close the terminal, Claude Code started it without PowerShell. Install PowerShell 7, or ask your administrator to unblock PowerShell, so the service can outlive the terminal.
[](#eacces-when-starting-a-background-session)
EACCES when starting a background session
Claude Code couldn’t run its own binary to start the [background service](../09-Agents-Patterns/agent-view.md#the-supervisor-process) that hosts background sessions. On an npm installation, this usually means `npm install -g @anthropic-ai/claude-code` was replacing the binary at that moment, whether you ran it or the [auto-updater](../01-Getting-Started/setup.md#auto-updates) did. The error appears when you open a session from [agent view](../09-Agents-Patterns/agent-view.md):
```python
Couldn't start the background service — spawn background service: EACCES: permission denied, posix_spawn '/usr/local/lib/node_modules/@anthropic-ai/claude-code/bin/claude'
```
When you start a session with `/background` or `claude --bg`, the same reason appears inside `Couldn't reach the background service (...)`. During the same reinstall window the error can name another code instead, such as `ENOENT` or `ENOEXEC`, or `EUNKNOWN` or `EPERM` on Windows; an `EUNKNOWN` that persists across retries has a [different cause](#eunknown-when-starting-a-background-session). On an npm installation, Claude Code waits for the reinstall to finish and retries on its own: up to ten seconds, and up to two minutes while an npm install of Claude Code is visibly still running on the machine, which covers another Claude Code process downloading an update. When the install outlasts that wait, the failure names the update instead of the bare error code:
```python
Claude Code is being updated by npm on this machine (still not runnable after 2 min, EACCES) — try again when the update finishes
```
Before v2.1.257, the wait stopped at ten seconds in every case, so this error appeared while another Claude Code process was still downloading an update. Before v2.1.246, Claude Code failed at once, without waiting. **What to do:**
- Wait a few seconds, then open the session or dispatch again. When the message says Claude Code is being updated, retry after the update finishes.
- If the error persists while no npm install is running, your user can’t run the installed binary. Check its permissions and its directory’s, or reinstall Claude Code.
[](#background-service-exited-before-it-became-reachable)
Background service exited before it became reachable
The process Claude Code started as the [background service](../09-Agents-Patterns/agent-view.md#the-supervisor-process) exited before it accepted connections, so Claude Code couldn’t open your session. When the service printed an error before exiting, the reason in parentheses gives the exit code or signal and the first line the service printed, which names what stopped it:
```python
Couldn't reach the background service (background service exited before it became reachable (exit code N): <the service's first error line>) — run 'claude daemon status'
```
When you open a session from [agent view](../09-Agents-Patterns/agent-view.md), the same reason follows `Couldn't start the background service —`. When the service printed nothing before exiting, the message says `nothing on stderr` instead. Claude Code reports the failure with the service’s error line. Before v2.1.246, the failure surfaced only after a 45-second wait, as `background service did not become reachable within 45s`, without the service’s error line. Two quoted reasons have known causes:
- `Error: claude native binary not installed.`: an npm install was replacing the Claude Code binary at that moment, so the service ran npm’s placeholder instead. Retry after the install finishes; if the line persists with no install running, [complete the npm install](troubleshoot-install.md#native-binary-not-found-after-npm-install). Before v2.1.257, a macOS npm self-update produced this failure on every start during the install window.
- `nothing on stderr` with exit code 1, on every start, on Windows: `daemon.lock` names a process that Claude Code can neither signal nor prove is gone, so each new service concludes another one holds the lock and exits. A lock whose writer Claude Code can prove is gone is replaced on its own and doesn’t produce this failure. When the failure repeats on every start, delete `~/.claude/daemon.lock`, then open the session or dispatch again. Before v2.1.257, such a lock blocked every start until you deleted the file.
**What to do:**
- If the message quotes a line, fix what it names, then open the session or dispatch again. The next attempt starts the service again
- Run `claude daemon status` to check whether a service is running now
[](#working-directory-no-longer-exists-when-starting-a-background-session)
Working directory no longer exists when starting a background session
The directory you started a [background session](../09-Agents-Patterns/agent-view.md) in was removed while the session was starting. Claude Code doesn’t start the session, and the message names the missing directory:
```python
Couldn't start a background session (working directory no longer exists or is not accessible: /tmp/demo)
```
Before v2.1.257, the session appeared to start and then showed in agent view as a failed row with the same reason. Before v2.1.281, this message also appeared when the directory was already gone before you started the session. That case reports [`could not be resolved on disk`](#workspace-not-trusted-when-dispatching-a-background-session). **What to do:**
- Recreate the directory the message names, or dispatch from a directory that exists, then try again
[](#workspace-not-trusted-when-dispatching-a-background-session)
Workspace not trusted when dispatching a background session
You started or restarted a [background session](../09-Agents-Patterns/agent-view.md) in a directory you haven’t [trusted](permissions.md#project-allow-rules-and-workspace-trust), and the workspace trust dialog couldn’t appear to ask you. Claude Code doesn’t start the session:
```python
Workspace not trusted. Run `claude` in /path/to/project once and accept the trust prompt, then retry.
```
From a terminal in the session’s own directory, the same command shows the trust dialog instead and starts the session once you accept. This message appears where no dialog can, such as in a script, or when you restart a session from a directory other than its own. Two variants name a different cause:
- **`The home directory is trusted one session at a time`**: the session’s directory is your home directory. Claude Code never saves trust for the home directory, so accepting the dialog there in an earlier session doesn’t count.
- **`<path> could not be resolved on disk`**: Claude Code couldn’t find the session’s directory on disk.
**What to do:**
- Run `claude` in the directory the message names and accept the trust dialog, then run the command again
- For the home-directory message, run the command from a terminal in your home directory so the dialog can appear, or start the session from a project directory instead
- For the `could not be resolved on disk` message, recreate the directory, or start a new session from a directory that exists
[](#wrapper-and-ide-errors)
Wrapper and IDE errors
These errors come from the program that launched Claude Code for you, such as an IDE extension or an [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) application, rather than from Claude Code itself.
[](#claude-code-process-exited-with-code-n)
Claude Code process exited with code N
The underlying `claude` process exited with a non-zero code. The exit code alone doesn’t say what failed: the real error is in the process’s own output, which the wrapper appends when it captured any and otherwise keeps in its logs.
```python
Error: Claude Code process exited with code 1
```
On Windows, the native build can exit with code `4294967295` right after a turn completes. When that exit lands at a turn boundary, with no message waiting and no background task running, the [VS Code extension](../03-IDE-Integrations/vs-code.md) closes the session quietly instead of showing this error. Your next message resumes the conversation. Before v2.1.273, the extension showed the error for that exit at every turn boundary, even though nothing was lost. **What to do:**
- In VS Code, follow the **View output logs** link shown with the error to see the underlying failure
- In an Agent SDK application, catch the error around your message loop. The entries under [CLI process exit](../05-Agent-SDK/agent-sdk-troubleshooting.md#cli-process-exit) cover what your code receives in each SDK language.
- Run `claude` in a terminal in the same project. The failure usually reproduces there with its real error message, which you can then look up on this page.
- Run `claude doctor` in a terminal to check the installation and configuration
[](#could-not-locate-the-claude-cli-on-path)
Could not locate the Claude CLI on PATH
The [VS Code extension](../03-IDE-Integrations/vs-code.md) shows this error on Windows when you open Claude Code in the integrated terminal, the terminal’s shell is PowerShell, and the extension can’t find the installed `claude` executable on PATH. The extension refuses to launch Claude Code until it finds the installed `claude` on PATH.
```python
Failed to run Claude Code: Error: Could not locate the Claude CLI on PATH. Launching by name in a PowerShell terminal would run a 'claude' from the open folder instead of the installed CLI, so the launch was blocked. Make sure the Claude CLI's install directory is on your system PATH (not only your PowerShell profile), then restart VS Code and try again. VS Code reads PATH when it starts, so PATH changes take effect only after a restart.
```
**What to do:**
- Open a new PowerShell window outside VS Code and run `where.exe claude`. If it doesn’t print a path, the CLI isn’t on your PATH: add its install directory by following [Verify your PATH](troubleshoot-install.md#verify-your-path). If it prints a path, the entry comes from your PowerShell profile or from a PATH change VS Code hasn’t picked up yet; the next two steps cover those cases.
- Set the PATH entry as a user or system environment variable, not in your PowerShell profile. The extension doesn’t run your profile, so a PATH edit that lives only there never reaches it.
- Restart VS Code after changing PATH. The extension checks the PATH that VS Code captured at startup, so a PATH change takes effect only after a restart.
[](#the-connection-to-claude-code-ended-before-this-message-completed)
The connection to Claude Code ended before this message completed
The [VS Code extension](../03-IDE-Integrations/vs-code.md) sent your message to the `claude` process, and the connection ended without an error before the process acknowledged or finished it. The extension can’t tell whether the message was processed, so it asks you to send it again:
```python
The connection to Claude Code ended before this message completed — it may not have been processed, so please send it again.
```
**What to do:**
- Send the message again. The next message starts a fresh `claude` process that resumes the conversation.
- If it repeats, run `claude` in a terminal in the same project. A failure that keeps ending the process usually reproduces there with its real error message.
[](#rewind-warnings-and-errors)
Rewind warnings and errors
These messages come from a [`/rewind`](checkpointing.md) code restore. `Restored the code, but skipped N files` is a warning that Claude Code skipped some paths. `No files were restored` is an error that means it restored nothing.
[](#restored-the-code-but-skipped-files)
Restored the code, but skipped files
A `/rewind` code restore skipped one or more tracked paths instead of writing or deleting through them. Claude Code skips a path when:
- it is, or became, a symlink, hard link, or other non-regular file
- its directory changed since the checkpoint
- its backup can’t be safely read
Skipped paths keep their current contents. Before v2.1.216, `/rewind` wrote and deleted through links at tracked paths, and didn’t report a partial restore.
```python
Restored the code, but skipped 2 files: the tracked path is (or became) a link or other non-regular file, its directory changed since the checkpoint, or its backup could not be safely read. Skipped files were left untouched — run with --debug for the paths.
```
**What to do:**
- Identify which files were skipped so you can handle each one with the steps below. The message gives only a count; the debug log at `~/.claude/debug/<session-id>.txt` names each skipped path as the restore runs, so turn on debug logging with `/debug` before your next restore. On macOS or Linux, you can instead find the links directly: `find . -type l` for symlinks and `find . -type f -links +1` for hard-linked files.
- If a skipped file is a link you created on purpose, such as a config file managed by a dotfile manager or a file hard-linked by tools like pnpm, the rewind left its contents alone. To undo the session’s changes to it, ask Claude to reverse the edit or edit the file yourself
- If you didn’t create the link, inspect the path before trusting its contents
[](#no-files-were-restored)
No files were restored
Claude Code shows this message when you restore code with [`/rewind`](checkpointing.md) and it can’t restore any of the files in that checkpoint. For each file, either the backup Claude Code saved before editing it is missing, or Claude Code couldn’t write to or delete the file.
```python
Failed to restore the code:
No files were restored: 1 file failed (backup missing, or the file could not be updated)
```
Claude Code deletes a session’s backups in the [retention sweep](claude-directory.md#cleaned-up-automatically), by default about 30 days after the session last saved one. If you resume a session after that, `/rewind` still lists its checkpoints, but rewinding to one of them can fail with this error. If the message also says `N paths were skipped for link safety`, see [Restored the code, but skipped files](#restored-the-code-but-skipped-files) for those paths. When you fork a session, for example with [`--fork-session`](cli-reference.md#cli-flags) or [`/branch`](sessions.md#branch-a-session), Claude Code copies the original session’s backups into the fork. When Claude Code can’t copy a backup, for example because the disk is full, that backup is missing in the fork. Rewinding to a checkpoint that needs it can fail with this error. **What to do:**
- Undo the changes another way: ask Claude to reverse its edits, or restore the files from version control. When the backups are gone, running `/rewind` again fails the same way.
- If Claude Code couldn’t write or delete a file, fix what blocks the write, such as file permissions, then run `/rewind` again.
- To keep backups longer in future sessions, raise [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays).
Before v2.1.260, Claude Code silently skipped files whose backups were missing, and the rewind appeared to succeed.
[](#session-saving-warnings)
Session saving warnings
Claude Code shows these warnings on a persistent line below the input box when it isn’t saving your session transcript. The session keeps working either way; the warnings tell you the session may be missing from [`--resume`](sessions.md) later.
[](#transcript-writes-are-failing)
Transcript writes are failing
Claude Code saves the transcript to disk as you work, and its writes to [the transcript file](sessions.md#where-transcripts-are-stored) are failing. The message names the cause with the underlying error code, for example a full disk:
```python
Transcript writes are failing (disk full — ENOSPC) · recent messages may not be saved for resume
```
The warning appears at different points depending on the error:
- On the first failure for conditions that don’t clear on their own: a full disk, an exceeded disk quota, a read-only filesystem, a path over the filesystem’s length limit, or, on macOS and Linux, a permission error
- After repeated failures spanning at least a minute for everything else, including permission errors on Windows, where an antivirus scan can fail a single write that then succeeds on retry
Before v2.1.217, Claude Code dropped the failing writes without a warning, and a later `--resume` missing recent messages was the first sign. **What to do:**
- Fix the condition the error code names: free disk space for `ENOSPC`; raise or clear the quota for `EDQUOT`; restore write access to the transcript location for `EACCES`, `EPERM`, or `EROFS`
- The warning clears on its own at the next successful write; no restart is needed
- Messages sent while the warning was showing may still be missing when you resume the session later
[](#transcript-saving-is-off-skip-prompt-history)
Transcript saving is off because CLAUDE_CODE_SKIP_PROMPT_HISTORY is set
This session started with [`CLAUDE_CODE_SKIP_PROMPT_HISTORY`](env-vars.md) set, so Claude Code writes no transcript or prompt history for it:
```python
Transcript saving is off — CLAUDE_CODE_SKIP_PROMPT_HISTORY is set · --resume will not find this session; if unintended, unset it and restart
```
The variable is an intentional opt-out for ephemeral scripted sessions, but it can also reach a session through a shell profile, a wrapper script, or a parent process that exported it. **What to do:**
- If you set the variable on purpose, no action is needed; the notice confirms the session won’t appear in `--resume`, `--continue`, or up-arrow history
- If you didn’t, remove the variable from the shell or script that launches `claude`, then start a new session. Messages from the current session aren’t saved retroactively.
[](#transcript-saving-is-off-child-session-marker)
Transcript saving is off because of an inherited CLAUDE_CODE_CHILD_SESSION marker
Claude Code sets [`CLAUDE_CODE_CHILD_SESSION`](env-vars.md) in the subprocesses it spawns, and treats an interactive session that inherits it as nested: Claude Code saves no transcript for it, so sessions that Claude itself starts don’t fill your `--resume` list. This notice means your current session inherited the marker:
```python
Transcript saving is off — inherited CLAUDE_CODE_CHILD_SESSION marker · restart with CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1 to keep future transcripts
```
The notice is expected when you ran `claude` from inside another Claude Code session; it signals a misclassification when the marker leaked through a long-lived intermediary, for example a terminal, `screen` session, or launcher that a Claude Code session originally started. Inside tmux, Claude Code detects a marker that arrived through the tmux server’s global environment and keeps saving, so this notice doesn’t appear for that case. **What to do:**
- If you started this session from inside another Claude Code session on purpose, no action is needed
- If this is a top-level session, exit and restart with [`CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1`](env-vars.md) set. Saving applies from the restart, so messages sent before it aren’t saved.
- To fix future launches from the same terminal or launcher, remove `CLAUDE_CODE_CHILD_SESSION` from its environment
[](#configuration-warnings)
Configuration warnings
Claude Code writes most of these messages to stderr, not into the conversation, and writes most of them at startup. An entry says so when its message appears somewhere else, such as in the debug log or as a startup notice in the conversation view, or at another time, such as the [unrecognized-model diagnostic line](#unrecognized-model-id-on-a-request) at request time.
[](#fullscreen-failed-start-notice)
Fullscreen renderer didn’t finish starting
A previous [fullscreen](fullscreen.md) session on this machine exited before it finished starting, so Claude Code starts this session on the classic renderer and prints one of these notices:
```python
Claude Code's fullscreen renderer didn't finish starting last time on this machine, so this launch is using the classic renderer. It will try fullscreen again next launch; /tui default keeps the classic renderer.
Claude Code's fullscreen renderer has repeatedly failed to start on this machine, so it has been turned off here. Run /tui fullscreen to try it again (this also resets after an update).
```
**What to do:**
- Follow [Fullscreen rendering](fullscreen.md#fullscreen-renderer-didnt-finish-starting). It says which notice you get, what Claude Code does in later sessions, and how to try fullscreen again or keep the classic renderer.
- If the session that died printed an exit message, see [Claude Code exited after an unrecoverable interface error](#exited-after-an-unrecoverable-interface-error) for what it names.
Before v2.1.236, Claude Code printed no notice and kept starting sessions in fullscreen rendering after a failed start.
[](#exited-after-an-unrecoverable-interface-error)
Claude Code exited after an unrecoverable interface error
Claude Code prints this message when it exits because its terminal interface hit an error it can’t recover from, in either renderer. The second sentence appears only when the error happened while the [fullscreen](fullscreen.md) renderer was starting:
```python
Claude Code exited after an unrecoverable interface error (<error>). It happened while the fullscreen renderer was starting, so the next launch will use the classic renderer (CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1 forces that any time).
```
**What to do:**
- Start Claude Code again. To pick the conversation back up, run `claude --resume` in the same directory.
- If the message names the fullscreen renderer, [Fullscreen rendering](fullscreen.md#fullscreen-renderer-didnt-finish-starting) says what the next launch does, which depends on how you turned fullscreen on, and how to try fullscreen again or keep the classic renderer.
Before v2.1.236, Claude Code exited without printing a message after this kind of error.
[](#agent-descriptions-are-over-the-15000-token-limit)
Agent descriptions are over the 15.0k-token limit
Claude Code shows this warning as a startup notice in the conversation view rather than on stderr. The combined descriptions of your [subagents](../09-Agents-Patterns/sub-agents.md), except the built-in ones, exceed 15,000 tokens as Claude Code estimates them. Each agent counts its name plus its `description` frontmatter. Claude Code loads every agent whether or not the total is over the limit, so the warning doesn’t change what loads.
```python
Agent descriptions are over the 15.0k-token limit (~16.2k tokens) · ask Claude to trim agent descriptions in .claude/agents/
```
**What to do:**
- Shorten the `description` frontmatter of your agent files, or ask Claude to trim them for you.
- Remove agent files you no longer use.
[](#a-skill-command-or-workflow-wasnt-loaded-because-its-name-is-reserved)
A skill, command, or workflow wasn’t loaded because its name is reserved
A skill folder, a frontmatter `name`, a file or subfolder in `.claude/commands/`, or a [saved workflow](workflows.md#save-the-workflow-for-reuse) uses the name `anthropic-skills` or a name that starts with `anthropic-skills:`. Claude Code [reserves that name for skills synced from claude.ai](../08-Plugins-Skills/skills.md#names-reserved-for-synced-skills) and doesn’t load that item. Claude Code shows this warning as a startup notice in the conversation view rather than on stderr:
```python
Not loaded: rename .claude/skills/anthropic-skills, then restart — its name uses "anthropic-skills", a name reserved for the skills synced from your claude.ai account
```
The notice names what to change for the first item it refused: a folder or file to rename, a `name:` line to edit, or a workflow to rename. When more than one item was refused, the notice ends with a count such as `· 2 more`, and the [debug log](debug-your-config.md) names each one. **What to do:**
- Rename the item the notice names, or edit the `name:` line it points to, then restart the session.
Before v2.1.282, Claude Code loaded skills and commands with these names.
[](#workspace-has-not-been-trusted)
Workspace has not been trusted
Claude Code found `permissions.allow` rules or `permissions.additionalDirectories` entries in the project’s `.claude/settings.json` or `.claude/settings.local.json` and didn’t apply them, because [allow rules from project settings require workspace trust](permissions.md#project-allow-rules-and-workspace-trust). The count, the setting name, and the file named in the message vary with your configuration. `deny` and `ask` rules aren’t affected.
```python
Ignoring 2 permissions.allow entries from .claude/settings.local.json: this workspace has not been trusted. Run Claude Code interactively here once and accept the trust dialog, or set projects["/Users/you/project"].hasTrustDialogAccepted: true in /Users/you/.claude.json.
```
**What to do:**
- Run `claude` in the directory and accept the trust dialog. [Project allow rules and workspace trust](permissions.md#project-allow-rules-and-workspace-trust) says which folder that acceptance covers.
- In [non-interactive mode](headless.md) with `-p` no dialog is shown. Set the `hasTrustDialogAccepted` entry in `~/.claude.json` using the exact `projects` key the message prints.
- If the message names `.claude/settings.local.json` and you started Claude Code outside a git repository or in your home directory, update to v2.1.200 or later. Versions 2.1.196 through 2.1.199 treated your own `.claude/settings.local.json` as repository-supplied in those workspaces. On v2.1.207 and later, updating isn’t enough outside a git repository if you haven’t trusted the folder: determining that a folder isn’t inside a repository runs git, and Claude Code runs that check only after you accept the trust dialog, so use the first step. Your home directory and any other [configuration home](permissions.md#project-allow-rules-and-workspace-trust) are exempt and don’t wait for the dialog. See [Project allow rules and workspace trust](permissions.md#project-allow-rules-and-workspace-trust).
[](#working-directory-is-a-network-path)
Working directory is a network path
Claude Code doesn’t add network paths as working directories. Looking up a network path can contact the host it names, and on Windows that contact can send the host your credentials, so Claude Code refuses the path without looking it up. You see this message when you run `/add-dir` with such a path, or as a warning at startup. When it appears at startup, Claude Code starts without that directory.
```python
\\server\share is a network path, which cannot be added as a working directory. On Windows, map the share to a drive letter and pass it at launch with --add-dir (a drive letter added mid-session does not yet carry remote-read trust).
```
Paths that Claude Code refuses this way include:
- UNC shares such as `\\server\share`
- Automount paths such as `/net/<host>`, unless you launched Claude Code from a directory under that host’s automount
- Local paths that reach a network location through a symbolic link or junction
Mapped drive letters and `\\wsl$` paths don’t count as network paths. **What to do:**
- On Windows, map the share to a drive letter, for example with `net use Z: \\server\share`, and pass the drive at launch with `claude --add-dir Z:\`.
- On macOS or Linux, mount the share at a local path and add that path instead.
- If the path is in `permissions.additionalDirectories`, remove it from the settings file that lists it.
Before v2.1.257, Claude Code accepted a reachable network path as a working directory.
[](#remote-managed-settings-failed-to-load)
Remote managed settings failed to load
Your session is eligible for [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), but Claude Code couldn’t fetch them or couldn’t apply what the server returned, so it shows this warning in interactive sessions. The parenthesized cause names what failed, such as `network error`, `request timed out`, or `authentication rejected (401)`. The cause `no setting in the server response could be applied as written` means the server answered but none of the settings it returned passed [validation](../13-Enterprise-Admin/server-managed-settings.md#invalid-entries-in-delivered-settings). Before v2.1.282, this cause read `server returned invalid settings`. The rest of the line says which policy the session runs on:
- **Settings cached from an earlier successful fetch**: Claude Code runs the session on that cached policy, except the [withheld environment variables](../13-Enterprise-Admin/server-managed-settings.md#fetch-and-caching-behavior), and the line reads `using cached policy`.
- **No cache**: Claude Code runs the session without server-managed settings, and the line reads `no remote policy applied`.
**What to do:**
- Act on the cause the message names: for a network cause, check that this machine can reach `api.anthropic.com`; for an authentication cause, check your sign-in with `/status`
- For `no setting in the server response could be applied as written`, ask your administrator to correct the settings on the server
- Run `/status` or `claude doctor` for the full diagnostic
Before v2.1.248, Claude Code reported a failed settings fetch only in the debug log.
[](#managed-settings-were-not-approved)
Managed settings were not approved
Your organization’s [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) include settings that need your approval, and you declined the [security approval dialog](../13-Enterprise-Admin/server-managed-settings.md#security-approval-dialogs), so Claude Code exits without applying them:
```python
Managed settings were not approved; exiting without applying them.
```
**What to do:**
- Start Claude Code again and approve the dialog to continue under your organization’s settings. A declined dialog isn’t remembered, so it appears again at the next start.
- If you’re unsure about a setting the dialog lists, ask whoever maintains your organization’s managed settings before approving
[](#managed-settings-block-the-default-model)
Managed settings block the default model
Your organization’s [managed settings](../13-Enterprise-Admin/managed-settings.md) block the model the Default option resolves to and every model it could step down to. A session that would start on the Default option exits at startup instead of running a blocked model. Which message you see depends on the setting that blocks it. When a [`deniedModels`](model-config.md#block-specific-models-or-versions) list blocks it, the message reads:
```python
Claude Code can't start: your organization's managed settings block the default model (claude-opus-5-5) in "deniedModels", and none of the models they allow can be used as the default instead. Ask your administrator to update "deniedModels" or "availableModels".
```
When an `availableModels` list with [`availableModelsMatch`](settings-reference.md#availablemodelsmatch) set to `"exact"` omits it, the message reads:
```python
Claude Code can't start: your organization allows only the models listed in "availableModels", and none of them can be used as the default model (claude-opus-5-5 isn't listed). Ask your administrator to update "availableModels".
```
**What to do:**
- If you administer the settings, add a model your users can run to `availableModels`, or narrow the `deniedModels` entries that block every fallback. [Block specific models or versions](model-config.md#block-specific-models-or-versions) describes how the Default option steps down
- If you don’t administer them, send the message to your administrator. Your own settings files can’t widen a managed `availableModels` or `deniedModels` list
[](#mcp-server-is-blocked-by-enterprise-managed-policy)
MCP server is blocked by enterprise managed policy
You selected **Reconnect** on a server in `/mcp`, or turned a disabled server back on there, and a setting that [restricts MCP servers](../06-MCP-Tools/General/managed-mcp.md) blocks that server. Claude Code refuses to connect it and shows:
```python
MCP server <name> is blocked by enterprise managed policy
```
Any of these settings can produce the message:
- A [`deniedMcpServers`](../06-MCP-Tools/General/managed-mcp.md#policy-based-control-with-allowlists-and-denylists) entry that matches the server, including one in your own `~/.claude/settings.json` or the project’s `.claude/settings.json`
- An [`allowedMcpServers`](../06-MCP-Tools/General/managed-mcp.md#policy-based-control-with-allowlists-and-denylists) list that the server doesn’t match
- [`strictPluginOnlyCustomization`](settings-reference.md#strictpluginonlycustomization) with `mcp` locked, which blocks servers configured in `~/.claude.json` and `.mcp.json`
- [`disableClaudeAiConnectors`](../06-MCP-Tools/General/mcp.md#disable-claude-ai-connectors), when the server is a claude.ai connector
**What to do:**
- Check your own user and project settings files for one of these settings and change or remove it
- If none of your own settings explains the block, ask your administrator which managed setting blocks the server
Before v2.1.257, **Reconnect** and re-enable in `/mcp` could connect a server that a mid-session policy update blocked.
[](#managed-settings-document-could-not-be-parsed)
Managed settings document could not be parsed
Your organization deploys [managed settings](../13-Enterprise-Admin/managed-settings.md), and one of the deployed documents is present but can’t be parsed as a JSON object, so Claude Code exits with code 1 at startup instead of running without the policy the document carries. The line names the failed source before the message:
```python
/Library/Application Support/ClaudeCode/managed-settings.json: Managed settings document could not be parsed as a JSON object; none of its settings are in effect. Fix or remove it.
```
The source is one of:
- The path of the `managed-settings.json` file or a drop-in file under `managed-settings.d`
- The macOS managed preferences profile, `per-user managed preferences` or `device-level managed preferences`
- The Windows registry value, `Registry: HKLM\SOFTWARE\Policies\ClaudeCode\Settings`
[Find entries Claude Code dropped](../13-Enterprise-Admin/managed-settings.md#find-entries-claude-code-dropped) lists what makes each source unparseable. Claude Code refuses to start even when another admin source delivers a valid policy. You see this error in interactive sessions, `claude -p`, Agent SDK sessions, [background sessions](../09-Agents-Patterns/agent-view.md), and most subcommands, `claude doctor` included. The refusal fails closed on purpose: settings in a document Claude Code can’t parse can’t be enforced, and starting anyway would run sessions without the organization’s controls. A schema problem in a parseable document doesn’t produce this error. [Find entries Claude Code dropped](../13-Enterprise-Admin/managed-settings.md#find-entries-claude-code-dropped) covers what Claude Code does with one. When a `managed-settings.d/` directory exists but can’t be listed, Claude Code reports `Managed settings drop-in directory could not be read:` followed by the underlying error instead. [Find entries Claude Code dropped](../13-Enterprise-Admin/managed-settings.md#find-entries-claude-code-dropped) covers when a read failure exits at startup. **What to do:**
- If you administer the machine, fix the named document so it parses as a JSON object, or remove the file, profile, or registry value. An empty `managed-settings.json` counts as `{}` and doesn’t block launch.
- If you don’t, ask your administrator to fix the deployed document. Nothing in your own settings files causes or clears this error.
[](#otelheadershelper-failed)
otelHeadersHelper failed
Claude Code shows this warning as a notification in the terminal interface, once per interactive session, when the [`otelHeadersHelper`](settings-reference.md#otelheadershelper) script fails or prints output that doesn’t meet the [script requirements](../13-Enterprise-Admin/monitoring-usage.md#script-requirements). While the script keeps failing, exports fail and your telemetry backend receives nothing from the session. The text after `See /status:` says what failed, such as the script’s exit code followed by its error output:
```python
otelHeadersHelper failed; telemetry is not being exported. See /status: exited 1: token service unreachable
```
**What to do:**
- Run `/status` to read the failure detail.
- Fix the script so it exits 0 within 30 seconds and prints a JSON object of string header values on stdout. See [script requirements](../13-Enterprise-Admin/monitoring-usage.md#script-requirements).
- If your organization deploys the script through [managed settings](../13-Enterprise-Admin/managed-settings.md), ask whoever maintains them to fix it.
In [non-interactive mode](headless.md) with `-p`, the same failure appears on stderr as `otelHeadersHelper failed (OpenTelemetry export headers unavailable): <error>` instead.
[](#headershelper-not-run)
headersHelper not run
Claude Code connected an MCP server with its static `headers` alone and skipped the server’s [`headersHelper`](../06-MCP-Tools/General/mcp.md#use-dynamic-headers-for-custom-authentication), because the helper is a shell command and the folder has no saved trust. A folder gets saved trust when you set its entry in `~/.claude.json` by hand or, outside your home directory, when you accept the trust dialog for it in an interactive session. See [Trust a folder before its headersHelper runs](../06-MCP-Tools/General/mcp.md#trust-a-folder-before-its-headershelper-runs) for which servers this check applies to. Claude Code writes this line in [non-interactive mode](headless.md) only, once per server. In an interactive session it writes the same refusal to the debug log instead.
```python
MCP server 'internal-api': headersHelper not run — this workspace has no persisted trust; accept the trust dialog here once interactively, or set projects["/Users/you/project"].hasTrustDialogAccepted in /Users/you/.claude.json.
```
The `projects` key the message prints is the folder [Project allow rules and workspace trust](permissions.md#project-allow-rules-and-workspace-trust) says Claude Code keys the trust on. Accepting the trust dialog for a parent folder doesn’t satisfy the check, and a `-p` or SDK session doesn’t satisfy it either. **What to do:**
- Run `claude` in the folder the message names, accept the trust dialog, then run your `-p` or SDK command again
- Set the `hasTrustDialogAccepted` entry in `~/.claude.json` yourself, using the exact `projects` key the message prints
- If you started the session in your home directory, work from a project directory you have trusted. When you accept the trust dialog in your home directory, Claude Code holds that trust for the current session only.
[](#malformed-tool-content-rule)
Malformed Tool(content) rule
A [permission rule](permissions.md#permission-rule-syntax) in one of your settings files doesn’t have the shape `Tool` or `Tool(content)`, for example because text follows the closing parenthesis or one of the parentheses is missing. Claude Code skips the rule and lists it in the invalid-settings dialog when an interactive session starts, and in [`claude doctor`](debug-your-config.md#check-resolved-settings) output:
```python
Invalid permission rule "Bash(ls) x" was skipped: Malformed Tool(content) rule. Rules take the form Tool or Tool(content) and must end at the closing ")"; parentheses inside the content are literal
```
**What to do:**
- In the settings file listed with the message, rewrite the rule so it ends at its closing parenthesis, for example `Bash(ls *)` in place of `Bash(ls) x`
- Leave parentheses inside the content as they are. They’re literal, so a rule such as `Edit(./Finance (2024)/**)` is valid without escaping
Before v2.1.260, Claude Code reported a rule with unmatched parentheses as `Mismatched parentheses`.
[](#is-not-matched-by-file-permission-checks)
Is not matched by file permission checks
Claude Code found a `Write`, `NotebookEdit`, `MultiEdit`, or `Glob` [permission rule](permissions.md#read-and-edit) with a path in one of your [settings files](settings.md#where-settings-live), in [managed settings](../13-Enterprise-Admin/managed-settings.md), or in a `--allowedTools`, `--disallowedTools`, or `--settings` flag value. It checks file permissions against `Edit` and `Read` rules only, so it never consults a path rule that names one of the other file tools. It keeps the rule and changes nothing else; the warning names the rule, its source in parentheses, and the replacement to write:
```python
Permission deny rule (.claude/settings.json): Write(docs/**) is not matched by file permission checks — only Edit(path) rules are. Use Edit(docs/**) instead (Edit rules cover all file-editing tools).
```
**What to do:**
- Replace `Write(path)`, `NotebookEdit(path)`, and legacy `MultiEdit(path)` rules with `Edit(path)`. `Edit` rules cover all file-editing tools.
- Except in `--allowedTools`, where Claude Code accepts a `Glob` rule without warning, replace `Glob(path)` rules with `Read(path)`.
- Fix the rule at the source the warning names in parentheses: a settings file path, or the flag itself for `--allowed-tools` and `--disallowed-tools`. A `claude-settings-<hash>.json` path that doesn’t exist on disk stands for an inline `--settings` value. Fix the JSON you pass to that flag.
- Leave bare tool-name rules such as `Write` or `Glob` alone. Claude Code matches them at the [tool level](permissions.md#match-all-uses-of-a-tool) and doesn’t warn about them.
- If the source reads `managed policy settings`, forward the warning to whoever maintains your managed settings, since you can’t clear it yourself.
In a [background session](../09-Agents-Patterns/agent-view.md) or with `--output-format json` or `stream-json`, Claude Code writes the warning to the debug log instead of stderr, so machine-read output stays clean. Run with `--debug` to capture it at `~/.claude/debug/<session-id>.txt`. Before v2.1.210, Claude Code accepted these rules without a warning.
[](#has-a-wildcard-before-the-rest-of-the-command)
Has a wildcard before the rest of the command
Claude Code found a `Bash` allow rule whose `*` comes before a later word that determines which command it is, such as `Bash(git * main)` or `Bash(git -C * status *)`, in one of your [settings files](settings.md#where-settings-live), in [managed settings](../13-Enterprise-Admin/managed-settings.md), or in an `--allowedTools` or `--settings` flag value. The `*` matches any text, including options inserted at that position: `Bash(git * main)` also approves `git -c core.fsmonitor=<script> diff main`, where `-c` makes git run a program the command names. [Wildcard patterns](permissions.md#wildcard-patterns) shows the matching rules. The warning exists so you can narrow a rule whose wildcard is broader than you intended. Claude Code keeps the rule and changes nothing about how it matches; the warning names the rule and its source in parentheses:
```python
Permission allow rule (.claude/settings.json): Bash(git -C * status *) has a wildcard before the rest of the command, so it also matches any options inserted at that position and approves them without a prompt. For git, options such as -c and --exec-path can run arbitrary commands. Replace that * with the exact value you mean, or only use * after the subcommand (for example Bash(git status *)).
```
**What to do:**
- Replace the `*` before the subcommand with the exact value you mean: `Bash(git checkout main)` in place of `Bash(git * main)`.
- Move every `*` after the subcommand: `Bash(git status *)` in place of `Bash(git -C * status *)`. Write one rule per subcommand you want to allow.
- Fix the rule at the source the warning names in parentheses: a settings file path, or the `--allowed-tools` flag itself. A `claude-settings-<hash>.json` path that doesn’t exist on disk stands for an inline `--settings` value. Fix the JSON you pass to that flag.
- If the source reads `managed policy settings`, forward the warning to whoever maintains your managed settings, since you can’t clear it yourself.
Claude Code doesn’t warn about deny and ask rules with the same shape: it refuses or prompts for the extra commands they match rather than approving them. It also doesn’t warn about rules whose subcommand comes before the first `*`, such as `Bash(git commit *)`, or rules in which no word other than an option follows the `*`, such as `Bash(git *)`, or about `:*` prefix rules such as `Bash(git:*)`. In a [background session](../09-Agents-Patterns/agent-view.md) or with `--output-format json` or `stream-json`, Claude Code writes the warning to the debug log instead of stderr, so machine-read output stays clean. Run with `--debug` to capture it at `~/.claude/debug/<session-id>.txt`. Before v2.1.246, Claude Code accepted these rules without a warning.
[](#crosssessioninbound-must-be-one-of-accept-hold-refuse)
crossSessionInbound must be one of accept, hold, refuse
A settings file sets [`crossSessionInbound`](settings-reference.md#crosssessioninbound) to a value Claude Code doesn’t recognize, such as the typo `"reject"`. The warning’s second sentence depends on which file holds the value; in a user, project, local, or `--settings` file it reads:
```python
"crossSessionInbound" must be one of "accept", "hold", "refuse"; received "reject". This value was ignored; while it is present, cross-session messages are held for your approval instead of being delivered. Set it to one of the values above.
```
In [managed settings](../13-Enterprise-Admin/managed-settings.md), Claude Code treats the unrecognized value as `refuse`, the most restrictive value, and the warning says cross-session messages are turned away until an administrator fixes it. For how the hold combines with values in your other settings files, see [`crossSessionInbound`](settings-reference.md#crosssessioninbound). **What to do:**
- Set the key to `"accept"`, `"hold"`, or `"refuse"`, or remove it
- When the warning names managed settings, ask the administrator to fix the value
Before v2.1.248, Claude Code ignored an unrecognized value without warning.
[](#the-200k-limit-isnt-enforced)
The 200K limit isn’t enforced
You set [`CLAUDE_CODE_DISABLE_1M_CONTEXT=1`](env-vars.md), which normally makes [auto-compaction](model-config.md#default-auto-compact-thresholds) hold sessions on 1M-context models to a 200K window, but no compaction threshold caps this session at or below 200K, so the conversation can grow past it.
```python
CLAUDE_CODE_DISABLE_1M_CONTEXT is set, but the 200K limit isn't enforced for <model>, so this session can grow past it. To enforce it, set CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000 (or the autoCompactWindow setting).
```
Claude Code enforces the 200K limit on its own for every model it recognizes as having a native 1M window, and for model IDs it doesn’t recognize it compacts at the window it assumes. The warning appears when other configuration defeats that enforcement:
- The model ID isn’t one Claude Code recognizes, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) alias, and you set [`CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1`](env-vars.md) or raised the assumed window past 200K with [`CLAUDE_CODE_MAX_CONTEXT_TOKENS`](env-vars.md). In this case the message also offers `or update to a Claude Code version that recognizes <model>` as a remedy.
- A `context-1m` beta requested through [`ANTHROPIC_BETAS`](env-vars.md) or the [`--betas`](cli-reference.md#cli-flags) flag still asks the API for the 1M window on a model that accepts that beta, while nothing compacts the session at 200K
**What to do:**
- Set [`CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000`](env-vars.md), or the [`autoCompactWindow`](settings-reference.md#autocompactwindow) setting to `200000`, so auto-compaction compacts at the 200K boundary
- If the message names a model ID this version doesn’t recognize, run `claude update`. A version that recognizes the ID as a 1M-context model enforces the limit without further configuration.
- If you want the session to use the model’s full window instead, unset `CLAUDE_CODE_DISABLE_1M_CONTEXT`; the warning reports only that the 200K limit isn’t enforced
In a [background session](../09-Agents-Patterns/agent-view.md) or with `--output-format json` or `stream-json`, Claude Code writes the warning to the debug log instead of stderr.
[](#unrecognized-model-id-on-a-request)
Unrecognized model ID on a request
Claude Code sent a request for a model ID that your Claude Code version doesn’t recognize, and found no [`modelOverrides`](model-config.md#override-model-ids-per-version) entry that maps that ID to a model it does recognize. Claude Code still sends the request with the ID as you configured it, and doesn’t exit or switch models.
```python
[claude-code:unrecognized_model] {"model":"my-proxy-model","query_source":"sdk"}
```
In a script or harness that reads stderr, match on the `[claude-code:unrecognized_model]` prefix. After the prefix and one space, Claude Code writes a one-line JSON object. Claude Code can add fields to it in a later version, so ignore any field you don’t expect. It writes at least these two:
- `model`: the model string as you configured it
- `query_source`: the request path that used the model. Claude Code reports `sdk` for a `-p` run and a value that starts with `agent:` for a subagent.
Claude Code writes the line to one of two places, depending on how you run it:
- In [non-interactive mode](headless.md) with `-p`, Claude Code writes it to stderr under every `--output-format`, so you can parse stdout without filtering the line out
- In an interactive session or a [background session](../09-Agents-Patterns/agent-view.md), Claude Code writes it to the debug log instead; run with `--debug` to capture it at `~/.claude/debug/<session-id>.txt`
Claude Code writes the line once per model string per process. It writes a separate line for each further unrecognized ID, such as one that a [subagent](../09-Agents-Patterns/sub-agents.md#choose-a-model) or [background functionality](../17-Billing-Plans/costs.md#background-token-usage) uses. Claude Code doesn’t write the line for provider IDs it resolves to a model it recognizes, such as Amazon Bedrock `us.anthropic.claude-...` IDs, Google Cloud’s Agent Platform IDs with an `@` version suffix, and Microsoft Foundry deployment names that contain a Claude model ID. Claude Code checks the model behind an Amazon Bedrock [application inference profile ARN](amazon-bedrock.md#map-each-model-version-to-an-inference-profile) rather than the ARN itself. It writes no line for an ARN it can’t resolve, such as a mistyped one. **What to do:**
- If you set the ID on purpose, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) alias, add a [`modelOverrides`](model-config.md#override-model-ids-per-version) entry to your [settings file](settings.md#where-settings-live) with the ID as its value. Use an Anthropic model ID as the key, not a family alias such as `opus`. For `my-proxy-model` from the example line, add this entry:
``` shiki
{
"modelOverrides": {
"claude-opus-4-6": "my-proxy-model"
}
}
```
Claude Code then treats `my-proxy-model` as `claude-opus-4-6` and stops writing the line.
- If the ID names a model newer than your Claude Code version, run `claude update`
- If the ID is a typo, fix it in whichever of the [places you can set a model](model-config.md#setting-your-model) or [alias variables](model-config.md#environment-variables) holds it. If `query_source` starts with `agent:`, fix it where you set the [subagent’s model](../09-Agents-Patterns/sub-agents.md#choose-a-model) instead.
Before v2.1.233, Claude Code wrote no line when it sent a request for a model ID it didn’t recognize.
[](#stale-sandbox-mask-files-left-by-a-killed-session)
Stale sandbox mask files left by a killed session
`claude doctor` prints this warning in its diagnostics, and `/status` lists the same line. It appears on Linux and WSL2 when [sandboxing](sandboxing.md) is enabled with filesystem isolation on. While a sandboxed command runs, the sandbox holds a write denial on a file that doesn’t exist yet by creating a 0-byte read-only placeholder there, and removes it afterward. A session killed before that cleanup runs, for example by SIGKILL, leaves the placeholders behind. Later sessions bind them read-only again on every start, so a settings write such as saving “Yes, and don’t ask again” fails where one sits.
```python
- Stale sandbox mask files left by a killed session: /home/you/project/.claude/settings.local.json
Fix: Remove each with `rm <path>` while no other Claude Code session is running in that project — a 0-byte read-only file where a settings file belongs makes "Yes, and don't ask again" fail to save, and the sandbox binds it read-only again on every start
```
**What to do:**
- Quit any other Claude Code session running in that project, then delete each listed file with `rm`. The warning names up to three files and counts the rest, so rerun `claude doctor` after deleting until the warning no longer appears. A placeholder that another session’s sandbox is still using is a live part of that session’s write protection
- If a permission choice you saved with “Yes, and don’t ask again” didn’t stick, save it again after deleting the placeholder
Before v2.1.257, `claude doctor` didn’t flag these files; earlier versions leave the same placeholders behind when a session is killed.
[](#responses-seem-lower-quality-than-usual)
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 doesn’t silently change model versions. It can switch to a fallback model in three specific cases:
- A configured [`--fallback-model`](cli-reference.md#cli-flags) takes over after an availability error, for that turn only, with a notice in the transcript
- An Amazon Bedrock or Google Cloud’s Agent Platform startup check finds your default model unavailable
- [Automatic model fallback](model-config.md#automatic-model-fallback) on Fable 5.1, Fable 5, Opus 5.5, Sonnet 5.5, and Opus 5 moves the session to the flagged category’s fallback model, when that category has one, and shows a notice in the transcript
The Model selection check below catches the second and third cases; the first appears as a transcript notice rather than a `/model` change. [Model configuration](model-config.md) explains when each 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](model-config.md#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](context-window.md) 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. The `/doctor` checkup flags oversized memory files and unused extensions, and `/context` shows MCP tool token usage. Before v2.1.205, `/doctor` opened a diagnostics screen that flagged oversized memory files and subagent definitions.
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](checkpointing.md). 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](#report-an-error) if `/feedback` is unavailable in your environment. If Claude warns about a suspected prompt injection, or refuses a request because of a suspected injection, and the text the warning names is context Claude Code adds to the conversation automatically rather than file or web content, run `claude update` and retry. If the warning repeats after updating, [report it](#report-an-error) rather than pasting the flagged content back into the prompt. Before v2.1.201, Sonnet 5 refused some requests the same way.
[](#report-an-error)
Report an error
For errors from components this page doesn’t cover, see the relevant guide:
- MCP server failed to connect or authenticate: [MCP](../06-MCP-Tools/General/mcp.md)
- Hook script failed or blocked a tool: [Debug hooks](../07-Hooks/hooks.md#debug-hooks)
- Permission denied or filesystem errors during install: [Troubleshoot installation and login](troubleshoot-install.md)
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. Sending to Anthropic requires [authentication](../13-Enterprise-Admin/iam.md). On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and other third-party providers, or when no Anthropic credentials are configured, `/feedback` saves a local archive you can send to your Anthropic account representative instead.
- Run `claude doctor` from your shell for a read-only diagnostic of your installation, or run the `/doctor` checkup inside Claude Code to find and fix setup problems
- Check [status.claude.com](https://status.claude.com) for active incidents
- Search [existing issues](https://github.com/anthropics/claude-code/issues) on GitHub
---
## Speed up responses with fast mode - Claude Code Docs
Source: https://code.claude.com/docs/en/fast-mode
Path: 02-Claude-Code-CLI/fast-mode.md
## On this page
- [Toggle fast mode](#toggle-fast-mode)
- [Switch models while fast mode is on](#switch-models-while-fast-mode-is-on)
- [Use fast mode in cloud sessions](#use-fast-mode-in-cloud-sessions)
- [Understand the cost tradeoff](#understand-the-cost-tradeoff)
- [See where fast mode spend appears](#see-where-fast-mode-spend-appears)
- [Decide when to use fast mode](#decide-when-to-use-fast-mode)
- [Fast mode vs effort level](#fast-mode-vs-effort-level)
- [Requirements](#requirements)
- [Enable fast mode for your organization](#enable-fast-mode-for-your-organization)
- [Use fast mode behind proxies and LLM gateways](#use-fast-mode-behind-proxies-and-llm-gateways)
- [Require per-session opt-in](#require-per-session-opt-in)
- [Handle rate limits](#handle-rate-limits)
- [Research preview](#research-preview)
- [See also](#see-also)
Model and responses
# Speed up responses with fast mode
Copy pageCopy page
Get faster Opus responses in Claude Code by toggling fast mode.
Copy pageCopy page
Fast mode is in [research preview](#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 up to 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 with faster responses. Fast mode is supported on Opus 5.5, Opus 5, and Opus 4.8. It is not available on Sonnet, Haiku, or other models. Opus 4.7 doesn’t support fast mode, so switching to it turns fast mode off. Fast mode for Opus 4.7 was deprecated on June 25, 2026, and removed on July 24, 2026. What to know:
- Use `/fast` to toggle on fast mode in the Claude Code CLI. The [VS Code extension](../03-IDE-Integrations/vs-code.md) offers a **Toggle fast mode** command when the selected model supports fast mode. Claude Code saves that toggle to your [`fastMode` setting](#toggle-fast-mode).
- Fast mode pricing per MTok input/output is \$8/\$40 on Opus 5.5 and \$10/\$50 on Opus 5 and Opus 4.8.
- Available to Claude Code users on subscription plans (Pro/Max/Team/Enterprise) and on Claude Console. Team and Enterprise organizations need an Owner to enable it first, and Console organizations need access provisioned first, both described under [Requirements](#requirements).
- For Claude Code users on subscription plans (Pro/Max/Team/Enterprise), fast mode is available via usage credits only and not included in the subscription rate limits.
[](#toggle-fast-mode)
Toggle fast mode
In the CLI, toggle fast mode in either of these ways:
- Run `/fast`, press Space to toggle on or off, then press Enter to confirm
- Set `"fastMode": true` in your [user settings file](settings.md)
By default, fast mode you turn on in an interactive session persists across sessions. You can configure fast mode to reset each session. See [require per-session opt-in](#require-per-session-opt-in) for details. Outside a [cloud session](#use-fast-mode-in-cloud-sessions), in [non-interactive mode](headless.md) with the `-p` flag, `/fast` works only in a session launched with fast mode in its [`--settings`](cli-reference.md#cli-flags) value, for example `claude -p --settings '{"fastMode": true}'`; the toggle then applies to that session only and isn’t saved as your default. The `-p` form requires Claude Code v2.1.205 or later. Elsewhere in non-interactive mode, the command reports that fast mode isn’t available. You can run `/fast` while Claude is working, and Claude Code toggles fast mode without waiting for the turn to end. Claude Code finishes the running turn at its original speed, so the speed change takes effect from your next turn. If your current model doesn’t support fast mode, turning it on also switches your model, and Claude Code uses the new model from its next request in that turn. For the best cost efficiency, enable fast mode at the start of a session rather than switching mid-conversation. See [understand the cost tradeoff](#understand-the-cost-tradeoff) for details. When you enable fast mode:
- If your current model doesn’t support fast mode, Claude Code switches to Opus
- 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
Opus 5.5 is the fast mode default in Claude Code v2.1.280 and later. Before v2.1.280, fast mode defaulted to Opus 5 from v2.1.219, to Opus 4.8 on v2.1.154 through v2.1.218, and to Opus 4.7 on v2.1.142 through v2.1.153. When you disable fast mode with `/fast` again, you remain on Opus. To switch to a different model, use `/model`.
[](#switch-models-while-fast-mode-is-on)
Switch models while fast mode is on
Fast mode follows your model switches in both directions:
- **Switch away**: when you switch to a model that doesn’t support fast mode, Claude Code turns fast mode off. This includes Opus 4.7; before v2.1.221, fast mode stayed on after a switch to Opus 4.7 and the API rejected the requests.
- **Switch back**: switching back to a supported Opus model turns fast mode on again when your saved fast mode preference is on, the same preference a new session starts from by default. A model switch never turns fast mode on for a session whose saved preference is off, and with [per-session opt-in](#require-per-session-opt-in) configured, switching back doesn’t turn it on either; run `/fast` to re-enable it.
Whenever a model switch turns fast mode on or off, Claude Code shows a `Fast mode ON` or `Fast mode OFF` confirmation, and the `↯` icon appears while fast mode is on. This holds whether you switch with `/model`, with [`/config model=<model>`](settings.md), or from a device connected through [Remote Control](remote-control.md). Claude Code resends the session’s fast mode status to devices connected through Remote Control after a model switch, a reconnection, or a failed [availability check](#use-fast-mode-behind-proxies-and-llm-gateways).
[](#use-fast-mode-in-cloud-sessions)
Use fast mode in cloud sessions
Fast mode works in [cloud sessions](claude-code-on-the-web.md) when it’s available on your account, whether the session runs on Anthropic-managed infrastructure or a [self-hosted runner](../13-Enterprise-Admin/self-hosted-environments.md). Requires Claude Code v2.1.271 or later in the session’s environment. Type `/fast on` in the session to turn fast mode on. It stays on for that session only and isn’t saved as your default. The [requirements](#requirements) apply in cloud sessions too. In the browser at [claude.ai/code](https://claude.ai/code), you can also turn fast mode on and off from the model menu on the message box. The menu shows the switch when your plan includes fast mode and the selected model supports it.
[](#understand-the-cost-tradeoff)
Understand the cost tradeoff
Fast mode has higher per-token pricing than standard Opus:
| Model | Input (MTok) | Output (MTok) |
|----------|--------------|---------------|
| Opus 5.5 | \$8 | \$40 |
| Opus 5 | \$10 | \$50 |
| Opus 4.8 | \$10 | \$50 |
Fast mode pricing is flat across the full 1M token context window. For the standard Opus rate to compare against, see the [Claude pricing reference](../17-Billing-Plans/about-claude-pricing.md). The first time you enable fast mode in a conversation, you pay the full fast mode uncached input token price for the entire conversation context. The deeper into a conversation you are, the more this costs, so enabling fast mode from the start is cheaper. The cost applies once per conversation, so toggling fast mode off and on again later does not repeat it. For the mechanism, see [how fast mode interacts with the prompt cache](prompt-caching.md#turning-on-fast-mode).
[](#see-where-fast-mode-spend-appears)
See where fast mode spend appears
You see fast mode spend in a different place depending on how you signed in, so first run [`/status`](commands.md) to check. If it shows a `Login method` row such as `Claude Max account`, you signed in with a Claude subscription. If it shows an `API key` row instead, your requests bill to a Claude Console organization.
- **Pro and Max**: you pay for fast mode from your usage credits. Go to [**Settings \> Usage**](https://claude.ai/settings/usage) on claude.ai, where the **Usage credits** section shows how much you’ve spent in usage credits this month. That figure includes fast mode but doesn’t break it out separately.
- **Team and Enterprise**: your organization pays for your fast mode usage from its usage credits. To see your own usage-credits spend, run [`/usage`](../17-Billing-Plans/costs.md#check-your-usage-credits-spend). For where your organization sees that spend, see [Claude for Teams and Enterprise](../17-Billing-Plans/costs.md#claude-for-teams-and-enterprise).
- **Claude Console**: your organization pays for fast mode with the rest of its API usage. On the Console [Usage](../04-API-Reference/Other/usage-limits.md) and [Cost](../04-API-Reference/Other/usage-limits.md) pages, select **Speed (Research Preview)** in the **Group by** menu to separate fast mode from standard-speed usage. You see that option only when the selected date range includes fast mode usage.
[](#decide-when-to-use-fast-mode)
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 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](model-config.md#adjust-effort-level) for maximum speed on straightforward tasks.
[](#requirements)
Requirements
Fast mode requires all of the following:
- **Anthropic API or subscription only**: fast mode is available through the Anthropic Console API and for Claude subscription plans using usage credits. It is not available on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or Claude Platform on AWS. Console organizations must also have [fast mode access provisioned](#enable-fast-mode-for-your-organization).
- **Usage credits turned on for subscription plans**: on a Pro, Max, Team, or Enterprise plan, your account must have [usage credits](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription) turned on, which allows billing beyond your plan’s included usage. Until they’re on, `/fast` reports “Fast mode requires usage credits”. How you turn them on depends on your plan:
- On Pro and Max, turn them on in the **Usage credits** section of [**Settings \> Usage**](https://claude.ai/settings/usage) on claude.ai, or run `/usage-credits` to open that page.
- On Team and Enterprise, a member with billing access turns them on for the organization at [**Admin settings \> Usage**](https://claude.ai/admin-settings/usage), and a member without it runs `/usage-credits` to send the organization’s admins a request.
Fast mode usage draws directly from usage credits, even if you have remaining usage on your plan.
- **Paid Console organization**: Claude Console accounts don’t use usage credits, and your organization pays for fast mode per token with the rest of its API usage. On the Console’s free Evaluation plan, `/fast` shows “Fast mode unavailable during evaluation. Please purchase credits.” To clear it, purchase credits in your [Console billing settings](../04-API-Reference/Other/usage-limits.md).
- **Owner enablement for Team and Enterprise**: fast mode is disabled by default for Team and Enterprise organizations. An Owner must explicitly [enable fast mode](#enable-fast-mode-for-your-organization) before users can access it.
Four organization settings can block turning fast mode on with `/fast`:
- **Fast mode not enabled**: if fast mode hasn’t been enabled for your organization, turning fast mode on with `/fast` shows “Fast mode has been disabled by your organization.”
- **Fast mode turned off by managed settings**: if your organization deploys [managed settings](../13-Enterprise-Admin/managed-settings.md) that set [`fastMode: false`](settings-reference.md#fastmode), turning fast mode on with `/fast` shows the same “Fast mode has been disabled by your organization” message.
- **Per-session opt-in required**: managed settings that set [`fastModePerSessionOptIn: true`](#require-per-session-opt-in) refuse `/fast on` with the same message everywhere except an interactive terminal session.
- **Fast-mode model not allowed**: if your organization’s [`availableModels`](model-config.md#restrict-model-selection) allowlist excludes the fast-mode Opus model, turning it on is refused with “is not in your organization’s allowed models”. In a session already running on an allowed Opus model that supports fast mode, `/fast` instead enables fast mode on your current model without switching models.
[](#enable-fast-mode-for-your-organization)
Enable fast mode for your organization
Where you enable fast mode depends on which product your organization uses:
- **Console** (API customers): an admin enables it in [Claude Code preferences](https://platform.claude.com/claude-code/preferences). Fast mode is in [research preview](#research-preview), so your organization must also have fast mode access provisioned before fast mode requests succeed. To get access, contact your account manager or join the waitlist, as described in [fast mode on the Claude API](../04-API-Reference/Guides/build-with-claude-fast-mode.md). Without provisioned access, the API rejects each fast mode request with a 429, and Claude Code treats each rejection as a [fast mode rate limit](#handle-rate-limits). Unlike a rate limit’s cooldown, the rejections continue until access is provisioned.
- **Claude AI** (Team and Enterprise): an Owner enables it at [Admin Settings \> Claude Code](https://claude.ai/admin-settings/claude-code)
Another option to disable fast mode entirely is to set `CLAUDE_CODE_DISABLE_FAST_MODE=1`. See [Environment variables](env-vars.md).
[](#use-fast-mode-behind-proxies-and-llm-gateways)
Use fast mode behind proxies and LLM gateways
Before offering fast mode, Claude Code checks your organization’s fast mode availability with a request directly to `api.anthropic.com`. The check doesn’t follow [`ANTHROPIC_BASE_URL`](../13-Enterprise-Admin/llm-gateway-connect.md#set-the-base-url-and-credential), so on a network that routes Claude traffic through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) and blocks direct egress to `api.anthropic.com`, the check fails even though inference requests work. The check does use a configured [HTTP proxy](../13-Enterprise-Admin/network-config.md#proxy-configuration), so a network block fails the check only where `api.anthropic.com` is unreachable even through the proxy. When the check fails, `/fast` reports “Fast mode unavailable due to network connectivity issues”, and requests run at standard speed, even when your organization has fast mode enabled. A check that succeeded in the past keeps working from its cached result, so a blocked check mostly affects new installations. The same connectivity message appears on an open network when the check reaches `api.anthropic.com` but presents a credential Anthropic rejects. A session whose resolved key is a gateway-issued credential, held in [`ANTHROPIC_API_KEY`](../13-Enterprise-Admin/llm-gateway-connect.md#set-the-base-url-and-credential) or produced by an [`apiKeyHelper`](settings-reference.md#apikeyhelper), sends the check with that key, and the rejected request is reported as a connectivity failure. To restore fast mode, allowlist direct egress to `api.anthropic.com` where a network block is the cause, or set whichever variable matches how the check fails:
- `CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS=1` treats a failed check as available and still honors a “disabled by your organization” response. Use it when your network refuses the connection, or when Anthropic rejects a gateway credential; allowlisting doesn’t help the credential case, since nothing is blocked.
- `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1` skips the check entirely. Use it when your network intercepts the request rather than refusing it.
Two gateway configurations report “Fast mode has been disabled by your organization” rather than the connectivity message, even when your organization has fast mode enabled:
- A session that authenticates with [`ANTHROPIC_AUTH_TOKEN`](../13-Enterprise-Admin/llm-gateway-connect.md#set-the-base-url-and-credential) alone skips the check: without a claude.ai login or an Anthropic API key, and without a cached successful check, Claude Code treats fast mode as disabled by your organization without sending the request.
- A proxy that intercepts the check and answers with its own page, for example a TLS-inspecting proxy returning an HTTP 200 block page, is read as a response saying your organization has fast mode disabled.
In both cases, set `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1` to restore fast mode. `CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS` doesn’t apply to either case, since it only bypasses failed checks and both of these produce a disabled response instead. Allowlisting direct egress doesn’t help the bearer-token case, which never sends the request. The variables affect only the client-side check. When your organization has fast mode disabled, the API rejects fast mode requests whether or not they’re set. A rejection from the API stands even with a skip variable set. Claude Code retries the rejected request at standard speed, turns fast mode off, and `/fast` reports that your organization has disabled fast mode. Setting `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` also suppresses the availability check. Without a previously cached successful check, `/fast` reports “Fast mode is currently unavailable”; both skip variables restore fast mode in that configuration too.
[](#require-per-session-opt-in)
Require per-session opt-in
By default, fast mode a user turns on in an interactive session persists across sessions. To change this, set `fastModePerSessionOptIn` to `true` in any [settings file](settings.md#where-settings-live), which causes each session to start with fast mode off and requires users to explicitly enable it with `/fast`. Owners on [Team](../17-Billing-Plans/pricing.md#team-&-enterprise) or [Enterprise](https://anthropic.com/contact-sales?utm_source=claude_code&utm_medium=docs&utm_content=fast_mode_enterprise) plans can deploy it organization-wide through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md).
```python
{
"fastModePerSessionOptIn": true
}
```
This is useful for controlling costs in organizations where users run multiple concurrent sessions. The user’s fast mode preference is still saved, so removing this setting restores the default persistent behavior. When managed settings set the key, `/fast on` works only in an interactive terminal session. Everywhere else, including [non-interactive mode](headless.md), the [VS Code extension](../03-IDE-Integrations/vs-code.md), and [cloud sessions](#use-fast-mode-in-cloud-sessions), it’s refused with a message that your organization has disabled fast mode.
[](#handle-rate-limits)
Handle rate limits
Fast mode has separate rate limits from standard Opus. All supported Opus models share one fast mode rate limit pool: usage on any of them draws from the same limits. When you hit the fast mode rate limit:
1. Fast mode automatically falls back to standard speed
2. The `↯` icon turns gray to indicate cooldown
3. You continue working at standard speed and pricing
4. When the cooldown expires, fast mode automatically re-enables
To disable fast mode manually instead of waiting for cooldown, run `/fast` again. If you run out of usage credits mid-session, Claude Code retries each rejected fast mode request at standard speed and pricing, so you keep working, and there is no cooldown. How you see the rejection depends on the session type:
- In an interactive session, Claude Code shows a “Fast mode disabled · usage credits exhausted” notification and turns fast mode off for the rest of the session. Your saved fast mode preference doesn’t change; run `/fast` to turn fast mode back on.
- In [non-interactive mode](headless.md) with `--output-format stream-json`, and through the Agent SDK, Claude Code emits the same text on the message stream as a `system` message with subtype `notification`, once per turn while you’re out of usage credits. Fast mode stays on. Requires Claude Code v2.1.221 or later.
[](#research-preview)
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)
See also
- [Model configuration](model-config.md): switch models and adjust effort levels
- [Manage costs effectively](../17-Billing-Plans/costs.md): track token usage and reduce costs
- [Status line configuration](statusline.md): display model and context information
---
## Feature availability - Claude Code Docs
Source: https://code.claude.com/docs/en/feature-availability
Path: 02-Claude-Code-CLI/feature-availability.md
## On this page
- [Availability by model provider](#availability-by-model-provider)
- [Features available on every provider](#features-available-on-every-provider)
- [Features that require a Claude subscription](#features-that-require-a-claude-subscription)
- [CLI capabilities that vary by provider](#cli-capabilities-that-vary-by-provider)
- [Admin and analytics](#admin-and-analytics)
- [Summary by provider](#summary-by-provider)
- [Availability by subscription plan](#availability-by-subscription-plan)
- [Model availability](#model-availability)
- [Related resources](#related-resources)
Deployment
# Feature availability
Copy pageCopy page
Compare which Claude Code features are available across Anthropic subscription plans, the Anthropic Console, Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry.
Copy pageCopy page
The Claude Code CLI and everything that runs locally work on every provider. For setup instructions per provider, see the [Enterprise deployment overview](third-party-integrations.md). To skip straight to what is missing on your provider, see the [summary by provider](#summary-by-provider) tabs. In the tables below, ✓ means available, ✗ means not available, and “See note” links to a footnote for partial support. A qualifier after ✓ narrows availability to that subset, and “Admin-enabled” means the feature is off until an organization admin turns it on.
[](#availability-by-model-provider)
Availability by model provider
How you authenticate determines which features Claude Code can reach. For a single list of what is missing on your provider, see the [summary by provider](#summary-by-provider) tabs. To find your column in the tables:
- **Claude subscription**: you sign in with a claude.ai account on the Pro, Max, Team, or Enterprise plan
- **Anthropic Console**: you authenticate with an Anthropic API key or by [signing in to a Console account without one](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key)
- **Amazon Bedrock**: you use Claude models from the Amazon Bedrock model catalog and set `CLAUDE_CODE_USE_BEDROCK`. The [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint) (`CLAUDE_CODE_USE_MANTLE`) is covered by this column
- **Claude Platform on AWS**: you bought Claude through AWS Marketplace but call the Anthropic API, and set `CLAUDE_CODE_USE_ANTHROPIC_AWS`
- **Google Cloud’s Agent Platform**: Google-operated; you set `CLAUDE_CODE_USE_VERTEX`
- **Microsoft Foundry**: Anthropic-operated; you set `CLAUDE_CODE_USE_FOUNDRY`
[](#features-available-on-every-provider)
Features available on every provider
These work on every provider:
- [CLI](../01-Getting-Started/quickstart.md) and [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md)
- [VS Code](../03-IDE-Integrations/vs-code.md) and [JetBrains](../03-IDE-Integrations/jetbrains.md) extensions
- [Subagents](../09-Agents-Patterns/sub-agents.md), [hooks](../07-Hooks/hooks-guide.md), [commands](commands.md), and [skills](../08-Plugins-Skills/skills.md)
- [CLAUDE.md memory](memory.md), [plugins](../08-Plugins-Skills/plugins.md), and [MCP servers](../06-MCP-Tools/General/mcp.md)
- [Checkpoints](checkpointing.md), [sandboxing](sandboxing.md), and [Workflows](workflows.md)
- [OpenTelemetry metrics](../13-Enterprise-Admin/monitoring-usage.md) and the [managed settings file](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms)
These have provider-specific differences:
- **MCP servers**: [connectors from claude.ai](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) load only when your claude.ai subscription is the active authentication method. [Tool search](../06-MCP-Tools/General/mcp.md#configure-tool-search) is off by default when `ANTHROPIC_BASE_URL` points to a non-first-party host, and isn’t supported on Google Cloud’s Agent Platform models earlier than the Claude 4.5 generation or on Microsoft Foundry [deployments hosted on Azure](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options)
- **Subagents**: the built-in [Explore subagent](../09-Agents-Patterns/sub-agents.md#built-in-subagents) caps its inherited model at Opus on the Claude API, and inherits the main conversation’s model directly on any other provider, including Claude Platform on AWS
- **[Commands](commands.md#all-commands)**:
- `/design-sync` and `/import` with its `claude import` subcommand form are unavailable on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Claude Platform on AWS, and through a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md#availability-and-limitations)
- `/voice` requires a claude.ai account
- `/list-agents` and its alias `/peers` are available only in sessions where [cross-session messaging is enabled](cross-session-messaging.md#availability)
[](#features-that-require-a-claude-subscription)
Features that require a Claude subscription
These require signing in with a claude.ai account and are not reachable with an Anthropic Console API key or from a third-party provider:
- [Cloud sessions](claude-code-on-the-web.md), Claude Code on mobile, and [Claude Code in Slack](../14-Connectors/slack.md)
- [Claude Code Desktop](../16-Mobile-Desktop/desktop.md)
- [Routines](web-scheduled-tasks.md) (`/schedule`)
- [Ultrareview](ultrareview.md)
- [Code Review](code-review.md): Team and Enterprise plans
- [Remote Control](remote-control.md)
- [Chrome extension](../03-IDE-Integrations/chrome.md)
- [Computer use](computer-use.md): Pro and Max plans
- [Artifacts](artifacts.md): Pro, Max, Team, and Enterprise plans
- [Voice dictation](voice-dictation.md)
Desktop is the partial exception: [gateway routing can be configured in the app or by an administrator](../13-Enterprise-Admin/llm-gateway-connect.md#desktop-app), Enterprise deployments can route Desktop to Google Cloud’s Agent Platform or a gateway provider via [managed settings](https://claude.com/docs/third-party/claude-desktop/configuration), and [Claude Desktop on 3P](https://claude.com/docs/third-party/claude-desktop/overview) runs the Code tab on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or a self-hosted LLM gateway. For per-plan availability of these features, see [Availability by subscription plan](#availability-by-subscription-plan).
[](#cli-capabilities-that-vary-by-provider)
CLI capabilities that vary by provider
These features work in the local CLI but depend on a server-side capability that not every provider exposes.
| Feature | Claude subscription | Anthropic Console | Amazon Bedrock | Claude Platform on AWS | Google Cloud’s Agent Platform | Microsoft Foundry |
|----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|-------------------------------|-------------------------------|-------------------------------|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
| [Web search](tools-reference.md#websearch-tool-behavior) | ✓ | ✓ | ✗ | ✓ | See note ^([1](#fn1)) | ✓ ([deployments hosted on Anthropic](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options)) |
| [Fast mode](fast-mode.md) | ✓ ([Owner-enabled](fast-mode.md#enable-fast-mode-for-your-organization) on Team and Enterprise) | ✓ (provisioned organizations) | ✗ | ✗ | ✗ | ✗ |
| [Auto mode](auto-mode-config.md) | ✓ | ✓ | See note ^([2](#fn2)) | ✓ | See note ^([2](#fn2)) | See note ^([2](#fn2)) |
| [Advisor](advisor.md) | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| [Cross-session messaging](cross-session-messaging.md) | ✓ ^([5](#fn5)) | ✓ (same machine) ^([5](#fn5)) | ✓ (same machine) ^([5](#fn5)) | ✓ (same machine) ^([5](#fn5)) | ✓ (same machine) ^([5](#fn5)) | ✓ (same machine) ^([5](#fn5)) |
| [Channels](channels.md) | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| [GitHub Actions](github-actions.md) | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ |
| [GitLab CI/CD](gitlab-ci-cd.md) | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
[](#admin-and-analytics)
Admin and analytics
Organization-level controls and usage visibility.
| Feature | Claude subscription | Anthropic Console | Amazon Bedrock | Claude Platform on AWS | Google Cloud’s Agent Platform | Microsoft Foundry |
|-------------------------------------------------------------|-----------------------------------------------------|-------------------------|-----------------------|------------------------|-------------------------------|-----------------------|
| [Analytics dashboard and API](../13-Enterprise-Admin/analytics.md) | ✓ (dashboard: Team and Enterprise; API: Enterprise) | ✓ ^([4](#fn4)) | ✗ | ✗ | ✗ | ✗ |
| [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) | ✓ (Team and Enterprise) | ✓ (Team and Enterprise) | ✗ | ✗ | ✗ | ✗ |
| [Zero Data Retention](zero-data-retention.md) | ✓ (qualified Enterprise accounts) | ✓ (qualified accounts) | See note ^([3](#fn3)) | ✓ (qualified accounts) | See note ^([3](#fn3)) | See note ^([3](#fn3)) |
¹ On Google Cloud’s Agent Platform, web search is available for Claude 4 models and later.
² On these providers, auto mode supports only Claude Sonnet 5 or later, Opus 4.7 or later, and the Fable models. See [Auto mode configuration](auto-mode-config.md). For the permission mode a session on these providers starts in, see [Which mode a session starts in](permission-modes.md#which-mode-a-session-starts-in). In v2.1.158 through v2.1.206, auto mode on these providers also required setting `CLAUDE_CODE_ENABLE_AUTO_MODE=1`; v2.1.207 removed the requirement.
³ Subject to your agreement with the cloud provider.
⁴ Dashboard and API only. [Contribution metrics](../13-Enterprise-Admin/analytics.md#enable-contribution-metrics) requires a claude.ai Team or Enterprise organization.
⁵ Requires Claude Code v2.1.224 or later on macOS and Linux, including Linux inside WSL 2. On native Windows, requires Claude Code v2.1.234 or later. With API key authentication, messaging is same-machine only. On Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry, messaging is same-machine only and requires Claude Code v2.1.248 or later. Claude can find your [cloud sessions](claude-code-on-the-web.md) and your sessions on other machines only from a session that is connected to [Remote Control](remote-control.md). To connect, you need a claude.ai sign-in and the other [Remote Control requirements](remote-control.md#requirements). See [Message sessions on other machines](cross-session-messaging.md#message-sessions-on-other-machines).
If you authenticate through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), feature availability matches the underlying provider the gateway forwards to, except for the features Claude Code itself turns off. Whenever `ANTHROPIC_BASE_URL` points at a host other than `api.anthropic.com`, Claude Code turns off features such as [Remote Control](remote-control.md#requirements) and [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md#platform-availability), whatever the gateway forwards. Some Anthropic-only features such as the [Advisor](advisor.md) work only if the gateway forwards requests intact to the Anthropic API.For how the requests Claude Code sends differ between an Amazon Bedrock- or Agent Platform-format gateway, an `ANTHROPIC_BASE_URL` gateway, and a Claude apps gateway sign-in, see [client behavior by connection method](../13-Enterprise-Admin/llm-gateway-protocol.md#how-the-connection-method-changes-client-behavior).
[](#summary-by-provider)
Summary by provider
Each tab lists what is unavailable or partially supported on that provider, with alternatives where one exists. Everything not listed works the same as on a Claude subscription, apart from the [provider-specific differences](#features-available-on-every-provider) noted above. On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Claude Platform on AWS, error reporting and telemetry to Anthropic are off by default. See [default behaviors by API provider](../13-Enterprise-Admin/data-usage.md#default-behaviors-by-api-provider) for what traffic still reaches Anthropic and how to opt out.
- Amazon Bedrock
- Claude Platform on AWS
- Google Cloud's Agent Platform
- Microsoft Foundry
- Anthropic Console
**Not available:** all [features that require a Claude subscription](#features-that-require-a-claude-subscription), plus [web search](tools-reference.md#websearch-tool-behavior), [fast mode](fast-mode.md), [Advisor](advisor.md), [Channels](channels.md), the [analytics dashboard](../13-Enterprise-Admin/analytics.md), [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), and the [`/design-sync` and `/import` commands](commands.md#all-commands).**Partial support:**
- [Desktop](../16-Mobile-Desktop/desktop.md): only via [Claude Desktop on 3P](https://claude.com/docs/third-party/claude-desktop/overview)
- [Auto mode](auto-mode-config.md): Sonnet 5 or later, Opus 4.7 or later, and Fable models only
- [Cross-session messaging](cross-session-messaging.md): between your sessions on this machine only ^([5](#fn5))
- [Zero Data Retention](zero-data-retention.md): subject to your AWS agreement
**Alternatives:** for scheduling, use [`/loop`](scheduled-tasks.md) instead of `/schedule`. For cloud sessions, use [GitHub Actions](github-actions.md) or [GitLab CI/CD](gitlab-ci-cd.md). For web lookups, use the [WebFetch tool](tools-reference.md#webfetch-tool-behavior) with a specific URL.
**Not available:** all [features that require a Claude subscription](#features-that-require-a-claude-subscription), plus [fast mode](fast-mode.md), [Advisor](advisor.md), [Channels](channels.md), [GitHub Actions](github-actions.md), the [analytics dashboard](../13-Enterprise-Admin/analytics.md), [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), and the [`/design-sync` and `/import` commands](commands.md#all-commands).**Available where Amazon Bedrock is not:** [web search](tools-reference.md#websearch-tool-behavior).**Partial support:**
- [Cross-session messaging](cross-session-messaging.md): between your sessions on this machine only ^([5](#fn5))
**Alternatives:** for scheduling, use [`/loop`](scheduled-tasks.md) instead of `/schedule`. For cloud sessions, use [GitLab CI/CD](gitlab-ci-cd.md).
**Not available:** all [features that require a Claude subscription](#features-that-require-a-claude-subscription), plus [fast mode](fast-mode.md), [Advisor](advisor.md), [Channels](channels.md), the [analytics dashboard](../13-Enterprise-Admin/analytics.md), [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), and the [`/design-sync` and `/import` commands](commands.md#all-commands).**Partial support:**
- [Desktop](../16-Mobile-Desktop/desktop.md): via [managed settings](https://claude.com/docs/third-party/claude-desktop/configuration) or [Claude Desktop on 3P](https://claude.com/docs/third-party/claude-desktop/overview)
- [Web search](tools-reference.md#websearch-tool-behavior): Claude 4 models and later
- [Auto mode](auto-mode-config.md): Sonnet 5 or later, Opus 4.7 or later, and Fable models only
- [Cross-session messaging](cross-session-messaging.md): between your sessions on this machine only ^([5](#fn5))
- [Zero Data Retention](zero-data-retention.md): subject to your Google Cloud agreement
**Alternatives:** for scheduling, use [`/loop`](scheduled-tasks.md) instead of `/schedule`. For cloud sessions, use [GitHub Actions](github-actions.md) or [GitLab CI/CD](gitlab-ci-cd.md).
**Not available:** all [features that require a Claude subscription](#features-that-require-a-claude-subscription), plus [fast mode](fast-mode.md), [Advisor](advisor.md), [Channels](channels.md), [GitLab CI/CD](gitlab-ci-cd.md), the [analytics dashboard](../13-Enterprise-Admin/analytics.md), [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), and the [`/design-sync` and `/import` commands](commands.md#all-commands).**Partial support:**
- [Desktop](../16-Mobile-Desktop/desktop.md): only via [Claude Desktop on 3P](https://claude.com/docs/third-party/claude-desktop/overview)
- [Web search](tools-reference.md#websearch-tool-behavior): [deployments hosted on Anthropic](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options) only
- [Auto mode](auto-mode-config.md): Sonnet 5 or later, Opus 4.7 or later, and Fable models only
- [Cross-session messaging](cross-session-messaging.md): between your sessions on this machine only ^([5](#fn5))
- [Zero Data Retention](zero-data-retention.md): subject to your Azure agreement
**Alternatives:** for scheduling, use [`/loop`](scheduled-tasks.md) instead of `/schedule`. For cloud sessions, use [GitHub Actions](github-actions.md).
**Not available:** all [features that require a Claude subscription](#features-that-require-a-claude-subscription).Everything in [CLI capabilities that vary by provider](#cli-capabilities-that-vary-by-provider) is available, except that [fast mode](fast-mode.md) requires [provisioned access](fast-mode.md#enable-fast-mode-for-your-organization). [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) are also available when your API key belongs to a Team or Enterprise organization.
[](#availability-by-subscription-plan)
Availability by subscription plan
If you authenticate through Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or an Anthropic Console API key, this section does not apply to you. When you sign in with a claude.ai account, your plan determines which of the features below are available.
| Feature | Pro | Max | Team | Enterprise |
|:----------------------------------------------------------------------------|:----|:----|:--------------|:---------------|
| [Cloud sessions](claude-code-on-the-web.md) | ✓ | ✓ | ✓ | ✓ ^([6](#fn6)) |
| [Routines](web-scheduled-tasks.md) | ✓ | ✓ | ✓ | ✓ |
| [Remote Control](remote-control.md) | ✓ | ✓ | Admin-enabled | Admin-enabled |
| [Channels](channels.md) | ✓ | ✓ | Admin-enabled | Admin-enabled |
| [Computer use](computer-use.md) | ✓ | ✓ | ✗ | ✗ |
| Dispatch ([Desktop](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch)) | ✓ | ✓ | ✗ | ✗ |
| [Code Review](code-review.md) | ✗ | ✗ | ✓ | ✓ |
| [Artifacts](artifacts.md) | ✓ | ✓ | ✓ | ✓ |
| [Analytics dashboard and contribution metrics](../13-Enterprise-Admin/analytics.md) | ✗ | ✗ | ✓ | ✓ |
| [Enterprise Analytics API](../13-Enterprise-Admin/analytics.md#access-data-programmatically) | ✗ | ✗ | ✗ | ✓ |
| [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) | ✗ | ✗ | ✓ | ✓ |
| [SSO](../17-Billing-Plans/what-is-the-team-plan.md) | ✗ | ✗ | ✓ | ✓ |
| SCIM | ✗ | ✗ | ✗ | ✓ |
| [Compliance API](../04-API-Reference/Endpoints/http-compliance.md) | ✗ | ✗ | ✗ | ✓ |
| [Zero Data Retention](zero-data-retention.md) | ✗ | ✗ | ✗ | ✓ ^([7](#fn7)) |
⁶ On Enterprise, requires a premium seat or a Chat + Claude Code seat. See [Use Claude Code in the cloud](claude-code-on-the-web.md).
⁷ Not included in the standard Enterprise plan. Requires separate enablement by Anthropic for qualified accounts. See [Zero Data Retention](zero-data-retention.md). For pricing and the full plan comparison, see [Team plans](../17-Billing-Plans/what-is-the-team-plan.md) and [Enterprise plans](../17-Billing-Plans/what-is-the-enterprise-plan.md).
[](#model-availability)
Model availability
For which Claude models and context-window sizes are available per provider and region, see [Model configuration](model-config.md) and the [Models overview](../20-Models/about-claude-models-overview.md). Vision, PDF input, and extended thinking are model capabilities rather than Claude Code features and work on every provider that offers the model. [Prompt caching](prompt-caching.md) works the same way on most providers; on Amazon Bedrock, support varies by model.
[](#related-resources)
Related resources
- [Enterprise deployment overview](third-party-integrations.md): compare authentication, billing, and regions across providers
- Provider setup guides: [Amazon Bedrock](amazon-bedrock.md), [Claude Platform on AWS](claude-platform-on-aws.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), [Microsoft Foundry](microsoft-foundry.md)
- [Platforms and integrations](platforms.md): where Claude Code runs, including the CLI, Desktop, IDE extensions, web, mobile, and CI/CD
---
## Extend Claude Code - Claude Code Docs
Source: https://code.claude.com/docs/en/features-overview
Path: 02-Claude-Code-CLI/features-overview.md
## On this page
- [Overview](#overview)
- [Match features to your goal](#match-features-to-your-goal)
- [Build your setup over time](#build-your-setup-over-time)
- [Compare similar features](#compare-similar-features)
- [Understand how features layer](#understand-how-features-layer)
- [Combine features](#combine-features)
- [Understand context costs](#understand-context-costs)
- [Context cost by feature](#context-cost-by-feature)
- [Understand how features load](#understand-how-features-load)
- [Learn more](#learn-more)
Core concepts
# Extend Claude Code
Copy pageCopy page
Understand when to use CLAUDE.md, Skills, subagents, hooks, MCP, and plugins.
Copy pageCopy page
Claude Code combines a model that reasons about your code with [built-in tools](how-claude-code-works.md#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](how-claude-code-works.md).
**New to Claude Code?** Start with [CLAUDE.md](memory.md) for project conventions, then add other extensions [as specific triggers come up](#build-your-setup-over-time).
[](#overview)
Overview
Extensions plug into different parts of the agentic loop:
- **[CLAUDE.md](memory.md)** adds persistent context Claude sees every session
- **[Output styles](output-styles.md)** set Claude’s role, tone, and response format for every response in a session
- **[Skills](../08-Plugins-Skills/skills.md)** add reusable knowledge and invocable workflows
- **[Code intelligence](tools-reference.md#lsp-tool-behavior)** connects Claude to a language server for symbol-level navigation and live type errors
- **[MCP](../06-MCP-Tools/General/mcp.md)** connects Claude to external services and tools
- **[Subagents](../09-Agents-Patterns/sub-agents.md)** run their own loops in isolated context, returning summaries
- **[Dynamic workflows](workflows.md)** run many subagents from a script Claude writes, returning one result
- **[Cross-session messaging](cross-session-messaging.md)** lets Claude pass a message from one of your sessions to another
- **[Hooks](../07-Hooks/hooks-guide.md)** run your script, HTTP request, MCP tool call, prompt, or subagent when Claude Code reaches a lifecycle event
- **[Plugins](../08-Plugins-Skills/plugins.md)** and **[marketplaces](../08-Plugins-Skills/plugins.md)** package and distribute these features
[Skills](../08-Plugins-Skills/skills.md) 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)
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.” |
| **[Output style](output-styles.md)** | Instructions that set Claude’s role, tone, and response format for a whole session | A voice, length, or format you want in every response, or Claude working as something other than a software engineer | The built-in Concise style for shorter responses; a custom style that answers every question with a diagram first |
| **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 |
| **[Dynamic workflow](workflows.md)** | Script Claude writes that runs many subagents in the background | Work that outgrows a handful of subagents, or findings you want cross-checked | Audit a whole codebase, with a second set of agents verifying each finding |
| **[Cross-session messaging](cross-session-messaging.md)** | Claude delivers a message from one of your sessions to another | Sessions you run yourself that need each other’s findings mid-task | One session warns another that a change it made breaks what the other is building on |
| **[Code intelligence](tools-reference.md#lsp-tool-behavior)** | Language-server navigation and diagnostics | Typed languages, large codebases where grep is slow or imprecise | Jump to a symbol’s definition instead of reading the whole file |
| **MCP** | Connect to external services | External data or actions | Query your database, post to Slack, control a browser |
| **Hook** | Script, HTTP request, MCP tool call, prompt, or subagent triggered by events | Automation that must run on every matching event | Run ESLint after every file edit |
| **[Artifact](artifacts.md)** | Publish session output as a private, interactive web page | Output you want to see or share visually rather than as terminal text | An incident timeline that updates as Claude investigates |
**[Plugins](../08-Plugins-Skills/plugins.md)** 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](../08-Plugins-Skills/plugins.md)**.
[](#build-your-setup-over-time)
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](memory.md) |
| You keep asking Claude to be shorter, explain more, or answer in the same format | Set an [output style](output-styles.md) |
| You keep typing the same prompt to start a task | Save it as a user-invocable [skill](../08-Plugins-Skills/skills.md) |
| You paste the same playbook or multi-step procedure into chat for the third time | Capture it as a [skill](../08-Plugins-Skills/skills.md) |
| You keep copying data from a browser tab Claude can’t see | Connect that system as an [MCP server](../06-MCP-Tools/General/mcp.md) |
| Claude reads many files to find where a symbol is defined or used | Install a [code intelligence plugin](../08-Plugins-Skills/plugins-code-intelligence.md) for your language |
| A side task floods your conversation with output you won’t reference again | Route it through a [subagent](../09-Agents-Patterns/sub-agents.md) |
| You want something to happen every time without asking | Write a [hook](../07-Hooks/hooks-guide.md) |
| A second repository needs the same setup | Package it as a [plugin](../08-Plugins-Skills/plugins.md) |
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)
Compare similar features
Some features can seem similar. For a deeper walkthrough of choosing between them, see [Steering Claude Code: when to use CLAUDE.md, skills, hooks, and subagents](https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more) on the blog. Here’s how to tell them apart.
- Skill vs Subagent
- CLAUDE.md vs Skill
- CLAUDE.md vs Output style
- CLAUDE.md vs Rules vs Skills
- Subagent vs Dynamic workflow
- 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](context-window.md) 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](../08-Plugins-Skills/skills.md) 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/`](memory.md#organize-rules-with-claude/rules/) files.
Both give Claude standing instructions. CLAUDE.md carries what Claude should know, and an output style sets how Claude responds.
| Aspect | CLAUDE.md | Output style |
|---------------|-------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| **Holds** | Facts and rules about your project | A role, tone, and response format |
| **Switching** | Always loaded | One active at a time; [switch styles](output-styles.md#change-your-output-style) whenever you want |
| **Best for** | Build commands, conventions, “never do X” rules | Shorter responses, explanations alongside code, a non-engineering role |
**Put it in CLAUDE.md** if it’s true of the project whatever style you’re in: coding conventions, build commands, project structure.**Use an output style** if it’s about the response itself and you might want it off again: length, format, how much Claude explains, or a different role such as a writing assistant. Claude Code includes [built-in styles](output-styles.md#built-in-output-styles), and you can write your own.**They combine.** CLAUDE.md stays loaded whichever style you pick. Claude follows both as instructions, so neither is enforced. For anything that has to happen every time, use a [hook](../07-Hooks/hooks-guide.md).
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](memory.md#path-specific-rules) 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 do work outside your main conversation. With subagents, Claude decides turn by turn what runs next. In a workflow, the script decides:
- **Subagents** are workers Claude spawns, each returning a summary to the conversation that spawned it
- **[Dynamic workflows](workflows.md)** are scripts Claude writes that run many subagents in the background and return one result
**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, so your main conversation stays clean. Subagents that Claude named when it spawned them can also [message each other](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup).**Use a dynamic workflow** when a job [outgrows a handful of subagents](workflows.md#when-to-use-a-workflow), or when you want the findings cross-checked before you see them, such as a codebase-wide audit, a large migration, or a plan drafted from several angles. To start one, [ask for a workflow in your prompt](workflows.md#ask-for-a-workflow-in-your-prompt).**To pass a finding from one of your sessions to another**, ask the first session’s Claude to send it. Claude delivers it with [cross-session messaging](cross-session-messaging.md). [Run agents in parallel](../09-Agents-Patterns/agents.md) compares the other ways to run more than one Claude at once, including sessions you hand off and check back on later.
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 purpose-built tools for an external system, with the connection and authentication handled by the server.**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.
Claude Code runs a hook at a lifecycle event; it loads a skill into context for Claude to apply.
| Aspect | Hook | Skill |
|------------------|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| **Runs** | A shell command, HTTP request, MCP tool call, LLM prompt, or subagent | Instructions Claude reads and follows |
| **Triggered by** | [Lifecycle events](../07-Hooks/hooks.md#hook-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)
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. See [how CLAUDE.md files load](memory.md#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](../08-Plugins-Skills/plugins-components.md#skills) to avoid conflicts. See [skill discovery](../08-Plugins-Skills/skills.md#resolve-skills-that-share-a-name) and [subagent scope](../09-Agents-Patterns/sub-agents.md#choose-the-subagent-scope).
- **MCP servers** override by name: local \> project \> user. See [MCP scope](../06-MCP-Tools/General/mcp.md#scope-hierarchy-and-precedence).
- **Hooks** merge: all registered hooks fire for their matching events regardless of source. See [hooks](../07-Hooks/hooks.md).
[](#combine-features)
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)
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-window.md).
[](#context-cost-by-feature)
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 |
| **Output styles** | Session start, and again when you switch styles | The active style’s full instructions; nothing for the Default style | 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 |
| **Code intelligence** | After file edits and on demand | Diagnostics after edits; symbol locations on lookup | Low; reduces file reads elsewhere |
| **Subagents** | When spawned | Fresh context with specified skills, or the parent conversation for a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) | 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. For a skill you didn’t write, set [`skillOverrides`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) in settings to do the same without editing its file.
[](#understand-how-features-load)
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
- Code intelligence
- 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](memory.md#how-claude-md-files-load) for details.
Keep CLAUDE.md under 200 lines. Move reference material to skills, which load on demand. To get [trim proposals for a checked-in CLAUDE.md](memory.md#my-claude-md-is-too-large), run `/doctor`.
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](commands.md) like `/code-review`, `/batch`, and `/debug` that work without setup. You can also create your own.**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 and server instructions from connected servers. Full JSON schemas stay deferred until Claude needs a specific tool.**Context cost:** [Tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is on by default, so idle MCP tools consume minimal context.
Run `/mcp` to see each server’s connection status. Run `/context all` to see how many tokens each loaded MCP tool uses. Claude Code [reconnects to remote servers automatically](../06-MCP-Tools/General/mcp.md#automatic-reconnection) if they drop, and you can disconnect servers you’re not actively using.
**When:** After file edits, and on demand when Claude navigates code.**What loads:** Type errors and warnings after each file edit. Definition, reference, and type information when Claude looks up a symbol.**Context cost:** Low. Symbol lookups often replace broad file reads, so net context use can go down.
The LSP tool is inactive until you install a [code intelligence plugin](../08-Plugins-Skills/plugins-code-intelligence.md) for your language.
**When:** On demand, when you or Claude spawns one for a task.**What loads:** Fresh, isolated context containing:
- The agent’s own system prompt, not the Claude Code system prompt
- Full content of skills listed in the agent’s `skills:` field
- CLAUDE.md and git status, except the built-in Explore and Plan agents [omit both](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup), and an agent whose definition sets [`omitClaudeMd`](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) skips the user, project, and local CLAUDE.md files
- Whatever context the lead agent passes in the prompt
For a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), Claude Code loads the parent’s conversation so far, system prompt, and tools instead.**Context cost:** Isolated from main session.
Use subagents for work that doesn’t need your full conversation context. Their isolation prevents bloating your main session.
**When:** On trigger. Claude Code runs hooks at specific lifecycle events like tool execution, session boundaries, prompt submission, permission requests, and compaction. See [Hooks](../07-Hooks/hooks.md) 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)
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
## Dynamic workflows
Run many subagents from one script
## Cross-session messaging
Let Claude message your other sessions
## MCP
Connect Claude to external services
## Hooks
Automate actions with hooks
## Plugins
Bundle and share feature sets
## Marketplaces
Host and distribute plugin collections
---
## Fullscreen rendering - Claude Code Docs
Source: https://code.claude.com/docs/en/fullscreen
Path: 02-Claude-Code-CLI/fullscreen.md
## On this page
- [Enable fullscreen rendering](#enable-fullscreen-rendering)
- [Fullscreen by default](#fullscreen-by-default)
- [What changes](#what-changes)
- [Use the mouse](#use-the-mouse)
- [Scroll the conversation](#scroll-the-conversation)
- [Auto-follow](#auto-follow)
- [Mouse wheel scrolling](#mouse-wheel-scrolling)
- [Scroll in the JetBrains IDE terminal](#scroll-in-the-jetbrains-ide-terminal)
- [Search and review the conversation](#search-and-review-the-conversation)
- [Watch your changes in the diff panel](#watch-your-changes-in-the-diff-panel)
- [Clear the conversation](#clear-the-conversation)
- [Use with tmux](#use-with-tmux)
- [Keep native text selection](#keep-native-text-selection)
- [Troubleshooting](#troubleshooting)
- [Stale or misplaced text on screen](#stale-or-misplaced-text-on-screen)
- [Claude Code's fullscreen renderer didn't finish starting last time appears at startup](#fullscreen-renderer-didnt-finish-starting)
- [How Claude Code counts failed starts](#how-claude-code-counts-failed-starts)
- [Research preview](#research-preview)
Interface
# Fullscreen rendering
Copy pageCopy page
Enable a smoother, flicker-free rendering mode with mouse support and stable memory usage in long conversations.
Copy pageCopy page
Fullscreen rendering is a [research preview](#research-preview). Whether you [start in fullscreen or in the classic renderer](#fullscreen-by-default) depends on your setup. Run `/tui fullscreen` or `/tui default` to switch in your current conversation. 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)
Enable fullscreen rendering
Run `/tui fullscreen` inside any Claude Code conversation. The CLI saves the [`tui` setting](settings-reference.md#tui) and relaunches into fullscreen with your conversation intact, so you can switch mid-session without losing context. Run `/tui default` to switch back to the classic renderer, or `/tui` with no argument to print which renderer is active. In [screen reader mode](accessibility.md), Claude Code always uses the classic renderer except in attached [background sessions](../09-Agents-Patterns/agent-view.md), which still render fullscreen. If you run `/tui fullscreen` in any other session, Claude Code prints an explanation instead of switching and doesn’t change the saved `tui` setting. Claude Code carries these into the relaunched session:
- The conversation as it appears on screen. After a [`/rewind`](checkpointing.md#rewind-and-summarize), that means:
- If you rewound earlier in the session, Claude Code relaunches from the rewound point, not from the longer transcript saved on disk. For example, if you rewound past your last three messages, the relaunched session opens without them
- If you rewound to before your first message, Claude Code relaunches with an empty conversation
- Your [permission mode](permission-modes.md) and [effort level](model-config.md#adjust-effort-level)
- The model you last picked with [`/model`](model-config.md#setting-your-model)
- Rules you passed with [`--allowed-tools` or `--disallowed-tools`](cli-reference.md#cli-flags), and your `--agent`, `--agents`, `--append-system-prompt`, and `--system-prompt-snapshot` flags
Claude Code declines to relaunch if the session has a restriction it can’t pass to the restarted process. Restrictions it can’t pass include:
- Launch flags such as a [`--system-prompt`](cli-reference.md#cli-flags) replacement, a [`--tools`](cli-reference.md#cli-flags) allowlist, or [`--setting-sources`](cli-reference.md#cli-flags)
- Deny or ask rules that a [hook or SDK permission update](../07-Hooks/hooks.md#permission-update-entries) added for this session only
In that case Claude Code prints [`Cannot switch renderers in this session`](errors.md#cannot-switch-renderers-in-this-session) with the reasons. It doesn’t switch or save anything. You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:
```python
CLAUDE_CODE_NO_FLICKER=1 claude
```
For how the [`tui`](settings-reference.md#tui) setting and the variable combine when both are set, see the setting’s entry. After a [failed fullscreen start](#fullscreen-renderer-didnt-finish-starting), Claude Code still honors the variable but not the setting. The `/tui` command clears `CLAUDE_CODE_NO_FLICKER` from the relaunched process so the setting it writes takes effect.
[](#fullscreen-by-default)
Fullscreen by default
Attached [background sessions](../09-Agents-Patterns/agent-view.md) render fullscreen, and other sessions in [screen reader mode](accessibility.md) use the classic renderer. Otherwise, Claude Code starts you in the renderer from the first row of this table that matches your setup:
| Your situation | Renderer you start in |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------|
| You set [`CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1`](env-vars.md) or `CLAUDE_CODE_NO_FLICKER=0` | Classic |
| You set `CLAUDE_CODE_NO_FLICKER=1` | Fullscreen |
| Claude Code [turned fullscreen off after a failed fullscreen start](#fullscreen-renderer-didnt-finish-starting) on this machine | Classic |
| You’re in iTerm2’s [`tmux -CC` integration mode](#use-with-tmux), or you’re connected over SSH to Claude Code running on Windows | Classic |
| You saved a [`tui` setting](settings-reference.md#tui) | The renderer the setting names |
| Your session doesn’t [fetch feature flags from Anthropic](env-vars.md#features-that-need-feature-flag-fetching), and Claude Code has stopped offering the startup dialog on this machine | Classic |
| Your session doesn’t fetch feature flags from Anthropic, and this machine’s first Claude Code launch ran v2.1.239 or later | Fullscreen |
| Your session fetches feature flags from Anthropic, and you first used Claude Code on or after May 6, 2026 | Fullscreen |
| Anything else | Classic |
Sessions that don’t fetch feature flags include those through [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md), and those with telemetry turned off. If you start in the classic renderer and haven’t saved a `tui` setting, Claude Code may open a dialog at startup offering the switch:
- If you accept, Claude Code relaunches the same way `/tui fullscreen` does, carrying the same session state, and saves the setting once the relaunched session has [started successfully](#fullscreen-renderer-didnt-finish-starting).
- If you choose **Not now**, Claude Code doesn’t offer again on this machine.
- Claude Code stops offering after it has shown the dialog on three launches, answered or not.
[](#what-changes)
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 doesn’t move 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](#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](#use-the-mouse) |
| `Cmd`-click to open a URL | `Cmd`-click on macOS, `Ctrl`-click elsewhere | [Use the mouse](#use-the-mouse) |
If mouse capture interferes with your workflow, you can [turn it off](#keep-native-text-selection) while keeping the flicker-free rendering.
[](#use-the-mouse)
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 suggestion in the `/` command or `@` file list** to accept it. Hovering highlights the row under your cursor.
- **Click an option in a select menu** to choose it. This covers permission prompts, `/model`, `/config`, and other dialogs that show a list of options. Hovering shows a pointer on the row under your cursor.
- **Click an option in a multi-select menu** to toggle it, and click the submit button to confirm your choices. Clicking a free-text row, such as the `Other` row in a multiple-choice question, focuses its input field so you can type an answer. Requires Claude Code v2.1.208 or later.
- **Click a setting’s value in the `/config` panel** to change it, and scroll the settings list with the mouse wheel. Requires Claude Code v2.1.271 or later.
- **Scroll a select or multi-select menu with the mouse wheel** when it has more options than it shows at once, such as the `/model` list in a short terminal window. The wheel scrolls the list while the pointer is over its options. Requires Claude Code v2.1.280 or later.
- **Scroll an overflowing list with its scrollbar.** In list panels such as `/skills`, `/mcp`, and `/plugin`’s Installed list, a scrollbar appears beside a list with more rows than fit while the pointer is over it. Click the track to jump to that point, or drag the thumb. Requires Claude Code v2.1.281 or later.
- **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.
- Clicking also expands the output of a `!` shell command, whether an older truncated result or the live progress row while the command runs. Requires Claude Code v2.1.257 or later.
- Clicking also expands a dim `Message from @<sender>` line when the sender is a [teammate](../09-Agents-Patterns/agent-teams.md) or another agent running in your session. The line for a message from [one of your other sessions](cross-session-messaging.md#what-a-message-looks-like) also shows the message’s first line and isn’t clickable, so press `Ctrl+o` to read that one.
- **Hold `Cmd` on macOS, or `Ctrl` on Linux and Windows, and click a URL or file path** to open it. Plain `http://` and `https://` URLs open in your browser, and file paths in tool output, like the ones printed after an Edit or Write, open in your default application. A plain click without the modifier doesn’t open links, matching native terminal behavior.
- Claude Code renders a network (UNC) path, such as `\\server\share\file.ts`, as plain text with no link, because opening a network path can send your Windows credentials to the host it names.
- Some macOS terminals forward `Cmd`+click to the running app instead of opening the link themselves, and the terminal mouse protocol has no way to encode the `Cmd` key, so Claude Code receives a plain click. In Ghostty, and in Warp on macOS, Claude Code detects this and lets a plain click on a link open it, and holding `Cmd` still works.
- In the VS Code integrated terminal and similar xterm.js-based terminals, Claude Code defers to the terminal’s own link handler, which uses the same gesture.
- **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. Double-clicking a URL selects the whole URL, including the scheme. 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 Copy on select 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. In the normal prompt view, what happens to an active selection depends on the key you press:
- **`Esc`**: Claude Code performs the key’s usual action, such as interrupting the running response or dismissing an open dialog, and the selection stays highlighted.
- **`PgUp`, `PgDn`, `Ctrl+Home`, `Ctrl+End`, or `Shift`, `Alt` or `Option`, or `Cmd`, `Win`, or `Super` with an arrow, `Home`, or `End` key**: the selection stays.
- **Any other key, including plain arrow keys, `Enter`, and typed characters**: Claude Code clears the selection.
- **A key bound to [`selection:clear`](keybindings.md#scroll-actions)**: Claude Code clears the selection, even when the key is `Esc` or another key that otherwise keeps it. The action has no default binding.
In [transcript mode](#search-and-review-the-conversation), the navigation and search keys listed there also keep the selection.
[](#scroll-the-conversation)
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 |
You can scroll back to the start of the session even after [compaction](context-window.md#what-survives-compaction). Claude continues working from the compaction summary, but Claude Code keeps every earlier message in the fullscreen scrollback across repeated compactions. 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`. `Ctrl+Fn+→` doesn’t reach Claude Code on macOS, so a MacBook keyboard has no working jump-to-bottom chord by default. Instead, use one of these options:
- Click the [jump-to-bottom button](#auto-follow).
- Scroll to the bottom with the mouse wheel to resume following.
- Rebind `scroll:bottom` to a chord your keyboard can send.
These actions are rebindable. See [Scroll actions](keybindings.md#scroll-actions) for the full list of action names, including half-page and full-page variants that have no default binding. While you’re scrolled up, a dim header row at the top of the conversation shows the most recent prompt that has scrolled above the view. Click the row to jump to that prompt.
[](#auto-follow)
Auto-follow
Scrolling up pauses auto-follow so new output doesn’t pull you back to the bottom. A `Jump to bottom` button floats over the bottom edge of the transcript while you’re scrolled up, and shows a count such as `3 new messages` when new output arrives. Click it, press `Ctrl+End`, or scroll to the bottom to resume following. While auto-follow is paused, the view also stays where you scrolled it when a response finishes streaming. The button’s keyboard hint reflects what your keyboard can send. On macOS it suggests clicking, or `Fn+↓` to scroll, because `Ctrl+End` doesn’t reach Claude Code from a Mac keyboard. Rebind [`scroll:bottom`](keybindings.md#scroll-actions) and the button shows your chord on every platform. On a terminal too narrow for the full label, the button shortens the hint instead of wrapping onto the transcript row underneath. 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
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 can’t detect which. Set `CLAUDE_CODE_SCROLL_SPEED` to multiply the base scroll distance:
```python
export CLAUDE_CODE_SCROLL_SPEED=3
```
A value of `3` matches the default in `vim` and similar applications. The setting accepts any positive value up to 20, including fractional values below 1 such as `0.25` to slow accelerated trackpad and wheel scrolling in terminals that already amplify wheel events. 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 the speed, `r` to reset to the auto-detected default, and `Enter` to save. The dialog steps in whole numbers up to 10, and on terminals that support finer control it also offers quarter steps down to 0.25. The command writes the same value the `CLAUDE_CODE_SCROLL_SPEED` environment variable sets, persisted to `~/.claude/settings.json`. The dialog’s maximum is 10: if you set a higher value through the environment variable, the dialog shows 10, and saving from the dialog persists 10. The command isn’t available in the JetBrains IDE terminal. Separately from the base speed, Claude Code accelerates the scroll rate when you spin the wheel quickly, so a fast spin covers more distance than the same number of slow notches. To turn acceleration off and keep a constant rate per notch, set `wheelScrollAccelerationEnabled` to `false` in [`settings.json`](settings-reference.md#all-settings). This setting requires Claude Code v2.1.174 or later.
[](#scroll-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)
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 |
| `{` / `}` | Jump to the previous or next prompt |
| `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`.
[](#watch-your-changes-in-the-diff-panel)
Watch your changes in the diff panel
In fullscreen rendering, [`/diff`](interactive-mode.md#review-changes-with-%2Fdiff) opens a panel beside the conversation rather than a viewer you have to close, so you can watch the changes accumulate while Claude works. In a wide terminal the panel can also open on its own once Claude starts editing files. [Diff panel](interactive-mode.md#diff-panel) covers what it shows, how to keep it closed, and how to change what it compares against.
[](#clear-the-conversation)
Clear the conversation
Run `/clear` to start a new conversation. If the display looks garbled or partially blank, press `Ctrl+L` to redraw the screen. The redraw keeps the conversation and your input in place. `Cmd+K` does the same as `Ctrl+L` when your terminal passes it through to Claude Code. iTerm2 and Terminal.app handle `Cmd+K` themselves and clear their own screen, and Claude Code detects the cleared screen and repaints the conversation. Before v2.1.280, starting with v2.1.260, pressing `Ctrl+L`, or `Cmd+K` where it reaches Claude Code, cleared the screen in fullscreen rendering. Before v2.1.238, pressing `Ctrl+L` twice within two seconds ran `/clear`.
[](#use-with-tmux)
Use with tmux
Fullscreen rendering works inside tmux, with three caveats. Mouse wheel scrolling requires tmux’s mouse mode. If your `~/.tmux.conf` doesn’t already enable it, add this line and reload your config:
```python
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 don’t 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 releases through the 3.6 series don’t implement synchronized output, so under those versions you may see more flicker during redraws than when running Claude Code directly in your terminal. Claude Code probes the terminal for synchronized-output support at startup and uses it when the terminal reports it. If you see flicker under tmux, upgrade to the newest tmux or run Claude Code in its own terminal tab outside tmux.
[](#keep-native-text-selection)
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 writes the selection to your system clipboard, and the path it uses depends on your setup. On a local session it runs a native clipboard tool:
- **macOS**: `pbcopy`
- **Linux**: `wl-copy` on Wayland, or `xclip` or `xsel` on X11, whichever is installed. Claude Code writes both the clipboard and the PRIMARY selection, so middle-click paste works.
- **Windows and WSL**: PowerShell `Set-Clipboard`
Inside tmux it also writes to the tmux paste buffer. Over SSH it falls back to OSC 52 escape sequences. Inside GNU screen, Claude Code copies long selections to the clipboard too. Before v2.1.219, if you copied a selection longer than roughly 570 characters, GNU screen printed base64 text into the window instead. Claude Code prints a toast after each copy telling you which path it used. Some terminals block OSC 52 by default. iTerm2 blocks it until you turn on Settings → General → Selection → Applications in terminal may access clipboard; running [`/terminal-setup`](terminal-config.md) in iTerm2 enables this for you. For a one-off native selection, the key to use depends on your terminal:
- **Terminal.app**: `Fn`
- **iTerm2**: `Option`
- **VS Code, Cursor, and Devin Desktop**: `Shift`, or `Option` on macOS with the `terminal.integrated.macOptionClickForcesSelection` setting enabled
- **Most other terminals**: `Shift`
Hold that key while you click and drag. Your terminal handles the selection itself instead of passing it to Claude Code, so copy shortcuts like `Cmd+C` work on what you select. Claude Code also shows the correct key in its on-screen hint. Over SSH or inside tmux, Claude Code can’t always detect the terminal you’re connecting from, so the hint lists the candidate keys instead. 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:
```python
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, URL clicking, and wheel scrolling inside Claude Code. To keep wheel scrolling but turn off click, drag, and hover handling, set `CLAUDE_CODE_DISABLE_MOUSE_CLICKS=1` instead. `CLAUDE_CODE_DISABLE_MOUSE` takes precedence when both variables are set. With clicks disabled, Claude Code still captures the mouse, so the wheel and touchpad scroll the conversation but left clicks do nothing inside Claude Code. You still need to hold your terminal’s key for native click-and-drag selection. Right-click and middle-click paste continue to work on terminals that support them.
[](#troubleshooting)
Troubleshooting
[](#stale-or-misplaced-text-on-screen)
Stale or misplaced text on screen
Fullscreen rendering sends only the cells that changed between frames. Some terminals, most commonly Windows Terminal and other ConPTY-backed hosts, coalesce these positioned writes incorrectly and leave fragments of earlier output on screen until you resize the window. Set [`CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT=1`](env-vars.md) to repaint every cell on every frame instead of sending incremental updates. On Windows PowerShell:
```python
$env:CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT = "1"
claude
```
On macOS or Linux:
```python
CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT=1 claude
```
On Windows, Claude Code already enables full repaint automatically for background sessions and [agent view](../09-Agents-Patterns/agent-view.md), so you only need to set the variable for an interactive fullscreen session you launched directly.
[](#fullscreen-renderer-didnt-finish-starting)
`Claude Code's fullscreen renderer didn't finish starting last time` appears at startup
If a fullscreen session on this machine crashes before it has started successfully, Claude Code starts your next session in the classic renderer and prints one of two lines. A session has started successfully once it has drawn its first frame and then either stayed up for 10 seconds or you ended it with `/exit`, Ctrl+C, or Ctrl+D. The line you see tells you what Claude Code does after this session:
- After one failed start, you see `Claude Code's fullscreen renderer didn't finish starting last time on this machine`. Claude Code tries fullscreen rendering again in the next session you start
- After two failed starts, you see `Claude Code's fullscreen renderer has repeatedly failed to start on this machine`. Claude Code keeps using the classic renderer until you update Claude Code or run `/tui fullscreen`, and prints nothing in those later sessions
To confirm that a failed start is why you’re in the classic renderer, run `/tui` with no argument. While a failed start is the reason, the `Current renderer` line says so. To keep the classic renderer, run `/tui default`, which saves the `tui` setting without relaunching. To try fullscreen rendering again, run `/tui fullscreen`. If that session doesn’t finish starting either, [report the problem](#research-preview). Before v2.1.236, Claude Code kept starting sessions in fullscreen rendering after a failed start.
[](#how-claude-code-counts-failed-starts)
How Claude Code counts failed starts
- Sessions that count: only sessions that started in fullscreen rendering because your `tui` setting says so, because you accepted the [startup dialog](#fullscreen-by-default), or because Claude Code starts you in fullscreen by default
- `CLAUDE_CODE_NO_FLICKER=1`: if you set it, Claude Code renders that session fullscreen even after a failed start, and doesn’t count it
- Count reset: Claude Code counts failed starts per Claude Code version, and a successful fullscreen start resets the count
- Startup dialog: if you accepted the dialog and the relaunched session crashed, Claude Code prints neither line and doesn’t show the dialog again on this Claude Code version
[](#research-preview)
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](https://github.com/anthropics/claude-code/issues). 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. When you switch back with `/tui default`, Claude Code may first show an optional feedback prompt asking what made you switch. Type a reason and press `Enter` to send it, or press `Esc` to skip. The CLI relaunches into the classic renderer either 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. Background sessions opened from [agent view](../09-Agents-Patterns/agent-view.md) or `claude attach` always use fullscreen rendering. The attaching terminal enters the alternate screen buffer to show the session, and the classic renderer has no scrollback or mouse handling there, so the `tui` setting and `CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN` don’t apply to them.
---
## Use Claude Code GitHub Actions with cloud providers - Claude Code Docs
Source: https://code.claude.com/docs/en/github-actions-cloud-providers
Path: 02-Claude-Code-CLI/github-actions-cloud-providers.md
## On this page
- [Choose your provider](#choose-your-provider)
- [Prerequisites](#prerequisites)
- [Set up the integration](#set-up-the-integration)
- [Troubleshooting](#troubleshooting)
- [What’s next](#what%E2%80%99s-next)
Code review & CI/CD
# Use Claude Code GitHub Actions with cloud providers
Copy pageCopy page
Run Claude Code GitHub Actions through Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry instead of the Claude API
Copy pageCopy page
[Claude Code GitHub Actions](github-actions.md) calls the Claude API by default. To route inference through your own cloud account instead, set the Claude Code GitHub Action’s provider input and configure your cloud to trust the workflow’s OpenID Connect (OIDC) token. The workflow authenticates with that token, so you store no long-lived cloud credential in your repository.
This page builds on the [GitHub Actions setup](github-actions.md#setup). It assumes you already know the workflow file and the `anthropics/claude-code-action` step, and covers only what a cloud provider changes.
[](#choose-your-provider)
Choose your provider
The Claude Code GitHub Action supports three providers, and the setup steps below differ only in the cloud-side configuration. Use the one where your organization already has Claude model access. You tell the Claude Code GitHub Action which provider to use with one input in the `anthropics/claude-code-action` step’s `with:` block:
- **Amazon Bedrock**: `use_bedrock: "true"`
- **Google Cloud’s Agent Platform**: `use_vertex: "true"`
- **Microsoft Foundry**: `use_foundry: "true"`
The complete workflow examples under [Set up the integration](#set-up-the-integration) already include the input for each provider.
[](#prerequisites)
Prerequisites
Before you start, you need:
- Admin access to the repository where the Claude Code GitHub Action runs, to install a GitHub App and add secrets
- Permission to create identity resources in your cloud account: IAM roles and OIDC identity providers on AWS, Workload Identity Federation resources and service accounts on Google Cloud, or Microsoft Entra applications on Azure
- Claude model access on your provider:
- **Amazon Bedrock**: access granted to Claude models. Cross-region inference profiles, such as the `us.` model IDs in this page’s examples, need access granted in every region of their region group. See [Claude Code on Amazon Bedrock](amazon-bedrock.md)
- **Google Cloud’s Agent Platform**: a project with the Agent Platform API enabled and access to Claude models. See [Claude Code on Google Cloud’s Agent Platform](google-vertex-ai.md)
- **Microsoft Foundry**: a Foundry resource with a Claude model deployment. See [Claude Code on Microsoft Foundry](microsoft-foundry.md)
[](#set-up-the-integration)
Set up the integration
Beyond the prerequisites, you create a GitHub identity for the Claude Code GitHub Action, the cloud-side trust configuration, the repository secrets, and the workflow file. The steps below walk through each.
1
Choose a GitHub identity
The Claude Code GitHub Action pushes commits and posts comments through a GitHub identity. The [quick setup](github-actions.md#quick-setup) installs the official Claude GitHub App for this. With a cloud provider, you choose the identity yourself:
- **Official [Claude GitHub App](https://github.com/apps/claude)**: install it on the repository, or skip to the next step if it’s already installed
- **Custom GitHub App**: create your own app when you want only the three permissions the Claude Code GitHub Action uses rather than the [official app’s full set](github-actions.md#github-app-permissions)
- **GitHub’s automatic `GITHUB_TOKEN`**: no app to create or install, but GitHub doesn’t trigger your CI workflows on commits made with it
The workflow examples in the fourth step authenticate with a custom app. That step also says what to change for the other two options.To create a custom app, [register a new GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) with webhooks disabled, since this integration doesn’t use them. Grant it three repository permissions:
- **Contents**: read and write
- **Issues**: read and write
- **Pull requests**: read and write
After registering the app, generate a private key and keep the downloaded `.pem` file, note the App ID from the app’s settings page, and [install the app](https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app) on the repository where the Claude Code GitHub Action runs. You add the key and the ID as secrets in the third step.
2
Configure cloud authentication
Configure your cloud to trust the OIDC token that GitHub issues to the workflow, so each workflow run gets short-lived cloud credentials. The bullets in each tab summarize what to create, and each tab links the cloud vendor’s own guide for the console-level steps.
- Amazon Bedrock
- Google Cloud's Agent Platform
- Microsoft Foundry
Create the trust configuration in your AWS account, following the [AWS guide to creating OIDC identity providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html):
- Add a GitHub OIDC identity provider with provider URL `https://token.actions.githubusercontent.com` and audience `sts.amazonaws.com`
- Create an IAM role trusted by that provider as a web identity, and attach the scoped invocation policy from [IAM configuration](amazon-bedrock.md#iam-configuration), which grants `bedrock:InvokeModel`, `bedrock:InvokeModelWithResponseStream`, `bedrock:ListInferenceProfiles`, and `bedrock:GetInferenceProfile`, along with two `aws-marketplace` subscription actions
- Limit the role’s trust policy to your repository with a subject condition such as `repo:your-org/your-repo:*`. See [GitHub’s OIDC hardening guide](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) for the claim format
Note the role’s ARN. You add it as a secret in the next step.
Create the federation resources in your Google Cloud project, following the [Workload Identity Federation documentation](https://cloud.google.com/iam/docs/workload-identity-federation):
- Enable three APIs: IAM Credentials, Security Token Service (STS), and the Agent Platform API, whose service name is `aiplatform.googleapis.com`
- Create a Workload Identity Pool with a GitHub OIDC provider whose issuer is `https://token.actions.githubusercontent.com`, and add an attribute condition that limits the pool to your repository
- Create a dedicated service account with only the `Vertex AI User` role, which is `roles/aiplatform.user`, and allow the pool to impersonate it
Note the provider’s full resource name and the service account’s email address. You add them as secrets in the next step.
Create a Microsoft Entra application with a federated credential for your repository, following [Microsoft’s guide to authenticating from GitHub Actions](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure-openid-connect):
- Register a Microsoft Entra application and add a federated identity credential that trusts tokens GitHub issues to your repository. A user-assigned managed identity works in place of an application. Both have the client ID you note below
- Assign the application the `Azure AI User` role on your Foundry resource. See [Azure RBAC configuration](microsoft-foundry.md#azure-rbac-configuration) for a narrower custom role
Note the application’s client ID, your tenant ID, and your subscription ID. You add them as secrets in the next step.
3
Add repository secrets
In the repository where the Claude Code GitHub Action runs, add the secrets for your provider, plus the two app secrets if you created a custom GitHub App in the first step. See GitHub’s guide to [using secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
| Secret | Needed for | Value |
|----------------------------------|-------------------------------|---------------------------------------------|
| `AWS_ROLE_TO_ASSUME` | Amazon Bedrock | The ARN of the IAM role |
| `GCP_WORKLOAD_IDENTITY_PROVIDER` | Google Cloud’s Agent Platform | The provider’s full resource name |
| `GCP_SERVICE_ACCOUNT` | Google Cloud’s Agent Platform | The service account’s email address |
| `AZURE_CLIENT_ID` | Microsoft Foundry | The Entra application’s client ID |
| `AZURE_TENANT_ID` | Microsoft Foundry | Your Microsoft Entra tenant ID |
| `AZURE_SUBSCRIPTION_ID` | Microsoft Foundry | Your Azure subscription ID |
| `APP_ID` | Custom GitHub App | The GitHub App’s ID |
| `APP_PRIVATE_KEY` | Custom GitHub App | The contents of the `.pem` private key file |
4
Create the workflow file
Create a workflow file for your provider, such as `.github/workflows/claude.yml`. Each example responds to `@claude` mentions, authenticates to GitHub with a custom app, and includes the `id-token: write` permission, which GitHub requires to issue the OIDC token that your cloud provider exchanges for credentials.If you chose a different GitHub identity in the first step, adjust the example:
- **Official Claude GitHub App**: delete the Generate GitHub App token step and the `github_token` line
- **GitHub’s automatic token**: delete the token-generation step and change the `github_token` line to `github_token: ${{ secrets.GITHUB_TOKEN }}`
On public repositories, a comment containing the trigger phrase from any user starts this workflow. The credential steps run before the Claude Code GitHub Action checks the commenter’s write access, so the action rejects unauthorized users only after the workflow has generated an App token and signed in to your cloud provider, which leaves audit-log entries and consumes Actions minutes. To avoid those runs, add a step that verifies the commenter’s write access before the credential steps.
- Amazon Bedrock
- Google Cloud's Agent Platform
- Microsoft Foundry
Replace the `aws-region` value with your own. The credentials step exports it as `AWS_REGION` for the rest of the job.
```python
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]
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') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- 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'
```
Bedrock model IDs include a cross-region inference profile prefix such as `us.`. Use the prefix for the region group where you granted model access.
Replace the `CLOUD_ML_REGION` value with your own. You don’t need to hardcode the project ID, because the workflow reads it from the `auth` step’s output.
```python
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]
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') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- 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 }}
use_vertex: "true"
claude_args: '--model claude-sonnet-5'
env:
ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }}
CLOUD_ML_REGION: us-east5
```
Replace `your-resource-name` with your Foundry resource name. Claude Code builds the endpoint URL from it. The `azure/login` step signs in with the workflow’s OIDC token, and Claude Code picks up the credentials through the Azure [default credential chain](https://learn.microsoft.com/en-us/azure/developer/javascript/sdk/authentication/credential-chains#defaultazurecredential-overview).
```python
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]
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') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- 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 Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.app-token.outputs.token }}
use_foundry: "true"
claude_args: '--model claude-sonnet-5'
env:
ANTHROPIC_FOUNDRY_RESOURCE: your-resource-name
```
Use a model ID that matches a Claude deployment in your Foundry resource. See [Claude Code on Microsoft Foundry](microsoft-foundry.md) for model configuration and version pinning.
With any provider, you can bound run length and cost by adding `--max-turns` to `claude_args`. See [Manage costs](github-actions.md#manage-costs).
5
Test the setup
Mention `@claude` in an issue or PR comment, then watch the run in the repository’s Actions tab. Claude replies in a comment on the same issue or PR.
[](#troubleshooting)
Troubleshooting
A failing run usually breaks in one of two places:
- **Authentication errors**: usually an OIDC misconfiguration. Check that the workflow includes the `id-token: write` permission, that the trust configuration’s repository condition matches your repository exactly, and that the secret names in your workflow match the ones you added
- **Trigger and CI problems**: these behave the same as when the Claude Code GitHub Action calls the Claude API. See the main page’s [troubleshooting section](github-actions.md#troubleshooting) and the Claude Code GitHub Action’s [FAQ](https://github.com/anthropics/claude-code-action/blob/main/docs/faq.md)
[](#what’s-next)
What’s next
- [Claude Code GitHub Actions](github-actions.md) for examples, parameters, and best practices
- [Claude Code on Amazon Bedrock](amazon-bedrock.md) for Bedrock model IDs and regions
- [Claude Code on Google Cloud’s Agent Platform](google-vertex-ai.md) for Agent Platform model IDs and regions
- [Claude Code on Microsoft Foundry](microsoft-foundry.md) for Foundry model and endpoint configuration
---
## Claude Code GitHub Actions - Claude Code Docs
Source: https://code.claude.com/docs/en/github-actions
Path: 02-Claude-Code-CLI/github-actions.md
## On this page
- [Setup](#setup)
- [Quick setup](#quick-setup)
- [Manual setup](#manual-setup)
- [Set up for an organization](#set-up-for-an-organization)
- [Uninstall](#uninstall)
- [GitHub App permissions](#github-app-permissions)
- [Interactive and automation modes](#interactive-and-automation-modes)
- [Who can trigger runs](#who-can-trigger-runs)
- [Example use cases](#example-use-cases)
- [Respond to @claude mentions](#respond-to-%40claude-mentions)
- [Run a skill](#run-a-skill)
- [Run on a schedule](#run-on-a-schedule)
- [Best practices](#best-practices)
- [Define project standards in CLAUDE.md](#define-project-standards-in-claude-md)
- [Protect your credentials](#protect-your-credentials)
- [Manage costs](#manage-costs)
- [Use a cloud provider](#use-a-cloud-provider)
- [Troubleshooting](#troubleshooting)
- [Claude not responding to @claude commands](#claude-not-responding-to-%40claude-commands)
- [CI not running on Claude’s commits](#ci-not-running-on-claude%E2%80%99s-commits)
- [Authentication errors](#authentication-errors)
- [Advanced configuration](#advanced-configuration)
- [Action parameters](#action-parameters)
- [Pass CLI arguments](#pass-cli-arguments)
- [Upgrade from beta](#upgrade-from-beta)
- [What’s next](#what%E2%80%99s-next)
Code review & CI/CD
# Claude Code GitHub Actions
Copy pageCopy page
Run Claude Code in GitHub Actions workflows to respond to @claude mentions, automate tasks, and turn issues into pull requests
Copy pageCopy page
[Claude Code GitHub Actions](https://github.com/anthropics/claude-code-action) is a GitHub Action that runs Claude Code inside your repository’s workflows. Mention `@claude` in a pull request or issue comment to have Claude analyze code, implement changes, and push commits. You can also give the Claude Code GitHub Action a prompt to run automatically on any GitHub event. Use it to turn issues into pull requests, fix bugs from a comment, or automate recurring tasks. Several products share the Claude Code name. This page covers the `claude-code-action` workflow integration, which you configure with workflow files in your repository. For the related products, see:
- [Code Review](code-review.md): automatic review on every pull request, without writing a workflow
- [Claude Code in the cloud](claude-code-on-the-web.md): Claude Code sessions that run on cloud infrastructure instead of your machine
- [Claude Agent SDK](../05-Agent-SDK/agent-sdk-overview.md): custom automation outside GitHub Actions. The Claude Code GitHub Action is built on the SDK
- [GitHub Enterprise Server](github-enterprise-server.md): Claude Code with self-hosted GitHub
[](#setup)
Setup
You can set up the Claude Code GitHub Action in one of two ways:
- **Quick setup**: run `/install-github-app` from Claude Code. Claude Code installs the GitHub App, adds your authentication secret, and prepares the workflow pull request for you
- **Manual setup**: install the app, add the secret, and copy the workflow file into your repository yourself. Use this path when you don’t run Claude Code locally, when the command fails, or when you want full control of the workflow files
For either path, you need admin access to the repository.
[](#quick-setup)
Quick setup
`/install-github-app` works only with github.com repositories. If your repository’s git remote is on gitlab.com or bitbucket.org, the command prints a notice and exits instead of starting setup. To run Claude Code from GitLab pipelines, see [Claude Code GitLab CI/CD](gitlab-ci-cd.md). Before you start, install the [GitHub CLI](https://cli.github.com) and authenticate it with `gh auth login`. Claude Code checks for it and warns you if it’s missing. Open `claude` in the repository you want to connect, run `/install-github-app`, and follow the prompts. Claude Code installs the Claude GitHub App, then sets up an authentication secret for the workflows:
- If Claude Code already has an API key, it reuses that key, and offers to keep the repository’s existing `ANTHROPIC_API_KEY` secret if one is already set
- Otherwise, choose between creating a long-lived token with your Claude subscription and pasting in an API key
Claude Code saves the credential as a repository secret, named `ANTHROPIC_API_KEY` for an API key or `CLAUDE_CODE_OAUTH_TOKEN` for a subscription token. Claude Code then pushes a branch with the workflow files you select, already set to use that secret, and opens GitHub in your browser with a pull request ready to create. Create and merge that pull request, and `@claude` works in the repository. To stop setup partway through, press Esc. A step already in progress finishes, and no later step starts. The closing message lists what already happened in the repository, such as a pushed branch or a saved secret. If you select the review workflow, Claude posts each review on the pull request itself, as an inline comment on each issue it finds or as one summary comment when it finds none. Claude skips some pull requests, such as drafts. The [review workflow example](#run-a-skill) uses the same skill and lists them. Before v2.1.229, Claude wrote its review only to the workflow run log. To update a review workflow that an earlier version generated, do one of the following:
- Run `/install-github-app` again. When the repository already has a `claude.yml`, select **Update workflow file with latest version**. Claude Code pushes fresh copies of the workflow files to a new branch and opens the pull request, the same as a first install.
- Add the `--comment` argument and the `claude_args` line from the [review workflow example](#run-a-skill) to the checked-in file yourself, which keeps any other edits you made to it.
After installing the GitHub App, Claude Code asks whether to continue with GitHub Actions setup. Choose **Skip for now** to stop with only the GitHub App installed. Run `/install-github-app` again later to finish the workflow and secret steps.
- When you install the GitHub App, you grant it several permissions. See [GitHub App permissions](#github-app-permissions) for the full set
- Quick setup works with the Claude API and Claude subscriptions. If you use Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry, see [Use Claude Code GitHub Actions with cloud providers](github-actions-cloud-providers.md)
[](#manual-setup)
Manual setup
To configure the Claude Code GitHub Action without running `/install-github-app`, install the app, add a secret, and copy a workflow file yourself:
1
Install the Claude GitHub App
Install the [Claude GitHub App](https://github.com/apps/claude) to your repository. The Claude Code GitHub Action relies on three of the app’s permissions:
- **Contents**: read and write, so Claude can modify repository files
- **Issues**: read and write, so Claude can respond to issues
- **Pull requests**: read and write, so Claude can create PRs and push changes
During installation, you also grant permissions that other Claude features use. See [GitHub App permissions](#github-app-permissions) for the full set.
2
Add an authentication secret
Add one of the following secrets to your repository, depending on how you authenticate. See GitHub’s guide to [using secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
- `ANTHROPIC_API_KEY`: a Claude API key from the [Claude Console](../04-API-Reference/Other/usage-limits.md)
- `CLAUDE_CODE_OAUTH_TOKEN`: an OAuth token that authenticates with your Claude subscription, available on Pro, Max, Team, and Enterprise plans. Generate one by running `claude setup-token` locally. See [Generate a long-lived token](../13-Enterprise-Admin/iam.md#generate-a-long-lived-token)
In workflow files, pass the secret to the matching input: `anthropic_api_key` for an API key, or `claude_code_oauth_token` for an OAuth token.
3
Copy the workflow file
Copy [examples/claude.yml](https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml) into your repository’s `.github/workflows/` directory. The file is a working workflow, not just an example. As committed, Claude responds whenever someone mentions `@claude` in an issue or pull request, authenticating with the `ANTHROPIC_API_KEY` secret. If you added `CLAUDE_CODE_OAUTH_TOKEN` instead, change the workflow’s `anthropic_api_key` line to `claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}`.
After setup, test the Claude Code GitHub Action by tagging `@claude` in an issue or PR comment.
[](#set-up-for-an-organization)
Set up for an organization
With quick setup or manual setup, you configure one repository at a time. To roll the Claude Code GitHub Action out across an organization:
- Install the [Claude GitHub App](https://github.com/apps/claude) once at the organization level, choosing all repositories or a selected list
- Store the authentication secret as an organization-level Actions secret so each repository doesn’t need its own copy
- Add the workflow file to each repository that should run the Claude Code GitHub Action, or define the job once as a [reusable workflow](https://docs.github.com/en/actions/using-workflows/reusing-workflows) that each repository calls
For a secret shared across repositories, authenticate with an API key from the [Claude Console](../04-API-Reference/Other/usage-limits.md) rather than an OAuth token, since an OAuth token is tied to the subscription of the person who ran `claude setup-token`. To avoid storing a long-lived secret entirely, authenticate through workload identity federation, where the Claude Code GitHub Action exchanges the workflow’s GitHub OpenID Connect (OIDC) token for Claude API access through a Claude Console service account. Set these inputs:
- `anthropic_federation_rule_id`: the federation rule ID, `fdrl_...`
- `anthropic_organization_id`: your Anthropic organization ID
- `anthropic_service_account_id`: the service account ID, `svac_...`. Optional, since the federation rule you create in the Console already targets a service account
- `anthropic_workspace_id`: the workspace ID, `wrkspc_...`. Optional when the federation rule targets a single workspace
Grant the workflow the `id-token: write` permission, which the Claude Code GitHub Action needs for the federation exchange even when you pass your own `github_token`. See the [Claude Code GitHub Action’s setup guide](https://github.com/anthropics/claude-code-action/blob/main/docs/setup.md) for the Console-side configuration. For data handling and retention questions in a security review, see [data usage](../13-Enterprise-Admin/data-usage.md) and [security](../13-Enterprise-Admin/security.md).
[](#uninstall)
Uninstall
To remove the Claude Code GitHub Action, undo each piece of the setup that applies to your installation:
- **Workflow files**: delete the workflows that use `anthropics/claude-code-action` from `.github/workflows/`. If you used quick setup, look for `claude.yml` and, if you selected the review workflow, `claude-code-review.yml`. With the workflows deleted, the Claude Code GitHub Action no longer runs
- **Secrets**: delete the `ANTHROPIC_API_KEY` or `CLAUDE_CODE_OAUTH_TOKEN` secret from the repository, and from organization-level Actions secrets if you [shared it across repositories](#set-up-for-an-organization). If you delete a secret, the credential it held stays valid. To retire an API key entirely, also delete the key in the [Claude Console](../04-API-Reference/Other/usage-limits.md)
- **GitHub App**: uninstall the Claude GitHub App in your repository or organization settings under GitHub Apps, but only if you don’t use it for another Claude feature, such as Code Review or web auto-fix
If you configured a [cloud provider](github-actions-cloud-providers.md), also delete the provider secrets, such as `AWS_ROLE_TO_ASSUME`, the `GCP_*` secrets, or the `AZURE_*` secrets, and uninstall the custom GitHub App along with its `APP_ID` and `APP_PRIVATE_KEY` secrets.
[](#github-app-permissions)
The [Claude GitHub App](https://github.com/apps/claude) is shared by every Claude feature that integrates with GitHub, including the Claude Code GitHub Action, [Code Review](code-review.md), and [auto-fix for pull requests](claude-code-on-the-web.md#auto-fix-pull-requests) in cloud sessions. A GitHub App has a single permission set covering all of its features, so the set includes some permissions that the Claude Code GitHub Action doesn’t use. When you install the app, you grant the following permissions:
| Permission | Access |
|------------------|----------------|
| Actions | Read and write |
| Checks | Read and write |
| Contents | Read and write |
| Discussions | Read and write |
| Issues | Read and write |
| Members | Read |
| Metadata | Read |
| Pull requests | Read and write |
| Repository hooks | Read and write |
| Statuses | Read |
| Workflows | Read and write |
The permission set can also change ahead of the features that use it. When the app requests a permission it didn’t have before, GitHub prompts the account owner to approve it, an organization owner for an organization install, and the installation keeps its old permissions until they do. For example, when Actions access changes from read to write, the app can re-run workflows rather than only view runs and logs, so GitHub asks the owner to approve the change. When you install the app, you accept its full permission set. GitHub doesn’t let you accept a subset. If your organization requires only the permissions the Claude Code GitHub Action uses, create a custom GitHub App with Contents, Issues, and Pull requests instead, following the [Claude Code GitHub Action’s setup guide](https://github.com/anthropics/claude-code-action/blob/main/docs/setup.md). A custom app covers only the Claude Code GitHub Action. Code Review and web auto-fix still require the official app. For details on how the Claude Code GitHub Action limits what Claude can do with these permissions, see the [security documentation](https://github.com/anthropics/claude-code-action/blob/main/docs/security.md).
[](#interactive-and-automation-modes)
Interactive and automation modes
The Claude Code GitHub Action detects how to run from your workflow configuration:
- **Interactive mode**: when the workflow provides no `prompt` input, Claude waits for the trigger phrase, `@claude` by default, in an issue or pull request comment, in a pull request review, or in the body or title of a newly opened issue, then responds to that request. Progress and results appear as a comment on the triggering issue or PR.
- **Automation mode**: when the workflow provides a `prompt` input, Claude runs without waiting for a mention, subject only to the [checks on who can trigger runs](#who-can-trigger-runs). By default, results appear in the workflow run log rather than a comment. Claude can post to the issue or pull request when the prompt directs it to and it has a tool that can post, as in the [code-review example](#run-a-skill).
[](#who-can-trigger-runs)
Who can trigger runs
In both modes, the Claude Code GitHub Action runs two checks on the triggering actor before Claude starts, and the run fails when either check rejects it:
- **Write access**: on issue and pull request events, the triggering user must have write access to the repository. To allow specific users without write access, set `allowed_non_write_users` and pass your own `github_token` input. Events that no user authors, such as a `schedule` trigger, skip this check.
- **Human actor**: on every event, the Claude Code GitHub Action rejects a bot actor unless you list it in `allowed_bots`, which keeps bots from triggering Claude in a loop. This check also applies to scheduled runs, which GitHub attributes to a repository user, usually the one who last changed the workflow’s `cron` schedule. If that user is a bot, list it in `allowed_bots`.
[](#example-use-cases)
Example use cases
The [examples directory](https://github.com/anthropics/claude-code-action/tree/main/examples) contains ready-to-use workflows for different scenarios. The examples on this page show API key authentication. If you authenticate with a Claude subscription, replace the `anthropic_api_key` line in any example with `claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}`.
[](#respond-to-@claude-mentions)
Respond to @claude mentions
This workflow runs the Claude Code GitHub Action in interactive mode, so Claude responds whenever someone mentions `@claude` in an issue or PR comment.
```python
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
```
The parts of this workflow that aren’t boilerplate:
- `id-token: write`: required for the Claude Code GitHub Action’s default GitHub App authentication
- `actions: read`: lets Claude read CI results on PRs
- `actions/checkout`: gives Claude a local copy of the repository to work in
- `if`: keeps runners from starting on comments that don’t mention `@claude`. The Claude Code GitHub Action also checks the trigger phrase itself before responding
Once the workflow is in place, mention `@claude` in any issue or PR comment with a request:
```python
@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 replies in a comment on the same issue or PR and updates it as it works.
[](#run-a-skill)
Run a skill
The `prompt` input accepts a [skill](../08-Plugins-Skills/skills.md) invocation as well as plain text:
- For a skill in your repository’s `.claude/skills/` directory, run `actions/checkout` before the `anthropics/claude-code-action` step so the skill files are available on the runner, then pass `/skill-name` as the `prompt`.
- For a skill packaged in a [plugin](../08-Plugins-Skills/plugins.md), install the plugin with the `plugin_marketplaces` and `plugins` inputs, then pass the namespaced `/plugin-name:skill-name` as the `prompt`. The `plugins` input takes `plugin-name@marketplace-name`, where the marketplace name comes from the marketplace’s own manifest rather than its repository URL.
The following workflow installs the `code-review` plugin and runs its skill when a pull request is opened, updated, reopened, or marked ready for review. It runs the same plugin as the review workflow from quick setup. Use a workflow like this when you want to control the prompt, model, and triggers yourself. For automatic reviews without maintaining a workflow file, see [Code Review](code-review.md). On public repositories, GitHub withholds secrets from runs triggered by fork pull requests, so the review runs only on pull requests from branches in the same repository.
```python
name: Code Review
on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- 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 --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment"'
```
Two lines in this workflow control where the review goes:
- **`--comment`**: Claude posts its review on the pull request, as an inline comment on each issue it finds or as one summary comment when it finds none. Without it, Claude posts nothing, and you read the findings in the workflow run log.
- **`claude_args`**: keep this line even though the skill’s own `allowed-tools` frontmatter names the same tool, because the Claude Code GitHub Action starts the MCP server that posts inline comments only when `--allowedTools` in `claude_args` names it.
Claude skips draft and closed pull requests, pull requests it judges not to need a review, such as automated or trivial ones, and pull requests that already have a comment from Claude.
[](#run-on-a-schedule)
Run on a schedule
With a `prompt` input, the Claude Code GitHub Action runs in automation mode on any GitHub event, including a cron schedule. For a plain-text prompt, Claude has no shell or GitHub API access until you grant the tools the prompt needs, with `--allowedTools` in `claude_args` or a [`permissions.allow` rule](permissions.md#permission-rule-syntax) in the `settings` input. If you invoke a skill instead, Claude can use the tools its [`allowed-tools` frontmatter](../08-Plugins-Skills/skills.md#pre-approve-tools-for-a-skill) grants. GitHub runs scheduled workflows only from the default branch and, in public repositories, disables the schedule after 60 days without repository activity. This workflow generates a report in the workflow run log at 09:00 UTC each day. Its `claude_args` line [passes CLI arguments](#pass-cli-arguments) that select the model and allow two GitHub MCP tools. Claude reads commits and issues through the GitHub API with those tools, so you can omit the checkout step:
```python
name: Daily Report
on:
schedule:
- cron: "0 9 * * *"
jobs:
report:
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
id-token: write
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 claude-opus-5-5
--allowedTools "mcp__github__list_commits,mcp__github__list_issues"
```
[](#best-practices)
Best practices
[](#define-project-standards-in-claude-md)
Define project standards in CLAUDE.md
Create a `CLAUDE.md` file in your repository root to define code style guidelines, review criteria, project-specific rules, and preferred patterns. Claude follows these guidelines when creating PRs and responding to requests. See the [memory documentation](memory.md) for details.
[](#protect-your-credentials)
Protect your credentials
Never commit API keys or OAuth tokens directly to your repository. Always store them as GitHub Secrets and reference them in workflows, for example `anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}`.
Grant the workflow only the permissions it needs, and review Claude’s changes before merging. For comprehensive security guidance including permissions and authentication, see the [Claude Code Action security documentation](https://github.com/anthropics/claude-code-action/blob/main/docs/security.md).
[](#manage-costs)
Manage costs
Each run consumes two kinds of resources:
- **GitHub Actions minutes**: the Claude Code GitHub Action runs on GitHub-hosted runners, which consume your GitHub Actions minutes. See [GitHub’s billing documentation](https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions) for pricing and minute limits.
- **API tokens**: each interaction consumes tokens based on the length of prompts and responses, task complexity, and codebase size. See [Claude’s pricing page](https://claude.com/platform/api) for current token rates. If you authenticate with an OAuth token, runs use your Claude subscription instead of API billing.
You can lower both kinds of cost by giving Claude clearer context and by capping how much work each run can do:
- Write specific `@claude` requests so Claude needs fewer turns to finish
- Use issue templates to provide context up front
- Keep your `CLAUDE.md` concise, since Claude reads it on every run
- Set `--max-turns` in `claude_args` to limit iterations
- Set workflow-level timeouts to avoid runaway jobs
- Use GitHub’s concurrency controls to limit parallel runs
For usage tracking across your organization, see the [analytics dashboard](../13-Enterprise-Admin/analytics.md) and [monitoring](../13-Enterprise-Admin/monitoring-usage.md). For how usage is measured and billed, see [costs](../17-Billing-Plans/costs.md).
[](#use-a-cloud-provider)
Use a cloud provider
By default, the Claude Code GitHub Action calls the Claude API directly with your API key or OAuth token. To route inference through your own cloud account instead, set the input for your provider and follow [Use Claude Code GitHub Actions with cloud providers](github-actions-cloud-providers.md):
- **Amazon Bedrock**: `use_bedrock: "true"`
- **Google Cloud’s Agent Platform**: `use_vertex: "true"`
- **Microsoft Foundry**: `use_foundry: "true"`
With all three providers, you authenticate through OIDC identity federation instead of a Claude API key, so you store no static cloud credentials in your repository.
[](#troubleshooting)
Troubleshooting
[](#claude-not-responding-to-@claude-commands)
Claude not responding to @claude commands
- Verify the GitHub App is installed on the repository
- Check that workflows are enabled for the repository
- Ensure your API key or OAuth token is set in repository secrets
- Confirm the comment contains `@claude` as a complete word, not `/claude` or `@claude-bot`
- Confirm the commenting user has write access to the repository. See [Who can trigger runs](#who-can-trigger-runs) for the exceptions
[](#ci-not-running-on-claude’s-commits)
CI not running on Claude’s commits
- GitHub doesn’t trigger workflows on commits made with the default `GITHUB_TOKEN`. If you pass `github_token: ${{ secrets.GITHUB_TOKEN }}` to the Claude Code GitHub Action, remove it so it authenticates as the Claude GitHub App, or pass a custom app token instead
- Check that your CI workflow’s triggers include the events Claude’s pushes produce, such as `push` or `pull_request`
[](#authentication-errors)
Authentication errors
- Confirm the API key or OAuth token is valid by testing it locally with `claude` before debugging the workflow
- For Bedrock, Agent Platform, and Foundry, see the cloud provider page’s [troubleshooting section](github-actions-cloud-providers.md#troubleshooting)
For more solutions, see the Claude Code GitHub Action’s [FAQ](https://github.com/anthropics/claude-code-action/blob/main/docs/faq.md).
[](#advanced-configuration)
Advanced configuration
[](#action-parameters)
Action parameters
These are the most commonly used inputs. Each maps to a `with:` key in the `anthropics/claude-code-action` step.
| Parameter | Description | Required |
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `prompt` | Instructions for Claude, as plain text or a [skill](../08-Plugins-Skills/skills.md) invocation. When omitted, Claude responds to the [trigger phrase](#interactive-and-automation-modes) instead | No |
| `claude_args` | CLI arguments passed to Claude Code | No |
| `anthropic_api_key` | Claude API key | For the Claude API, unless you use `claude_code_oauth_token` or [workload identity federation](#set-up-for-an-organization). Not used for Bedrock, Agent Platform, or Foundry |
| `claude_code_oauth_token` | OAuth token for authenticating with a Claude subscription, generated with `claude setup-token` | No |
| `github_token` | Token for GitHub operations. When omitted, the Claude Code GitHub Action authenticates as the Claude GitHub App | No |
| `plugin_marketplaces` | Newline-separated list of plugin marketplace Git URLs | No |
| `plugins` | Newline-separated list of plugin names to install before execution | No |
| `settings` | Claude Code settings, as a JSON string or a path to a settings JSON file | No |
| `trigger_phrase` | Trigger phrase Claude responds to. Default: `@claude` | No |
| `use_bedrock` | Use Amazon Bedrock instead of the Claude API | No |
| `use_vertex` | Use Google Cloud’s Agent Platform instead of the Claude API | No |
| `use_foundry` | Use Microsoft Foundry instead of the Claude API | No |
For the full input list, see the Claude Code GitHub Action’s [configuration reference](https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md#inputs).
[](#pass-cli-arguments)
Pass CLI arguments
The `claude_args` parameter accepts any [Claude Code CLI argument](cli-reference.md):
```python
claude_args: "--max-turns 5 --model claude-sonnet-5 --mcp-config /path/to/config.json"
```
Common arguments:
- `--max-turns`: limit the number of conversation turns
- `--model`: model to use, for example `claude-sonnet-5`. Without this argument, the Claude Code GitHub Action uses the Claude Code [default model](model-config.md)
- `--mcp-config`: path to [MCP configuration](../06-MCP-Tools/General/mcp.md)
- `--allowedTools`: comma-separated list of allowed tools. The `--allowed-tools` alias also works
- `--debug`: enable debug output
[](#upgrade-from-beta)
Upgrade from beta
If your workflows still reference `anthropics/claude-code-action@beta`, update them to v1:
1. Change `@beta` to `@v1` in the `uses` line
2. Remove the `mode` input, since the Claude Code GitHub Action now [detects the mode automatically](#interactive-and-automation-modes)
3. Replace `direct_prompt` with `prompt`
4. Move CLI options such as `max_turns` and `model` into `claude_args`. `custom_instructions` has no same-name flag and becomes `--append-system-prompt`
For the full input mapping and before-and-after examples, see the [migration guide](https://github.com/anthropics/claude-code-action/blob/main/docs/migration-guide.md).
[](#what’s-next)
What’s next
- [Use Claude Code GitHub Actions with cloud providers](github-actions-cloud-providers.md): route inference through Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry
- [Configuration reference](https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md#inputs): the full list of action inputs
- [Examples directory](https://github.com/anthropics/claude-code-action/tree/main/examples): ready-to-use workflows for more scenarios
- [Code Review](code-review.md): automatic pull request review without maintaining a workflow file
---
## Claude Code with GitHub Enterprise Server - Claude Code Docs
Source: https://code.claude.com/docs/en/github-enterprise-server
Path: 02-Claude-Code-CLI/github-enterprise-server.md
## On this page
- [What works with GitHub Enterprise Server](#what-works-with-github-enterprise-server)
- [Admin setup](#admin-setup)
- [GitHub App permissions](#github-app-permissions)
- [Manual setup](#manual-setup)
- [Network requirements](#network-requirements)
- [Developer workflow](#developer-workflow)
- [Teleport sessions to your terminal](#teleport-sessions-to-your-terminal)
- [Plugin marketplaces on GHES](#plugin-marketplaces-on-ghes)
- [Add a GHES marketplace](#add-a-ghes-marketplace)
- [Pre-register GHES marketplaces with managed settings](#pre-register-ghes-marketplaces-with-managed-settings)
- [Allowlist GHES marketplaces in managed settings](#allowlist-ghes-marketplaces-in-managed-settings)
- [Limitations](#limitations)
- [Troubleshooting](#troubleshooting)
- [Cloud session fails to clone repository](#cloud-session-fails-to-clone-repository)
- [Marketplace add fails with a policy error](#marketplace-add-fails-with-a-policy-error)
- [Marketplace add on claude.ai fails with a GitHub access error](#marketplace-add-on-claude-ai-fails-with-a-github-access-error)
- [GHES instance not reachable](#ghes-instance-not-reachable)
- [Session start fails with Unable to get organization UUID](#session-start-fails-with-unable-to-get-organization-uuid)
- [Related resources](#related-resources)
Code review & CI/CD
# Claude Code with GitHub Enterprise Server
Copy pageCopy page
Connect Claude Code to your self-hosted GitHub Enterprise Server instance for cloud sessions, code review, and plugin marketplaces.
Copy pageCopy page
[](#what-works-with-github-enterprise-server)
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 |
|:---------------------|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------|
| Cloud sessions | ✅ Supported | An Owner connects the GHES instance once; developers use `claude --cloud` or [claude.ai/code](https://claude.ai/code) as usual |
| Code Review | ✅ Supported | Same automated PR reviews as github.com |
| Claude Security | ✅ Supported | Available in public beta for Enterprise plans at [claude.ai/security](https://claude.ai/security) |
| Teleport sessions | ✅ Supported | Move sessions between cloud and terminal with `--teleport` |
| Plugin marketplaces | ✅ Supported | Credential requirements differ by surface. See [Plugin marketplaces on GHES](#plugin-marketplaces-on-ghes) |
| Contribution metrics | ✅ Supported | Delivered via webhooks to the [analytics dashboard](../13-Enterprise-Admin/analytics.md) |
| 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)
Admin setup
An Owner connects your GHES instance to Claude Code once. After that, developers in your organization can use GHES repositories without any additional configuration. You need the Owner or Primary Owner role in 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](#manual-setup) is available.
1
Open Claude Code admin settings
Go to [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) and find the GitHub Enterprise Server section.
2
Start the guided setup
Click **Connect**. Enter a display name of up to 20 characters 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](https://claude.ai/admin-settings/claude-code) and enable [Code Review](code-review.md#set-up-code-review), Claude Security, and [contribution metrics](../13-Enterprise-Admin/analytics.md#enable-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 below, which together cover cloud sessions, Code Review, Claude Security, plugin marketplaces, 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 |
| Commit statuses | Read | Reading CI status from providers that report commit statuses instead of check runs |
| Repository hooks | Read and write | Creating a webhook on a plugin marketplace repository when **Sync automatically** is turned on for a marketplace in [**Organization settings \> Plugins & skills**](https://claude.ai/admin-settings/skills?tab=marketplaces) |
| Metadata | Read | Required by GitHub for all apps |
| Organization members | Read | Matching the Claude GitHub App on github.com, which uses it to check a connecting user’s organization role when linking an installation |
The app subscribes to `pull_request`, `issue_comment`, `pull_request_review_comment`, `pull_request_review`, `check_run`, and `status` events. GitHub applies a manifest only when the app is created, so an app created from an earlier version of the manifest keeps the permissions and events it was created with. If your app is missing any of the permissions or events above, add them in the app’s settings on your GHES instance. GitHub then asks an owner of each installation to approve the new permissions, and the installation keeps its old permissions until they do.
[](#manual-setup)
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](#github-app-permissions), then enter the connection details in the form: a display name, your GHES hostname and optional port, and the app’s ID, client ID, client secret, webhook secret, and private key. The form also accepts an optional custom CA certificate and read replica hostnames. Claude generates the app’s webhook URL when you save the connection. After you click **Add configuration**, open the connection’s **More options** menu, select **Copy webhook URL**, and paste the URL into the app’s webhook settings on your GHES instance. Use the same webhook secret you entered in the form.
[](#network-requirements)
Network requirements
For Anthropic-hosted sessions, 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 Anthropic’s [outbound IP addresses](../04-API-Reference/Endpoints/ip-addresses.md#outbound-ip-addresses). Sessions in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments-deploy.md#configure-git) clone from inside your network instead, unless the runner opts into the [Anthropic git proxy](../13-Enterprise-Admin/self-hosted-environments-deploy.md#use-the-anthropic-git-proxy), which fetches from Anthropic’s side and needs the same reachability. Hosted pre-session flows, such as the repository picker, run on Anthropic’s side before a session starts. They need your GHES instance to be reachable from Anthropic infrastructure even when the session runs in a self-hosted environment. The [SCM connector](../13-Enterprise-Admin/self-hosted-environments-reference.md#scm-connector-flags) isn’t available, so those flows can’t reach a GHES host that’s only routable internally.
[](#developer-workflow)
Developer workflow
Once an Owner 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, replacing `github.example.com` and the repository path with your GHES hostname and repository:
```python
git clone git@github.example.com:platform/api-service.git
cd api-service
```
Then start a cloud session. Claude detects the GHES host from your git remote and routes the session through your organization’s configured instance:
```python
claude --cloud "Add retry logic to the payment webhook handler"
```
The session clones your repository from GHES and pushes changes back to a branch. Monitor progress at [claude.ai/code](https://claude.ai/code). See [Use Claude Code in the cloud](claude-code-on-the-web.md) for the full cloud session workflow including diff review, auto-fix, and routines.
[](#teleport-sessions-to-your-terminal)
Teleport sessions to your terminal
Pull a cloud 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](claude-code-on-the-web.md#teleport-requirements) for details.
[](#plugin-marketplaces-on-ghes)
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, but installation works differently depending on where you add the marketplace, and credentials differ across surfaces:
| Surface | How installation works | What each user needs |
|:--------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Claude Code CLI and desktop | Claude Code clones the marketplace repository using the machine’s existing git credentials | Git access to your GHES host from their machine |
| Managed settings (`extraKnownMarketplaces`) | Claude Code registers the entry and clones the repository using the machine’s existing git credentials | Git access to your GHES host from their machine |
| claude.ai organization plugin settings | An Owner selects the GHES instance as the source; Anthropic’s backend fetches and syncs the repository using the GitHub App from [admin setup](#admin-setup) | Nothing per user once added. The Owner adding it needs their own GitHub Enterprise account connected as an access check, and the GitHub App must be installed on the marketplace repository |
| claude.ai user settings | Anthropic’s backend fetches the repository using the submitting user’s GitHub Enterprise connection | Their own GitHub Enterprise account connected to Claude |
| Cloud sessions | Cloud sessions clone marketplaces inside the session sandbox. The sandbox can reach your GHES instance only when the session’s repository is on that same instance, and its git credentials are scoped to the session’s repositories | Not reliable for GHES-hosted marketplaces: a different host than the session’s repository is not reachable, and even same-instance installs can fail. Use the CLI, managed settings, or claude.ai instead |
[](#add-a-ghes-marketplace)
Add a GHES marketplace
The `owner/repo` shorthand always resolves to github.com. For GHES-hosted marketplaces, use the full git URL, replacing `github.example.com` and the repository path with your own. HTTPS URLs are recommended:
```python
/plugin marketplace add https://github.example.com/platform/claude-plugins.git
```
SSH URLs work if the machine already trusts your GHES host:
```python
/plugin marketplace add git@github.example.com:platform/claude-plugins.git
```
Claude Code runs git non-interactively and rejects SSH connections to hosts that are not in the machine’s `known_hosts` file. An HTTPS URL with a git credential helper avoids the `known_hosts` requirement. See [Create and distribute a plugin marketplace](../08-Plugins-Skills/plugin-marketplaces.md) for the full guide to building marketplaces.
[](#pre-register-ghes-marketplaces-with-managed-settings)
Pre-register GHES marketplaces with managed settings
The `extraKnownMarketplaces` setting pre-registers a marketplace so developers get it without manual setup. It works from [any settings file](settings-reference.md#extraknownmarketplaces), including a repository’s `.claude/settings.json`; managed settings deliver it organization-wide:
```python
{
"extraKnownMarketplaces": {
"internal-tools": {
"source": {
"source": "git",
"url": "https://github.example.com/platform/claude-plugins.git"
}
}
}
}
```
Claude Code installs these marketplaces locally: it registers each entry and clones the repository with the machine’s existing git credentials. This path does not go through claude.ai, so the per-user GitHub Enterprise connection is not required. For a successful rollout:
- **Use a full git URL.** The `owner/repo` shorthand always resolves to github.com and cannot reference a GHES host.
- **Prefer HTTPS URLs.** SSH clones fail on machines that do not already trust your GHES host key. An HTTPS URL with your organization’s standard git credential helper works on any machine with credentials configured.
- **Confirm each machine can clone from your GHES host.** If a machine lacks credentials, the marketplace is registered but never installed, and its plugins report as not found instead of prompting for credentials.
- **Confirm the setting reaches each machine.** A managed settings file only takes effect on machines it’s deployed to, for example through your device management system. See [Deploy managed settings](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) for file locations.
[](#allowlist-ghes-marketplaces-in-managed-settings)
Allowlist GHES marketplaces in managed settings
If your organization uses [managed settings](settings.md) to restrict which marketplaces developers can add, use the `hostPattern` source type to allow all marketplaces from your GHES instance without enumerating each repository. See [Delivery mechanisms](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) for file locations on each platform. Add the JSON to your `managed-settings.json` file or equivalent MDM policy:
```python
{
"strictKnownMarketplaces": [
{
"source": "hostPattern",
"hostPattern": "^github\\.example\\.com$"
}
]
}
```
See the [strictKnownMarketplaces](settings-reference.md#strictknownmarketplaces) and [extraKnownMarketplaces](settings-reference.md#extraknownmarketplaces) settings reference for the complete schema.
[](#limitations)
Limitations
A few features behave differently on GHES than on github.com. The [feature table](#what-works-with-github-enterprise-server) summarizes support; this section covers the workarounds.
- **`/install-github-app` command**: follow the [admin setup](#admin-setup) flow on claude.ai instead. If you also want GitHub Actions workflows on GHES, adapt the [example workflow](https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml) 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)
Troubleshooting
[](#cloud-session-fails-to-clone-repository)
Cloud session fails to clone repository
If `claude --cloud` fails with a clone error, verify that an Owner has completed setup for your GHES instance and that the GitHub App is installed on the repository you’re working in. Ask the Owner who connected the instance to confirm that the hostname registered in Claude settings matches the hostname in your git remote.
[](#marketplace-add-fails-with-a-policy-error)
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](#allowlist-ghes-marketplaces-in-managed-settings).
[](#marketplace-add-on-claude-ai-fails-with-a-github-access-error)
Marketplace add on claude.ai fails with a GitHub access error
If adding a GHES marketplace from your user settings fails with a generic error like “Marketplace couldn’t be added”, check your GitHub Enterprise connection first. This is what appears when your own GitHub Enterprise account is not connected to Claude, even if your organization’s GHES instance is configured and other users are connected. The dialog does not point to the GitHub Enterprise connect flow, and the “Connect to GitHub” option on the Browse tab signs in to github.com, which does not grant access to GHES repositories. To connect your GitHub Enterprise account: the repository picker on [claude.ai/code](https://claude.ai/code) offers a connect option for each configured GHES instance, and Owners can also connect from the GitHub Enterprise section of the [Claude Code admin settings](https://claude.ai/admin-settings/claude-code). Then add the marketplace again. Alternatively, ask an Owner to add the marketplace in the organization plugin settings, which removes the per-user connection requirement. On other claude.ai surfaces, a “Repository not found. If it’s private, GitHub access is required” error on a GHES marketplace usually indicates the same missing connection. Connect your GitHub Enterprise account through one of the paths above, then try again.
[](#ghes-instance-not-reachable)
GHES instance not reachable
If reviews or Anthropic-hosted cloud sessions time out, your GHES instance may not be reachable from Anthropic infrastructure. Confirm your firewall allows inbound connections from Anthropic’s [outbound IP addresses](../04-API-Reference/Endpoints/ip-addresses.md#outbound-ip-addresses). Sessions in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) reach GHES from inside your network, so when one of them can’t clone, check the runner’s own network path instead. For the repository picker and other hosted pre-session flows, see [Network requirements](#network-requirements).
[](#session-start-fails-with-unable-to-get-organization-uuid)
Session start fails with `Unable to get organization UUID`
Claude Code couldn’t read a claude.ai organization from your credentials. Sign in with `/login` using an account in your Team or Enterprise organization, since GitHub Enterprise Server support is limited to those plans. See [Unable to get organization UUID](claude-code-on-the-web.md#unable-to-get-organization-uuid) for the causes and the other messages this state produces.
[](#related-resources)
Related resources
These pages cover the features referenced throughout this guide in more depth:
- [Use Claude Code in the cloud](claude-code-on-the-web.md): run Claude Code sessions on cloud infrastructure
- [Code Review](code-review.md): automated PR reviews
- [Plugin marketplaces](../08-Plugins-Skills/plugins-host-marketplace.md): build and distribute plugin catalogs
- [Analytics](../13-Enterprise-Admin/analytics.md): track usage and contribution metrics
- [Managed settings](settings.md): organization-wide policy configuration
- [Network configuration](../13-Enterprise-Admin/network-config.md): firewall and IP allowlist requirements
---
## Claude Code GitLab CI/CD - Claude Code Docs
Source: https://code.claude.com/docs/en/gitlab-ci-cd
Path: 02-Claude-Code-CLI/gitlab-ci-cd.md
## On this page
- [Why use Claude Code with GitLab?](#why-use-claude-code-with-gitlab)
- [How it works](#how-it-works)
- [What can Claude do?](#what-can-claude-do)
- [Setup](#setup)
- [Quick setup](#quick-setup)
- [Manual setup (recommended for production)](#manual-setup-recommended-for-production)
- [Example use cases](#example-use-cases)
- [Turn issues into MRs](#turn-issues-into-mrs)
- [Get implementation help](#get-implementation-help)
- [Fix bugs quickly](#fix-bugs-quickly)
- [Using with Amazon Bedrock and Google Cloud](#using-with-amazon-bedrock-and-google-cloud)
- [Configuration examples](#configuration-examples)
- [Amazon Bedrock job example (OIDC)](#amazon-bedrock-job-example-oidc)
- [Agent Platform job example (Workload Identity Federation)](#agent-platform-job-example-workload-identity-federation)
- [Best practices](#best-practices)
- [CLAUDE.md configuration](#claude-md-configuration)
- [Security considerations](#security-considerations)
- [Optimizing performance](#optimizing-performance)
- [CI costs](#ci-costs)
- [Troubleshooting](#troubleshooting)
- [Claude not responding to @claude commands](#claude-not-responding-to-%40claude-commands)
- [Job can’t write comments or open MRs](#job-can%E2%80%99t-write-comments-or-open-mrs)
- [Authentication errors](#authentication-errors)
- [Advanced configuration](#advanced-configuration)
- [Common parameters and variables](#common-parameters-and-variables)
- [Customizing Claude’s behavior](#customizing-claude%E2%80%99s-behavior)
Code review & CI/CD
# Claude Code GitLab CI/CD
Copy pageCopy page
Learn about integrating Claude Code into your development workflow with GitLab CI/CD
Copy pageCopy page
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](https://gitlab.com/gitlab-org/gitlab/-/issues/573776).
This integration is built on top of the [Claude Code CLI and Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), enabling programmatic use of Claude in your CI/CD jobs and custom automation workflows.
[](#why-use-claude-code-with-gitlab)
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 Cloud’s Agent Platform to meet data residency and procurement needs
- **Secure by default**: Runs in your GitLab runners with your branch protection and approvals
[](#how-it-works)
How it works
Claude Code uses GitLab CI/CD to run AI tasks in isolated jobs and commit results back via MRs:
1. **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.
2. **Provider abstraction**: Use the provider that fits your environment:
- Claude API (SaaS)
- Amazon Bedrock (IAM-based access, cross-region options)
- Google Cloud’s Agent Platform (GCP-native, Workload Identity Federation)
3. **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)
What can Claude do?
In a GitLab pipeline, Claude Code can:
- 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)
Setup
[](#quick-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.
1. **Add a masked CI/CD variable**
- Go to **Settings** → **CI/CD** → **Variables**
- Add `ANTHROPIC_API_KEY` (masked, protected as needed)
2. **Add a Claude job to `.gitlab-ci.yml`**
```python
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
# The installer places claude in ~/.local/bin, which isn't on PATH in this image
- export PATH="$HOME/.local/bin:$PATH"
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 Cloud’s Agent Platform instead of the Claude API, see the [Using with Amazon Bedrock and Google Cloud](#using-with-amazon-bedrock-and-google-cloud) section below for authentication and environment setup.
[](#manual-setup-recommended-for-production)
Manual setup (recommended for production)
If you prefer a more controlled setup or need enterprise providers:
1. **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 Amazon Bedrock
- **Google Cloud’s Agent Platform**: **Configure Workload Identity Federation for GitLab** → **GCP**
2. **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
3. **Add the Claude job to `.gitlab-ci.yml`**: use the [Quick setup](#quick-setup) job for the Claude API, or a provider job from [Configuration examples](#configuration-examples)
4. **(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)
Example use cases
[](#turn-issues-into-mrs)
Turn issues into MRs
In an issue comment:
```python
@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)
Get implementation help
In an MR discussion:
```python
@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)
Fix bugs quickly
In an issue or MR comment:
```python
@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-and-google-cloud)
Using with Amazon Bedrock and Google Cloud
For enterprise environments, you can run Claude Code entirely on your cloud infrastructure with the same developer experience.
- Amazon Bedrock
- Google Cloud's Agent Platform
[](#prerequisites)
Prerequisites
Before setting up Claude Code with Amazon Bedrock, you need:
1. An AWS account with Amazon Bedrock access to the desired Claude models
2. GitLab configured as an OIDC identity provider in AWS IAM
3. An IAM role with Amazon Bedrock permissions and a trust policy restricted to your GitLab project/refs
4. GitLab CI/CD variables for role assumption:
- `AWS_ROLE_TO_ASSUME` (role ARN)
- `AWS_REGION` (Amazon Bedrock region)
[](#setup-instructions)
Setup instructions
Configure AWS to allow GitLab CI jobs to assume an IAM role via OIDC (no static keys).**Required setup:**
1. Enable Amazon Bedrock and request access to your target Claude models
2. Create an IAM OIDC provider for GitLab if not already present
3. Create an IAM role trusted by the GitLab OIDC provider, restricted to your project and protected refs
4. Attach least-privilege permissions for Amazon Bedrock invoke APIs
Use the [Amazon Bedrock job example](#configuration-examples) to exchange the job’s OIDC token for temporary AWS credentials at runtime.
[](#prerequisites-2)
Prerequisites
Before setting up Claude Code with Google Cloud’s Agent Platform, you need:
1. A Google Cloud project with:
- Google Cloud’s Agent Platform API enabled
- Workload Identity Federation configured to trust GitLab OIDC
2. A dedicated service account with only the required Google Cloud’s Agent Platform roles
3. GitLab CI/CD variables:
- `GCP_WORKLOAD_IDENTITY_PROVIDER` (provider resource name without the `//iam.googleapis.com/` prefix, such as `projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider`)
- `GCP_SERVICE_ACCOUNT` (service account email)
- `GCP_PROJECT_ID` (Google Cloud project ID)
[](#setup-instructions-2)
Setup instructions
Configure Google Cloud to allow GitLab CI jobs to impersonate a service account via Workload Identity Federation.**Required setup:**
1. Enable IAM Credentials API, STS API, and Google Cloud’s Agent Platform API
2. Create a Workload Identity Pool and provider for GitLab OIDC
3. Create a dedicated service account with Google Cloud’s Agent Platform roles
4. Grant the WIF principal permission to impersonate the service account
Use the [Agent Platform job example](#configuration-examples) to authenticate without storing keys.
[](#configuration-examples)
Configuration examples
Below are ready-to-use snippets you can adapt to your pipeline.
[](#amazon-bedrock-job-example-oidc)
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 Amazon Bedrock permissions (least privilege recommended)
**Required CI/CD variables:**
- `AWS_ROLE_TO_ASSUME`: ARN of the IAM role for Amazon Bedrock access
- `AWS_REGION`: Amazon Bedrock region (for example, `us-west-2`)
GitLab mints the job’s OIDC token from the `id_tokens:` block and exposes it as `GITLAB_OIDC_TOKEN`. Set `aud` to the audience value you configured on the IAM OIDC identity provider in AWS, for example your GitLab instance URL.
```python
stages:
- ai
claude-bedrock:
stage: ai
image: node:24-alpine3.21
rules:
- if: '$CI_PIPELINE_SOURCE == "web"'
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.example.com
before_script:
- apk add --no-cache bash curl jq git aws-cli
- curl -fsSL https://claude.ai/install.sh | bash
# The installer places claude in ~/.local/bin, which isn't on PATH in this image
- export PATH="$HOME/.local/bin:$PATH"
# Exchange the job's OIDC token for AWS credentials
- export AWS_WEB_IDENTITY_TOKEN_FILE="/tmp/oidc_token"
- printf "%s" "$GITLAB_OIDC_TOKEN" > "$AWS_WEB_IDENTITY_TOKEN_FILE"
- >
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"
CLAUDE_CODE_USE_BEDROCK: "1"
```
Model IDs for Amazon 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.
[](#agent-platform-job-example-workload-identity-federation)
Agent Platform job example (Workload Identity Federation)
**Prerequisites:**
- Google Cloud’s Agent Platform API enabled in your GCP project
- Workload Identity Federation configured to trust GitLab OIDC
- A service account with Google Cloud’s Agent Platform permissions
**Required CI/CD variables:**
- `GCP_WORKLOAD_IDENTITY_PROVIDER`: provider resource name without the `//iam.googleapis.com/` prefix, such as `projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider`
- `GCP_SERVICE_ACCOUNT`: service account email
- `GCP_PROJECT_ID`: Google Cloud project ID
- `CLOUD_ML_REGION`: Google Cloud’s Agent Platform region (for example, `us-east5`)
GitLab mints the job’s OIDC token from the `id_tokens:` block and exposes it as `GITLAB_OIDC_TOKEN`. Set `aud` to the audience value you configured on the Workload Identity Pool provider, for example your GitLab instance URL. The job writes the token to a file, and the credential configuration’s `credential_source` entry tells Google’s auth libraries to read it from there. Setting `GOOGLE_APPLICATION_CREDENTIALS` to the credential configuration file makes it available to Claude Code through [Application Default Credentials](google-vertex-ai.md#3-configure-gcp-credentials).
```python
stages:
- ai
claude-vertex:
stage: ai
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
rules:
- if: '$CI_PIPELINE_SOURCE == "web"'
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.example.com
before_script:
- apt-get update && apt-get install -y git && apt-get clean
- curl -fsSL https://claude.ai/install.sh | bash
# The installer places claude in ~/.local/bin, which isn't on PATH in this image
- export PATH="$HOME/.local/bin:$PATH"
# Write the job's OIDC token where credential_source expects it
- printf "%s" "$GITLAB_OIDC_TOKEN" > /tmp/oidc_token
# Write the WIF credential configuration to a file (no downloaded keys)
- |
cat > /tmp/cred.json <<EOF
{
"type": "external_account",
"audience": "//iam.googleapis.com/${GCP_WORKLOAD_IDENTITY_PROVIDER}",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_url": "https://sts.googleapis.com/v1/token",
"credential_source": {
"file": "/tmp/oidc_token"
},
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${GCP_SERVICE_ACCOUNT}:generateAccessToken"
}
EOF
# Expose the credentials to Claude Code via Application Default Credentials
- export GOOGLE_APPLICATION_CREDENTIALS=/tmp/cred.json
# Authenticate the gcloud CLI with the same credential configuration
- gcloud auth login --cred-file=/tmp/cred.json
- gcloud config set project "$GCP_PROJECT_ID"
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"
CLAUDE_CODE_USE_VERTEX: "1"
ANTHROPIC_VERTEX_PROJECT_ID: "$GCP_PROJECT_ID"
```
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)
Best practices
[](#claude-md-configuration)
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)
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)
Optimizing performance
- Keep `CLAUDE.md` focused and concise
- Provide clear issue/MR descriptions to reduce iterations
- Cache npm and package installs in runners where possible
[](#ci-costs)
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](../17-Billing-Plans/about-claude-pricing.md) 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
[](#troubleshooting)
Troubleshooting
[](#claude-not-responding-to-@claude-commands)
Claude not responding to @claude commands
- Verify your pipeline is being triggered (manually, MR event, or via a note event listener/webhook)
- Ensure your `ANTHROPIC_API_KEY` or cloud provider variables are present
- Check that the comment contains `@claude` (not `/claude`) and that your mention trigger is configured
[](#job-can’t-write-comments-or-open-mrs)
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)
Authentication errors
- **For Claude API**: Confirm `ANTHROPIC_API_KEY` is valid and unexpired
- **For Amazon Bedrock or Google Cloud’s Agent Platform**: Verify OIDC/WIF configuration, role impersonation, and secret names; confirm region and model availability
[](#advanced-configuration)
Advanced configuration
[](#common-parameters-and-variables)
Common parameters and variables
Control Claude Code runs in your jobs with these CLI flags, GitLab keywords, and variables:
- `-p`: provide instructions inline, for example `claude -p "Review this MR"`
- `--max-turns`: limit the number of back-and-forth iterations
- `timeout`: limit total job execution time with GitLab’s job-level `timeout` keyword, for example `timeout: 30m`
- `ANTHROPIC_API_KEY`: required for the Claude API (not used for Amazon Bedrock or Google Cloud’s Agent Platform)
- Provider-specific environment: `AWS_REGION`, project/region vars for Google Cloud’s Agent Platform
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)
Customizing Claude’s behavior
You can guide Claude in two primary ways:
1. **CLAUDE.md**: Define coding standards, security requirements, and project conventions. Claude reads this during runs and follows your rules.
2. **Custom prompts**: Pass task-specific instructions via `-p` in the job. Use different prompts for different jobs (for example, review, implement, refactor).
---
## Glossary - Claude Code Docs
Source: https://code.claude.com/docs/en/glossary
Path: 02-Claude-Code-CLI/glossary.md
## On this page
- [A](#a)
- [AGENTS.md](#agents-md)
- [Agent teams](#agent-teams)
- [Agentic coding](#agentic-coding)
- [Agentic harness](#agentic-harness)
- [Agentic loop](#agentic-loop)
- [Artifact](#artifact)
- [Auto memory](#auto-memory)
- [Auto mode](#auto-mode)
- [B](#b)
- [Bare mode](#bare-mode)
- [Bundled skills](#bundled-skills)
- [C](#c)
- [Channel](#channel)
- [Checkpoint](#checkpoint)
- [.claude directory](#claude-directory)
- [CLAUDE.md](#claude-md)
- [Cloud session](#cloud-session)
- [Command](#command)
- [Compaction](#compaction)
- [Connector](#connector)
- [Context window](#context-window)
- [D](#d)
- [Dispatch](#dispatch)
- [E](#e)
- [Effort level](#effort-level)
- [Extended thinking](#extended-thinking)
- [F](#f)
- [Frontmatter](#frontmatter)
- [H](#h)
- [Hook](#hook)
- [M](#m)
- [Managed settings](#managed-settings)
- [MCP (Model Context Protocol)](#mcp-model-context-protocol)
- [MCP server](#mcp-server)
- [MCP Tool Search](#mcp-tool-search)
- [N](#n)
- [Non-interactive mode](#non-interactive-mode)
- [O](#o)
- [Output style](#output-style)
- [P](#p)
- [Permission mode](#permission-mode)
- [Permission rule](#permission-rule)
- [Plan mode](#plan-mode)
- [Plugin](#plugin)
- [Project trust](#project-trust)
- [Prompt injection](#prompt-injection)
- [R](#r)
- [Remote Control](#remote-control)
- [Rules](#rules)
- [S](#s)
- [Sandboxing](#sandboxing)
- [Session](#session)
- [Settings layers](#settings-layers)
- [Skill](#skill)
- [Subagent](#subagent)
- [Surface](#surface)
- [System prompt](#system-prompt)
- [System reminder](#system-reminder)
- [T](#t)
- [Teleport](#teleport)
- [Tool](#tool)
- [Turn](#turn)
- [V](#v)
- [Verification loop](#verification-loop)
- [W](#w)
- [Worktree isolation](#worktree-isolation)
- [Deprecated and renamed terms](#deprecated-and-renamed-terms)
Glossary
# Glossary
Copy pageCopy page
Definitions for Claude Code terminology. Learn what agentic loop, compaction, CLAUDE.md, hooks, subagents, MCP, and other core concepts mean.
Copy pageCopy page
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](../04-API-Reference/About/about-claude-glossary.md). For Claude Desktop terms such as desktop extension, MCPB, and DXT, see the [Claude Help Center](https://support.claude.com/).
[](#a)
A
[](#agents-md)
AGENTS.md
A markdown file of project instructions you write for AI coding agents. If your repository has one and no [CLAUDE.md](#claude-md), Claude reads it as your project instructions without you adding a second file. You can change the **Project instructions** setting in `/config` to have Claude read both files or only `CLAUDE.md`. Reading `AGENTS.md` directly requires Claude Code v2.1.277 or later. In some sessions Claude [can’t read `AGENTS.md`](memory.md#when-agents-md-support-is-unavailable), so [import it from a `CLAUDE.md`](memory.md#share-one-file-with-other-coding-tools) there instead. Learn more: [AGENTS.md](memory.md#agents-md)
[](#agent-teams)
Agent teams
Multiple independent Claude Code sessions coordinated by a team lead, with a shared task list and peer-to-peer messaging. Unlike [subagents](#subagent), 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 disabled by default; see [Enable agent teams](../09-Agents-Patterns/agent-teams.md#enable-agent-teams). Learn more: [Run agent teams](../09-Agents-Patterns/agent-teams.md)
[](#agentic-coding)
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](#tool) that let it act, not just advise. Learn more: [How Claude Code works](how-claude-code-works.md)
[](#agentic-harness)
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](how-claude-code-works.md)
[](#agentic-loop)
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](#hook), [skills](#skill), and [MCP](#mcp-model-context-protocol), plug into specific phases of this loop. Learn more: [How Claude Code works](how-claude-code-works.md#the-agentic-loop)
[](#artifact)
Artifact
A live, interactive web page Claude Code publishes from your session to a private URL on claude.ai, so you can see output visually or share it instead of reading terminal text. The page updates in place when the session republishes. Artifacts you create from Claude Code appear in the same gallery as artifacts created in claude.ai conversations. Sharing options depend on your plan: see [Share an artifact](artifacts.md#share-an-artifact). Learn more: [Share session output as artifacts](artifacts.md)
[](#auto-memory)
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](#claude-md), which you write. Learn more: [Auto memory](memory.md#auto-memory)
[](#auto-mode)
Auto mode
A [permission mode](#permission-mode) where a separate classifier model reviews actions instead of you, so Claude Code runs most of them without asking you. Claude Code still asks you before actions your explicit ask rules match. With Claude Code v2.1.283 or later, auto mode is the [built-in starting permission mode](permission-modes.md#which-mode-a-session-starts-in) for interactive terminal and VS Code sessions, and on earlier versions only on Pro, Max, and Team plans. The classifier blocks scope escalation, untrusted infrastructure, and [prompt injection](#prompt-injection). Tool results are stripped from what it sees, so hostile content in a file or web page can’t manipulate it directly. Learn more: [Eliminate prompts with auto mode](permission-modes.md#eliminate-prompts-with-auto-mode)
[](#b)
B
[](#bare-mode)
Bare mode
With `--bare`, Claude Code starts without loading hooks, skills, custom commands, subagents, installed plugins, MCP servers, auto memory, or CLAUDE.md, apart from skills in a directory you pass with `--add-dir`. Recommended for CI and scripted calls where you need the same result on every machine. Learn more: [Start faster with bare mode](headless.md#start-faster-with-bare-mode)
[](#bundled-skills)
Bundled skills
Prompt-based playbooks included with Claude Code, such as `/batch`, `/code-review`, `/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](../08-Plugins-Skills/skills.md#bundled-skills)
[](#c)
C
[](#channel)
Channel
An [MCP server](#mcp-model-context-protocol) 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](channels.md)
[](#checkpoint)
Checkpoint
A restore point created at each prompt you send that starts a turn. 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 saved with the conversation, so a resumed session can still `/rewind` to them. They’re separate from git and don’t track changes made through the Bash tool. Learn more: [Checkpointing](checkpointing.md)
[](#claude-directory)
`.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-directory.md)
[](#claude-md)
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. Project-root CLAUDE.md survives [compaction](#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](#managed-settings) for your organization. All discovered files are concatenated into context rather than overriding each other, ordered from broadest scope to most specific. Claude Code can also load a project’s [AGENTS.md](#agents-md) files, on their own or alongside CLAUDE.md. Learn more: [CLAUDE.md files](memory.md#claude-md-files)
[](#cloud-session)
Cloud session
A Claude Code session that keeps running after you close your laptop, because it runs on cloud infrastructure instead of your machine: Anthropic-managed by default, or a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) your organization operates. You start one from claude.ai/code, the Claude mobile app, the Desktop app with **Cloud** selected, `claude --cloud`, or a [routine](web-scheduled-tasks.md). A session in your terminal, IDE, or the Desktop app with **Local** selected is a local session; to reach a local session from another device, use [Remote Control](#remote-control). Learn more: [Use Claude Code in the cloud](claude-code-on-the-web.md)
[](#command)
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](#plugin). [Skills](#skill) are the recommended way to package multi-step commands. Two other uses of the word are unrelated: `claude` CLI subcommands such as `claude mcp add`, listed in the [CLI reference](cli-reference.md#cli-commands), and the `command` field of a stdio [MCP server](#mcp-server) entry, which specifies the executable Claude Code launches to start the server. Learn more: [Commands](commands.md) · [Skills](../08-Plugins-Skills/skills.md)
[](#compaction)
Compaction
Automatic summarization of your conversation when the [context window](#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](context-window.md#what-survives-compaction) · [When context fills up](how-claude-code-works.md#when-context-fills-up)
[](#connector)
Connector
An [MCP server](#mcp-server) added to your claude.ai account rather than configured in Claude Code. When you sign in to Claude Code with that account, your connectors appear in `/mcp` alongside the servers you added locally. Organizations can also provision connectors and set per-tool controls on them. Learn more: [Use MCP servers from claude.ai](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai)
[](#context-window)
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](#compaction) summarizes it. Run `/context` to see what’s using space. For the underlying model concept, see the [platform glossary](../04-API-Reference/About/about-claude-glossary.md#context-window). Learn more: [Explore the context window](context-window.md)
[](#d)
D
[](#dispatch)
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](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch)
[](#e)
E
[](#effort-level)
Effort level
A setting that controls adaptive reasoning, which lets the model decide whether and how much to think on each step. Higher effort means more thinking tokens and deeper reasoning; lower effort is faster and cheaper. Effort is supported on Fable models, on Opus 4.6 and later, and on Sonnet 4.6 and later. Learn more: [Adjust effort level](model-config.md#adjust-effort-level)
[](#extended-thinking)
Extended thinking
Visible step-by-step reasoning the model performs before responding. You can adjust it with the [effort level](#effort-level), or cap thinking tokens with `MAX_THINKING_TOKENS` on models with a fixed thinking budget. Thinking appears in gray italic text in the terminal. Learn more: [Use extended thinking](model-config.md#extended-thinking)
[](#f)
F
[](#frontmatter)
Frontmatter
A block of YAML settings at the very top of a Markdown file, between an opening `---` line and a closing `---` line. Skills, subagents, output styles, and rules each read their configuration from frontmatter, such as a skill’s `description` or a subagent’s `tools`, and treat everything after the closing `---` as the instructions. The opening `---` must be the file’s first line. Each file type accepts its own set of fields. Learn more: [Skill frontmatter](../08-Plugins-Skills/skills.md#frontmatter-reference), [Subagent frontmatter](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields), [Output style frontmatter](output-styles.md#frontmatter), [Rule frontmatter](memory.md#rules-frontmatter-reference)
[](#h)
H
[](#hook)
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](../07-Hooks/hooks-guide.md) · [Hooks reference](../07-Hooks/hooks.md)
[](#m)
M
[](#managed-settings)
Managed settings
Settings enforced org-wide by IT or DevOps, delivered from Anthropic’s servers through the admin console or deployed to devices at an OS-level path outside `~/.claude`. User and project settings cannot override managed settings. Server-managed delivery applies on [eligible configurations](../13-Enterprise-Admin/server-managed-settings.md#platform-availability); see [Security considerations](../13-Enterprise-Admin/server-managed-settings.md#security-considerations). Use this for security policies, compliance requirements, or standardized tooling across a fleet. Learn more: [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) · [Settings files](settings.md#where-settings-live)
[](#mcp-model-context-protocol)
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](../04-API-Reference/About/about-claude-glossary.md#mcp-model-context-protocol). Learn more: [Model Context Protocol](../06-MCP-Tools/General/mcp.md)
[](#mcp-server)
MCP server
A program that gives Claude tools, prompts, or resources over [MCP](#mcp-model-context-protocol). You add servers with `claude mcp add`, in `.mcp.json`, through a [plugin](#plugin), or as a claude.ai [connector](#connector). A local stdio server runs as a process Claude Code starts from the `command` and `args` fields of its configuration, which have nothing to do with the [commands](#command) you type at the prompt. Learn more: [Model Context Protocol](../06-MCP-Tools/General/mcp.md)
[](#mcp-tool-search)
MCP Tool Search
A context-saving mechanism that defers MCP tool schemas until needed. Only tool names and server instructions 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](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search)
[](#n)
N
[](#non-interactive-mode)
Non-interactive mode
A mode that executes a single prompt and exits without an interactive prompt, invoked with `-p` or `--print`. Used for CI, scripts, and piping. The run is still saved as a resumable session unless you pass `--no-session-persistence`. The [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) is the Python and TypeScript equivalent. Formerly called headless mode. Learn more: [Run Claude Code programmatically](headless.md)
[](#o)
O
[](#output-style)
Output style
A configuration that changes the instructions Claude Code gives Claude, to set response behavior, tone, or format. Unlike [CLAUDE.md](#claude-md), which adds project context alongside Claude Code’s default instructions, a custom output style can replace the default software engineering instructions. Learn more: [Output styles](output-styles.md)
[](#p)
P
[](#permission-mode)
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`. The `default` mode is labeled Manual in the CLI, in the VS Code and JetBrains extensions, and in the desktop app, and Claude Code accepts `manual` as an alias for the value. Learn more: [Choose a permission mode](permission-modes.md)
[](#permission-rule)
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](#permission-mode). Learn more: [Configure permissions](permissions.md)
[](#plan-mode)
Plan mode
A [permission mode](#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](permission-modes.md#analyze-before-you-edit-with-plan-mode)
[](#plugin)
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](../08-Plugins-Skills/plugins.md). Learn more: [Plugins](../08-Plugins-Skills/plugins.md)
[](#project-trust)
Project trust
A dialog accepting a directory before Claude Code loads its configuration. Acceptance is saved per project directory, except your home directory, where trust is held for the current session only and the prompt reappears on each launch. Until you trust a directory, Claude Code holds back some of the content its repository supplies, such as project allow rules and marketplaces from `.claude/settings.json`. [What runs before you trust a folder](permissions.md#what-runs-before-you-trust-a-folder) lists each kind of content, including what a `-p` session runs without a dialog. Learn more: [The `.claude` directory](claude-directory.md)
[](#prompt-injection)
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 injection detection, and trust verification. [Auto mode](#auto-mode) adds a server-side probe that scans tool results for suspicious content and a classifier that reviews actions with tool results stripped, so injected text can’t manipulate it directly. Learn more: [Protect against prompt injection](../13-Enterprise-Admin/security.md#protect-against-prompt-injection)
[](#r)
R
[](#remote-control)
Remote Control
A way to continue a local Claude Code session from your phone or browser via claude.ai. Your code execution and files stay on your machine; the interface is remote. Different from a [cloud session](claude-code-on-the-web.md), which runs in a cloud sandbox. Learn more: [Remote Control](remote-control.md)
[](#rules)
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/`](memory.md#organize-rules-with-claude/rules/)
[](#s)
S
[](#sandboxing)
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](#permission-rule). Learn more: [Sandboxing](sandboxing.md)
[](#session)
Session
A conversation tied to your current directory, with its own independent [context window](#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](how-claude-code-works.md#work-with-sessions)
[](#settings-layers)
Settings layers
The hierarchy Claude Code reads configuration from, in precedence order from highest to lowest: [managed policy](#managed-settings), 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. See [Settings precedence](settings.md#settings-precedence). Learn more: [Settings files](settings.md#where-settings-live)
[](#skill)
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](../08-Plugins-Skills/skills.md)
[](#subagent)
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. A subagent stays inside the session that spawned it. To pass findings between separate sessions you run yourself, use [cross-session messaging](cross-session-messaging.md). Built-in subagents include Explore, Plan, and general-purpose. Learn more: [Create custom subagents](../09-Agents-Patterns/sub-agents.md)
[](#surface)
Surface
Any place you access Claude Code: the CLI, VS Code, JetBrains, Desktop, or claude.ai. All surfaces share the same engine. Sessions on your machine read your local CLAUDE.md, settings, and skills; [cloud sessions](cloud-environments.md#what-carries-over-from-your-setup) start from a fresh clone of your repository and don’t read `~/.claude/` on your machine. Slack and the Chrome extension are integrations that connect to a surface rather than surfaces themselves. Learn more: [Platforms and integrations](platforms.md)
[](#system-prompt)
System prompt
The instructions Claude Code sends ahead of your conversation on every request, covering how Claude uses tools, behaves safely, and formats its responses. You can add to the system prompt with `--append-system-prompt` or replace it with `--system-prompt`. The system prompt is the first layer of the [prompt cache](prompt-caching.md#how-the-cache-is-organized). Your [CLAUDE.md](#claude-md) files and the instructions of your [output style](#output-style) aren’t part of the system prompt. Claude Code delivers them in the conversation as [system reminders](#system-reminder). Learn more: [System prompt flags](cli-reference.md#system-prompt-flags)
[](#system-reminder)
System reminder
A message that Claude Code, as the [harness](#agentic-harness), adds to the conversation to give Claude context. You don’t send system reminders yourself. Claude Code inserts them as a session runs, for example when the session starts, when a hook returns text, or when a file changes on disk. Claude reads them alongside your messages. The following all reach Claude as system reminders:
- Your [CLAUDE.md](#claude-md) files
- The instructions of your [output style](#output-style)
- Text a [hook](#hook) returns as `additionalContext`
- The list of available [skills](#skill)
- A note that a file Claude read earlier has changed on disk
- The commit and pull request attribution lines
In a logged API request, a system reminder appears wrapped in `<system-reminder>` tags inside a user message, or on some models as a separate message with the `system` role. Learn more: [Context Claude Code adds outside the system prompt](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#context-claude-code-adds-outside-the-system-prompt)
[](#t)
T
[](#teleport)
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 cloud session’s last state. The reverse direction is `--cloud`, which sends a local task to run in the cloud. Learn more: [From cloud to terminal](claude-code-on-the-web.md#from-cloud-to-terminal)
[](#tool)
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](#agentic-loop). Learn more: [Tools available to Claude](tools-reference.md)
[](#turn)
Turn
One complete response from Claude within a [session](#session). A turn begins when you send a message and ends when Claude finishes responding, with any number of [tool](#tool) calls in between. [Stop hooks](#hook) fire at the end of each turn. A session consists of many turns, and the [agentic loop](#agentic-loop) describes what happens inside one. Learn more: [How Claude Code works](how-claude-code-works.md#the-agentic-loop)
[](#v)
V
[](#verification-loop)
Verification loop
How a session knows the work is actually done rather than just plausible. You give Claude a check it can run, such as a test suite, a build, or a screenshot comparison, and Claude iterates until the check passes instead of stopping after one attempt. A verification loop is the prerequisite for [`/goal`](goal.md), unattended runs, and [dynamic workflows](workflows.md): without one, the only thing deciding the agent is finished is the agent itself. Learn more: [Give Claude a way to verify its work](best-practices.md#give-claude-a-way-to-verify-its-work)
[](#w)
W
[](#worktree-isolation)
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](worktrees.md)
------------------------------------------------------------------------
[](#deprecated-and-renamed-terms)
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](#non-interactive-mode) | Same `-p` flag, same behavior |
| Web session; “Claude Code on the web” as the name for any cloud session | [Cloud session](#cloud-session) | ”Claude Code on the web” now names only the browser surface at claude.ai/code |
| Custom commands | [Skills](#skill) | `.claude/commands/` files still work |
| Slash commands | Commands | ”Slash” dropped from product copy |
---
## Keep Claude working toward a goal - Claude Code Docs
Source: https://code.claude.com/docs/en/goal
Path: 02-Claude-Code-CLI/goal.md
## On this page
- [Compare ways to keep a session running](#compare-ways-to-keep-a-session-running)
- [Use /goal](#use-%2Fgoal)
- [Set a goal](#set-a-goal)
- [Write an effective condition](#write-an-effective-condition)
- [Check status](#check-status)
- [Clear a goal](#clear-a-goal)
- [Resume with an active goal](#resume-with-an-active-goal)
- [Run non-interactively](#run-non-interactively)
- [How evaluation works](#how-evaluation-works)
- [When a turn fails](#when-a-turn-fails)
- [Errors you have to fix clear the goal](#errors-you-have-to-fix-clear-the-goal)
- [Other errors retry or pause the goal](#other-errors-retry-or-pause-the-goal)
- [Background work defers evaluation](#background-work-defers-evaluation)
- [Evaluation model and cost](#evaluation-model-and-cost)
- [Requirements](#requirements)
- [See also](#see-also)
Automation
# Keep Claude working toward a goal
Copy pageCopy page
Set a completion condition with /goal and Claude keeps working until it’s met, a model judges it impossible, or an error you have to fix clears the goal.
Copy pageCopy page
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 the model judges it not yet met, Claude starts another turn instead of returning control to you. The goal clears automatically once the condition is met, if the model judges the condition impossible to satisfy, or if a turn fails on [an error you have to fix](#errors-you-have-to-fix-clear-the-goal). 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
[](#compare-ways-to-keep-a-session-running)
Compare ways to keep a session running
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, or, in an interactive session, an [idle check-in](#background-work-defers-evaluation) or an [automatic retry](#other-errors-retry-or-pause-the-goal) comes due | A model confirms the condition is met or judges it impossible, or a turn fails on [an error you have to fix](#errors-you-have-to-fix-clear-the-goal), or you run [`/goal clear`](#clear-a-goal) |
| [`/loop`](scheduled-tasks.md#run-a-prompt-repeatedly-with-%2Floop) | A time interval elapses | You stop it, or Claude decides the work is done |
| [Stop hook](../07-Hooks/hooks-guide.md#prompt-based-hooks) | 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](auto-mode-config.md) 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](scheduled-tasks.md#compare-scheduling-options) for cloud routines and desktop scheduled tasks.
[](#use-/goal)
Use `/goal`
One goal can be active per session. The same command sets, checks, and clears it depending on the argument.
[](#set-a-goal)
Set a goal
Run `/goal` followed by the condition you want satisfied. If a goal is already active, the new one replaces it.
```python
/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. A goal doesn’t change your permission mode. To let goal turns run unattended, run `/goal` in [auto mode](auto-mode-config.md). In [Manual mode](permission-modes.md), Claude still asks before tool calls that your settings don’t already allow, such as the test command above. While the goal is active, the transcript shows each verdict the evaluator returns, and you can press Ctrl+O to see the reason behind it. The status view also shows the most recent reason, so you can see what Claude is working toward next.
[](#write-an-effective-condition)
Write an effective condition
The [evaluator](#how-evaluation-works) 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 appears 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)
Check status
Run `/goal` with no arguments to see the current state.
```python
/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
The turn count and the most recent reason appear after the first evaluation has run. 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)
Clear a goal
Run `/goal clear` to remove an active goal before it resolves.
```python
/goal clear
```
Claude prints `Goal cleared:` followed by the condition to confirm, or `No goal set` if nothing was active. `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)
Resume with an active goal
When you resume a session, Claude Code restores a goal that was still active when the session ended. Claude Code restores it on every resume route: `--continue`, `--resume` with a session ID, name, or [transcript file path](sessions.md#resume-a-session), and the [session picker](sessions.md#use-the-session-picker). Before v2.1.239, Claude Code restored the goal on every route except the `claude --resume` picker. Claude Code carries the condition over but resets the turn count, timer, and token-spend baseline. It doesn’t restore a goal that was already achieved or cleared.
[](#run-non-interactively)
Run non-interactively
`/goal` works in [non-interactive mode](headless.md), in the [desktop app](../16-Mobile-Desktop/desktop.md), and through [Remote Control](remote-control.md). Setting a goal with `-p` runs the loop to completion in a single invocation:
```python
claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"
```
With the default text output, nothing prints until the run ends, so a goal that runs many turns can look stuck. Add `--output-format stream-json --verbose` to emit each message as the loop runs. Interrupt the process with Ctrl+C to stop a non-interactive goal before it resolves.
[](#how-evaluation-works)
How evaluation works
`/goal` is a wrapper around a session-scoped [prompt-based Stop hook](../07-Hooks/hooks.md#prompt-based-hooks). Each time Claude finishes a turn, Claude Code sends the condition and the conversation so far to your configured [small fast model](model-config.md), which defaults to Haiku on the Claude API; on a third-party provider, check your [provider page](third-party-integrations.md) for the platform’s default. The model returns one of three verdicts, each with a short reason:
- **Not yet met**: Claude keeps working and takes the reason as guidance for the next turn.
- **Met**: Claude Code clears the goal and records an achieved entry in the transcript.
- **Impossible**: the evaluator judged that the condition can never be satisfied. Claude Code clears the goal and records a failed entry in the transcript along with the reason. You don’t need to clear it yourself.
If Claude keeps answering the evaluator without making progress (no tool use for several turns in a row), Claude Code stops the loop, prints a warning, and returns control to you with the goal still set. Evaluation resumes after your next prompt. The [hooks guide](../07-Hooks/hooks-guide.md#stop-hook-hits-the-block-cap) explains the underlying mechanism.
[](#when-a-turn-fails)
When a turn fails
When a turn fails, Claude Code clears the goal if the error is one you have to fix. After any other error the goal stays set.
[](#errors-you-have-to-fix-clear-the-goal)
Errors you have to fix clear the goal
If a turn fails on an error that won’t clear until you fix it, Claude Code clears the goal and prints a warning naming the cause. The warning starts with `Goal cleared after an unrecoverable error` and ends with `Run /goal again to continue`. Fix the cause, then [set the goal again](#set-a-goal) with `/goal <condition>`. Four kinds of failure clear the goal:
- An authentication failure, when Claude Code manages its own credentials. When a host manages them for you, such as the desktop app or a [cloud session](claude-code-on-the-web.md), Claude Code leaves the goal active because the host restores access on its own.
- An exhausted credit balance
- A context overflow that [auto-compaction](model-config.md#set-the-auto-compact-window) couldn’t clear
- A model that isn’t available
[](#other-errors-retry-or-pause-the-goal)
Other errors retry or pause the goal
After any other failure the goal stays set. In an interactive session on Claude Code v2.1.269 or later, Claude Code also prints a line naming the cause and either retries on its own or waits for you:
- **Retry**: after a failure that tends to clear on its own, such as an overloaded server or a dropped connection, a notice starting with `Goal still active` shows the wait before the next attempt. After three automatic retries, the goal pauses instead.
- **Pause**: after a failure that a retry would only repeat, such as an API rate limit, a claude.ai [usage limit](errors.md#youve-hit-your-session-limit), or a hook that ended the turn, a notice starting with `Goal paused` names the cause. If the session is [waiting to continue automatically when a usage limit resets](interactive-mode.md#wait-for-a-usage-limit-to-reset), Claude resumes work toward the goal then.
Send a message at any time to start the next turn immediately. To turn automatic retries off, set [`CLAUDE_CODE_GOAL_CHECKIN_MINUTES`](env-vars.md) to `0`, which also turns [check-ins](#background-work-defers-evaluation) off.
[](#background-work-defers-evaluation)
Background work defers evaluation
If a subagent or a background shell command is still running when a turn ends, Claude Code skips the evaluation for that turn. It evaluates at the end of the next turn that finishes with no background work running. When the background work finishes, Claude Code delivers the result to Claude as a new turn, so you don’t have to prompt. Once background work has kept the goal waiting for 30 minutes, a check-in is due. In the check-in, Claude Code lists the running tasks and asks Claude to read their output, keep waiting if they’re progressing, and fix or stop any that are stuck. After the first check-in, Claude Code waits twice as long before each later check-in, up to four times the first interval: with the default, 1 hour after the first check-in, then every 2 hours. Claude Code delivers a due check-in, the first one included, in one of two ways:
- **When a turn ends**: Claude Code delivers the check-in at the end of the next turn that finishes with the work still running. In a non-interactive session, such as one started with `-p`, this is the only way Claude Code delivers check-ins.
- **While the session is idle**: in an interactive session, Claude Code also starts a turn on its own to deliver the check-in instead of waiting for your next prompt. If the background work has stopped without reporting a result, Claude Code asks Claude to continue toward the goal. Claude Code starts at most three idle check-ins per goal between your prompts. In the third idle check-in, Claude Code says that idle check-ins are paused until you send another prompt. Before v2.1.246, idle check-ins were uncapped. Idle check-ins require Claude Code v2.1.236 or later.
Before v2.1.239, only idle check-ins backed off this way; a check-in delivered at a turn end recurred at the first interval. To change the first interval, set [`CLAUDE_CODE_GOAL_CHECKIN_MINUTES`](env-vars.md). Claude Code uses your value in place of the 30-minute interval and scales the later intervals with it. Set it to `0` to turn off check-ins and [automatic retries](#other-errors-retry-or-pause-the-goal). Check-ins require Claude Code v2.1.234 or later.
[](#evaluation-model-and-cost)
Evaluation model and cost
To evaluate on a different model, set [`ANTHROPIC_DEFAULT_HAIKU_MODEL`](model-config.md#environment-variables).
Claude Code reads `ANTHROPIC_DEFAULT_HAIKU_MODEL` everywhere it uses the small fast model, not only for `/goal` evaluation. When you set it, Claude Code also resolves the [`haiku` alias](model-config.md#model-aliases) to that model and runs [background functionality](../17-Billing-Plans/costs.md#background-token-usage), such as conversation summarization, on it.
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)
Requirements
Claude Code makes `/goal` available under the same [workspace trust rule as hooks in settings files](permissions.md#what-runs-before-you-trust-a-folder), because the evaluator is part of the hooks system. `/goal` is also unavailable when [`disableAllHooks`](../07-Hooks/hooks.md#disable-or-remove-hooks) is `true` after settings precedence applies, or when [`allowManagedHooksOnly`](settings-reference.md#allowmanagedhooksonly) is set in managed settings. In each case, the command tells you why instead of silently doing nothing.
[](#see-also)
See also
- [Run a prompt repeatedly with `/loop`](scheduled-tasks.md#run-a-prompt-repeatedly-with-%2Floop): re-run on a time interval instead of toward a condition
- [Prompt-based hooks](../07-Hooks/hooks-guide.md#prompt-based-hooks): write your own Stop hook when you need custom evaluation logic
- [Auto mode](auto-mode-config.md): approve tool calls automatically so each goal turn runs unattended
- [Scheduling comparison](scheduled-tasks.md#compare-scheduling-options): run work on a schedule independent of any open session
---
## Claude Code on Google Cloud's Agent Platform - Claude Code Docs
Source: https://code.claude.com/docs/en/google-vertex-ai
Path: 02-Claude-Code-CLI/google-vertex-ai.md
## On this page
- [Prerequisites](#prerequisites)
- [Sign in with Agent Platform](#sign-in-with-agent-platform)
- [Region configuration](#region-configuration)
- [Set up manually](#set-up-manually)
- [1. Enable Agent Platform API](#1-enable-agent-platform-api)
- [2. Request model access](#2-request-model-access)
- [3. Configure GCP credentials](#3-configure-gcp-credentials)
- [Advanced credential configuration](#advanced-credential-configuration)
- [4. Configure Claude Code](#4-configure-claude-code)
- [5. Pin model versions](#5-pin-model-versions)
- [6. Verify your configuration](#6-verify-your-configuration)
- [Startup model checks](#startup-model-checks)
- [IAM configuration](#iam-configuration)
- [1M token context window](#1m-token-context-window)
- [Troubleshooting](#troubleshooting)
- [Additional resources](#additional-resources)
Deployment
# Claude Code on Google Cloud's Agent Platform
Copy pageCopy page
Learn about configuring Claude Code through Google Cloud’s Agent Platform, formerly Vertex AI, including setup, IAM configuration, and troubleshooting.
Copy pageCopy page
[](#prerequisites)
Prerequisites
Before configuring Claude Code with Google Cloud’s Agent Platform, formerly Vertex AI, ensure you have:
- A Google Cloud Platform (GCP) account with billing enabled
- A GCP project with Google Cloud’s Agent Platform 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 Google Cloud’s Agent Platform credentials, follow [Sign in with Google Cloud’s Agent Platform](#sign-in-with-agent-platform) below. To deploy Claude Code across a team, use the [manual setup](#set-up-manually) steps and [pin your model versions](#5-pin-model-versions) before rolling out.
[](#sign-in-with-agent-platform)
Sign in with Agent Platform
If you have Google Cloud credentials and want to start using Claude Code through Google Cloud’s Agent Platform, the login wizard walks you through it. You complete the GCP-side prerequisites once per project; the wizard handles the Claude Code side.
1
Enable Claude models in your GCP project
[Enable Google Cloud’s Agent Platform API](#1-enable-agent-platform-api) for your project, then request access to the Claude models you want in the [Google Cloud’s Agent Platform Model Garden](https://console.cloud.google.com/vertex-ai/model-garden). See [IAM configuration](#iam-configuration) for the permissions your account needs.
2
Start Claude Code and choose Google Cloud's Agent Platform
Run `claude`. At the login prompt, select **3rd-party platform**, then **Google Vertex AI**, the label the login prompt still uses for Google Cloud’s Agent Platform. If you’re already signed in, run `/login` to open the same menu.
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 asks for 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](settings.md), 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. The model pin step starts from your currently pinned models. The wizard writes to `~/.claude/settings.json`, or to `$CLAUDE_CONFIG_DIR/settings.json` when [`CLAUDE_CONFIG_DIR`](env-vars.md#variables) is set.
[](#region-configuration)
Region configuration
Claude Code supports Google Cloud’s Agent Platform [global](https://cloud.google.com/blog/products/ai-machine-learning/global-endpoint-for-claude-models-generally-available-on-vertex-ai), 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 Google Cloud’s Agent Platform hostname for each form, including the `aiplatform.eu.rep.googleapis.com` and `aiplatform.us.rep.googleapis.com` hosts for multi-region locations.
Google Cloud’s Agent Platform may not support the Claude Code default models on every endpoint type. Model availability varies across [specific regions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#genai-partner-models), multi-region locations, and [global endpoints](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#supported_models). You may need to switch to a supported location or specify a supported model.
[](#set-up-manually)
Set up manually
To configure Google Cloud’s Agent Platform through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.
[](#1-enable-agent-platform-api)
1. Enable Agent Platform API
Enable Google Cloud’s Agent Platform API in your GCP project. Replace `YOUR-PROJECT-ID` with your GCP project ID here and in the configuration step below:
```python
# Set your project ID
gcloud config set project YOUR-PROJECT-ID
# Enable Agent Platform API
gcloud services enable aiplatform.googleapis.com
```
[](#2-request-model-access)
2. Request model access
Request access to Claude models in Google Cloud’s Agent Platform:
1. Go to the [Google Cloud’s Agent Platform Model Garden](https://console.cloud.google.com/vertex-ai/model-garden)
2. Search for “Claude” models
3. Request access to desired Claude models (for example, Claude Sonnet 4.6)
4. Wait for approval (may take 24-48 hours)
[](#3-configure-gcp-credentials)
3. Configure GCP credentials
Claude Code uses standard Google Cloud authentication. For more information, see [Google Cloud authentication documentation](https://cloud.google.com/docs/authentication). Claude Code supports [X.509 certificate-based Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation-with-x509-certificates) through the same Application Default Credentials chain. Set `GOOGLE_APPLICATION_CREDENTIALS` to the path of your credential configuration file.
Claude Code addresses Google Cloud’s Agent Platform requests to the project in `ANTHROPIC_VERTEX_PROJECT_ID`, even when `GCLOUD_PROJECT`, `GOOGLE_CLOUD_PROJECT`, or the credential file referenced by `GOOGLE_APPLICATION_CREDENTIALS` carries a different project.
[](#advanced-credential-configuration)
Advanced credential configuration
Claude Code supports automatic credential refresh for GCP through the `gcpAuthRefresh` setting. Add it to your Claude Code [settings file](settings.md), for example `~/.claude/settings.json`. 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.
```python
{
"gcpAuthRefresh": "gcloud auth application-default login",
"env": {
"ANTHROPIC_VERTEX_PROJECT_ID": "your-project-id"
}
}
```
Before running the command, Claude Code requests an access token with your current credentials to confirm they’re actually expired, and skips the command when they still work. If the check doesn’t finish within five seconds, Claude Code also skips the command and runs it only after a request fails with a credential error. Before v2.1.261, a check that timed out counted as an expired credential, so the command could open your browser at startup even though your credentials were still valid. Claude Code shows you the command’s output, but can’t send the command interactive input. 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`, Claude Code runs it under the same [workspace trust rule as hooks in settings files](permissions.md#what-runs-before-you-trust-a-folder), which includes `-p` sessions in folders you’ve never trusted.
[](#4-configure-claude-code)
4. Configure Claude Code
Set the following environment variables:
```python
# Enable Agent Platform integration
export CLAUDE_CODE_USE_VERTEX=1
export CLOUD_ML_REGION=global
export ANTHROPIC_VERTEX_PROJECT_ID=YOUR-PROJECT-ID
# Optional: Override the Agent Platform endpoint URL for custom endpoints or gateways
# export ANTHROPIC_VERTEX_BASE_URL=https://aiplatform.googleapis.com
# 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](env-vars.md) for the full list. Check [Google Cloud’s Agent Platform Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) to determine which models support global endpoints versus regional only. If a region value isn’t shaped like a region or location name, Claude Code treats it as unset. For example, Claude Code treats a value containing a slash, dot, or space as unset. Claude Code falls back to a different source for each variable:
- `VERTEX_REGION_CLAUDE_*`: Claude Code falls back to `CLOUD_ML_REGION`.
- `CLOUD_ML_REGION`: Claude Code falls back to `us-east5`.
[Prompt caching](prompt-caching.md) 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. To set different TTLs for your main conversation and for the requests Claude Code makes outside it, [choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself). To raise your rate limits, contact Google Cloud support. When using Google Cloud’s Agent Platform, the `/logout` command is unavailable since authentication is handled through Google Cloud credentials. Claude Code decides between [MCP tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) and upfront loading by model generation:
- **Claude Opus 4.5, Sonnet 4.5, Haiku 4.5, and later**: Claude Code enables tool search by default.
- **Earlier models, including all Claude 3.x models**: Claude Code loads MCP tool definitions upfront, because their Agent Platform serving stacks reject the required beta header. Setting `ENABLE_TOOL_SEARCH=true` doesn’t override this.
Set `ENABLE_TOOL_SEARCH=false` to disable tool search on every model. Before v2.1.221, Claude Code disabled tool search for all models on Google Cloud’s Agent Platform unless you set `ENABLE_TOOL_SEARCH=true`.
[](#5-pin-model-versions)
5. Pin model versions
Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as `sonnet` and `opus` resolve to Claude Code’s built-in default for Google Cloud’s Agent Platform, which can lag the newest release and may not yet be enabled in your project. Claude Code [falls back](#startup-model-checks) to an earlier or lower-tier model at startup when the default is unavailable, but pinning lets you control when your users move to a new model.
Set these environment variables to specific Google Cloud’s Agent Platform model IDs. Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias on Google Cloud’s Agent Platform resolves to Opus 5.5, and without `ANTHROPIC_DEFAULT_SONNET_MODEL`, the `sonnet` alias resolves to Sonnet 4.5. This example pins each alias to a specific version:
```python
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'
export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-5'
export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5@20251001'
```
For current and legacy model IDs, see [Models overview](../20-Models/about-claude-models-overview.md). See [Model configuration](model-config.md#pin-models-for-third-party-deployments) 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-opus-5-5` |
| Small/fast model | `claude-sonnet-4-5@20250929` |
Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Google Cloud’s Agent Platform, Claude Code uses the default Sonnet model for background tasks because Haiku may not be enabled in every project or region. Two selections change which model carries them:
- When you select a primary model with `--model`, `ANTHROPIC_MODEL`, or the `model` setting, background tasks use that model. When Claude Code starts the session on the model you set with [`ANTHROPIC_DEFAULT_MODEL`](model-config.md#set-a-default-model-for-new-sessions), background tasks use that model too. Setting `ANTHROPIC_DEFAULT_OPUS_MODEL` without `ANTHROPIC_DEFAULT_SONNET_MODEL` also counts as a selection, because the built-in Sonnet model may not be enabled in a project that steers its own Opus.
- To use Haiku for background tasks, set `ANTHROPIC_DEFAULT_HAIKU_MODEL` to a model ID that is available in your project.
Opus models have a higher per-token price than Sonnet models, so a deployment that doesn’t pin a primary model is billed at the Opus rate once it updates to v2.1.207 or later. To keep Sonnet 4.5 as the primary model, set `ANTHROPIC_MODEL` to its full model ID. A deployment that steers the default with `ANTHROPIC_DEFAULT_SONNET_MODEL` and doesn’t set `ANTHROPIC_DEFAULT_OPUS_MODEL` keeps its steered Sonnet model as the default.
Before v2.1.280, the primary model on Google Cloud’s Agent Platform defaulted to Opus 5 and the `opus` alias resolved to Opus 5 from v2.1.219. On v2.1.207 through v2.1.218, the primary model on Google Cloud’s Agent Platform defaulted to Opus 4.8 and the `opus` alias resolved to Opus 4.8. Before v2.1.207, the primary model defaulted to Sonnet 4.5, the `opus` alias resolved to Opus 4.6, and background tasks always used the primary model. To customize models further:
```python
export ANTHROPIC_MODEL='claude-opus-4-8'
export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5@20251001'
```
[](#6-verify-your-configuration)
6. Verify your configuration
Start Claude Code and run `/status` to confirm the setup. The `API provider` line shows `Google Vertex AI`, and the `GCP project`, `Default region`, and `Model` lines show your project ID, region, and resolved model. If the provider line is missing, the environment variables aren’t reaching the process. Confirm they are exported in the shell where you launched `claude`, or set them in the `env` block of your [settings file](settings.md).
[](#startup-model-checks)
Startup model checks
When Claude Code starts with Google Cloud’s Agent Platform configured, it verifies that the models it intends to use are accessible in your project. 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](settings.md) 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 for the current session and shows a notice. It tries earlier versions of the default model first and, when the default is an Opus model and no Opus version is available, falls back to the default Sonnet model. The fallback is not persisted. Enable the newer model in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) or [pin a version](#5-pin-model-versions) to make the choice permanent. When you start the session on a specific Sonnet or Opus version, for example with `--model`, `ANTHROPIC_MODEL`, or the [`model` setting](settings-reference.md#model), that version acts as the session’s pinned default for the matching `sonnet` or `opus` alias. Claude Code skips the availability check for the built-in default your model replaces and starts on the model you configured, with no fallback notice. Model aliases such as `opus` don’t act as pins, and neither does a model ID Claude Code doesn’t recognize.
[](#iam-configuration)
IAM configuration
Assign the `roles/aiplatform.user` role, which 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 [Google Cloud’s Agent Platform IAM documentation](https://cloud.google.com/vertex-ai/docs/general/access-control).
Create a dedicated GCP project for Claude Code to simplify cost tracking and access control.
[](#1m-token-context-window)
1M token context window
Claude Sonnet 5, Opus 4.6 and later, and Sonnet 4.6 support the [1M token context window](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model) on Google Cloud’s Agent Platform. Sonnet 5 always runs with the 1M window, with no `[1m]` variant to select. For the other models, Claude Code automatically enables the extended context window when you select a 1M model variant. The [setup wizard](#sign-in-with-agent-platform) 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](model-config.md#pin-models-for-third-party-deployments) for details, including how to use the 1M window without changing the pin.
[](#troubleshooting)
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](#3-configure-gcp-credentials) for all options
If you encounter quota issues:
- Check current quotas or request quota increase through [Cloud Console](https://cloud.google.com/docs/quotas/view-manage)
If you encounter “model not found” 404 errors:
- Confirm model is Enabled in [Model Garden](https://console.cloud.google.com/vertex-ai/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](https://console.cloud.google.com/vertex-ai/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)
Additional resources
- [Google Cloud’s Agent Platform documentation](https://cloud.google.com/vertex-ai/docs)
- [Google Cloud’s Agent Platform pricing](https://cloud.google.com/vertex-ai/pricing)
- [Google Cloud’s Agent Platform quotas and limits](https://cloud.google.com/vertex-ai/docs/quotas)
---
## Run Claude Code programmatically - Claude Code Docs
Source: https://code.claude.com/docs/en/headless
Path: 02-Claude-Code-CLI/headless.md
## On this page
- [Basic usage](#basic-usage)
- [Start faster with bare mode](#start-faster-with-bare-mode)
- [Background tasks at exit](#background-tasks-at-exit)
- [Stop a run with SIGTERM](#stop-a-run-with-sigterm)
- [If the working directory is deleted](#if-the-working-directory-is-deleted)
- [Examples](#examples)
- [Pipe data through Claude](#pipe-data-through-claude)
- [Add Claude to a build script](#add-claude-to-a-build-script)
- [Get structured output](#get-structured-output)
- [Stream responses](#stream-responses)
- [Follow subagent messages](#follow-subagent-messages)
- [Handle API retries](#handle-api-retries)
- [Read session metadata](#read-session-metadata)
- [Fail CI when a plugin or MCP server doesn’t load](#fail-ci-when-a-plugin-or-mcp-server-doesn%E2%80%99t-load)
- [Track plugin installs](#track-plugin-installs)
- [Auto-approve tools](#auto-approve-tools)
- [Turn off permission prompts in unattended runs](#turn-off-permission-prompts-in-unattended-runs)
- [Create a commit](#create-a-commit)
- [Customize the system prompt](#customize-the-system-prompt)
- [Continue conversations](#continue-conversations)
- [Next steps](#next-steps)
Automation
# Run Claude Code programmatically
Copy pageCopy page
Use the Agent SDK to run Claude Code programmatically from the CLI, Python, or TypeScript.
Copy pageCopy page
The [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) 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](../05-Agent-SDK/agent-sdk-python.md) and [TypeScript](../05-Agent-SDK/agent-sdk-typescript.md) packages for full programmatic control. To run Claude Code in non-interactive mode, pass `-p` with your prompt and the [CLI options](cli-reference.md) you need:
```python
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](../05-Agent-SDK/agent-sdk-overview.md).
[](#basic-usage)
Basic usage
Add the `-p` (or `--print`) flag to any `claude` command to run it non-interactively. Not every [CLI option](cli-reference.md) combines with `-p`. Claude Code rejects `--bg`, and rejects `--cloud` with a task description, with an error naming the conflict; `--cloud` with a session ID and `-p` instead [queues a message into that cloud session](claude-code-on-the-web.md#send-follow-ups-from-the-cli) and exits. Options you’ll combine with `-p` often include:
- `--continue` for [continuing conversations](#continue-conversations)
- `--allowedTools` for [auto-approving tools](#auto-approve-tools)
- `--output-format` for [structured output](#get-structured-output)
This example asks Claude a question about your codebase and prints the response:
```python
claude -p "What does the auth module do?"
```
Claude Code exits with code 0 on success and a non-zero code when the run fails, so your scripts can branch on the exit status. If you pass an invalid flag, Claude Code reports the error to stderr before the run starts. When a failure happens inside the run, such as missing authentication, Claude Code prints the failure as the result on stdout.
[](#start-faster-with-bare-mode)
Start faster with bare mode
Add `--bare` to reduce startup time by skipping auto-discovery of hooks, skills, custom commands, [subagents](../09-Agents-Patterns/sub-agents.md), installed plugins, MCP servers, auto memory, and CLAUDE.md. Without it, `claude -p` loads the same [context](how-claude-code-works.md#the-context-window) 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. A directory you name with `--add-dir` is a partial exception: bare mode loads skills from its `.claude/skills/` folder, but still skips its `.claude/commands/` and `.claude/agents/` folders. [Skills from additional directories](../08-Plugins-Skills/skills.md#skills-from-additional-directories) covers what does and doesn’t load. Without `--bare`, a `-p` session runs the hooks in a project’s `.claude/settings.json` and connects the servers in its `.mcp.json`, even in a folder you’ve never trusted. A `-p` session shows no workspace trust dialog and no per-server approval prompt. [What runs before you trust a folder](permissions.md#what-runs-before-you-trust-a-folder) covers each kind of repository content under `-p` and how to keep it out. 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. Set `ANTHROPIC_API_KEY` before running it, because bare mode doesn’t use your subscription login:
```python
claude --bare -p "Summarize README.md" --allowedTools "Read"
```
In bare mode, Claude Code never reads OAuth credentials or the system keychain. For the Anthropic API, set `ANTHROPIC_API_KEY` in the environment, with a key created in the [Claude Console](../04-API-Reference/Other/usage-limits.md), or supply an `apiKeyHelper` in the `--settings` JSON. Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry continue to read their own provider credentials as usual. 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` is the recommended mode for scripted and SDK calls, and will become the default for `-p` in a future release.
[](#background-tasks-at-exit)
Background tasks at exit
If Claude starts a [background Bash task](tools-reference.md#bash-tool-behavior) during a `claude -p` run, for example a dev server or a watch build, that shell is terminated about five seconds after Claude has returned its final result and stdin has closed. The grace period lets a task that finishes right after the result still deliver its output. If Claude starts a background [subagent](../09-Agents-Patterns/sub-agents.md) or workflow, `claude -p` instead stays open until that work completes, because its result is part of the final output. By default the wait ends after 10 minutes of continuous idle waiting, so a stuck subagent or workflow can’t hold the process open indefinitely. At that point Claude Code stops whatever is still running and drops its partial result. To change the limit, set [`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`](env-vars.md), or set it to `0` to wait without one. If Claude starts a [Monitor](tools-reference.md#monitor-tool) watch during a `claude -p` run, Claude Code waits for the watch until it times out or the ten-minute cap ends the wait, whichever comes first. While it waits, Claude keeps responding to what the watch reports. By default, a watch times out five minutes after Claude starts it.
[](#stop-a-run-with-sigterm)
Stop a run with SIGTERM
If you stop a `claude -p` run with SIGTERM, for example with `kill` or from a process supervisor, Claude Code exits with code 143. Claude Code leaves the turn that was in progress unfinished and records no result for it. To end the turn instead, send SIGINT, or call the Agent SDK’s `interrupt()`, before you stop the process. On SIGTERM, Claude Code terminates the process tree of any Bash command that is still running. Claude Code then runs [`SessionEnd` hooks](../07-Hooks/hooks.md#sessionend) and exits. While exiting, Claude Code starts no new tool call, sends no new model request, and runs no hook other than `SessionEnd`. If the run was in the middle of a command or waiting on a permission prompt when the signal arrived, Claude Code handles that step as follows:
- **Running a command**: Claude Code records the command as killed in the session.
- **Waiting for an answer to a permission prompt**: if you send SIGTERM to the process, Claude Code leaves the prompt unanswered. If your program closes the session through the Agent SDK, the SDK ends Claude Code’s input before sending any signal, and Claude Code cancels the prompt as soon as the input ends.
When you [resume the session](#continue-conversations), Claude Code leaves the interrupted turn as it is, and your next prompt drives the conversation. To have Claude Code continue the interrupted turn on resume instead, set [`CLAUDE_CODE_RESUME_INTERRUPTED_TURN=1`](env-vars.md).
[](#if-the-working-directory-is-deleted)
If the working directory is deleted
If the working directory of a `claude -p` or Agent SDK session is deleted mid-session, the session keeps running. When a turn starts while the directory is missing, Claude Code emits a [warning message](../05-Agent-SDK/agent-sdk-typescript.md#sdkinformationalmessage) in `stream-json` output, and shell commands fail until the directory exists again.
[](#examples)
Examples
These examples highlight common CLI patterns. Where a command names a file such as `auth.py` or `build-error.txt`, substitute a file from your own project. In CI or other scripted environments, add [`--bare`](#start-faster-with-bare-mode) so Claude Code starts without loading the host’s hooks, plugins, auto memory, or `CLAUDE.md`.
[](#pipe-data-through-claude)
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:
```python
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 without consulting the [usage dashboard](../17-Billing-Plans/costs.md). When you continue an earlier conversation with `--continue` or `--resume`, the run reports the conversation’s whole total, [earlier runs’ spend included](../05-Agent-SDK/agent-sdk-cost-tracking.md#accumulate-costs-across-multiple-calls). Both figures are [client-side estimates](../05-Agent-SDK/agent-sdk-cost-tracking.md) and can differ from your actual bill.
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.
If Claude Code can’t read stdin, for example because the process that started it disconnected its end, Claude Code prints a warning to stderr and continues with the prompt from the command line. Before v2.1.211, an unreadable stdin on Windows crashed the session or made it exit silently with no output.
[](#add-claude-to-a-build-script)
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:
```python
{
"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.\""
}
}
```
Run it with `npm run lint:claude`.
[](#get-structured-output)
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:
```python
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](https://json-schema.org/) 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:
```python
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"]}'
```
If the value isn’t a valid JSON Schema, `claude` exits with `Error: --json-schema is not a valid JSON Schema` followed by the validator’s diagnostic. Claude Code accepts schemas that use the `format` keyword, such as `"format": "email"`, but treats `format` as an annotation and doesn’t enforce it. Before v2.1.205, Claude Code silently ignored an invalid schema and returned unstructured text, and treated any schema containing `format` as invalid.
Use a tool like [jq](https://jqlang.org/) to parse the response and extract specific fields:
```python
# 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)
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:
```python
claude -p "Explain recursion" --output-format stream-json --verbose --include-partial-messages
```
The last line of the stream is a `result` message with the final response text, cost, and session metadata. If your consumer reads the stream slowly, Claude Code waits for the queued output to drain before exiting, scaling the wait with how much is still queued, capped at 30 seconds. Before v2.1.214 the exit wait was capped at about two seconds, which could cut off the end of a large response. The following example uses [jq](https://jqlang.org/) 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:
```python
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'
```
For programmatic streaming with callbacks and message objects, see [Stream responses in real-time](../05-Agent-SDK/agent-sdk-streaming-output.md) in the Agent SDK documentation.
[](#follow-subagent-messages)
Follow subagent messages
Messages from [subagents](../09-Agents-Patterns/sub-agents.md) appear in the stream as `assistant` and `user` messages whose `parent_tool_use_id` field is the ID of the tool call that spawned the subagent. Messages from the main conversation carry `null` in that field. The first message from a subagent running in the [foreground](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) is a `user` message carrying the prompt that drives it. After that first message, Claude Code emits:
- **By default**: the subagent’s `tool_use` and `tool_result` blocks.
- **With [`--forward-subagent-text`](cli-reference.md#cli-flags) or [`CLAUDE_CODE_FORWARD_SUBAGENT_TEXT`](env-vars.md)**: the subagent’s text and thinking blocks too, so you can reconstruct each subagent’s transcript. This requires Claude Code v2.1.211 or later.
When you enable either option, Claude Code forwards messages from [subagents at every nesting depth](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents), whether each one was spawned with the Agent tool or started as a [forked skill](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent). Messages of subagents that a forked skill spawns, and of forked skills started inside a subagent or another forked skill, require Claude Code v2.1.275 or later. In `parent_tool_use_id`, the nested subagent’s messages carry the ID of the Agent or Skill tool call that started it, so you can rebuild the full nesting tree by following those IDs. Before v2.1.219, messages from nested subagents didn’t appear in the stream. Skills that [run in a subagent](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent) appear in the stream the same way: the forked skill’s first message is a `user` message carrying the skill content that drives the run. If you enable either option, the stream also carries the forked skill’s text and thinking blocks. Before v2.1.265, only a forked skill’s `tool_use` and `tool_result` blocks appeared in the stream.
[](#handle-api-retries)
Handle API retries
When an API request fails with a retryable error, Claude Code emits a `system/api_retry` event before retrying. On v2.1.246 or later, when a `401` or `403` rejects an [`apiKeyHelper`](settings-reference.md#apikeyhelper) credential, Claude Code makes the first two retries quietly with no event, then emits the event as usual from the third consecutive retry onward. The quiet retries still count toward `attempt`. You can use the event to show retry progress in your own interface.
| 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 for this failure’s cause, which can be fewer than the session-wide budget |
| `retry_delay_ms` | integer | milliseconds until the next attempt |
| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |
| `no_response` | object, optional | present only when the failed attempt got [no response headers in time](errors.md#no-response-from-api). `waited_ms` is how long that attempt waited and `retry_wait_ms` is how long the retry will wait. In these events, `max_retries` reflects the one retry this cause normally gets, not the session-wide budget. Requires Claude Code v2.1.261 or later |
| `error` | string | error category: `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `rate_limit`, `overloaded`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, or `unknown` |
| `uuid` | string | unique event identifier |
| `session_id` | string | session the event belongs to |
[](#read-session-metadata)
Read session metadata
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 startup events precede it:
- `plugin_install` events, when [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](env-vars.md) is set.
- [`hook_started`, `hook_progress`, and `hook_response` events](../05-Agent-SDK/agent-sdk-typescript.md#sdkhookstartedmessage), while a configured [`SessionStart`](../07-Hooks/hooks.md#sessionstart) or [`Setup`](../07-Hooks/hooks.md#setup) hook runs. These stream as the hook produces them. Claude Code v2.1.169 through v2.1.203 delivered them in one batch after the hook completed, still ahead of `system/init`; v2.1.204 restored live delivery.
The event also carries an optional `capabilities` array of strings naming the protocol behaviors this Claude Code version implements, such as `interrupt_receipt_v1` or `interrupt_cancel_queued_v1`. Check it to feature-detect instead of comparing version strings, and ignore values you don’t recognize. The field requires Claude Code v2.1.205 or later and is absent from earlier versions. See [`SDKSystemMessage`](../05-Agent-SDK/agent-sdk-typescript.md#sdksystemmessage) for the capability list.
[](#fail-ci-when-a-plugin-or-mcp-server-doesn’t-load)
Fail CI when a plugin or MCP server doesn’t load
Use the plugin fields in the `system/init` event to catch a plugin that didn’t 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. A plugin that didn’t load is absent from `plugins`. The key is omitted when there are no errors |
When a `--plugin-dir` directory or archive itself fails to load, its `plugin_errors` entry includes the resolved absolute path as `path`. Use it to tell which of several `--plugin-dir` values failed. The `path` field requires Claude Code v2.1.283 or later. Use the MCP server fields the same way. When you pass [`--mcp-config`](cli-reference.md#cli-flags) with `-p`, Claude Code waits for still-pending servers before running the first turn, up to the [`MCP_TIMEOUT`](env-vars.md) startup timeout, 30 seconds by default. A remote server with a [cached tool list](../05-Agent-SDK/agent-sdk-mcp.md#connection-timing) skips the wait, shows `pending` in `system/init`, and connects on its first tool call. The wait requires Claude Code v2.1.221 or later. Claude Code validates each `--mcp-config` entry at startup and skips entries that fail validation, for example a `url` entry with no `type`. The run continues and exits cleanly, so check these fields to catch a server that never loaded:
| Field | Type | Description |
|---------------------|-------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mcp_servers` | array | MCP servers in the session, each with `name` and `status` |
| `mcp_server_errors` | array | `--mcp-config` entries skipped by config validation, each with `name`, `type`, and `message`. `type` is a skip category such as `unknown_type`, `url_missing_type`, `invalid_config`, or `reserved_name`; treat values you don’t recognize as a generic skip. Affected servers are absent from `mcp_servers`. The key is omitted when there are no errors, so a CI gate can fail on a non-empty array. Requires Claude Code v2.1.219 or later |
When you run the command by hand in a terminal, Claude Code also prints a startup warning to stderr, such as `Warning: 1 MCP server skipped due to invalid config:`, followed by the reason for each skipped entry. When you redirect stderr, or when a program such as a CI runner or an SDK host captures it, Claude Code prints no warning and reports the skipped entries only in the `mcp_server_errors` field. The warning requires Claude Code v2.1.219 or later.
[](#track-plugin-installs)
Track plugin installs
When [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](env-vars.md) 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 |
[](#auto-approve-tools)
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:
```python
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](permission-modes.md). For `-p`, the [built-in starting permission mode](permission-modes.md#which-mode-a-session-starts-in) is Manual on every plan, so pass the permission mode you want:
- **`auto`**: pass `--permission-mode auto` to have a classifier review most actions instead of you
- **`dontAsk`**: Claude Code denies every call that would otherwise prompt, which is useful for locked-down CI runs. Actions that need no approval in Manual mode still run, such as file reads in your working directories and the [read-only command set](permissions.md#read-only-commands), and so do actions your `--allowedTools` entries or `permissions.allow` rules cover. `AskUserQuestion`, connector tools [your organization set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools), and MCP tools marked [`requiresUserInteraction`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool) are denied even when an allow rule matches
- **`acceptEdits`**: Claude writes files without prompting, and Claude Code auto-approves common filesystem commands such as `mkdir`, `touch`, `mv`, and `cp`. The [actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) still apply. Apart from the read-only command set, other shell commands and network requests still need an `--allowedTools` entry or a `permissions.allow` rule. See [what `acceptEdits` auto-approves](permission-modes.md#auto-approve-file-edits-with-acceptedits-mode) for the full list
This example applies lint fixes with `acceptEdits` as the baseline:
```python
claude -p "Apply the lint fixes" --permission-mode acceptEdits
```
[](#turn-off-permission-prompts-in-unattended-runs)
Turn off permission prompts in unattended runs
Pass `--permission-prompts none` when nobody is available to answer permission prompts, for example in a scheduled job. The flag matters most when your run has a permission host: an Agent SDK app with a [`canUseTool` callback](../05-Agent-SDK/agent-sdk-user-input.md), or an MCP tool you pass with [`--permission-prompt-tool`](cli-reference.md#cli-flags). Without the flag, your run waits for that host to answer each permission request. With the flag, your run doesn’t consult the host or wait on it. Anything that would prompt is denied unless a `PermissionRequest` hook allows it, Claude is told that nobody can approve the request and not to retry it, and the run continues. In a `-p` run with no host, these requests are denied either way, and the flag also tells Claude not to retry them. Permission rules, [`PermissionRequest` hooks](../07-Hooks/hooks.md#permissionrequest), and the permission mode you set still decide every call first; Claude Code denies only the requests that nothing else resolves. This example runs an unattended task in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode). The classifier reviews each action as usual, and Claude Code denies anything that would have fallen back to a prompt:
```python
claude -p "Update the dependency pins and run the tests" --permission-mode auto --permission-prompts none
```
With `--permission-prompts none`, Claude Code removes the tools that need an answer from a person, such as [`AskUserQuestion`](tools-reference.md#askuserquestion-tool-behavior), so Claude can’t call them. Any [MCP elicitation request](../06-MCP-Tools/General/mcp.md#respond-to-mcp-elicitation-requests) that no [`Elicitation` hook](../07-Hooks/hooks.md#elicitation) answers is cancelled. With `--output-format stream-json`, denials appear as `permission_denied` system messages, and the final result message lists them in `permission_denials`.
The `--permission-prompts` flag requires Claude Code v2.1.259 or later. Earlier versions reject it with an unknown-option error.
[](#create-a-commit)
Create a commit
This example reviews staged changes and creates a commit with an appropriate message:
```python
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](settings-reference.md#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`.
Command support differs in `-p` mode:
- User-invoked [skills](../08-Plugins-Skills/skills.md) and custom commands work. Include `/skill-name` in the prompt string and Claude Code expands it before running.
- Built-in commands that only run in the terminal interface, such as `/login`, aren’t available.
- `/model`, `/effort`, `/fast`, `/color`, and `/rename` accept the value as an argument, for example `/model sonnet`, and `/mcp` with no argument prints a text summary of server status. These forms require Claude Code v2.1.205 or later and follow each command’s [availability notes](commands.md#all-commands).
- To change a setting, pass `key=value` to `/config`, for example `/config thinking=false`.
- `/output-style <style>` switches [output styles](output-styles.md) and `/output-style` alone lists them. Requires Claude Code v2.1.269 or later.
[](#customize-the-system-prompt)
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. Save it as a shell script, for example `review.sh`:
```python
gh pr diff "$1" | claude -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format json
```
In the script, `"$1"` stands for the first argument you pass on the command line. Run `bash review.sh 123` and the shell replaces `"$1"` with `123`, so the script fetches the diff for PR 123. Claude Code prints the review as JSON, with the text in the `result` field. See [system prompt flags](cli-reference.md#system-prompt-flags) for more options including `--system-prompt` to fully replace the default prompt.
[](#continue-conversations)
Continue conversations
Use `--continue` to continue the most recent conversation, or `--resume` with a session ID to continue a specific conversation. On Claude Code v2.1.257 or later, when you pass `--continue`, Claude Code opens a [background session](sessions.md#resume-a-session) that has finished, but not one that is still running. This example runs a review, then sends follow-up prompts:
```python
# 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:
```python
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"
```
You can run the two commands from different directories: Claude Code [finds the session by its ID](sessions.md#resume-a-session) in any project on this machine. Before v2.1.223, Claude Code looked for the ID only in the current project directory and its git worktrees, so you had to run both commands from the same directory. In place of the session ID, you can pass `--resume` the absolute path to a session’s `.jsonl` [transcript file](sessions.md#where-transcripts-are-stored), and Claude Code continues the conversation stored in that file.
[](#next-steps)
Next steps
- [Agent SDK quickstart](../05-Agent-SDK/agent-sdk-quickstart.md): build your first agent with Python or TypeScript
- [CLI reference](cli-reference.md): all CLI flags and options
- [GitHub Actions](github-actions.md): use the Agent SDK in GitHub workflows
- [GitLab CI/CD](gitlab-ci-cd.md): use the Agent SDK in GitLab pipelines
---
## How Claude Code works - Claude Code Docs
Source: https://code.claude.com/docs/en/how-claude-code-works
Path: 02-Claude-Code-CLI/how-claude-code-works.md
## On this page
- [The agentic loop](#the-agentic-loop)
- [Models](#models)
- [Tools](#tools)
- [What Claude can access](#what-claude-can-access)
- [Environments and interfaces](#environments-and-interfaces)
- [Execution environments](#execution-environments)
- [Interfaces](#interfaces)
- [Work with sessions](#work-with-sessions)
- [Work across branches](#work-across-branches)
- [Resume or fork sessions](#resume-or-fork-sessions)
- [The context window](#the-context-window)
- [Context Claude Code adds on its own](#context-claude-code-adds-on-its-own)
- [When context fills up](#when-context-fills-up)
- [Manage context with skills and subagents](#manage-context-with-skills-and-subagents)
- [Stay safe with checkpoints and permissions](#stay-safe-with-checkpoints-and-permissions)
- [Undo changes with checkpoints](#undo-changes-with-checkpoints)
- [Control what Claude can do](#control-what-claude-can-do)
- [Work effectively with Claude Code](#work-effectively-with-claude-code)
- [Ask Claude Code for help](#ask-claude-code-for-help)
- [It’s a conversation](#it%E2%80%99s-a-conversation)
- [Interrupt and steer](#interrupt-and-steer)
- [Delegate, don’t dictate](#delegate-don%E2%80%99t-dictate)
- [What’s next](#what%E2%80%99s-next)
Core concepts
# How Claude Code works
Copy pageCopy page
Understand the agentic loop, built-in tools, and how Claude Code interacts with your project.
Copy pageCopy page
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](#work-effectively-with-claude-code). For step-by-step walkthroughs, see [Common workflows](common-workflows.md). For extensibility features like skills, MCP, and hooks, see [Extend Claude Code](features-overview.md).
[](#the-agentic-loop)
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](#models) that reason and [tools](#tools) that act. Claude Code is the layer around the model that provides the tools and manages the context the model sees. This surrounding layer is what the term agentic harness refers to.
[](#models)
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](model-config.md) 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
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](../08-Plugins-Skills/plugins-code-intelligence.md)) |
These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See [Tools available to Claude](tools-reference.md) 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:
1. Run the test suite to see what’s failing
2. Read the error output
3. Search for the relevant source files
4. Read those files to understand the code
5. Edit the files to fix the issue
6. 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](../08-Plugins-Skills/skills.md), connect to external services with [MCP](../06-MCP-Tools/General/mcp.md), automate workflows with [hooks](../07-Hooks/hooks.md), and offload tasks to [subagents](../09-Agents-Patterns/sub-agents.md). These extensions form a layer on top of the core agentic loop. See [Extend Claude Code](features-overview.md) for guidance on choosing the right extension for your needs.
[](#what-claude-can-access)
What Claude can access
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](memory.md).** A markdown file where you store project-specific instructions, conventions, and context that Claude should know every session. If your repository has an AGENTS.md for other coding agents, Claude [can read that](memory.md#agents-md) on its own or alongside CLAUDE.md.
- **[Auto memory](memory.md#auto-memory).** Learnings Claude saves automatically as you work, like 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](../06-MCP-Tools/General/mcp.md) for external services, [skills](../08-Plugins-Skills/skills.md) for workflows, [subagents](../09-Agents-Patterns/sub-agents.md) for delegated work, and [Claude in Chrome](../03-IDE-Integrations/chrome.md) 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)
Environments and interfaces
The [agentic loop](#the-agentic-loop), [tools](#tools), and capabilities are the same everywhere you use Claude Code. What changes is where the code executes and how you interact with it.
[](#execution-environments)
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, or [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md) your organization operates | Offload tasks, work on repos you don’t have locally |
| **Remote Control** | Your machine, controlled from a browser | Use the web UI while execution and your files stay local |
[](#interfaces)
Interfaces
You can access Claude Code through the terminal, the [desktop app](../16-Mobile-Desktop/desktop.md), [IDE extensions](../03-IDE-Integrations/vs-code.md), [claude.ai/code](https://claude.ai/code), [Remote Control](remote-control.md), [Slack](../14-Connectors/slack.md), and [CI/CD pipelines](github-actions.md). The interface determines how you see and interact with Claude, but the underlying agentic loop is identical. See [Use Claude Code everywhere](code-home.md#use-claude-code-everywhere) for the full list.
[](#work-with-sessions)
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](#undo-changes-with-checkpoints), [resuming, and forking](#resume-or-fork-sessions) 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`](claude-directory.md#application-data). **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](memory.md#auto-memory), and you can add your own persistent instructions in [CLAUDE.md](memory.md).
[](#work-across-branches)
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](sessions.md#use-the-session-picker) 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](worktrees.md), which create separate directories for individual branches.
[](#resume-or-fork-sessions)
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](sessions.md).
[](#the-context-window)
The context window
Claude’s context window holds your conversation history, file contents, command outputs, [CLAUDE.md](memory.md), [auto memory](memory.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](context-window.md).
[](#context-claude-code-adds-on-its-own)
Context Claude Code adds on its own
If Claude follows a rule you didn’t write, such as adding a `Co-Authored-By` trailer to a commit, the rule may have come from a [system reminder](glossary.md#system-reminder). As you work, Claude Code adds its own context to the conversation alongside your messages:
- Your CLAUDE.md files
- The instructions of your [output style](output-styles.md)
- A note when a file Claude read earlier changes on disk
- The commit and pull request attribution lines
To change or remove the attribution lines, set [`attribution`](settings-reference.md#attribution). To remove Claude Code’s built-in commit and pull request instructions, set [`includeGitInstructions`](settings-reference.md#includegitinstructions) to `false`. For the other switches, see [Turn off the context your agent replaces](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#turn-off-the-context-your-agent-replaces).
[](#when-context-fills-up)
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](troubleshooting.md#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](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search), so only tool names and server instructions consume context until Claude uses a specific tool.
[](#manage-context-with-skills-and-subagents)
Manage context with skills and subagents
Beyond compaction, you can use other features to control what loads into context. [Skills](../08-Plugins-Skills/skills.md) 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`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) to do the same from settings. [Subagents](../09-Agents-Patterns/sub-agents.md) work in their own context window. A subagent starts fresh unless it’s a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), which starts with a copy of your conversation so far. Either way, the subagent’s tool calls stay out of your context, and Claude gets back a summary when the subagent finishes. See [context costs](features-overview.md#understand-context-costs) for what each feature costs, and [reduce token usage](../17-Billing-Plans/costs.md#reduce-token-usage) for tips on managing context.
[](#stay-safe-with-checkpoints-and-permissions)
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)
Undo changes with checkpoints
**File edits are reversible.** Before Claude edits a 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 separate from git and remain available when you resume a conversation. They only cover file changes, and a restore [skips symlinked and hard-linked files](checkpointing.md#symlinked-and-hard-linked-paths-not-restored). Actions that affect remote systems (databases, APIs, deployments) can’t be checkpointed. You control those with your permission mode and permission rules.
[](#control-what-claude-can-do)
Control what Claude can do
Choose a permission mode to set what Claude can do without asking you. Press `Shift+Tab` to cycle through the permission modes:
- **Auto**: a classifier reviews most actions in the background and blocks the risky ones instead of asking you. With Claude Code v2.1.283 or later, it’s the [built-in starting permission mode](permission-modes.md#which-mode-a-session-starts-in) for interactive terminal and VS Code sessions, and on earlier versions only on Pro, Max, and Team plans
- **Manual**: Claude asks before file edits and shell commands
- **Accept edits**: Claude edits files and runs common filesystem commands like `mkdir` and `mv` without asking, still asks for other commands
- **Plan**: Claude explores and proposes a plan without editing your source files
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](permissions.md) for details.
------------------------------------------------------------------------
[](#work-effectively-with-claude-code)
Work effectively with Claude Code
These tips help you get better results from Claude Code. For more on specific prompts, verification, and planning, see [Best practices](best-practices.md).
[](#ask-claude-code-for-help)
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` generates a starter CLAUDE.md for your project
- `/doctor` runs a setup checkup that diagnoses installation and configuration issues and can fix them
[](#it’s-a-conversation)
It’s a conversation
Claude Code is conversational. You don’t need perfect prompts. Start with what you want, then refine:
```python
Fix the login bug
```
\[Claude investigates, tries something\]
```python
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)
Interrupt and steer
You can redirect Claude at any point without starting over. Do either of these:
- **Press `Esc`** to stop Claude immediately. The running tool call is canceled and Claude waits for your next instruction. If you have messages queued, Claude Code [sends them next](interactive-mode.md#queue-messages-while-claude-works).
- **Type a correction and press `Enter`** without stopping Claude. The message shows as queued in the conversation. If Claude is running tool calls, it reads the message as soon as those calls finish, within the same turn, and adjusts before its next step. [Queue messages while Claude works](interactive-mode.md#queue-messages-while-claude-works) covers when other queued entries are sent.
[](#delegate-don’t-dictate)
Delegate, don’t dictate
Think of delegating to a capable colleague. Give context and direction, then trust Claude to figure out the details:
```python
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)
What’s next
## Extend with features
Add skills and MCP connections
## Common workflows
Step-by-step guides for typical tasks
---
## How to create custom skills | Claude Help Center
Source: https://support.claude.com/en/articles/12512198-how-to-create-custom-skills
Path: 02-Claude-Code-CLI/how-to-create-custom-skills.md
# How to create custom skills
July 22, 2026
Skills are available for users on Free, Pro, Max, Team, and Enterprise plans. This feature requires **[code execution to be enabled](../15-Claude-AI-Features/create-and-edit-files-with-claude.md#h_1c99382190)**. Skills are also available in beta for Claude Code users and for all API users using the code execution tool.
Custom skills let you enhance Claude with specialized knowledge and workflows specific to your organization or personal work style. This article explains how to create, structure, and test your own skills.
Skills can be as simple as a few lines of instructions or as complex as multi-file packages with executable code. The best skills:
- Solve a specific, repeatable task
- Have clear instructions that Claude can follow
- Include examples when helpful
- Define when they should be used
- Are focused on one workflow rather than trying to do everything
------------------------------------------------------------------------
## Record a skill
Recording a skill is available on Pro, Max, and Team plans, in Cowork in Claude for Mac. It isn't available in chat, on Windows, or on Free and Enterprise plans.
Instead of writing a skill by hand, you can record yourself doing a task and let Claude build the skill from what it observes. You send Claude a video of your screen, clicks, typing, and voice, and Claude proposes a skill for you to review before you save it.
### Before you record
1. Update to the latest version of Claude for Mac.
2. Grant the macOS permissions Claude asks for the first time you record: **Accessibility** for mouse and keyboard tracking, and **Screen recording** for screen visibility. macOS may ask you to restart Claude.
3. Close any files, apps, or conversations you don't want captured.
**Warning:** Don't type passwords or secrets, or display sensitive information or private conversations while recording. Everything on your screen is captured for the length of the session, along with anything you say.
### Record your workflow
1. Open Cowork in Claude for Mac.
2. Start a recording one of two ways:
1. Click the "+" button in the composer, then select "Record a skill."
2. Go to **[Customize \> Skills](https://claude.ai/customize/skills)**, click "Add," then select "Record your screen."
3. Click "Start recording." To narrate as you work, leave the microphone on. Use the microphone control to mute it or choose a different input.
4. Do the task the way you normally would. The capture bar shows that recording is in progress and counts the steps it's captured.
5. Click "Done" when you're finished, or "Discard" to throw the recording away without creating anything.
A recording can run for about 10 minutes. A countdown appears in the capture bar when you have about a minute left. When it reaches zero, recording stops and everything you've captured up to that point is sent to Claude, the same as if you'd clicked "Done."
**Tip:** Talk through what you're doing while you record. Narration gives Claude context it can't get from your screen alone, like why you skip a step or how you choose between two options.
### What happens after you click Done
Claude starts a Cowork task and reviews the recording, then proposes a skill. Depending on what it finds, you'll see one of two things:
- **A new skill,** marked **NEW** on the proposal card. Click "Save" to keep it, or "Dismiss" to discard the proposal.
- **An update to an existing skill.** If the recording overlaps a skill you already have, Claude proposes changes to that skill instead. The card shows which skill the proposal is based on. Click "Update" to apply the changes, or "Dismiss" to discard them.
Expand **Content** on the proposal card to read the skill before you decide.
Skills you save from a recording appear in **[Customize \> Skills](https://claude.ai/customize/skills)** and work like any other skill. You can edit them, share them, and delete them on the same terms.
### What's kept from a recording
The video and audio from your recording aren't retained. After you send your recording to Claude, Claude reviews the recording to build the skill. What's saved afterward is a set of screenshots from the session, which you can view by expanding the **Recorded demonstration** step in the task.
Because those screenshots live in the Cowork task, deleting the task removes them. See **[Get started with Claude Cowork](../15-Claude-AI-Features/getting-started-with-local-agent-mode.md)** for how task deletion and retention work.
------------------------------------------------------------------------
## Create a skill.md file
Every skill consists of a directory containing at minimum a skill.md file, which is the core of the skill. This file must start with a YAML frontmatter to hold name and description fields, which are required metadata. It can also contain additional metadata, instructions for Claude or reference files, executable scripts, or tools.
### Required metadata fields
**name:** A human-friendly name for your skill (64 characters maximum)
- **Example:** Brand Guidelines
**description:** A clear description of what the skill does and when to use it.
- This is critical—Claude uses this to determine when to invoke your skill (200 characters maximum).
- **Example:** Apply Acme Corp brand guidelines to presentations and documents, including official colors, fonts, and logo usage.
### Optional metadata fields
**dependencies:** Software packages required by your skill.
- **Example:** python\>=3.8, pandas\>=1.5.0
The metadata in the skill.md file serves as the first level of a progressive disclosure system, providing just enough information for Claude to know when the skill should be used without having to load all of the content.
### Markdown body
The markdown body is the second level of detail after the metadata, so Claude will access this if needed after reading the metadata. Depending on your task, Claude can access the skill.md file and use the skill.
### Example skill.md
**Brand guidelines skill**
## Metadata
name: Brand Guidelines
description: Apply Acme Corp brand guidelines to all presentations and documents
## Overview
This skill provides Acme Corp's official brand guidelines for creating consistent, professional materials. When creating presentations, documents, or marketing materials, apply these standards to ensure all outputs match Acme's visual identity. Claude should reference these guidelines whenever creating external-facing materials or documents that represent Acme Corp.
## Brand Colors
Our official brand colors are:
- Primary: #FF6B35 (Coral)
- Secondary: #004E89 (Navy Blue)
- Accent: #F7B801 (Gold)
- Neutral: #2E2E2E (Charcoal)
## Typography
Headers: Montserrat Bold
Body text: Open Sans Regular
Size guidelines:
- H1: 32pt
- H2: 24pt
- Body: 11pt
## Logo Usage
Always use the full-color logo on light backgrounds. Use the white logo on dark backgrounds. Maintain minimum spacing of 0.5 inches around the logo.
## When to Apply
Apply these guidelines whenever creating:
- PowerPoint presentations
- Word documents for external sharing
- Marketing materials
- Reports for clients
## Resources
See the resources folder for logo files and font downloads.
## Add resources
If you have too much information to add to a single skill.md file (e.g., sections that only apply to specific scenarios), you can add more content by adding files within your skill directory. For example, add a REFERENCE.md file containing supplemental and reference information to your skill directory. Referencing it in skill.md will help Claude decide if it needs to access that resource when executing the skill.
## Add scripts
For more advanced skills, attach executable code files to skill.md, allowing Claude to run code. For example, our document skills use the following programming languages and packages:
- Python (pandas, numpy, matplotlib)
- JavaScript/Node.js
- Packages to help with file editing
- Visualization tools
**Note:** Claude and Claude Code can install packages from standard repositories (Python PyPI, JavaScript npm) when loading skills. It’s not possible to install additional packages at runtime with API Skills—all dependencies must be pre-installed in the container.
------------------------------------------------------------------------
## Package your skill
Once your skill folder is complete:
1. Ensure the folder name matches your skill's name.
2. Create a ZIP file of the folder.
3. The ZIP should contain the skill folder as its root (not a subfolder).
**Correct structure:**
my-skill.zip
└── my-skill/
├── skill.md
└── resources/
**Incorrect structure:**
my-skill.zip
└── (files directly in ZIP root)
------------------------------------------------------------------------
## Test your skill
### Before uploading
1\. Review your skill.md for clarity.
2\. Check that the description accurately reflects when Claude should use the skill.
3\. Verify all referenced files exist in the correct locations.
4\. Test with example prompts to ensure Claude invokes it appropriately.
### After uploading to Claude
1\. Enable the skill in **[Customize \> Skills](https://claude.ai/customize/skills)**.
2\. Try several different prompts that should trigger it.
3\. Review Claude's thinking to confirm it's loading the skill.
4\. Iterate on the description if Claude isn't using it when expected.
When you're iterating on a skill with Claude in chat, you can edit the skill files directly where they open beside the conversation. Highlight the text you want changed, click "Edit with Claude," and type your request. For skills with multiple files, leave edit requests across the files and send them together, and Claude applies them in one pass. Learn more about **[editing artifacts](../15-Claude-AI-Features/what-are-artifacts-and-how-do-i-use-them.md#h_9cbf05e668)**.
**Note for Team and Enterprise plans:** To make a skill available to all users in your organization, see **[Provision and manage skills for your organization](../15-Claude-AI-Features/provisioning-and-managing-skills-for-your-organization.md)**.
------------------------------------------------------------------------
## Best practices
**Keep it focused:** Create separate skills for different workflows. Multiple focused skills compose better than one large skill.
**Write clear descriptions:** Claude uses descriptions to decide when to invoke your skill. Be specific about when it applies.
**Start simple:** Begin with basic instructions in Markdown before adding complex scripts. You can always expand on the skill later.
**Use examples:** Include example inputs and outputs in your skill.md file to help Claude understand what success looks like.
**Test incrementally:** Test after each significant change rather than building a complex skill all at once.
**Skills can build on each other:** While skills can't explicitly reference other skills, Claude can use multiple skills together automatically. This composability is one of the most powerful parts of the skills feature.
**Review the open Agent Skills specification:** Follow the guidelines at **[agentskills.io](http://agentskills.io)**, so skills you create can work across platforms that adopt the standard.
For a more in-depth guide to skill creation, refer to **[Skill authoring best practices](../04-API-Reference/Agents-Tools/agents-and-tools-agent-skills-best-practices.md)** in our Claude Docs.
------------------------------------------------------------------------
## Security considerations
- Exercise caution when adding scripts to your skill.md file.
- Don't hardcode sensitive information (API keys, passwords).
- Review any skills you download before enabling them.
- Use appropriate MCP connections for external service access.
------------------------------------------------------------------------
## Example skills to reference
Visit our repository on GitHub for example skills you can use as templates: **[https://github.com/anthropics/skills/tree/main/skills](https://github.com/anthropics/skills/tree/main/skills)**.
---
## Interactive mode - Claude Code Docs
Source: https://code.claude.com/docs/en/interactive-mode
Path: 02-Claude-Code-CLI/interactive-mode.md
## On this page
- [Keyboard shortcuts](#keyboard-shortcuts)
- [General controls](#general-controls)
- [Text editing](#text-editing)
- [Word boundaries in editing shortcuts](#make-ctrl-w-delete-back-to-whitespace)
- [Theme and display](#theme-and-display)
- [Multiline input](#multiline-input)
- [Quick commands](#quick-commands)
- [Transcript viewer](#transcript-viewer)
- [Voice input](#voice-input)
- [Commands](#commands)
- [Complete a command mid-prompt](#complete-a-command-mid-prompt)
- [Vim editor mode](#vim-editor-mode)
- [Mode switching](#mode-switching)
- [Remap INSERT-mode key sequences](#remap-insert-mode-key-sequences)
- [Navigation (NORMAL mode)](#navigation-normal-mode)
- [Editing (NORMAL mode)](#editing-normal-mode)
- [Text objects (NORMAL mode)](#text-objects-normal-mode)
- [Visual mode](#visual-mode)
- [Command history](#command-history)
- [Reverse search with Ctrl+R](#reverse-search-with-ctrl%2Br)
- [Background Bash commands](#background-bash-commands)
- [How backgrounding works](#how-backgrounding-works)
- [Shell mode with ! prefix](#shell-mode-with-prefix)
- [Queue messages while Claude works](#queue-messages-while-claude-works)
- [When Claude Code sends what you queued](#when-claude-code-sends-what-you-queued)
- [Take back what you queued](#take-back-what-you-queued)
- [Prompt suggestions](#prompt-suggestions)
- [When Claude Code skips suggestions](#when-claude-code-skips-suggestions)
- [Turn prompt suggestions off](#turn-prompt-suggestions-off)
- [Emoji shortcodes](#emoji-shortcodes)
- [Check spelling as you type](#check-spelling-as-you-type)
- [Prerequisites](#prerequisites)
- [Turn spell checking on or off](#turn-spell-checking-on-or-off)
- [What Claude Code underlines](#what-claude-code-underlines)
- [When Claude Code underlines nothing](#when-claude-code-underlines-nothing)
- [Invisible characters in prompts](#invisible-characters-in-prompts)
- [Review changes with /diff](#review-changes-with-%2Fdiff)
- [Diff panel](#diff-panel)
- [Diff viewer](#diff-viewer)
- [Side questions with /btw](#side-questions-with-%2Fbtw)
- [Task list](#task-list)
- [Session recap](#session-recap)
- [Wait for a usage limit to reset](#wait-for-a-usage-limit-to-reset)
- [Cancel the wait](#cancel-the-wait)
- [Start a wait yourself](#start-a-wait-yourself)
- [Turn automatic continue off](#turn-automatic-continue-off)
- [PR review status](#pr-review-status)
- [GitLab merge requests](#gitlab-merge-requests)
- [Issue reference links](#issue-reference-links)
- [See also](#see-also)
Reference
# Interactive mode
Copy pageCopy page
Complete reference for keyboard shortcuts, input modes, and interactive features in Claude Code sessions.
Copy pageCopy page
[](#keyboard-shortcuts)
Keyboard shortcuts
Keyboard shortcuts may vary by platform and terminal. In [fullscreen rendering](fullscreen.md), press `?` in the transcript viewer to see available shortcuts there.**macOS users**: Option/Alt key shortcuts (`Alt+B`, `Alt+F`, `Alt+D`, `Alt+Y`, `Alt+P`) require configuring Option as Meta in your terminal. See [Enable Option key shortcuts on macOS](terminal-config.md#enable-option-key-shortcuts-on-macos) for the setting in each terminal.
[](#general-controls)
General controls
| Shortcut | Description | Context |
|:---------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Ctrl+C` | Interrupt, or clear input | Interrupts a running operation. If nothing is running, the first press clears the prompt input and a second press exits Claude Code |
| `Ctrl+X Ctrl+K` | Stop all running [background subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) in this session, and turn off [artifact auto-replies](artifacts.md#let-claude-reply-to-comments-on-its-own) for the rest of it. Press twice within 3 seconds to confirm | Subagent control |
| `Ctrl+D` | Exit Claude Code session | The first press shows a confirmation hint and a second press within 800ms exits. When the prompt has text, `Ctrl+D` deletes the character after the cursor instead |
| `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; Claude Code strips the comment block when you save |
| `Ctrl+L` | Redraw the screen | Forces a full terminal redraw, keeping input and conversation history. Use this to recover if the display becomes garbled or partially blank. See [Clear the conversation](fullscreen.md#clear-the-conversation) for fullscreen rendering |
| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution, with a timestamp and the model used on each assistant message. Also expands lines that collapse by default, such as MCP calls, shown as a single `Called slack 3 times` line, and [messages from your other sessions](cross-session-messaging.md#what-a-message-looks-like), shown as a one-line `Message from @<sender>` preview |
| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |
| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows and WSL) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt. On WSL, both `Ctrl+V` and `Alt+V` are bound; use `Alt+V` if your terminal intercepts `Ctrl+V` |
| `Ctrl+B` | Background running tasks | Backgrounds Bash commands and agents. Tmux users press twice |
| `Ctrl+T` | Toggle Claude’s task checklist | Show or hide [Claude’s to-do checklist](#task-list) in the status area. This is not the background-task view; use [`/tasks`](commands.md) to see running shells and subagents |
| `Ctrl+S` | Stash or restore prompt | With text in the input, stashes it and clears the prompt. Pressed again on an empty prompt, restores the stashed text, cursor position, pasted content, and input mode, so a stashed `!` [shell command](#shell-mode-with-prefix) comes back in shell mode |
| `Ctrl+Z` | Suspend Claude Code | Unix only. Suspends the process to your shell; run `fg` to resume |
| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus. In a tabbed dialog, the keys switch tabs while the tab row has focus. See [Tabs actions](keybindings.md#tabs-actions) for how focus moves |
| `Tab` | Accept an autocomplete suggestion, or add a comment to a permission answer | While autocomplete suggestions are showing in the prompt input, accepts the selected suggestion. On most permission prompts, with **Yes** or **No** focused, opens a comment field on that option, and pressing it again closes the field. See [add a comment when you answer a permission prompt](permissions.md#add-a-comment-when-you-answer-a-permission-prompt) |
| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | When the input spans more than one visual row, whether wrapped or multiline, first moves the cursor within the prompt. Once the cursor is on the first or last visual row, pressing again navigates command history. While you have messages queued, `Up` from the first row instead [takes them back](#take-back-what-you-queued) |
| `Esc` | Interrupt Claude, or close a dialog | Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far. If you have [messages queued](#queue-messages-while-claude-works), Claude Code sends them next. When a dialog is open, `Esc` closes the dialog. While a footer item is selected, such as a row in the [subagent panel](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) below the prompt, `Esc` [deselects it](keybindings.md#footer-actions) instead of interrupting. On a permission prompt, `Esc` declines the action, the same as [**No** without a comment](permissions.md#add-a-comment-when-you-answer-a-permission-prompt) |
| `Esc` + `Esc` | Clear input draft, or rewind | When the prompt input contains text, double `Esc` clears it and saves the draft to history so `Up` recalls it. When the input is empty, double `Esc` opens the [rewind menu](checkpointing.md) to restore or summarize code and conversation from a previous point |
| `Ctrl+Enter` or `Ctrl+X Ctrl+S` | Send queued messages now | Sends your [queued messages](#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. In [shell mode](#shell-mode-with-prefix), the key only queues your command. In terminals that don’t report extended keys, `Ctrl+Enter` arrives as plain `Enter`; `Ctrl+X Ctrl+S` works in any terminal. Requires Claude Code v2.1.275 or later |
| `Shift+Tab`, or `Alt+M` on Windows when the Node or Bun runtime doesn’t enable VT input mode | Cycle permission modes | Cycle through `default` (labeled Manual in the mode indicator), `acceptEdits`, `plan`, and, when available, `bypassPermissions` and then `auto`. From `auto`, the first press switches to `default`. See [permission modes](permission-modes.md). On a file permission prompt, the same key closes an open [comment field](permissions.md#add-a-comment-when-you-answer-a-permission-prompt). With no field open, it selects the option that allows the action for the rest of the session, when the prompt offers that option |
| `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. Has no effect on Opus 5.5, Sonnet 5.5, or the Fable models, which always use extended thinking. Works on macOS without configuring Option as Meta |
| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](fast-mode.md) |
[](#text-editing)
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 back to previous whitespace | Stores deleted text for pasting. One press removes a whole path or `--flag=value`. To delete only the previous word, press `Option+Delete` on macOS or `Ctrl+Backspace` on Windows |
| `Ctrl+Y` | Paste deleted text | Pastes the text you last deleted with one of the word or line deletion shortcuts, such as `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](#keyboard-shortcuts) on macOS |
| `Alt+B` | Move cursor back one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
| `Alt+F` | Move cursor forward one word | Moves to the end of the current word, or to the end of the next word when the cursor is between words. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
| `Alt+D` | Delete to end of word | Deletes to the end of the current word, or to the end of the next word when the cursor is between words. Stores deleted text for pasting. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
| `Ctrl+_` or `Ctrl+Shift+-` | Undo last input edit | Restores the previous input text and cursor position |
[](#make-ctrl-w-delete-back-to-whitespace)
Word boundaries in editing shortcuts
The word shortcuts `Alt+B`, `Alt+F`, `Alt+D`, `Option+Delete`, and `Ctrl+Backspace` treat a word as a run of letters and digits, so punctuation such as `_`, `.`, and `/` separates words. With `src/utils/foo.ts` in the prompt, repeated presses of `Alt+B` stop at the start of `ts`, `foo`, `utils`, and `src`. `Ctrl+W` is different: it ignores punctuation and deletes back to the previous whitespace, so one press removes all of `src/utils/foo.ts`. In text written without spaces, such as Chinese or Japanese, the word shortcuts still move or delete one word at a time. These readline conventions apply in Claude Code v2.1.261 and later. The [`keybindingFlavor`](settings-reference.md#keybindingflavor) setting that turned them on in earlier versions is deprecated and has no effect. You can’t remap these shortcuts in the [keybindings configuration file](keybindings.md), which has no actions for them.
[](#theme-and-display)
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)
Multiline input
| Method | Shortcut | Context |
|:-----------------|:---------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Quick escape | `\` + `Enter` | Works in all terminals |
| Option key | `Option+Enter` | After enabling [Option as Meta](terminal-config.md#enable-option-key-shortcuts-on-macos) on macOS |
| Shift+Enter | `Shift+Enter` | Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, Windows Terminal. For other terminals, see [Enter multiline prompts](terminal-config.md#enter-multiline-prompts) |
| Control sequence | `Ctrl+J` | Works in any terminal without configuration |
| Paste mode | Paste directly | For code blocks, logs |
[](#quick-commands)
Quick commands
| Shortcut | Description | Notes |
|:-------------------|:-------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/` at start | Command or skill | See [commands](#commands) and [skills](../08-Plugins-Skills/skills.md) |
| `!` at start | Shell mode | Run a command directly, add its output to the session, and have Claude respond to it |
| `@` | File path mention | Trigger file path autocomplete. In sessions with [cross-session messaging](cross-session-messaging.md#message-another-session), when you type at least one letter after the `@`, Claude Code also suggests your other live sessions on this machine, so you can tell Claude to message the one you pick. Requires Claude Code v2.1.232 or later |
| `:` | Emoji shortcode | Type a full `:name:` to insert the emoji, or two or more characters for suggestions. See [Emoji shortcodes](#emoji-shortcodes). Requires Claude Code v2.1.217 or later |
| `?` on empty input | Toggle the shortcut help panel | Typing `?` when the input already contains text inserts the character |
[](#transcript-viewer)
Transcript viewer
When the transcript viewer is open (toggled with `Ctrl+O`), these shortcuts are available. Run `/tui` with no argument to check which renderer is active. `Ctrl+E` can be rebound via [`transcript:toggleShowAll`](keybindings.md).
| Shortcut | Description |
|:---------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `?` | Toggle the keyboard shortcut help panel. Requires [fullscreen rendering](fullscreen.md) |
| `{` / `}` | Jump to the previous or next user prompt, like vim paragraph motion. Requires [fullscreen rendering](fullscreen.md) |
| `Ctrl+E` | Toggle show all content. Available in the classic renderer only, not in [fullscreen rendering](fullscreen.md) |
| `[` | 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](fullscreen.md#search-and-review-the-conversation) |
| `v` | Write the conversation to a temporary file and open it in `$VISUAL` or `$EDITOR`. Requires [fullscreen rendering](fullscreen.md) |
| `q`, `Ctrl+C`, `Esc` | Exit transcript view. All three can be rebound via [`transcript:exit`](keybindings.md) |
[](#voice-input)
Voice input
| Shortcut | Description | Notes |
|:--------------------|:----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Hold or tap `Space` | Voice dictation | Requires [voice dictation](voice-dictation.md) to be enabled. Hold to record, or run `/voice tap` for tap-to-toggle. [Rebindable](voice-dictation.md#rebind-the-dictation-key) |
[](#commands)
Commands
Type `/` in Claude Code to see the commands available to you, or type `/` followed by any letters to filter. The `/` menu lists built-in commands, bundled and user-authored [skills](../08-Plugins-Skills/skills.md), and commands contributed by [plugins](../08-Plugins-Skills/plugins.md) and [MCP servers](../06-MCP-Tools/General/mcp.md#use-mcp-prompts-as-commands). Not all built-in commands are visible to every user since some depend on your platform or plan, and [a few available commands are hidden from the menu by design](commands.md#how-the-command-menu-matches-what-you-type) and run when you type their full name. In [fullscreen rendering](fullscreen.md#use-the-mouse), the `/` command and `@` file suggestion lists also respond to the mouse: hovering highlights a row and clicking accepts it. See the [commands reference](commands.md) for the full list of commands included in Claude Code.
[](#complete-a-command-mid-prompt)
Complete a command mid-prompt
Command completion also works partway through a prompt: type `/` after a space, then the first letters of a name, as in `run the tests, then /com`. Only commands whose names start with those letters match, so a file path such as `/tmp/notes.md` doesn’t keep a list open. Claude Code runs a command itself only when the command [starts your message](commands.md).
- **In [fullscreen rendering](fullscreen.md)**: the matches open as a list while you type, with no row highlighted, so `Enter` still sends your prompt as typed. Press `Tab` to insert the top match, or pick a row with the arrow keys and `Enter`.
- **Outside fullscreen**: the rest of the top match appears as ghost text at your cursor, with a count such as `+2` when more commands match. Press `Tab` to insert the only match, or to open the list when several match, then pick a row with the arrow keys and `Enter`.
In both renderers, press `Tab` on a bare mid-prompt `/` to list every command. A plugin skill matches on its bare name too, so `/deploy` finds a skill named `myplugin:deploy-app`. When you insert the match, Claude Code writes the full `/myplugin:deploy-app`.
[](#vim-editor-mode)
Vim editor mode
Enable vim-style editing via `/config` → Editor mode. Claude Code keeps your vim mode and cursor position when you toggle the [transcript viewer](#transcript-viewer) with `Ctrl+O` or open and close a panel such as `/config`. If you leave the prompt in NORMAL mode, it’s still in NORMAL mode when you return, with the cursor where you left it.
[](#mode-switching)
Mode switching
| Command | Action | From mode |
|:------------------|:----------------------------------------------------------------------------------------------------------|:---------------|
| `Esc` or `Ctrl+[` | Enter NORMAL mode. In terminals that use the Kitty keyboard protocol, `Ctrl+[` requires v2.1.242 or later | 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 |
[](#remap-insert-mode-key-sequences)
Remap INSERT-mode key sequences
The [`vimInsertModeRemaps`](settings-reference.md#viminsertmoderemaps) setting maps a two-key INSERT-mode sequence to Escape, so a mapping like `jj` returns you to NORMAL mode. Requires Claude Code v2.1.208 or later. The following `~/.claude/settings.json` example turns on vim mode and maps `jj` to Escape:
```python
{
"editorMode": "vim",
"vimInsertModeRemaps": { "jj": "<Esc>" }
}
```
Each key is exactly two printable characters typed in sequence, and `"<Esc>"` is the only supported target. Entries with a different length or target are ignored. Typing the first character of a sequence inserts it normally. Pressing the second character within one second removes that pending character and switches to NORMAL mode, leaving neither character in your input. After the one-second window, or if a different key follows, both characters stay as literal text, so you can still type a word containing the sequence by pausing between the two keys. Claude Code reads this setting from your user settings file, the `--settings` flag, and [managed settings](../13-Enterprise-Admin/managed-settings.md) only. Entries in a project’s `.claude/settings.json` or `.claude/settings.local.json` are ignored, so a checked-out repository can’t remap your keystrokes.
[](#navigation-normal-mode)
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 |
| `/` | Open reverse history search, same as `Ctrl+R`. The empty search prompt shows a hint: press `Esc` then `i` then `/` to open the command menu instead |
In vim NORMAL mode, if the cursor is at the beginning or end of input and can’t move further, `j`/`k` and `↑`/`↓` navigate command history instead. `←` on an empty prompt opens [agent view](../09-Agents-Patterns/agent-view.md) from NORMAL mode as well as INSERT; before v2.1.219, `←` on an empty prompt did nothing in NORMAL mode.
[](#editing-normal-mode)
Editing (NORMAL mode)
| Command | Action |
|:----------------------|:--------------------------------------------------------------------------------------------------------------------------|
| `x` | Delete character |
| `r{char}` | Replace character under cursor with `{char}` |
| `dd` | Delete line |
| `D` | Delete to end of line |
| `dw`/`de`/`db` | Delete word/to end/back |
| `df{char}`/`dt{char}` | Delete to and including, or up to, the next occurrence of a character |
| `dj`/`dk` | Delete the current line and the line below or above |
| `dgg`/`dG` | Delete from the current line to the first or last line |
| `d0`/`c0`/`y0` | Delete, change, or yank from the cursor back to the beginning of the line. Requires Claude Code v2.1.281 or later |
| `cc` | Change line |
| `C` | Change to end of line |
| `cw`/`ce`/`cb` | Change word/to end/back |
| `s` | Substitute character: delete the character under the cursor and enter INSERT mode. Requires Claude Code v2.1.211 or later |
| `S` | Substitute line: clear the line and enter INSERT mode. Requires Claude Code v2.1.211 or later |
| `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 (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)
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)
Command history
Claude Code keeps a history of the prompts you type, and Up-arrow recall reaches prompts from past sessions of the same project:
- Input history is stored per working directory
- Running `/clear` starts a new session: recall then lists the new session’s prompts first, with earlier sessions’ prompts after them. The previous session’s conversation is preserved and can be resumed.
- Submitting the same prompt twice in a row records one history entry, so pressing Up steps to the previous distinct prompt
- When you recall a prompt that included pasted text, Claude Code sends the full pasted content again when you resubmit. If the content has since been [cleaned up](claude-directory.md#cleaned-up-automatically), Claude Code doesn’t send the literal `[Pasted text #N]` string; see [Paste large content](terminal-config.md#paste-large-content) for what happens to the prompt
- History expansion with `!` is disabled by default
[](#reverse-search-with-ctrl+r)
Reverse search with Ctrl+R
Press `Ctrl+R` to interactively search through your command history. In [fullscreen rendering](fullscreen.md), `Ctrl+R` opens a search dialog instead: type to filter, press `Up` and `Down` to move through matches, and press `Ctrl+S` to cycle the scope through this session, this project, and all projects. Press `Enter` or `Tab` to place a match in the prompt input, or `Esc` to cancel. The steps below describe the classic renderer’s inline search:
1. **Start search**: press `Ctrl+R` to activate reverse history search
2. **Type query**: enter text to search for in previous commands. The search term is highlighted in matching results
3. **Navigate matches**: press `Ctrl+R` again to cycle through older matches
4. **Search scope**: the inline search always searches prompts from all projects
5. **Accept match**:
- Press `Tab` or `Esc` to accept the current match and continue editing
- Press `Enter` to accept and execute the command immediately
6. **Cancel search**:
- Press `Ctrl+C` to cancel and restore your original input
- Press `Backspace` on empty search to cancel
The inline search scans your full prompt history, newest first, with duplicates collapsed to the newest occurrence. The fullscreen dialog searches your whole prompt history in the selected scope, newest first, with duplicates collapsed to the newest occurrence: the most recent prompts appear immediately, and matches from older prompts fill in as Claude Code loads the rest. Matching prompts display with the search term highlighted, so you can find and reuse previous inputs. Accepting a match or canceling the search takes effect immediately, even while Claude Code is still loading the history.
[](#background-bash-commands)
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)
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.
When a command reaches its timeout before it finishes, Claude Code automatically [moves it to the background](tools-reference.md#background-commands) instead of stopping it, unless the command starts with `sleep`. To change how long commands run before that happens, set the [Bash timeout environment variables](tools-reference.md#timeout-and-output-limits). **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. On macOS and Linux, when you stop a background task from [`/tasks`](commands.md) or Claude Code stops it at exit, processes that detached from the task’s shell, such as ones started under `setsid` or `timeout`, stop too
- If you background the session instead of exiting it, your background tasks keep running in the background session. See [background a running session](../09-Agents-Patterns/agent-view.md#from-inside-a-session)
- Background tasks are automatically terminated if output exceeds 5GB, with a note in stderr explaining why
- On macOS and Linux, Claude Code stops your running background tasks when the operating system reports critical memory pressure, provided the session has been idle for at least 30 minutes and no turn or subagent is running. Requires Claude Code v2.1.193 or later
- The [debug log](debug-your-config.md) says why tasks were stopped, or why a pressure event left them running
- Set [`CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP`](env-vars.md) to `1` to turn off memory-pressure stops
- Background commands owned by a [subagent](../09-Agents-Patterns/sub-agents.md) have no time limit, except that a command owned by a subagent running in the foreground ends when that subagent gives its final response; see [Background commands](tools-reference.md#background-commands) in the tools reference. Before v2.1.218, neither the memory-pressure reap nor the former 60-minute limit on subagent commands covered commands moved to the background with `Ctrl+B`
To disable all background task functionality, set the `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to `1`. See [Environment variables](env-vars.md) 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)
Shell mode with `!` prefix
Run shell commands directly without going through Claude by prefixing your input with `!`:
```python
! 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
- Doesn’t 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
- Supports live file path autocomplete as of v2.1.193 on all platforms: type a token containing a forward slash, such as `./src/` or `~/`, to see a dropdown of matching files and directories, then press `Tab` to accept. Use forward slashes on Windows too; the dropdown is triggered by `/`, not `\`
- 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
Unless your session is one of those listed under [strict sandbox mode](sandboxing.md#the-unsandboxed-retry-escape-hatch), commands you type in shell mode run outside the [sandbox](sandboxing.md) even when you’ve enabled sandboxing, because the sandbox applies to the commands Claude runs. Claude responds to the command output automatically once it lands in the transcript, so you can run `! npm test` and get an explanation of the failures without a second prompt. The response costs the same as sending a normal prompt. To restore the earlier behavior where the output is added to context without a response, set [`respondToBashCommands`](settings-reference.md#respondtobashcommands) to `false` in `settings.json`. Before v2.1.186, shell mode always added output to context without a response.
[](#queue-messages-while-claude-works)
Queue messages while Claude works
Type a message and press `Enter` while Claude is working. Claude Code queues the message instead of interrupting the turn, and lists the queued entries in the conversation until it sends them. You can queue `!` [shell commands](#shell-mode-with-prefix) and most [commands](commands.md) the same way, apart from the commands, such as `/status`, that Claude Code runs as soon as you send them. Sent and queued messages show in gray until Claude starts responding to them, so you can tell which messages Claude hasn’t started on yet. If you queue a message with a selection attached from a [connected IDE](../03-IDE-Integrations/vs-code.md#the-built-in-ide-mcp-server) or the [diff panel](#diff-panel), it keeps the selection you had when you pressed `Enter`, whatever you select afterward.
[](#when-claude-code-sends-what-you-queued)
When Claude Code sends what you queued
When a queued entry reaches Claude depends on what you queued.
- Messages: if you queue a message while Claude is running tool calls, Claude Code passes it to Claude as soon as those tool calls finish, within the same turn. When the turn ends with messages still queued, they go out without another key press, in the order you typed them
- Commands and shell commands: Claude Code holds them until the turn ends, then runs them one at a time, keeping the order you queued them in
To send what you queued without waiting, press `Ctrl+Enter`. Your queued messages go out right away, with your draft queued behind them if you had typed one. Requires Claude Code v2.1.275 or later. If you queued a `!` shell command ahead of your messages, the key interrupts the turn. Otherwise, what happens to the turn depends on what Claude is doing when you press the key:
- Running shell commands, subagents, or other work that can move to the [background](#background-bash-commands): that work moves to the background and keeps running, and Claude reads your messages in the same turn
- Only writing a response, or running something that can’t move to the background: Claude Code interrupts the turn and sends your messages next. Before v2.1.281, the key interrupted the turn in both cases
In [shell mode](#shell-mode-with-prefix), the key only queues your command. In terminals that don’t report extended keys, `Ctrl+Enter` arrives as plain `Enter` and queues the draft instead; `Ctrl+X Ctrl+S` works in any terminal. Both keys are bindings of the [`chat:sendNow` action](keybindings.md#chat-actions). Press `Esc` to interrupt the turn without submitting your draft. Claude Code keeps what you queued and sends it right away. Claude Code runs some commands as soon as you send them instead of queueing them, among them `/model`, `/effort`, and `/fast`. Each of the three changes a setting: the model, the effort level, or fast mode. Whether Claude Code applies the new setting to the turn Claude is already working on, or only from your next turn, differs by command:
- [`/model`](model-config.md#setting-your-model): once you confirm the [cache warning](prompt-caching.md#switching-models), if Claude Code shows one, Claude Code applies your change to the next request it makes in that turn
- [`/effort`](model-config.md#adjust-effort-level): once you confirm the [cache warning](prompt-caching.md#changing-effort-level), if Claude Code shows one, Claude Code applies your change to the next request it makes in that turn
- [`/fast`](fast-mode.md#toggle-fast-mode): Claude Code keeps the fast mode setting that was active when the turn started, so your speed change applies from your next turn. If your current model doesn’t support fast mode, turning it on also [switches your model](prompt-caching.md#turning-on-fast-mode), and Claude Code uses the new model from its next request in that turn
[](#take-back-what-you-queued)
Take back what you queued
Press `Up` from the first line of the input box to take back the queued messages and commands. Claude Code removes them from the queue and puts them in the input box, one per line, ahead of any text you had typed. Edit the text and press `Enter` to queue it again as one entry, or clear the input box to drop it. Claude Code takes back queued shell commands only when the input box is empty and you have nothing else queued, and it switches the input box to shell mode when it does. Otherwise it leaves them in the queue, listed with their `!` prefix, and runs them after the turn ends.
[](#prompt-suggestions)
Prompt suggestions
When you first open a session, Claude Code shows a grayed-out example command in the prompt input to help you get started. It picks this from your project’s git history, so the example reflects files you’ve been working on recently. After Claude responds, Claude Code can suggest your next prompt 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
Claude Code generates each of these next-prompt suggestions with a short background request to the same model your session is using. The request counts toward your plan’s usage limits or your API costs. Because it reuses the conversation’s prompt cache, it is mostly cache reads plus a few output tokens, so the added cost is small.
[](#when-claude-code-skips-suggestions)
When Claude Code skips suggestions
In interactive mode, Claude Code leaves prompt suggestions off by default and hides the **Prompt suggestions** toggle in `/config` in a [session that doesn’t fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), such as one on a third-party provider or through a Claude apps gateway, and in a [first session after an install or upgrade](env-vars.md#first-session-after-an-install-or-upgrade) whose flags haven’t arrived yet. Claude Code also skips individual suggestions in several situations, including:
- The prompt cache is cold, to avoid unnecessary cost
- After the first turn of a conversation, in some sessions
- The previous response ended in an error
- While you’re in plan mode
- Your account is close to or at its usage limit. To keep suggestions on until you reach the limit, set [`CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION`](env-vars.md) to `true`. Before v2.1.238, Claude Code skipped them near the limit even with the variable set to `true`
- In an [agent team](../09-Agents-Patterns/agent-teams.md), in teammates’ sessions by default. The lead’s session shows suggestions
In print mode, Claude Code doesn’t generate suggestions by default. Pass [`--prompt-suggestions`](cli-reference.md#cli-flags) with `-p "<prompt>" --output-format stream-json --verbose` to have Claude Code emit a `prompt_suggestion` message after each turn that generates one. The generator skips very short conversations and cold prompt caches here too, so a single short `-p` query can emit none.
[](#turn-prompt-suggestions-off)
Turn prompt suggestions off
To disable prompt suggestions entirely, use any of the following:
- Turn off **Prompt suggestions** in `/config`
- Set [`promptSuggestionEnabled`](settings-reference.md#promptsuggestionenabled) to `false` in your settings file
- Set the [`CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION`](env-vars.md) environment variable to `false`, which takes precedence over the setting:
``` shiki
export CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false
```
To turn prompt suggestions off across an organization, set `promptSuggestionEnabled` to `false` in [managed settings](../13-Enterprise-Admin/managed-settings.md). Also set `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` to `false` under the managed [`env`](settings-reference.md#env) key so that users can’t re-enable them with their own environment variable.
[](#emoji-shortcodes)
Emoji shortcodes
Type a `:` followed by an emoji shortcode in the prompt input to insert the emoji. Requires Claude Code v2.1.217 or later.
- Type a complete shortcode such as `:heart:` and Claude Code replaces it with ❤️ as soon as you type the closing `:`
- Type `:` plus at least two characters of a name, such as `:hea`, to open a suggestion popup, then press `Tab` or `Enter` to insert the highlighted emoji
The shortcode must start the input or follow a space, so a `:` inside a word or URL doesn’t open suggestions. To turn the feature off, set [`emojiCompletionEnabled`](settings-reference.md#emojicompletionenabled) to `false` in `settings.json`. This disables both the suggestion popup and the inline replacement.
[](#check-spelling-as-you-type)
Check spelling as you type
Claude Code can underline misspelled words in the prompt input while you type. It checks only the text in the input box, never Claude’s replies or your files. It also checks nothing while the input box is in [shell mode](#shell-mode-with-prefix), `Ctrl+R` history search, or [voice dictation](voice-dictation.md). Spell checking is off by default, and Claude Code checks nothing in [screen reader mode](accessibility.md). Requires Claude Code v2.1.235 or later.
[](#prerequisites)
Prerequisites
- Install [aspell](https://github.com/GNUAspell/aspell), [hunspell](https://github.com/hunspell/hunspell), or [ispell](https://en.wikipedia.org/wiki/Ispell) and make sure it’s on your `PATH`. Claude Code runs the first of the three it finds, in that order, on every platform, including a `.cmd` shim a package manager installs on Windows.
- To check that the program is on your `PATH`, run `aspell --version`, `hunspell --version`, or `ispell -v` in your terminal. A “command not found” error means it isn’t on your `PATH` yet.
[](#turn-spell-checking-on-or-off)
Turn spell checking on or off
Claude Code reads the [`spellcheck`](settings-reference.md#spellcheck) setting from three places, and ignores it in a project’s `.claude/settings.json` and `.claude/settings.local.json`. Turn it on from whichever one you use:
- User settings
- Command line
- Managed settings
Add `spellcheck` to `~/.claude/settings.json`. It applies in every project you open, like the rest of your [user settings](settings.md#where-settings-live):
```python
{
"spellcheck": { "enabled": true }
}
```
Save `spellcheck` in a JSON file, such as `spellcheck.json`:
```python
{
"spellcheck": { "enabled": true }
}
```
Then pass the file to `--settings`. It applies to that session only:
```python
claude --settings spellcheck.json
```
Add `spellcheck` to one of your organization’s [managed settings sources](permissions.md#managed-settings). It applies to every user who receives those settings, and they can’t turn it off:
```python
{
"spellcheck": { "enabled": true }
}
```
To check that spell checking is on, type a misspelled word and a space. Claude Code underlines the word. If it doesn’t, see [When Claude Code underlines nothing](#when-claude-code-underlines-nothing). To turn spell checking off again, set `enabled` to `false` in the same place, or remove `spellcheck`. To choose which of the three programs Claude Code runs, which dictionary it uses, or the underline color, add any of these fields next to `enabled`, in the same place:
- `checker`: `aspell`, `hunspell`, or `ispell`. Claude Code doesn’t fall back from a checker you name, and treats any other value as `auto`.
- `language`: a dictionary name in your checker’s form, such as `en_GB`. Claude Code ignores any value that isn’t a plain dictionary name, such as a path or a name with spaces, and the checker uses its default dictionary.
- `color`: a color name such as `yellow`, or a `#rrggbb`, `#rgb`, `rgb(r,g,b)`, `ansi256(n)`, or `ansi:<name>` value. Claude Code uses your theme’s error color by default and for any value it doesn’t recognize.
For example, this `spellcheck` setting runs hunspell with its `en_GB` dictionary and underlines words in yellow. It works the same in `~/.claude/settings.json`, in the file you pass to `--settings`, and in managed settings:
```python
{
"spellcheck": {
"enabled": true,
"checker": "hunspell",
"language": "en_GB",
"color": "yellow"
}
}
```
If more than one of the three places has a `spellcheck` setting, Claude Code uses only one of them: managed settings first, then `--settings`, then user settings. It doesn’t combine fields from two places. For example, when `--settings` sets `spellcheck`, a `language` in your user settings has no effect.
[](#what-claude-code-underlines)
What Claude Code underlines
Shortly after you pause typing, Claude Code underlines the words the dictionary doesn’t know. It leaves the word you’re still typing alone until you move past it, and it never changes your text. It also skips text that looks like code:
- Commands such as `/help`, `@` mentions, URLs, file paths, and flags such as `--verbose`
- Words with digits, underscores, or a capital letter after the first, and text in backticks
Claude Code also skips Chinese, Japanese, Korean, Thai, Lao, Khmer, and Myanmar text. Claude Code has no word list of its own: a word is misspelled when your checker says so. To stop Claude Code from underlining a word, add the word to your checker’s personal dictionary, following the checker’s own documentation. Claude Code picks up the new word after you restart it.
[](#when-claude-code-underlines-nothing)
When Claude Code underlines nothing
Claude Code underlines nothing when it can’t keep a checker running:
- No checker is installed, or the one you named in `checker` is missing
- The checker fails twice in a row, at startup or later in the session. Claude Code restarts it after the first failure and stops checking after the second, until you restart Claude Code
- The checker takes more than 15 seconds to answer, three times. Each time, Claude Code leaves the words it was waiting on unmarked; after the third, it stops checking until you restart Claude Code
To find out which of these happened, start `claude --debug` with spell checking on and type a word. Then look for the `[spellcheck]` lines in the debug log at `~/.claude/debug/<session-id>.txt`. One line names the program Claude Code started, or lists the ones it looked for and didn’t find. Later lines say why it stopped. A missing-dictionary error there means the checker has no dictionary for your `language` value, or no default one when `language` is unset. Install one, or set `language` to a dictionary you have.
[](#invisible-characters-in-prompts)
Invisible characters in prompts
Pasted text can carry Unicode characters that a terminal draws as nothing at all, such as tag characters, bidirectional controls, and zero-width spaces, so a prompt can contain text you never see. To keep copied text from carrying instructions your terminal doesn’t draw, Claude Code removes those characters when you press Enter, before sending anything. It cleans both the prompt and the contents of any collapsed [pasted-text reference](terminal-config.md#paste-large-content) the prompt includes. Claude Code keeps the joiners that Persian and Indic scripts write and the selectors inside emoji sequences. If Claude Code removed anything, that Enter sends nothing. The cleaned prompt goes back into the input box with a notice such as `Removed 3 invisible characters · review and press Enter to send`, and pressing Enter again sends the text as shown. When you pass a prompt on the command line, as in `claude "fix the login bug"`, or pipe one into an interactive session, Claude Code doesn’t wait for a second Enter. It removes the characters, shows a notice, and sends the cleaned prompt. If the cleaned prompt would begin with `/`, Claude Code puts it in the input box for you to review and send instead.
[](#review-changes-with-/diff)
Review changes with /diff
Run `/diff` to look over the changes in your working tree without leaving Claude Code. You see the edits Claude has made so far alongside anything else you haven’t committed. In the changes `/diff` reads from git, a submodule appears as a single entry, and only when the commit it points to changes; edits to files inside the submodule don’t appear there. In [fullscreen rendering](fullscreen.md), `/diff` opens the [diff panel](#diff-panel) beside the conversation, which stays open and updates while you keep working. In the classic renderer, `/diff` opens the [diff viewer](#diff-viewer) in place of the prompt, and you close it when you’re done reading.
[](#diff-panel)
Diff panel
The diff panel lists the changed files with their added and removed line counts, and shows each file’s diff under the list. Claude Code refreshes it each time Claude edits a file or runs a shell command. To close it, run `/diff` again or click the `✕` in its header. To use the panel you need:
- [Fullscreen rendering](fullscreen.md)
- A git repository
- A terminal at least 110 columns wide
- Claude Code v2.1.260 or later
When the panel can’t open, `/diff` opens the diff viewer instead or tells you why. The panel also opens on its own once Claude starts editing files, if your terminal is at least 144 columns wide. After you’ve opened it yourself with `/diff`, later sessions open it as soon as Claude edits a file in any terminal wide enough to fit it. Close the panel and it stays closed, in this session and later ones, until you run `/diff` again. While the panel is open, you can:
- **Jump to a file**: click its row in the list. Scroll the panel with the mouse wheel. When the file list itself is too long to fit, scroll it with `Alt+Up` and `Alt+Down`, or `Ctrl+Up` and `Ctrl+Down`.
- **Ask Claude about specific lines**: select them in the panel with the mouse. Claude Code attaches the selection to your next prompt and shows a line count in the input until you send it.
- To send the prompt without the selection, move the cursor to just after the line-count indicator and press `Backspace` to delete it. Requires Claude Code v2.1.271 or later.
- **Show the files the panel leaves out**: the list skips test files and generated files, and collapses changes from before this session into one line at the bottom. Click either count line to expand it.
- **Change what the panel compares against**: press `Ctrl+X B` to cycle from this session’s changes, to your uncommitted changes as one list, to everything since your branch split from the default branch. Claude Code remembers the choice for each project.
To bind keys to these actions, see [Diff panel actions](keybindings.md#diff-panel-actions).
[](#diff-viewer)
Diff viewer
The diff viewer takes the place of the prompt until you close it. Its **Current** view shows your uncommitted changes from git, or, when there are none, what your branch adds on top of the default branch. The viewer also has a turn view for each prompt after which Claude edited files, showing just those edits. Claude Code builds the turn views from Claude’s file edits rather than from git, so a change Claude makes through a shell command appears only under Current. Use these keys in the viewer:
- **Left and Right**: move between Current and the turn views.
- **Up and Down**: select a file.
- **Enter**: open the selected file’s diff. Scroll it with Up and Down, or PageUp and PageDown.
- **Esc**: return from a file’s diff to the list, or close the viewer from the list.
To rebind these keys, see [Diff actions](keybindings.md#diff-actions).
[](#side-questions-with-/btw)
Side questions with /btw
Use `/btw` to ask a question about your current work without adding to the conversation history.
```python
/btw what was the name of that config file again?
```
Claude answers a side question from what’s already in the conversation: your messages, its replies, and the tool results it has gathered. You can ask about code Claude has already read, decisions it made earlier, or anything else from the session. A later side question also sees your earlier side questions: Claude Code replays the newest 20 exchanges with each ask, until you clear them. The question and answer never enter the conversation history. In the terminal, they appear in a dismissible overlay. The terminal keeps the thread in memory: press `x` to clear the earlier exchanges, and it’s gone when you exit Claude Code. In the [VS Code extension](../03-IDE-Integrations/vs-code.md#use-the-prompt-box)’s chat panel, `/btw` opens a panel rather than the overlay this section describes, and you ask follow-up questions right in the panel. The panel’s thread survives window reloads, on the retention schedule that page describes. You need the extension at v2.1.227 or later. Earlier extension versions don’t offer `/btw`.
- **Available while Claude is working**: you can run `/btw` even while Claude is processing a response. The side question runs independently and doesn’t interrupt the main turn. It sees everything in the conversation so far, except the reply Claude is still writing.
- **No tool access**: side questions answer only from what is already in context. Claude can’t read files, run commands, or search when answering a side question. If Claude writes out tool calls as text anyway, the answer ends with a note that nothing was executed.
- **Single response**: there are no follow-up turns in the overlay. To continue the thread, ask another `/btw` question. To continue with full tool access in a local session, press `f` to fork this question and answer into a [background subagent](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation).
- **Low cost**: while the conversation’s [prompt cache](prompt-caching.md) is warm, a side question costs little beyond the answer itself.
Your five newest earlier side questions appear as a dimmed list above the current answer, with a count of any older ones. They stay out of the conversation history. To return to the overlay after dismissing it, run `/btw` with no question. The overlay reopens on your most recent exchange. Before v2.1.212, `/btw` without a question printed a usage message instead. Once the answer appears, the overlay accepts these keys.
| Key | Action |
|:-----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Space`, `Enter`, `Escape` | Dismiss the answer and return to the prompt |
| `Up` / `Down` | Scroll the answer |
| `Shift+Left` / `Shift+Right` | Step between this answer and your earlier `/btw` answers. `Shift+Left` moves to older answers and `Shift+Right` returns toward the current one. `[` and `]` do the same, for terminals that don’t report `Shift` with arrow keys. `Tab` / `Shift+Tab` cycle through the same answers. Requires Claude Code v2.1.257 or later. Between v2.1.187 and v2.1.256, the keys were plain `Left` / `Right` |
| `c` | Copy the answer to your clipboard as raw Markdown. Use this instead of mouse selection, which captures the hard-wrapped terminal rendering rather than the source text |
| `f` | Start a [forked subagent](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) that inherits the parent conversation plus this question and answer, so it can continue with full tool access. You stay in the current session and find the fork in the [panel below your prompt](../09-Agents-Patterns/sub-agents.md#observe-and-steer-running-forks). Available in local sessions only |
| `x` | Clear the list of earlier `/btw` exchanges shown above the current answer |
In an attached [background session](../09-Agents-Patterns/agent-view.md#attach-to-a-session), `Left` detaches and returns you to agent view, even while the answer is still arriving. The side question keeps running while you’re away. The next time you attach to the session, the overlay reopens with the side question, or with its answer. Before v2.1.257, `Left` didn’t detach there. `/btw` sees your full conversation but has no tools. A [subagent](../09-Agents-Patterns/sub-agents.md) has tools and starts from the prompt it receives, or, for a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), from a copy of this conversation. Use `/btw` to ask about what Claude already knows from this session; use a subagent to go find out something new.
[](#task-list)
Task list
The task list is Claude’s to-do checklist: items Claude created to plan multi-step work, with indicators showing what’s pending, in progress, or complete. It’s separate from the background-task view. To see running shells and subagents, use [`/tasks`](commands.md) instead. The list fills only in sessions that have the task-tracking tools, which Claude Code provides by default on [Claude 3.x models, Opus 4 through 4.7, Sonnet 4 through 4.6, and Haiku 4.5](tools-reference.md#task-tool-availability). On any other model, including a model ID Claude Code doesn’t recognize, the list stays empty unless you opt in with `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` or one of the other ways under [Task tool availability](tools-reference.md#task-tool-availability). When the session has the tools, the task list works as follows:
- Press `Ctrl+T` to toggle the task list view. The display shows up to five tasks at a time. When Claude hasn’t created any checklist items yet, the toggle has no visible effect because there’s nothing to display
- If you leave the list expanded, Claude Code restores the expanded view the next time you launch into a session that still has tasks, such as with `--resume` or `--continue`. When the task list is empty, Claude Code starts it collapsed
- 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)
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. Claude Code caps both automatic recaps and `/recap` output at 400 characters. To turn automatic recaps off, open `/config` and turn off **Session recap**. Session recap is on by default for every plan and provider. The recap is always skipped in non-interactive mode.
[](#wait-for-a-usage-limit-to-reset)
Wait for a usage limit to reset
When a claude.ai [usage limit](errors.md#youve-hit-your-session-limit) stops Claude mid-task, Claude Code waits in the open session and continues the task on its own after the limit resets. Automatic continue is on by default in interactive sessions signed in with a claude.ai subscription. Requires Claude Code v2.1.234 or later. While Claude Code waits, a line at the bottom of the session shows when it will continue:
```python
Usage limit reached · continuing automatically at 3:45pm · esc to cancel
```
Keep the session open. What happens next depends on how the wait ends:
- **At the reset**: the line reads `continuing shortly`, then `Usage limit reset · continuing automatically`, and Claude Code sends Claude a fixed prompt to pick the task up where it stopped. It doesn’t resend your last message.
- **After your computer slept**: if it slept for more than about 30 minutes and the limit reset while it slept, the line reads `Your usage limit has reset · press enter to continue`. Press `Enter` to continue. After a shorter sleep, Claude Code continues on its own.
- **Early**: when you finish adding [usage credits](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription) with `/usage-credits`, sign back in after `/upgrade`, or switch models with `/model` during the wait, Claude Code checks whether usage is available again and continues right away if it is. It doesn’t check after an upgrade or purchase you make in a browser on your own. Under [`opusplan`](model-config.md#opusplan-model-setting) and other model settings that run plan mode on a different model, Claude Code waits for the reset instead.
The continued task runs like any other turn. Claude Code still asks for [permissions](permissions.md) as usual, so the task can stop on a prompt while you’re away. If it hits the limit again, Claude Code re-arms the wait on its own at most twice in a row, then stops and shows `Automatic continue stopped after repeated usage-limit hits · /rate-limit-options to try again`.
[](#cancel-the-wait)
Cancel the wait
Press `Esc` at an empty prompt, or `Ctrl+C`, while the line shows, or run [`/rate-limit-options`](commands.md#all-commands) and pick **Don’t continue automatically**. Claude Code confirms with a line that starts `Automatic continue cancelled`. After a cancel, nothing continues until you send a prompt or pick the row that starts **Wait here, then continue automatically** from `/rate-limit-options` again. Claude Code doesn’t start a wait on its own again for that reset window; the next reset window starts fresh. The wait also ends without continuing the task in these cases:
- **You send a prompt**: Claude Code runs your prompt instead of waiting.
- **You exit Claude Code**: the wait doesn’t restart when you resume the session.
- **The conversation changes hands**: you switch accounts with `/login`, clear or rewind the conversation, `/resume` another session, pull one with `/teleport`, relaunch with `/tui`, or hand the session to Claude Desktop, a background session, or the cloud.
- **The setting turns off, or the reset moves past 24 hours**: this ends only a wait Claude Code started on its own. A wait you picked from `/rate-limit-options` keeps counting down.
- **The continuation is blocked**: a [`UserPromptSubmit` hook](../07-Hooks/hooks.md#userpromptsubmit) that blocks the continuation prompt, or a failure before it reaches the model, ends the wait. Claude Code tells you the continuation didn’t run. Send a prompt to continue.
[](#start-a-wait-yourself)
Start a wait yourself
Claude Code doesn’t start the wait on its own in these cases:
- **Remote Control and agent team teammate sessions**: a person at that terminal can still start one.
- **A reset more than 24 hours away**: a weekly limit can reset days out.
- **An Opus or Sonnet limit while you run a model outside that family**: your next turn may not hit that limit. [`opusplan`](model-config.md#opusplan-model-setting) and other model settings that run plan mode on the limited family don’t get this exception.
In those cases, and whenever automatic continue is off, Claude Code opens the usage-limit options menu once per reset window when you hit a limit at your own terminal. Pick the row that starts **Wait here, then continue automatically** to start the wait. In a [Remote Control](remote-control.md) or [agent team](../09-Agents-Patterns/agent-teams.md) teammate session, run `/rate-limit-options` yourself to open the menu. Claude Code doesn’t offer the wait at all in these cases:
- **Background sessions and `-p` runs**: the menu row isn’t available.
- **API keys, cloud providers, and usage-based billing**: usage there is metered per request, so there is no reset to wait for.
- **An [LLM gateway](../13-Enterprise-Admin/llm-gateway.md#subscriptions-and-gateways) without a saved claude.ai login**: Claude Code offers the wait only while a saved claude.ai login is the active credential.
[](#turn-automatic-continue-off)
Turn automatic continue off
In `/config`, turn off **Continue automatically at usage limit**, or set [`autoContinueAtUsageLimit`](settings-reference.md#autocontinueatusagelimit) to `false` in your user settings. `/config autoContinueAtUsageLimit=false` also works, including with `-p`, but the `key=value` form can’t turn it back on, because the setting grants unattended execution. Which settings files Claude Code reads for this key is in the [settings reference](settings-reference.md#autocontinueatusagelimit).
[](#pr-review-status)
PR review status
When working on a branch with an open pull request, Claude Code displays a clickable PR link in the footer, such as “PR \#446”. The link has a colored underline indicating the review state:
- Green: approved
- Yellow: pending review
- Red: changes requested
- Gray: draft
The badge disappears once the pull request merges or closes. `Cmd+click` (macOS) or `Ctrl+click` (Windows/Linux) the link to open the pull request in your browser. The status refreshes as soon as a `git push`, or a `gh pr` command that changes the pull request, such as `gh pr create` or `gh pr merge`, succeeds in the session. Claude Code renders the badge as a hyperlink even when it can’t detect hyperlink support in your terminal, which commonly happens over SSH or in tmux. Set [`FORCE_HYPERLINK=0`](env-vars.md) to render the badge as plain text. When you set [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](env-vars.md), Claude Code doesn’t check pull request or merge request status.
PR status for GitHub repositories needs a GitHub token. Claude Code finds one based on the remote’s host:
- **github.com**: `GH_TOKEN` or `GITHUB_TOKEN`, or the token saved by `gh auth login`. Without one, the footer shows `install gh for PR status` when the `gh` CLI isn’t installed, or `gh auth login for PR status` when it is
- **A GitHub Enterprise host set as `GH_HOST`**: `GH_ENTERPRISE_TOKEN` or `GITHUB_ENTERPRISE_TOKEN`, or the token saved by `gh auth login --hostname <host>`. Without one, the footer shows the same hints
- **Any other GitHub host**: the token saved by `gh auth login --hostname <host>`. Without one, Claude Code shows no badge and no hint
[](#gitlab-merge-requests)
GitLab merge requests
When you work on a branch with an open GitLab merge request, Claude Code shows a clickable `MR !N` badge in the footer slot that otherwise holds the GitHub PR link. `!N` is GitLab’s own reference syntax for merge request number N. The colored underline shows the merge request’s state:
- Green: GitLab reports the merge request as mergeable
- Yellow: any other open state
- Gray: draft
The badge disappears once the merge request merges or closes. It refreshes as soon as a `git push`, or a `glab mr` command that changes the merge request, such as `glab mr create` or `glab mr merge`, succeeds in the session. To get the badge, you need:
- Claude Code v2.1.234 or later
- A repository remote that points at your GitLab host, either gitlab.com or a self-managed instance
- The [`glab` CLI](https://gitlab.com/gitlab-org/cli) on your `PATH`, authenticated with `glab auth login`
Claude Code ignores `glab`’s token environment variables, such as `GITLAB_TOKEN`, when it checks status, so you get no badge from an exported token alone. Claude Code also looks for `glab` and for its login once per session, so restart Claude Code after you install `glab` or run `glab auth login`.
[](#issue-reference-links)
Issue reference links
When Claude mentions an issue as `owner/repo#123`, you can click the reference to open it, as long as your terminal supports hyperlinks. If Claude Code doesn’t detect hyperlink support in your terminal, set [`FORCE_HYPERLINK`](env-vars.md) to `1` to turn the links on, or to `0` to keep references as plain text. You get a link only for the two-part `owner/repo#123` form. These stay plain text:
- A bare `#123`
- A nested GitLab path such as `group/subgroup/project#123`
- Any reference inside a code span or code block
Claude Code builds the link for the host of the repository it identifies from your git remote, not for the repository the reference names:
| Your repository’s host | Where `owner/repo#123` links |
|:-------------------------------------------------------------------|:---------------------------------------------|
| github.com, a GitHub Enterprise host, or any host not listed below | `https://<host>/owner/repo/issues/123` |
| gitlab.com | `https://gitlab.com/owner/repo/-/issues/123` |
| bitbucket.org, codeberg.org, or gitea.com | No link; the reference stays plain text |
[](#see-also)
See also
- [Skills](../08-Plugins-Skills/skills.md) - Custom prompts and workflows
- [Checkpointing](checkpointing.md) - Rewind Claude’s edits and restore previous states
- [CLI reference](cli-reference.md) - Command-line flags and options
- [Settings](settings.md) - Configuration options
- [Memory management](memory.md) - Managing CLAUDE.md files
---
## Customize keyboard shortcuts - Claude Code Docs
Source: https://code.claude.com/docs/en/keybindings
Path: 02-Claude-Code-CLI/keybindings.md
## On this page
- [Configuration file](#configuration-file)
- [Contexts](#contexts)
- [Available actions](#available-actions)
- [App actions](#app-actions)
- [History actions](#history-actions)
- [Chat actions](#chat-actions)
- [Autocomplete actions](#autocomplete-actions)
- [Confirmation actions](#confirmation-actions)
- [Permission actions](#permission-actions)
- [Transcript actions](#transcript-actions)
- [History search actions](#history-search-actions)
- [Task actions](#task-actions)
- [Theme actions](#theme-actions)
- [Help actions](#help-actions)
- [Tabs actions](#tabs-actions)
- [Attachments actions](#attachments-actions)
- [Footer actions](#footer-actions)
- [Message selector actions](#message-selector-actions)
- [Diff actions](#diff-actions)
- [Diff panel actions](#diff-panel-actions)
- [Model picker actions](#model-picker-actions)
- [Effort slider actions](#effort-slider-actions)
- [Select actions](#select-actions)
- [Plugin actions](#plugin-actions)
- [Settings actions](#settings-actions)
- [Agents actions](#agents-actions)
- [Voice actions](#voice-actions)
- [Scroll actions](#scroll-actions)
- [Keystroke syntax](#keystroke-syntax)
- [Modifiers](#modifiers)
- [Uppercase letters](#uppercase-letters)
- [Non-US keyboard layouts](#non-us-keyboard-layouts)
- [Chords](#chords)
- [Special keys](#special-keys)
- [Unbind default shortcuts](#unbind-default-shortcuts)
- [Reserved shortcuts](#reserved-shortcuts)
- [Terminal conflicts](#terminal-conflicts)
- [Text fields](#text-fields)
- [Vim mode interaction](#vim-mode-interaction)
- [Validation](#validation)
Interface
# Customize keyboard shortcuts
Copy pageCopy page
Customize keyboard shortcuts in Claude Code with a keybindings configuration file.
Copy pageCopy page
Claude Code supports customizable keyboard shortcuts. Run `/keybindings` to create or open your configuration file at `~/.claude/keybindings.json`.
[](#configuration-file)
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+S`:
```python
{
"$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+s": null
}
}
]
}
```
[](#contexts)
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` | A task is running in the foreground |
| `ThemePicker` | Theme picker dialog |
| `Attachments` | Image attachment navigation in select dialogs |
| `Footer` | Footer indicator navigation (tasks, teams, diff, artifacts) |
| `MessageSelector` | Rewind and summarize dialog message selection |
| `DiffDialog` | Diff viewer navigation |
| `DiffPanel` | The [diff panel](interactive-mode.md#diff-panel) is open |
| `ModelPicker` | Model picker effort level |
| `EffortSlider` | Effort slider opened by `/effort` |
| `Select` | Generic select/list components |
| `Plugin` | Plugin dialog (browse, discover, manage) |
| `Agents` | [Agent view](../09-Agents-Patterns/agent-view.md) (`claude agents`) |
| `Scroll` | Conversation scrolling and text selection in fullscreen mode |
Before v2.1.205, a `Doctor` context and a `doctor:fix` action existed for the `/doctor` diagnostics screen.
[](#available-actions)
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)
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. Press twice within 800ms to confirm |
| `app:redraw` | (unbound) | Force terminal redraw |
| `app:toggleTodos` | Ctrl+T | Toggle visibility of Claude’s to-do checklist. This is not the [`/tasks`](commands.md) background-task view |
| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |
[](#history-actions)
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)
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 and conversation |
| `chat:clearScreen` | Cmd+K | Same as `chat:clearInput`. See [Clear the conversation](fullscreen.md#clear-the-conversation) for how Cmd+K behaves on iTerm2 and Terminal.app |
| `chat:killAgents` | Ctrl+X Ctrl+K | Stop all running [background subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) in this session and turn off [artifact auto-replies](artifacts.md#let-claude-reply-to-comments-on-its-own) for the rest of it |
| `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:queueSubmit` | Ctrl+X Enter | Submit the message, marked to wait its turn: while Claude is working, Claude Code [queues it](interactive-mode.md#queue-messages-while-claude-works) and never interrupts the turn. Unlike `chat:submit`, it submits the draft even while an autocomplete suggestion is highlighted. Requires v2.1.247 or later |
| `chat:sendNow` | Ctrl+Enter, Ctrl+X Ctrl+S | Send your [queued messages](interactive-mode.md#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](interactive-mode.md#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. When nothing is running, the key submits the draft, and in [shell mode](interactive-mode.md#shell-mode-with-prefix) it only queues the command. Terminals that don’t report extended keys deliver `Ctrl+Enter` as plain `Enter`, so `Ctrl+X Ctrl+S` is the binding that works in any terminal. Requires v2.1.275 or later |
| `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. The [agent view dispatch input](../09-Agents-Patterns/agent-view.md#keyboard-shortcuts) follows this action’s single-keystroke bindings too |
| `chat:stash` | Ctrl+S | Stash current prompt |
| `chat:imagePaste` | Ctrl+V (Alt+V on Windows and WSL) | Paste image from clipboard. On WSL, both shortcuts are bound by default |
\*On Windows without VT mode (Node \<24.2.0/\<22.17.0, Bun \<1.2.23), defaults to Meta+M.
[](#autocomplete-actions)
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)
Confirmation actions
Actions available in the `Confirmation` context:
| Action | Default | Description |
|:------------------------|:------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `confirm:yes` | Enter | Confirm action |
| `confirm:no` | 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. On a file permission prompt, closes an open [comment field](permissions.md#add-a-comment-when-you-answer-a-permission-prompt); with no field open, selects the option that allows the action for the rest of the session, when the prompt offers that option |
\*On Windows without VT mode (Node \<24.2.0/\<22.17.0, Bun \<1.2.23), defaults to Meta+M. Before v2.1.257, a `confirm:toggleExplanation` action, bound to `Ctrl+E` by default, showed a model-generated explanation of the command on Bash and PowerShell permission prompts. Dialogs use `confirm:yes` and `confirm:no` to accept and cancel even when they don’t ask a yes-or-no question. If you bind a bare letter such as `y` or `n` in this context, the letter also acts on dialogs that never show it as a key. A dialog that shows `y` and `n` as its keys reads those letters itself and needs no binding. In most dialogs, pressing `Ctrl+C` or `Ctrl+D` twice closes the dialog instead of exiting Claude Code. The hint after the first press says whether the second press closes the dialog or exits. Both keys are [reserved](#reserved-shortcuts) and can’t be rebound. This example binds `y` to `confirm:yes` and `n` to `confirm:no`:
```python
{
"bindings": [
{
"context": "Confirmation",
"bindings": {
"y": "confirm:yes",
"n": "confirm:no"
}
}
]
}
```
With these bindings, `y` and `n` still type as letters while a [text field](#text-fields) has focus. Before v2.1.280, `y` was also bound to `confirm:yes` and `n` to `confirm:no` by default. If you created your `keybindings.json` with `/keybindings` before v2.1.280, the file lists both bindings and they stay in effect until you delete those two lines.
[](#permission-actions)
Permission actions
Actions available in the `Confirmation` context for permission dialogs:
| Action | Default | Description |
|:-------------------------|:----------|:--------------------------------------------------------------------------------------------------------------------|
| `permission:toggleDebug` | (unbound) | Toggle permission debug info. The previous default of Ctrl+D was removed in v2.1.146 because it shadowed `app:exit` |
[](#transcript-actions)
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 |
`transcript:toggleShowAll` applies in the classic renderer only; in [fullscreen rendering](fullscreen.md), the transcript viewer doesn’t offer a show-all toggle.
[](#history-search-actions)
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 |
The `historySearch:next`, `historySearch:accept`, `historySearch:cancel`, and `historySearch:execute` defaults apply to the inline history search in the classic renderer, which always searches prompts from all projects. `historySearch:cycleScope` takes effect only in [fullscreen rendering](fullscreen.md), where `Ctrl+R` opens a search dialog instead and `Ctrl+S` cycles its scope. The dialog’s other keys are fixed and can’t be rebound: `Enter` or `Tab` places the highlighted match in the prompt input and `Esc` cancels.
[](#task-actions)
Task actions
Actions available in the `Task` context:
| Action | Default | Description |
|:------------------|:----------------------|:---------------------------------------------------------------------------------|
| `task:background` | Ctrl+B, Ctrl+X Ctrl+B | Background current task. The Ctrl+X Ctrl+B chord avoids the tmux prefix conflict |
[](#theme-actions)
Theme actions
Actions available in the `ThemePicker` context:
| Action | Default | Description |
|:---------------------------------|:--------|:---------------------------|
| `theme:toggleSyntaxHighlighting` | Ctrl+T | Toggle syntax highlighting |
[](#help-actions)
Help actions
Actions available in the `Help` context:
| Action | Default | Description |
|:---------------|:--------|:----------------|
| `help:dismiss` | Escape | Close help menu |
[](#tabs-actions)
Tabs actions
Actions available in the `Tabs` context:
| Action | Default | Description |
|:----------------|:----------------|:-------------|
| `tabs:next` | Tab, Right | Next tab |
| `tabs:previous` | Shift+Tab, Left | Previous tab |
In a tabbed dialog, `tabs:next` and `tabs:previous` switch tabs while the tab row has focus. In some dialogs, such as `/help` and `/sandbox`, the tab-switching keys also work from inside the tab’s content. `Up` and `Down` move focus between the tab row and the tab’s content, and a list in the content responds to keys only while it has focus.
[](#attachments-actions)
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)
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 |
| `footer:dismiss` | (unbound) | Binding a key to this action has no effect, and a `keybindings.json` that names it remains valid. Before v2.1.281, Backspace and Delete were bound to it and dismissed the selected artifact link from the footer. |
While a footer item is selected, such as a row in the agent panel below the prompt, `Enter` opens it even when you rebind `Enter` in the `Chat` context to `chat:queueSubmit` or `chat:newline`. `Chat` bindings on keys the `Footer` context doesn’t bind, such as `Shift+Tab` for `chat:cycleMode`, keep working while an item is selected.
[](#message-selector-actions)
Message selector actions
In the message list of the [rewind menu](checkpointing.md), you move through messages and pick one with the [Select actions](#select-actions) and their default keys. Your `Select` bindings for those actions apply there too. The `MessageSelector` context has no actions or default bindings of its own. Use it to change a key for this list alone, by binding a Select action such as `select:accept` in a `MessageSelector` block. This example binds `o` to pick the highlighted message in the rewind menu, without changing any other list:
```python
{
"bindings": [
{
"context": "MessageSelector",
"bindings": {
"o": "select:accept"
}
}
]
}
```
Before v2.1.283, this list ignored `Select` bindings and had its own actions: `messageSelector:up`, `messageSelector:down`, `messageSelector:top`, `messageSelector:bottom`, and `messageSelector:select`. If your `keybindings.json` binds one of those names, the binding keeps working in this list as the Select action that does the same thing. `Home` and `End` jump to either end of the list; before v2.1.283, keys such as `Shift+K` and `Shift+J` did that by default.
[](#diff-actions)
Diff actions
Actions available in the `DiffDialog` context:
| Action | Default | Description |
|:----------------------|:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------|
| `diff:dismiss` | Escape | Close diff viewer; from the detail view, returns to the file list instead |
| `diff:previousSource` | Left | Previous diff source |
| `diff:nextSource` | Right | Next diff source |
| `diff:previousFile` | Up, K | Previous file in the file list; scroll up one line in the detail view |
| `diff:nextFile` | Down, J | Next file in the file list; scroll down one line in the detail view |
| `diff:back` | (unbound) | Go back in diff viewer. Escape performs the back action via `diff:dismiss`. The previous default of Left in the detail view was removed in v2.1.203 |
The file list also responds to the [Select actions](#select-actions), through their default keys and your `Select` bindings. `select:previous` and `select:next` move to the previous and next file, and `Enter` opens the selected file’s diff through `select:accept`. To change one of those keys for the file list alone, bind the Select action in a `DiffDialog` block. Before v2.1.283, the file list ignored `Select` bindings, and `Enter` opened the selected file’s diff through a separate `diff:viewDetails` action. If your `keybindings.json` binds `diff:viewDetails`, the binding keeps working in the file list as `select:accept`. The diff detail view also binds pager-style keys to the standard [scroll actions](#scroll-actions). These bindings are part of the `DiffDialog` context and apply only in the detail view; the `Scroll` context defaults listed under [Scroll actions](#scroll-actions) are unchanged.
| Action | Default | Description |
|:----------------------|:---------------|:----------------------------|
| `scroll:pageUp` | PageUp | Scroll up half a viewport |
| `scroll:pageDown` | PageDown | Scroll down half a viewport |
| `scroll:fullPageUp` | Shift+Space, B | Scroll up a full viewport |
| `scroll:fullPageDown` | Space | Scroll down a full viewport |
| `scroll:top` | G, Home | Jump to the top |
| `scroll:bottom` | Shift+G, End | Jump to the bottom |
[](#diff-panel-actions)
Diff panel actions
Actions for the [diff panel](interactive-mode.md#diff-panel) that `/diff` opens in fullscreen rendering. `app:cycleDiffBase` is in the `DiffPanel` context, which is active while the panel is open; the others are `Global`. The panel requires Claude Code v2.1.260 or later.
| Action | Default | Description |
|:----------------------------|:---------------------|:--------------------------------------------------------------------------|
| `app:toggleReplTab` | (unbound) | Open or close the diff panel, the same as running `/diff` |
| `app:cycleDiffBase` | Ctrl+X B | Cycle the panel’s comparison base: this session, uncommitted, then branch |
| `app:diffFileListUp` | Ctrl+Up, Meta+Up | Scroll the panel’s file list up when it overflows |
| `app:diffFileListDown` | Ctrl+Down, Meta+Down | Scroll the panel’s file list down when it overflows |
| `app:toggleDiffNoiseFilter` | (unbound) | Show or hide test and generated files in the panel |
| `app:toggleDiffPreSession` | (unbound) | Expand or collapse the changes from before this session |
[](#model-picker-actions)
Model picker actions
Actions available in the `ModelPicker` context:
| Action | Default | Description |
|:------------------------------|:--------|:---------------------------------------------|
| `modelPicker:decreaseEffort` | Left | Decrease effort level |
| `modelPicker:increaseEffort` | Right | Increase effort level |
| `modelPicker:thisSessionOnly` | s | Apply highlighted model to this session only |
[](#effort-slider-actions)
Effort slider actions
Actions available in the `EffortSlider` context, the slider that opens when you run `/effort` with no arguments. The slider’s Enter and Escape keys can’t be rebound.
| Action | Default | Description |
|:-------------------------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `effortSlider:decreaseEffort` | Left | Move the slider to the next lower effort level. Requires v2.1.284 or later |
| `effortSlider:increaseEffort` | Right | Move the slider to the next higher effort level. Requires v2.1.284 or later |
| `effortSlider:toggleUltracode` | Tab | Turn [ultracode](workflows.md#let-claude-decide-with-ultracode) on or off for this session, when the slider [offers it](model-config.md#when-ultracode-is-available). Requires v2.1.284 or later |
| `effortSlider:thisSessionOnly` | s | Apply the focused [effort level](model-config.md#adjust-effort-level) to this session only. Requires v2.1.257 or later |
[](#select-actions)
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:pageUp` | PageUp | Move up one page of options |
| `select:pageDown` | PageDown | Move down one page of options |
| `select:first` | Home | First option |
| `select:last` | End | Last option |
| `select:accept` | Enter | Accept selection |
| `select:cancel` | Escape | Cancel selection |
In list panels such as `/skills`, `/mcp`, and `/tasks`, Claude Code applies your `select:pageUp`, `select:pageDown`, `select:first`, and `select:last` bindings. In most other lists, such as the `/model` picker, your `select:first` and `select:last` bindings apply. PageUp and PageDown page through the options in those lists regardless of your bindings. Before v2.1.280, those other lists ignored Home, End, and your `select:first` and `select:last` bindings. Before v2.1.283, the `/mcp` tool list paged with fixed PageUp and PageDown keys regardless of your bindings.
[](#plugin-actions)
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)
Settings actions
Actions available in the `Settings` context. The `select:accept` and `confirm:no` actions are reused from the [Select](#select-actions) and [Confirmation](#confirmation-actions) contexts with Settings-specific behavior: changes apply to each setting as soon as you change it, so Escape closes the panel with your changes saved rather than declining.
| Action | Default | Description |
|:------------------|:-------------|:------------------------------------------------|
| `settings:search` | / | Enter search mode |
| `settings:retry` | R | Retry loading usage data on error |
| `select:accept` | Enter, Space | Change the selected setting or open its submenu |
| `confirm:no` | Escape | Close the panel. Changes are already saved |
[](#agents-actions)
Agents actions
Actions available in the `Agents` context, which applies in [agent view](../09-Agents-Patterns/agent-view.md), opened with `claude agents`. Requires v2.1.257 or later.
| Action | Default | Description |
|:--------------------|:--------|:---------------------------------------------------------------------------------------------|
| `agents:switchView` | Ctrl+S | Switch [session grouping](../09-Agents-Patterns/agent-view.md#organize-the-list) between state and directory |
| `agents:togglePin` | Ctrl+T | [Pin or unpin](../09-Agents-Patterns/agent-view.md#organize-the-list) the selected session |
While agent view is open, Claude Code uses the `Agents` binding for any key the `Agents` context binds, and it ignores a `Chat` or `Global` binding on the same key. For example, pressing Ctrl+S in agent view switches the session grouping rather than triggering the default `chat:stash`. The dispatch input’s external-editor shortcut isn’t an `Agents` action. Agent view follows the `Chat` context’s `chat:externalEditor` binding, Ctrl+G by default. Bindings fire on single keystrokes in agent view, so the Ctrl+X Ctrl+E chord bound to `chat:externalEditor` doesn’t open the editor there.
[](#voice-actions)
Voice actions
Actions available in the `Chat` context when [voice dictation](voice-dictation.md) is enabled:
| Action | Default | Description |
|:-------------------|:--------|:---------------------------------------------------------|
| `voice:pushToTalk` | Space | Dictate a prompt. Hold or tap depending on `/voice` mode |
[](#scroll-actions)
Scroll actions
Actions available in the `Scroll` context when [fullscreen rendering](fullscreen.md) is enabled:
| Action | Default | Description |
|:----------------------------|:---------------------|:----------------------------------------------------------------------------------------------------------|
| `scroll:lineUp` | `wheelup` | Scroll up one line. Mouse wheel scrolling triggers this action |
| `scroll:lineDown` | `wheeldown` | 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. Requires v2.1.234 or later |
| `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)
Keystroke syntax
[](#modifiers)
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:
```python
ctrl+k Ctrl + K
shift+tab Shift + Tab
meta+p Option + P on macOS, Alt + P elsewhere
ctrl+shift+c Multiple modifiers
```
[](#uppercase-letters)
Uppercase letters
Claude Code parses key names case-insensitively, so `K` is the same binding as `k` and `ctrl+K` is the same as `ctrl+k`. To bind Shift and a letter, write `shift+k`.
[](#non-us-keyboard-layouts)
Non-US keyboard layouts
Write the key names of Ctrl shortcuts as Latin characters even when your active keyboard layout types other characters. How Claude Code matches the key you press to a binding depends on the kind of layout:
- Under a non-Latin layout such as Cyrillic, Claude Code matches Ctrl shortcuts by the key’s US-layout position when the terminal uses the Kitty keyboard protocol and reports that position. In such a terminal, with a Russian layout active, pressing Ctrl and the physical W key triggers `ctrl+w`. In a terminal that doesn’t report the position, Claude Code matches whatever the terminal sends for the keypress: an ASCII control code triggers the Latin shortcut, and a keypress that arrives as the Cyrillic character matches no binding
- Under layouts that rearrange Latin letters, such as AZERTY, Claude Code matches the letter that the key types, so pressing Ctrl and the key labeled A triggers `ctrl+a`
Before v2.1.247, pressing a Ctrl shortcut under a non-Latin layout didn’t trigger its binding in terminals that use the Kitty keyboard protocol, such as Ghostty, Kitty, WezTerm, and iTerm2.
[](#chords)
Chords
Chords are sequences of keystrokes separated by spaces:
```python
ctrl+k ctrl+s Press Ctrl+K, release, then Ctrl+S
```
Press each keystroke within 3 seconds of the one before it. If you wait longer, Claude Code cancels the chord and shows a brief notice saying so.
[](#special-keys)
Special keys
- `escape` or `esc` - Escape key
- `enter` or `return` - Enter key
- `tab` - Tab key
- `space` - Space bar
- `up`, `down`, `left`, `right` - Arrow keys
- `pageup`, `pagedown` - Page Up and Page Down keys
- `home`, `end` - Home and End keys
- `backspace`, `delete` - Delete keys
- `wheelup`, `wheeldown` - Mouse wheel scroll events
[](#unbind-default-shortcuts)
Unbind default shortcuts
Set an action to `null` to unbind a default shortcut:
```python
{
"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. A chord in any active context keeps its prefix reserved, so you must unbind each chord in the context that defines it. Claude Code binds these default chords on the `ctrl+x` prefix: `ctrl+x ctrl+k`, `ctrl+x ctrl+e`, `ctrl+x enter`, `ctrl+x ctrl+a`, `ctrl+x ctrl+s`, and `ctrl+x tab` in `Chat`, `ctrl+x ctrl+b` in `Task`, and `ctrl+x b` in `DiffPanel`. The `ctrl+x enter` chord requires v2.1.247 or later, `ctrl+x b`, `ctrl+x ctrl+a`, and `ctrl+x tab` require v2.1.260 or later, and `ctrl+x ctrl+s` requires v2.1.275 or later. To reclaim `ctrl+x` itself as a single-key binding, unbind all of them:
```python
{
"bindings": [
{
"context": "Task",
"bindings": {
"ctrl+x ctrl+b": null
}
},
{
"context": "DiffPanel",
"bindings": {
"ctrl+x b": null
}
},
{
"context": "Chat",
"bindings": {
"ctrl+x ctrl+k": null,
"ctrl+x ctrl+e": null,
"ctrl+x enter": null,
"ctrl+x ctrl+a": null,
"ctrl+x ctrl+s": null,
"ctrl+x tab": 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)
Reserved shortcuts
These shortcuts cannot be rebound:
| Shortcut | Reason |
|:----------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Ctrl+C | Hardcoded interrupt/cancel |
| Ctrl+D | Hardcoded exit |
| Ctrl+M | Claude Code always receives it as Enter |
| Ctrl+\[ | Claude Code always receives it as Escape. In terminals that use the Kitty keyboard protocol, this requires v2.1.242 or later |
| Ctrl+I | Claude Code always receives it as Tab |
| Ctrl+H | Sends the ASCII backspace byte. [How Claude Code reads it on Windows](terminal-config.md#fix-backspace-deleting-a-whole-word-on-windows) depends on your terminal and the [`CLAUDE_CODE_BS_AS_CTRL_BACKSPACE`](env-vars.md) environment variable |
| Caps Lock | Not delivered to terminal applications |
[](#terminal-conflicts)
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) |
[](#text-fields)
Text fields
If you bind a bare letter, digit, or Space, you can still type that character in a text field inside a dialog or panel. One such field is the `Other` answer to a question Claude asks. While the field has focus, a printable key you press without Ctrl, Alt, or Cmd goes to the field, and Claude Code doesn’t match it against your bindings. These keys still run their bindings while the field has focus:
- Keys that don’t type a character, such as Enter, Escape, Tab, and the arrow keys
- Any key pressed with Ctrl, Alt, or Cmd
- The second keystroke of a [chord](#chords) already in progress
At the main prompt, Claude Code matches every key against the active contexts, such as `Chat`, and types the key only when no binding takes it.
[](#vim-mode-interaction)
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
- Vim keys aren’t remappable through the keybindings file. To map a two-key INSERT-mode sequence such as `jj` to Escape, use the [`vimInsertModeRemaps`](interactive-mode.md#remap-insert-mode-key-sequences) setting
- In vim NORMAL mode, `?` shows the help menu (vim behavior)
- In vim NORMAL mode, `/` opens history search, the same as Ctrl+R in standard mode
[](#validation)
Validation
Claude Code validates your keybindings and writes a warning to the debug log for:
- Parse errors (invalid JSON or structure)
- Misspelled modifiers, such as `ctl+k`. Claude Code drops the part it doesn’t recognize and applies the binding to the keystroke that remains, `k` in this example.
- Invalid context names
- Invalid action values, such as an action that isn’t a string or `null`
- Unknown action names, such as a typo of a registered action. Claude Code skips the binding and keeps any default binding for that key in effect. Before v2.1.246, a binding with an unknown action name silently disabled that key
- Reserved shortcut conflicts
- Duplicate bindings in the same context
Start Claude Code with [`--debug`](cli-reference.md#cli-flags) to see the details.
---
## Set up Claude Code in a monorepo or large codebase - Claude Code Docs
Source: https://code.claude.com/docs/en/large-codebases
Path: 02-Claude-Code-CLI/large-codebases.md
## On this page
- [What this guide covers](#what-this-guide-covers)
- [Settings on this page](#settings-on-this-page)
- [The example monorepo](#the-example-monorepo)
- [Choose where to start Claude](#choose-where-to-start-claude)
- [Layer CLAUDE.md files by directory](#layer-claude-md-files-by-directory)
- [Choose between per-directory CLAUDE.md and path-scoped rules](#choose-between-per-directory-claude-md-and-path-scoped-rules)
- [Exclude irrelevant CLAUDE.md files](#exclude-irrelevant-claude-md-files)
- [Reduce what Claude reads](#reduce-what-claude-reads)
- [Block reads of generated and vendored code](#block-reads-of-generated-and-vendored-code)
- [Reduce file reads with code intelligence](#reduce-file-reads-with-code-intelligence)
- [Scope worktrees and file access](#scope-worktrees-and-file-access)
- [Check out only the directories you need](#check-out-only-the-directories-you-need)
- [Grant access across packages or repositories](#grant-access-across-packages-or-repositories)
- [Add per-directory skills](#add-per-directory-skills)
- [Keep skills discoverable](#keep-skills-discoverable)
- [Centralize conventions when layering stops scaling](#centralize-conventions-when-layering-stops-scaling)
- [Recommend the right plugin at session start](#recommend-the-right-plugin-at-session-start)
- [Put it together](#put-it-together)
- [Scope and plan changes that span packages](#scope-and-plan-changes-that-span-packages)
- [Next steps](#next-steps)
Guides
# Set up Claude Code in a monorepo or large codebase
Copy pageCopy page
Configure Claude Code for monorepos and large single-tree codebases with nested CLAUDE.md files, sparse worktrees, code intelligence, and per-package skills so Claude stays focused on the code you’re working in.
Copy pageCopy page
A large codebase can be one repository with millions of lines or a monorepo with many packages. Claude Code works at any size, but as the codebase grows, the defaults tuned for smaller projects can fill the context window with instructions and file reads unrelated to the task, costing tokens and degrading Claude’s performance. This guide shows individual developers and engineering teams how to scope Claude to the part of the codebase a task touches. Each section notes whether a setting is personal to your machine or committed to the repository.
[](#what-this-guide-covers)
What this guide covers
The [table below](#settings-on-this-page) lists each setting and what it accomplishes. The [file tree after it](#the-example-monorepo) is the example monorepo every code sample on this page refers to.
[](#settings-on-this-page)
Settings on this page
Each setting below is independent. They layer rather than replace each other, so apply whichever fit your repository. [Choose where to start Claude](#choose-where-to-start-claude) determines where your settings files live, so read it first. [Put it together](#put-it-together) shows all of them combined.
| I want to | Use |
|:----------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------|
| Load only the conventions for the code you touch, instead of one root file covering every subsystem | Per-directory [CLAUDE.md files](#layer-claude-md-files-by-directory) |
| Exclude CLAUDE.md files for packages you never work in | [`claudeMdExcludes`](#exclude-irrelevant-claude-md-files) |
| Block Claude from opening build output, generated code, and vendored dependencies | [`Read` deny rules](#block-reads-of-generated-and-vendored-code) in `permissions.deny` |
| Find a symbol’s definition or callers through the language server instead of scanning files | A [code intelligence plugin](#reduce-file-reads-with-code-intelligence) |
| Check out only the directories a task needs when Claude creates a worktree | [`worktree.sparsePaths`](#check-out-only-the-directories-you-need) |
| Read and edit a sibling package or another repository from the same session | [`--add-dir`](#grant-access-across-packages-or-repositories) or `additionalDirectories` |
| Give Claude procedures specific to one area that load only when relevant | Per-directory [skills](#add-per-directory-skills) |
| Replace many per-directory CLAUDE.md files with one set of conventions everyone installs | A [plugin](#centralize-conventions-when-layering-stops-scaling) in an internal marketplace |
For workflow techniques that keep context small in any repository, such as [running exploration in a subagent](best-practices.md#use-subagents-for-investigation) so file reads stay out of the main conversation, see [Best practices for Claude Code](best-practices.md). To roll out a baseline configuration to every developer in your organization, see [Set up Claude Code for your organization](../13-Enterprise-Admin/admin-setup.md).
[](#the-example-monorepo)
The example monorepo
The examples throughout this page refer to a monorepo with three packages. The same patterns work in a large single-tree codebase: where an example uses `packages/api/`, substitute your own subsystem directory such as `src/backend/` or `lib/core/`.
```python
monorepo/
CLAUDE.md # root instructions
packages/
api/
CLAUDE.md # API-specific instructions
.claude/skills/
src/
web/
CLAUDE.md # frontend-specific instructions
.claude/skills/
src/
shared/
CLAUDE.md # shared library instructions
src/
```
[](#choose-where-to-start-claude)
Choose where to start Claude
Where you launch `claude` determines which files Claude can read and edit without an additional permission grant, which CLAUDE.md files load into context at startup, and which project settings apply.
| Start from | File access | CLAUDE.md loaded at launch | Use when |
|:----------------|:----------------------------------------|:---------------------------------------------------------------------|:-------------------------------------------|
| Repository root | Every file | Root only; subdirectory files load on demand when Claude reads there | Tasks span multiple packages or subsystems |
| A subdirectory | That subtree only, until you grant more | That directory’s plus every ancestor’s | Work is scoped to one package or subsystem |
Project settings in `.claude/settings.json` aren’t inherited from parent directories the way CLAUDE.md files are. For which directory’s `.claude/settings.json` a session reads, see [where Claude Code looks for each file](settings.md#where-claude-code-looks-for-each-file). Each section below states whether its settings file belongs at the repository root or in the subdirectory you start from, and whether it is committed or kept local.
[](#layer-claude-md-files-by-directory)
Layer CLAUDE.md files by directory
In a large codebase, a single CLAUDE.md at the repository root tends to either grow to cover every subsystem’s conventions, costing context on instructions unrelated to the current task, or stay too generic to be useful. Splitting instructions across per-directory files means Claude loads repository-wide rules plus only the conventions for the code you’re working in. Claude Code loads every [CLAUDE.md](memory.md) file from your working directory and every parent directory at launch, then loads each subdirectory’s file on demand when it reads files there. A root file sets repository-wide rules and each subdirectory adds its own. A common split is two levels:
- **Root `CLAUDE.md`**: instructions that apply everywhere, such as coding standards and commit conventions
- **Per-subdirectory `CLAUDE.md`**: conventions specific to that area’s stack. In a monorepo that’s one per package. In a large single tree it’s one per subsystem such as `src/db/` or `src/api/`
Commit these files to the repository so teammates inherit them. Each directory’s owner typically maintains its file. To trim a file that is already checked in, run the [`/doctor` checkup](memory.md#my-claude-md-is-too-large). The root `CLAUDE.md` holds the rules that apply in every package:
CLAUDE.md
```python
Run package scripts from the package directory, not the monorepo root.
Prefix commit subjects with the package name, for example `api: add rate limiting`.
Never edit files under packages/*/generated/. Run `npm run codegen` in the package instead.
```
Each subdirectory’s `CLAUDE.md`, here `packages/api/CLAUDE.md`, adds the conventions specific to that area:
packages/api/CLAUDE.md
```python
Copy `.env.example` to `.env` before running anything. Tests and the dev server fail without it.
Write database queries with the Knex query builder. Never put raw SQL strings in route handlers.
Never edit a migration after it has merged. Add a new migration instead.
```
When you start Claude from `packages/api/`, it loads both `packages/api/CLAUDE.md` and the root `CLAUDE.md`. Claude sees the local instructions alongside the repository-wide rules, with no instructions from `packages/web/` in context. The same holds for any subdirectory in a non-monorepo tree. To confirm which files loaded, run `/context` and check the list under **Memory files**. A few ways to keep the files current as the codebase and models change:
- **Review in pull requests**: treat CLAUDE.md edits like any other documentation change so conventions track the code
- **Revisit after major model releases**: instructions that worked around an older model’s limitation may become overhead once a newer model handles the case on its own. For example, a rule that forces single-file refactors can be deleted once the limitation is gone
- **Add a Stop hook that proposes updates**: a [`Stop` hook](../07-Hooks/hooks.md#stop) receives the path to the session transcript when Claude finishes responding, so a script can review the session and propose CLAUDE.md updates while the gap it exposed is fresh
For more on how CLAUDE.md files load and interact, see [Memory and project instructions](memory.md).
[](#choose-between-per-directory-claude-md-and-path-scoped-rules)
Choose between per-directory CLAUDE.md and path-scoped rules
Per-directory `CLAUDE.md` files and [path-scoped rules](memory.md#path-specific-rules) under `.claude/rules/` both let you target instructions to part of the tree. They differ in where the file lives and when it loads.
| Approach | File location | Loads when | Use when |
|:-------------------------------------|:-----------------------------------------|:----------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
| Per-directory `CLAUDE.md` | Inside the directory, alongside its code | At launch when started from that directory, or on demand when Claude reads a file there | Directory owners maintain their own conventions; instructions are versioned with the code |
| Path-scoped rule in `.claude/rules/` | Central `.claude/` at the repo root | When Claude works with a file matching the rule’s `paths:` glob | You want all conventions in one place, or the same rule applies to many scattered paths |
For a comparison that also covers skills, see [Compare similar features](features-overview.md#compare-similar-features).
[](#exclude-irrelevant-claude-md-files)
Exclude irrelevant CLAUDE.md files
When you start Claude from the repository root, each subdirectory’s CLAUDE.md loads as soon as Claude reads a file in that directory. The `claudeMdExcludes` setting skips specific files by path or glob pattern so they never load. Use this for directories you never work in, such as other teams’ packages, legacy code, or vendored subtrees. The exclusion list is static, not a per-task switch. To focus on one package today and another tomorrow, [start Claude from that package’s directory](#choose-where-to-start-claude) instead of editing exclusions. If you only want these exclusions for yourself, put the setting in `.claude/settings.local.json`. Claude Code adds that file to your global gitignore when it saves a setting there. Since you are creating it by hand here, add it to your gitignore yourself. Patterns use glob syntax matched against absolute file paths, so start relative-style patterns with `**/` to match anywhere in the tree. The example below excludes a package owned by another team:
.claude/settings.local.json
```python
{
"claudeMdExcludes": [
"**/packages/web/**"
]
}
```
This skips every CLAUDE.md and rules file under that package. The root CLAUDE.md and the packages you do work in still load normally. These patterns cover other common cases:
- `"**/packages/*/CLAUDE.md"`: excludes every package’s CLAUDE.md while keeping the root
- `"**/packages/legacy-*/**"`: excludes every package whose name matches the glob, including rules
- `"/home/user/monorepo/legacy/CLAUDE.md"`: excludes one specific file by absolute path
Managed policy CLAUDE.md files cannot be excluded, so organization-wide instructions always apply. You can set `claudeMdExcludes` at any [settings scope](settings.md#where-settings-live): user, project, local, or managed. Arrays merge across scopes, so a team can set project-level defaults while individuals add local overrides. For the full exclusion documentation, see [Exclude specific CLAUDE.md files](memory.md#exclude-specific-claude-md-files).
[](#reduce-what-claude-reads)
Reduce what Claude reads
Instructions are only part of what ends up in Claude’s context. File reads are another cost that grows with the codebase. The settings below block reads of irrelevant paths and replace exhaustive file scans with language-server lookups.
[](#block-reads-of-generated-and-vendored-code)
Block reads of generated and vendored code
Claude’s content searches respect `.gitignore` by default, so paths already listed there, such as `node_modules/`, `dist/`, and `build/`, stay out of search results without additional configuration. For paths that are checked in, such as a vendored SDK or committed generated code, add `Read` deny rules in `permissions.deny` to block Claude from opening those files. The deny rules can cover everyone working in the repository, only you, or every session on the machine, depending on which settings file you put them in:
- **Everyone working in the repository**: commit the rules to `.claude/settings.json`, at the repository root if you start Claude there, or in each package’s `.claude/` if you start from subdirectories. Like other project settings on this page, that file isn’t inherited from parent directories.
- **Yourself only**: use `.claude/settings.local.json` at the repository root, which loads in every CLI session inside the repository regardless of starting directory, except in the cases where Claude Code [doesn’t use the repository root](settings.md#where-claude-code-looks-for-each-file), such as on Windows. Relative patterns like the example’s `Read(./**/vendor/**/*)` still [anchor at the session’s current working directory](permissions.md#read-and-edit) rather than the repository root, so if you start sessions from subdirectories, write the rules in this file as `//`-absolute paths, such as `Read(//absolute/path/to/repo/**/vendor/**/*)`. Before v2.1.211, `.claude/settings.local.json` also loaded only from the starting directory.
- **Everyone, enforced in every session**: set the rules in [managed settings](../13-Enterprise-Admin/managed-settings.md), which user and project settings cannot override.
The example below blocks build artifacts and a vendored SDK. Its directory patterns end with `/**/*` rather than `/**` so that each rule covers everything inside the directory but not the directory itself. Claude can then still list those directories or change into them, for example with `ls dist` or `cd build`.
.claude/settings.json
```python
{
"permissions": {
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)",
"Read(./**/*.generated.*)",
"Read(./**/vendor/**/*)"
]
}
}
```
Deny rules cover Claude’s built-in file tools. In Bash, they cover the file commands Claude Code recognizes, such as `cat`, `head`, `grep`, and `find`, when a denied path appears as an argument, and the target of a [redirection](permissions.md#redirections) such as `< file`. Claude Code also makes a best-effort attempt to leave denied paths out of the results of the built-in Grep and Glob tools. A Bash search such as `grep -r` or `find` over a directory that contains denied files still includes them in its output. Deny rules don’t cover subprocesses that open files themselves. For the full pattern syntax, see [Read and Edit permission rules](permissions.md#read-and-edit).
[](#reduce-file-reads-with-code-intelligence)
Reduce file reads with code intelligence
In a large codebase, finding where a symbol is defined or used can cost many file reads and grep calls. [Code intelligence plugins](../08-Plugins-Skills/plugins-code-intelligence.md) connect Claude to a language server so it can jump to definitions, find references, and surface type errors directly instead of scanning the tree. The official marketplace has plugins for TypeScript, Python, Go, Rust, and other common languages. Run the command below inside a Claude Code session to install the TypeScript plugin:
```python
/plugin install typescript-lsp@claude-plugins-official
```
If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
To enable a plugin for everyone in the repository rather than installing it yourself, add it to the [`enabledPlugins` project setting](settings-reference.md#plugin-settings). Code intelligence plugins require the language’s language server binary on each developer’s machine. See [which binary each language requires](../08-Plugins-Skills/plugins-code-intelligence.md). Installing from the official marketplace requires network access to GitHub, where the marketplace is hosted. On a restricted network, [add the marketplace from an internal Git host or local path](../08-Plugins-Skills/discover-plugins.md#add-a-marketplace) instead. This pairs well with `claudeMdExcludes` and the `Read` deny rules above. Those keep irrelevant content out of context, and code intelligence keeps Claude from reading through what remains to locate a definition.
[](#scope-worktrees-and-file-access)
Scope worktrees and file access
These settings control what’s on disk in worktrees and which directories Claude can read and write beyond your starting point.
[](#check-out-only-the-directories-you-need)
Check out only the directories you need
The `--worktree` flag starts a session in a new git worktree so changes stay isolated from your main checkout. By default it checks out the entire repository. In a large repository, the `worktree.sparsePaths` setting uses git sparse-checkout to write only the listed directories plus root-level files to disk, so worktrees start faster and use less space. If everyone working in this directory needs the same paths, commit the setting to `.claude/settings.json`. To add paths for yourself, use `.claude/settings.local.json`: the lists merge across scopes, so a local file can add paths to the committed list but not remove them. The JSON examples on this page show one setting at a time. If your `.claude/settings.json` already contains other keys, such as the `permissions.deny` rules above, add the `worktree` key alongside them rather than replacing the file. [Put it together](#put-it-together) shows the combined result. The example below shows the committed file:
.claude/settings.json
```python
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
]
}
}
```
When Claude creates a worktree, it checks out only `.claude/`, `packages/api/`, and `packages/shared/` instead of the full tree. Paths in `sparsePaths` are relative to the repository root, regardless of which subdirectory you start Claude from. Any directory paths work here, not only package roots. This is particularly useful for [subagent worktree isolation](worktrees.md#isolate-subagents-with-worktrees). Subagents are parallel Claude instances spawned for subtasks, and each one that runs in a worktree gets a lightweight checkout instead of the full tree. All worktrees in a session share the same `sparsePaths`, so if one subagent needs `packages/api/` and another needs `packages/web/`, list both. List directories in `sparsePaths`, not individual files. Root-level files like `package.json`, `tsconfig.base.json`, and lock files are always checked out alongside the directories you list. Root-level directories are not, so include `.claude` in the list if you want the repository root’s `.claude/settings.json` or `.claude/rules/` available inside the worktree. For project skills, agents, and commands, see [What worktrees share with the main checkout](worktrees.md#what-worktrees-share-with-the-main-checkout). Sparse checkout requires git to enable `extensions.worktreeConfig` in the repository’s shared `.git/config` while a sparse worktree exists. Claude Code removes that entry after the last worktree is removed, but only if Claude Code added it. It never removes a value you set yourself. Before v2.1.207, the entry remained after the last worktree was removed, and go-git-based tools such as `tea` failed to open the repository until you ran `git config --unset extensions.worktreeConfig`. To avoid duplicating large directories like `node_modules` across worktrees, pair `sparsePaths` with `symlinkDirectories` in the same `.claude/settings.json`:
.claude/settings.json
```python
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
}
}
```
This creates a symlink from each worktree’s `node_modules/` back to the main repository’s copy rather than duplicating it on disk.
The `sparsePaths` and `symlinkDirectories` settings are read from your starting directory before the worktree is created. After creation, the session’s working directory is the worktree root, not the subdirectory you launched from. Project settings inside the worktree therefore load from the worktree root’s `.claude/settings.json`, the checked-out copy of the repository root’s file. Put any other settings you need inside worktrees, such as permission rules or hooks, in the repository root’s `.claude/settings.json`.
For the full worktree settings reference, see [Worktree settings](settings-reference.md#worktree).
[](#grant-access-across-packages-or-repositories)
Grant access across packages or repositories
This section applies when you start Claude from a subdirectory, or when a task spans multiple checkouts. If you start from the repository root in a single large tree, Claude already has access to every file and you can skip this. When you start Claude from `packages/api/`, it can read and write files within that directory. If a task requires changes across packages, such as updating a shared type that both `api` and `web` import, you need to grant access to the sibling directory. The same mechanism grants access to a separately-checked-out repository. The `additionalDirectories` setting in `.claude/settings.json` gives Claude access to directories outside the working directory. The example below grants access to two sibling packages:
packages/api/.claude/settings.json
```python
{
"permissions": {
"additionalDirectories": [
"../shared",
"../web"
]
}
}
```
Relative paths resolve against the directory you start Claude from. With this configuration, Claude can read and edit files in `packages/shared/` and `packages/web/` while working from `packages/api/`. You can also grant access at runtime without editing settings by passing `--add-dir` when you start Claude:
```python
claude --add-dir ../shared
```
However you add a directory, Claude can read and edit files in it. Whether the directory’s CLAUDE.md, `.claude/rules/` files, and skills also load depends on how you added it:
| Added with | Loads CLAUDE.md and rules | Loads skills |
|:---------------------------------------|:-----------------------------------------|:-------------|
| `additionalDirectories` setting | Never | Never |
| `--add-dir` flag or `/add-dir` command | Only with the environment variable below | Yes |
To load CLAUDE.md and rules files from a directory added with `--add-dir` or `/add-dir`, set the `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` environment variable:
```python
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared
```
The environment variable has no effect on directories listed in the `additionalDirectories` setting. See [Load from additional directories](memory.md#load-from-additional-directories) for details. For sibling directories that everyone in this area needs, commit `additionalDirectories` to `.claude/settings.json`. For a personal selection or one-off access, use `.claude/settings.local.json` or pass `--add-dir` at launch.
[](#add-per-directory-skills)
Add per-directory skills
Any subdirectory can define [skills](../08-Plugins-Skills/skills.md) scoped to its own stack. A skill loads on demand when Claude determines it’s relevant, so API-specific tooling doesn’t consume context during frontend work. Skills live under `.claude/skills/` inside the directory. Commit them alongside that area’s code so anyone who clones the repository gets them. In a monorepo this can be one set of skills per package. In a large single-tree codebase it’s one set per subsystem such as `src/db/.claude/skills/`. Create a skill directory inside the subdirectory:
```python
mkdir -p packages/api/.claude/skills/api-testing
```
Then write `SKILL.md` inside that directory, here `packages/api/.claude/skills/api-testing/SKILL.md`. This example teaches Claude the API package’s testing patterns:
packages/api/.claude/skills/api-testing/SKILL.md
```python
---
name: api-testing
description: Testing patterns for the API package. Use when writing or modifying tests in packages/api/.
---
## Test structure
Tests are in `src/__tests__/` mirroring the `src/` directory structure.
Each route file has a corresponding `.test.ts` file.
## Running tests
- All tests: `npm test`
- Single file: `npm test -- src/__tests__/routes/users.test.ts`
- Watch mode: `npm test -- --watch`
## Test utilities
- `src/__tests__/helpers/db.ts`: provides `setupTestDb()` and `teardownTestDb()` for database tests
- `src/__tests__/helpers/auth.ts`: provides `createTestUser()` and `getAuthToken()` for authenticated endpoints
## Patterns
- Use `supertest` for HTTP assertions, not raw fetch
- Always wrap database tests in a transaction that rolls back
- Mock external services in `src/__tests__/mocks/`
```
A different subdirectory holds different skills the same way: `packages/web/.claude/skills/component-patterns/` describes the frontend’s component conventions instead of testing. When Claude works on a file in `packages/api/`, it loads the api-testing skill. When it works in `packages/web/`, it loads component-patterns instead. Neither directory’s skills load during the other’s tasks. You can also scope a skill by file pattern instead of by placement. The [`paths` frontmatter field](../08-Plugins-Skills/skills.md#frontmatter-reference) takes glob patterns, and Claude loads the skill automatically only when it works with matching files. Use this for a skill that lives in the repository root’s `.claude/skills/` but applies only to certain files wherever they appear, such as a database-migration skill scoped to `**/migrations/**`. For more on creating and organizing skills, see [Skills](../08-Plugins-Skills/skills.md).
[](#keep-skills-discoverable)
Keep skills discoverable
With skills spread across many directories, the list Claude chooses from can grow large. Claude picks a skill by reading every discovered skill’s name and description, and only the chosen skill’s full content loads into context. This section covers how to keep that list small. Which skills are in scope depends on where you start Claude:
- **From a subdirectory such as `packages/api/`**: skills from that directory, every parent up to the repository root, and the user and enterprise levels
- **From the repository root**: root skills, plus skills from every subdirectory Claude touches during the session, which can accumulate into the hundreds
- **After adding a sibling with [`--add-dir`](#grant-access-across-packages-or-repositories)**: that sibling’s skills load too. The `additionalDirectories` setting grants file access only and does not load skills
Names always load, but [when there are many, some skills lose their descriptions entirely](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short), which can strip the keywords Claude uses to decide whether a skill applies. Keep descriptions short and lead with words a request would contain, like “writing or modifying tests in `packages/api/`”. For skills that many directories share, such as PR conventions or a deploy checklist, place them in the repository root’s `.claude/skills/` so they load from any starting directory. When shared skills need their own version history or must work across repositories, package them as a [plugin](../08-Plugins-Skills/plugins.md) instead. Plugin skills use a `plugin-name:skill-name` namespace, so they never collide with per-directory skills. A platform team can version and update them in one place. To find which skills go unused, enable the OpenTelemetry [logs exporter](../13-Enterprise-Admin/monitoring-usage.md) and set `OTEL_LOG_TOOL_DETAILS=1` so skill names are recorded verbatim instead of redacted. The [`skill_activated` event](../13-Enterprise-Admin/monitoring-usage.md#skill-activated-event) records every invocation in its `skill.name` attribute, and `invocation_trigger` records whether a command, Claude, or a nested skill invoked it, which tells you what to consolidate or retire.
[](#centralize-conventions-when-layering-stops-scaling)
Centralize conventions when layering stops scaling
Per-directory CLAUDE.md files can become hard to govern as the codebase grows. Conventions drift, files go stale, and no one owns the root. Solving that typically falls to the team that maintains the repository’s Claude Code setup rather than to each developer working in their own area. Move conventions and reference content out of always-loaded CLAUDE.md and into mechanisms that load on demand:
- [Skills](../08-Plugins-Skills/skills.md): reference material Claude loads only when relevant to the task
- [Plugins](../08-Plugins-Skills/plugins.md): versioned bundles of skills, hooks, and commands that a platform team owns centrally
- [MCP servers](../06-MCP-Tools/General/mcp.md): if your organization already runs a code search or RAG index over the repository, expose it as an MCP tool so Claude queries it instead of reading files directly
See [server-managed or endpoint-managed settings](../13-Enterprise-Admin/server-managed-settings.md#choose-between-server-managed-and-endpoint-managed-settings) for how platform teams can enforce these centrally.
[](#recommend-the-right-plugin-at-session-start)
Recommend the right plugin at session start
Once conventions live in plugins, a teammate starting Claude in an unfamiliar part of the tree has no signal about which plugin that area’s owners maintain. A [`SessionStart` hook](../07-Hooks/hooks.md#sessionstart) can close that gap, since Claude Code adds plain text the hook prints to stdout to Claude’s context before the first prompt. For example, you can write a script that reads the launch directory from the [hook input](../07-Hooks/hooks.md#common-input-fields), looks it up in a path-to-plugin map committed to the repository, and prints the recommendation for Claude to relay in its first reply. See [Automate actions with hooks](../07-Hooks/hooks-guide.md) to write and register the hook.
[](#put-it-together)
Put it together
The combined configuration below uses the monorepo layout. The same files work for any subdirectory in a large single tree. Each subdirectory’s `.claude/settings.json` must be self-contained rather than layered on a root file. The example commits `worktree`, `additionalDirectories`, and the `Read` deny rules in `.claude/settings.json` so every developer in `packages/api/` gets the same sibling access, sparse paths, and exclusions. The file below is the committed per-area settings for `packages/api/`:
packages/api/.claude/settings.json
```python
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
},
"permissions": {
"additionalDirectories": [
"../shared"
],
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)"
]
}
}
```
Because this session starts from `packages/api/`, sibling packages’ CLAUDE.md files are already out of scope, so `claudeMdExcludes` is not needed here. Add it to the repository root’s `.claude/settings.local.json` instead if you also start sessions from the root. The `additionalDirectories` entry applies when you start Claude from `packages/api/` directly. Inside a worktree created from this session, the working directory is the worktree root, so this settings file does not load. The sibling packages are already reachable inside the worktree without it, but the deny rules need a second copy in the repository root’s `.claude/settings.json` so worktree sessions pick them up, as the [worktree settings note](#check-out-only-the-directories-you-need) describes:
.claude/settings.json
```python
{
"permissions": {
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)"
]
}
}
```
After setup, the repository has this layout:
```python
monorepo/
CLAUDE.md
.claude/settings.json # deny rules for worktree sessions
packages/
api/
CLAUDE.md
.claude/settings.json # worktree, additionalDirectories, deny rules
.claude/skills/api-testing/SKILL.md
web/
CLAUDE.md
.claude/skills/component-patterns/SKILL.md
shared/
CLAUDE.md
```
With this setup, starting Claude from `packages/api/`:
- Loads the root CLAUDE.md and `packages/api/CLAUDE.md`, skips `packages/web/CLAUDE.md`
- Can read and edit files in `packages/api/` and `packages/shared/`
- Skips reads of build output under `dist/` and `build/` in `packages/api/`
- Has the api-testing skill available on demand
- Creates worktrees containing `.claude/`, `packages/api/`, `packages/shared/`, and root-level files, with the deny rules applied across the worktree from the root settings file
[](#scope-and-plan-changes-that-span-packages)
Scope and plan changes that span packages
The configuration above controls what Claude sees. When a single change touches several packages, such as updating a shared type along with every call site that uses it, how you scope and sequence the task also affects the result. Two techniques help keep a cross-package change consistent:
- **Give Claude the whole change in one session**: handing over the shared edit and its call sites together keeps the decisions behind each edit consistent, rather than re-deriving them per package
- **Plan before editing**: [plan first](best-practices.md#explore-first-then-plan-then-code) in [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode), and Claude writes the plan to a file. A long cross-package session [compacts its context](context-window.md#what-survives-compaction) along the way. Claude Code re-injects the plan file after each compaction, so the plan survives where conversation history may not
[](#next-steps)
Next steps
Once this configuration is in place, you can refine it:
- Use [hooks](../07-Hooks/hooks-guide.md) to run per-directory linters or type-checkers after Claude edits files
- Review [Manage costs effectively](../17-Billing-Plans/costs.md) to understand how codebase size affects token usage and how to set spend limits before a wider rollout
- Read [How Claude Code works in large codebases](https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start) on the Claude blog for organizational rollout patterns and ownership models that sit above the per-repository configuration on this page
---
## Docs Llms Txt Cc59D2A156
Source: https://code.claude.com/docs/llms.txt
Path: 02-Claude-Code-CLI/llms.md
\# Claude Code Docs \> Official documentation for Claude Code, Anthropic's agentic coding tool available in the terminal, IDE, desktop app, and browser. Covers installation, configuration, skills, subagents, hooks, MCP, the Agent SDK, and reference material. \## Getting started \### Getting started - \[Overview\](code-home.md): Claude Code is an agentic coding tool that reads your codebase, edits files, runs commands, and integrates with your development tools. Available in your terminal, IDE, desktop app, and browser. - \[Quickstart\](../01-Getting-Started/quickstart.md): Welcome to Claude Code! - \[Claude Code changelog\](changelog.md): Release notes for Claude Code, including new features, improvements, and bug fixes by version. \### Core concepts - \[How Claude Code works\](how-claude-code-works.md): Understand the agentic loop, built-in tools, and how Claude Code interacts with your project. - \[Extend Claude Code\](features-overview.md): Understand when to use CLAUDE.md, Skills, subagents, hooks, MCP, and plugins. - \[Explore the .claude directory\](claude-directory.md): Where Claude Code reads CLAUDE.md, settings.json, hooks, skills, commands, subagents, workflows, rules, and auto memory. Explore the .claude directory in your project and ~/.claude in your home directory. - \[Explore the context window\](context-window.md): An interactive simulation of how Claude Code's context window fills during a session. See what loads automatically, what each file read costs, and when rules and hooks fire. - \[How Claude Code uses prompt caching\](prompt-caching.md): Claude Code manages prompt caching automatically. See why a model switch triggers a slow uncached turn, what \`/compact\` costs, why CLAUDE.md edits don't apply mid-session, and how to check your cache hit rate. \### Use Claude Code - \[How Claude remembers your project\](memory.md): Give Claude persistent instructions with CLAUDE.md or AGENTS.md files, and let Claude accumulate learnings automatically with auto memory. - \[Manage sessions\](sessions.md): Name, resume, branch, and switch between Claude Code conversations. Covers \`--continue\`, \`--resume\`, \`--from-pr\`, the \`/resume\` picker, session naming, exporting transcripts, and where transcripts are stored. - \[Common workflows\](common-workflows.md): Step-by-step guides for exploring codebases, fixing bugs, refactoring, testing, and other everyday tasks with Claude Code. - \[Prompt library\](prompt-library.md): Copy-paste prompts for Claude Code, tagged by task and role. - \[Best practices for Claude Code\](best-practices.md): Tips and patterns for getting the most out of Claude Code, from configuring your environment to scaling across parallel sessions. \### Platforms and integrations - \[Platforms and integrations\](platforms.md): Choose where to run Claude Code and what to connect it to. Compare the CLI, Desktop, VS Code, JetBrains, web, mobile, and integrations like Chrome, Slack, and CI/CD. - \[Continue local sessions from any device with Remote Control\](remote-control.md): Continue a local Claude Code session from your phone, tablet, or any browser using Remote Control. Works with claude.ai/code and the Claude mobile app. - \[Let Claude coordinate ongoing work with Projects\](claude-projects.md): Give Claude a body of related work in one conversation and let it coordinate parallel cloud sessions that share repositories, instructions, and memory. - \[Claude Code on mobile\](../16-Mobile-Desktop/mobile.md): Start, monitor, and steer Claude Code tasks from your phone with the Claude app for iOS and Android. - \[Use Claude Code with Chrome\](../03-IDE-Integrations/chrome.md): Connect Claude Code to your Chrome browser to test web apps, debug with console logs, automate form filling, and extract data from web pages. - \[Let Claude use your computer from the CLI\](computer-use.md): Enable computer use in the Claude Code CLI so Claude can open apps, click, type, and see your screen on macOS. Test native apps, debug visual issues, and automate GUI-only tools without leaving your terminal. - \[Use Claude Code in VS Code\](../03-IDE-Integrations/vs-code.md): Install and configure the Claude Code extension for VS Code. Get AI coding assistance with inline diffs, @-mentions, plan review, and keyboard shortcuts. - \[JetBrains IDEs\](../03-IDE-Integrations/jetbrains.md): Use Claude Code with JetBrains IDEs including IntelliJ, PyCharm, WebStorm, and more - \[Claude Code in Slack\](../14-Connectors/slack.md): Delegate coding tasks directly from your Slack workspace. Anthropic is retiring this earlier version for Team and Enterprise workspaces in favor of Claude Tag; it remains the setup path on Pro and Max plans. - \[Claude Tag\](claude-tag.md): Bring Claude into your team's Slack channels with Claude Tag and find its setup and usage documentation on claude.com. \#### Claude Code in the cloud - \[Get started with Claude Code in the cloud\](web-quickstart.md): Run Claude Code in the cloud from your browser or phone. Connect a GitHub repository, submit a task, and review the PR without local setup. - \[Use Claude Code in the cloud\](claude-code-on-the-web.md): Run Claude Code sessions in the cloud from your browser, phone, Desktop app, or terminal, move them with \`--cloud\` and \`--teleport\`, and auto-fix pull requests. - \[Automate work with routines\](web-scheduled-tasks.md): Put Claude Code on autopilot. Define routines that run on a schedule, trigger on API calls, or react to GitHub events from cloud infrastructure. - \[Find bugs with ultrareview\](ultrareview.md): Run a deep, multi-agent code review in the cloud with /code-review ultra to find and verify bugs before you merge. \#### Claude Code on desktop - \[Get started with the desktop app\](../16-Mobile-Desktop/desktop-quickstart.md): Install the Claude desktop app, open the Code tab, and start your first Claude Code session on a project folder on your computer. - \[Desktop application\](../16-Mobile-Desktop/desktop.md): Get more out of Claude Code Desktop: parallel sessions with Git isolation, drag-and-drop pane layout, integrated terminal and file editor, side chats, computer use, Dispatch sessions from your phone, visual diff review, app previews, PR monitoring, connectors, and enterprise configuration. - \[Claude Desktop on Linux (beta)\](../16-Mobile-Desktop/desktop-linux.md): Install and update the Claude desktop app on Ubuntu and Debian - \[Claude Code Desktop in WSL\](../16-Mobile-Desktop/desktop-wsl.md): Run Code sessions inside a WSL 2 distribution on Windows - \[Schedule recurring tasks in Claude Code Desktop\](../16-Mobile-Desktop/desktop-scheduled-tasks.md): Set up scheduled tasks in Claude Code Desktop to run Claude automatically on a recurring basis for daily code reviews, dependency audits, or morning briefings. - \[Test iOS apps in the simulator\](../16-Mobile-Desktop/desktop-ios-simulator.md): Claude Code Desktop opens your app in the iOS Simulator pane when Claude builds, runs, or checks it, with a separate simulator for each session. \#### Code review & CI/CD - \[Catch security issues as Claude writes code\](security-guidance.md): Install the security-guidance plugin to have Claude review its own code changes for vulnerabilities and fix them in the same session. - \[Scan your codebase for vulnerabilities\](claude-security.md): Install the Claude Security plugin to scan your codebase for vulnerabilities in a Claude Code session and turn findings into patches you review and apply. - \[Code Review\](code-review.md): Set up automated PR reviews that catch logic errors, security vulnerabilities, and regressions using multi-agent analysis of your full codebase - \[Claude Code GitHub Actions\](github-actions.md): Run Claude Code in GitHub Actions workflows to respond to @claude mentions, automate tasks, and turn issues into pull requests - \[Use Claude Code GitHub Actions with cloud providers\](github-actions-cloud-providers.md): Run Claude Code GitHub Actions through Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry instead of the Claude API - \[Claude Code with GitHub Enterprise Server\](github-enterprise-server.md): Connect Claude Code to your self-hosted GitHub Enterprise Server instance for cloud sessions, code review, and plugin marketplaces. - \[Claude Code GitLab CI/CD\](gitlab-ci-cd.md): Learn about integrating Claude Code into your development workflow with GitLab CI/CD \## Build with Claude Code \### Agents and parallel work - \[Run agents in parallel\](../09-Agents-Patterns/agents.md): Compare the ways Claude Code can take on multiple tasks at once: subagents, agent view, agent teams, dynamic workflows, and projects. - \[Create custom subagents\](../09-Agents-Patterns/sub-agents.md): Create and use specialized AI subagents in Claude Code for task-specific workflows and improved context management. - \[Manage multiple agents with agent view\](../09-Agents-Patterns/agent-view.md): Dispatch and manage many Claude Code sessions from one screen. Agent view shows what every session is doing and which ones need your input. - \[Orchestrate teams of Claude Code sessions\](../09-Agents-Patterns/agent-teams.md): Coordinate multiple Claude Code instances working together as a team, with shared tasks, inter-agent messaging, and centralized management. - \[Message your other Claude Code sessions\](cross-session-messaging.md): Let Claude list and message your other Claude Code sessions on this machine, and reach your sessions on other machines or in the cloud. - \[Orchestrate subagents at scale with dynamic workflows\](workflows.md): Dynamic workflows orchestrate many subagents from a script Claude writes and you can rerun. Use them for codebase audits, large migrations, and cross-checked research. - \[Run parallel sessions with worktrees\](worktrees.md): Isolate parallel Claude Code sessions in separate git worktrees so changes don't collide. Covers the \`--worktree\` flag, subagent isolation, \`.worktreeinclude\`, cleanup, and non-git VCS hooks. \### MCP - \[Connect to MCP servers\](../06-MCP-Tools/General/mcp-quickstart.md): Add an MCP server to Claude Code, verify the connection, and find the configuration on disk. - \[Connect Claude Code to tools via MCP\](../06-MCP-Tools/General/mcp.md): Learn how to connect Claude Code to your tools with the Model Context Protocol. \### Skills - \[Extend Claude with skills\](../08-Plugins-Skills/skills.md): Create, manage, and share skills to extend Claude's capabilities in Claude Code. Includes custom commands and bundled skills. \### Artifacts - \[Share session output as artifacts\](artifacts.md): Artifacts turn Claude Code's work into live, interactive pages on claude.ai that you can keep private, share with your organization, or publish to a public link. \### Automation - \[Automate actions with hooks\](../07-Hooks/hooks-guide.md): Run shell commands automatically when Claude Code edits files, finishes tasks, or needs input. Format code, send notifications, validate commands, and enforce project rules. - \[Push events into a running session with channels\](channels.md): Use channels to push messages, alerts, and webhooks into your Claude Code session from an MCP server. Forward CI results, chat messages, and monitoring events so Claude can react while you're away. - \[Run prompts on a schedule\](scheduled-tasks.md): Use /loop and the cron scheduling tools to run prompts repeatedly, poll for status, or set one-time reminders within a Claude Code session. - \[Keep Claude working toward a goal\](goal.md): Set a completion condition with /goal and Claude keeps working until it's met, a model judges it impossible, or an error you have to fix clears the goal. - \[Run Claude Code programmatically\](headless.md): Use the Agent SDK to run Claude Code programmatically from the CLI, Python, or TypeScript. - \[Launch sessions from links\](deep-links.md): Open a Claude Code terminal session from a URL. Embed \`claude-cli://\` links in runbooks, alerts, and dashboards so a click opens Claude Code in the right repo with the right prompt. \### Guides - \[Set up Claude Code in a monorepo or large codebase\](large-codebases.md): Configure Claude Code for monorepos and large single-tree codebases with nested CLAUDE.md files, sparse worktrees, code intelligence, and per-package skills so Claude stays focused on the code you're working in. \### Troubleshooting - \[Troubleshoot installation and login\](troubleshoot-install.md): Fix command not found, PATH, permission, network, and authentication errors when installing or signing in to Claude Code. - \[Troubleshooting\](troubleshooting.md): Fix high CPU or memory usage, hangs, auto-compact thrashing, and search problems in Claude Code, and find the right page for other issues. - \[Debug your configuration\](debug-your-config.md): Diagnose why CLAUDE.md, settings, hooks, MCP servers, or skills aren't taking effect. Use /context, /doctor, /hooks, and /mcp to see what actually loaded. - \[Error reference\](errors.md): Look up Claude Code runtime error messages with what each one means and how to fix it. \## Plugins \### Plugins - \[Plugins overview\](../08-Plugins-Skills/plugins.md): Understand what a Claude Code plugin is, when you need one instead of a standalone skill or MCP server, and which page to read to install or create one. \### Use plugins - \[Install and manage plugins\](../08-Plugins-Skills/discover-plugins.md): Install Claude Code plugins from a marketplace on any surface you use, choose an install scope, and update or remove them later. - \[Anthropic's marketplaces\](../08-Plugins-Skills/plugins-anthropic-marketplaces.md): Anthropic's official, community, and demo plugin marketplaces for Claude Code: their names, repositories, how you add each, and where to browse their plugins. - \[Code intelligence plugins\](../08-Plugins-Skills/plugins-code-intelligence.md): Install a language server plugin so Claude sees type errors after edits and navigates code by symbol, and answer the LSP plugin recommendation dialog. - \[Plugin security and trust\](../08-Plugins-Skills/plugins-security.md): Decide whether to trust a plugin before you install it, from what a plugin can do on your machine to how to review one and remove it. \### Create plugins - \[Create a Claude Code plugin\](../08-Plugins-Skills/plugins-create.md): Build your first Claude Code plugin from an empty directory, test it without a marketplace, and convert an existing .claude/ setup. - \[Add components to a plugin\](../08-Plugins-Skills/plugins-components.md): Add skills, hooks, MCP servers, and every other component type to a Claude Code plugin, with an example that validates for each. - \[Plugin dependencies\](../08-Plugins-Skills/plugins-dependencies.md): Declare the plugins your plugin depends on, with version ranges such as ^1.2, and see how Claude Code installs, resolves, and prunes them. - \[Test plugins with evals\](../08-Plugins-Skills/plugin-evals.md): Write eval cases for your Claude Code plugin, run them with claude plugin eval, grade the results, compare against a no-plugin baseline, and gate CI on the score. - \[Publish and distribute a plugin\](../08-Plugins-Skills/plugins-publish.md): Publish a Claude Code plugin through your own marketplace or Anthropic's directory, with a pre-release checklist and how users get updates. - \[Measure plugin cost and usage\](../08-Plugins-Skills/plugins-measure.md): Measure a Claude Code plugin's token cost, find out whether people still use it, and pick the telemetry events for organization-wide plugin questions. - \[Recommend your plugin from your CLI\](../08-Plugins-Skills/plugins-cli-hints.md): Prompt Claude Code users to install your official-marketplace plugin by emitting a claude-code-hint tag from your CLI or SDK. \### Run a marketplace - \[Create a marketplace\](../08-Plugins-Skills/plugin-marketplaces.md): Build a plugin marketplace from a marketplace.json file and test it locally before you host it. - \[Host and maintain a marketplace\](../08-Plugins-Skills/plugins-host-marketplace.md): Publish a plugin marketplace where users can reach it, grant access to a private one, and release updates and renames without breaking installs. - \[Recommend plugins for your org\](../08-Plugins-Skills/plugins-relevance.md): Add a relevance block to marketplace plugin entries so Claude Code suggests them when a user's work matches, and allowlist the marketplace in managed settings. \### Manage plugins for your organization - \[Manage Claude Code plugins for your organization\](../08-Plugins-Skills/plugins-org.md): Control which plugins Claude Code installs and allows across your organization through managed settings. \### Troubleshooting - \[Troubleshoot plugins\](../08-Plugins-Skills/plugins-troubleshooting.md): Fix plugin errors in Claude Code. Find the exact message you saw, grouped by stage from where /plugin runs through install and org policy. - \[Plugin loading reference\](../08-Plugins-Skills/plugins-loading.md): Trace where Claude Code loads each plugin from, which settings file decides whether it loads, and why an update changed nothing. \### Reference - \[Plugin manifest reference\](../08-Plugins-Skills/plugins-reference.md): Complete reference for plugin.json: every field with its type and default, accepted path forms, and the userConfig and environment variable schemas. - \[Marketplace reference\](../08-Plugins-Skills/plugins-marketplace-reference.md): Complete reference for marketplace.json fields, plugin entries, and the plugin and marketplace source objects, with where each is valid. - \[Plugin commands reference\](../08-Plugins-Skills/plugins-cli-reference.md): Complete reference for the claude plugin shell commands, /plugin and /reload-plugins in a session, and the flags that load a plugin for one session. \## Administration \### Setup and access - \[Set up Claude Code for your organization\](../13-Enterprise-Admin/admin-setup.md): A decision map for administrators deploying Claude Code, covering API providers, managed settings, policy enforcement, usage monitoring, and data handling. - \[Advanced setup\](../01-Getting-Started/setup.md): System requirements, platform-specific installation, version management, and uninstallation for Claude Code. - \[Authentication\](../13-Enterprise-Admin/iam.md): Log in to Claude Code and configure authentication for individuals, teams, and organizations. - \[Deploy managed settings\](../13-Enterprise-Admin/managed-settings.md): Deploy managed settings to every developer's machine: delivery mechanisms per OS, how Claude Code combines managed sources, and how to verify enforcement. - \[Configure server-managed settings\](../13-Enterprise-Admin/server-managed-settings.md): Centrally configure Claude Code for your organization through server-delivered settings, without requiring device management infrastructure. - \[Control MCP server access for your organization\](../06-MCP-Tools/General/managed-mcp.md): Restrict which MCP servers users can add or connect to, or provide servers to every user, with managed configuration files, managed settings, allowlists, and denylists. - \[Configure auto mode\](auto-mode-config.md): Tell the auto mode classifier which repos, buckets, and domains your organization trusts. Set environment context, override the default block and allow rules, and inspect your effective config with the auto-mode CLI subcommands. \### Deployment - \[Enterprise deployment overview\](third-party-integrations.md): Learn how Claude Code can integrate with various third-party services and infrastructure to meet enterprise deployment requirements. - \[Feature availability\](feature-availability.md): Compare which Claude Code features are available across Anthropic subscription plans, the Anthropic Console, Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry. - \[Claude Code on Amazon Bedrock\](amazon-bedrock.md): Learn about configuring Claude Code through Amazon Bedrock, including setup, IAM configuration, and troubleshooting. - \[Claude Code on Claude Platform on AWS\](claude-platform-on-aws.md): Configure Claude Code to use the Anthropic-operated Claude API with AWS authentication, IAM access control, and AWS Marketplace billing. - \[Claude Code on Google Cloud's Agent Platform\](google-vertex-ai.md): Learn about configuring Claude Code through Google Cloud's Agent Platform, formerly Vertex AI, including setup, IAM configuration, and troubleshooting. - \[Claude Code on Microsoft Foundry\](microsoft-foundry.md): Learn about configuring Claude Code through Microsoft Foundry, including setup, configuration, and troubleshooting. - \[Enterprise network configuration\](../13-Enterprise-Admin/network-config.md): Configure Claude Code for enterprise environments with proxy servers, custom Certificate Authorities (CA), and mutual Transport Layer Security (mTLS) authentication. - \[Run Claude Code behind a corporate launcher\](../13-Enterprise-Admin/corporate-launcher.md): Route the processes Claude Code starts from its own binary, including the background service and every agent view session, through a required launcher with CLAUDE_CODE_PROCESS_WRAPPER or the processWrapper setting. - \[Development containers\](devcontainer.md): Run Claude Code inside a dev container for consistent, isolated environments across your team. \### Gateways - \[Run Claude Code through a gateway\](../13-Enterprise-Admin/gateways.md): Route Claude Code through a self-hosted gateway for centralized credentials, usage tracking, and cost controls. Covers the architecture, Anthropic's Claude apps gateway, and using other gateway products. \#### Claude apps gateway - \[Claude apps gateway for Amazon Bedrock, Claude Platform on AWS, Google Cloud, and Microsoft Foundry\](../13-Enterprise-Admin/claude-apps-gateway.md): Run Claude Code through Amazon Bedrock, Claude Platform on AWS, Google Cloud, or Microsoft Foundry behind a self-hosted gateway with SSO sign-in, per-group model access, and OTLP telemetry. - \[Claude apps gateway configuration\](../13-Enterprise-Admin/claude-apps-gateway-config.md): Reference for every gateway.yaml option: listener and TLS, OIDC, session, Postgres store, Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry upstreams, model routing, managed policies, and telemetry. - \[Claude apps gateway spend limits\](../13-Enterprise-Admin/claude-apps-gateway-spend-limits.md): Cap each developer's spend through the Claude apps gateway by day, week, or month. Set limits with an Admin API and the gateway enforces them live on every request. - \[Claude apps gateway deployment and operations\](../13-Enterprise-Admin/claude-apps-gateway-deploy.md): Register the gateway with your IdP, build the container, deploy on Kubernetes or Cloud Run, and operate it: health checks, secret rotation, upgrades, and security. - \[Deploy Claude apps gateway on AWS\](../13-Enterprise-Admin/claude-apps-gateway-on-aws.md): A worked example of running Claude apps gateway on AWS: ECS Fargate or EKS, Amazon RDS for PostgreSQL, AWS Secrets Manager, and IAM-role auth to Amazon Bedrock. - \[Deploy Claude apps gateway on Google Cloud\](../13-Enterprise-Admin/claude-apps-gateway-on-gcp.md): A worked example of running Claude apps gateway on Google Cloud: Cloud Run or GKE, Cloud SQL for PostgreSQL, Secret Manager, and service-account auth to Google Cloud's Agent Platform. \#### Other gateways - \[Other LLM gateways\](../13-Enterprise-Admin/llm-gateway.md): Route Claude Code through an LLM gateway your organization already runs. Covers connecting Claude Code to a gateway, rolling one out for your organization, and what Claude Code sends to a gateway. - \[Connect Claude Code to an LLM gateway\](../13-Enterprise-Admin/llm-gateway-connect.md): Point Claude Code at your organization's LLM gateway. Check whether your admin already configured it, or set the base URL and credential yourself, then verify the connection and fix gateway errors. - \[Roll out an LLM gateway for your organization\](../13-Enterprise-Admin/llm-gateway-rollout.md): Deploy a gateway product for Claude Code: configure it to forward what Claude Code sends, issue developer credentials, distribute the configuration through managed settings, and verify the rollout. - \[Claude Code gateway compatibility guide\](../13-Enterprise-Admin/llm-gateway-protocol.md): Keep an LLM gateway compatible with Claude Code: the endpoints it calls, the headers and body fields to forward, and what breaks when they're stripped. \### Usage and costs - \[Monitoring\](../13-Enterprise-Admin/monitoring-usage.md): Learn how to enable and configure OpenTelemetry for Claude Code. - \[Manage costs effectively\](../17-Billing-Plans/costs.md): Track token usage, set team spend limits, and reduce Claude Code costs with context management, model selection, extended thinking settings, and preprocessing hooks. - \[Track team usage with analytics\](../13-Enterprise-Admin/analytics.md): View Claude Code usage metrics, track adoption, and measure engineering velocity in the analytics dashboard. \### Security and data - \[Security\](../13-Enterprise-Admin/security.md): Learn about Claude Code's security safeguards and best practices for safe usage. - \[Data usage\](../13-Enterprise-Admin/data-usage.md): Learn about Anthropic's data usage policies for Claude - \[Zero data retention\](zero-data-retention.md): Learn about Zero Data Retention (ZDR) for Claude Code, available to qualified accounts on Claude for Enterprise, including scope, disabled features, and how to request enablement. \### Adoption - \[Communications kit\](../13-Enterprise-Admin/communications-kit.md): Launch announcements, drip-campaign messages, and FAQ responses for rolling Claude Code out to your engineering organization. - \[Champion kit\](../13-Enterprise-Admin/champion-kit.md): A playbook for engineers advocating Claude Code internally: what to share, how to answer questions, and how to grow adoption on your team. \## Configuration \### Settings - \[Settings files and precedence\](settings.md): Change Claude Code settings, pick the scope a key belongs in, verify the change, and learn which value Claude Code uses when a key is set in several places. - \[All settings\](settings-reference.md): Complete reference for every Claude Code settings.json key: where each one goes, its type and default, and a paste-ready example, with an index of every key. - \[Example settings files\](settings-example.md): Realistic settings.json files for a developer, a team, and an organization: copy one, keep the keys you want, and change the values. \### Permissions and sandboxing - \[Configure permissions\](permissions.md): Control what Claude Code can access and do with fine-grained permission rules, modes, and managed policies. - \[Choose a permission mode\](permission-modes.md): Control whether Claude asks before acting. Switch permission modes with Shift+Tab in the CLI, the mode indicator in VS Code, or the mode selector in Desktop. - \[Configure the sandboxed Bash tool\](sandboxing.md): Learn how Claude Code's sandboxed Bash tool provides filesystem and network isolation for safer, more autonomous agent execution. - \[Choose a sandbox environment\](sandbox-environments.md): Compare Claude Code sandbox options: the built-in sandboxed Bash tool, sandbox runtime, dev containers, Docker, and VMs. Choose the right isolation for your threat model. \### Environments - \[Configure cloud environments\](cloud-environments.md): Configure cloud environments for Claude Code cloud sessions: network access levels, environment variables, setup scripts, and environment caching. \#### Self-hosted environments - \[Self-hosted environments\](../13-Enterprise-Admin/self-hosted-environments.md): Run Claude Code cloud sessions on infrastructure you control: set up a self-hosted environment, deploy runners, and route sessions to your own compute. - \[Self-hosted environments quickstart\](../13-Enterprise-Admin/self-hosted-environments-quickstart.md): Set up your first self-hosted environment: install Claude Code, create the environment, start a runner, and route a session to it. - \[Deploy self-hosted environments to production\](../13-Enterprise-Admin/self-hosted-environments-deploy.md): Run self-hosted runners in production: security hardening, network egress control, git credentials, Kubernetes and Compose recipes, and troubleshooting. - \[Customize sessions in self-hosted environments\](../13-Enterprise-Admin/self-hosted-environments-configuration.md): Customize self-hosted environment sessions with wrapper scripts for per-session credentials, lifecycle hooks, and on-demand runner spawning. - \[Test self-hosted environments end to end\](../13-Enterprise-Admin/self-hosted-environments-testing.md): Verify a self-hosted runner image from CI: dispatch a session with the CLI, read Claude's replies through a Stop hook, and script the full loop. - \[Self-hosted environments reference\](../13-Enterprise-Admin/self-hosted-environments-reference.md): Complete reference for the self-hosted runner and orchestrator: CLI flags, environment variables, and Prometheus metrics. - \[Verify session identity in self-hosted environments\](../13-Enterprise-Admin/self-hosted-environments-identity.md): Verify the CLAUDE_CODE_SESSION_ACCESS_TOKEN JWT so services on your network can trust requests from sessions in your self-hosted environment. \### Model and responses - \[Model configuration\](model-config.md): Configure which model Claude Code uses, effort levels, extended context, and the auto-compact window - \[Speed up responses with fast mode\](fast-mode.md): Get faster Opus responses in Claude Code by toggling fast mode. - \[Escalate hard decisions with the advisor tool\](advisor.md): Pair your main model with a stronger advisor model that Claude consults at key moments during a task. - \[Output styles\](output-styles.md): Change Claude Code's role, tone, and response format with a built-in output style such as Concise or Explanatory, or write a custom style. \### Interface - \[Configure your terminal for Claude Code\](terminal-config.md): Fix Shift+Enter for newlines, get a terminal bell when Claude finishes, configure tmux, match the color theme, and enable Vim mode in the Claude Code CLI. - \[Fullscreen rendering\](fullscreen.md): Enable a smoother, flicker-free rendering mode with mouse support and stable memory usage in long conversations. - \[Use Claude Code with a screen reader\](accessibility.md): Set up Claude Code for screen readers such as VoiceOver and NVDA, plus settings for screen magnifiers, reduced motion, and colorblind-friendly themes. - \[Voice dictation\](voice-dictation.md): Speak your prompts in the Claude Code CLI with hold-to-record or tap-to-record voice dictation. - \[Customize your status line\](statusline.md): Configure a custom status bar to monitor context window usage, costs, and git status in Claude Code - \[Customize keyboard shortcuts\](keybindings.md): Customize keyboard shortcuts in Claude Code with a keybindings configuration file. \## Reference \### Reference - \[CLI reference\](cli-reference.md): Complete reference for Claude Code command-line interface, including commands and flags. - \[Commands\](commands.md): Complete reference for commands available in Claude Code, including built-in commands and bundled skills. - \[Environment variables\](env-vars.md): Reference for environment variables that control Claude Code behavior. - \[Tools reference\](tools-reference.md): Complete reference for the tools Claude Code can use, including permission requirements and per-tool behavior. - \[Interactive mode\](interactive-mode.md): Complete reference for keyboard shortcuts, input modes, and interactive features in Claude Code sessions. - \[Checkpointing\](checkpointing.md): Track, rewind, and summarize Claude's edits and conversation to manage session state. - \[Hooks reference\](../07-Hooks/hooks.md): Reference for Claude Code hook events, configuration schema, JSON input/output formats, exit codes, async hooks, HTTP hooks, prompt hooks, and MCP tool hooks. - \[Channels reference\](channels-reference.md): Build an MCP server that pushes webhooks, alerts, and chat messages into a Claude Code session. Reference for the channel contract: capability declaration, notification events, reply tools, sender gating, and permission relay. \### Glossary - \[Glossary\](glossary.md): Definitions for Claude Code terminology. Learn what agentic loop, compaction, CLAUDE.md, hooks, subagents, MCP, and other core concepts mean. \## Agent SDK \### Agent SDK - \[Agent SDK overview\](../05-Agent-SDK/agent-sdk-overview.md): Build production AI agents with Claude Code as a library - \[Quickstart\](../05-Agent-SDK/agent-sdk-quickstart.md): Get started with the Python or TypeScript Agent SDK to build AI agents that work autonomously - \[Migrate to Claude Agent SDK\](../05-Agent-SDK/agent-sdk-migration-guide.md): Guide for migrating the Claude Code TypeScript and Python SDKs to the Claude Agent SDK - \[Troubleshoot the Agent SDK\](../05-Agent-SDK/agent-sdk-troubleshooting.md): Fix Agent SDK errors when the Claude Code CLI fails to start, the CLI process exits, or a successful result arrives without structured output. \### Build agents - \[Configure your agent\](../05-Agent-SDK/agent-sdk-configuration.md): Configure Agent SDK sessions: compose the options object, set the model, environment, and limits, and find each feature option's page. - \[Examples\](../05-Agent-SDK/agent-sdk-examples.md): Find a complete, runnable Agent SDK project or a guided recipe in the Claude Cookbook that matches what you want to build. \### Core concepts - \[How the agent loop works\](../05-Agent-SDK/agent-sdk-agent-loop.md): Understand the message lifecycle, tool execution, context window, and architecture that power your SDK agents. - \[Use Claude Code features in the SDK\](../05-Agent-SDK/agent-sdk-claude-code-features.md): Load project instructions, skills, hooks, and other Claude Code features into your SDK agents. - \[Work with sessions\](../05-Agent-SDK/agent-sdk-sessions.md): How sessions persist agent conversation history, and when to use continue, resume, and fork to return to a prior run. - \[Persist sessions to external storage\](../05-Agent-SDK/agent-sdk-session-storage.md): Mirror Agent SDK session transcripts to your own object store, key-value store, or database so other hosts can resume your sessions. \### Input and output - \[Streaming Input\](../05-Agent-SDK/agent-sdk-streaming-vs-single-mode.md): Understanding the two input modes for Claude Agent SDK and when to use each - \[Handle approvals and user input\](../05-Agent-SDK/agent-sdk-user-input.md): Surface Claude's approval requests and clarifying questions to users, then return their decisions to the SDK. - \[Stream responses in real-time\](../05-Agent-SDK/agent-sdk-streaming-output.md): Get real-time responses from the Agent SDK as text and tool calls stream in - \[Get structured output from agents\](../05-Agent-SDK/agent-sdk-structured-outputs.md): Return validated JSON from agent workflows using JSON Schema, Zod, or Pydantic. Get type-safe, structured data after multi-turn tool use. \### Extend with tools - \[Give Claude custom tools\](../05-Agent-SDK/agent-sdk-custom-tools.md): Define custom tools with the Claude Agent SDK's in-process MCP server so Claude can call your functions, hit your APIs, and perform domain-specific operations. - \[Connect to external tools with MCP\](../05-Agent-SDK/agent-sdk-mcp.md): Configure MCP servers to extend your agent with external tools. Covers transport types, tool search for large tool sets, authentication, and error handling. - \[Scale to many tools with tool search\](../05-Agent-SDK/agent-sdk-tool-search.md): Scale your agent to thousands of tools by discovering and loading only what's needed, on demand. - \[Subagents in the SDK\](../05-Agent-SDK/agent-sdk-subagents.md): Define and invoke subagents to isolate context, run tasks in parallel, and apply specialized instructions in your Claude Agent SDK applications. \### Customize behavior - \[Modifying system prompts\](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md): Choose between the \`claude_code\` preset and a custom system prompt, and customize behavior with CLAUDE.md, output styles, append, or a fully custom prompt. - \[Extend agents with skills\](../05-Agent-SDK/agent-sdk-skills.md): Control which skills Claude can invoke in Claude Agent SDK sessions, dispatch commands by name, and author skills your sessions discover - \[Plugins in the SDK\](../05-Agent-SDK/agent-sdk-plugins.md): Load custom plugins to extend Claude Code with skills, agents, hooks, and MCP servers through the Agent SDK \### Control and observability - \[Configure permissions\](../05-Agent-SDK/agent-sdk-permissions.md): Control how your agent uses tools with permission modes, hooks, and declarative allow/deny rules. - \[Intercept and control agent behavior with hooks\](../05-Agent-SDK/agent-sdk-hooks.md): Intercept and customize agent behavior at key execution points with hooks - \[Rewind file changes with checkpointing\](../05-Agent-SDK/agent-sdk-file-checkpointing.md): Track file changes during agent sessions and restore files to any previous state - \[Track cost and usage\](../05-Agent-SDK/agent-sdk-cost-tracking.md): Learn how to track token usage, estimate costs, and configure prompt caching with the Claude Agent SDK. - \[Observability with OpenTelemetry\](../05-Agent-SDK/agent-sdk-observability.md): Export traces, metrics, and events from the Agent SDK to your observability backend using OpenTelemetry. - \[Track todos\](../05-Agent-SDK/agent-sdk-todo-tracking.md): Track todos in Agent SDK sessions and render Claude's progress in your application from structured tool calls \### Deployment - \[Hosting the Agent SDK\](../05-Agent-SDK/agent-sdk-hosting.md): Deploy the Agent SDK in production: subprocess architecture, session persistence, scaling, observability, and multi-tenant isolation for Docker, Kubernetes, and sandbox providers. - \[Securely deploying AI agents\](../05-Agent-SDK/agent-sdk-secure-deployment.md): A guide to securing Claude Code and Agent SDK deployments with isolation, credential management, and network controls \### SDK references - \[Agent SDK reference - TypeScript\](../05-Agent-SDK/agent-sdk-typescript.md): Complete API reference for the TypeScript Agent SDK, including all functions, types, and interfaces. - \[TypeScript SDK V2 session API (removed)\](../05-Agent-SDK/agent-sdk-typescript-v2-preview.md): Reference for the removed V2 TypeScript Agent SDK session API, with session-based send/stream patterns for multi-turn conversations. - \[Agent SDK reference - Python\](../05-Agent-SDK/agent-sdk-python.md): Complete API reference for the Python Agent SDK, including all functions, types, and classes. \## What's New \### What's New - \[What's new\](whats-new-index.md): A weekly digest of notable Claude Code features, with code snippets, demos, and context on why they matter. - \[Week 37 · September 7–11, 2026\](whats-new-2026-w37.md): Test your plugins with claude plugin eval and pop Claude Code Desktop panes out into their own windows. - \[Week 36 · August 31 – September 4, 2026\](whats-new-2026-w36.md): Switch to Claude Fable 5.1, let computer use run in the background on Desktop, and watch Claude's edits in a live /diff panel. - \[Week 35 · August 24–28, 2026\](whats-new-2026-w35.md): Resume terminal sessions in the Claude Code Desktop app, review feedback reports that Claude drafts for you, and start a session in restricted mode. - \[Week 34 · August 17–21, 2026\](whats-new-2026-w34.md): Draft editable UI artboards with the /design skill, set the Concise output style, and start a Claude Code session on your machine from your phone. - \[Week 33 · August 10–14, 2026\](whats-new-2026-w33.md): Claude Code Desktop auto-continues after a usage limit resets, fork mode turns on by default, and GitLab merge requests and marketplaces join GitHub. - \[Week 32 · August 3–7, 2026\](whats-new-2026-w32.md): Claude Code sessions message each other, self-hosted environments run cloud sessions on your infrastructure, and auto mode becomes the default permission mode. - \[Week 30 · July 20–24, 2026\](whats-new-2026-w30.md): Opus 5 becomes the default Opus model, Claude Code Desktop adds an iOS Simulator pane, and the Claude Security plugin scans your code for vulnerabilities. - \[Week 29 · July 13–17, 2026\](whats-new-2026-w29.md): Pull live data into published artifacts through MCP connectors, and use Claude Code with a screen reader in the new screen reader mode. - \[Week 28 · July 6–10, 2026\](whats-new-2026-w28.md): Browse external sites from the Desktop app's built-in browser, run a full setup checkup with /doctor, and pick up auto mode transcript protections and agent view upgrades. - \[Week 27 · June 29 – July 3, 2026\](whats-new-2026-w27.md): Claude Sonnet 5 becomes the default model, Claude in Chrome reaches general availability, subagents run in the background by default, Claude Desktop arrives on Linux in beta, and /radio tunes into Claude FM. - \[Week 26 · June 22–26, 2026\](whats-new-2026-w26.md): Authenticate MCP servers from your shell with claude mcp login, get a response to shell mode command output with the ! prefix, and resume a conversation from before /clear with /rewind. - \[Week 25 · June 15–19, 2026\](whats-new-2026-w25.md): Publish a live, shareable page from your session with Artifacts, match tool parameters in deny and ask rules, and set any setting from the prompt with /config. - \[Week 24 · June 8–12, 2026\](whats-new-2026-w24.md): Move a session to a new directory with /cd, let subagents spawn their own subagents, and troubleshoot a broken configuration with safe mode. - \[Week 23 · June 1–5, 2026\](whats-new-2026-w23.md): Run auto mode on Amazon Bedrock, Google Cloud's Agent Platform, and Microsoft Foundry, prompt before writing files that can run code in acceptEdits mode, list installed plugins with /plugin list, and require an approved version range for managed deployments. - \[Week 22 · May 25–29, 2026\](whats-new-2026-w22.md): Run Claude Code on Claude Opus 4.8, orchestrate large tasks with dynamic workflows, catch security issues with the security-guidance plugin, and use fast mode on Opus 4.8 at a lower price. - \[Week 21 · May 18–22, 2026\](whats-new-2026-w21.md): Use auto mode on the Pro plan and with Sonnet 4.6, see which skills, subagents, and MCP servers drive your plan limits in /usage, and review diffs with the new /code-review command. - \[Week 20 · May 11–15, 2026\](whats-new-2026-w20.md): Manage every Claude Code session from one screen with agent view, keep Claude working toward a goal until a condition holds, and run fast mode on Opus 4.7 by default. - \[Week 19 · May 4–8, 2026\](whats-new-2026-w19.md): Load plugins from .zip archives and URLs, search command history across every project with Ctrl+R, branch new worktrees from local HEAD or the remote default, and block actions unconditionally with auto mode hard deny rules. - \[Week 18 · April 27 – May 1, 2026\](whats-new-2026-w18.md): Claude Code on Windows runs without Git Bash, claude auth login accepts a pasted OAuth code when the browser callback can't reach localhost, claude project purge cleans up local state per project, and pasting a PR URL into /resume finds the session that created it. - \[Week 17 · April 20–24, 2026\](whats-new-2026-w17.md): /ultrareview opens as a research preview, automatic session recaps when you return to a terminal, custom color themes you can build and ship in plugins, and a redesigned Claude Code on the web. - \[Week 16 · April 13–17, 2026\](whats-new-2026-w16.md): Claude Opus 4.7 with the new xhigh effort level, Routines on Claude Code on the web, mobile push notifications that ping your phone when Claude needs you, a /usage breakdown that shows what's driving your limits, and native binaries replacing the bundled JavaScript. - \[Week 15 · April 6–10, 2026\](whats-new-2026-w15.md): Ultraplan cloud planning, the Monitor tool with self-pacing /loop, /team-onboarding for packaging your setup, and /autofix-pr from your terminal. - \[Week 14 · March 30 – April 3, 2026\](whats-new-2026-w14.md): Computer use in the CLI, interactive in-product lessons, flicker-free rendering, per-tool MCP result-size overrides, and plugin executables on PATH. - \[Week 13 · March 23–27, 2026\](whats-new-2026-w13.md): Auto mode for hands-off permissions, computer use built in, PR auto-fix in the cloud, transcript search, and a PowerShell tool for Windows. \## Resources \### Resources - \[Legal and compliance\](../13-Enterprise-Admin/legal-and-compliance.md): Legal agreements, compliance certifications, and security information for Claude Code. \> The links below point to documentation indexes. Follow each \`/\_llms/\` index recursively until you reach documentation pages. \## Indexes - \[French (209 pages)\](https://code.claude.com/docs/\_llms/fr.md): Documentation for French. - \[German (210 pages)\](https://code.claude.com/docs/\_llms/de.md): Documentation for German. - \[Italian (209 pages)\](https://code.claude.com/docs/\_llms/it.md): Documentation for Italian. - \[Japanese (209 pages)\](https://code.claude.com/docs/\_llms/jp.md): Documentation for Japanese. - \[Spanish (209 pages)\](https://code.claude.com/docs/\_llms/es.md): Documentation for Spanish. - \[Korean (210 pages)\](https://code.claude.com/docs/\_llms/ko.md): Documentation for Korean. - \[Simplified Chinese (210 pages)\](https://code.claude.com/docs/\_llms/zh-cn.md): Documentation for Simplified Chinese. - \[Traditional Chinese (210 pages)\](https://code.claude.com/docs/\_llms/zh-tw.md): Documentation for Traditional Chinese. - \[Russian (209 pages)\](https://code.claude.com/docs/\_llms/ru.md): Documentation for Russian. - \[Indonesian (209 pages)\](https://code.claude.com/docs/\_llms/id.md): Documentation for Indonesian. - \[Brazilian Portuguese (208 pages)\](https://code.claude.com/docs/\_llms/pt-br.md): Documentation for Brazilian Portuguese.
---
## Manage API key environment variables in Claude Code | Claude Help Center
Source: https://support.claude.com/en/articles/12304248-managing-api-key-environment-variables-in-claude-code
Path: 02-Claude-Code-CLI/managing-api-key-environment-variables-in-claude-code.md
# Manage API key environment variables in Claude Code
May 5, 2026
When using Claude Code, it's important to understand how authentication methods are prioritized to avoid unexpected API charges and ensure you're using your intended account.
## How authentication works
- Claude Code prioritizes environment variable API keys over authenticated subscriptions.
- This is intentional behavior designed to give you flexibility in choosing your authentication method.
- When an API key is set as an environment variable, you'll be charged via API pay-as-you-go rates using the API account associated with that key.
- This happens even if you're logged into Claude Code with a claude.ai subscription or a different Console account.
## Best practices
**To use Claude Code with your Claude subscription:** Keep the ANTHROPIC_API_KEY environment variable unset.
- This prevents unexpected API charges and ensures you're using your subscription's included usage.
- If you need to use a specific API key occasionally, set it temporarily only when needed.
- Run /status in Claude Code periodically to verify your current authentication method.
## Authentication conflict warnings
Claude Code will notify you when there's a conflict between your authenticated subscription and an environment variable API key:
1. During initial setup, if an API key is detected in your environment variables, Claude Code will ask you to confirm which authentication method you want to use.
2. After successful login, you'll see a notification if both credentials are active, alerting you to the potential for unexpected API charges.
## Check your current configuration
To verify if an API key is set as an environment variable, run /status in Claude Code. This will show you which authentication method is currently active.
To check your environment variable directly, run one of these commands in a terminal (outside of Claude Code):
macOS/Linux:
echo $ANTHROPIC_API_KEY
Windows CMD:
echo %ANTHROPIC_API_KEY%
Windows PowerShell:
echo $env:ANTHROPIC_API_KEY
## Set an API key temporarily
If you need to use an API key for the current terminal session only:
macOS/Linux:
export ANTHROPIC_API_KEY='your-api-key-here'
Windows CMD:
set ANTHROPIC_API_KEY=your-api-key-here
Windows PowerShell:
$env:ANTHROPIC_API_KEY="your-api-key-here"
## Set an API key environment variable permanently
macOS/Linux:
For zsh (default on macOS):
bash
# Add to shell config file
echo 'export ANTHROPIC_API_KEY="your-api-key-here"' >> ~/.zshrc
# Apply changes
source ~/.zshrc
For bash:
bash
# Add to shell config file
echo 'export ANTHROPIC_API_KEY="your-api-key-here"' >> ~/.bash_profile
# Apply changes
source ~/.bash_profile
Windows:
1. Open System Properties → Advanced → Environment Variables
2. Under "User variables", click "New"
3. Variable name: ANTHROPIC_API_KEY
4. Variable value: your-api-key-here
5. Click OK and restart your terminal
## Remove an API key environment variable
macOS/Linux (temporary):
unset ANTHROPIC_API_KEY
macOS (permanent):
# Remove from config file
sed -i '' '/ANTHROPIC_API_KEY/d' ~/.zshrc
source ~/.zshrc
Linux (permanent)
sed -i '/ANTHROPIC_API_KEY/d' ~/.zshrc
Windows CMD:
set ANTHROPIC_API_KEY=
Windows PowerShell:
Remove-Item Env:ANTHROPIC_API_KEY
Windows (permanent): Delete the variable from System Environment Variables settings.
## Common issues to avoid
- Setting environment variables in shell configuration files and forgetting about them.
- Not restarting your terminal after changing environment variables.
- Assuming you're using your subscription when an API key is configured in your environment.
If you have any questions, please **[contact our Support team](https://support.claude.com/en/articles/9015913-how-to-get-support)**.
---
## How Claude remembers your project - Claude Code Docs
Source: https://code.claude.com/docs/en/memory
Path: 02-Claude-Code-CLI/memory.md
## On this page
- [CLAUDE.md vs auto memory](#claude-md-vs-auto-memory)
- [CLAUDE.md files](#claude-md-files)
- [When to add to CLAUDE.md](#when-to-add-to-claude-md)
- [Choose where to put CLAUDE.md files](#choose-where-to-put-claude-md-files)
- [Set up a project CLAUDE.md](#set-up-a-project-claude-md)
- [Write effective instructions](#write-effective-instructions)
- [Import additional files](#import-additional-files)
- [How CLAUDE.md files load](#how-claude-md-files-load)
- [Load from additional directories](#load-from-additional-directories)
- [Organize rules with .claude/rules/](#organize-rules-with-claude%2Frules%2F)
- [Set up rules](#set-up-rules)
- [Path-specific rules](#path-specific-rules)
- [Rule frontmatter reference](#rules-frontmatter-reference)
- [Share rules across projects with symlinks](#share-rules-across-projects-with-symlinks)
- [User-level rules](#user-level-rules)
- [Manage CLAUDE.md for large teams](#manage-claude-md-for-large-teams)
- [Deploy organization-wide CLAUDE.md](#deploy-organization-wide-claude-md)
- [Exclude specific CLAUDE.md files](#exclude-specific-claude-md-files)
- [AGENTS.md](#agents-md)
- [When Claude Code reads AGENTS.md](#when-claude-code-reads-agents-md)
- [Choose which instruction files load](#choose-which-instruction-files-load)
- [When AGENTS.md support is unavailable](#when-agents-md-support-is-unavailable)
- [Where AGENTS.md differs from CLAUDE.md](#where-agents-md-differs-from-claude-md)
- [Remove an earlier AGENTS.md workaround](#remove-an-earlier-agents-md-workaround)
- [Share one file with other coding tools](#share-one-file-with-other-coding-tools)
- [Migrate instructions from other tools](#migrate-instructions-from-other-tools)
- [Auto memory](#auto-memory)
- [Enable or disable auto memory](#enable-or-disable-auto-memory)
- [Storage location](#storage-location)
- [How it works](#how-it-works)
- [Audit and edit your memory](#audit-and-edit-your-memory)
- [View and edit with /memory](#view-and-edit-with-%2Fmemory)
- [Troubleshoot memory issues](#troubleshoot-memory-issues)
- [Claude isn’t following my CLAUDE.md](#claude-isn%E2%80%99t-following-my-claude-md)
- [My AGENTS.md isn’t loading](#my-agents-md-isn%E2%80%99t-loading)
- [I don’t know what auto memory saved](#i-don%E2%80%99t-know-what-auto-memory-saved)
- [My CLAUDE.md is too large](#my-claude-md-is-too-large)
- [Instructions seem lost after /compact](#instructions-seem-lost-after-%2Fcompact)
- [Related resources](#related-resources)
Use Claude Code
# How Claude remembers your project
Copy pageCopy page
Give Claude persistent instructions with CLAUDE.md or AGENTS.md files, and let Claude accumulate learnings automatically with auto memory.
Copy pageCopy page
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. Claude can also read a repository’s [`AGENTS.md` files](#agents-md), on their own or alongside CLAUDE.md
- **Auto memory**: notes Claude writes itself based on your corrections and preferences
This page covers how to:
- [Write and organize CLAUDE.md files](#claude-md-files)
- [Use an existing AGENTS.md](#agents-md) as your project instructions, on its own or alongside CLAUDE.md
- [Scope rules to specific file types](#organize-rules-with-claude/rules/) with `.claude/rules/`
- [Configure auto memory](#auto-memory) so Claude takes notes automatically
- [Troubleshoot](#troubleshoot-memory-issues) when instructions aren’t being followed
[](#claude-md-vs-auto-memory)
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. To block an action regardless of what Claude decides, use a [PreToolUse hook](../07-Hooks/hooks-guide.md) instead. 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 | Your preferences, corrections you give Claude, project context Claude can’t derive from the code |
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](../09-Agents-Patterns/sub-agents.md#enable-persistent-memory) for details.
[](#claude-md-files)
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. If your repository uses `AGENTS.md` instead, see [AGENTS.md](#agents-md).
[](#when-to-add-to-claude-md)
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](../08-Plugins-Skills/skills.md) or a [path-scoped rule](#organize-rules-with-claude/rules/) instead. The [extension overview](features-overview.md#build-your-setup-over-time) covers when to use each mechanism.
[](#choose-where-to-put-claude-md-files)
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.
[TABLE]
CLAUDE.md and CLAUDE.local.md files in the directory hierarchy above the working directory are loaded at launch. Files in subdirectories load on demand when Claude reads files in those directories. See [How CLAUDE.md files load](#how-claude-md-files-load) for the full resolution order. For large projects, you can break instructions into topic-specific files using [project rules](#organize-rules-with-claude/rules/). Rules let you scope instructions to specific file types or subdirectories.
[](#set-up-a-project-claude-md)
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. To confirm the file loaded, run `/context` in a session and check the list under **Memory files**.
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.For an interactive multi-phase flow instead, set the `CLAUDE_CODE_NEW_INIT` environment variable to `1` before you run `/init`. Set it in your shell or in the `env` block of a settings file, as shown in [Set environment variables](env-vars.md#set-environment-variables). With it set, `/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. The variable only changes how `/init` runs, so you can leave it set.
[](#write-effective-instructions)
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](context-window.md) 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](#path-specific-rules) so instructions load only when Claude works with matching files. You can also split content into [imports](#import-additional-files) 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/`](#organize-rules-with-claude/rules/) periodically to remove outdated or conflicting instructions. In monorepos, use [`claudeMdExcludes`](#exclude-specific-claude-md-files) to skip CLAUDE.md files from other teams that aren’t relevant to your work. To have Claude check these files for outdated or conflicting instructions, run `/doctor prompt-audit` in a session. Claude reads your CLAUDE.md, CLAUDE.local.md, and AGENTS.md files, plus the rules, skills, commands, subagents, and output styles under `.claude/` and `~/.claude/`. It looks for problems such as instructions written for older models, references to files or commands that don’t exist, and files that contradict each other. You get a report of findings and a set of proposed edits, and nothing in your files changes until you ask Claude to apply them. To audit one file or directory instead, pass its path, for example `/doctor prompt-audit .claude/skills/deploy`. The audit runs through the bundled `/claude-api` skill, so it’s unavailable while that skill is turned off in [`skillOverrides`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) or with [`disableBundledSkills`](settings-reference.md#disablebundledskills). `/doctor prompt-audit` requires Claude Code v2.1.283 or later.
[](#import-additional-files)
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 four hops. To import a file whose path contains spaces, put a backslash before each space. Without the backslashes, the path ends at the first space, even when the import is on a line of its own. A path wrapped in quotes isn’t imported at all, with or without the backslashes. This import loads a file from a folder named `Design Docs`:
```python
- API conventions @Design\ Docs/api-conventions.md
```
Import parsing skips Markdown code spans and fenced code blocks. To mention a path in your CLAUDE.md without importing it, wrap it in backticks: writing `` `@README` `` keeps the text literal, while `@README` outside backticks imports the file. To pull in a README, package.json, and a workflow guide, reference them with `@` syntax anywhere in your CLAUDE.md:
```python
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. With `CLAUDE_CODE_NEW_INIT=1` set, 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:
```python
# Individual Preferences
- @~/.claude/my-project-instructions.md
```
An import in a project-level memory file is external when its path resolves outside your working directory, like the home directory import above. 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 doesn’t appear again.Claude Code shows the dialog to protect you from files other people commit to a shared project. User-scope memory files, such as `~/.claude/CLAUDE.md` and `~/.claude/rules/`, are files you wrote yourself. Except in [Cowork](../15-Claude-AI-Features/product-cowork.md) sessions on your desktop, Claude Code loads their imports without the dialog and trusts them like the rest of your personal configuration.In Cowork sessions on your desktop, Claude Code skips any import in a user-scope file that resolves to a path outside the session’s working directory and loads the rest of the file. In those sessions it also skips a `~/.claude/CLAUDE.md` that is itself a symlink or hard link, and a symlinked `~/.claude/rules/` directory or rule file that points outside the working directory.
[](#how-claude-md-files-load)
How CLAUDE.md files load
Claude Code loads `CLAUDE.md` and `CLAUDE.local.md` from your current working directory and every directory above it. Run Claude Code in `foo/bar/` and 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`](#exclude-specific-claude-md-files) to skip them. For the full layout of root and per-directory CLAUDE.md files and rules, see [Monorepos and large repos](large-codebases.md). 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)
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:
```python
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config
```
The inline form sets the variable for that one launch in Bash or Zsh. To keep it on for every session, add it to the `env` block in `~/.claude/settings.json` as shown in [Set environment variables](env-vars.md#set-environment-variables). 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`](cli-reference.md).
[](#organize-rules-with-claude/rules/)
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](#path-specific-rules), 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](../08-Plugins-Skills/skills.md) instead, which only load when you invoke them or when Claude determines they’re relevant to your prompt.
[](#set-up-rules)
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/`:
```python
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](#path-specific-rules) are loaded at launch with the same priority as `.claude/CLAUDE.md`. Project rules are skipped if you exclude `project` from [`--setting-sources`](cli-reference.md). Before v2.1.211, rules that load on demand, including path-scoped rules and rules in nested `.claude/rules/` directories, loaded even when `project` was excluded.
[](#path-specific-rules)
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.
```python
---
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. As of v2.1.198, matching also works when Claude reaches a file through a symlinked path to the project directory, for example in a symlinked checkout. 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:
```python
---
paths:
- "src/**/*.{ts,tsx}"
- "lib/**/*.ts"
- "tests/**/*.test.ts"
---
```
Each brace group multiplies the number of expanded patterns: `src/*.{ts,tsx}` expands to two patterns, and `{a,b}/{c,d}/*.{ts,tsx}` to eight. To keep expansion bounded, a rule’s whole `paths` list shares one budget of 1,000 expanded patterns and 4 MiB, and patterns without braces don’t count against it. Claude Code uses any pattern that would exceed the budget unexpanded, and its literal braces match no files. Before v2.1.217, a `paths` value with many brace groups stalled or crashed the CLI at startup. Glob syntax treats `[` as the start of a bracket expression such as `[abc]`. A pattern with a `[` that can’t be read as a bracket expression, such as `photos [2024/**`, is invalid: it matches nothing, and the rule’s other patterns keep working. To match a literal `[` in a file name, escape it as `photos \[2024/**`. Before v2.1.207, one invalid pattern made the Read tool fail for every file the rule was evaluated against, instead of matching nothing.
[](#rules-frontmatter-reference)
Rule frontmatter reference
Configure a rule with YAML [frontmatter](glossary.md#frontmatter) between `---` markers at the top of the file. `paths` is the only field Claude Code reads from a rule; any other field is ignored without an error. Claude Code removes the frontmatter before loading the rule into context.
| Field | Required | Description |
|:--------|:---------|:-----------------------------------------------------------------------------------------------------------------------------|
| `paths` | No | Glob patterns that [scope the rule to matching files](#path-specific-rules). Accepts a YAML list or a comma-separated string |
If the YAML between the markers doesn’t parse, Claude Code ignores the frontmatter and loads the rule as if it had no `paths`. Run `claude --debug` to see the parse error.
[](#share-rules-across-projects-with-symlinks)
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. Circular symlinks are detected and handled gracefully. Claude Code treats a symlink whose target is outside your working directory like an [external import](#import-additional-files). The linked rules don’t load until you approve external imports for the project, and after that only the ones without a [`paths` field](#path-specific-rules) load. Claude Code asks for that approval only when a project memory file imports a file outside the working directory with `@path`, not for symlinks alone. To load shared rules without that approval, keep them in [`~/.claude/rules/`](#user-level-rules), where they apply to every project on your machine. This example links both a shared directory and an individual file:
```python
ln -s ~/shared-claude-rules .claude/rules/shared
ln -s ~/company-standards/security.md .claude/rules/security.md
```
If you point a `.claude/rules/` or `CLAUDE.md` symlink at a network path such as the UNC share `\\server\share` or a path under `/net` or `/Network`, the linked instructions don’t load. Claude Code doesn’t follow the link, because looking up such a path can contact the host it names. `\\wsl$` paths don’t count as network paths.
[](#user-level-rules)
User-level rules
Personal rules in `~/.claude/rules/` apply to every project on your machine. Use them for preferences that aren’t project-specific:
```python
~/.claude/rules/
├── preferences.md # Your personal coding preferences
└── workflows.md # Your preferred workflows
```
Claude Code loads user-level rules before project rules, so a project rule appears later in Claude’s context than a user rule. Neither set overrides the other: if a user rule and a project rule conflict, Claude may follow either one, so keep the two consistent.
[](#manage-claude-md-for-large-teams)
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)
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](../13-Enterprise-Admin/managed-settings.md) 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:
```python
{
"claudeMd": "Always run `make lint` before committing.\nNever push directly to main."
}
```
A managed CLAUDE.md and [managed settings](../13-Enterprise-Admin/managed-settings.md) 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` |
| Login method and organization restrictions | 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)
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:
```python
{
"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](settings.md#where-settings-live): user, project, local, or managed policy. Arrays merge across layers. To exclude a rules file you reach through a [symlink](#share-rules-across-projects-with-symlinks), whether the file or its directory is the link, write the pattern against either path: the file’s path under `.claude/rules/` or its link target. A pattern that matches either path excludes the file. Before v2.1.239, only a pattern that matched the link target excluded the file. Managed policy CLAUDE.md files cannot be excluded. This ensures organization-wide instructions always apply regardless of individual settings.
[](#agents-md)
AGENTS.md
Claude Code can read [`AGENTS.md`](glossary.md#agents-md) as your project instructions, so a repository already set up for other coding agents works without adding a `CLAUDE.md`, an import, or a setting. This table shows what Claude reads by default for each combination of instruction files in your repository:
| Your repository has | Claude reads |
|:----------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
| An `AGENTS.md`, and no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `AGENTS.md` |
| An `AGENTS.md` and a `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `CLAUDE.md` files only |
| A `CLAUDE.md` that already [imports `AGENTS.md`](#share-one-file-with-other-coding-tools) | Your `CLAUDE.md`, with `AGENTS.md` included through the import |
To change the default, for example to have Claude always read both files, read only `CLAUDE.md`, or read only your organization’s managed instructions, [change the **Project instructions** setting](#choose-which-instruction-files-load).
Reading `AGENTS.md` directly requires Claude Code v2.1.277 or later. In some sessions Claude [can’t read `AGENTS.md`](#when-agents-md-support-is-unavailable), so [import it from a `CLAUDE.md`](#share-one-file-with-other-coding-tools) there instead.
[](#when-claude-code-reads-agents-md)
When Claude Code reads AGENTS.md
By default, Claude reads `AGENTS.md` only when you have no `CLAUDE.md` in your working directory or above it. Here’s which of your files count for that check:
- **Count, so Claude reads them instead of `AGENTS.md`**: a `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md` in your working directory or any directory above it
- **Don’t count, and keep loading alongside `AGENTS.md`**: your `~/.claude/CLAUDE.md`, your organization’s managed `CLAUDE.md`, and `.claude/rules/` files
When none count, here’s what Claude reads and how you can tell:
- **At session start**: every `AGENTS.md` and `.claude/AGENTS.md` in your working directory and the directories above it. In an interactive session you see a line such as `no CLAUDE.md found; AGENTS.md loaded: /home/you/repo/AGENTS.md` in the conversation
- **As Claude works in subdirectories**: a subdirectory’s `AGENTS.md`, when Claude opens a file there with the Read tool and that subdirectory has none of the three `CLAUDE.md` files of its own
- **Inside each `AGENTS.md`**: [`@path` imports](#import-additional-files) are expanded, [`claudeMdExcludes`](#exclude-specific-claude-md-files) patterns apply, and subagents that [skip project instructions](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup) skip these files too
- **Not read**: `AGENTS.local.md`, `AGENTS.override.md`, or anything under a `.agents/` directory
Because `CLAUDE.local.md` counts, adding one to keep your own uncommitted instructions in a project that relies on `AGENTS.md` stops Claude from reading `AGENTS.md` for you. To keep your `CLAUDE.local.md` and still have Claude read `AGENTS.md`, set **Project instructions** to [`claude-md-and-agents-md`](#choose-which-instruction-files-load).
[](#choose-which-instruction-files-load)
Choose which instruction files load
To change which files Claude reads, type `/config` in a Claude Code session to open the settings panel, then set **Project instructions** to one of these values:
| Value | What Claude reads |
|:--------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `claude-md-or-agents-md` | Your `CLAUDE.md` files, or your `AGENTS.md` files when you have no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it. This is the default |
| `claude-md-and-agents-md` | Your `CLAUDE.md` and `AGENTS.md` files together, each directory’s `CLAUDE.md` files first and its `AGENTS.md` after them. Claude Code skips an `AGENTS.md` it has already loaded, so one that your `CLAUDE.md` imports or symlinks to isn’t read twice |
| `claude-md` | Your `CLAUDE.md` files only |
| `managed-only` | Only your organization’s managed `CLAUDE.md` and [auto memory](#auto-memory) at launch. Your project, local, and user `CLAUDE.md` files, your `.claude/rules/` files, and every `AGENTS.md` are left out. A subdirectory’s `CLAUDE.md` and `.claude/rules/` files, and [path-scoped rules](#path-specific-rules), still load when Claude reads a file there |
You can also set the value in a settings file instead of `/config`. Add it under the built-in `agents-md` plugin’s ID in [`pluginConfigs`](settings-reference.md#pluginconfigs), in `~/.claude/settings.json`, a `--settings` file, or [managed settings](../13-Enterprise-Admin/managed-settings.md). Claude Code ignores it in project and local settings files. This example has Claude read both files:
settings.json
```python
{
"pluginConfigs": {
"agents-md@builtin": {
"options": { "instructionFiles": "claude-md-and-agents-md" }
}
}
}
```
Your change applies from the next message you send and in every new session.
[](#when-agents-md-support-is-unavailable)
When AGENTS.md support is unavailable
In these sessions Claude reads `CLAUDE.md` files only, and **Project instructions** doesn’t appear in the `/config` settings panel:
- You’re on a Claude Code version before v2.1.277
- You disabled the built-in `agents-md` plugin in `/plugin`
- In some cases, it’s your [first session after you upgrade](env-vars.md#first-session-after-an-install-or-upgrade) from v2.1.276 or earlier. Claude reads `AGENTS.md` from your next session on
Before v2.1.281, some sessions, such as those on Amazon Bedrock or with telemetry disabled, read `CLAUDE.md` files only. On those versions, update Claude Code. To give Claude your `AGENTS.md` in any of these sessions, [import it from a `CLAUDE.md`](#share-one-file-with-other-coding-tools).
[](#where-agents-md-differs-from-claude-md)
Where AGENTS.md differs from CLAUDE.md
An `AGENTS.md` that Claude reads through the **Project instructions** setting differs from a `CLAUDE.md` in these places:
| | `CLAUDE.md` | `AGENTS.md` read through the setting |
|:--------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------|
| [`InstructionsLoaded` hooks](../07-Hooks/hooks.md#instructionsloaded) | Fire | Don’t fire. They fire as usual for an `AGENTS.md` that a `CLAUDE.md` imports or symlinks to |
| Directories you add with `--add-dir` while [`CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD`](#load-from-additional-directories) is set | Their `CLAUDE.md` loads | Their `AGENTS.md` doesn’t load |
| An `@path` import of a file outside your working directory | Claude Code asks you to approve [external imports](#import-additional-files) | Loads only if you already approved external imports for this project, with no prompt |
[](#remove-an-earlier-agents-md-workaround)
Remove an earlier AGENTS.md workaround
If you set Claude Code up to read `AGENTS.md` before it did so on its own, here’s what to do with each common setup:
- **A `CLAUDE.md` containing `@AGENTS.md`**: you can leave it. Keeping the import never makes Claude read `AGENTS.md` twice, whichever **Project instructions** value you use. Remove the `CLAUDE.md` if it holds nothing else, or keep it if some of your sessions [can’t load `AGENTS.md` directly](#when-agents-md-support-is-unavailable).
- **A `CLAUDE.md` that tells Claude in words to read `AGENTS.md`**: Claude sees `AGENTS.md` only if it decides to open the file. Delete the `CLAUDE.md` so Claude reads `AGENTS.md` directly, or replace the sentence with an `@AGENTS.md` import.
- **A `CLAUDE.md` symlinked to `AGENTS.md`**: nothing, or delete the symlink. Either way Claude reads the content once.
- **A `SessionStart` hook that prints `AGENTS.md`**: remove it. Once Claude reads `AGENTS.md` directly, the hook adds a second copy to the context.
[](#share-one-file-with-other-coding-tools)
Share one file with other coding tools
When Claude isn’t reading your `AGENTS.md` directly, you can still keep it as the one file every tool shares by putting an `@AGENTS.md` import in a `CLAUDE.md` next to it. Do this when your project also has a `CLAUDE.md`, when you’ve set **Project instructions** to `claude-md`, or in sessions that [can’t load `AGENTS.md`](#when-agents-md-support-is-unavailable). Add any Claude-specific instructions below the import, and Claude reads the imported file first, then the rest:
CLAUDE.md
```python
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.
```
If you don’t need Claude-specific content, a symlink also works:
```python
ln -s AGENTS.md CLAUDE.md
```
The command prints no output on success. Before you choose the symlink over the import, check these constraints:
- **Editing**: Claude reads `CLAUDE.md` through the link, but the Edit and Write tools [refuse to write through a symlink](errors.md#refusing-after-a-symlink-changed), and the refusal directs Claude to edit the link’s target, `AGENTS.md`, instead
- **Windows**: if you or anyone who clones the repository works on Windows, use the `@AGENTS.md` import instead. Creating a symlink there needs Administrator privileges or Developer Mode, and Git checks a committed symlink out as a plain text file unless `core.symlinks` is enabled, which leaves that clone with a one-line `CLAUDE.md` in place of your instructions
With either approach, run `/context` in your next session and confirm `CLAUDE.md` appears under **Memory files**.
[](#migrate-instructions-from-other-tools)
Migrate instructions from other tools
Running [`/init`](commands.md) reads other tools’ instruction files and incorporates the relevant parts into the generated `CLAUDE.md`:
- Cursor rules in `.cursor/rules/` or `.cursorrules`
- Copilot rules in `.github/copilot-instructions.md`
- With `CLAUDE_CODE_NEW_INIT=1` set: `AGENTS.md`, `.devin/rules/`, `.windsurf/rules/` or `.windsurfrules`, and `.clinerules`
You can also run [`/import`](commands.md) to bring a supported coding agent’s configuration into Claude Code, which appends a one-time copy of instruction files such as `AGENTS.md` to the matching `CLAUDE.md` and carries over MCP servers, commands, subagents, and skills. Requires Claude Code v2.1.213 or later.
[](#auto-memory)
Auto memory
Auto memory lets Claude accumulate knowledge across sessions without you writing anything. As it works, Claude saves four kinds of notes for itself. Claude records the kind as a `type` field in the memory file’s frontmatter:
- `user`: your role, expertise, and working preferences
- `feedback`: corrections you give Claude and approaches you confirm
- `project`: ongoing work, deadlines, and decisions that Claude can’t derive from the code or git history
- `reference`: where to find information outside the project, such as an issue tracker or dashboard
Claude skips anything it can derive from the codebase, such as architecture, file paths, or debugging fixes. It also skips anything your CLAUDE.md files already say. 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.
[](#enable-or-disable-auto-memory)
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, which saves `autoMemoryEnabled` to your user settings at `~/.claude/settings.json`. To turn it off for a single project, set `autoMemoryEnabled` in that project’s settings:
```python
{
"autoMemoryEnabled": false
}
```
To disable auto memory via environment variable, set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1`.
[](#storage-location)
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. If you set [`CLAUDE_CODE_PROJECT_DIR_NAME`](sessions.md#name-the-project-directory-yourself) beside `CLAUDE_CONFIG_DIR`, Claude Code uses that name as the `<project>` directory under `<config dir>/projects/` instead, whichever repository you launch it in, so projects launched with that config directory share one auto memory directory. Requires Claude Code v2.1.234 or later. To store auto memory in a different location, set `autoMemoryDirectory` in your `settings.json`. It is read from any [settings scope](settings.md#settings-precedence): user, project, local, policy, or `--settings`.
```python
{
"autoMemoryDirectory": "~/my-custom-memory-dir"
}
```
The value must be an absolute path or start with `~/`. When you set it in a project’s `.claude/settings.json` or `.claude/settings.local.json`, Claude Code honors it under the same [workspace trust rule as hooks in settings files](permissions.md#what-runs-before-you-trust-a-folder). While [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) is on, Claude Code loads no auto memory from a directory that a [repository-supplied settings file](permissions.md#when-your-local-settings-file-needs-trust) chooses and saves none to it, wherever that directory sits. The directory contains a `MEMORY.md` index and one topic file per memory:
```python
~/.claude/projects/<project>/memory/
├── MEMORY.md # Index, one line per memory, loaded into every session
├── user_role.md # One memory
├── feedback_testing.md # One memory
└── ... # 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. Claude Code deletes old session transcripts after the [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays) retention period, but excludes the memory files in the memory directory from that [retention sweep](claude-directory.md#cleaned-up-automatically). `MEMORY.md` and topic files stay until you or Claude edits or deletes them.
[](#how-it-works)
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. After Claude writes to `MEMORY.md`, Claude Code measures the file against the 200-line and 25KB read limits. If the file is near a limit, Claude Code reminds Claude to shorten it: keep one line per entry, move detail into topic files, and merge or drop stale entries. If the file is over a limit, the write still succeeds, but Claude Code returns an [error telling Claude to rewrite the index](errors.md#memory-index-is-over-its-read-limit), because everything past the limit is dropped on the next load. This limit applies only to `MEMORY.md`. Claude Code loads a CLAUDE.md file of up to 4 MiB in full and skips a larger file. Shorter files produce better adherence. Claude Code doesn’t load topic files such as `user_role.md` or `feedback_testing.md` at startup. Claude reads them on demand using its standard file tools when it needs the information. The main conversation’s auto memory isn’t loaded into [subagents](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup); the exception is a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), which inherits the parent conversation and system prompt. A subagent’s own auto memory, enabled with the subagent `memory` field, is a separate directory. Claude reads and writes memory files during your session. When you see messages like “Saved 2 memories” or “Recalled 2 memories” in the Claude Code interface, Claude is actively updating or reading from `~/.claude/projects/<project>/memory/`. When Claude writes a memory file that begins with YAML frontmatter, Claude Code records the write time in a `modified` frontmatter field as an ISO 8601 timestamp. The timestamp shows how current the fact is, both to you and to Claude when it reads the memory back. Any file that has frontmatter gets the field the next time Claude writes it, including files created on earlier versions; Claude Code never adds frontmatter to a file that has none. The `modified` field requires Claude Code v2.1.214 or later.
[](#audit-and-edit-your-memory)
Audit and edit your memory
Auto memory files are plain markdown you can edit or delete at any time. Run [`/memory`](#view-and-edit-with-%2Fmemory) to browse and open memory files from within a session.
[](#view-and-edit-with-/memory)
View and edit with `/memory`
The `/memory` command lists your CLAUDE.md, CLAUDE.local.md, and other memory file locations across user and project scopes, including user and project CLAUDE.md entries for files that don’t exist yet. It also lets you toggle auto memory on or off and provides an option to open the auto memory folder. Select any file to open it in your editor; selecting one that doesn’t exist yet creates it first. To check which `CLAUDE.md` and rules files loaded into the current session, run `/context`. GUI editors such as VS Code open the file in a separate window, and you can keep using the session while it’s open. Before v2.1.216, `/memory` waited for you to close the file before responding. Terminal editors such as Vim take over the terminal until you exit. 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)
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 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 `/context` and check the list under **Memory files** to verify your CLAUDE.md and CLAUDE.local.md files loaded. If a `CLAUDE.md` file is missing there, Claude can’t see it. Use `/memory` to open and edit the files.
- Check that the relevant CLAUDE.md is in a location that gets loaded for your session (see [Choose where to put CLAUDE.md files](#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.
- Check whether your instruction competes with guidance Claude Code adds on its own. If your CLAUDE.md sets commit or pull request rules, turn off the built-in ones with [`includeGitInstructions`](settings-reference.md#includegitinstructions) and set the attribution text with [`attribution`](settings-reference.md#attribution).
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](../07-Hooks/hooks-guide.md) 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`](cli-reference.md#system-prompt-flags). You pass it at launch, so it’s better suited to scripts and automation than interactive use. For how it behaves when you resume a conversation, see [System prompt flags in resumed conversations](cli-reference.md#system-prompt-flags-in-resumed-conversations).
Use the [`InstructionsLoaded` hook](../07-Hooks/hooks.md#instructionsloaded) to log which `CLAUDE.md` and rules files are loaded, when they load, and why. This is useful for debugging path-specific rules or lazy-loaded files in subdirectories.
[](#my-agents-md-isn’t-loading)
My AGENTS.md isn’t loading
If your repository has an `AGENTS.md` and Claude doesn’t seem to know what it says, the usual cause is a `CLAUDE.md` somewhere on the project path. By default Claude reads `AGENTS.md` only when you have no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it. Check these in order:
1. Look for a `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md` in your working directory or any directory above it, other than your `~/.claude/CLAUDE.md`. If you find one, Claude reads it instead of `AGENTS.md` unless you set **Project instructions** to `claude-md-and-agents-md`.
2. Run `claude --version` and confirm v2.1.277 or later. Before v2.1.281, some sessions, such as those on Amazon Bedrock or with telemetry disabled, [couldn’t load `AGENTS.md`](#when-agents-md-support-is-unavailable) either, so on those versions update to v2.1.281 or later.
3. Type `/config` in your session to open the settings panel and confirm **Project instructions** isn’t set to `claude-md` or `managed-only`. If you don’t see the setting there at all, your session is one that [can’t load `AGENTS.md`](#when-agents-md-support-is-unavailable).
To check whether Claude read your `AGENTS.md`, run `/memory` and look for its path in the list. Before v2.1.280, `/memory` and `/context` didn’t list an `AGENTS.md` that Claude read directly. On those versions, ask Claude what its project instructions say instead. If you want to keep the `CLAUDE.md` you found, or your session can’t load `AGENTS.md`, [add a `CLAUDE.md` next to your `AGENTS.md` that imports it](#share-one-file-with-other-coding-tools).
[](#i-don’t-know-what-auto-memory-saved)
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)
My CLAUDE.md is too large
Files over 200 lines consume more context and may reduce adherence. Claude Code skips a file over 4 MiB. Use [path-scoped rules](#path-specific-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](#import-additional-files) helps organization but doesn’t reduce context, since imported files load at launch. If one of your instruction files is over the recommended length, you see a warning at startup and when you run `/status`. You also see a warning when files that are each within that length add up past a combined limit at session start. Each CLAUDE.md, rules file, and `@path` import counts as a separate file. The [`/doctor`](commands.md#all-commands) checkup proposes trims for a checked-in CLAUDE.md: it cuts content Claude can derive from the codebase, such as directory layouts, dependency lists, and architecture overviews, and keeps pitfalls, rationale, and conventions that differ from tool defaults. The trim check requires Claude Code v2.1.206 or later.
[](#instructions-seem-lost-after-/compact)
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 and rules with [`paths:` frontmatter](#path-specific-rules) reload as Claude reads files they apply to. If an instruction disappeared after compaction, it was given only in conversation, lives in a nested CLAUDE.md that hasn’t reloaded yet, or is a path-scoped rule that hasn’t matched a file since. Add conversation-only instructions to CLAUDE.md to make them persist. See [What survives compaction](context-window.md#what-survives-compaction) for the full breakdown. See [Write effective instructions](#write-effective-instructions) for guidance on size, structure, and specificity.
[](#related-resources)
Related resources
- [Debug your configuration](debug-your-config.md): diagnose why CLAUDE.md or settings aren’t taking effect
- [Skills](../08-Plugins-Skills/skills.md): package repeatable workflows that load on demand
- [Settings](settings.md): configure Claude Code behavior with settings files
- [Subagent memory](../09-Agents-Patterns/sub-agents.md#enable-persistent-memory): let subagents maintain their own auto memory
---
## Claude Code on Microsoft Foundry - Claude Code Docs
Source: https://code.claude.com/docs/en/microsoft-foundry
Path: 02-Claude-Code-CLI/microsoft-foundry.md
## On this page
- [Prerequisites](#prerequisites)
- [Setup](#setup)
- [1. Provision Microsoft Foundry resource](#1-provision-microsoft-foundry-resource)
- [2. Configure Azure credentials](#2-configure-azure-credentials)
- [3. Configure Claude Code](#3-configure-claude-code)
- [4. Pin model versions](#4-pin-model-versions)
- [5. Run Claude Code](#5-run-claude-code)
- [Azure RBAC configuration](#azure-rbac-configuration)
- [Troubleshooting](#troubleshooting)
- [Additional resources](#additional-resources)
Deployment
# Claude Code on Microsoft Foundry
Copy pageCopy page
Learn about configuring Claude Code through Microsoft Foundry, including setup, configuration, and troubleshooting.
Copy pageCopy page
[](#prerequisites)
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](#4-pin-model-versions) before rolling out.
[](#setup)
Setup
[](#1-provision-microsoft-foundry-resource)
1. Provision Microsoft Foundry resource
First, create a Claude resource in Azure:
1. Go to the [Microsoft Foundry portal](https://ai.azure.com/)
2. Create a new resource, noting your resource name
3. Create deployments for the Claude models, noting the deployment name you give each; you’ll set these names as the model variables in step 4:
- Claude Opus
- Claude Sonnet
- Claude Haiku
When you configure a deployment, you also choose its [hosting option](https://code.claude.com/docs/20-Models/build-with-claude-claude-in-microsoft-foundry-cac680095c.md#hosting-options), which determines whether inference runs on Azure or on Anthropic infrastructure.
[](#2-configure-azure-credentials)
2. Configure Azure credentials
Claude Code supports three authentication methods for Microsoft Foundry. Choose the method that best fits your security requirements. **Option A: API key authentication**
1. Navigate to your resource in the Microsoft Foundry portal
2. Go to the **Endpoints and keys** section
3. Copy **API Key**
4. Set the environment variable, replacing `your-azure-api-key` with the key you copied:
```python
export ANTHROPIC_FOUNDRY_API_KEY=your-azure-api-key
```
**Option B: Microsoft Entra ID authentication** When neither `ANTHROPIC_FOUNDRY_API_KEY` nor `ANTHROPIC_FOUNDRY_AUTH_TOKEN` is set, Claude Code automatically uses the Azure SDK [default credential chain](https://learn.microsoft.com/en-us/azure/developer/javascript/sdk/authentication/credential-chains#defaultazurecredential-overview). This supports a variety of methods for authenticating local and remote workloads. On local environments, you commonly may use the Azure CLI:
```python
az login
```
**Option C: Bearer token authentication** Claude Code sends the value of `ANTHROPIC_FOUNDRY_AUTH_TOKEN` on every request as the `Authorization: Bearer` header. Use this option when another process, such as a host application or a sign-in script, has already obtained an access token for you. Requires Claude Code v2.1.203 or later. Set the variable to a bearer token that Microsoft Entra ID issued for your resource:
```python
export ANTHROPIC_FOUNDRY_AUTH_TOKEN=your-entra-access-token
```
`ANTHROPIC_FOUNDRY_AUTH_TOKEN` takes precedence over `ANTHROPIC_FOUNDRY_API_KEY` and over the default credential chain.
When using Microsoft Foundry, the `/logout` command is unavailable since authentication is handled through Azure credentials.
[](#3-configure-claude-code)
3. Configure Claude Code
Set the following environment variables to enable Microsoft Foundry:
```python
# 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)
4. Pin model versions
Pin specific model versions for every deployment. Without pinning, model aliases such as `sonnet` and `opus` resolve to Claude Code’s built-in default for Microsoft Foundry, which can lag the newest release and may not yet be available in your account. Microsoft Foundry has no startup model check, so requests fail when the default is unavailable. 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 Microsoft Foundry resolves to Opus 4.6. Set it to the ID of a newer Opus model, such as Opus 4.8:
```python
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'
export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-5'
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 Microsoft 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](../20-Models/about-claude-models-overview.md). See [Model configuration](model-config.md#pin-models-for-third-party-deployments) for the full list of environment variables. [Prompt caching](prompt-caching.md) 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:
```python
export ENABLE_PROMPT_CACHING_1H=1
```
To set different TTLs for your main conversation and for the requests Claude Code makes outside it, [choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself).
[](#5-run-claude-code)
5. Run Claude Code
With the environment variables set, start Claude Code from your project directory:
```python
claude
```
Claude Code reads `CLAUDE_CODE_USE_FOUNDRY` and the other Microsoft Foundry variables from the environment and connects to your Azure resource on the first prompt. Unlike Amazon Bedrock and Google Cloud’s Agent Platform, Microsoft Foundry has no interactive setup wizard, so the environment variables in steps 3 and 4 are the only configuration path. To verify your setup, run `/status` inside Claude Code. The API provider line shows `Microsoft Foundry`, along with the resource name or base URL you configured.
[](#azure-rbac-configuration)
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:
```python
{
"permissions": [
{
"dataActions": [
"Microsoft.CognitiveServices/accounts/providers/*"
]
}
]
}
```
For details, see [Microsoft Foundry RBAC documentation](https://learn.microsoft.com/en-us/azure/ai-foundry/concepts/rbac-azure-ai-foundry).
[](#troubleshooting)
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`.
If requests fail with repeated connection errors on the first prompt:
- Check that `ANTHROPIC_FOUNDRY_RESOURCE` is set to your actual resource name rather than a placeholder. Claude Code builds the endpoint URL from this value, so an incorrect name points at a host that doesn’t exist.
[](#additional-resources)
Additional resources
- [Microsoft Foundry documentation](https://learn.microsoft.com/en-us/azure/ai-foundry/what-is-azure-ai-foundry)
- [Microsoft Foundry models](https://ai.azure.com/explore/models)
- [Microsoft Foundry pricing](https://azure.microsoft.com/en-us/pricing/details/ai-foundry/)
---
## Model configuration - Claude Code Docs
Source: https://code.claude.com/docs/en/model-config
Path: 02-Claude-Code-CLI/model-config.md
## On this page
- [Available models](#available-models)
- [Model aliases](#model-aliases)
- [Work with Fable](#work-with-fable)
- [Fable and usage credits](#fable-and-usage-credits)
- [Setting your model](#setting-your-model)
- [Set a default model for new sessions](#set-a-default-model-for-new-sessions)
- [A new session starts on a different model than you picked](#a-new-session-starts-on-a-different-model-than-you-picked)
- [Restrict model selection](#restrict-model-selection)
- [Surface coverage](#surface-coverage)
- [Default model behavior](#default-model-behavior)
- [Enforce the allowlist for the Default model](#enforce-the-allowlist-for-the-default-model)
- [Control the model users run on](#control-the-model-users-run-on)
- [Merge behavior](#merge-behavior)
- [Mantle model IDs](#mantle-model-ids)
- [Block specific models or versions](#block-specific-models-or-versions)
- [Organization model restrictions](#organization-model-restrictions)
- [Organization default model](#organization-default-model)
- [Organization effort limits](#organization-effort-limits)
- [Special model behavior](#special-model-behavior)
- [default model setting](#default-model-setting)
- [opusplan model setting](#opusplan-model-setting)
- [Fallback model chains](#fallback-model-chains)
- [Automatic model fallback](#automatic-model-fallback)
- [Check what triggered fallback](#check-what-triggered-fallback)
- [Ask before switching](#ask-before-switching)
- [Enable fallback on Bedrock, Agent Platform, and Foundry](#enable-fallback-on-bedrock-agent-platform-and-foundry)
- [Security research and biology workloads](#security-research-and-biology-workloads)
- [Adjust effort level](#adjust-effort-level)
- [Choose an effort level](#choose-an-effort-level)
- [Use ultrathink for one-off deep reasoning](#use-ultrathink-for-one-off-deep-reasoning)
- [Set the effort level](#set-the-effort-level)
- [Adaptive reasoning and fixed thinking budgets](#adaptive-reasoning-and-fixed-thinking-budgets)
- [Extended thinking](#extended-thinking)
- [Extended context](#extended-context)
- [Sonnet 5.5 and Sonnet 5 context window](#sonnet-5-5-and-sonnet-5-context-window)
- [Context window and auto-compaction](#context-window-and-auto-compaction)
- [Set the auto-compact window](#set-the-auto-compact-window)
- [Default auto-compact thresholds](#default-auto-compact-thresholds)
- [Correct the window for a gateway or custom model ID](#correct-the-window-for-a-gateway-or-custom-model-id)
- [Checking your current model](#checking-your-current-model)
- [Add a custom model option](#add-a-custom-model-option)
- [Environment variables](#environment-variables)
- [Pin models for third-party deployments](#pin-models-for-third-party-deployments)
- [Customize pinned model display and capabilities](#customize-pinned-model-display-and-capabilities)
- [Override model IDs per version](#override-model-ids-per-version)
- [Prompt caching configuration](#prompt-caching-configuration)
- [Version history](#version-history)
Model and responses
# Model configuration
Copy pageCopy page
Configure which model Claude Code uses, effort levels, extended context, and the auto-compact window
Copy pageCopy page
[](#available-models)
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](../20-Models/about-claude-models-overview.md)**
- Amazon Bedrock: an inference profile ARN
- Microsoft Foundry: a deployment name
- Google Cloud’s Agent Platform: a version name
For guidance on which model and effort level fit different kinds of work, see [Choosing a Claude model and effort level in Claude Code](https://claude.com/blog/claude-model-and-effort-level-in-claude-code) on the blog.
`ANTHROPIC_BASE_URL` changes where requests are sent, not which model answers them. To route Claude through an LLM gateway, see [LLM gateways](../13-Enterprise-Admin/llm-gateway.md).
[](#model-aliases)
Model aliases
Use a model alias to select model settings without remembering exact version numbers:
| Model alias | Behavior |
|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **`default`** | Special value that clears any model override and reverts to the [runtime default for your account](#default-model-setting). Not itself a model alias |
| **`best`** | Uses the model the [`fable` alias resolves to](#fable-alias-resolution) where Fable is available to you, otherwise the same model as `opus` |
| **`fable`** | Uses the [Fable model for your provider](#fable-alias-resolution) for your hardest and longest-running tasks |
| **`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](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model) for long sessions. No effect when `sonnet` already resolves to Sonnet 5.5 or Sonnet 5 with their native 1M window; behind an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), selects the 1M window for that model |
| **`opus[1m]`** | Uses Opus with a [1 million token context window](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model) for long sessions |
| **`opusplan`** | Special mode that uses `opus` during plan mode, then switches to `sonnet` for execution |
The version that the `opus` and `sonnet` aliases resolve to depends on the provider:
| Provider | `opus` | `sonnet` |
|:----------------------------------------------------------|:---------|:-----------|
| Anthropic API | Opus 5.5 | Sonnet 5.5 |
| [Claude Platform on AWS](claude-platform-on-aws.md) | Opus 5.5 | Sonnet 4.6 |
| Amazon Bedrock, Google Cloud’s Agent Platform | Opus 5.5 | Sonnet 4.5 |
| Microsoft Foundry | Opus 4.6 | Sonnet 4.5 |
Unless you set `ANTHROPIC_DEFAULT_FABLE_MODEL`, the `fable` alias resolves to Fable 5.1, except in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions, where `fable` and `best` resolve to Fable 5. A gateway that isn’t configured to serve `claude-fable-5-1` rejects requests for that model. To use Fable 5.1 through a gateway that serves it, select it with `/model claude-fable-5-1`. Where an alias resolves to an older model, newer models are available by selecting the full model name explicitly or setting `ANTHROPIC_DEFAULT_OPUS_MODEL` or `ANTHROPIC_DEFAULT_SONNET_MODEL`. Earlier versions resolve these aliases to older models. For the version at which each alias changed, see [Version history](#version-history). 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-5-5`, or set the corresponding environment variable like `ANTHROPIC_DEFAULT_OPUS_MODEL`.
Sonnet 5.5 requires Claude Code v2.1.284 or later, and Opus 5.5 requires v2.1.280 or later. If a request for one of them from an older version fails, see [Claude Code does not support this model](errors.md#claude-code-does-not-support-this-model). Run `claude update` to upgrade.
[](#work-with-fable)
Work with Fable
[Claude Fable 5.1](../20-Models/about-claude-models-overview.md) and Claude Fable 5 are the most capable models in Claude Code, suited to tasks larger than a single sitting. They sustain long autonomous sessions, investigate before acting, and verify their work more often than smaller models. Fable 5.1 is the newer release. Neither Fable model is the account-type default on any plan or provider. Select one explicitly:
- **Fable 5.1**: run `/model fable`, or launch with `claude --model fable`. In [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions, where the alias resolves to Fable 5, run `/model claude-fable-5-1` instead.
- **Fable 5**: select it by model ID. On the Anthropic API, run `/model claude-fable-5` or launch with `claude --model claude-fable-5`. On other providers, use your provider’s Fable 5 model ID or [pin it](#pin-models-for-third-party-deployments) with `ANTHROPIC_DEFAULT_FABLE_MODEL`.
If you connect to the Anthropic API directly and your user settings hold `claude-fable-5` or `claude-fable-5[1m]` as the model, for example because you selected Fable in the `/model` picker before v2.1.257, Claude Code changes that saved value to the `fable` or `fable[1m]` alias the first time you run v2.1.257 or later. The startup model line shows `(auto-updated)` once. A `claude-fable-5` value in project, local, or managed settings stays as it is. Requests that a Fable model’s safety classifiers flag, most often in cybersecurity and biology domains, trigger [automatic model fallback](#automatic-model-fallback). To get the most from Fable:
- **Describe the outcome, not the steps**: hand it the result you want and let it plan the path. To keep it working toward that outcome, [set a goal](goal.md).
- **Hand it ambiguous problems**: root-cause investigations, outage debugging, and architecture decisions are where the extra investigation and verification pay off.
- **Skip the verification reminders**: it verifies its own work with less prompting, so reminders to test or check are usually unnecessary.
- **Size up larger tasks**: give it work you would normally break into pieces. It holds long sessions without losing the thread.
Fable 5.1 requires Claude Code v2.1.257 or later. If a request for it from an older version fails, see [Claude Code does not support this model](errors.md#claude-code-does-not-support-this-model). Run `claude update` to upgrade. For availability under zero data retention, see [Model availability under ZDR](zero-data-retention.md#model-availability-under-zdr).
On the Anthropic API, a Fable model appears in the `/model` picker unless [`availableModels`](#restrict-model-selection) or [organization model restrictions](#organization-model-restrictions) exclude it. When your organization can’t use Fable at all, for example under [zero data retention](zero-data-retention.md#model-availability-under-zdr), the row stays in the picker grayed out, with a note on why.
[](#fable-and-usage-credits)
Fable and usage credits
Depending on your plan and seat tier, Fable usage can bill to [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) instead of drawing on your plan’s included limits. When it does, the `/model` picker shows “Requires usage credits” on the Fable row. To manage usage credits, see [Add usage credits to your subscription](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription). In interactive sessions, Claude Code shows a consent prompt before a Fable request bills usage credits. Members of Enterprise plans with organization billing don’t see the prompt. You can continue on Fable using usage credits or switch to your default model. You can also dismiss the prompt:
- In the `/model` picker, you keep your current model.
- Mid-session, Claude Code continues the turn on your default model.
After you choose to continue on Fable using usage credits, Claude Code doesn’t show the prompt again. In a session with [Remote Control](remote-control.md) connected, a [background session](../09-Agents-Patterns/agent-view.md), or an [agent team](../09-Agents-Patterns/agent-teams.md) teammate’s session, nobody may be at the terminal, so Claude Code holds the mid-session consent prompt for the [`dialogExpiry`](settings-reference.md#dialogexpiry) deadline, five minutes by default. If nobody has answered by the deadline, Claude Code ends the turn without sending the request and adds a notice to the transcript, which the Remote Control client also shows. Your model selection is unchanged, and Claude Code asks for consent again on your next message. What you can do while the prompt is waiting depends on the session:
- With Remote Control connected or in a teammate’s session, press any key at the terminal to cancel the deadline, and Claude Code waits for your answer.
- In a background session, answer before the deadline.
- If you send a new message from the remote client before anyone has typed at the terminal, Claude Code ends the turn the same way, and your new message starts the next turn. After someone types at the terminal, Claude Code keeps waiting for the answer and queues your new message behind it.
In [non-interactive mode](headless.md) with the `-p` flag and through the Agent SDK, Claude Code never shows the consent prompt. When a Fable request there would bill to usage credits, Claude Code bills it without asking.
[](#setting-your-model)
Setting your model
You can configure your model in several ways, listed in order of priority:
1. **During session**: use `/model <alias|name>` to switch immediately, or run `/model` with no argument to open the picker. See [when Claude Code asks you to confirm the switch](prompt-caching.md#switching-models)
2. **At startup**: launch with `claude --model <alias|name>`
3. **Environment variable**: set `ANTHROPIC_MODEL=<alias|name>`
4. **Settings**: configure permanently in your settings file using the `model` field
5. **[Default for new sessions](#set-a-default-model-for-new-sessions)**: set `ANTHROPIC_DEFAULT_MODEL=<alias|name>`
`/model` saves your choice as the default for new sessions by writing the `model` field in your user settings. In the picker:
- `Enter`: switch model and save as your default
- `s`: switch model for this session only and leave your default unchanged. To use a different key, rebind [`modelPicker:thisSessionOnly`](keybindings.md#model-picker-actions)
Typing `/model <name>` directly behaves like `Enter`. To switch for this session only, open the picker with `/model` and press `s` on the model’s row. On an Enterprise plan, when you’re logged in with your claude.ai account and save a default with `/model`, Claude Code also records the choice on that account. This requires Claude Code v2.1.280 or later.
- When your admin hasn’t set an [organization default model](#organization-default-model), the [Default option](#default-model-setting) can resolve to the recorded model, and when it does, the picker’s Default row shows that model’s name.
- If [model restrictions](#restrict-model-selection) exclude the recorded model or it isn’t available to your account, and your admin hasn’t set an organization default model, the Default option resolves as if nothing were recorded.
- If you choose Default or `opusplan` in `/model`, the recorded choice doesn’t change.
If you switch models with `/model`, the switch also reaches [subagents that inherit the main conversation’s model](../09-Agents-Patterns/sub-agents.md#choose-a-model), because Claude Code resolves their model from the one your session is using when Claude starts them. Switch to Opus before Claude delegates research or test runs to one of them, and that work runs on Opus too. To keep a custom subagent on a smaller model, set `model` in its definition. If you set a model with `/model` in [non-interactive mode](headless.md), with the `-p` flag, your choice applies to the current session only and isn’t saved as your default; `/model` in that mode requires Claude Code v2.1.205 or later. Project and managed settings still take precedence and reapply on the next launch. An [organization default model](#organization-default-model) that your admin has configured to override user selection also reapplies on the next launch. In v2.1.144 through v2.1.152, `/model` applied to the current session only and `d` in the picker saved a default. The `--model` flag and `ANTHROPIC_MODEL` environment variable apply only to the session you launch with them. To run different models in different terminals at the same time, launch each one with its own `--model` flag rather than switching with `/model`. Prices in the `/model` picker appear when Claude Code talks to the Anthropic API, directly or through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) that proxies it, and the price on a row is the price of the model that row selects. On [third-party providers](third-party-integrations.md) such as Amazon Bedrock and on the [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md), your provider or gateway determines what you pay, so picker rows show no price. The price is a display label only; it doesn’t affect which model a row selects or what your provider bills. Before v2.1.206, [Claude Platform on AWS](claude-platform-on-aws.md) and gateway sessions showed Anthropic list prices, and a row could show the price of a different model than the one it selected. Resumed sessions started with `claude --resume`, `--continue`, or the `/resume` picker keep the model they were using when the transcript was saved, regardless of the current `model` setting. If the restored model has been retired or is excluded by [`availableModels`](#restrict-model-selection), the session falls through to the normal precedence order. This prevents another session’s `/model` choice from changing the model on resume. On providers that use provider-specific deployment IDs rather than Anthropic model IDs, such as Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, the transcript model isn’t restored at all and the session resolves its model through the normal precedence order. A model you pick for the new launch with `--model` or `ANTHROPIC_MODEL` still takes precedence over the restored model. As of v2.1.195, so does an [`ANTHROPIC_DEFAULT_OPUS_MODEL`](#environment-variables) family variable. [`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions) can too, under the conditions listed in its section. 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; the project or managed setting reapplies on the next launch. On platforms that embed Claude Code and set [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](env-vars.md), the host’s model configuration takes precedence over managed model settings, while a managed `availableModels` allowlist stays in force unless the host supplies its own; [Exceptions to managed settings precedence](settings.md#exceptions-to-managed-settings-precedence) says which keys and variables the host overrides. If you or your organization configure [PreModelSwitch hooks](../07-Hooks/hooks.md#premodelswitch), they run before a requested switch applies and can block it or ask you to confirm. When Claude Code can’t tell which PreModelSwitch hooks your organization’s [managed plugins](settings-reference.md#enabledplugins) deliver, for example because a managed plugin failed to load, it refuses the switch rather than apply it unchecked, and it checks again on each new attempt. See [Model switch was blocked by a PreModelSwitch hook](errors.md#model-switch-was-blocked-by-a-premodelswitch-hook) for the message and recovery. When you switch models through the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) `setModel()` method, through an app such as the [Desktop app](../16-Mobile-Desktop/desktop.md), or from a device connected through [Remote Control](remote-control.md), Claude Code checks the value at the switch:
- **Agent SDK or an app**: with Claude Code v2.1.268 or later, unless Claude Code accepts a model ID locally, as it does for your [custom model option](#add-a-custom-model-option), it confirms the ID with your provider the first time the session switches to it. The confirmation runs on every provider, and an ID your provider doesn’t offer is refused at the switch instead of failing on your next request.
- **Remote Control**: on the Anthropic API, Claude Code checks the value locally and sends no request.
See [Model is not a recognized model id](errors.md#model-is-not-a-recognized-model-id) and [Model not found](errors.md#model-not-found) for the messages. If you set the model with the `--model` flag, the `ANTHROPIC_MODEL` environment variable, or the `model` setting, Claude Code doesn’t check it up front, and a mistyped value produces [There’s an issue with the selected model](errors.md#theres-an-issue-with-the-selected-model) on the first request. When the requested model has a scheduled retirement date or is automatically remapped to a newer version, Claude Code shows a warning that names the requested model. Interactive sessions show it as a startup notice. From v2.1.182, the same warning is written to stderr in [non-interactive mode](headless.md) when using the default text output format. The check also covers a `model` set in [subagent frontmatter](../09-Agents-Patterns/sub-agents.md). The stderr warning is suppressed for `--output-format json` and `stream-json`; read the actual model from the `modelUsage` field of the [result message](headless.md#get-structured-output) instead. For example, start a session on Opus:
```python
claude --model opus
```
Then switch models from within the session:
```python
/model sonnet
```
Example settings file:
```python
{
"permissions": {
"allow": ["Bash(npm run lint)"]
},
"model": "opus"
}
```
[](#set-a-default-model-for-new-sessions)
Set a default model for new sessions
Set `ANTHROPIC_DEFAULT_MODEL=<alias|name>` to choose the model your sessions start on by default. Requires Claude Code v2.1.236 or later. Claude Code starts a new session on the variable’s model only when none of these selects a model:
- The `--model` flag
- `ANTHROPIC_MODEL`
- A `model` value in any settings file, including the choice you save with `/model`
- An [organization default model](#organization-default-model)
A choice you save with `/model` takes precedence over the variable on later launches too. With `ANTHROPIC_MODEL` set instead, Claude Code returns to that variable’s model on the next launch, whatever you saved with `/model`. Claude Code also resolves the Default option to the variable’s model, unless an organization default model applies. When the Default option resolves to the variable’s model, the Default row in the `/model` picker shows the label Set by ANTHROPIC_DEFAULT_MODEL. Claude Code ignores the variable in these cases, and the Default option resolves as if you hadn’t set it:
- You set it to `default`, `inherit`, `opusplan`, or `haiku`
- [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model) is on
- Your organization’s [model restrictions](#restrict-model-selection) exclude the model
- The model isn’t available to your account
When a new session would start on the variable’s model, a session you resume with `claude --resume`, `--continue`, or the `/resume` picker starts on it too. Claude Code doesn’t restore the model saved in that session’s transcript. Otherwise Claude Code doesn’t use the variable when you [resume a session](#setting-your-model).
[](#a-new-session-starts-on-a-different-model-than-you-picked)
A new session starts on a different model than you picked
When you pick a model with `/model` and your next session starts on something else, these are the usual causes:
- **You chose it for one session.** Pressing `s` in the picker, launching with `--model`, and running `/model` in non-interactive mode all apply to the current session and leave your saved default alone.
- **Something with higher priority sets the model.** A `model` value in project or managed settings, `ANTHROPIC_MODEL` in your shell, or an [organization default](#organization-default-model) your admin set to override user choices applies again at every launch. Your `/model` choice is still saved; it’s outranked. When project or managed settings set the model, the startup header names the file.
- **Claude Code couldn’t save your choice.** `/model` writes `model` to `~/.claude/settings.json`. If you can’t write to that file, for example because another tool generates it or links it to a read-only copy, the model you chose lasts for the session and the next launch reads the old value. Set `model` in the tool that generates the file, or make the file writable. See [A change you made in Claude Code is lost in new sessions](settings.md#a-change-you-made-in-claude-code-is-lost-in-new-sessions).
- **You resumed a session.** A session you resume with `claude --resume` or `--continue` usually [keeps the model it was using](#setting-your-model) rather than your current default.
[](#restrict-model-selection)
Restrict model selection
Administrators can use `availableModels` in [managed or policy settings](../13-Enterprise-Admin/managed-settings.md) to restrict which models users can select. Entries match a model family such as `sonnet`, a version prefix such as `claude-sonnet-4-5`, or a full model ID such as `claude-sonnet-4-5-20250929`. A version prefix also matches later model IDs that extend it with another segment, so `claude-fable-5` permits both Fable 5 and Fable 5.1, while `claude-fable-5-1` permits Fable 5.1 only. To block a model the list permits, or to make each model ID entry permit only the version it names, see [Block specific models or versions](#block-specific-models-or-versions). On platforms that embed Claude Code and set [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](env-vars.md), the host’s model configuration takes precedence over managed model settings, while a managed `availableModels` allowlist stays in force unless the host supplies its own; [Exceptions to managed settings precedence](settings.md#exceptions-to-managed-settings-precedence) says which keys and variables the host overrides. When `availableModels` is set, the allowlist applies everywhere a user can specify a model:
- **Main session model**: `/model`, the `--model` flag, the `ANTHROPIC_MODEL` environment variable, the `model` setting, [`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions), and the model restored when [resuming a session](#setting-your-model)
- **Alias resolution**: the `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, and `ANTHROPIC_DEFAULT_FABLE_MODEL` environment variables cannot redirect an allowed alias to a model outside the list
- **Fast mode**: `/fast` refuses to toggle when it would implicitly switch to an Opus model outside the list, with the message “is not in your organization’s allowed models”
- **Subagent and teammate models**: the `model` field in [subagent](../09-Agents-Patterns/sub-agents.md#choose-a-model) frontmatter, the Agent tool’s `model` parameter, [agent team](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) teammate models, `CLAUDE_CODE_SUBAGENT_MODEL`, and, on v2.1.197 and earlier, the model picker in the `/agents` wizard
- **Skill and command models**: the `model` frontmatter in [skills and commands](../08-Plugins-Skills/skills.md)
- **Advisor model**: the configured [`advisorModel`](advisor.md) setting and the `--advisor` flag
- **Background agent model**: the model selected in the [dispatch picker](../09-Agents-Patterns/agent-view.md)
On the Anthropic API and [Claude Platform on AWS](claude-platform-on-aws.md), a model family alias, `opus`, `sonnet`, `haiku`, or `fable`, resolves to its usual model when the allowlist permits that model. When the allowlist blocks that model, Claude Code substitutes the newest version of the family that the allowlist permits and shows a notice naming both the requested and substituted models. With `["sonnet", "claude-opus-4-6"]`, for example, both `/model opus` and `--model opus` select Claude Opus 4.6, the newest permitted Opus. Before v2.1.205, an alias whose newest released version was outside the list was rejected or replaced like any other blocked selection, even when the list permitted an older version. The substitution needs a permitted version to land on: when the allowlist permits no version of the alias’s family, the alias follows the rejection and replacement behavior below like any other blocked value. Claude Code handles any other blocked selection according to where the model was set:
- **`/model`**: Claude Code rejects the switch with an error
- **`--model` flag, `ANTHROPIC_MODEL`, or the `model` setting**: Claude Code replaces the value at startup with a warning naming both the requested and substituted models, and the session starts on the default model
- **[`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions)**: Claude Code ignores the variable
- **Subagent or teammate override**: Claude Code runs the subagent or teammate on a fallback model rather than failing the request. See [Choose a model](../09-Agents-Patterns/sub-agents.md#choose-a-model) for the subagent fallback and [Specify teammates and models](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) for the teammate fallback. In interactive sessions, Claude Code warns you when it substitutes a subagent’s model, by this fallback or by the newest-permitted-version substitution above, naming the requested and substituted models; it doesn’t report a teammate’s fallback. Where the newest-permitted-version substitution above operates, a blocked family alias follows it instead. Before v2.1.222, an alias fell back like any other blocked value on every provider
- **Skill or command override**: Claude Code ignores the override, including a blocked family alias, and the skill or command runs on the session model. A skill or command that [runs in a subagent](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent) follows the subagent behavior above instead
- **`advisorModel` setting**: the advisor is disabled for the session
- **`--advisor` flag**: Claude Code exits with an error at launch. In a [background session](../09-Agents-Patterns/agent-view.md), it starts the session without the advisor instead of exiting
Claude Code hides excluded models from the `/model` picker. A full model ID in the list that has no built-in picker row, such as an older version that the list pins, appears in the `/model` picker as its own labeled row, unless Claude Code replaces the built-in options with a [`modelPicker`](settings-reference.md#modelpicker) lineup. Before v2.1.199, such an ID was selectable only by typing `/model <id>`. Model changes that Claude Code makes on your behalf are checked the same way:
- **[Fallback model chains](#fallback-model-chains)**: entries outside the allowlist are dropped
- **Plan-mode upgrades**: on the Anthropic API and Claude Platform on AWS, an upgrade such as [`opusplan`](#opusplan-model-setting) to an excluded model uses the newest permitted version of the upgrade family. On providers with provider-specific model IDs, and when no version is permitted, the upgrade is skipped and planning continues on the session’s model
- **[Automatic model fallback](#automatic-model-fallback)**: a fallback whose target is excluded does not run, so the flagged request ends with a refusal instead
- **[Auto mode classifier](permission-modes.md#eliminate-prompts-with-auto-mode)**: the classifier’s Claude Sonnet 5 default applies only when the allowlist permits Sonnet 5. When it’s excluded, the classifier runs on the session’s model, which the allowlist already governs, or on an Opus model when the session runs on a [Fable model](#work-with-fable). On providers other than the Anthropic API, that Opus fallback runs on the provider’s default Opus model without consulting the allowlist. Requires Claude Code v2.1.210 or later
- **[Fast mode](fast-mode.md)**: enabling fast mode is refused when the model the session would run on afterward is outside the allowlist
```python
{
"availableModels": ["sonnet", "haiku"]
}
```
[](#surface-coverage)
Surface coverage
Every surface enforces the allowlist it receives. Which delivery mechanism reaches each surface differs:
| Delivery mechanism | CLI and IDE | Desktop local sessions | Web, mobile, and cloud sessions | Agent SDK and non-interactive | Cowork |
|:-----------------------------------------------------------------------------------|:------------|:-----------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------|:-------------------------------------------------------------------------------------------|
| [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) from the admin console | Enforced | Enforced | Enforced, except in [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions | Enforced | Remote Cowork sessions: the server checks the model. On the user’s machine: not delivered. |
| [MDM or managed settings files](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) | Enforced | Enforced | Not delivered in Anthropic-hosted environments; in [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md), enforced from the runner image per [how Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) | Enforced | Enforced where deployed |
- [Cloud sessions](claude-code-on-the-web.md), including those you start from the Desktop app, run on Anthropic-managed VMs by default: settings deployed to your device do not reach them, so deliver the allowlist through server-managed settings. Sessions your organization routes to a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) run on your own compute and also read the managed settings file in the runner image. [How Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) says when that file applies. A mid-session model switch in a cloud session is rejected when the requested model is excluded by the allowlist. When the `availableModels` list in your server-managed settings is non-empty, the server rejects a request to start a cloud session at claude.ai/code or from the Desktop app on a model the list excludes.
- [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions run in cloud environments but don’t receive server-managed settings; in a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md), they still read the managed settings file in the runner image. To set the model for those sessions, see [Choose the model for a scope](https://claude.com/docs/claude-tag/admins/customize#choose-the-model-for-a-scope) in the Claude Tag admin guide.
- Cowork, the agentic-work tab in the Claude Desktop app, runs its sessions on Claude Code but, by design, does not receive server-managed settings from the claude.ai admin console. When the `availableModels` list in your server-managed settings is non-empty and a user picks a model outside it, the server rejects that model for a remote Cowork session. A managed settings file applies to Cowork sessions when it is present where the session runs; remote Cowork sessions run on Anthropic-managed VMs, where a device-deployed file is not present.
- Sessions on [third-party providers](../13-Enterprise-Admin/server-managed-settings.md#platform-availability) such as Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and [Claude Platform on AWS](claude-platform-on-aws.md) do not receive server-managed settings, so deliver the allowlist through MDM or managed settings files there.
- Server-managed delivery also requires the session to authenticate with an [eligible login or key](../13-Enterprise-Admin/server-managed-settings.md#platform-availability). Fleets that generate keys only through an [`apiKeyHelper`](settings-reference.md#apikeyhelper) script should deliver the allowlist through MDM or managed settings files.
- The Desktop Code tab also hosts [SSH sessions](../16-Mobile-Desktop/desktop.md#ssh-sessions), which read the managed settings file from the remote host they run on. See [Desktop managed settings](../16-Mobile-Desktop/desktop.md#managed-settings).
- The model pickers on claude.ai and in the Desktop app hide or grey out models excluded by your organization’s allowlist. The picker state is a convenience for users; it doesn’t enforce the allowlist.
[](#default-model-behavior)
Default model behavior
With the default prefix matching, `availableModels` on its own leaves the Default option on the system’s [runtime default](#default-model-setting) for the account until you also set [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model). If that default is a model you intend to restrict, set `enforceAvailableModels` as well, or [block that model](#block-specific-models-or-versions). With `availableModels: []`, named model selections are blocked and `enforceAvailableModels` has no effect.
[](#enforce-the-allowlist-for-the-default-model)
Enforce the allowlist for the Default model
Set `enforceAvailableModels: true` alongside a non-empty `availableModels` in managed settings to extend the allowlist to the Default option. This requires Claude Code v2.1.175 or later.
```python
{
"availableModels": ["sonnet", "haiku"],
"enforceAvailableModels": true
}
```
For a member with no model [recorded on their account](#setting-your-model), the Default option resolves to the account-type default, or to the [organization default model](#organization-default-model) when an admin has set one. When that model is not in the allowlist, the Default option instead resolves to the first `availableModels` entry that names an allowed, available model, and the `/model` picker’s Default row shows that model. This applies everywhere the default is reached: session startup, selecting Default in `/model`, the `"default"` keyword in [fallback model chains](#fallback-model-chains), and the fallback used when an excluded selection is dropped. A model recorded on a member’s account is checked against `availableModels` too; [Setting your model](#setting-your-model) describes how the Default option treats it. `enforceAvailableModels` remaps the Default option only when `availableModels` is non-empty. When `availableModels` is non-empty but no entry resolves to an allowed and available model, enforcement is skipped with a warning visible only under `--debug`. Keep at least one guaranteed-available entry in the list to avoid this. Deploy both keys together in the highest-ranked managed source you deliver. By default Claude Code reads only that source, so a pair placed in a managed settings file is ignored when the admin console delivers any settings; under the opt-in merge in [how Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources), Claude Code still ignores a `modelOverrides` map from a source ranked below the one that sets `availableModels`.
[](#control-the-model-users-run-on)
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’s [runtime default](#default-model-setting) regardless of what `model` is set to, unless [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model) or the [keys that block specific versions](#block-specific-models-or-versions) apply to it. To fully control the model experience, combine these settings:
- **`availableModels`**: restricts which named models users can switch to
- **`enforceAvailableModels`**: extends the `availableModels` allowlist to the Default option, so Default cannot resolve to a model outside the list
- **`deniedModels`** and **`availableModelsMatch`**: [block specific versions](#block-specific-models-or-versions) that an `availableModels` entry would otherwise permit
- **`model`**: sets the initial model selection when a session starts
- **`ANTHROPIC_DEFAULT_SONNET_MODEL`** / **`ANTHROPIC_DEFAULT_OPUS_MODEL`** / **`ANTHROPIC_DEFAULT_HAIKU_MODEL`** / **`ANTHROPIC_DEFAULT_FABLE_MODEL`**: control what the `sonnet`, `opus`, `haiku`, and `fable` aliases resolve to, and which version the [account-type default](#default-model-setting) uses
This example starts users on Sonnet 4.5, limits the picker to Sonnet and Haiku, and ensures Default resolves to a model on the allowlist rather than the tier default:
```python
{
"model": "claude-sonnet-4-5",
"availableModels": ["claude-sonnet-4-5", "haiku"],
"enforceAvailableModels": true,
"env": {
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-5"
}
}
```
Without `enforceAvailableModels` or the `env` block, a user who selects Default in the picker gets the [runtime default](#default-model-setting) rather than the version pinned in `model`. The two settings cover different scopes: `enforceAvailableModels` makes Default obey the allowlist, while the `env` block pins which version a permitted alias such as `sonnet` resolves to. Use `enforceAvailableModels` alone when restricting model families is enough; add the `env` block when you also need to pin a specific version.
[](#merge-behavior)
Merge behavior
When the managed settings Claude Code applies define `availableModels`, that list alone applies, apart from a [host platform that supplies its own](settings.md#exceptions-to-managed-settings-precedence): entries in user, project, or local settings cannot extend it, and Claude Code never merges `availableModels` across managed sources either; [how Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) says which source’s list applies. Otherwise, lists from user, project, and local settings are [concatenated and deduplicated](settings.md#settings-precedence) like other array settings. Before Claude Code v2.1.175, entries from lower-precedence scopes merged into the managed list instead of being replaced by it. Within the effective list, an entry naming a specific model in a family, whether a version prefix or a full model ID, disables that family’s wildcard entry: `["sonnet", "claude-sonnet-4-5"]` allows only Sonnet 4.5 versions, not every Sonnet model.
[](#mantle-model-ids)
Mantle model IDs
When the [Amazon Bedrock Mantle endpoint](amazon-bedrock.md#use-the-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 matching described in [Pin models for third-party deployments](#pin-models-for-third-party-deployments). The setting still restricts the picker to listed entries, and a Mantle ID embeds a family name, so it counts as a specific entry and disables that family’s wildcard: alongside any Mantle IDs, list the version prefixes or full IDs you want to keep selectable. See [Merge behavior](#merge-behavior).
[](#block-specific-models-or-versions)
Block specific models or versions
An `availableModels` entry such as `claude-opus-5` also permits later releases that extend it, such as Opus 5.5, as soon as Claude Code supports them. Two managed settings let you hold a release back, and both require Claude Code v2.1.283 or later:
- [`deniedModels`](settings-reference.md#deniedmodels): list the models to block. A listed model is blocked even when `availableModels` permits it, and the key also works with no allowlist at all. A release that no entry blocks stays permitted
- [`availableModelsMatch`](settings-reference.md#availablemodelsmatch): set it to `"exact"` so that each model ID in `availableModels` permits only the version it names. A newer version of a listed model ID then stays blocked until you add it to the list
Earlier versions ignore both keys, so also set [`requiredMinimumVersion`](settings-reference.md#requiredminimumversion) to keep those versions from starting. This example permits Opus and Sonnet models and blocks Opus 5.5 in every spelling, including dated and provider-specific IDs:
```python
{
"availableModels": ["opus", "sonnet"],
"deniedModels": ["claude-opus-5-5"]
}
```
A blocked model, whether `deniedModels` names it or an `"exact"` list omits it, is treated as a blocked selection everywhere [the allowlist applies](#restrict-model-selection). It is hidden from the `/model` picker, and `/model <name>` rejects it. If you name a blocked model ID with `--model`, `ANTHROPIC_MODEL`, or the `model` setting, Claude Code drops it at startup and resolves the Default option instead. If a [hook](../07-Hooks/hooks.md) or background request names a model that `deniedModels` blocks, such as an agent hook’s `model` field, that request runs on the session’s model instead. The Default option follows both keys too, whether or not you set [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model). If you set it with a non-empty `availableModels`, a blocked default counts as a model outside the allowlist. Otherwise, a Default option that would resolve to a blocked model steps down in this order:
1. The newest permitted version of the same family
2. The newest permitted model of each lower-cost family in turn: Sonnet, then Haiku
3. The first `availableModels` entry that names a permitted model
If none of those is permitted, a session starting on the Default option [refuses to start](errors.md#managed-settings-block-the-default-model) with an error that names the key to fix. An `"exact"` list affects the Default option only when the managed `availableModels` list names at least one model or family. Claude Code reads both keys from managed settings only. If you set either one in user, project, or local settings or with `--settings`, Claude Code ignores it with a warning.
[](#organization-model-restrictions)
Organization model restrictions
Organization admins on Claude Enterprise plans restrict which models members can run by disabling individual models in the claude.ai admin console. This restriction is delivered with the account’s entitlements when Claude Code authenticates, separate from any `availableModels` list in settings, and the server enforces the same restriction independently when a session is created. Requires Claude Code v2.1.187 or later. The restriction applies when a member signs in or uses their own API key. Organization-scoped credentials, such as organization service keys, are not tied to a user, so the restriction does not apply to them. The Claude Console has no model restriction control. Organizations without a Claude Enterprise plan, including those whose members authenticate through the Anthropic API, restrict models with [`availableModels`](#restrict-model-selection) in [managed settings](../13-Enterprise-Admin/managed-settings.md) instead, adding [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model) to cover the Default option. [Surface coverage](#surface-coverage) says how each surface receives and enforces these settings. A restricted model is hidden from the `/model` picker. Selecting it by name with `--model`, the `ANTHROPIC_MODEL` environment variable, or the `model` setting shows the notice `Model "<name>" is restricted by your organization's settings. Using <model> instead.` and the session starts on an allowed model. Typing `/model <name>` for a restricted model is rejected with `Model '<name>' is restricted by your organization's settings. Run /model to choose a different model.` and the session keeps its current model. A [model family alias](#restrict-model-selection) such as `opus` resolves to its usual model when the organization permits it. When the organization restricts that model, Claude Code substitutes the newest version of the family that the organization permits, with the same substitution notice. `/model <alias>` is rejected only when every version of its family is restricted; an alias set with `--model`, `ANTHROPIC_MODEL`, or the `model` setting is still replaced at startup in that case. Before v2.1.205, a family alias was substituted or rejected based on its newest released version alone, even when an older version was allowed. Restrictions apply org-wide or per role:
- Disabling a model at the organization level removes it for every member.
- Role-level access grants different models to different custom roles, and a member who holds several roles can use any model that one of their roles grants.
- Haiku models are always available and can’t be disabled, so every member keeps at least one usable model.
- An access change takes effect on new requests within about a minute; the `/model` picker reflects it the next time a session starts.
Both restrictions apply together: a model is selectable only when it is permitted by `availableModels` and not restricted by the organization. Organization restrictions reach sessions on the Anthropic API and [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) deployments only; on any other provider, use `availableModels` instead.
[](#organization-default-model)
Organization default model
Organization admins on Claude Enterprise plans can set a default model for Claude Code members from the claude.ai admin console, for the whole organization or per custom role. When one is set, the Default option resolves to that model. Requires Claude Code v2.1.196 or later. The Default row in the `/model` picker shows the organization default’s name with the label Org default. The label reads Org default whether the admin set the default for the whole organization or for your role. A role default covers members of that custom role and takes precedence over the organization-wide default; when several of your roles set different defaults, the most capable model applies. The organization default is a starting point, not a restriction. These selections take precedence over it:
- the `--model` flag and the `ANTHROPIC_MODEL` environment variable
- a `model` value in [managed settings](../13-Enterprise-Admin/managed-settings.md) or supplied through `--settings`
- a `model` value in your user, project, or local settings, including a model you save with `/model`
Admins can also configure the organization default to override user selection. With override on, it takes precedence over the `model` value in user, project, and local settings, so a model you save with `/model` applies for the current session and the organization default returns on the next launch. When your selection differs, `/model` shows `Your organization's default (<model>) applies on restart`. The `--model` flag, `ANTHROPIC_MODEL`, managed settings, and `--settings` still take precedence even with override on. Override is available to a limited set of organizations; ask your Anthropic account team about availability. To limit which models members can select, use [organization model restrictions](#organization-model-restrictions) or [`availableModels`](#restrict-model-selection) instead. Claude Code reads the organization default once at startup, so a default the admin changes mid-session takes effect on the next launch. When the organization default doesn’t override user selection, the first interactive launch after the admin changes it clears the `model` key from your user settings once, so the new default applies. It changes nothing else in the file, and a model you save with `/model` after that launch is kept. The organization default passes through these restriction checks before it is adopted:
- With the default prefix matching, [`availableModels`](#restrict-model-selection) on its own doesn’t apply to the organization default, so an organization default outside the allowlist still applies. When [`enforceAvailableModels`](#enforce-the-allowlist-for-the-default-model) is also set, an organization default outside the allowlist is remapped to the first allowlist entry as well
- an organization default that [organization model restrictions](#organization-model-restrictions) deny for your account is replaced by the newest allowed model in its family, or a lower-cost family when every version of it is restricted
- for an organization default that `deniedModels` or an `"exact"` list blocks, see [Block specific models or versions](#block-specific-models-or-versions)
- an organization default that isn’t available to your account at all is skipped, and the Default option resolves as it would [without an organization default](#default-model-setting)
As of v2.1.199, when the organization default is a different model family from your account type’s usual default, the `/model` picker keeps a separate row for that usual family, so you can still switch to it for a session. In v2.1.196 through v2.1.198 that row is missing from the picker. The organization default reaches only sessions authenticated with the Anthropic API. To set a default anywhere else, including [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) deployments, use the `model` key in [managed settings](../13-Enterprise-Admin/managed-settings.md) instead.
[](#organization-effort-limits)
Organization effort limits
Your organization can cap the [effort level](#adjust-effort-level) in two ways. On a Claude Enterprise plan, organization admins set per-role effort limits, described below. On any plan and any provider, including Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, the [`maxEffortLevel`](settings-reference.md#maxeffortlevel) managed setting caps effort on the client instead. When both apply to a model, the lower cap applies. Organization admins on Claude Enterprise plans can set a maximum [effort level](#adjust-effort-level) per model for each custom role, alongside role-level [organization model restrictions](#organization-model-restrictions). Levels above the cap aren’t offered in the `/effort` picker, and naming a higher level with `--effort` or `/effort` runs at the cap instead. In interactive sessions and plain-text `--print` runs, a warning names the requested and applied levels; with `json` or `stream-json` output or in background agents, the clamp applies silently. Caps are per model, so switching models can change which levels are available. When several of your roles grant the same model, the least restrictive cap applies. Requires Claude Code v2.1.195 or later. Effort limits are delivered together with [organization model restrictions](#organization-model-restrictions) and reach the same sessions.
[](#special-model-behavior)
Special model behavior
[](#default-model-setting)
`default` model setting
The behavior of `default` depends on your account type:
- **Pro, Max, Team, Enterprise, and Anthropic API**: defaults to Opus 5.5
- **Claude Platform on AWS, Amazon Bedrock, and Google Cloud’s Agent Platform**: defaults to Opus 5.5
- **Microsoft Foundry**: defaults to Sonnet 4.5
Before v2.1.280, `default` resolved to Sonnet 5 on Pro and Team Standard, and to Opus 5 on Max, Team Premium, Enterprise, the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Google Cloud’s Agent Platform from v2.1.219. Before v2.1.219, `default` resolved to Opus 4.8 on the Anthropic API, Max, Team Premium, and Enterprise pay-as-you-go from v2.1.154, and on Claude Platform on AWS, Amazon Bedrock, and Google Cloud’s Agent Platform from v2.1.207. Before v2.1.207, `default` resolved to Opus 4.7 on Claude Platform on AWS and to Sonnet 4.5 on Amazon Bedrock and Google Cloud’s Agent Platform. When an admin has set an [organization default model](#organization-default-model), `default` resolves to that model instead of the account-type default above. Requires Claude Code v2.1.196 or later. `default` can also resolve to the model you set with [`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions), under the conditions listed in its section, or to the model [recorded on your account](#setting-your-model). When nothing is recorded on your account, managed settings [enforce the allowlist for the Default model](#enforce-the-allowlist-for-the-default-model), and the account-type default is not in `availableModels`, `default` resolves to the enforced Default instead of the account-type default above. When an organization default and enforcement both apply, the organization default replaces the account-type default first and enforcement then applies to it: an allowlisted organization default is kept, while one outside the list resolves to the enforced Default. Fable models are not the account-type default on any plan or provider. Choosing one with `/model` saves it as the selected model in your user settings, so later sessions start on it. For the one-time change Claude Code makes to a saved Fable 5 selection in v2.1.257, see [Work with Fable](#work-with-fable).
[](#opusplan-model-setting)
`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 pairs Opus’s reasoning for planning with Sonnet’s efficiency for execution. The plan-mode Opus phase uses the same context window as the `opus` model setting, and the execution phase uses the same window as `sonnet`. When `opus` and `sonnet` resolve to models that run with the [1M context window](#extended-context) by default, as the current models do on the Anthropic API, both phases run with it. To request 1M context for both phases where they don’t, [set the model](#setting-your-model) to `opusplan[1m]`, for example with `/model opusplan[1m]`. Setting it with `/model` requires Claude Code v2.1.265 or later; on earlier versions, use the `--model` flag or the `model` setting instead. When [`availableModels`](#restrict-model-selection) excludes the newest Opus but permits an older version, for example `["sonnet", "claude-opus-4-6"]`, `opusplan` uses the newest permitted Opus for planning and stays on Sonnet only when every Opus is excluded. A Haiku session that would normally upgrade to Sonnet in plan mode likewise uses the newest permitted Sonnet, and stays on Haiku only when every Sonnet is excluded. Before v2.1.205, plan mode stayed on the session’s model whenever the newest version of the upgrade family was excluded, even when the allowlist permitted an older one. The substitution of an older permitted version applies on the Anthropic API and [Claude Platform on AWS](claude-platform-on-aws.md). On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Mantle, whose deployments use provider-specific model IDs, plan mode stays on the session’s model whenever the upgrade model is excluded. For a hybrid approach where Claude decides mid-task when to consult a second model rather than switching at the plan boundary, see the [advisor tool](advisor.md).
[](#fallback-model-chains)
Fallback model chains
When the primary model is overloaded, unavailable, or returns another non-retryable server error, Claude Code can switch to a fallback model instead of failing the request. Authentication, billing, rate-limit, request-size, and transport errors, and a [denial by your organization’s policy check](errors.md#automatic-retries), never trigger a switch; those follow their normal retry and error handling. Configure one or more fallback models and Claude Code tries them in order, showing a notice when it switches. The switch lasts for the current turn only, so your next message tries the primary model first again. Claude Code caps chains at three models after duplicate removal and ignores extra entries. Set a chain for one session with the `--fallback-model` flag, which accepts a comma-separated list:
```python
claude --fallback-model sonnet,haiku
```
To persist a chain across sessions, set `fallbackModel` in [settings](settings.md) as an array:
```python
{
"fallbackModel": ["claude-sonnet-5", "claude-haiku-4-5"]
}
```
The `--fallback-model` flag takes precedence over the `fallbackModel` setting. Each entry accepts a model name or alias, and `"default"` expands to the default model. Claude Code doesn’t confirm the chain at startup and `/status` doesn’t display it. The notice shown when a switch happens is the first visible sign that a fallback is configured. When a request fails over, Claude Code tries each entry in order until one accepts it. An entry that can’t be reached either, such as a retired model pinned in settings, fails over to the next one the same way. Claude Code removes two kinds of entry before that walk starts:
- **Outside the allowlist**: Claude Code drops any entry not permitted by [`availableModels`](#restrict-model-selection) when it reads the chain.
- **Smaller context window during compaction**: the chain also covers [compaction](context-window.md#what-survives-compaction), but Claude Code won’t fall back to a model with a smaller context window than the primary’s, since summarizing there would cut off part of the conversation first. If every fallback is smaller, compaction shows the original error and you can retry.
Claude Code also applies the chain to [subagents](../09-Agents-Patterns/sub-agents.md). When a subagent’s request fails over, Claude Code tries your configured fallback models in order, and the subagent continues on the model that accepts the request. Your session’s model is unchanged. Before v2.1.247, a failure the chain covers ended the subagent instead.
[](#automatic-model-fallback)
Automatic model fallback
This section covers content-based fallback from Fable models, Opus 5.5, Sonnet 5.5, and Opus 5. For availability-based fallback when a model is overloaded or unavailable, see [Fallback model chains](#fallback-model-chains). Fable models, Opus 5.5, Sonnet 5.5, and Opus 5 run with safety classifiers, which most often flag cybersecurity and biology content. When a classifier flags a request and the flagged category has a fallback model, Claude Code re-runs the request on that model and shows a notice in the transcript. For those two categories, the fallback model depends on which model refused:
- **Fable 5.1, Fable 5, and Opus 5.5**: biology-flagged requests re-run on Opus 5, and cybersecurity-flagged requests re-run on Opus 4.8.
- **Sonnet 5.5**: cybersecurity-flagged requests re-run on Sonnet 5. Biology-flagged requests end with a refusal instead, because Sonnet 5.5 has no biology fallback model.
- **Opus 5**: cybersecurity-flagged requests re-run on Opus 4.8. Biology-flagged requests end with a refusal instead, because Opus 5 runs its own biology classifiers with no fallback model.
On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, Claude Code resolves these targets through your deployment’s model IDs instead. See [Enable fallback on Bedrock, Agent Platform, and Foundry](#enable-fallback-on-bedrock-agent-platform-and-foundry). After a fallback, the session continues on the fallback model. To return to your original model, run [`/model`](#setting-your-model). Category-based fallback requires Claude Code v2.1.219 or later. Before v2.1.219, every flagged Fable 5 request re-ran on your provider’s default Opus model, and Opus 5 was not a fallback source. The fallback model is checked against [`availableModels`](#restrict-model-selection). When it is blocked, no fallback occurs. The refusal is shown as a normal error and the session’s model is unchanged.
[](#check-what-triggered-fallback)
Check what triggered fallback
Fallback can trigger on the first request of a session, before you send anything unusual, because the first request carries workspace context such as your CLAUDE.md content and git status. A repository that contains security or biology material can trip the classifier on that context alone. To check whether customizations are the trigger, start a session with `claude --safe-mode`, which disables customizations such as CLAUDE.md, skills, MCP servers, and hooks. Git status and directory names are not customizations and are still included.
[](#ask-before-switching)
Ask before switching
To decide what happens each time a request is flagged, rather than switching automatically, run `/config` and turn off **Switch models when a message is flagged**, or set [`switchModelsOnFlag`](settings-reference.md#switchmodelsonflag) to `false` in your settings file. A flagged request then pauses the session with two options: switch to the fallback model, or edit the prompt and retry on the current model. Some cases behave differently:
- When the flagged category has no fallback model, such as a biology flag on Opus 5 or Sonnet 5.5, Claude Code doesn’t show the prompt and the request ends with the refusal.
- If both models flag the same request, you can edit the prompt and retry, or start a new session.
- In [cloud sessions](claude-code-on-the-web.md) on the mobile app, editing and retrying is not supported. Switch models, or continue the session from a desktop browser or the desktop app.
- In [non-interactive mode](cli-reference.md#cli-flags) and SDK integrations that can’t show the prompt, a flagged request ends the turn with a refusal instead.
- When the fallback target is blocked by [`availableModels`](#restrict-model-selection), Claude Code doesn’t show the prompt. The flagged request ends with the refusal, the same as automatic fallback when the target is blocked.
[](#enable-fallback-on-bedrock-agent-platform-and-foundry)
Enable fallback on Bedrock, Agent Platform, and Foundry
On [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), and [Microsoft Foundry](microsoft-foundry.md), model IDs are provider-specific, so automatic fallback only operates when Claude Code can identify each model involved:
- Claude Code must recognize the current model as a fallback source. Fable 5.1 and Fable 5 are recognized when the model ID contains `claude-fable-5`, matches the value of `ANTHROPIC_DEFAULT_FABLE_MODEL`, or is mapped with [`modelOverrides`](#override-model-ids-per-version). Opus 5.5, Sonnet 5.5, and Opus 5 are recognized by their provider model ID or a [`modelOverrides`](#override-model-ids-per-version) mapping.
- An Opus target must resolve in your deployment, whichever model refused: set `ANTHROPIC_DEFAULT_OPUS_MODEL`, or keep an Opus 4.8 entry in the provider’s model list. Without one, fallback stays off for every source model, including Sonnet 5.5, and flagged requests end with a refusal.
- The flagged category’s fallback model must resolve in your deployment. From a Fable model, Opus 5.5, or Opus 5, if you set `ANTHROPIC_DEFAULT_OPUS_MODEL`, flagged requests re-run on that model for every category that has a fallback; a biology flag on Opus 5 still ends with a refusal. If you don’t set it, cybersecurity-flagged requests re-run on the Opus 4.8 entry, and biology-flagged requests from a Fable model or Opus 5.5 on an Opus 5 entry. From Sonnet 5.5, cybersecurity-flagged requests re-run on the model you set in `ANTHROPIC_DEFAULT_SONNET_MODEL`, or on a Sonnet 5 entry in the provider’s model list if you don’t set it.
If either model can’t be identified, Claude Code doesn’t switch. The flagged request ends with a refusal message, and you can switch models with [`/model`](#setting-your-model) and retry. To make both models identifiable, set the pins for your source model:
- **Fable models**: set `ANTHROPIC_DEFAULT_FABLE_MODEL` to your Fable model ID so Claude Code recognizes it as a fallback source.
- **Every source model**: set `ANTHROPIC_DEFAULT_OPUS_MODEL` to an Opus model ID to turn fallback on and give the flagged categories a target. A pin that names a model outside the Opus family, or the model that refused, leaves the refusal standing.
- **Sonnet 5.5**: in addition to the Opus pin, set `ANTHROPIC_DEFAULT_SONNET_MODEL` or keep a Sonnet 5 entry in the provider’s model list to supply the model the request re-runs on. A Sonnet pin that names a model outside the Sonnet family, or Sonnet 5.5 itself, leaves the refusal standing.
[](#security-research-and-biology-workloads)
Security research and biology workloads
Workloads in offensive security or biology, including penetration testing, Capture the Flag (CTF) exercises, and biology-adjacent codebases, trigger fallback frequently, often on the first request. For substantive biology work on Fable 5.1, Fable 5, or Opus 5.5, Claude Code moves the session to Opus 5 at the first flagged request, and later biology-flagged requests end in refusals there, because Opus 5 has no biology fallback. On Opus 5 and Sonnet 5.5, you get those refusals from the first flagged request. This is expected routing for these domains, not an account flag. If your organization needs Fable-class capability for this work, ask your Anthropic account team about trusted access programs.
[](#adjust-effort-level)
Adjust effort level
[Effort levels](../04-API-Reference/Guides/build-with-claude-effort.md) 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. The available effort levels depend on the model. Models not listed here do not support effort:
| Model | Levels |
|:---------------------------------------------------------------|:----------------------------------------|
| Fable 5.1 and Fable 5 | `low`, `medium`, `high`, `xhigh`, `max` |
| Opus 5.5, Sonnet 5.5, Opus 5, Sonnet 5, Opus 4.8, and 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. Your organization or your own settings can also cap the levels a model offers; see [Organization effort limits](#organization-effort-limits). Claude Code resolves the session’s effort level in this order, taking the first that applies:
1. An explicit choice: the [`CLAUDE_CODE_EFFORT_LEVEL`](env-vars.md#variables) environment variable, launching with `--effort`, or `/effort` in the session ([a non-interactive `/effort` has narrower effect](#non-interactive-effort))
2. Your settings: the level you saved for the model or an [`effortLevel`](settings-reference.md#effortlevel) key, with the precedence between them and across settings files stated at [`modelSettings`](settings-reference.md#modelsettings)
3. The model’s default effort: `high` on every model that supports effort, except that Opus 5.5 and Sonnet 5.5 default to `medium`, Opus 4.7 defaults to `xhigh`, and, when your organization sets a default effort level for its [organization default model](#organization-default-model), that level is the default when you run that model
Opus 5.5 starts at `medium` unless one of the sources above sets a level for it, and a top-level `effortLevel` in your user settings file doesn’t count for Opus 5.5. That key is the older form `/effort` wrote before Claude Code saved levels per model: it keeps applying where it applied before, on Opus 5, Fable 5.1, and earlier models, while Opus 5.5 and models released after it start at their own default until you choose a level for them with `/effort` or the `/model` picker. A top-level `effortLevel` in project, local, or managed settings, or one passed with `--settings`, applies to every model. When you set `low`, `medium`, `high`, or `xhigh` in an interactive session on your machine, you choose how long it lasts by how you confirm it:
- `Enter` in the `/effort` slider or the `/model` picker, or a level typed after `/effort`: save the level as your default and apply it in later sessions
- `s` in the `/effort` slider or the `/model` picker: apply the level to this session only. Requires Claude Code v2.1.257 or later
Claude Code saves the level per model, under the [`modelSettings`](settings-reference.md#modelsettings) key in your user settings, so each model keeps its own saved level. `max` is the deepest reasoning level. Unless you set it through the `CLAUDE_CODE_EFFORT_LEVEL` environment variable, Claude Code applies `max` to the current session only.
A level you pick from the effort control on a phone or browser connected through [Remote Control](remote-control.md#what-connected-devices-see) applies to that session only.
When you set a level with `/effort` in a [`-p` run](headless.md), Claude Code applies it to that session only and doesn’t save it as your default. The `/effort` slider also has an **Ultracode** toggle. Ultracode is a Claude Code setting rather than a model effort level: with it on, Claude orchestrates [dynamic workflows](workflows.md) for substantive tasks, at whichever effort level the session runs at. For where it can be set persistently, see the [`ultracode`](settings-reference.md#ultracode) setting. Turning ultracode on or off with `/effort` or the `ultracode` setting leaves the effort level unchanged. The `--effort ultracode` flag and the Agent SDK `effortLevel: "ultracode"` value turn it on and also set the level to `xhigh`. Picking a level in the `/effort` slider or the `/model` picker leaves ultracode as it was. You can turn on ultracode through any of the following:
- **`/effort`**: run `/effort ultracode` to turn it on for the current session or `/effort ultracode off` to turn it off. In the `/effort` slider, press `Tab` to flip the **Ultracode** toggle, then `Enter` to apply it
- **`--effort` flag**: launch with `claude --effort ultracode`, which starts the session at `xhigh` effort with ultracode on
- **`ultracode` setting**: set [`"ultracode": true`](settings-reference.md#ultracode) in a settings file, with `--settings`, or in an Agent SDK control request. An [`applyFlagSettings()`](../05-Agent-SDK/agent-sdk-typescript.md#applyflagsettings) request also accepts `effortLevel: "ultracode"`, which turns it on and sets the effort level to `xhigh`
The `/effort ultracode off` form, the slider toggle, and keeping ultracode on at effort levels other than `xhigh` require Claude Code v2.1.284 or later. Before v2.1.284, turning on ultracode set the session to `xhigh` effort, picking another level turned it off, and an effort cap below `xhigh` made it unavailable. Passing `ultracode` to the `--effort` flag or the Agent SDK `effortLevel` value requires Claude Code v2.1.203 or later. Before v2.1.203, `--effort ultracode` printed `Unknown --effort value 'ultracode'` and the session started at the default effort. The persisted `effortLevel` setting and the `CLAUDE_CODE_EFFORT_LEVEL` environment variable don’t accept `ultracode`. If `CLAUDE_CODE_EFFORT_LEVEL` or an [effort cap](#organization-effort-limits) sets the session’s level, ultracode stays on at that level. Ultracode is unavailable when:
- [Workflows are turned off](workflows.md#turn-workflows-off)
- The model doesn’t support `xhigh` effort
In those cases `--effort ultracode` starts the session with ultracode off, at the highest effort level the model and any cap allow, up to `xhigh`.
[](#choose-an-effort-level)
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` | Quick exchanges where you review each result, such as brainstorming, a first sketch, or a small change like a rename |
| `medium` | The default on Opus 5.5 and Sonnet 5.5, where it fits day-to-day engineering work with a clear scope, such as implementing a new feature. On other models, reduces token usage for cost-sensitive work that can trade off some intelligence |
| `high` | Work where verification matters or edge cases are likely, such as fixing a bug in an existing codebase. The default on every model except Opus 5.5, Sonnet 5.5, and Opus 4.7 |
| `xhigh` | Deeper reasoning at higher token spend. The default on Opus 4.7 |
| `max` | Hard problems you want Claude to work through without you, such as finding security vulnerabilities. `max` may show diminishing returns and is prone to overthinking, so test before adopting it broadly |
| `ultracode` | A Claude Code setting rather than a level: plans a [dynamic workflow](workflows.md) for each substantive task at any effort level |
In tests on Opus 5.5 and Fable 5.1, Claude at a higher level tested more edge cases and verified more of its work before answering. It also made more choices on its own. At a lower level, Claude returned a starting point sooner, which fits work where you review each result and steer the next step. To see the same tasks run at each level, read [Using Claude Code: Spending your effort](https://claude.dev/blog/spending-your-effort/) on the blog. The effort scale is calibrated per model, so the same level name does not represent the same underlying value across models. Opus 5.5 [defaults to `medium`](#adjust-effort-level), one level below Opus 5’s default of `high`. In Anthropic’s testing, Opus 5.5 at `medium` matches or exceeds Opus 5 at `high` on coding and knowledge-work evaluations. At a given level, Opus 5.5 tends to think more per turn than Opus 5. When you move from Opus 5 to Opus 5.5, start at `medium` rather than carrying over the level you used on Opus 5. To test levels against your own work, see [Calibrate effort](../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5-5.md#calibrate-effort) in the Opus 5.5 prompting guide.
[](#use-ultrathink-for-one-off-deep-reasoning)
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. Claude Code passes other phrases such as “think”, “think hard”, and “think more” through as ordinary prompt text and doesn’t recognize them as keywords.
[](#set-the-effort-level)
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 clear your saved level for the active model. You can run it while Claude is working, and once you confirm the [cache warning](prompt-caching.md#changing-effort-level), if Claude Code shows one, Claude Code applies the new level to the next request in the turn
- **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 a per-model level in [`modelSettings`](settings-reference.md#modelsettings), or set [`effortLevel`](settings-reference.md#effortlevel) to `low`, `medium`, `high`, or `xhigh` as the default for models without one. `max` isn’t accepted as a level in either key, and `ultracode` has its own [`ultracode`](settings-reference.md#ultracode) key
- **From a connected device**: in a [Remote Control](remote-control.md#what-connected-devices-see) session, pick a level from the effort control on your phone or in your browser. The level applies to the current session only. Requires Claude Code v2.1.234 or later
- **Skill and subagent frontmatter**: set `effort` in a [skill](../08-Plugins-Skills/skills.md#frontmatter-reference) or [subagent](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) markdown file to override the effort level when that skill or subagent runs
Frontmatter effort applies when that skill or subagent is active, overriding the session level but not the environment variable. A [`maxEffortLevel`](settings-reference.md#maxeffortlevel) or [organization effort cap](#organization-effort-limits) still limits the level the skill or subagent runs at. If you set `effortLevel` in [managed settings](../13-Enterprise-Admin/managed-settings.md), Claude Code applies it at the settings step of the [effort resolution order](#adjust-effort-level), and users can still change the level with `/effort` or `--effort`. To keep users at or below a level, set [`maxEffortLevel`](settings-reference.md#maxeffortlevel). The effort slider appears in `/model` when a supported model is selected. The current effort level is also shown in the session header next to the model name, for example “with low effort”, so you can confirm which setting is active without opening `/model`. The footer also briefly shows the effort level at startup and when it changes.
[](#adaptive-reasoning-and-fixed-thinking-budgets)
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. Fable models, Sonnet 5 and later, and Opus 4.7 and later always use adaptive reasoning. The fixed thinking budget mode and `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` don’t apply to them. 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](env-vars.md).
[](#extended-thinking)
Extended thinking
Extended thinking is the reasoning Claude emits before responding. On models that support [adaptive reasoning](#adjust-effort-level), 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. With thinking turned off on the Anthropic API, Claude Code sends effort `high` instead of a higher level to models it knows [don’t accept that combination](errors.md#effort-isnt-available-with-thinking-turned-off), such as Opus 5.
| 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 through an environment variable | Set [`MAX_THINKING_TOKENS=0`](env-vars.md), which turns thinking off on the Anthropic API except on Opus 5.5, Sonnet 5.5, and Fable models. On [third-party providers](third-party-integrations.md), Claude Code omits the `thinking` parameter instead, and adaptive-reasoning models may still think. Other values apply only with a [fixed thinking budget](#adaptive-reasoning-and-fixed-thinking-budgets) |
You can’t turn thinking off on Opus 5.5, Sonnet 5.5, or the Fable models. The session toggle and the `/config` row show `Thinking can't be turned off` for these models instead of offering the switch, and a saved `alwaysThinkingEnabled: false` or `MAX_THINKING_TOKENS=0` has no effect there. On these models, the model decides per step how much to think based on the effort level. The saved setting applies again when you switch to a model that accepts it. Claude Code collapses thinking output 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](settings.md) 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)
Extended context
Fable 5.1, Fable 5, Sonnet 5 and later, Opus 4.6 and later, and Sonnet 4.6 support a [1 million token context window](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model) for long sessions with large codebases. On the Anthropic API, Fable 5.1, Fable 5, Sonnet 5 and later, and Opus 4.7 and later run with the 1M window on every plan, including Pro. You don’t select a `[1m]` variant or turn on usage credits for the 1M window on these models. Fable usage itself can bill to usage credits on some plans; see [Fable and usage credits](#fable-and-usage-credits). Opus 4.6 and Sonnet 4.6 reach 1M only through their `[1m]` variant, and access to that variant depends on your plan. On Max, Team, and Enterprise plans, including both Team Standard and Team Premium seats, Opus 4.6 with 1M context is included with your subscription. Sonnet 4.6 with 1M context requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) on every subscription plan, including Max.
| Plan | Opus 4.6 with 1M context | Sonnet 4.6 with 1M context |
|---------------------------|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| Max, Team, and Enterprise | Included with subscription | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
| Pro | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
| API and pay-as-you-go | Full access | Full access |
Claude Code checks these plan requirements only when it connects to the Anthropic API directly. If you point `ANTHROPIC_BASE_URL` at an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md#subscriptions-and-gateways) and your saved claude.ai login stays the active credential, Claude Code doesn’t check your plan’s usage credits. The `[1m]` options stay available in `/model`, and the gateway decides whether the request succeeds. Before v2.1.229, Claude Code rejected `/model sonnet[1m]` in that configuration when it couldn’t confirm usage credits on the account. To turn off 1M context, set `CLAUDE_CODE_DISABLE_1M_CONTEXT=1`. Claude Code removes 1M model variants from the model picker. On models with a native 1M window, such as Sonnet 5 and the Fable models, it also treats the model as having a 200K context window:
- With auto-compaction on, sessions compact at the 200K boundary through [auto-compaction](#set-the-auto-compact-window). Setting the auto-compact window above 200K doesn’t lift the hold, because Claude Code caps that window at the model’s context window.
- With auto-compaction off, sessions stop at the 200K boundary with the [context-limit error](errors.md#prompt-is-too-long) instead of compacting.
Before v2.1.223, Claude Code held only Sonnet 5, Opus 4.8, and Opus 5 sessions to 200K. See [environment variables](env-vars.md). 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 usage credits, tokens are billed to usage credits. If your account supports 1M context, the option appears in the `/model` picker in the latest versions of Claude Code. If you don’t see it, restart your session, and on a third-party provider check whether your deployment [pinned the model](#pin-models-for-third-party-deployments) with an `ANTHROPIC_DEFAULT_*_MODEL` variable. You can also use the `[1m]` suffix with model aliases or full model names:
```python
# 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-8[1m]
```
[](#sonnet-5-5-and-sonnet-5-context-window)
Sonnet 5.5 and Sonnet 5 context window
On the Anthropic API, Sonnet 5.5 and Sonnet 5 always run with the 1M context window. There is no 200K variant, no `[1m]` suffix to select, and no usage credits required on any plan. Sessions auto-compact before the window fills, at about 967K tokens by default; set [`CLAUDE_CODE_AUTO_COMPACT_WINDOW`](env-vars.md) to choose a different threshold. Two configurations budget the window at 200K instead:
- **LLM gateway**: when `ANTHROPIC_BASE_URL` points at a [gateway](../13-Enterprise-Admin/llm-gateway.md), Claude Code can’t verify 1M support. To use the full window, select Sonnet 5.5 (1M context) in the model picker, which maps to `sonnet[1m]`, or run `/model claude-sonnet-5[1m]` for Sonnet 5.
- **`CLAUDE_CODE_DISABLE_1M_CONTEXT=1`**: holds sessions on every model with a native 1M window to a 200K window; see [Extended context](#extended-context) for how the hold is enforced. Useful for deployments that need to cap context.
[](#context-window-and-auto-compaction)
Context window and auto-compaction
The auto-compact window is how full the context window can get before Claude Code compacts the conversation. For what compaction keeps and drops per mechanism, see [What survives compaction](context-window.md#what-survives-compaction).
[](#set-the-auto-compact-window)
Set the auto-compact window
You can set the auto-compact window in three places:
- **For this session and later ones**: run `/autocompact` with a value, like `/autocompact 500k`. Claude Code saves it to your user settings as [`autoCompactWindow`](settings-reference.md#autocompactwindow) and applies it to the current session; if a higher-priority [settings scope](settings.md#settings-precedence) such as managed settings sets the key, the command saves your value but the session keeps that scope’s window, and the command says so. Run `/autocompact auto` to return to the window tuned for your model.
- **For one launch**: pass [`--autocompact`](cli-reference.md#cli-flags) when starting Claude Code. The flag overrides your saved setting for that launch without changing it, and `claude --autocompact auto` runs the session at the tuned window even if your saved setting has a value. Unlike `/autocompact`, the flag isn’t preempted by a higher-priority settings scope such as managed settings.
- **In scripts and cloud environments**: set [`CLAUDE_CODE_AUTO_COMPACT_WINDOW`](env-vars.md). While it’s set, it takes precedence over the command, the flag, and the setting, and `/autocompact` reports the override instead of changing the window.
The command and the flag accept a window size from 100K to 1M tokens, in any of these forms:
- A plain token count, such as `200000`
- A `k` or `M` suffix, such as `500k` or `1M`
- A bare number from 100 to 1000, meaning thousands, so `200` sets 200,000
The environment variable accepts only the plain token count. Claude Code caps the window at the model’s context window.
[](#default-auto-compact-thresholds)
Default auto-compact thresholds
If you don’t set an auto-compact window, Claude Code compacts when the conversation reaches the model’s context limit, except in these sessions:
- [Cloud sessions](claude-code-on-the-web.md) compact as the conversation approaches the model’s limit
- Sonnet 4.6 and Opus 4.6 without [extended context](#extended-context) compact at the 200K boundary, and so do Opus 4.8 and later when they run with a 200K context window, such as on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry
- When you set [`CLAUDE_CODE_DISABLE_1M_CONTEXT=1`](env-vars.md), models with a native 1M window, such as Sonnet 5 and the Fable models, compact at the 200K boundary
- Models running with a native 1M window, such as Sonnet 5, the Fable models, and Opus 4.7 and later on the Anthropic API, compact before the window fills, at about 967K tokens by default. On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, [Pin models for third-party deployments](#pin-models-for-third-party-deployments) says which models run with that window; for the configurations that budget Sonnet 5.5 and Sonnet 5 at 200K instead, see [Sonnet 5.5 and Sonnet 5 context window](#sonnet-5-5-and-sonnet-5-context-window)
- Sessions on a model ID Claude Code doesn’t recognize, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) alias, compact at the context window Claude Code assumes for the ID; see [Correct the window for a gateway or custom model ID](#correct-the-window-for-a-gateway-or-custom-model-id)
[](#correct-the-window-for-a-gateway-or-custom-model-id)
Correct the window for a gateway or custom model ID
On an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) or other custom deployment, Claude Code can assume a context window for the model ID that differs from the model’s real window, whether or not it resolves the ID to a Claude model. Set [`CLAUDE_CODE_MAX_CONTEXT_TOKENS`](env-vars.md) to the window Claude Code should assume instead. How the variable applies depends on the ID. Claude Code treats an ID as a provider or custom spelling when it doesn’t start with `claude-`, in any casing, or when it carries a suffix that Claude Code strips when reading the ID, such as the `@YYYYMMDD` date used on Google Cloud’s Agent Platform. Before v2.1.259, Claude Code didn’t count a stripped suffix, so an unrecognized `claude-` ID with a date suffix was treated as a bare `claude-` name. An unrecognized provider or custom spelling, the same spelling with `[1m]`, and every other ID are three separate cases:
- If Claude Code can’t resolve a provider or custom spelling to a model it recognizes and the ID doesn’t contain `[1m]`, the variable applies directly and proactive compaction continues at the declared window.
- If Claude Code can’t resolve a provider or custom spelling to a model it recognizes and the ID contains `[1m]`, in any casing, Claude Code assumes a 1M window for it and the variable doesn’t apply on its own. To correct the window while keeping proactive compaction, also set [`CLAUDE_CODE_DISABLE_1M_CONTEXT=1`](env-vars.md). With that variable set, Claude Code sizes the ID like the same spelling without `[1m]`, so `CLAUDE_CODE_MAX_CONTEXT_TOKENS` applies when it would apply to that untagged spelling. With a declared window above 200K, Claude Code then shows a [startup warning](errors.md#the-200k-limit-isnt-enforced) that the 200K limit isn’t enforced. The warning is expected in this configuration.
- If the ID resolves to a model Claude Code recognizes, or the ID is a bare `claude-` name with no suffix for Claude Code to strip, in any casing, the variable takes effect only when you also set [`DISABLE_COMPACT`](env-vars.md), which disables all compaction. For example, an ID that contains a Claude model name that Claude Code knows, such as `anthropic/claude-opus-4-8`, `us.anthropic.claude-…-v1:0`, or the dated `claude-sonnet-4-5@20250929`, resolves to that model. This includes IDs that also contain `[1m]`: Claude Code resolves `claude-opus-4-8[1m]` to Opus 4.8 even with `CLAUDE_CODE_DISABLE_1M_CONTEXT` set.
For a model ID Claude Code doesn’t recognize, set [`CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1`](env-vars.md) to have Claude Code compact only after the API rejects the conversation with a [too-long error Claude Code recognizes](errors.md#prompt-is-too-long). Claude Code doesn’t run that recovery when a gateway [rewrites the error](../13-Enterprise-Admin/llm-gateway-connect.md#troubleshoot-gateway-errors) to wording Claude Code doesn’t recognize.
[](#checking-your-current-model)
Checking your current model
You can see which model you’re currently using in two places:
- In the [status line](statusline.md), if you have one configured
- In `/status`, which also displays your account information
[](#add-a-custom-model-option)
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 [gateway model discovery](../13-Enterprise-Admin/llm-gateway-protocol.md#model-discovery). To list several models instead, in your own order and under labels you choose, set [`modelPicker`](settings-reference.md#modelpicker). Its entry says which rows the picker keeps when that lineup replaces the built-in one. This example sets all three variables to make a gateway-routed Opus deployment selectable. Claude Code reads environment variables at startup, so run the exports before launching `claude`, or restart an existing session to pick them up:
```python
export ANTHROPIC_CUSTOM_MODEL_OPTION="my-gateway/claude-opus-5-5"
export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME="Opus via Gateway"
export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION="Custom deployment routed through the internal LLM gateway"
```
`ANTHROPIC_CUSTOM_MODEL_OPTION_NAME` and `ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION` are optional:
- If you omit the name, the entry shows the model’s name when Claude Code [recognizes the ID](#customize-pinned-model-display-and-capabilities), and the model ID otherwise.
- If you omit the description, Claude Code uses `Custom model (<model-id>)`.
Claude Code lists the custom entry after the built-in entries, and any [`modelPicker`](settings-reference.md#modelpicker) rows you append come after it. Claude Code skips validation for the model ID set in `ANTHROPIC_CUSTOM_MODEL_OPTION`, so you can use any string your API endpoint accepts. When [`availableModels`](#restrict-model-selection) is set, include the custom model ID in the allowlist as well. Otherwise Claude Code filters the custom entry from the picker and rejects a `--model` selection of it like any other excluded model. A custom ID that embeds a family name, such as `my-gateway/claude-opus-5-5`, counts as a specific entry for that family and disables its wildcard, so also list the versions you intend to keep selectable. See [Merge behavior](#merge-behavior).
[](#environment-variables)
Environment variables
Use the following environment variables to control the model names that the aliases map to. Each value must be a full model name, or the equivalent identifier for your API provider. To choose the model your sessions start on, set [`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions), which this table omits.
| Environment variable | Description |
|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ANTHROPIC_DEFAULT_FABLE_MODEL` | The model to use for `fable`, and the model ID Claude Code recognizes as a Fable model for [automatic model fallback](#automatic-model-fallback) on third-party providers |
| `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](../17-Billing-Plans/costs.md#background-token-usage) |
| `CLAUDE_CODE_SUBAGENT_MODEL` | The default model for [subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model), [agent team](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) teammates, and [workflow](workflows.md) agents that aren’t assigned a model another way. Accepts an alias such as `haiku` or a full model name. A per-invocation model or a definition’s `model` field, including `inherit`, takes precedence. To change that, set [`CLAUDE_CODE_SUBAGENT_MODEL_FORCE`](../09-Agents-Patterns/sub-agents.md#run-every-subagent-on-one-model) |
On third-party providers, [Customize pinned model display and capabilities](#customize-pinned-model-display-and-capabilities) describes what a pinned model’s row in the `/model` picker shows. Note: `ANTHROPIC_SMALL_FAST_MODEL` is deprecated in favor of `ANTHROPIC_DEFAULT_HAIKU_MODEL`.
[](#pin-models-for-third-party-deployments)
Pin models for third-party deployments
When deploying Claude Code through [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), [Microsoft Foundry](microsoft-foundry.md), or [Claude Platform on AWS](claude-platform-on-aws.md), pin model versions before rolling out to users. Without pinning, Claude Code uses model aliases such as `fable`, `opus`, `sonnet`, and `haiku` that resolve to a built-in default model ID for each provider. That default can lag the newest Anthropic release, and the model it points to may not yet be enabled in a user’s account. When the default is unavailable, Amazon Bedrock and Google Cloud’s Agent Platform users see a notice and the session falls back to an earlier version of the default model, or to the default Sonnet model when the default is an Opus model and no Opus version is available. Microsoft Foundry users see errors instead, because Microsoft Foundry has no equivalent startup check. On Amazon Bedrock and Google Cloud’s Agent Platform, a user who starts the session on a specific Sonnet or Opus version, for example with `--model`, `ANTHROPIC_MODEL`, or the `model` setting, pins that version as the session’s default for the matching alias: the startup check skips the built-in default it replaces and shows no fallback notice. Before v2.1.211, the check ran and could show a notice even when a session model was explicitly configured.
Set the 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 |
|:------------------------------|:---------------------------------------------------------------------|
| Amazon Bedrock | `export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` |
| Google Cloud’s Agent Platform | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
| Microsoft Foundry | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
Apply the same pattern for `ANTHROPIC_DEFAULT_FABLE_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL`. For current and legacy model IDs across all providers, see [Models overview](../20-Models/about-claude-models-overview.md). To upgrade users to a new model version, update these environment variables and redeploy. To enable [extended context](#extended-context) for a pinned model, append `[1m]` to the model ID in `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, or `ANTHROPIC_DEFAULT_FABLE_MODEL`:
```python
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8[1m]'
```
With the `[1m]` suffix, the 1M context window applies to all usage of the pinned alias, including the plan-mode Opus phase of [`opusplan`](#opusplan-model-setting) and [subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model) whose `model` frontmatter names the alias.
- Claude Code strips the suffix before sending the model ID to your provider.
- Only append `[1m]` when the underlying model [supports 1M context](../04-API-Reference/Guides/build-with-claude-context-windows.md#context-window-sizes-by-model).
- The suffix is read per variable, not per model. On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, a model ID without `[1m]` in one variable uses 200K context even if another variable sets the same model with the suffix. Sonnet 5 always runs with the 1M window on these providers and never needs the suffix.
When you set an `ANTHROPIC_DEFAULT_*_MODEL` variable, the `/model` picker shows one row for that model in place of the family’s built-in rows, including any 1M context rows. To reach the 1M window without adding the suffix to that variable, your users run `/model opus[1m]`, and Claude Code applies the suffix to the model the variable names. `/model sonnet[1m]` works the same way.
An `availableModels` allowlist delivered through [MDM or a managed settings file](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) still applies when using third-party providers; [server-managed settings are not delivered there](../13-Enterprise-Admin/server-managed-settings.md#platform-availability).Filtering matches on a model alias such as `opus`, a version prefix such as `claude-opus-4-8`, or the full provider-form model ID. Provider-specific prefixes such as `us.anthropic.` are not stripped, so to allow a specific model, list its full provider-form ID, or map it through [`modelOverrides`](#override-model-ids-per-version). For a pinned model, that ID is the value you set in its `ANTHROPIC_DEFAULT_*_MODEL` variable. Any `[1m]` suffix is stripped from both the allowlist entry and the requested model before matching.
[](#customize-pinned-model-display-and-capabilities)
Customize pinned model display and capabilities
When you pin a model on a third-party provider, its row in the `/model` picker shows the model’s name by default if Claude Code recognizes the pinned ID, and the raw ID otherwise:
- **Recognized**: the exact ID of a model Claude Code knows, such as its Anthropic API ID or your provider’s or gateway’s form of it, with or without the `[1m]` suffix. Pin `us.anthropic.claude-sonnet-4-5-20250929-v1:0` and the row reads `Sonnet 4.5`.
- **Not recognized**: any other ID, such as an application inference profile ARN or a model version Claude Code doesn’t know, unless a [`modelOverrides`](#override-model-ids-per-version) entry maps a model to that exact string. On Microsoft Foundry, deployment names are user-defined, so Claude Code never recognizes a pinned ID there, mapped or not, and the row shows the deployment name by default.
When a row shows the model’s name, its default description includes the pinned ID so you can still see which ID is pinned. Claude Code may also not recognize which features a pinned model supports. You can set the display name and description yourself and declare capabilities with companion environment variables for each pinned model. These variables take effect on third-party providers such as Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry. The `_NAME` and `_DESCRIPTION` variables also take effect when `ANTHROPIC_BASE_URL` points to an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). 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. When not set, the row shows the model’s name if Claude Code recognizes the pinned ID, and the pinned ID otherwise |
| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | Display description for the pinned Opus model in the `/model` picker. When not set, the row shows a default description that begins `Custom Opus model` |
| `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`, `ANTHROPIC_DEFAULT_FABLE_MODEL`, and `ANTHROPIC_CUSTOM_MODEL_OPTION`. Claude Code enables features like [effort levels](#adjust-effort-level) and [extended thinking](#extended-thinking) by matching the model ID against known patterns. Provider-specific IDs such as Amazon 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](#adjust-effort-level) and the `/effort` command |
| `xhigh_effort` | The `xhigh` effort level |
| `max_effort` | The `max` effort level |
| `thinking` | [Extended 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, Claude Code enables the listed capabilities and disables the unlisted ones 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 an Amazon Bedrock custom model ARN, sets a friendly name, and declares its capabilities:
```python
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)
Override model IDs per version
On platforms that embed Claude Code and set [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](env-vars.md), the host’s model configuration takes precedence over managed model settings, while a managed `availableModels` allowlist stays in force unless the host supplies its own; [Exceptions to managed settings precedence](settings.md#exceptions-to-managed-settings-precedence) says which keys and variables the host overrides. 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 Amazon Bedrock inference profile ARN, Google Cloud’s Agent Platform version name, or Microsoft Foundry deployment name for governance, cost allocation, or regional routing. Set `modelOverrides` in your [settings file](settings.md#where-settings-live):
```python
{
"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](../20-Models/about-claude-models-overview.md). For dated model IDs, include the date suffix exactly as it appears there. Unknown keys are ignored. To stop the `[claude-code:unrecognized_model]` [diagnostic line](errors.md#unrecognized-model-id-on-a-request) for an ID such as a gateway alias, add an entry with that ID as its value. Overrides replace the built-in model IDs that back each entry in the `/model` picker. On Amazon Bedrock, `modelOverrides` entries take precedence over any inference profiles that Claude Code discovers automatically at startup. Claude Code passes values that are already provider-native, such as Amazon Bedrock inference profile ARNs or Microsoft Foundry deployment names, to the provider as-is. Overrides also apply when you pass an Anthropic model ID directly through `--model`, the `ANTHROPIC_MODEL` environment variable, or an `ANTHROPIC_DEFAULT_*_MODEL` environment variable. On Amazon Bedrock, Google Cloud’s Agent Platform, and [Mantle](amazon-bedrock.md#use-the-mantle-endpoint), an Anthropic model ID with no `modelOverrides` entry resolves to the same provider-specific ID as the `/model` picker row for that version, when the provider supports that version. Mantle supports a subset of versions. For an Anthropic model ID outside that subset, Claude Code sends the raw ID to Mantle without mapping it, unless a `modelOverrides` entry covers it. Before v2.1.200, `--model` and the environment-variable values reached the provider as-is without going through the override map. `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. When `enforceAvailableModels` is set in managed settings, the enforced Default resolves through `modelOverrides` from [managed settings](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) only. An admin’s mapping, such as a version pinned to an inference profile ARN, is honored in the enforced Default. Overrides from user or project settings do not affect it. When `availableModels` is set in [managed settings](../13-Enterprise-Admin/managed-settings.md), only `modelOverrides` from managed settings apply to an Anthropic model ID passed directly through `--model` or the environment variables above. Claude Code ignores overrides in user or project settings for those IDs, and never resolves an ID the managed list excludes through `modelOverrides` from any settings source. This managed-source restriction requires Claude Code v2.1.200 or later. See [Restrict model selection](#restrict-model-selection) for how blocked IDs are handled.
[](#prompt-caching-configuration)
Prompt caching configuration
Claude Code automatically uses [prompt caching](prompt-caching.md) 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 the per-model settings |
| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for the [default Haiku model](prompt-caching.md#disable-prompt-caching) |
| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for the [default Sonnet model](prompt-caching.md#disable-prompt-caching) |
| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for the [default Opus model](prompt-caching.md#disable-prompt-caching) |
| `DISABLE_PROMPT_CACHING_FABLE` | Set to `1` to disable prompt caching for Fable models only |
To choose the cache TTL for the main conversation and for subagents separately, see [choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself). For what triggers a cache miss, see [How Claude Code uses prompt caching](prompt-caching.md).
[](#version-history)
Version history
This table lists the Claude Code version at which each model alias changed the model it resolves to, newest first.
| Version | Change |
|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|
| v2.1.284 | `sonnet` resolves to Sonnet 5.5 on the Anthropic API |
| v2.1.280 | `opus` resolves to Opus 5.5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Google Cloud’s Agent Platform |
| v2.1.257 | `fable` resolves to Fable 5.1, except in Claude apps gateway sessions |
| v2.1.219 | `opus` resolves to Opus 5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
| v2.1.207 | `opus` resolves to Opus 4.8 on Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
| v2.1.197 | `sonnet` resolves to Sonnet 5 on the Anthropic API |
| v2.1.154 | `opus` resolves to Opus 4.8 on the Anthropic API |
| Earlier | `opus` resolves to Opus 4.7 on Claude Platform on AWS and to Opus 4.6 on Amazon Bedrock and Agent Platform. `fable` resolves to Fable 5 on every provider |
---
## Output styles - Claude Code Docs
Source: https://code.claude.com/docs/en/output-styles
Path: 02-Claude-Code-CLI/output-styles.md
## On this page
- [Built-in output styles](#built-in-output-styles)
- [Default](#default)
- [Proactive](#proactive)
- [Concise](#concise)
- [Explanatory](#explanatory)
- [Learning](#learning)
- [Change your output style](#change-your-output-style)
- [Create a custom output style](#create-a-custom-output-style)
- [Frontmatter reference](#frontmatter)
- [Choose between an output style and other features](#choose-between-an-output-style-and-other-features)
- [How output styles work](#how-output-styles-work)
- [Related resources](#related-resources)
Model and responses
# Output styles
Copy pageCopy page
Change Claude Code’s role, tone, and response format with a built-in output style such as Concise or Explanatory, or write a custom style.
Copy pageCopy page
An output style is a set of instructions that sets Claude’s role, tone, and response format for every response in a session. Claude Code includes four built-in styles besides its default, and you can write your own. Use an output style to change the way Claude responds and works with you for a whole session, so you don’t repeat the request in each prompt. For example, a built-in style can make responses shorter, add an explanation of each change, or have Claude start work without asking routine questions. A custom style can also turn Claude into something other than a software engineer, such as a writing assistant or a data analyst.
- To use a built-in style, pick one from the [built-in output styles](#built-in-output-styles) and [switch to it](#change-your-output-style).
- To write your own instructions, [create a custom output style](#create-a-custom-output-style).
An output style gives Claude instructions to follow. It doesn’t guarantee that something always happens or never happens. Some needs fit a different feature:
- For what Claude should know about your project, use [CLAUDE.md](memory.md).
- For something that has to happen every time, such as formatting after each edit or blocking a command, use a [hook](../07-Hooks/hooks-guide.md).
- For skills, subagents, and the other options, see [Choose between an output style and other features](#choose-between-an-output-style-and-other-features).
[](#built-in-output-styles)
Built-in output styles
Claude Code starts in the [**Default**](#default) style, its standard instructions for completing software engineering tasks. Each of the four other built-in styles keeps those instructions and adds its own. This table shows what each style changes about a session and when it fits:
| Style | What changes | Use it when |
|:----------------------------|:----------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------|
| [Proactive](#proactive) | Claude starts work right away and makes reasonable assumptions rather than asking about routine decisions | You want Claude to keep working through routine decisions, and you’ll correct course if an assumption is wrong |
| [Concise](#concise) | Responses lead with the result and leave out preamble, narration, and recaps | Default responses are longer than you want |
| [Explanatory](#explanatory) | Claude adds short `Insight` blocks that explain the choices behind the code it writes | You’re getting to know a codebase or want the reasoning along with the change |
| [Learning](#learning) | Claude explains its choices and leaves small pieces of code for you to write yourself | You want hands-on coding practice while the task still gets done |
[](#default)
Default
Default means no output style is selected. Claude Code adds no style instructions, and Claude works from Claude Code’s standard system prompt, which is written for software engineering tasks. `default` appears in the `/output-style` list with the other styles, so you [select it the same way](#change-your-output-style).
[](#proactive)
Proactive
In the Proactive style, Claude starts implementing as soon as you send a task. It makes reasonable assumptions about routine decisions rather than stopping to ask, and it doesn’t switch to plan mode unless you ask for a plan. You can redirect it at any point. The style’s instructions also tell Claude to check with you in the conversation before an action that deletes data or changes a shared or production system. That check is an instruction Claude follows and is separate from permission prompts. Switching to the Proactive style doesn’t change your [permission mode](permission-modes.md). Your permission mode still decides which tool calls run without asking you, so permission prompts appear the same way they did before you switched.
[](#concise)
Concise
In the Concise style, the first sentence of a response states what happened or what the answer is. Claude leaves out the lead-in, the step-by-step narration, and the closing recap, and answers a simple question in one to three sentences. It does the engineering work as thoroughly as in the Default style. Requires Claude Code v2.1.237 or later. Claude still writes at full length in these cases:
- **Anything you ask for**: when you ask for an explanation or more detail, Claude answers in full.
- **Anything you need in order to act safely**: error reports, failing test output, security warnings, and confirmations for destructive actions keep their complete content.
[](#explanatory)
Explanatory
In the Explanatory style, Claude does the task the way it does in the Default style and adds short explanations of why it made the choices it made. Each explanation appears in the conversation, before or after the code it’s about, in a block labeled `Insight`. The explanations aren’t written into your files as comments. An `Insight` block carries two or three points about your codebase or the code Claude wrote, such as this one after adding an API endpoint:
```python
★ Insight ─────────────────────────────────────
- Every route in this repo goes through the withAuth wrapper, so the new endpoint gets session checks without its own middleware.
- Rate limits are set per route in limits.ts, which is why this change adds an entry there rather than a global default.
─────────────────────────────────────────────────
```
[](#learning)
Learning
In the Learning style, Claude adds the same `Insight` blocks as the [Explanatory style](#explanatory) and also asks you to write some of the code. Claude handles routine implementation itself. When it reaches a piece with a real design decision, such as error handling, a data structure, or business logic with more than one valid approach, it leaves a few lines for you. Claude marks the spot with a `TODO(human)` comment in the file, then sends a request that says what’s already built, what to write, and what to weigh:
```python
● Learn by Doing
Context: The upload form is in place and calls validateFile() before accepting a file. Size and type checks work for images, but the switch statement has no handling for documents yet.
Your Task: In upload.js, implement the case "document" branch inside validateFile(). Look for TODO(human).
Guidance: Decide on a size limit for documents and whether the file extension has to match the MIME type. Return {valid: boolean, error?: string}.
```
Claude then stops and waits. Write your code at the `TODO(human)` comment and tell Claude when you’re done. Claude responds with one `Insight` about your code and continues the task.
[](#change-your-output-style)
Change your output style
Pick a style with the command, a menu, or a settings file. The command and both menus save your choice to `.claude/settings.local.json` at the [local project level](settings.md).
- **`/output-style` command**: run `/output-style <style>` to switch, for example `/output-style concise`. With no argument, the command lists the styles you can pick and marks the current one. The command also works in [non-interactive mode](headless.md) and Agent SDK sessions, and from the mobile app or web via [Remote Control](remote-control.md#limitations), where you can list and select only [built-in styles](#built-in-output-styles). Requires Claude Code v2.1.269 or later.
- **Terminal menu**: run `/config` and select **Output style** to pick a style from a menu.
- **VS Code extension**: open the [command menu](../03-IDE-Integrations/vs-code.md#use-the-prompt-box) with `/` and select **Output styles** to pick a style, including your custom styles. Requires Claude Code v2.1.257 or later.
- **Desktop app**: set the `outputStyle` field in a settings file, for example `.claude/settings.local.json`, the file the terminal menu writes. When you run `/config` there, Claude Code [opens **Settings \> Claude Code**](../16-Mobile-Desktop/desktop.md#what%E2%80%99s-not-available-in-desktop) rather than a menu.
To set a style without the menu, edit the `outputStyle` field directly in a settings file:
```python
{
"outputStyle": "Explanatory"
}
```
The value is case-sensitive, so write the built-in names as `Proactive`, `Concise`, `Explanatory`, and `Learning`. A value that doesn’t match a style name exactly, such as `explanatory`, gives you the Default style. The `/output-style` command ignores case. To make a style your default across projects, set `outputStyle` in `~/.claude/settings.json`. A project’s own settings files [take precedence](settings.md#settings-precedence) over that value. When you switch styles mid-session, Claude uses the new style starting with your next message. For what that first message costs in prompt caching, see [Changing output style](prompt-caching.md#changing-output-style). Before v2.1.251, the new style applied only after you ran `/clear` or started a new session.
[](#create-a-custom-output-style)
Create a custom output style
A custom output style is a Markdown file: frontmatter for metadata, then the instructions for Claude. In the VS Code extension, you can also create the file from the [**Output styles** menu](../03-IDE-Integrations/vs-code.md#use-the-prompt-box) rather than writing it by hand. This requires Claude Code v2.1.261 or later.
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](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms)
Project output styles load from every `.claude/output-styles/` between the working directory and the repository root. When more than one of these nested directories defines a style with the same name, Claude Code uses the one closest to the working 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:
```python
---
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 `/output-style <style>` in the terminal, or run `/config` and select your style under **Output style**. Claude uses the new style starting with your next message. In the terminal, Claude Code reads style files when it starts, so if you create or edit one during a running session, restart Claude Code to pick up the change.
[Plugins](../08-Plugins-Skills/plugins-reference.md) can also ship output styles in an `output-styles/` directory.
[](#frontmatter)
Frontmatter reference
Configure an output style with YAML [frontmatter](glossary.md#frontmatter) between `---` markers at the top of the file. All fields are optional, and field names use lowercase words separated by hyphens. A misspelled field is ignored without an error. If the YAML doesn’t parse, the style still loads under its file name with no fields set; run `claude --debug` to see the parse error.
| Field | Required | Description |
|:---------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | No | Name of the output style, shown in the `/config` picker. Default: the file name |
| `description` | No | Description of the output style, shown in the `/config` picker |
| `keep-coding-instructions` | No | Set to `true` to keep Claude Code’s built-in software engineering instructions alongside your style. Default: `false` |
| `force-for-plugin` | No | Plugin output styles only. Set to `true` to 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. Default: `false` |
[](#choose-between-an-output-style-and-other-features)
Choose between an output style and other features
An output style applies to every response in a session. It’s an instruction Claude follows, so nothing enforces it. When what you want is narrower than every response, or has to happen without fail, another feature fits better. This table matches what you want to the feature that does it:
| You want | Use | Why it fits |
|:-----------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------|
| Every response in a certain voice, length, or format, or Claude in a different role | An output style | It applies to the whole session, and you switch styles with one command |
| Claude to know your project’s conventions, commands, and structure | [CLAUDE.md](memory.md) | It holds what Claude should know about the codebase, and it stays loaded whichever style you pick |
| Instructions for one kind of task, such as a release checklist or a review procedure | A [skill](../08-Plugins-Skills/skills.md) | Claude loads it only when you invoke it or the task matches, so it doesn’t shape unrelated responses |
| Something to happen every time without exception, such as formatting after each edit or blocking a command | A [hook](../07-Hooks/hooks-guide.md) | Claude Code runs a hook itself at a lifecycle event, so it doesn’t depend on Claude following an instruction |
| A helper with its own instructions, model, and tools for a focused task | A [subagent](../09-Agents-Patterns/sub-agents.md) | It runs in a separate context with its own system prompt and returns a summary to your conversation |
| An addition to Claude’s instructions that you pass when you start Claude Code | [`--append-system-prompt`](cli-reference.md#system-prompt-flags) | It appends to the system prompt without removing anything |
These features combine. For example, you can use CLAUDE.md for what Claude should know, an output style for how it responds, and a hook for anything that has to be guaranteed. [Extend Claude Code](features-overview.md) compares the rest of the extension features.
[](#how-output-styles-work)
How output styles work
An output style changes the instructions Claude Code gives Claude.
- Claude Code sends the active style’s instructions with every request.
- 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`.
Output styles apply to the main conversation and to a [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), which inherits the parent’s full conversation and system prompt. Other [subagents run their own system prompt](../09-Agents-Patterns/sub-agents.md#what-loads-at-startup), so styles don’t change how they respond. Token usage depends on the style. A style’s instructions add 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. The Concise style does the opposite by instructing Claude to keep responses short by default. For custom styles, output token usage depends on what your instructions tell Claude to produce.
[](#related-resources)
Related resources
- [Settings](settings.md): where the `outputStyle` field lives and how settings precedence works
- [Permission modes](permission-modes.md): how the Proactive style compares to auto mode
- [Plugins](../08-Plugins-Skills/plugins.md): package and distribute output styles alongside skills, hooks, and agents
- [Debug your configuration](debug-your-config.md): diagnose why an output style isn’t taking effect
---
## Choose a permission mode - Claude Code Docs
Source: https://code.claude.com/docs/en/permission-modes
Path: 02-Claude-Code-CLI/permission-modes.md
## On this page
- [Available modes](#available-modes)
- [Actions no mode auto-approves](#actions-no-mode-auto-approves)
- [Common setups](#common-setups)
- [Which mode a session starts in](#which-mode-a-session-starts-in)
- [Start in a different permission mode](#start-in-a-different-mode)
- [Switch permission modes](#switch-permission-modes)
- [Auto-approve file edits with acceptEdits mode](#auto-approve-file-edits-with-acceptedits-mode)
- [Analyze before you edit with plan mode](#analyze-before-you-edit-with-plan-mode)
- [Review and approve a plan](#review-and-approve-a-plan)
- [Set plan mode as the default](#set-plan-mode-as-the-default)
- [Eliminate permission prompts with auto mode](#eliminate-prompts-with-auto-mode)
- [Auto mode on Bedrock, Agent Platform, or Foundry](#enable-auto-mode-on-bedrock-agent-platform-or-foundry)
- [Server-side classifier review](#server-side-classifier-review)
- [What the classifier blocks by default](#what-the-classifier-blocks-by-default)
- [The first read outside the working directories](#first-read-outside-the-working-directories)
- [Boundaries you state in conversation](#boundaries-you-state-in-conversation)
- [Approvals you state in conversation](#approvals-you-state-in-conversation)
- [When auto mode falls back](#when-auto-mode-falls-back)
- [Repeated-block thresholds](#repeated-block-thresholds)
- [How auto mode evaluates actions](#how-auto-mode-evaluates-actions)
- [Allow only pre-approved tools with dontAsk mode](#allow-only-pre-approved-tools-with-dontask-mode)
- [Skip all checks with bypassPermissions mode](#skip-all-checks-with-bypasspermissions-mode)
- [Protected paths](#protected-paths)
- [Critical paths](#critical-paths)
- [Which paths are critical](#which-paths-are-critical)
- [Other targets that count as critical paths](#other-targets-that-count-as-critical-paths)
- [Removals inside nested commands and inline scripts](#removals-inside-nested-commands-and-inline-scripts)
- [Rewrite a flagged command](#rewrite-a-flagged-command)
- [Critical-path removals in each permission mode](#critical-path-removals-in-each-permission-mode)
- [Time limits and denials in auto and bypassPermissions modes](#time-limits-and-denials-in-auto-and-bypasspermissions-modes)
- [Remove-Item in PowerShell](#remove-item-in-powershell)
- [See also](#see-also)
Permissions and sandboxing
# Choose a permission mode
Copy pageCopy page
Control whether Claude asks before acting. Switch permission modes with Shift+Tab in the CLI, the mode indicator in VS Code, or the mode selector in Desktop.
Copy pageCopy page
A permission mode sets which actions Claude can take in a session without asking you first. In Manual mode, Claude Code stops and asks you before most actions that edit files, run shell commands, or reach the network. In [auto mode](#eliminate-prompts-with-auto-mode), a second model, the classifier, reviews actions instead of you; [how the classifier evaluates actions](#how-the-classifier-evaluates-actions) lists which actions it reviews and which skip it. With Claude Code v2.1.283 or later, auto mode is the built-in starting permission mode for interactive terminal and VS Code sessions. On earlier versions, it’s the built-in starting permission mode only on Pro, Max, and Team plans. [Which mode a session starts in](#which-mode-a-session-starts-in) covers the surfaces and settings that change the starting permission mode. You can also change a running session’s permission mode at any time.
[](#available-modes)
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. Manual mode appears under its config value, `default`.
| Mode | What runs without asking | Best for |
|:--------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------|:------------------------------------------------|
| `default` | Reads only | Reviewing every action yourself, sensitive work |
| [`acceptEdits`](#auto-approve-file-edits-with-acceptedits-mode) | Reads, file edits, and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) | Iterating on code you’re reviewing |
| [`plan`](#analyze-before-you-edit-with-plan-mode) | Reads, plus classifier-approved commands when [auto mode](#eliminate-prompts-with-auto-mode) is available | Exploring a codebase before changing it |
| [`auto`](#eliminate-prompts-with-auto-mode) | Everything, with background safety checks | Long tasks, reducing prompt fatigue |
| [`dontAsk`](#allow-only-pre-approved-tools-with-dontask-mode) | Reads and pre-approved tools; anything that would prompt is denied | Locked-down CI and scripts |
| [`bypassPermissions`](#skip-all-checks-with-bypasspermissions-mode) | Everything | Isolated containers and VMs only |
The mode that reviews every action is named **Manual** in the CLI, in `claude --help`, in the VS Code and JetBrains extensions, and in the desktop app. Its config value is `default`, which is what hooks and SDK integrations use. The CLI accepts `manual` as an alias wherever you type the value, for example `claude --permission-mode manual` or `"defaultMode": "manual"`. The Manual label and the `manual` alias require Claude Code v2.1.200 or later. The desktop app’s label doesn’t depend on your CLI version. Writes to [protected paths](#protected-paths) are never auto-approved except in `bypassPermissions` mode and in plan-mode sessions where bypass permissions are available, meaning interactive terminal sessions started in a way that [puts `bypassPermissions` in the mode cycle](#switch-permission-modes). Modes set the baseline. Layer [permission rules](permissions.md#manage-permissions) on top to pre-approve or block specific tools. Deny rules block in every mode, including `bypassPermissions`. Deny and ask rules don’t apply to [`EndConversation`](tools-reference.md#endconversation-tool-behavior) as long as Claude still has at least one other tool it can call. Allow rules have no effect in `bypassPermissions`.
[](#actions-no-mode-auto-approves)
Actions no mode auto-approves
Claude Code doesn’t auto-approve the following in any mode, including `bypassPermissions`. Each bullet links to the section that says what happens instead in each mode:
- Tools matched by an explicit [ask rule](permissions.md#manage-permissions)
- Connector tools your organization [set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools), in sessions where that setting reaches Claude Code
- Tools that require user interaction: the built-in `AskUserQuestion` tool and MCP tools marked [`requiresUserInteraction`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool)
- `rm` and `rmdir` removals targeting a [critical path](#critical-paths), which no allow rule or `PreToolUse` hook `"allow"` approves
- The [cross-session messaging safeguards](#skip-all-checks-with-bypasspermissions-mode)
- Reads outside the working directories while [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) is on: recognized file-reading Bash commands prompt even in auto mode and `bypassPermissions` mode, and so does any [unsandboxed retry](sandboxing.md#the-unsandboxed-retry-escape-hatch) that needs approval to run outside the sandbox. Requires Claude Code v2.1.257 or later. A command the shell parser can’t trace, such as one that changes directory more than once or runs a subshell, prompts the same way even when it names no outside path. This prompt doesn’t apply when the command runs in the [sandbox](sandboxing.md) and the sandbox enforces the block.
[](#common-setups)
Common setups
Permission modes decide whether Claude asks before an action, and the [Bash sandbox](sandboxing.md) and outer [isolation boundaries](sandbox-environments.md) decide what an action can reach once it runs. Each row below pairs a goal with the flags or settings that get you there and the isolation it needs, as a starting point. [Available modes](#available-modes) lists what runs without a prompt in each mode.
| You want to | Start with | Isolation needed | Notes |
|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Review every action yourself | Manual mode: `claude --permission-mode default` | None | Sensitive work, unfamiliar code |
| Iterate locally with fewer prompts, without a classifier | Manual mode plus the Bash sandbox in [auto-allow mode](sandboxing.md#sandbox-modes): `claude --permission-mode default`, then run `/sandbox` and select auto-allow | The built-in Bash sandbox, on macOS, Linux, and WSL2 | Deny rules still apply, and ask rules that name a command, such as `Bash(git push *)`, still prompt. To turn the sandbox on from a settings file instead, set [`sandbox.enabled`](settings-reference.md#sandbox-enabled) to `true` |
| Explore before changing anything | `claude --permission-mode plan` | None | Claude Code blocks edits until you [approve a plan](#review-and-approve-a-plan) |
| Work hands-off in auto mode | `claude --permission-mode auto`, the [built-in starting permission mode](#which-mode-a-session-starts-in) with v2.1.283 or later | None; a sandbox or container adds defense in depth | Requires a [supported model](#eliminate-prompts-with-auto-mode), and your organization can [turn auto mode off](#eliminate-prompts-with-auto-mode) |
| Run in CI with an exact allowlist | `claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"` | None beyond what your CI runner provides | [Cloud sessions](claude-code-on-the-web.md) ignore `dontAsk` from settings files |
| Run fully unattended inside a container | `claude -p "<prompt>" --dangerously-skip-permissions` | Required: a container, VM, or the [sandbox runtime](sandbox-environments.md#sandbox-runtime); on Linux and macOS, run it as a [non-root user](#skip-all-checks-with-bypasspermissions-mode) | Cloud sessions ignore this mode from settings files. In this `-p` run, the [few calls that would still prompt](#skip-all-checks-with-bypasspermissions-mode) are denied instead |
The Bash sandbox and auto mode work independently and combine, with the exceptions listed under [Sandbox modes](sandboxing.md#sandbox-modes). For the full interaction, see [How sandboxing relates to permissions and permission modes](sandboxing.md#how-sandboxing-relates-to-permissions-and-permission-modes) and [How isolation relates to permission modes](sandbox-environments.md#how-isolation-relates-to-permission-modes).
[](#which-mode-a-session-starts-in)
Which mode a session starts in
When you start a new session in a terminal, Claude Code takes the permission mode from the first of these that applies:
1. The `--permission-mode` flag, or `--dangerously-skip-permissions`
2. `permissions.defaultMode` in a [settings file](settings.md#where-settings-live) If you set `"auto"` in `.claude/settings.json` or `.claude/settings.local.json`, the value doesn’t take effect, and Claude Code then uses the built-in default rather than a `defaultMode` from `~/.claude/settings.json`. If you set `"bypassPermissions"` in those two files, it doesn’t take effect either, and the session starts in Manual mode. The other values apply from any settings file.
3. The built-in default
Conversations the VS Code extension starts follow the extension’s own list in [Switch permission modes](#switch-permission-modes). For the permission mode Claude Code starts a resumed session in, see [permission mode on resume](sessions.md#permission-mode-on-resume). The built-in `auto` default requires Claude Code v2.1.228 or later on macOS, Linux, and WSL, and v2.1.233 or later on native Windows. On earlier versions, the built-in default is Manual. The built-in default depends on how you run Claude Code. The first row that matches your session applies. The table covers sessions you start in a terminal or through the VS Code extension; for the desktop app and claude.ai, see the Desktop and Web tabs in [Switch permission modes](#switch-permission-modes).
| How you run Claude Code | Built-in starting permission mode |
|:-------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Any settings file sets `disableAutoMode` to `"disable"` | `default` |
| `claude -p` or the [Agent SDK](../05-Agent-SDK/agent-sdk-permissions.md) | `default` |
| In a terminal or through the [VS Code extension](../03-IDE-Integrations/vs-code.md) | `auto` with Claude Code v2.1.283 or later; on earlier versions, `auto` on Pro, Max, or Team plans in sessions that [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), and `default` otherwise |
In your [first session after an install or upgrade](env-vars.md#first-session-after-an-install-or-upgrade), Claude Code can choose the starting permission mode before its feature flags arrive. That session can start in a different permission mode than the table gives, and your next session matches the table. When the flag, a settings file, or the built-in default selects `auto` but auto mode isn’t available to the session, Claude Code starts the session in Manual instead. Auto mode is unavailable when the session doesn’t meet the [availability requirements](#eliminate-prompts-with-auto-mode), such as a settings file turning it off or a model that doesn’t support it, or when Anthropic has temporarily turned it off server-side. The first time the built-in default starts one of your sessions in auto mode, Claude Code shows a notice that links to this page:
- In a terminal, once, at the top of the session
- In the VS Code extension, as a card on the new-conversation screen that stays until you dismiss it
On Pro, Max, and Team plans, if your `~/.claude/settings.json` sets a `defaultMode` other than `auto` and no other settings file sets one, your sessions keep starting in that mode. Claude Code asks once, in the terminal or in the VS Code extension, whether to change the setting to auto mode. If you decline, your setting stays as it is.
[](#start-in-a-different-mode)
Start in a different permission mode
You can set the starting permission mode for one session, or as a default for every session on a machine, in a project, or in an organization. When more than one settings file sets `permissions.defaultMode`, [settings precedence](settings.md#settings-precedence) decides, so a project or managed value outranks `~/.claude/settings.json`. To change the permission mode of a session that’s already running, see [Switch permission modes](#switch-permission-modes).
| To set the starting permission mode for | Do this |
|:-------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| One session you’re about to start | Pass the permission mode as a flag, for example `claude --permission-mode default` |
| Every terminal session you start on this machine | Set `permissions.defaultMode` in `~/.claude/settings.json`. For what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes) |
| Every terminal session you start in one project | Set `permissions.defaultMode` in the project’s `.claude/settings.json`. Sessions you start in a terminal honor every value except `auto` and `bypassPermissions`; sessions the VS Code extension starts don’t read project settings for the starting permission mode |
| Every terminal session in your organization | Set `permissions.defaultMode` in [managed settings](../13-Enterprise-Admin/managed-settings.md). Terminal sessions start in that mode and people can still switch to auto mode; for what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes). To remove auto mode so nobody can select it, set `permissions.disableAutoMode` to `"disable"` instead |
This example makes every terminal session on your machine start in Manual mode, whose config value is `default`. Save it in `~/.claude/settings.json`:
```python
{
"permissions": {
"defaultMode": "default"
}
}
```
The next session you start shows `⏸ manual mode on` in the status bar.
[](#switch-permission-modes)
Switch permission modes
Each interface has its own control for switching permission modes during a session and its own way of choosing the permission mode new sessions start in. Select your interface to see its controls.
- CLI
- VS Code
- JetBrains
- Desktop
- Web and mobile
**During a session**: press `Shift+Tab` to cycle permission modes. From `auto`, the first press switches to `default`, and the cycle then runs `default` → `acceptEdits` → `plan` → back to `default`. Optional modes, described below, slot in after `plan`. The status bar shows the active mode as a gray `⏸ manual mode on` for `default`, or as `⏵⏵ accept edits on`, `⏸ plan mode on`, `⏵⏵ auto mode on`, `⏵⏵ don't ask on`, or `⏵⏵ bypass permissions on`.Not every mode is in the default cycle:
- `auto`: appears when [auto mode is available](#eliminate-prompts-with-auto-mode); cycling to it switches permission modes without a confirmation prompt
- `bypassPermissions`: appears after you start with `--permission-mode bypassPermissions`, `--dangerously-skip-permissions`, `--allow-dangerously-skip-permissions`, or `permissions.defaultMode: "bypassPermissions"` in [user, `--settings`, or managed settings](settings-reference.md#permissions-defaultmode). The `--allow-` variant adds the permission 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`.**From a Bash permission prompt**: in the Manual and `acceptEdits` permission modes, when [auto mode](#eliminate-prompts-with-auto-mode) is available, Claude Code adds **Yes, and switch to auto mode** to a Bash command’s permission prompt. Select it to approve the command and switch the session to auto mode. [PowerShell tool](tools-reference.md#powershell-tool) prompts don’t offer the option. Requires Claude Code v2.1.247 or later.Claude Code doesn’t add the option to prompts forced by one of your [`ask` rules](permissions.md#manage-permissions) or by a [hook](../07-Hooks/hooks.md#pretooluse-decision-control), because auto mode still shows you those prompts, so switching wouldn’t remove them.**At startup**: pass the permission mode as a flag.
```python
claude --permission-mode plan
```
**As a default**: set `permissions.defaultMode` at the scope you want, as described in [Start in a different permission mode](#start-in-a-different-mode).The same `--permission-mode` flag works with `-p` for [non-interactive runs](headless.md).
**During a session**: click the mode indicator at the bottom of the prompt box. It uses these labels for the modes on this page:
| UI label | Mode |
|:-------------------|:--------------------|
| Manual | `default` |
| Edit automatically | `acceptEdits` |
| Plan | `plan` |
| Auto | `auto` |
| Bypass permissions | `bypassPermissions` |
**As a default**: to pin the permission mode conversations start in, set `claudeCode.initialPermissionMode` in your VS Code user settings to `default`, `manual`, `acceptEdits`, `plan`, or `bypassPermissions`. The setting doesn’t accept `auto`; to start in Auto, leave it unset and pick **Auto** from the mode indicator once, as item 2 below describes. The extension starts each new conversation in the first of these that applies:
1. `claudeCode.initialPermissionMode`
2. The mode you last picked from the mode indicator, if it was Manual, Edit automatically, or Auto. Picking Plan or Bypass permissions applies to that conversation only
3. `permissions.defaultMode` from [managed settings](../13-Enterprise-Admin/managed-settings.md) or `~/.claude/settings.json`
4. The [built-in default](#which-mode-a-session-starts-in) for your plan, provider, and organization settings
The extension never reads a project’s `.claude/settings.json` or `.claude/settings.local.json` for the starting permission mode. When `claudeCode.claudeProcessWrapper` is set, items 3 and 4 don’t apply: those conversations start in Manual unless item 1 or item 2 sets a permission mode.Before v2.1.283, item 3 applied only on Pro, Max, and Team plans in sessions that [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching).Auto appears in the mode indicator when [auto mode is available](#eliminate-prompts-with-auto-mode).Bypass permissions requires the **Allow dangerously skip permissions** toggle in the extension settings. Without it, the permission mode doesn’t appear in the indicator, and a `bypassPermissions` value from item 1 or item 3 starts the conversation in Manual instead. Auto from any item likewise starts the conversation in Manual when auto mode isn’t available.See the [VS Code guide](../03-IDE-Integrations/vs-code.md) for extension-specific details.
The JetBrains plugin runs Claude Code in the IDE terminal, so switching permission modes works the same as in the CLI: press `Shift+Tab` to cycle, or pass `--permission-mode` when launching.
**During a session**: in the Code tab, use the mode selector next to the send button. Not every mode appears in the selector:
- **Auto**: appears when [auto mode is available](#eliminate-prompts-with-auto-mode)
- **Bypass permissions**: requires the **Allow bypass permissions mode** toggle in Desktop settings on Pro and Max plans; on Team and Enterprise plans, organization policy controls it instead
The Cowork tab doesn’t use these modes. Cowork has its own permission modes, enabled separately, and the Cowork tab shows no mode selector at all until a mode beyond its default is enabled for your account. See the [Cowork docs](https://claude.com/docs/cowork/overview).For desktop-specific details, see [Choose a permission mode](../16-Mobile-Desktop/desktop.md#choose-a-permission-mode) in the Desktop guide.**As a default**: set `defaultMode` in [settings](settings.md#where-settings-live). The desktop app reads the same settings files as the CLI and applies the permission mode to new local sessions.A mode you pick in the mode selector is remembered per folder and takes precedence over `defaultMode` for that folder. Plan is the exception: picking it applies to the current session only.For where `defaultMode` goes in a settings file, see the example under [Start in a different permission mode](#start-in-a-different-mode).
Use the mode dropdown next to the prompt box on [claude.ai/code](https://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](claude-code-on-the-web.md)**: Accept edits, Plan, and Auto. Accept edits corresponds to `default` mode: cloud sessions pre-approve file edits regardless of mode, so the dropdown shows Accept edits instead of Manual. Cloud sessions still honor `defaultMode: "acceptEdits"` from settings. Auto mode appears only when your organization allows it and the selected model supports it. Bypass permissions isn’t available.
- **[Remote Control](remote-control.md) sessions** on your local machine: Manual, Accept edits, and Plan for a session you started yourself, and you can’t select Auto or Bypass permissions from the app. For a project thread running on your computer, see [Run a thread on your own computer](claude-projects.md#run-a-thread-on-your-own-computer).
- Except for Bypass permissions, the dropdown shows the permission mode the local session is in, including one set from the terminal. It updates when the permission mode changes in the app or in the terminal.
- Sessions hosted by the [desktop app](../16-Mobile-Desktop/desktop.md) or the [VS Code extension](../03-IDE-Integrations/vs-code.md) report permission mode changes to claude.ai as they happen, the same as sessions hosted in a terminal.
- Before v2.1.202, sessions connected with `/remote-control` or `claude --remote-control` didn’t report their permission mode at all, so claude.ai and the mobile app could show a permission mode the session wasn’t in. The mismatch affected only the label. Claude Code generated permission prompts from the session’s actual permission mode, and they still appeared in the app for approval.
For Remote Control, the local machine running the session must be signed in with your claude.ai account; API keys aren’t supported. You can also set the starting permission mode when launching that local session:
```python
claude remote-control --permission-mode acceptEdits
```
[](#auto-approve-file-edits-with-acceptedits-mode)
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`. Each path also goes through the [symlink check](permissions.md#symlinks), so a write that resolves outside that scope isn’t auto-approved either. Paths outside that scope, writes to [protected paths](#protected-paths), `rm` and `rmdir` removals targeting a [critical path](#critical-paths), and all other Bash commands except the [built-in read-only set](permissions.md#read-only-commands) still prompt. When the [PowerShell tool](tools-reference.md#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, and `Remove-Item` gets [its own check](#remove-item-in-powershell). A positional argument that contains a quote character, such as the apostrophe in `Set-Content .\notes.txt "It's done"`, still prompts even on in-scope paths, because Claude Code can’t statically validate an argument whose quoted and unquoted readings differ. Pass the content through a named parameter such as `-Value` to avoid the prompt. 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 Manual mode to enter it, or start with it directly:
```python
claude --permission-mode acceptEdits
```
[](#analyze-before-you-edit-with-plan-mode)
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. Except in interactive terminal sessions with [bypass permissions available](#skip-all-checks-with-bypasspermissions-mode), edits stay blocked until you approve the plan. What happens to a shell command during planning depends on the session, and the first of these cases that matches applies:
- **Interactive terminal sessions with bypass permissions available**: neither the classifier nor a prompt applies to planning commands. [Skip all checks with bypassPermissions mode](#skip-all-checks-with-bypasspermissions-mode) covers the few things that still prompt there.
- **[Auto mode](auto-mode-config.md) available and the `useAutoModeDuringPlan` setting on**, which it is by default: the classifier reviews shell commands other than [critical-path removals](#critical-paths) instead of prompting you. Approved commands run, and rejected ones are blocked.
- **Auto mode not available, or `useAutoModeDuringPlan` off**: commands outside the [built-in read-only set](permissions.md#read-only-commands) prompt for approval, including when the sandbox’s [auto-allow mode](sandboxing.md#sandbox-modes) is enabled.
Enter plan mode by pressing `Shift+Tab` or prefixing a single prompt with `/plan`. You can also start in plan mode from the CLI:
```python
claude --permission-mode plan
```
Press `Shift+Tab` again to leave plan mode without approving a plan.
[](#review-and-approve-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 choose:
- **Yes, and use auto mode**: approve and start in [auto mode](#eliminate-prompts-with-auto-mode). If auto mode isn’t [available to your session](#eliminate-prompts-with-auto-mode), for example because your organization turned it off, this option reads **Yes, auto-accept edits**. If you started the session with bypass permissions enabled, the option reads **Yes, and switch to BYPASS PERMISSIONS (no further prompts) for this session** instead.
- **Yes, manually approve edits**: approve and review each edit individually.
- **No, keep planning**: stay in plan mode and tell Claude what to change.
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`](settings-reference.md#showclearcontextonplanaccept) is enabled, the list gains a first option that approves the plan and clears the planning context. Accepting a plan also gives the session a [generated title](sessions.md#name-your-sessions) based on the plan, unless you’ve already named the session.
[](#set-plan-mode-as-the-default)
Set plan mode as the default
To make plan mode the default for a project’s terminal sessions, set `defaultMode` to `plan` in `.claude/settings.json`, placed as the example under [Start in a different permission mode](#start-in-a-different-mode) shows. Conversations the [VS Code extension](../03-IDE-Integrations/vs-code.md) starts don’t read project settings for the starting permission mode. There, set `claudeCode.initialPermissionMode` to `plan` in your VS Code user settings instead.
[](#eliminate-prompts-with-auto-mode)
Eliminate permission prompts with auto mode
Auto mode lets Claude execute without routine 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. Explicit [ask rules](permissions.md#manage-permissions) still force a prompt. With Claude Code v2.1.283 or later, auto mode is the [built-in starting permission mode](#which-mode-a-session-starts-in) for interactive terminal and VS Code sessions on every plan and provider. On earlier versions, it’s the built-in starting permission mode only on Pro, Max, and Team plans. The classifier also reviews each message Claude sends to another agent with [`SendMessage`](tools-reference.md), whether plain text or a structured [agent team](../09-Agents-Patterns/agent-teams.md) message, before Claude Code delivers it, both in auto mode and in [plan mode while the classifier reviews commands](#analyze-before-you-edit-with-plan-mode); the send review requires Claude Code v2.1.222 or later. By default, the classifier doesn’t review `rm` and `rmdir` removals targeting a critical path, such as `rm -rf /` or `rm -rf ~`. [Critical paths](#critical-paths) covers what happens to them in each permission mode. Auto mode also nudges Claude to keep working without stopping for clarifying questions, though Claude still asks when your prompt or a skill explicitly relies on it. For stronger autonomous behavior in a mode that still prompts you, set the [Proactive output style](output-styles.md) instead.
Auto mode reduces permission 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**: All plans.
- **Organization**: on Team and Enterprise, auto mode is available by default. Administrators can turn it off for the organization by setting `permissions.disableAutoMode` to `"disable"` in [managed settings](../13-Enterprise-Admin/managed-settings.md).
- **Model**: on the Anthropic API and [Claude Platform on AWS](claude-platform-on-aws.md), Claude Opus 4.6 or later, Sonnet 4.6 or later, or a [Fable model](model-config.md#work-with-fable). On Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and signed-in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions, only Claude Sonnet 5 or later, Opus 4.7 or later, and the Fable models. Older models, including Sonnet 4.5, Opus 4.5, Haiku, and claude-3 models, are not supported on any provider.
- **Provider**: available by default on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and signed-in Claude apps gateway sessions.
If Claude Code reports auto mode as unavailable, first check these requirements and whether any settings file sets [`disableAutoMode`](settings-reference.md#disableautomode). Anthropic may also have turned auto mode off server-side, or the server may have rejected auto mode for your account. A session that received either answer keeps auto mode off until the session ends, so start a new session later. A separate message that names a model and says auto mode “cannot determine the safety” of an action means a classifier request failed. That failure is usually transient, but on Amazon Bedrock it can repeat until your account can invoke the named model. See the [error reference](errors.md#auto-mode-cannot-determine-the-safety-of-an-action) for the causes and what to do. If you set `defaultMode: "auto"` in [settings](settings-reference.md#all-settings) and a terminal session starts in Manual mode with no error, the setting is likely in `.claude/settings.json` or `.claude/settings.local.json`. `auto` doesn’t take effect from those files. Move it to `~/.claude/settings.json`. For a conversation the VS Code extension started, check the extension’s own list in [Switch permission modes](#switch-permission-modes) instead.
[](#enable-auto-mode-on-bedrock-agent-platform-or-foundry)
Auto mode on Bedrock, Agent Platform, or Foundry
On [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), [Microsoft Foundry](microsoft-foundry.md), and signed-in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) sessions, auto mode is available by default. With Claude Code v2.1.283 or later, it’s also the [built-in starting permission mode](#which-mode-a-session-starts-in) for interactive terminal and [VS Code](../03-IDE-Integrations/vs-code.md) sessions. To choose the starting permission mode yourself, set `permissions.defaultMode` as [Start in a different permission mode](#start-in-a-different-mode) describes, or pick a permission mode from the VS Code extension’s mode indicator. Only Claude Sonnet 5 or later, Opus 4.7 or later, and the Fable models are supported on these providers. On any other model, the session starts in Manual instead. To prevent developers from using auto mode, set `disableAutoMode` to `"disable"` in [managed settings](../13-Enterprise-Admin/managed-settings.md). This removes `auto` from the `Shift+Tab` cycle, and a session started with `--permission-mode auto` starts in Manual instead. A session already running in auto mode leaves it when the setting reaches that session from an [admin-deployed source](../13-Enterprise-Admin/managed-settings.md#which-managed-source-claude-code-uses), and shows `auto mode disabled by settings`. Before v2.1.251, a running session kept auto mode until it ended. In v2.1.158 through v2.1.206, auto mode was off on these providers until you set `CLAUDE_CODE_ENABLE_AUTO_MODE=1`, and Claude Code ignored `defaultMode: "auto"` on these providers unless the variable was also set. The variable is still accepted for compatibility and has no effect from v2.1.207 onward.
[](#server-side-classifier-review)
Server-side classifier review
In auto mode, Claude Code can ask the server to check the actions that [the decision order](#how-the-classifier-evaluates-actions) sends for review, as part of the session’s model requests, in place of sending its own classifier requests. These sessions ask:
- **A direct connection to the Anthropic API**: in an interactive terminal session, on every claude.ai plan and on accounts that use the Claude API, as Anthropic rolls it out. Requires Claude Code v2.1.271 or later on Pro, Max, and Team plans, and v2.1.278 or later on Enterprise plans and Claude API accounts. From v2.1.282, a session that [doesn’t fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), for example because you turned telemetry off, asks the server by default in any kind of session.
- **A cloud provider, or an LLM gateway or proxy**: on [Claude Platform on AWS](claude-platform-on-aws.md), Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, and whenever you point `ANTHROPIC_BASE_URL` at an [LLM gateway or proxy](../13-Enterprise-Admin/llm-gateway.md), whatever your plan. Asking by default requires Claude Code v2.1.278 or later.
- **A signed-in [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md) session**: requires Claude Code v2.1.280 or later
Where the server reviews the actions, its verdicts decide them. Two other outcomes are possible:
- **The server doesn’t review the session**: a response completes with no review results, or the server answers that it doesn’t review this session. The most common causes are an LLM gateway or proxy that drops the request for review or the results, and a platform, region, or credential that doesn’t have server-side checks yet. Claude Code falls back to its own classifier requests. Once that fallback holds for the rest of the session, it shows a [notice about classifier request charges](../17-Billing-Plans/auto-mode-classifier-billing.md) on accounts where those requests are billed.
- **The server gives no verdict for an action**: Claude Code denies the action rather than run it unreviewed. On any connection, this happens when the response ends before the review results arrive or the results arrive in a form Claude Code can’t read. An LLM gateway or proxy that cuts responses short or rewrites the results can cause either. On a direct connection to the Anthropic API, it also happens when the server’s check fails for the action, for example by timing out. [The server returned no safety verdict](errors.md#the-server-returned-no-safety-verdict) covers the denial message, what happens when denials repeat, and what to do.
To skip asking the server and always use Claude Code’s own classifier requests, set [`CLAUDE_CODE_AUTO_MODE_SERVER=0`](env-vars.md). On a direct connection to the Anthropic API, the variable requires Claude Code v2.1.281 or later. Setting it to `1` there turns server review on in a session that doesn’t have it yet, such as a `-p` or Agent SDK session, unless you’ve also set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`. If you set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` and leave `CLAUDE_CODE_AUTO_MODE_SERVER` unset, Claude Code also stops asking the server, except as [Disable pre-release capabilities](../13-Enterprise-Admin/llm-gateway-protocol.md#disable-pre-release-capabilities) describes.
[](#what-the-classifier-blocks-by-default)
What the classifier blocks by default
The classifier trusts your working directory and the remotes that were configured for it when the session started. A remote added or repointed during the session with `git remote add` or `git remote set-url` isn’t trusted, and everything else is treated as external until you [configure trusted infrastructure](auto-mode-config.md). Before v2.1.200, remotes added mid-session were also trusted. **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
- Committing or pushing a change that would send secrets or sensitive data outside the repository when it runs, or widen what a deploy exposes. This covers a CI workflow or deploy configuration that passes a secret to a destination that doesn’t already receive it, a script or setup step that reads a secret store and sends the data out, and a config change that widens what a deploy publishes, such as a registry, visibility, artifact, or sourcemap setting. The check applies on any branch, applies even when the repository is public, and fires when the change is committed or pushed, whether or not that commit or push triggers the pipeline; clearing it requires naming the execution effect, not only the commit or push. Before v2.1.211, this check was scoped to the default branch instead: a push there was blocked when it carried sensitive content, changes concealed or misdescribed relative to what you asked for, content ported in from outside the repository, or routed around a review you asked for
- `git reset --hard`, `git checkout -- .`, `git restore .`, `git clean -fd`, `git stash drop`, or `git stash clear`, which the classifier presumes would discard uncommitted changes
- `git commit --amend` when the commit at HEAD was not created in this session
- From v2.1.198, `git commit --amend` when the commit at HEAD has already been pushed. A message-only reword is not blocked: `--amend -m` with nothing newly staged, on a commit that Claude created during this session
- `terraform destroy`, `pulumi destroy`, `cdk destroy`, or `terragrunt destroy`, and applying a plan that destroys resources
- Writing to a secret manager, or changing DNS records or TLS certificates
- Merging a pull request no human has approved, approving Claude’s own pull request, or disabling CI checks
- Posting a comment that is itself a command to automation, such as `atlantis apply` or a bot’s `/deploy` or `/merge`
- Toggling, ramping, or deleting a production feature flag
- Applying infrastructure changes to a protected IaC scope, or draining and removing cluster nodes
- Writes to a shared compute cluster that reach beyond the resource you named, such as a label selector or `--all` that catches other users’ jobs
- Creating Kubernetes resources that run on every node or intercept cluster traffic, such as DaemonSets and admission webhooks
- Interactive shells or port-forwards into a sensitive remote target
- Opening a tunnel or reverse shell that makes a local service reachable from the public internet
- Printing a live credential or token into the transcript or a file
- Accessing a location listed as a sensitive data location in your [environment](auto-mode-config.md#define-trusted-infrastructure), or copying data out of one. As of v2.1.198 this also blocks sending data from one to an audience the entry excludes
- Routing a package install around your internal package registry to a public registry. As of v2.1.198, this also applies when you’ve told Claude an internal registry or mirror exists in the conversation, not only when one is listed in your environment
- Running a command with a flag that disarms a safety guard, like `--insecure`
- Launching an autonomous agent loop that runs without human approval or a sandbox, such as one started with `--dangerously-skip-permissions` or `--no-sandbox`. As of v2.1.198 this also covers running a third-party agent or eval harness with isolation and per-action approval disabled, such as a runner started with `--yes-always`
- [Claude in Chrome](../03-IDE-Integrations/chrome.md) browser actions that could send page content, cookies, or credentials off-origin
Several of these categories depend on [environment](auto-mode-config.md#define-trusted-infrastructure) entries, such as sensitive remote targets and protected IaC scopes, that you can narrow to concrete names. Claude Code v2.1.198 and later also block these by default:
- Deleting files in `/tmp`, `$TMPDIR`, or another shared scratch or cache directory by wildcard, glob, or age filter rather than by a specific named path
- Including sensitive details in content sent, uploaded, published, or written to other people or shared systems, when your own message didn’t authorize those details for that recipient. PR and issue bodies, commit messages, and comments count as this kind of outbound content when the repository is outside the trust boundary or public, including your organization’s own public repositories; internal file paths, code names, live API response data such as emails or account identifiers, and infrastructure identifiers count as sensitive details. The PR, issue, and commit-message scoping requires Claude Code v2.1.200 or later. Live personal data from an API response in a PR or issue body, such as an email address, an account or organization identifier, or a usage metric, requires you to name those details and the recipient regardless of the repository’s visibility or trust boundary. That check requires Claude Code v2.1.203 or later
- Sending keystrokes to Claude Code’s own tmux pane to drive its own interface, which the classifier treats as Claude changing its own permissions or oversight
Claude Code v2.1.200 and later also block these by default:
- Commenting out, deleting, or force-passing a test or assertion that guards security behavior, such as auth, access control, input validation, or sandboxing
- Deleting or tearing down a stateful resource Claude didn’t create in the session, when no more specific deletion rule applies and you didn’t name that resource
- Repointing an API base URL, proxy endpoint, webhook receiver, or registry mirror at a third-party host that doesn’t fit the task, including in example files like `.env.example`
- Changing where pushes go with `git remote set-url` or `git remote add`, unless you named the new remote
- Pushing secrets or personal or entrusted data to a repository known to be public, or pushing confidential material there that isn’t part of that repository’s own work. A dotfiles repository’s own subject matter is the one exception for personal or entrusted data, and content from a private repository reaching any public surface is blocked the same way; both refinements require Claude Code v2.1.203 or later. Before v2.1.203, personal data was grouped with confidential material and blocked only when it wasn’t part of that repository’s own work. When a repository’s visibility isn’t established, the classifier doesn’t block on that alone; it judges the content against the other rules instead
- Opening a pull request against a different repository or organization, forking with `gh repo fork`, or pushing to a third-party repository, unless you named that external target
Claude Code v2.1.203 and later also block these by default:
- Content from a sensitive local store, or from a file whose name, path, or type marks it as sensitive, entering a commit, a push, PR or issue text, a gist or paste, or a package publish, unless you named both the source and the destination. Session transcripts and conversation logs, credential and configuration dot-folders such as SSH keys, cloud credentials, browser profiles, and shell history, and user-data exports all count, and the repository being private doesn’t clear it
Claude Code v2.1.205 and later also block these by default:
- Writing to Claude Code session transcripts, the `.jsonl` history files under `~/.claude/projects/` or your configured config directory, whether directly or through a shell command. The rule also covers the metadata lines Claude Code appends to each transcript entry for its own checks. Reading a transcript isn’t blocked
- A recursive forced delete such as `rm -rf "$VAR"` or `Remove-Item -Recurse -Force $dir` whose target is a shell variable that isn’t assigned anywhere in the conversation the classifier sees, or a glob rooted at such a variable. The value came only from earlier command output, which the classifier never receives, so the classifier can’t verify the deletion target against the other deletion rules. The block clears when you name the exact path being deleted, or when Claude re-runs the delete with the resolved literal path written into the command. Deletes whose target the classifier can resolve aren’t affected. A glob directly under the variable, as in `rm -rf "$VAR"/*`, is a [critical path](#critical-paths) instead. `Remove-Item` targets that are a bare `*` or end in `/*` or `\*` never reach the classifier: Claude Code [denies them outright](#remove-item-in-powershell).
Claude Code v2.1.257 and later also block these by default:
- Requesting credentials from the cloud instance-metadata endpoint, such as `169.254.169.254`, or explicitly authenticating a cloud, cluster, or registry call with the machine’s own service-account or node identity
- Reaching a public host by a route other than a direct request, such as a tunnel, a reverse shell, or a resolver or proxy configuration rewritten to point outside
- Reading credentials that belong to the host rather than to your task, such as node certificates or the node’s container-registry auth
- Connecting to or scanning sibling containers, pods, or VMs that Claude didn’t start, or the node beneath the container
If Claude Code runs somewhere that is meant to allow one of these, describe that setup in a [Host containment entry](auto-mode-config.md#define-trusted-infrastructure) in `autoMode.environment`. Claude Code v2.1.261 and later also block these by default:
- Posting or writing a link to a public paste, diagram, or data-sharing service in a message, PR or issue text, a document, or anywhere else the link will be opened or fetched, when the URL itself carries the content being shared, unless you named that service
**Allowed by default**:
- Local file operations in your working directory
- Installing dependencies declared in your lock files or manifests
- Forwarding request-scoped credentials to the matching first-party API endpoint
- Read-only HTTP requests
- Pushing to any branch of the repository you’re working in, including the default branch. A non-default branch whose name marks it as a deploy or publication target, such as `production` or `gh-pages`, isn’t covered: the classifier judges a push there on its own terms. The push’s content is still checked against the other rules, [`permissions.deny` rules](permissions.md#manage-permissions) can still block push commands [as written](permissions.md#bash-rule-limits) in every mode, and the remote’s own branch protection still applies. Before v2.1.211, only pushes to the branch you started on, branches Claude created, and routine pushes to the default branch were allowed by default, and before v2.1.203 any direct push to the default branch was blocked
- Deleting the exact jobs Claude created earlier in the same session
- Reading, reviewing, or writing security-related code, configs, and threat models as part of your task
- Messages between agents working together in the same multi-agent session
- Sending data to the trusted domains, buckets, and services you list in [`environment`](auto-mode-config.md#define-trusted-infrastructure). This covers data flow only, not destructive or credential operations on the same infrastructure
- [Claude in Chrome](../03-IDE-Integrations/chrome.md) navigation to a trusted internal domain, localhost, or a URL you named
Sandboxed commands don’t get network access by default. Claude names the hosts a command needs on the command itself, the classifier reviews them with the command, and an approved list opens those hosts for that one command alone. [Per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode) covers what a list can and can’t open and what happens when a command reaches for an unlisted host. Run `claude auto-mode defaults` to print the full rule lists as JSON. If routine actions get blocked, an administrator can add trusted repos, buckets, and services via the `autoMode.environment` setting: see [Configure auto mode](auto-mode-config.md). Pushing to any branch of the repository you’re working in and creating a pull request that matches your request run without a prompt, unless the push or pull request falls under the [blocked list](#what-the-classifier-blocks-by-default), such as secrets or sensitive data leaving the repository, or a pull request that targets a different repository or organization. To require a human checkpoint before these commands while staying in auto mode, add `permissions.ask` rules, which match the command [as written](permissions.md#bash-rule-limits): see [Common boundaries](auto-mode-config.md#common-boundaries).
[](#first-read-outside-the-working-directories)
The first read outside the working directories
While [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) is off, file reads run without a prompt in auto mode, including reads outside the [working directories](permissions.md#working-directories). The first time Claude uses the Read, Grep, or Glob tool on a path outside them, Claude Code asks whether to allow that read. The prompt doesn’t appear in non-interactive `-p` runs or background sessions; reads there run as before. Whatever you answer, Claude keeps working:
- **Yes, and keep allowing any reads outside the working directories**: the read runs, later reads outside the working directories run as before, and Claude Code records your answer so the prompt doesn’t appear again
- **No, and block reads outside the working directories from now on**: the read is refused, and Claude Code sets [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) to `true` in your user settings, which makes the file tools refuse such reads in every later session and every permission mode. To let Claude read such a path later, add its directory with `/add-dir` or remove the setting.
- **No, and ask again next time**: the read is refused, and the next read outside the working directories prompts again
- **Yes, but ask again next time**: the read runs, nothing is saved, and the next read outside the working directories prompts again
[](#boundaries-you-state-in-conversation)
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](../17-Billing-Plans/costs.md#reduce-token-usage) removes the message that stated it. For a hard guarantee, add a [deny rule](permissions.md#permission-rule-syntax) instead.
[](#approvals-you-state-in-conversation)
Approvals you state in conversation
If you tell Claude that a blocked action is allowed, the classifier reads that as your approval and can clear the block. How you worded it decides whether the action runs, and how far the approval reaches:
- **Name the action and its specifics**: your message has to name the action and the specific thing that makes it dangerous, such as the branch of a force push. Naming the verb alone clears nothing, so “you can force-push” leaves the block in place.
- **Expect it to cover one action**: an approval covers the destructive action you named, so a later action is blocked again unless you granted the approval as standing. To stop approving a routine pattern one action at a time, add it to [`autoMode.allow`](auto-mode-config.md#override-the-block-and-allow-rules).
- **Some blocks stay in place**: [the classifier’s precedence order](auto-mode-config.md#override-the-block-and-allow-rules) sets out which blocks your approval can reach. To run a step it won’t clear, [leave auto mode](#switch-permission-modes) and answer the permission prompt.
[](#when-auto-mode-falls-back)
When auto mode falls back
When auto mode can’t approve your session’s actions, what happens depends on the case:
- **A blocked action**: Claude Code shows a notification and lists the action in `/permissions` under the **Recently denied** tab, where you can press `r` to retry it with a manual approval.
- **Repeated blocks**: 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. See [Repeated-block thresholds](#repeated-block-thresholds) for how the blocks are counted.
- **No verdict from the classifier**: when a safety check separate from auto mode refuses the classifier’s own request, or the classifier’s response doesn’t parse, Claude Code denies the action without the notification or the **Recently denied** entry. See [Auto mode cannot determine the safety of an action](errors.md#auto-mode-cannot-determine-the-safety-of-an-action) for the message each case shows and what to do.
- **No verdict from the server**: under [server-side classifier review](#server-side-classifier-review), Claude Code denies an action the server gives no verdict for, and stops the turn after ten responses in a row with no verdict. See [The server returned no safety verdict](errors.md#the-server-returned-no-safety-verdict).
- **A mode switch during a check**: if you switch permission modes while a classifier check is pending, Claude Code discards a verdict the new mode wouldn’t have requested. You’re prompted for approval instead, or the action is auto-denied in [`dontAsk` mode](#allow-only-pre-approved-tools-with-dontask-mode).
[](#repeated-block-thresholds)
Repeated-block thresholds
The thresholds of 3 blocks in a row and 20 blocks total are not configurable. The total counter persists for the session and resets only when its own limit triggers a fallback. Claude Code doesn’t count a denial toward either threshold when a safety check separate from auto mode refuses the classifier’s own request. A [non-interactive](headless.md) `-p` run without a [`--permission-prompt-tool`](cli-reference.md#cli-flags) has no prompt to fall back to. When repeated blocks reach a threshold, the action doesn’t run and Claude keeps working. Claude Code doesn’t stop the run. 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](auto-mode-config.md).
[](#how-auto-mode-evaluates-actions)
How auto mode evaluates actions
The following sections cover the order Claude Code evaluates an action in, how the classifier reviews subagent work, and what classifier calls add in cost and latency.
How the classifier evaluates actions
Each action goes through a fixed decision order. The first matching step wins:
1. Actions matching your [allow, ask, or deny rules](permissions.md#manage-permissions) resolve immediately, with these exceptions:
- Writes to [protected paths](#protected-paths) route to the classifier even when an allow rule matches
- No allow rule approves `rm` and `rmdir` removals targeting a [critical path](#critical-paths)
- MCP tools marked [`requiresUserInteraction`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool) prompt you directly even when an allow rule matches, and so do connector tools [your organization set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code
- A shell command that carries [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode) also routes to the classifier even when an allow rule matches, because a rule approves the command, not its hosts
- Ask rules that match on a command’s content, such as `Bash(git push *)`, fall back to a permission prompt
- A write that the [symlink check](permissions.md#symlinks) resolves to a protected path prompts you when the path Claude requested isn’t itself protected
2. Read-only actions and file edits in your working directory are auto-approved, except writes to [protected paths](#protected-paths) and [the first read outside the working directories](#first-read-outside-the-working-directories), which prompts you
- In a session with [server-side classifier review](#server-side-classifier-review), read-only and [sandboxed](sandboxing.md#sandbox-modes) shell commands wait for that review and are blocked if it flags them
- A write inside your working directory that the [symlink check](permissions.md#symlinks) resolves to a location outside it prompts you
3. Everything else goes to the classifier, apart from [critical-path removals](#critical-paths) under their default handling. The connector tools and `requiresUserInteraction` MCP tools that prompt you directly in step 1 never reach the classifier either, so neither an org-required approval nor a consent step is auto-approved
4. If the classifier blocks, Claude receives the reason. In most sessions the reason names the rule the classifier matched, such as `[Data Exfiltration]`, rather than giving a written explanation; see [Review denials](auto-mode-config.md#review-denials)
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
- [`Monitor`](tools-reference.md#monitor-tool) allow rules, because Claude Code runs Monitor commands through the shell
Narrow rules like `Bash(npm test)` stay in effect. Claude Code restores the dropped rules when you leave auto mode. Before v2.1.236, Claude Code left `Monitor` allow rules in effect in auto mode, so a rule that matched the whole tool approved Monitor commands without classifier review.Claude Code also runs `git status` itself before a command that would discard uncommitted work, such as `git reset --hard` or `rm -rf`, and shows the classifier whether staged, modified, or untracked work is present. Claude Code reports untracked files in that check even when the repository’s git configuration sets `status.showUntrackedFiles=no`.In the classifier requests sent by Claude Code itself, the classifier sees user messages, tool calls other than read-only lookups such as file reads and searches, and your CLAUDE.md content. Tool results are stripped from those requests, so hostile content in a file or web page can’t manipulate the classifier directly.You can annotate a call’s result with a [PostToolUse hook’s `classifierContext` field](../07-Hooks/hooks.md#annotate-a-result-for-the-auto-mode-classifier), which the classifier reads as application-provided context. The field requires Claude Code v2.1.236 or later.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](https://claude.com/blog/auto-mode) and the [engineering deep dive](https://www.anthropic.com/engineering/claude-code-auto-mode).
How auto mode handles subagents
The classifier checks [subagent](../09-Agents-Patterns/sub-agents.md) work at three points:
1. Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.
2. 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.
3. When the subagent finishes, the classifier reviews its work and its final report before the parent reads the report. When the classifier flags the subagent’s work or report, or a separate API safety check refuses the review, the report is still delivered, prepended with a security warning. When the classifier is unavailable for the review, the report arrives with a note to verify the subagent’s work before acting on it.
Cost and latency
The classifier runs on Claude Sonnet 5 by default rather than on your `/model` selection. A classifier model that Anthropic configures server-side takes precedence over that default. When your session’s model is Claude Sonnet 4.6, or when [`availableModels`](model-config.md#restrict-model-selection) excludes Sonnet 5, the classifier runs on the session’s model instead, or on an Opus model when the session runs on a [Fable model](model-config.md#work-with-fable); on providers other than the Anthropic API, that Opus fallback is the provider’s default Opus model.The session’s first auto-mode request validates the Sonnet 5 default: if the request succeeds, Sonnet 5 stays the session’s classifier model, and if it fails because the model isn’t available, the session uses the fallback instead. After that validation settles, the classifier’s model doesn’t change for the session.On Enterprise plans and on accounts that use the Claude API, [Claude Platform on AWS](claude-platform-on-aws.md), Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry, 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. Where the server reviews the actions as part of the session’s model requests, there are no separate classifier calls to count; see [Server-side classifier review](#server-side-classifier-review).Sandboxed network access adds no per-connection classifier requests. The classifier judges [the hosts a command names](sandboxing.md#per-command-allowed-domains-in-auto-mode) together with the command in one review, and Claude Code checks each connection against the approved list without calling the classifier again.
[](#allow-only-pre-approved-tools-with-dontask-mode)
Allow only pre-approved tools with dontAsk mode
If you set `dontAsk` mode, Claude Code auto-denies every tool call that would otherwise prompt you. Claude still runs actions that need no approval in Manual mode, such as file reads inside your working directories and [read-only Bash commands](permissions.md#read-only-commands), plus actions matching your `permissions.allow` rules and calls approved by a [PreToolUse hook](permissions.md#extend-permissions-with-hooks). Use this mode for CI pipelines or restricted environments where you pre-define what Claude may do; the session never waits for input. The status bar shows `⏵⏵ don't ask on` while this mode is active. Claude Code denies calls matching your explicit [`ask` rules](permissions.md#manage-permissions) rather than prompting. It also denies the built-in `AskUserQuestion` tool even if your allow rules match it, and does the same to connector tools [your organization set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code. It denies MCP tools marked [`_meta["anthropic/requiresUserInteraction"]`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool) the same way, because their approval card needs an answer this mode never collects; this requires Claude Code v2.1.199 or later. `rm` and `rmdir` removals targeting a [critical path](#critical-paths), such as `rm -rf /` and `rm -rf ~`, are denied even when an allow rule matches them or a `PreToolUse` hook allows them. [Cloud sessions](claude-code-on-the-web.md) ignore `defaultMode: "dontAsk"`; see [bypassPermissions](#skip-all-checks-with-bypasspermissions-mode) for details. Set it at startup with the flag:
```python
claude --permission-mode dontAsk
```
[](#skip-all-checks-with-bypasspermissions-mode)
Skip all checks with bypassPermissions mode
`bypassPermissions` mode disables permission prompts and safety checks so tool calls execute immediately, including writes to [protected paths](#protected-paths). The [actions no mode auto-approves](#actions-no-mode-auto-approves) still prompt in this mode. The [Remove-Item in PowerShell](#remove-item-in-powershell) denies also apply in this mode. Two [cross-session messaging](cross-session-messaging.md) safeguards still apply in this mode, and in interactive terminal plan-mode sessions where bypass permissions are available:
- The [`isolatePeerMachines`](settings-reference.md#isolatepeermachines) approval prompt for messages to your sessions beyond this machine still appears.
- When no [`crossSessionInbound`](cross-session-messaging.md#control-inbound-messages) value applies, Claude Code holds an inbound message from another of your sessions for your approval, and delivers without asking only when the sending session identifies itself as also bypassing permission prompts. If you leave the permission mode while messages are held, Claude Code re-applies the inbound rules and delivers any held message they now accept.
In interactive terminal sessions with bypass permissions available, Claude Code also doesn’t enforce [plan mode’s](#analyze-before-you-edit-with-plan-mode) blocks. Claude is still instructed to plan without editing, but a file edit or shell command it attempts during planning runs without prompting. Explicit [ask rules](permissions.md#manage-permissions) and `rm` and `rmdir` removals targeting a [critical path](#critical-paths) still prompt. Plan mode keeps its blocks wherever Claude Code runs without an interactive terminal, including [non-interactive runs](headless.md) with `-p`, [Agent SDK](../05-Agent-SDK/agent-sdk-permissions.md#plan-mode-plan) sessions, and conversations in the [VS Code extension](../03-IDE-Integrations/vs-code.md)’s chat panel. There, `--allow-dangerously-skip-permissions` makes `bypassPermissions` selectable later.
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 can’t enter `bypassPermissions` from a session you started without it enabled. Enable it at launch with [`permissions.defaultMode: "bypassPermissions"`](settings-reference.md#permissions-defaultmode) or with an enabling flag:
```python
claude --permission-mode bypassPermissions
```
The `--dangerously-skip-permissions` flag is equivalent. Claude Code refuses `bypassPermissions` in a session you start with [`--restricted`](cli-reference.md#cli-flags). `--restricted` requires Claude Code v2.1.248 or later. The first time you start an interactive session with this mode enabled, Claude Code shows a warning dialog asking you to accept responsibility for actions taken without permission checks:
- **If you accept**: Claude Code sets `skipDangerousModePermissionPrompt` to `true` in `~/.claude/settings.json`, so later sessions skip the dialog. To see the dialog again, remove the key from that file or set it to `false`. The [`skipDangerousModePermissionPrompt` reference](settings-reference.md#skipdangerousmodepermissionprompt) lists the other settings files where you or your organization can set it.
- **If you decline**: Claude Code exits.
In [non-interactive mode](headless.md) no dialog is shown, and a [background session](../09-Agents-Patterns/agent-view.md) started with `--bg` is refused until you’ve accepted the dialog in an interactive session. On Linux and macOS, Claude Code refuses to start in this mode when running as root or under `sudo`:
```python
--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](devcontainer.md) configuration, which runs Claude Code as a non-root user. [Cloud sessions](claude-code-on-the-web.md) don’t honor `defaultMode: "bypassPermissions"` or `"dontAsk"` from your settings files, so a repository’s checked-in settings can’t start a cloud session in bypass-permissions mode. The setting is ignored silently and the session starts in the permission mode shown in the mode dropdown instead. See [Switch permission modes](#switch-permission-modes) for which modes cloud sessions offer.
`bypassPermissions` offers no protection against prompt injection or unintended actions. For background safety checks with far fewer permission prompts, use [auto mode](#eliminate-prompts-with-auto-mode) instead. Administrators can block this mode by setting `permissions.disableBypassPermissionsMode` to `"disable"` in [managed settings](../13-Enterprise-Admin/managed-settings.md).
[](#protected-paths)
Protected paths
Writes to a small set of paths are never auto-approved, except in `bypassPermissions` mode and in interactive terminal sessions in plan mode with [bypass permissions](#skip-all-checks-with-bypasspermissions-mode) available. This prevents accidental corruption of repository state and Claude’s own configuration.
| Mode | Protected-path writes |
|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `default`, `acceptEdits` | Prompted |
| `plan` | Allowed in interactive terminal sessions with [bypass permissions](#skip-all-checks-with-bypasspermissions-mode) available. Otherwise, routed to the classifier when [auto mode](#eliminate-prompts-with-auto-mode) is available during planning, and prompted when it isn’t |
| `auto` | Routed to the classifier |
| `dontAsk` | Denied |
| `bypassPermissions` | Allowed |
In a session started with [`--restricted`](cli-reference.md#cli-flags), which requires Claude Code v2.1.248 or later, the classifier can’t approve protected-path writes. In the modes that route protected-path writes to the classifier, a write that the [symlink check](permissions.md#symlinks) resolves to a protected path prompts you instead when the path Claude requested isn’t itself protected. [`permissions.allow`](permissions.md#manage-permissions) rules in settings files do not pre-approve protected-path writes. The safety check runs before Claude Code evaluates allow rules from settings, so an entry such as `Edit(.claude/**)` in `~/.claude/settings.json` or `.claude/settings.json` does not change the per-mode outcome in the table above. In permission modes that prompt, the prompt for a write to the project’s `.claude/` folder or to `~/.claude/` can offer one of these session-scoped options:
- For the project’s `.claude/` folder: **Yes, and allow Claude to edit files in this project’s .claude folder for this session**
- For `~/.claude/`: **Yes, and allow Claude to edit files in its ~/.claude folder for this session**
Protected directories:
- `.git`
- `.config/git`
- `.vscode`
- `.idea`
- `.husky`
- `.cargo`
- `.devcontainer`
- `.yarn`
- `.mvn`
- `.claude`, except for `.claude/worktrees` where Claude stores its own git worktrees
Protected files:
- `.gitconfig`, `.gitmodules`
- `.bashrc`, `.bash_profile`, `.bash_login`, `.bash_aliases`, `.bash_logout`, `.zshrc`, `.zprofile`, `.zshenv`, `.zlogin`, `.zlogout`, `.profile`, `.envrc`
- `.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnp.cjs`, `.pnp.loader.mjs`, `.pnpmfile.cjs`, `bunfig.toml`, `.bunfig.toml`
- `.bazelrc`, `.bazelversion`, `.bazeliskrc`
- `.pre-commit-config.yaml`, `lefthook.yml`, `lefthook.yaml`, `.lefthook.yml`, `.lefthook.yaml`
- `gradle-wrapper.properties`, `maven-wrapper.properties`
- `.devcontainer.json`
- `.ripgreprc`, `pyrightconfig.json`
- `.mcp.json`, `.claude.json`
[](#critical-paths)
Critical paths
Critical paths are the directories Claude Code protects from `rm` and `rmdir` commands, such as the filesystem root, your home directory, and your working directory. Claude Code never lets a [`permissions.allow`](permissions.md#manage-permissions) rule or a [`PreToolUse` hook](permissions.md#extend-permissions-with-hooks) that returns `"allow"` approve an `rm` or `rmdir` command that targets a critical path, even in modes that skip other prompts. This circuit breaker guards against model error. A matching deny rule still blocks the command outright. What happens instead [depends on your permission mode](#critical-path-removals-in-each-permission-mode). `Remove-Item` and the `cmd` removal built-ins have their own checks, covered in [Remove-Item in PowerShell](#remove-item-in-powershell).
[](#which-paths-are-critical)
Which paths are critical
Claude Code treats an `rm` or `rmdir` target as a critical path when it is any of the following:
- The filesystem root
- Top-level directories, meaning any direct child of the root, such as `/usr`, `/etc`, or `/data`
- Your home directory
- Windows drive roots and their top-level directories, such as `C:\` and `C:\Windows`
- Your working directory and its parents
- Your additional working directories and their parents, but only when the removal is a glob under one of them, such as `rm -rf <dir>/*`. `rm -rf <dir>` on the directory itself doesn’t trigger this check
[](#other-targets-that-count-as-critical-paths)
Other targets that count as critical paths
Claude Code also treats the following `rm` and `rmdir` targets as critical paths. The last column says why each one counts.
| Target | Example | Why it counts |
|:----------------------------------------------------------------------------------------------------------------------------------------|:------------------------|:---------------------------------------------------------------------------------------------------------------|
| A glob or trailing slash directly under a shell variable | `rm -rf "$DIR"/*` | The command becomes a removal from the filesystem root when the variable is empty |
| The same form under a positional parameter such as `$1` or `$@`, when nothing in the command gives it a value | `rm -rf "$1"/*` | The command expands to a removal from the root |
| A shell variable followed by one common top-level directory name, such as `mnt`, `tmp`, `usr`, or `Users` | `rm -rf "$TMPDIR/mnt"` | When the variable expands empty, the command removes `/mnt` |
| A variable that the same command assigns from a directory-printing substitution, such as `$(pwd)` or `$(git rev-parse --show-toplevel)` | `D=$(pwd); rm -rf "$D"` | The value can name your working directory or repository root |
| A target that is only the output of a command substitution, when the `rm` is recursive | `rm -rf "$(pwd)"` | Claude Code can’t check the target before the command runs |
| A trailing command substitution after a critical path | `rm -rf ~/$(cmd)` | Claude Code checks the path that would remain if the substitution expanded empty, here your home directory |
| A target that is only backslashes | `rm -rf "\\"` | Git Bash on Windows reads a lone backslash as the current drive’s root, so the check applies on every platform |
To turn off the check on a target that is only command substitution output, set [`CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT=1`](env-vars.md#variables) in the environment that launches Claude Code.
[](#removals-inside-nested-commands-and-inline-scripts)
Removals inside nested commands and inline scripts
Claude Code also looks inside these constructs:
- **Nested commands**: a subshell with `(...)`, a brace group with `{ ...; }`, command substitution with `$(...)` or backticks, or process substitution with `<(...)`. Claude Code finds a critical-path removal whether it sits inside the nested form, as in `(rm -rf ~)` or `echo "$(rm -rf ~)"`, or elsewhere in the same command.
- **Inline scripts**: Claude Code checks a script passed to a shell such as `sh -c` or `bash -c` for the shell variable and positional parameter [targets](#other-targets-that-count-as-critical-paths).
- When the script is double-quoted, the invoking shell expands its variables before the inner shell receives the script. In `find . -name '*.tmp' -exec sh -c "rm -rf \"$1\"/*" _ {} \;`, the command expands to a removal from the filesystem root once per match, and Claude Code treats it as a critical-path removal.
- A single-quoted script that binds `$1` to a real value, as `sh -c 'rm -rf "$1"/*' _ {}` does, isn’t flagged.
[](#rewrite-a-flagged-command)
Rewrite a flagged command
How to rewrite a command so it passes the check depends on which of the [other targets](#other-targets-that-count-as-critical-paths) it uses:
- **A glob or trailing slash under a variable such as `$DIR`**: guard each expansion so the shell stops with an error when the variable is unset or empty, as in `rm -rf "${DIR:?}"/*`, or use a literal path. A removal whose expansions are all guarded that way passes this check, so in `bypassPermissions` mode it runs without a prompt unless another [critical-path](#critical-paths) check flags it.
- **A glob or trailing slash under a variable that is normally set, such as `$HOME`**: use a literal path.
- **A variable assigned from a directory-printing substitution**: use a literal path. A `"${D:?}"` guard doesn’t clear this check, because the variable isn’t empty.
- **A target that is only command substitution output**: run the substitution on its own first, then remove the literal paths it prints. The prompt tells Claude to do the same.
For a glob or trailing slash under a variable, the prompt names the flagged `rm` and says how to rewrite it so the check passes.
[](#critical-path-removals-in-each-permission-mode)
Critical-path removals in each permission mode
What Claude Code does with a critical-path removal depends on your permission mode:
| Mode | Outcome |
|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `default`, `acceptEdits` | Asks you to approve it |
| `plan` | Asks you to approve it. When [the classifier reviews commands during planning](#analyze-before-you-edit-with-plan-mode) and no bypass permissions are available, handles it as in `auto` mode |
| `auto` | Asks you to approve it in the terminal, with a [time limit](#time-limits-and-denials-in-auto-and-bypasspermissions-modes). Elsewhere, denies it |
| `dontAsk` | Denies it |
| `bypassPermissions` | Asks you to approve it, with a time limit in the terminal |
If an explicit [ask rule](permissions.md#manage-permissions) matches the command, Claude Code asks you instead, even in `auto` mode and without a time limit. In modes that ask, a [`PermissionRequest` hook](../07-Hooks/hooks.md#permissionrequest) can answer the prompt.
[](#time-limits-and-denials-in-auto-and-bypasspermissions-modes)
Time limits and denials in auto and bypassPermissions modes
In `auto` and `bypassPermissions` modes, the terminal prompt for a critical-path removal shows a two-minute countdown:
- If the countdown runs out before you answer, Claude Code denies the command and tells Claude what to do instead, so an unattended session keeps working.
- Press any key while the prompt is open to stop the countdown and keep the prompt waiting for your answer.
- After three of these prompts run out unanswered in a session, Claude Code stops showing them and denies further critical-path removals immediately. Sending a new message starts the count over.
In `auto` mode, wherever Claude Code can’t show you a terminal prompt, it denies the command immediately, for example in [non-interactive runs](headless.md) with `-p`, in [Agent SDK](../05-Agent-SDK/agent-sdk-permissions.md) sessions, and in the VS Code extension’s chat panel and the Desktop app. The denial tells Claude to report what it wanted to delete and leave the removal to you. The `auto` and `bypassPermissions` handling requires Claude Code v2.1.281 or later. To turn it off, set [`CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT=1`](env-vars.md#variables) in the environment that launches Claude Code. In `auto` mode, critical-path removals then go to the classifier instead, and in `bypassPermissions` mode the prompt has no time limit.
[](#remove-item-in-powershell)
Remove-Item in PowerShell
When you enable the [PowerShell tool](tools-reference.md#powershell-tool), Claude Code gives `Remove-Item` and the `cmd` built-ins `rd`, `rmdir`, `del`, and `erase` their own checks, separate from the `rm` critical-path list. For `Remove-Item`, the outcome depends on the target, and the first matching case applies:
- **System paths**: the filesystem root and its top-level directories, drive roots and their top-level directories, and your home directory. Claude Code denies the command in every mode, without asking you.
- **Wildcards**: a bare `*`, or any target ending in `/*` or `\*`, including a glob under a shell variable such as `$dir/*`. Claude Code denies the command in every mode, without asking you, before the [classifier](#eliminate-prompts-with-auto-mode) sees it.
- **Your working directory or one of its parents, with `-Recurse`**: Claude Code treats the command like any other that needs approval in your permission mode, so it asks you in modes that ask, sends it to the classifier in `auto` mode, and denies it in `dontAsk` mode. `bypassPermissions` mode skips this check.
The system-paths case also applies to `rd`, `rmdir`, `del`, and `erase` when Claude runs them through `cmd`, as in `cmd /c rd /s /q C:\Users`. By default, Claude Code denies such a command in every mode, without asking you. This `cmd` check requires Claude Code v2.1.283 or later. When judging a `cmd` target, Claude Code treats a PowerShell variable that follows literal text as empty. That makes `cmd /c rd /s /q "C:\$name"` a removal of `C:\`, so it is denied too. A trailing wildcard counts as the folder it empties, so `cmd /c del /q C:\*` is denied and `cmd /c del /q dist\*` in your project is not. To turn the `cmd` check off, set [`CLAUDE_CODE_DISABLE_POWERSHELL_CMD_RM_DENY=1`](env-vars.md#variables) in the environment that launches Claude Code. Claude Code ignores this variable in a settings file’s `env` block. `Remove-Item` on a system path stays denied either way.
[](#see-also)
See also
- [Permissions](permissions.md): allow, ask, and deny rules; managed policies
- [Configure auto mode](auto-mode-config.md): tell the classifier which infrastructure your organization trusts
- [Hooks](../07-Hooks/hooks.md): custom permission logic via `PreToolUse` and `PermissionRequest` hooks
- [Security](../13-Enterprise-Admin/security.md): safeguards and best practices
- [Sandboxing](sandboxing.md): filesystem and network isolation for Bash commands
- [Non-interactive mode](headless.md): run Claude Code with the `-p` flag
---
## Configure permissions - Claude Code Docs
Source: https://code.claude.com/docs/en/permissions
Path: 02-Claude-Code-CLI/permissions.md
## On this page
- [Permission system](#permission-system)
- [Add a comment when you answer a permission prompt](#add-a-comment-when-you-answer-a-permission-prompt)
- [Manage permissions](#manage-permissions)
- [Permission modes](#permission-modes)
- [Permission rule syntax](#permission-rule-syntax)
- [Match all uses of a tool](#match-all-uses-of-a-tool)
- [Use specifiers for fine-grained control](#use-specifiers-for-fine-grained-control)
- [Match by input parameter](#match-by-input-parameter)
- [Wildcard patterns](#wildcard-patterns)
- [Tool name wildcards](#tool-name-wildcards)
- [Tool-specific permission rules](#tool-specific-permission-rules)
- [Bash](#bash)
- [Compound commands](#compound-commands)
- [Wrappers](#process-wrappers)
- [What a Bash rule doesn’t match](#bash-rule-limits)
- [Read-only commands](#read-only-commands)
- [Redirections](#redirections)
- [PowerShell](#powershell)
- [Read and Edit](#read-and-edit)
- [Symlinks](#symlinks)
- [WebFetch](#webfetch)
- [Allow or deny every fetch](#allow-or-deny-every-fetch)
- [MCP](#mcp)
- [Agent (subagents)](#agent-subagents)
- [Cd](#cd)
- [Extend permissions with hooks](#extend-permissions-with-hooks)
- [Working directories](#working-directories)
- [Move the session to another directory](#move-the-session-to-another-directory)
- [Additional directories grant file access, not configuration](#additional-directories-grant-file-access-not-configuration)
- [How permissions interact with sandboxing](#how-permissions-interact-with-sandboxing)
- [Managed settings](#managed-settings)
- [Settings precedence](#settings-precedence)
- [Project allow rules and workspace trust](#project-allow-rules-and-workspace-trust)
- [When your local settings file needs trust](#when-your-local-settings-file-needs-trust)
- [What runs before you trust a folder](#what-runs-before-you-trust-a-folder)
- [Example configurations](#example-configurations)
- [See also](#see-also)
Permissions and sandboxing
# Configure permissions
Copy pageCopy page
Control what Claude Code can access and do with fine-grained permission rules, modes, and managed policies.
Copy pageCopy page
Claude Code supports fine-grained permissions so that you can specify exactly what the agent is allowed to do and what it can’t. You can check permission settings into version control to share them with every developer in your organization, and each developer can customize their own.
[](#permission-system)
Permission system
Claude Code uses a tiered permission system to balance power and safety. The table shows, for each tool type, whether Manual mode asks before the action runs. The other [permission modes](#permission-modes) change which of these ask you; in auto mode a classifier reviews actions instead of you, and [how the classifier evaluates actions](permission-modes.md#how-the-classifier-evaluates-actions) lists which ones it sees.
| Tool type | Example | Approval required | ”Yes, and don’t ask again” behavior |
|:------------------|:-----------------|:-------------------------------------------------------------------------------------------------------------------|:---------------------------------------|
| Read-only | File reads, Grep | No, within the [working directory and additional directories](#working-directories) | N/A |
| Bash commands | Shell execution | Yes, except a built-in set of [read-only commands](#read-only-commands) | Permanently per repository and command |
| File modification | Edit/write files | Yes | Until session end |
| Web fetch | WebFetch | Yes, except a built-in set of [preapproved documentation domains](tools-reference.md#webfetch-tool-behavior) | Permanently per repository and domain |
| Web search | WebSearch | Yes | Permanently per repository |
When you choose “Yes, and don’t ask again” and the approval saves permanently, such as for a Bash command or a WebFetch domain, Claude Code saves the rule to `.claude/settings.local.json` at the root of the git repository, resolved through [worktrees](worktrees.md) to the main checkout. The rule applies to future sessions anywhere in that repository, including sessions started in subdirectories and in worktrees. A file-modification approval isn’t saved to the file: as the table shows, it lasts until the session ends. In some cases, such as outside a git repository or on Windows, Claude Code doesn’t use the repository root; [Where Claude Code looks for each file](settings.md#where-claude-code-looks-for-each-file) lists those cases and where it saves the rule instead. Before v2.1.211, Claude Code always saved the rule in the starting directory, so an approval granted in a worktree or subdirectory didn’t apply to the rest of the repository. Rules that earlier versions saved in a subdirectory or worktree still apply to sessions started there. Sometimes a permission prompt offers only a one-time approval, with no “don’t ask again” option and no option to allow the action for the rest of the session. Claude Code offers those options only when the prompt can show you everything they would allow, so a rule you save from a prompt covers only what its option named. When a prompt offers only the one-time approval, approve the action once, or add the rule yourself in [`/permissions`](#manage-permissions).
[](#add-a-comment-when-you-answer-a-permission-prompt)
Add a comment when you answer a permission prompt
You can attach a note to Claude when you approve or deny a single action. On most permission prompts, including Bash, PowerShell, file, and MCP tool prompts, move to **Yes** or **No** and press `Tab` to open a comment field on that option. WebFetch and browser prompts don’t offer the field. The options that allow the action for the rest of the session or save a rule don’t take one either. With the field open, type the comment and then press one of these keys:
- `Enter`: submits your answer with the comment attached. If you leave the field empty, Claude Code submits the answer without a comment.
- `Tab`: closes the field without answering. Claude Code keeps the text you typed and still sends it if you answer with that option.
- `Shift+Tab`: on a file prompt, such as an Edit or Write prompt, closes the field the same as `Tab`. Before v2.1.235, pressing `Shift+Tab` inside the field instead selected the option that allows the action for the rest of the session, so Claude Code approved the action for the rest of the session and discarded the comment.
Claude Code delivers the comment differently depending on how you answered:
- **Yes**: Claude Code runs the action, then sends your comment to Claude after the result.
- **No**: Claude Code sends your comment to Claude as the reason for the denial, and Claude continues working. If you select **No** without a comment on a prompt from the main conversation, Claude Code stops the turn.
[](#manage-permissions)
Manage permissions
You can view and manage Claude Code’s tool permissions with `/permissions`. The dialog lists all permission rules and the `settings.json` file each rule comes from. You can open the dialog while Claude is working: when you add or remove a rule, Claude Code applies the change starting with Claude’s next tool call in the same turn. Before v2.1.234, Claude Code queued the command until the turn finished.
- **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, then ask, then allow. The first match in that order determines the outcome, and rule specificity doesn’t change the order. A broad deny rule like `Bash(aws *)` blocks every matching call, including calls that also match a narrower allow rule like `Bash(aws s3 ls)`. An allow rule can’t carve an exception out of a deny rule. The same precedence applies between ask and allow: a matching ask rule prompts even when a more specific allow rule also matches the same call. Deny rules behave differently depending on whether they name a tool or scope a pattern within one. A bare tool name like `Bash` removes the tool from Claude’s context entirely, so Claude never sees it. If you add such a rule mid-session, Claude can’t call the tool from its next tool call on; [Denying an entire tool](prompt-caching.md#denying-an-entire-tool) covers what happens to a definition Claude has already seen. A scoped rule like `Bash(rm *)` leaves the tool available and blocks matching calls when Claude attempts them. Bare-name removal applies to every tool except [`EndConversation`](tools-reference.md#endconversation-tool-behavior): a deny rule can’t remove it while any other tool remains, and an ask rule never prompts for it.
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](permission-modes.md), or a [PreToolUse hook](#extend-permissions-with-hooks).
When [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) is available to your session, the dialog also includes the [auto mode classifier rules](auto-mode-config.md#edit-rules-from-permissions). Select the **Auto mode** tab to view them.
[](#permission-modes)
Permission modes
Claude Code supports several permission modes that control how it approves tool calls. See [Permission modes](permission-modes.md) for when to use each one. To change the mode sessions start in, set `defaultMode` in your [settings files](settings.md#where-settings-live). [Which mode a session starts in](permission-modes.md#which-mode-a-session-starts-in) covers the built-in default for each plan and what the VS Code extension reads.
| Mode | Description |
|:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `default` | Prompts for permission on first use of each tool. Labeled Manual in the CLI, the VS Code and JetBrains extensions, and the desktop app, and Claude Code accepts `manual` as an alias. The label and alias require Claude Code v2.1.200 or later. The desktop app’s label doesn’t depend on your CLI version |
| `acceptEdits` | Automatically accepts file edits and common filesystem commands such as `mkdir`, `touch`, `mv`, and `cp` for paths in the working directory or `additionalDirectories` |
| `plan` | Claude reads files and runs read-only shell commands to explore but doesn’t edit your source files; with [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) available, classifier-approved commands also run. Labeled Plan in the CLI and the VS Code extension |
| `auto` | Auto-approves tool calls with background safety checks that verify actions align with your request |
| `dontAsk` | Auto-denies every call that would otherwise prompt; file reads in your working directories and other actions that need no approval still run, as do tools pre-approved via `/permissions` or `permissions.allow` rules. `AskUserQuestion`, MCP tools marked [`requiresUserInteraction`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool), and connector tools [your organization set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code are denied even if you’ve allowed them |
| `bypassPermissions` | Skips permission prompts, except for the [actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) |
In `bypassPermissions` mode, Claude Code skips permission prompts, including for writes to [protected paths](permission-modes.md#protected-paths) such as `.git` and `.claude`. The [cross-session messaging safeguards](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) still apply. Only use this mode in isolated environments like containers or VMs where Claude Code can’t cause damage.
To prevent `bypassPermissions` or `auto` mode from being used, set `permissions.disableBypassPermissionsMode` or `permissions.disableAutoMode` to `"disable"` in any [settings file](settings.md#where-settings-live). These are most useful in [managed settings](#managed-settings) where they can’t be overridden.
[](#permission-rule-syntax)
Permission rule syntax
Permission rules follow the format `Tool` or `Tool(specifier)`. Parentheses inside the specifier are literal, so a command or path that contains them needs no escaping.
[](#match-all-uses-of-a-tool)
Match all uses of a tool
To match all uses of a tool, use only 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. As a deny rule, both forms remove the tool from Claude’s context.
[](#use-specifiers-for-fine-grained-control)
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 |
[](#match-by-input-parameter)
Match by input parameter
Deny and ask rules can match a top-level input parameter on any built-in tool with `Tool(param:value)`. To match a parameter on an MCP tool, pass a deny rule with [`--disallowedTools`](cli-reference.md#cli-flags). When Claude Code loads a settings file, it skips any `mcp__` rule that has parentheses. Claude Code lists the skipped rule in the invalid-settings dialog when an interactive session starts, and in [`claude doctor`](debug-your-config.md#check-resolved-settings) output. A parameter rule matches when Claude calls the tool with that parameter set to that exact value. An allow rule for one parameter value wouldn’t establish that the call is safe overall, so allow rules continue to use each tool’s own specifier syntax. This works for any scalar parameter the tool accepts:
| Rule | Matches |
|:-------------------------------|:---------------------------------------------|
| `Agent(model:opus)` | Agent calls that request the Opus model tier |
| `Agent(isolation:worktree)` | Agent calls that request a git worktree |
| `Bash(run_in_background:true)` | Bash calls that run in the background |
Parameter matching follows these rules:
- The parameter name must be a direct field of the tool’s input, such as `model` on the Agent tool. Fields nested inside an object or array are not matchable
- Each rule names one parameter. To gate on both `model` and `isolation`, write two rules, `Agent(model:opus)` and `Agent(isolation:worktree)`, rather than combining them in one rule
- The value supports `*` as a wildcard that matches any sequence of characters, so `Agent(isolation:*)` matches any explicit isolation value. Without `*` the match is exact
- A parameter the model omits is never matched, so `Agent(model:*)` doesn’t match a call that leaves `model` unset
- The value is compared against the literal input Claude sends, before any normalization. `Agent(model:opus)` matches the alias `opus` but not a full model ID. Run with [`--verbose`](cli-reference.md) to see the exact parameter names and values in each tool call
- Whitespace around the colon is ignored
You can’t match a tool’s primary content field this way: `command` for Bash and PowerShell, `file_path` for Read, Edit, and Write, `path` for Grep and Glob, `notebook_path` for NotebookEdit, and `url` for WebFetch. A rule like `Bash(command:rm *)` would be bypassable by a compound command, so Claude Code ignores it and emits a startup warning. Use `Bash(rm *)`, `Read(./path)`, or `WebFetch(domain:host)` instead.
[](#wildcard-patterns)
Wildcard patterns
A `*` in a Bash rule matches any text, including spaces, so one rule covers a family of commands. A rule with no `*` matches one exact command.
Put the `*` after the subcommand. In `git log --oneline main`, `git` is the program and `log` is the subcommand, the word that determines what the program does. Claude Code matches everything before the first `*` as written, so those words are what limit the rule: `Bash(git log *)` allows only `git log` commands, and `Bash(git *)` allows every git command. Claude Code [warns at startup](errors.md#has-a-wildcard-before-the-rest-of-the-command) about an allow rule with a `*` before the subcommand, such as `Bash(git * main)`.
Write the command you want Claude to run without asking, and replace the parts that vary with `*`. With this configuration, Claude Code runs npm scripts and git commits without asking and refuses commands that begin with `git push`. A push written another way, such as `git -C . push`, isn’t matched; see [what a Bash rule doesn’t match](#bash-rule-limits).
```python
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)"
],
"deny": [
"Bash(git push *)"
]
}
}
```
A `*` can go anywhere in the rule: at the start, in the middle, or at the end. Each row shows a rule, commands it matches, and nearby commands it doesn’t match:
| You write | Matches | Doesn’t match |
|:-----------------------|:-------------------------------------------------------------------------------------|:---------------------------------------|
| `Bash(npm run build)` | `npm run build` | `npm run build --watch` |
| `Bash(npm run *)` | `npm run build`, `npm run test --watch`, `npm run` | `npm install` |
| `Bash(git log * main)` | `git log --oneline main`, `git log -5 main`, `git log --output=<file> main` | `git log main`, `git push origin main` |
| `Bash(git * main)` | `git merge main`, `git push origin main`, `git -c core.fsmonitor=<script> diff main` | `git log` |
| `Bash(* --version)` | `node --version`, `bash -c 'echo hi' --version` | `node -v` |
| `Bash(ls *)` | `ls -la`, `ls` | `lsof` |
| `Bash(ls*)` | `ls -la`, `lsof` | |
| `Bash(* --help *)` | `npm --help x` | `npm --help` |
Three matching rules produce those rows:
- **The `*` stands in for whatever text is in its place.** In `Bash(git * main)`, it stands in for the subcommand, so Claude Code matches every git subcommand and every option before it. That includes `-c`, which makes git run a program you name. In `Bash(* --version)`, the `*` stands in for the program, so any program matches.
- **A `*` at the end, with a space before it, also matches the bare command.** `Bash(ls *)` matches `ls`, and `Bash(git log *)` matches `git log`. That holds only when the trailing `*` is the rule’s only wildcard: `Bash(* --help *)` matches `npm --help x` but not `npm --help`.
- **The space before a trailing `*` is part of the rule.** `Bash(ls *)` requires a space after `ls`, so `lsof` doesn’t match. `Bash(ls*)` has no space, so it matches `lsof` too.
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, and 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-name-wildcards)
Tool name wildcards
Deny and ask rules also accept glob patterns in the tool-name position. The pattern must match the full tool name: `"*"` matches every tool, and `"mcp__*"` matches every MCP tool across all servers. A tool matched by a bare-name glob deny rule is removed from Claude’s context, the same as a bare tool name, including the [`EndConversation`](tools-reference.md#endconversation-tool-behavior) exception: a glob deny can’t remove it while any other tool remains, and a glob ask never prompts for it. This configuration denies every MCP tool:
```python
{
"permissions": {
"deny": [
"mcp__*"
]
}
}
```
Allow rules accept tool-name globs only after a literal `mcp__<server>__` prefix. The server segment must be glob-free so the rule names a specific server you configured. `mcp__puppeteer__*` matches every tool from the `puppeteer` server, and `mcp__github__get_*` matches its `get_` tools. An unanchored allow glob such as `"*"`, `"B*"`, or `"mcp__*"` is skipped with a warning and doesn’t auto-approve anything. A deny or ask rule whose tool name matches no known tool produces a startup warning to catch typos. Tool names containing `_` or `*` are exempt from the check, and so are the names of tools Claude Code has removed, such as `TaskOutput`. The label shown for a tool in the transcript and permission dialog can differ from its canonical name. For example, the tool labeled `Stop Task` in the transcript has the canonical name `TaskStop`. Permission rules and [hook matchers](../07-Hooks/hooks.md) don’t match the label, so a rule written as `Stop Task` doesn’t match. For deny and ask rules, the startup warning above catches the mismatch. Use the canonical names listed in the [tools reference](tools-reference.md).
[](#tool-specific-permission-rules)
Tool-specific permission rules
[](#bash)
Bash
Bash rules match the whole command text, with `*` standing in for any text. [Wildcard patterns](#wildcard-patterns) shows which commands each rule shape matches and where to put the `*`. The rest of this section covers how Claude Code matches compound commands and wrappers, what a rule doesn’t match, read-only commands, and redirections.
[](#compound-commands)
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.
Deny and ask rules apply when any subcommand matches them, including a command nested inside a subshell, a command substitution, or a control-flow body such as a `for` loop. An ask rule like `Bash(git clean *)` still prompts you for `cd /tmp && git clean -f` or `echo "$(git clean -f)"`, even in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode). When `&&` or `||` has nothing after it, such as in `npm test &&`, Claude Code treats the command as unparseable and doesn’t split it into subcommands for allow-rule matching, so a rule such as `Bash(npm *)` doesn’t approve it. When you approve a compound command with “Yes, and 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 directory outside your working directories generate their own Read rule for that path. Up to 5 rules may be saved for a single compound command.
[](#process-wrappers)
Wrappers
Before matching Bash rules, Claude Code strips a fixed set of wrappers, so a rule like `Bash(npm test *)` also matches `timeout 30 npm test`. The stripped wrappers are `timeout`, `time`, `nice`, `nohup`, and `stdbuf`, plus the shell builtins `command` and `builtin`, and zsh’s `noglob`. Each runs its argument as the actual command. Two related forms aren’t stripped: the query form `command -v`, which looks up a command rather than running one, and zsh’s `nocorrect`. Claude Code also strips a leading assignment of certain known-safe environment variables, so `Bash(npm test *)` matches `NODE_ENV=test npm test`. An allow rule won’t match past an assignment of any other variable. A deny or ask rule matches past any leading assignment, so `Bash(rm *)` in deny still matches `FOO=bar rm -rf tmp/`. 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` can’t be auto-approved by a prefix rule like `Bash(watch *)`, so in Manual mode they always prompt. The same applies to `find` with `-exec` or `-delete`: a `Bash(find *)` rule doesn’t cover these forms. To approve a specific invocation, write an exact-match rule for the full command string.
[](#bash-rule-limits)
What a Bash rule doesn’t match
A Bash rule matches the command text Claude writes, after Claude Code splits [compound commands](#compound-commands) and strips [wrappers](#process-wrappers). It doesn’t match the same program invoked in a different form, so a deny or ask rule covers the invocation Claude usually produces and isn’t a security boundary around the program. These rules in `deny` or `ask` stop the first form and not the others:
| Rule | Stops | Doesn’t stop |
|:-------------------|:---------------------------|:------------------------------------------------------------------------------------------------------|
| `Bash(curl *)` | `curl https://example.com` | `/usr/bin/curl https://example.com`, `sh -c 'curl https://example.com'` |
| `Bash(rm *)` | `rm -rf build/` | `/bin/rm -rf build/`, `bash -c 'rm -rf build/'` |
| `Bash(git push *)` | `git push origin main` | `git -C . push origin main`, `git -c push.default=current push origin main`, `git 'push' origin main` |
Your other rules and the permission mode decide the commands in the last column. For filesystem and network enforcement that doesn’t depend on the command text, use [sandboxing](sandboxing.md). To inspect the full command text with your own logic before it runs, use a [PreToolUse hook](#extend-permissions-with-hooks).
[](#read-only-commands)
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, except as [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) changes for paths outside your working directories. The set includes `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. In auto mode, these commands can also wait for the classifier’s review; see [how the classifier evaluates actions](permission-modes.md#how-the-classifier-evaluates-actions). A redirect such as `ls > out.txt` adds a check on the target. See [Redirections](#redirections). 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. In Manual mode, commands from this set still prompt in these cases:
- **Unquoted globs for commands with write-capable flags**: commands with write-capable or exec-capable flags, such as `find`, `sort`, `sed`, and `git`, prompt when an unquoted glob is present, because the glob could expand to a flag like `-delete`.
- **`docker` pointed at another daemon**: read-only forms of `docker` prompt when the command carries a flag that selects a different daemon, such as `-H`, `--context`, or Podman’s `--url` and `--connection`.
- **`file` with path-opening flags**: `file` prompts when it passes `-m`/`--magic-file` or `-f`/`--files-from`, because those flags make `file` open the paths named in the flag’s value.
- **Network paths on Windows**: a command whose arguments include a network (UNC) path, such as `\\server\share\file`, prompts because accessing a network path can send your Windows credentials to the host it names. The same check applies to [PowerShell tool](tools-reference.md#powershell-tool) commands.
- **Writes to special shell variables**: a command that sets, unsets, or loops over certain special shell variables, such as `PATH` or `IFS`, prompts even when the rest of the command is read-only.
- **Commands the analysis can’t parse**: when Claude Code can’t fully parse a command, it asks for approval instead of treating the command as read-only. Commands longer than 10,000 characters always prompt because they exceed what the analysis parses.
A `cd` into a path inside your working directory or an [additional directory](#working-directories) is also read-only, and a compound command like `cd packages/api && ls` runs without a prompt when each part qualifies on its own. These combinations prompt even when each part is read-only:
- **`cd` with `git`**: prompts when the `cd` changes into a different directory, since running `git` in a new directory can execute that directory’s hooks. A `cd` whose target resolves to the current working directory is a no-op and doesn’t trigger the prompt.
- **`cd` with a redirect**: prompts when Claude Code can’t determine which directory the redirect target resolves against after the `cd` runs. A command whose only redirect target is `/dev/null`, such as `cd app; grep -r pattern . 2>/dev/null`, doesn’t prompt, because `/dev/null` doesn’t depend on the working 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://short.example.com/xyz`, which redirects to GitHub
- Variables: `URL=http://github.com && curl $URL`
For more reliable URL filtering, consider:
- **Restrict Bash network tools**: use deny rules to stop `curl`, `wget`, and similar commands, then use the WebFetch tool with `WebFetch(domain:github.com)` permission for allowed domains. A deny rule doesn’t match the same program by path or inside `sh -c`, so pair it with the [sandbox network allowlist](sandboxing.md#network-isolation) when the restriction must hold; see [what a Bash rule doesn’t match](#bash-rule-limits)
- **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 doesn’t prevent network access. If Bash is allowed, Claude can still use `curl`, `wget`, or other tools to reach any URL.
[](#redirections)
Redirections
When a command redirects output or input, Claude Code checks the redirect target against your file rules as if Claude wrote or read that file directly:
- **Output redirects**: for `> file`, `>> file`, or `2> file`, the check covers your `Edit` allow and deny rules, [protected paths](permission-modes.md#protected-paths), and the [working directories](#working-directories). A rule such as `Bash(git commit *)` allows the command, not the target. A target that starts with `~` or contains a glob character needs your approval.
- **Input redirects**: for `< file`, the check covers your `Read` allow and deny rules and the working directories. A target outside the working directories needs your approval unless an allow rule covers it. A target that contains a glob pattern, or a relative path that follows a `cd` in the same command, needs your approval even when an allow rule covers it. Claude Code checks input targets in v2.1.257 and later.
Targets with no file behind them aren’t checked: `/dev/null`, file-descriptor forms such as `2>&1` and `<&3`, and here-docs and here-strings. Claude Code also checks the files a `tee` command writes, including in a pipeline such as `make | tee build.log`. The check covers your `Edit` allow and deny rules, [protected paths](permission-modes.md#protected-paths), and the [working directories](#working-directories). An allow rule such as `Bash(tee *)` doesn’t cover a destination outside the working directories. Claude Code checks `tee` targets in v2.1.269 and later.
[](#powershell)
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`:
```python
{
"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)
Read and Edit
To block Claude’s file tools from reading a file or directory, add a `Read` deny rule for its path, such as `Read(./.env)` or `Read(./secrets/**)`; [Exclude sensitive files](settings-reference.md#exclude-sensitive-files) has a paste-ready example. `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, to `@file` mentions in your prompts, and to the selection and open-file context that a connected [IDE](../03-IDE-Integrations/vs-code.md#the-built-in-ide-mcp-server) shares with Claude. A `Read` deny rule also blocks the [Edit and Write tools](errors.md#file-is-covered-by-a-read-deny-rule) on the same path, including creating a new file there. NotebookEdit isn’t covered, so add an `Edit` deny rule for paths no tool may change. The check requires Claude Code v2.1.208 or later on edits, and v2.1.228 or later on writes. Claude Code checks file permissions against `Edit(path)` and `Read(path)` rules only. If you write a path rule for `Write`, `NotebookEdit`, `Glob`, or the legacy `MultiEdit` tool instead, Claude Code accepts the rule but never consults it, and [warns at startup](errors.md#is-not-matched-by-file-permission-checks), except for a `Glob` rule passed in `--allowedTools`. Use `Edit(docs/**)` in place of `Write(docs/**)`, `NotebookEdit(docs/**)`, or `MultiEdit(docs/**)`, and `Read(docs/**)` in place of `Glob(docs/**)`. Claude Code doesn’t warn about a tool-name rule with no path, such as a deny rule for `Write`; it matches that rule at the tool level everywhere. Requires Claude Code v2.1.210 or later.
Read and Edit deny rules apply to Claude’s built-in file tools, to file commands Claude Code recognizes in Bash, such as `cat`, `head`, `tail`, `sed`, and `tee`, and to the targets of Bash [redirections](#redirections) such as `> file` and `< file`. They don’t apply to a command that reads files without naming them, such as `grep -r pattern .` run from the directory that holds the file, or 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](sandboxing.md).
Read and Edit rules both use [gitignore](https://git-scm.com/docs/gitignore) pattern syntax with four distinct pattern types; for single-segment directory patterns, the matching depth also depends on the rule type, described later in this section:
| 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 the settings source | `Edit(/src/**/*.ts)` | `<primary working directory>/src/**/*.ts` in project settings |
| `path` or `./path` | Path relative to current directory | `Read(*.env)` | `<cwd>/*.env` |
A pattern like `/Users/alice/file` isn’t an absolute path. The single leading slash anchors at the settings source, not the filesystem root. Use `//Users/alice/file` for absolute paths.
A `/path` pattern anchors at a directory associated with the settings source that defines it, so the same rule matches different locations depending on where you put it:
| Rule defined in | `/path` resolves to |
|:------------------------------------------------|:-----------------------------------|
| Project settings at `.claude/settings.json` | `<primary working directory>/path` |
| Local settings at `.claude/settings.local.json` | `<primary working directory>/path` |
| User settings at `~/.claude/settings.json` | `~/.claude/path` |
| A file passed with `--settings <file>` | `<directory of file>/path` |
| CLI flags or session rules | `<primary working directory>/path` |
A rule you add through `/permissions` follows the row for the settings file you save it to. Local settings rules anchor at the session’s [primary working directory](#working-directories), not at the repository root where Claude Code [stores the file](#permission-system) in v2.1.211 and later. In a session started at the repository root, the two directories are the same; in a [worktree](worktrees.md) session, a shared rule such as `Edit(/src/**)` matches that worktree’s own `src/` directory. A deny rule such as `Read(/secrets/**)` in user settings blocks `~/.claude/secrets/**`, not a `secrets` directory in your project. To write a rule in user settings that applies inside every project, use a `//` absolute path or a `~/` home-relative path instead. 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 `<primary working directory>/docs/`, not `/docs/` or `<primary working directory>/.claude/docs/`
- `Read(~/.zshrc)`: reads your home directory’s `.zshrc`
- `Edit(//tmp/scratch.txt)`: edits the absolute path `/tmp/scratch.txt`
- `Read(src/**)`: as an allow rule, reads from `<current-directory>/src/` only; as a deny or ask rule, matches a `src` directory at any depth under the current directory
A rule only matches files under its anchor; within that bound, matching depth depends on the pattern shape and, for single-segment directory patterns, the rule type, described below. 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 |
A relative pattern with a single directory segment, such as `src/**`, matches at different depths depending on the rule type:
- **Allow rules**: `Edit(src/**)` matches only `<cwd>/src` and the files under it. To allow a directory name at any depth, write `Edit(**/src/**)`.
- **Deny and ask rules**: `Read(secrets/**)` matches a directory named `secrets` at any depth under the current directory, so the rule also applies to nested copies.
Every other pattern shape matches at the same depth in every rule type: `Edit(/src/**)` and `Edit(src/components/**)` match only at their anchored location, while `Edit(**/src/**)` matches at any depth. The following example shows each pattern shape against a project with a top-level `src/` directory and a nested copy under `vendor/`:
```python
<current-directory>/
├── src/
│ └── app.ts
└── vendor/
└── pkg/
└── src/
└── lib.js
```
| Rule | Matches `src/app.ts` | Matches `vendor/pkg/src/lib.js` |
|:-------------------------------------|:---------------------|:--------------------------------|
| `Edit(src/**)` as an allow rule | Yes | No |
| `Edit(src/**)` as a deny or ask rule | Yes | Yes |
| `Edit(/src/**)` in any rule type | Yes | No |
| `Edit(**/src/**)` in any rule type | Yes | Yes |
In gitignore patterns, `*` matches within a single path segment and can appear at any position in the pattern, while `**` matches across directories.
When you approve a file path with “Yes, and don’t ask again”, Claude Code escapes gitignore pattern characters in that path, such as `[`, `]`, and `*`, so the generated rule matches only the literal path you approved. Rules you write yourself aren’t escaped. Before v2.1.202, Claude Code saved the path unescaped, so a generated rule for a directory named `[2024-06] Reports` could fail to match its own path or match unintended sibling directories. You don’t need to escape parentheses in a path, so `Edit(./Finance (2024)/**)` matches the `Finance (2024)` folder as spelled. A deny or ask rule whose path isn’t usable as a gitignore pattern still guards that exact path. An allow rule with an unusable pattern doesn’t approve anything. A deny or ask pattern that starts with `!` is a gitignore negation. It carves the paths it matches out of the `path` or `./path` rules listed before it. In one settings file’s `deny` list, `Read(*.env)` followed by `Read(!sample.env)` blocks every file whose name ends in `.env` at any depth, except files named `sample.env`. A `!` rule listed first carves nothing out. The carve-out reaches only rules from the same source. A `Read(!.env)` in project settings or in `--disallowedTools` doesn’t cancel a `Read(./.env)` deny from managed settings or any other settings file. Two limits narrow what a `!` pattern can carve out:
- Claude Code reads a `!` pattern relative to the current directory even when `/`, `~/`, or `//` follows the `!`, so the pattern can’t reach a rule anchored with one of those prefixes. `Read(!~/notes/public/**)` carves nothing out of `Read(~/notes/**)`.
- A carve-out can’t reopen a file inside a directory that a rule blocks as a whole. With `Read(secrets/**)` and `Read(!secrets/public/**)`, Claude Code still blocks `secrets/public` along with the rest of `secrets`.
[](#symlinks)
Symlinks
When a file path Claude requests goes through a symlink, the permission check covers two paths: the one Claude requested and the file it resolves to. This applies to symbolic links on macOS, Linux, and Windows, and to directory junctions on Windows.
##### How rules match a symlinked path
Allow and deny rules treat the requested path and the file it resolves to differently:
- **Allow rules**: apply only when both the requested path and the file it resolves to match. A read through a symlink inside an allowed directory that points outside it doesn’t match the rule.
- **Deny rules**: apply when either the requested path or the file it resolves to 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.
On macOS and Linux, a deny or ask rule written through a symlinked directory with a `//`, `~/`, or `/` pattern also applies at the directory’s real location. For example, on macOS, where `/etc` resolves to `/private/etc`, `Read(//etc/**)` blocks `/private/etc/hosts` too. Before v2.1.268, a deny or ask rule written through a symlinked directory didn’t apply to a path given by its real location. Grep and Glob search the directory the `path` argument resolves to. Claude Code applies `Read` deny rules to that directory.
##### Writes through a symlink
If the path Claude asks to edit or write is itself a symlink, the Edit and Write tools [refuse the write and direct Claude to the link’s target](errors.md#refusing-after-a-symlink-changed). A write can still pass through a symlink when a directory on the way to the file is a symlink, or when a Bash or PowerShell command does the writing. For those writes, what happens depends on where the file the write resolves to sits relative to your [working directories](#working-directories) and the [protected paths](permission-modes.md#protected-paths):
- **Resolves outside the working directories**: when the requested path is inside your working directories and the file it resolves to isn’t, the write isn’t auto-approved in [`acceptEdits` mode](permission-modes.md#auto-approve-file-edits-with-acceptedits-mode). In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), unless an allow rule approves the write, you’re prompted for it instead of the classifier deciding. The prompt names the path the write resolves to.
- **Resolves to a protected path that the requested path doesn’t name**: the [protected paths table](permission-modes.md#protected-paths) gives the outcome for each permission mode, except that where the table routes the write to the classifier, this write prompts you instead.
##### Paths that can’t be resolved or that change
When Claude Code can’t determine where a path leads on disk, for example because symlinks on it form a loop, the Read, Edit, and Write tools [refuse the operation](errors.md#refusing-after-a-symlink-changed). When a tool then opens the approved file, it [confirms that the path still resolves to the location the permission check approved](errors.md#refusing-after-a-symlink-changed).
[](#webfetch)
WebFetch
WebFetch rules use a `domain:` prefix and match against the hostname of the requested URL. Matching is case-insensitive, supports `*` wildcards, and strips a trailing `.` from both the rule and the hostname so `example.com.` and `example.com` are treated the same.
- `WebFetch(domain:example.com)` matches requests to `example.com`
- `WebFetch(domain:*.example.com)` matches any subdomain at any depth, such as `api.example.com` or `a.b.example.com`, but not `example.com` itself
- `WebFetch(domain:*)` matches every domain. It isn’t the same as a bare `WebFetch` rule; see [Allow or deny every fetch](#allow-or-deny-every-fetch)
In any position other than a leading `*.` or a bare `*`, the wildcard matches only the text between two dots. `WebFetch(domain:example.*)` matches `example.org`, where `*` becomes `org`, but not `example.evil.com`, where `*` would have to become `evil.com` and cross a dot. This keeps a trailing wildcard from matching domains an attacker could register. Wildcards in `WebFetch` rules require Claude Code v2.1.172 or later to match fetches.
[](#allow-or-deny-every-fetch)
Allow or deny every fetch
A bare `WebFetch` rule is the tool name with no `domain:` part, such as `"deny": ["WebFetch"]`. Both it and `WebFetch(domain:*)` cover every URL, but Claude Code applies them differently, and only the `domain:` form also adds its domain to the sandbox’s [allowed or denied domain list](sandboxing.md#network-isolation). That section lists the wildcard forms the sandbox honors and the version that added bare `*`. Each row shows what a rule does in the `allow` list and in the `deny` list:
| Rule | In `allow` | In `deny` |
|:---------------------|:-----------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
| `WebFetch` | Claude fetches without prompting you. Doesn’t change which hosts sandboxed commands can reach. | Claude Code removes the `WebFetch` tool, so Claude can’t fetch at all. Doesn’t change which hosts sandboxed commands can reach. |
| `WebFetch(domain:*)` | Claude fetches without prompting you, and sandboxed commands can reach any host. | Claude Code keeps the tool and refuses each fetch, and sandboxed commands can’t reach any host. |
The two forms also differ on reads of [artifacts](artifacts.md), the pages the Artifact tool publishes on claude.ai. A bare `WebFetch` deny or ask rule doesn’t apply to those reads. A `domain:` rule covering `claude.ai` or the `*.claudeusercontent.com` content host, such as `WebFetch(domain:claude.ai)` or `WebFetch(domain:*)`, denies each read or prompts before it. An [`Artifact` rule](artifacts.md#disable-artifacts) does the same. When a rule blocks a read, the denial names the rule. Before v2.1.268, a bare `WebFetch` deny rule blocked every artifact read, and a bare ask rule prompted before each one. To let Claude fetch freely while keeping the sandbox allowlist as it is, use the bare form. This `settings.json` does that:
```python
{
"permissions": {
"allow": ["WebFetch"]
}
}
```
When you ask Claude to fetch a page, it fetches without a prompt. When you ask it to run a [sandboxed](sandboxing.md) `curl` against a host outside the sandbox allowlist, Claude Code still prompts you for that host, because the bare rule didn’t add the host to the allowlist. In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), Claude instead names the host in the command’s [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode) for the classifier to review.
[](#mcp)
MCP
MCP rules use the server name as configured in Claude Code, optionally followed by the name of a tool from that server.
- `mcp__puppeteer` matches any tool provided by the `puppeteer` server
- `mcp__puppeteer__*` uses wildcard syntax and also matches all tools from the `puppeteer` server
- `mcp__puppeteer__puppeteer_navigate` matches the `puppeteer_navigate` tool provided by the `puppeteer` server
If your organization has set a [claude.ai connector](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools) tool to `ask` and that setting reaches Claude Code in your session, allow rules for that tool don’t take effect: Claude Code prompts on every call, even in `auto` and `bypassPermissions` modes. In `dontAsk` mode, which never prompts, Claude Code denies the call instead. Tools from connectors Claude Code fetches itself appear as `mcp__claude_ai_<server>__<tool>`. In a [Cowork](https://claude.com/docs/cowork/overview) session in the Claude Desktop app, Claude runs shell commands through Cowork’s `mcp__workspace__bash` tool rather than the built-in `Bash` tool, and Cowork likewise provides `mcp__workspace__web_fetch` for web fetches. Claude Code also applies deny rules that name the whole `Bash` or `WebFetch` tool to these Cowork tools, so a managed `Bash` deny rule stops Claude from running shell commands in Cowork. When Claude Code blocks such a call, the message names the Cowork tool: `Permission to use mcp__workspace__bash has been denied.` Allow rules don’t carry over: Claude Code never applies a `Bash` allow rule to `mcp__workspace__bash`.
[](#agent-subagents)
Agent (subagents)
Use `Agent(AgentName)` rules to control which [subagents](../09-Agents-Patterns/sub-agents.md) 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:
```python
{
"permissions": {
"deny": ["Agent(Explore)"]
}
}
```
[](#cd)
Cd
`Cd` rules control which directories the [`/cd` command](commands.md) can move the session to. `Cd` is not a model-invocable tool: Claude can’t call it, and the rules apply only when you run `/cd` yourself. A bare `Cd` deny rule disables `/cd` entirely. A `Cd(<path-pattern>)` deny rule blocks matching targets. Deny rules check every spelling of the target, including each symlink hop it resolves through, so a rule written for one path also blocks targets that resolve to it. Adding any `Cd` allow rule switches `/cd` to allowlist mode: the resolved target directory must match one of your allow rules, or `/cd` refuses. With no `Cd` rules configured, `/cd` keeps its default behavior and prompts you to trust an unfamiliar directory. Path patterns share the `//`, `~/`, and `/` anchors from [Read and Edit rules](#read-and-edit), but matching is anchored to the whole directory path rather than gitignore-style. `*` matches exactly one path segment and `**` matches across segments. A trailing `/**` also matches its named root.
| Rule | Matches | Does not match |
|-----------------------|-----------------------------------------------------------------------|------------------------------|
| `Cd(~/code/*)` | `~/code/app` | `~/code/app/src`, `~/code` |
| `Cd(~/code/**)` | `~/code` and any directory under it | directories outside `~/code` |
| `Cd(**/node_modules)` | any `node_modules` directory at any depth under the current directory | `node_modules/pkg` |
[](#extend-permissions-with-hooks)
Extend permissions with hooks
[Claude Code hooks](../07-Hooks/hooks-guide.md) let you register custom shell commands that evaluate permissions at runtime. When Claude Code makes a tool call, PreToolUse hooks run before the permission prompt, for every tool except [`EndConversation`](tools-reference.md#endconversation-tool-behavior). The hook output can deny the tool call, force a prompt, or skip the prompt to let the call proceed. Hook decisions don’t bypass permission rules. Claude Code evaluates deny and ask rules regardless of what a PreToolUse hook returns: 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](#manage-permissions), including deny rules set in managed settings. MCP tools marked [`requiresUserInteraction`](../06-MCP-Tools/General/mcp.md#require-approval-for-a-specific-tool) also still prompt when a hook returns `"allow"`, as do connector tools [your organization set to `ask`](../06-MCP-Tools/General/mcp.md#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code. 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](../07-Hooks/hooks-guide.md#block-edits-to-protected-files) for a hook script you can adapt.
[](#working-directories)
Working directories
By default, Claude has access to files in the directory where you launched it. That directory is the session’s primary working directory until you [move the session with `/cd`](#move-the-session-to-another-directory). 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](settings.md#where-settings-live)
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. You can’t add most [network paths](errors.md#working-directory-is-a-network-path), such as the UNC share `\\server\share`, as working directories, because looking one up can contact the host it names. On Windows, map the share to a drive letter instead and pass the drive with `--add-dir` at launch. Set [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) to make the file tools refuse the paths it fences in every permission mode. In auto mode, Claude Code offers to turn it on the first time Claude [reads outside the working directories](permission-modes.md#first-read-outside-the-working-directories). In background sessions on macOS, the session host requests access to protected folders such as `~/Desktop`, `~/Documents`, and `~/Downloads` separately from your terminal when Claude needs to read or write files there; if reads there fail with `Operation not permitted`, see [how to grant folder access to background sessions](../09-Agents-Patterns/agent-view.md#background-sessions-can%E2%80%99t-read-desktop-documents-or-downloads-on-macos).
[](#move-the-session-to-another-directory)
Move the session to another directory
To move the session to a different primary working directory, rather than [adding a directory](#working-directories) alongside the current one, run `/cd <path>`. Claude Code keeps the conversation, loads the new directory’s `CLAUDE.md`, and prompts you to [trust the workspace](#project-allow-rules-and-workspace-trust) if you haven’t worked in it before. Afterward, Claude Code [finds the moved session](sessions.md#resume-a-session) when you run `--resume` from the new directory. As soon as you move, Claude Code applies the new directory’s project configuration:
- Its project settings, including their permission rules and [hooks](../07-Hooks/hooks.md)
- Its [`.mcp.json` servers](../06-MCP-Tools/General/mcp.md#project-scope), subject to the same [server approval](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) as at startup, and the [local-scope](../06-MCP-Tools/General/mcp.md#local-scope) MCP servers you registered in it
- The [plugins](../08-Plugins-Skills/plugins.md) its settings enable, its [skills](../08-Plugins-Skills/skills.md#discovery-from-parent-and-nested-directories), and its [subagents](../09-Agents-Patterns/sub-agents.md)
- Its [`env`](settings-reference.md#env) values, applied on top of the environment variables from the previous directory’s settings, which stay in effect
Claude Code also disconnects the previous directory’s project and [local-scope](../06-MCP-Tools/General/mcp.md#local-scope) MCP servers, and the servers of [plugins](../06-MCP-Tools/General/mcp.md#plugin-provided-mcp-servers) that are no longer enabled after the move. It takes [additional directories](#working-directories) from the new directory’s settings instead of the previous one’s, and keeps the directories you added with `--add-dir` or `/add-dir`. Hooks the move activates still receive [`${CLAUDE_PROJECT_DIR}`](../07-Hooks/hooks.md#reference-scripts-by-path) set to the project root where the session started. When the new directory isn’t trusted yet, Claude Code lists in the trust prompt the allow rules, additional directories, hooks, and helper commands the directory’s settings would activate, so you can review them before you accept. If you decline, the session stays where it is. Before v2.1.246, `/cd` didn’t apply the new directory’s settings, hooks, MCP servers, or skills until you resumed the session, and its trust prompt didn’t list what the directory’s settings would activate. Restrict or disable `/cd` targets with [`Cd` permission rules](#cd).
[](#additional-directories-grant-file-access-not-configuration)
Additional directories grant file access, not configuration
Adding a directory extends where Claude can read and edit files. It doesn’t make that directory a full configuration root: most `.claude/` configuration is not discovered from additional directories, though a few types are loaded as exceptions. These exceptions apply only to directories added with the `--add-dir` flag or the `/add-dir` command, including directories the Agent SDK adds through the flag. Directories listed in `permissions.additionalDirectories` in a settings file grant file access only and don’t load any of the configuration below. The Agent SDK’s [`additionalDirectories`](../05-Agent-SDK/agent-sdk-typescript.md#options) option in TypeScript and [`add_dirs`](../05-Agent-SDK/agent-sdk-python.md#claudeagentoptions) option in Python receive the exceptions too, even though the TypeScript option shares its name with the settings key. The SDK passes each entry to Claude Code as `--add-dir`, so those directories behave like flag-added directories. Skills, commands, and subagents from any flag-added directory load through the `project` [setting source](../05-Agent-SDK/agent-sdk-claude-code-features.md#control-filesystem-settings-with-settingsources), so they don’t load when you exclude that source with [`--setting-sources`](cli-reference.md) on the CLI or `settingSources` in the SDK, and [bare mode](headless.md#start-faster-with-bare-mode) skips the commands and subagents among them. The following configuration types are loaded from `--add-dir` directories:
| Configuration | Loaded from `--add-dir` |
|:-------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Skills](../08-Plugins-Skills/skills.md) in `.claude/skills/` | Yes, with live reload |
| [Command files](../08-Plugins-Skills/skills.md#where-skills-live) in `.claude/commands/` | Yes, without live reload. When the added directory and your project both define a command with the same name, Claude Code runs your project’s command |
| [Subagents](../09-Agents-Patterns/sub-agents.md) in `.claude/agents/` | Yes, without live reload |
| [Settings](settings.md) in `.claude/settings.json` and `.claude/settings.local.json` | `enabledPlugins` and [`extraKnownMarketplaces`](settings-reference.md#extraknownmarketplaces) keys only |
| [CLAUDE.md](memory.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 |
To load the skills, commands, and subagents from a subdirectory of your [primary working directory](#working-directories) mid-session, run `/add-dir` with that subdirectory’s path. Claude Code loads them for the rest of the session without prompting you or adding a working directory, because the subdirectory is already readable. This requires Claude Code v2.1.257 or later. Claude Code discovers output styles from the current working directory and its parents, your user directory at `~/.claude/`, and managed settings. Hooks and other `.claude/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. `.claude/settings.local.json` loads from the git repository root instead, even when you start Claude Code in a subdirectory, except in the cases where Claude Code [doesn’t use the repository root](settings.md#where-claude-code-looks-for-each-file), such as on Windows; before v2.1.211, it too loaded only from the current working directory. [Agent SDK](../05-Agent-SDK/agent-sdk-claude-code-features.md#control-filesystem-settings-with-settingsources) sessions load it from the working directory in all versions. 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](../08-Plugins-Skills/plugins.md) 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)
How permissions interact with sandboxing
Permissions and [sandboxing](sandboxing.md) are complementary security layers:
- **Permissions** control which tools Claude Code can use and which files or domains it can access. They apply to Bash, Read, Edit, WebFetch, MCP, and every other tool, except that a deny or ask rule can’t block [`EndConversation`](tools-reference.md#endconversation-tool-behavior) while any other tool remains.
- **Sandboxing** provides OS-level enforcement that restricts shell commands’ filesystem and network access. It applies only to Bash, PowerShell, and [Monitor](tools-reference.md#monitor-tool) commands and their child processes.
Use both for defense-in-depth, since sandbox restrictions still apply even if a prompt injection bypasses Claude’s decision-making. Paths and domains from both sandbox settings and permission rules are [merged into the final sandbox configuration](sandboxing.md#permission-rules). When you enable sandboxing and leave `autoAllowBashIfSandboxed` at its default of `true`, sandboxed Bash commands run without prompting even if your permissions include a bare `Bash` ask rule, or the [equivalent `Bash(*)` form](#match-all-uses-of-a-tool): the sandbox boundary substitutes for that whole-tool prompt. In [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode), Claude Code skips this substitution. Without an ask rule, the [built-in read-only commands](#read-only-commands) still run without prompting, and any other shell command goes through the regular permission flow while you are still planning; see [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) for how Claude Code gates commands there. With a bare `Bash` ask rule, every Bash command prompts, including sandboxed read-only commands, the same as outside sandboxing. Before v2.1.212, the substitution applied in plan mode as well. These checks still apply:
- Content-scoped ask rules like `Bash(git push *)` still force a prompt
- Explicit deny rules still apply
- `rm` or `rmdir` commands that target a [critical path](permission-modes.md#critical-paths) still go through the regular permission flow
Commands that won’t run sandboxed, such as excluded commands, respect the bare `Bash` ask rule as usual. See [sandbox modes](sandboxing.md#sandbox-modes) to change this behavior.
[](#managed-settings)
Managed settings
For organizations that need centralized control, administrators deploy managed settings that user and project settings can’t override, apart from a few [security-sensitive keys](settings.md#exceptions-to-managed-settings-precedence). [Deploy managed settings](../13-Enterprise-Admin/managed-settings.md) covers the delivery mechanisms, precedence within the managed tier, and the [keys that only managed settings can set](../13-Enterprise-Admin/managed-settings.md#managed-only-settings). One of those keys, [`allowManagedPermissionRulesOnly`](settings-reference.md#allowmanagedpermissionrulesonly), makes managed settings the only settings source of permission rules. Its entry lists every source Claude Code then ignores. `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.
[](#settings-precedence)
Settings precedence
Permission rules follow the same [settings precedence](settings.md#settings-precedence) as all other Claude Code settings, with managed settings highest: no other level, including command line arguments, can override a managed permission rule. If a tool is denied at any level, no other level can allow it. For example, a managed settings deny can’t be overridden by `--allowedTools`, and `--disallowedTools` can add restrictions beyond what managed settings define. The same holds across settings scopes: 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. Embedding hosts can supply additional managed policy via the SDK `managedSettings` option, including permission allow rules unless the admin sets the `allowManaged*Only` locks; [Deliver policy to Claude Desktop sessions](../13-Enterprise-Admin/claude-apps-gateway.md#deliver-policy-to-claude-desktop-sessions) covers when embedder policy applies at all.
[](#project-allow-rules-and-workspace-trust)
Project allow rules and workspace trust
`permissions.allow` rules and `permissions.additionalDirectories` entries in a project’s `.claude/settings.json` grant capability, so Claude Code applies them only after you accept the [workspace trust dialog](../13-Enterprise-Admin/security.md#additional-safeguards) for that folder. The dialog lists the rules and directories the folder would grant so you can review them first. `deny` and `ask` rules aren’t affected, since they only restrict. Claude Code keys and stores the trust you accept according to where you start it:
- In a repository, Claude Code keys the trust on the git repository root, so the trust covers the whole repository apart from any git repository nested inside it, such as a submodule. In a [worktree](worktrees.md), it uses the main checkout’s root, as it does for [saved rules](#permission-system).
- Outside a repository, Claude Code keys the trust on the directory you started it from, and the trust covers any subdirectory of that directory apart from a git repository nested inside it, such as a clone. Each covered subdirectory then counts as a folder whose parent you trusted.
- When you start in your home directory, Claude Code holds the trust for the current session only and doesn’t write it to disk; see the [additional safeguards](../13-Enterprise-Admin/security.md#additional-safeguards) note.
Claude Code shows the trust dialog in interactive sessions only. A `claude -p` run or an SDK session never shows it, and trusting a parent folder doesn’t count for these rules, so [What runs before you trust a folder](#what-runs-before-you-trust-a-folder) says which repository content Claude Code still uses in each of those two situations. Before it starts or restarts a [background session](../09-Agents-Patterns/agent-view.md), Claude Code also checks workspace trust for the directory the session runs in. If you run `claude --bg` from a terminal in a directory you haven’t trusted, the trust dialog appears first and the session starts once you accept it. Where no dialog can appear, such as in a script, the command exits with a [`Workspace not trusted`](errors.md#workspace-not-trusted-when-dispatching-a-background-session) error instead.
[](#when-your-local-settings-file-needs-trust)
When your local settings file needs trust
`.claude/settings.local.json` is normally your own file, so Claude Code applies its allow rules and additional directories without the trust step. When the file is tracked in git, or `.claude` is a symlink, Claude Code treats it as repository-supplied instead and holds its rules until you trust the folder. Claude Code runs git to tell the two apart, and it runs git only once you’ve trusted the folder: you accepted the trust dialog for it or for a parent directory whose trust extends to it, or you’re in a `-p` or SDK session, which counts as accepted. Until then, where you started Claude Code decides what happens to the file’s rules:
- **In your configuration home:** Claude Code applies that folder’s `.claude/settings.local.json` right away without running git. Your configuration home is your home directory, or a directory whose `.claude` subdirectory you’ve set as [`CLAUDE_CONFIG_DIR`](env-vars.md#variables). If that `CLAUDE_CONFIG_DIR` directory sits inside a git repository and Claude Code [keeps your local settings at the repository root](settings.md#where-claude-code-looks-for-each-file) instead, it holds the rules like anywhere else.
- **Anywhere else:** Claude Code holds the file’s rules like project settings. Once the check has run, Claude Code applies the rules of an untracked file, or of a file in a directory outside any git repository, even though you haven’t trusted that exact folder.
The configuration-home exception skips only the trust step. `~/.claude/settings.local.json` is still [local scope](settings.md#compare-the-scope-of-each-settings-file), so Claude Code reads it only in sessions you start in your home directory itself, not in every project. To apply permission rules across all your projects, add them to your user settings instead: `~/.claude/settings.json`, or `$CLAUDE_CONFIG_DIR/settings.json` when `CLAUDE_CONFIG_DIR` is set.
On versions 2.1.196 through 2.1.199, Claude Code held the file’s rules in your configuration home and outside git repositories too, and printed the [`this workspace has not been trusted`](errors.md#workspace-has-not-been-trusted) warning there. Before v2.1.207, Claude Code applied an untracked file’s rules before you accepted the dialog.
[](#what-runs-before-you-trust-a-folder)
What runs before you trust a folder
Each row is one kind of content a repository can supply. The columns are the two situations in which you haven’t trusted the folder itself: you trusted only a parent folder, or you ran `claude -p` or the SDK there, which never shows the trust dialog. The parent-folder column doesn’t apply inside a [nested repository](#project-allow-rules-and-workspace-trust): in an interactive session Claude Code shows the trust dialog for it, and a `claude -p` or SDK run there follows the `claude -p` column.
| What the repository supplies | You trusted only a parent folder | `claude -p` or the SDK, folder never trusted |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Hooks](../07-Hooks/hooks.md) in settings files, the [`env`](settings-reference.md#env) block and helper commands such as [`apiKeyHelper`](settings-reference.md#apikeyhelper), and a project skill’s [hooks](../07-Hooks/hooks.md#hooks-in-skills-and-agents) and [`allowed-tools`](../08-Plugins-Skills/skills.md#pre-approve-tools-for-a-skill) | Used | Used. Workspace trust never gates a skill’s `allowed-tools` in any session |
| `permissions.allow` rules and `additionalDirectories` in `.claude/settings.json` | Not used until you accept the trust dialog, which appears again listing them | Not used. Claude Code prints a [`this workspace has not been trusted`](errors.md#workspace-has-not-been-trusted) warning to stderr |
| Frontmatter hooks in a project [subagent](../09-Agents-Patterns/sub-agents.md#hooks-in-subagent-frontmatter), a project [`@skills-dir` plugin](../08-Plugins-Skills/plugins-loading.md#plugins-shared-through-a-repository), and [`extraKnownMarketplaces`](settings-reference.md#extraknownmarketplaces) entries from the repository or an `--add-dir` directory | Not used, and no dialog is offered | Not used |
| Inline [`mcpServers`](../09-Agents-Patterns/sub-agents.md#scope-mcp-servers-to-a-subagent) in the frontmatter of a subagent from the repository or an `--add-dir` directory. Before v2.1.238, Claude Code loaded these servers in both situations | Not used, and no dialog is offered | Not used |
| Servers in `.mcp.json`, including ones the repository [approves in its own settings](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) | Claude Code asks you before connecting them. The repository’s own approvals don’t count | Connected without asking, approved or not. The SDK loads them only when `settingSources` includes project settings. `claude mcp list` in the same folder still reports such a server as pending |
| A [`headersHelper`](../06-MCP-Tools/General/mcp.md#trust-a-folder-before-its-headershelper-runs) on a server in `.mcp.json`. Before v2.1.238, Claude Code ran the helper in both situations | Not run until you accept the trust dialog, which appears again naming where the helper is declared. Claude Code connects the server with its static `headers` alone until then | Not run. Claude Code connects the server with its static `headers` alone and prints a [`headersHelper not run`](errors.md#headershelper-not-run) line per server to stderr |
For the rows that need this exact folder trusted, trust it by hand: set `projects["<path>"].hasTrustDialogAccepted` to `true` in `~/.claude.json`, where `<path>` is the repository root, or the folder itself outside a repository. Claude Code prints the exact key in the debug log line for a skipped subagent hook or inline MCP server, in the stderr warning for skipped allow rules, and in the `headersHelper not run` line for a skipped helper. Before you run `claude -p` in a repository you didn’t write, decide what it may run on your machine:
- Pass `--setting-sources user`, or set the SDK’s `settingSources` without project settings, so Claude Code reads neither the project’s settings files nor its `.mcp.json`
- Start with [`--bare`](headless.md#start-faster-with-bare-mode) so Claude Code reads no hooks, skills, custom commands, subagents, plugins, or `.mcp.json` servers from the project. The project’s `env` block and helpers such as `awsAuthRefresh` in its settings files still apply, and Claude Code reads `apiKeyHelper` only from `--settings`
- Pass `--settings '{"disableAllHooks": true}'` to [turn hooks off](../07-Hooks/hooks.md#disable-or-remove-hooks) for that run. Setting it in your user settings alone isn’t enough, because the repository’s project settings take precedence over yours and can set it back to `false`
- Add a [`disabledMcpjsonServers`](settings-reference.md#disabledmcpjsonservers) entry to reject a `.mcp.json` server by name in every session type
[](#example-configurations)
Example configurations
This [repository](https://github.com/anthropics/claude-code/tree/main/examples/settings) includes starter settings configurations for common deployment scenarios. Use these as starting points and adjust them to fit your needs.
[](#see-also)
See also
- [All settings](settings-reference.md#permission-settings): every settings key, including the permission keys
- [Configure auto mode](auto-mode-config.md): tell the auto mode classifier which infrastructure your organization trusts
- [Sandboxing](sandboxing.md): OS-level filesystem and network isolation for Bash commands
- [Authentication](../13-Enterprise-Admin/iam.md): set up user access to Claude Code
- [Security](../13-Enterprise-Admin/security.md): security safeguards and best practices
- [Hooks](../07-Hooks/hooks-guide.md): automate workflows and extend permission evaluation
---
## Platforms and integrations - Claude Code Docs
Source: https://code.claude.com/docs/en/platforms
Path: 02-Claude-Code-CLI/platforms.md
## On this page
- [Where to run Claude Code](#where-to-run-claude-code)
- [Connect your tools](#connect-your-tools)
- [Work when you are away from your terminal](#work-when-you-are-away-from-your-terminal)
- [Related resources](#related-resources)
- [Platforms](#platforms)
- [Integrations](#integrations)
- [Remote access](#remote-access)
Platforms and integrations
# Platforms and integrations
Copy pageCopy page
Choose where to run Claude Code and what to connect it to. Compare the CLI, Desktop, VS Code, JetBrains, web, mobile, and integrations like Chrome, Slack, and CI/CD.
Copy pageCopy page
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)
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](../01-Getting-Started/quickstart.md) | Terminal workflows, scripting, remote servers | Full feature set, [Agent SDK](headless.md), [computer use](computer-use.md) on macOS (Pro and Max), third-party providers |
| [Desktop](../16-Mobile-Desktop/desktop.md) | Visual review, parallel sessions, managed setup | Diff viewer, app preview, [computer use](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer) and [Dispatch](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch) on Pro and Max |
| [VS Code](../03-IDE-Integrations/vs-code.md) | Working inside VS Code without switching to a terminal | Inline diffs, integrated terminal, file context |
| [JetBrains](../03-IDE-Integrations/jetbrains.md) | Working inside IntelliJ, PyCharm, WebStorm, or other JetBrains IDEs | Diff viewer, selection sharing, terminal session |
| [Web](claude-code-on-the-web.md) | Long-running tasks that don’t need much steering, or work that should continue when you’re offline | Cloud, Anthropic-managed by default; continues after you disconnect |
| [Mobile](../16-Mobile-Desktop/mobile.md) | Starting and monitoring tasks while away from your computer | Cloud sessions from the Claude app for iOS and Android, [Remote Control](remote-control.md) for local sessions, [Dispatch](../16-Mobile-Desktop/desktop.md#sessions-from-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](../03-IDE-Integrations/vs-code.md#use-third-party-providers) and in [JetBrains](feature-availability.md#features-available-on-every-provider), which runs the CLI in your IDE’s terminal. Enterprise [Desktop](../16-Mobile-Desktop/desktop.md) deployments support Google Cloud’s Agent Platform, and Desktop supports [gateway providers](../13-Enterprise-Admin/llm-gateway-connect.md#desktop-app); for Amazon Bedrock or Microsoft Foundry, use the CLI or an IDE extension, or [Claude Desktop on 3P](https://claude.com/docs/third-party/claude-desktop/overview), which runs the Code tab on those providers. Desktop and the IDE extensions trade some CLI-only features for visual review and tighter editor integration. The web runs in the 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)
Connect your tools
Integrations let Claude work with services outside your codebase.
| Integration | What it does | Use it for |
|:-------------------------------------------------|:-----------------------------------------------------------------------------------|:------------------------------------------------------------------------------------|
| [Chrome](../03-IDE-Integrations/chrome.md) | Controls your browser with your logged-in sessions | Testing web apps, filling forms, automating sites without an API |
| [GitHub Actions](github-actions.md) | Runs Claude in your CI pipeline | Automated PR reviews, issue triage, scheduled maintenance |
| [GitLab CI/CD](gitlab-ci-cd.md) | Same as GitHub Actions for GitLab | CI-driven automation on GitLab |
| [Code Review](code-review.md) | Reviews every PR automatically | Catching bugs before human review |
| [Slack](../14-Connectors/slack.md) | Responds to `@Claude` mentions in your channels | Turning bug reports into pull requests from team chat |
| [Claude Tag](https://claude.com/docs/claude-tag) | Runs `@Claude` as your organization’s shared identity with admin-configured access | Shared team access on Team and Enterprise plans, instead of per-user Slack sessions |
For integrations not listed here, [MCP servers](../06-MCP-Tools/General/mcp.md) and [connectors](../16-Mobile-Desktop/desktop.md#connect-external-tools) let you connect almost anything: Linear, Notion, Google Drive, or your own internal APIs.
[](#work-when-you-are-away-from-your-terminal)
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](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch) | Message a task from the Claude mobile app | Your machine (Desktop) | [Pair the mobile app with Desktop](https://code.claude.com/docs/99-Other/assign-tasks-from-anywhere-in-claude-cowork-claude-help-center-6bf98a1bec.md) | Delegating work while you’re away, minimal setup |
| [Remote Control](remote-control.md) | Drive a running session from [claude.ai/code](https://claude.ai/code) or the Claude mobile app | Your machine (CLI, Desktop, or VS Code) | Run [`claude remote-control` or `/remote-control`](remote-control.md#start-a-remote-control-session) | Steering in-progress work from another device |
| [Channels](channels.md) | Push events from a chat app like Telegram or Discord, or your own server | Your machine (CLI) | [Install a channel plugin](channels.md#quickstart) or [build your own](channels-reference.md) | Reacting to external events like CI failures or chat messages |
| [Slack](../14-Connectors/slack.md) | Mention `@Claude` in a team channel | Anthropic cloud | [Install the Slack app](../14-Connectors/slack.md#setting-up-claude-code-in-slack) with [Claude Code on the web](claude-code-on-the-web.md) enabled | PRs and reviews from team chat |
| [Self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md) | Start a [cloud session](claude-code-on-the-web.md) and pick your organization’s environment | Your organization’s infrastructure | [Deploy runners](../13-Enterprise-Admin/self-hosted-environments-quickstart.md), on Team and Enterprise plans | Cloud sessions that must run inside your network |
| [Scheduled tasks](scheduled-tasks.md) | Set a schedule | [CLI](scheduled-tasks.md), [Desktop](../16-Mobile-Desktop/desktop-scheduled-tasks.md), or [cloud](web-scheduled-tasks.md) | Pick a frequency | Recurring automation like daily reviews |
If you’re not sure where to start, [install the CLI](../01-Getting-Started/quickstart.md) and run it in a project directory. If you’d rather not use a terminal, [Desktop](../16-Mobile-Desktop/desktop-quickstart.md) gives you the same engine with a graphical interface.
[](#related-resources)
Related resources
[](#platforms)
Platforms
- [CLI quickstart](../01-Getting-Started/quickstart.md): install and run your first command in the terminal
- [Desktop](../16-Mobile-Desktop/desktop.md): visual diff review, parallel sessions, computer use, and Dispatch
- [VS Code](../03-IDE-Integrations/vs-code.md): the Claude Code extension inside your editor
- [JetBrains](../03-IDE-Integrations/jetbrains.md): the extension for IntelliJ, PyCharm, and other JetBrains IDEs
- [Web](claude-code-on-the-web.md): cloud sessions from your browser at claude.ai/code that keep running when you disconnect
- [Projects](claude-projects.md): one conversation where Claude coordinates many cloud sessions for a body of work and reports back
- [Mobile](../16-Mobile-Desktop/mobile.md): the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) and [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) for starting and monitoring tasks while away from your computer
[](#integrations)
Integrations
- [Chrome](../03-IDE-Integrations/chrome.md): automate browser tasks with your logged-in sessions
- [Computer use](computer-use.md): let Claude open apps and control your screen on macOS
- [GitHub Actions](github-actions.md): run Claude in your CI pipeline
- [GitLab CI/CD](gitlab-ci-cd.md): the same for GitLab
- [Code Review](code-review.md): automatic review on every pull request
- [Slack](../14-Connectors/slack.md): send tasks from team chat, get PRs back
- [Claude Tag](https://claude.com/docs/claude-tag): run `@Claude` as your organization’s shared identity on Team and Enterprise plans
[](#remote-access)
Remote access
- [Dispatch](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch): message a task from your phone and it can spawn a Desktop session
- [Remote Control](remote-control.md): drive a running session from your phone or browser
- [Channels](channels.md): push events from chat apps or your own servers into a session
- [Scheduled tasks](scheduled-tasks.md): run prompts on a recurring schedule
---
## How Claude Code uses prompt caching - Claude Code Docs
Source: https://code.claude.com/docs/en/prompt-caching
Path: 02-Claude-Code-CLI/prompt-caching.md
## On this page
- [How the cache is organized](#how-the-cache-is-organized)
- [Where the cache lives](#where-the-cache-lives)
- [Actions that invalidate the cache](#actions-that-invalidate-the-cache)
- [Switching models](#switching-models)
- [Changing effort level](#changing-effort-level)
- [Turning on fast mode](#turning-on-fast-mode)
- [Connecting or removing an MCP server](#connecting-or-removing-an-mcp-server)
- [Enabling or disabling a plugin](#enabling-or-disabling-a-plugin)
- [Plugin components that keep the cache](#plugin-components-that-keep-the-cache)
- [Plugins that provide MCP servers](#plugins-that-provide-mcp-servers)
- [Code intelligence plugins](#code-intelligence-plugins)
- [When plugin changes apply](#when-plugin-changes-apply)
- [Plugins you enable and then disable in one session](#plugins-you-enable-and-then-disable-in-one-session)
- [Denying an entire tool](#denying-an-entire-tool)
- [Compacting the conversation](#compacting-the-conversation)
- [Accumulating many images](#accumulating-many-images)
- [Upgrading Claude Code](#upgrading-claude-code)
- [Actions that keep the cache](#actions-that-keep-the-cache)
- [Editing files in your repository](#editing-files-in-your-repository)
- [Editing CLAUDE.md mid-session](#editing-claude-md-mid-session)
- [Changing permission mode](#changing-permission-mode)
- [Changing output style](#changing-output-style)
- [Invoking skills and commands](#invoking-skills-and-commands)
- [Running /recap](#running-%2Frecap)
- [Rewinding the conversation](#rewinding-the-conversation)
- [Resuming a session](#resuming-a-session)
- [Cache lifetime](#cache-lifetime)
- [Which TTL each request gets](#which-ttl-each-request-gets)
- [Choose the TTL yourself](#choose-the-ttl-yourself)
- [Cache scope](#cache-scope)
- [Check cache performance](#check-cache-performance)
- [Subagents and the cache](#subagents-and-the-cache)
- [Disable prompt caching](#disable-prompt-caching)
- [Related resources](#related-resources)
Core concepts
# How Claude Code uses prompt caching
Copy pageCopy page
Claude Code manages prompt caching automatically. See why a model switch triggers a slow uncached turn, what `/compact` costs, why CLAUDE.md edits don’t apply mid-session, and how to check your cache hit rate.
Copy pageCopy page
Prompt caching makes Claude Code faster and more cost-efficient. Without caching, the API would reprocess your full history on every turn. With caching, it reuses what it already processed, bills the re-read at the [cached token rate](../17-Billing-Plans/about-claude-pricing.md), and fully processes only what changed. Claude Code handles prompt caching for you, unless you [disable it](#disable-prompt-caching). It is still useful to know how prompt caching works, because some actions invalidate the cache and make the next response slower and more expensive while it rebuilds. This page covers which actions those are, why some settings wait for a restart to apply, and how to check cache performance when usage looks high.
[](#how-the-cache-is-organized)
How the cache is organized
Each time you send a message in Claude Code, it makes a new API request. The model doesn’t remember anything between requests, so Claude Code re-sends the full context: the system prompt, your project context, every prior message and tool result, and your new message. New content is appended at the end, which means most of each request is identical to the one before it. Prompt caching is how the API avoids reprocessing the part that didn’t change. The API caches by matching the start of each request, called the prefix, against content it recently processed. On a normal turn, the prefix is the entire previous request and only the latest exchange is new. The match is exact, so a change anywhere in the prefix recomputes everything after it. There is no per-file or per-segment caching. See [how prompt caching works](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#how-prompt-caching-works) in the API reference for the underlying mechanism.
To get the most out of prefix matching, Claude Code orders each request so content that rarely changes between turns comes first:
| Layer | Content | Changes when |
|-----------------|-------------------------------------------------|-------------------------------------------------|
| System prompt | Core instructions, tool definitions | The set of loaded tool definitions changes |
| Project context | CLAUDE.md, auto memory, unscoped rules | Session starts, or after `/clear` or `/compact` |
| Conversation | Your messages, Claude’s responses, tool results | Every turn |
A change to the conversation layer leaves the system prompt and project context cached. A change to the system prompt invalidates everything, because all later content now sits behind a different prefix. The third column gives common triggers rather than an exhaustive list, and the sections below cover the full set. The prefix-match rule explains most of the behaviors on this page. [Plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) and [skill loading](../08-Plugins-Skills/skills.md), for example, append their instructions as conversation messages, so the cached prefix stays intact. Two settings don’t appear in the layer table but still affect what stays cached:
- **Model**: each model has its own cache. Switching models recomputes the entire request even when the content is identical. See [Switching models](#switching-models) below.
- **Effort level**: on most models, each effort level has its own cache, so changing effort mid-session recomputes the entire request. On Opus 5.5, Sonnet 5.5, and Fable 5.1 with an API key or a Claude subscription, the cache stays intact by default. See [Changing effort level](#changing-effort-level) below.
Pick your model and effort level at the top of a session, then save `/compact` for natural breaks between tasks. The fewer changes you make mid-task, the higher your cache hit rate.
[](#where-the-cache-lives)
Where the cache lives
Caching happens server-side, in whichever infrastructure serves your model. Where that is depends on how you authenticate:
- **API key, Claude subscription, or [Claude Platform on AWS](claude-platform-on-aws.md)**: the cache lives in Anthropic’s infrastructure, accessed through the [Claude API](../04-API-Reference/Other/home.md)
- **Amazon Bedrock or Google Cloud’s Agent Platform**: the cache lives in your cloud provider’s serving infrastructure
- **Microsoft Foundry**: depends on the deployment’s [hosting option](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options). Hosted on Azure deployments are served on Azure infrastructure; Hosted on Anthropic deployments are served on Anthropic’s infrastructure
- **Custom `ANTHROPIC_BASE_URL` or [LLM gateway](../13-Enterprise-Admin/llm-gateway.md)**: the cache lives wherever your requests are forwarded, and whether caching works depends on the gateway
Claude Code also appends system context mid-conversation, such as file-change notices, and marks that block for caching on every provider and connection unless you set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`](../13-Enterprise-Admin/llm-gateway-protocol.md#disable-pre-release-capabilities), in which case that block is sent uncached. At the provider’s own endpoint, Amazon Bedrock and its [Mantle endpoint](amazon-bedrock.md#use-the-mantle-endpoint), Google Cloud’s Agent Platform, and Microsoft Foundry cache the block the same way the Claude API does. When your requests pass through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), a custom `ANTHROPIC_BASE_URL`, or a cloud provider base-URL override such as [`ANTHROPIC_BEDROCK_BASE_URL`](env-vars.md), what stays cached depends on how the gateway handles the [`cache_control` markers](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#explicit-cache-breakpoints) Claude Code sends:
- **Forwards them unchanged**: the block and your conversation cache the same as at the provider’s own endpoint.
- **Rejects the marked request with a `400` error naming `cache_control`**: Claude Code re-sends the request with the marker moved off the block and onto your last conversation message, and keeps it there for the rest of the conversation. The block bills as uncached input; your conversation stays cached.
- **Removes the markers while returning success**: your entire conversation history bills as uncached input on every turn. A gateway that converts block-form system content to a plain string drops the marker the same way.
For what each provider stores and processes, see [data usage](../13-Enterprise-Admin/data-usage.md). Wherever the cache lives, entries expire after a period of inactivity, and [Cache lifetime](#cache-lifetime) below covers the TTL and how to extend it.
[](#actions-that-invalidate-the-cache)
Actions that invalidate the cache
These actions can cause the next request to miss part or all of the cache. You see a one-time slower, more expensive turn, after which the new prefix is cached. Most of them are avoidable mid-task once you know they have a cost. A model switch can feel free until you notice the slower turn that follows.
- [Switching models](#switching-models)
- [Changing effort level](#changing-effort-level)
- [Turning on fast mode](#turning-on-fast-mode)
- [Connecting or removing an MCP server](#connecting-or-removing-an-mcp-server)
- [Enabling or disabling a plugin](#enabling-or-disabling-a-plugin)
- [Denying an entire tool](#denying-an-entire-tool)
- [Compacting the conversation](#compacting-the-conversation)
- [Accumulating many images](#accumulating-many-images)
- [Upgrading Claude Code](#upgrading-claude-code)
[](#switching-models)
Switching models
Each model has its own cache. Switching with [`/model`](model-config.md#setting-your-model) means the next request reads the entire conversation history with no cache hits, even though the content is identical. When you run `/model` at the terminal, Claude Code asks you to confirm the switch only while the cache is still warm and the new model isn’t the one that produced the last response. The cache stays warm for one [cache TTL](#cache-lifetime) after Claude Code last sent a request in this conversation or Claude last responded. Once that time passes, the cache has expired, so Claude Code switches without asking. Before v2.1.238, Claude Code didn’t check the cache TTL and asked even after the cache had expired. You can also require this confirmation or skip it with a [PreModelSwitch hook](../07-Hooks/hooks.md#premodelswitch-decision-control). The [`opusplan` model setting](model-config.md#opusplan-model-setting) resolves to Opus during plan mode and Sonnet during execution, so each plan-mode toggle is a model switch and starts a fresh cache. [Automatic model fallback](model-config.md#automatic-model-fallback) on Fable models, Opus 5.5, Sonnet 5.5, and Opus 5 is also a model switch. When a safety classifier flags a request in a category that has a fallback model, Claude Code re-runs the request on that model and the session continues there. When a skill or command’s frontmatter names a [`model`](../08-Plugins-Skills/skills.md#frontmatter-reference) other than the session’s current model, that turn is also a model switch: the next request reads the entire conversation history with no cache hits. The session model resumes on your next prompt. A `context: fork` skill sets the [forked subagent’s model](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent) instead.
[](#changing-effort-level)
Changing effort level
On most models, changing the [effort level](model-config.md#adjust-effort-level) mid-session means the next request reads the entire conversation history with no cache hits. While the cache is still warm, Claude Code asks you to confirm the change first. On Opus 5.5, Sonnet 5.5, and Fable 5.1 with an API key or a Claude subscription, changing effort keeps the cache, and Claude Code applies the new level without asking. This doesn’t apply on Amazon Bedrock, Google Cloud’s Agent Platform, or a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md), or when you set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`](../13-Enterprise-Admin/llm-gateway-protocol.md#disable-pre-release-capabilities) or your organization has a HIPAA configuration. Before v2.1.260, changing effort on Fable 5.1 with an API key or a Claude subscription also invalidated the cache.
[](#turning-on-fast-mode)
Turning on fast mode
Enabling [fast mode](fast-mode.md) adds a request header that is part of the cache key, so the first request Claude Code sends with fast mode on reads the entire conversation history with no cache hits. Claude Code sets that header once when a turn starts and keeps it for the whole turn, so when you turn fast mode on while Claude is working, the cache miss from the header happens on the first request of your next turn. Those uncached input tokens are billed at [fast mode rates](fast-mode.md#understand-the-cost-tradeoff), which is why turning it on at the start of a session costs less than turning it on deep into a long one. If your current model doesn’t support fast mode, enabling fast mode also [switches your model](#switching-models), and that switch starts a fresh cache on its own from the next request in the running turn. The cost applies once per conversation. After the first fast mode turn, Claude Code keeps sending the header and varies only the request’s speed setting, which is not part of the cache key. Turning fast mode off, the [automatic fallback to standard speed](fast-mode.md#handle-rate-limits) after a rate limit, and turning it back on later all keep the cache. If you [run out of usage credits](fast-mode.md#handle-rate-limits) mid-session, Claude Code retries each rejected fast mode request at standard speed the same way, so this fallback also keeps the cache. `/clear` and `/compact` reset this, since they rebuild the cache at those points anyway.
[](#connecting-or-removing-an-mcp-server)
Connecting or removing an MCP server
Tool definitions sit in the system prompt layer, so the cache invalidates when the set of tool definitions in the request changes between turns. Toggling the [advisor tool](advisor.md) is an exception: its definition sits after the cache breakpoint, so enabling or disabling `/advisor` keeps the cached prefix intact. Whether an [MCP server](../06-MCP-Tools/General/mcp.md) change does this depends on whether [tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) defers the session’s MCP tools, the default on supported models:
- **Tools deferred**: Claude Code keeps the tool list from the conversation’s first request for the whole conversation, so a server connecting or disconnecting mid-session doesn’t disturb anything already cached. A server that finishes connecting after the first request supplies its tools as deferred definitions that Claude loads on demand.
- **Tools loaded upfront**: adding a definition invalidates the cache, and so does removing one on purpose. This applies when tool search is [below its `auto` threshold, disabled, or unavailable](../06-MCP-Tools/General/mcp.md#configure-tool-search), such as on Google Cloud’s Agent Platform models earlier than the Claude 4.5 generation, with a custom `ANTHROPIC_BASE_URL` gateway, or on a Microsoft Foundry [deployment hosted on Azure](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options) once Claude Code detects that the deployment rejects tool search.
Without tool search, whether a mid-session server change invalidates the cache depends on what changed. For each change, this table gives whether the cache is kept and what happens to the tool definitions in the next request.
| Mid-session change | Cache | Tool definitions in the next request |
|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| A server connects, or a [dynamic tool update](../06-MCP-Tools/General/mcp.md#dynamic-tool-updates) adds tools | Invalidated | The new definitions are added |
| A server drops out with no action on your part, such as a stdio server’s process exiting | Kept | The server’s definitions stay unchanged. A call to one of its tools returns an error instead of running |
| A remote server [reconnects automatically](../06-MCP-Tools/General/mcp.md#automatic-reconnection) after its connection drops | Kept, unless a request sent while the server reconnects adds the `WaitForMcpServers` tool, which invalidates the cache once | The server’s definitions stay unchanged. A request sent while the server reconnects can add `WaitForMcpServers` when the conversation hasn’t listed it yet, and the tool then stays listed for the rest of the conversation |
| You remove a tool on purpose, such as with a [deny rule](#denying-an-entire-tool) or by disabling its server in `/mcp` | Invalidated | The definition is removed |
When you resume a conversation whose tools load into the prefix, one of its MCP servers can still be connecting as the first request goes out. If the transcript recorded that server’s tool definitions, that request includes them as recorded, so it doesn’t change when the server finishes connecting with the same tools. Editing your MCP config does not by itself change the cache. The new config takes effect only after a restart, which is when the server connects or disconnects.
[](#enabling-or-disabling-a-plugin)
Enabling or disabling a plugin
When you enable or disable a [plugin](../08-Plugins-Skills/plugins.md), what the change costs depends on which component types the plugin provides. The cases below cover each component type, when Claude Code applies the change, and what happens when you disable a plugin again in the same session.
[](#plugin-components-that-keep-the-cache)
Plugin components that keep the cache
Claude Code never invalidates the cache for a plugin’s skills, commands, agents, hooks, monitors, or themes. It appends their content after the existing conversation, so the next request pays for that content and still reads everything before it from the cache.
[](#plugins-that-provide-mcp-servers)
Plugins that provide MCP servers
When you enable or disable a plugin that provides [MCP servers](../08-Plugins-Skills/plugins-components.md#mcp-servers), Claude Code follows the same rules as when you [connect or remove an MCP server](#connecting-or-removing-an-mcp-server).
[](#code-intelligence-plugins)
Code intelligence plugins
When you enable a [code intelligence plugin](../08-Plugins-Skills/plugins-code-intelligence.md), Claude gets the [LSP tool](tools-reference.md#lsp-tool-behavior).
[](#when-plugin-changes-apply)
When plugin changes apply
A change you make in the `/plugin` menu goes through [`/reload-plugins`](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins), which Claude Code runs for you when you close the menu. You pay the cost, whether appended announcements or a full re-read, on the first turn after the change applies. Claude Code can also apply a change on its own:
- For a plugin with a `command` source, Claude Code [can reload the plugin itself](../08-Plugins-Skills/plugins-loading.md#when-a-command-source-re-runs).
- When you [install a plugin from the `/plugin` interface](../08-Plugins-Skills/discover-plugins.md#install-a-plugin), Claude Code can activate it during the install. The install summary tells you whether it did.
- When you [move the session with `/cd`](permissions.md#move-the-session-to-another-directory) on v2.1.246 or later, Claude Code applies the plugins the new directory’s settings enable as part of the move, without the full re-read warning that holds a `/reload-plugins`.
- In interactive sessions, when you add or remove a plugin in a [folder of plugins](../08-Plugins-Skills/plugins-create.md#load-a-directory-or-archive-for-one-session) you passed with `--plugin-dir`, the change applies right away. If applying it would trigger a full re-read, Claude Code holds the change instead and shows a notice to run `/reload-plugins`. Requires Claude Code v2.1.265 or later.
When `/reload-plugins` runs and the reload would trigger a full re-read, Claude Code shows a warning and doesn’t apply the reload. Run `/reload-plugins --force` to apply it anyway. `/reload-plugins` also runs in sessions without an interactive terminal, such as the desktop app, the Agent SDK, and [non-interactive mode](headless.md) with `-p`, when you type it into the session directly. Requires Claude Code v2.1.260 or later. In those sessions the reload applies everything except plugin MCP server changes, which [take effect in your next session](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) and so never cost a full re-read mid-session.
[](#plugins-you-enable-and-then-disable-in-one-session)
Plugins you enable and then disable in one session
When you disable a plugin you enabled earlier in the session, Claude Code restores the previous request shape. If that prefix is still within its [cache lifetime](#cache-lifetime), the next request reads the older cache entry instead of rebuilding.
[](#denying-an-entire-tool)
Denying an entire tool
If you add a bare tool name like `Bash` or `WebFetch` as a [deny rule](permissions.md#manage-permissions), Claude can’t call that tool from your next request on, whether you add the rule through `/permissions` or by [editing a settings file directly](settings.md#when-edits-take-effect). That includes a rule you add through `/permissions` in the middle of a turn. When [tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is active, which is the default on supported models, the request’s tool definitions don’t change and the cached prefix survives. When tool search is unavailable or disabled, Claude Code removes the definition from the next request, which invalidates the cache, and so does removing the rule later. Only a deny rule that matches in the tool-name position blocks a tool this way: a bare tool name, the equivalent `Bash(*)` form, or a [tool-name glob](permissions.md#tool-name-wildcards) like `"*"`. A glob that matches only MCP tools, such as `"mcp__*"`, blocks those tools the same way. Scoped deny rules like `Bash(rm *)`, and all allow and ask rules, don’t change which tools Claude sees. Claude Code checks them when Claude attempts a call, leaving the prefix intact.
[](#compacting-the-conversation)
Compacting the conversation
[Compaction](context-window.md#what-survives-compaction) replaces your message history with a summary. By design, this invalidates the conversation layer, since the next request has a new, shorter history that doesn’t share a prefix with the old one. Claude Code reuses the system prompt layer unless the conversation was [resumed while keeping a system prompt that would otherwise have changed](#resuming-a-session); in that case the first compaction switches to the current prompt and that layer rebuilds once. It reloads project context from disk, which cache-hits only if CLAUDE.md and memory are unchanged since the session started. To produce the summary, Claude Code sends a separate request with the same system prompt, tools, and history as your conversation, plus a summarization instruction appended as a final user message. While the cache is warm, that request reads your prefix from the cache, so a mid-session `/compact` costs a fraction of what the context size suggests and spends most of its time generating the summary. After a break longer than the [cache lifetime](#cache-lifetime), there is no cache left to read, so the summarization request reprocesses the full history as uncached input. This is why `/compact` costs the most when you [resume an old session](sessions.md#resume-from-a-summary). In both the warm and cold cases, the turn after compaction rebuilds the conversation cache for only the much shorter summary, so that turn is not the slow part.
Compaction works in your favor when the context you discard is content you no longer need. To choose when its overhead happens, run `/compact` at a natural break in your work, such as between tasks, instead of waiting for auto-compaction to trigger mid-task. If you’ve gone down a path you want to abandon entirely, [`/rewind`](#rewinding-the-conversation) to an earlier turn instead. Rewinding truncates back to a prefix that is already cached, rather than building a new one as compaction does.
[](#accumulating-many-images)
Accumulating many images
The API limits how many images and PDFs each request can carry. For the current numbers, see [Request limits](../04-API-Reference/Guides/build-with-claude-vision.md#request-limits) in the API docs. Claude Code also caps the total size of the images and PDFs in a request, so large screenshots reach the limit with fewer images than small ones. When the next request would pass either limit, Claude Code removes a batch of the oldest images and PDFs from what it sends, which leaves room for more before it needs to remove any again. Claude can no longer see the removed images. If Claude needs one of them again, share it again. Removing images changes the messages that held them, so the next request reprocesses the conversation from the earliest of those messages onward. Because Claude Code removes a batch at a time, you see one slower turn per batch rather than one with each new screenshot.
[](#upgrading-claude-code)
Upgrading Claude Code
A new Claude Code version typically updates the system prompt or tool definitions, so the first conversation you start after an upgrade builds its cache from the top. [Auto-update](../01-Getting-Started/setup.md#auto-updates) downloads new versions in the background but applies them on the next launch, never mid-session, so you see this as an uncached first turn after restarting rather than a surprise during a session. Set `DISABLE_AUTOUPDATER=1` to control when upgrades apply.
For what it costs to resume a conversation you started before the upgrade, see [Resuming a session](#resuming-a-session).
[](#actions-that-keep-the-cache)
Actions that keep the cache
These actions either append to the end of the conversation or don’t touch the request at all. Some of them, such as editing CLAUDE.md, keep the cache for the same reason the change doesn’t reach the running session until `/clear`, `/compact`, or a restart.
- [Editing files in your repository](#editing-files-in-your-repository)
- [Editing CLAUDE.md mid-session](#editing-claude-md-mid-session)
- [Changing permission mode](#changing-permission-mode)
- [Changing output style](#changing-output-style)
- [Invoking skills and commands](#invoking-skills-and-commands)
- [Running `/recap`](#running-%2Frecap)
- [Rewinding the conversation](#rewinding-the-conversation)
- [Spawning a subagent](#subagents-and-the-cache)
[](#editing-files-in-your-repository)
Editing files in your repository
File contents enter context only when Claude reads them, and reads append to the conversation. Editing a file Claude previously read does not retroactively change the earlier read in history. Instead, Claude Code appends a [`<system-reminder>`](glossary.md#system-reminder) noting the file changed, and Claude re-reads it if needed.
[](#editing-claude-md-mid-session)
Editing CLAUDE.md mid-session
Your project-root and user-level CLAUDE.md files are read once at session start and held in memory. Editing them mid-session does not invalidate the cache, but the edit also doesn’t apply. Claude keeps working with the version that was loaded at session start. The new content loads on the next `/clear`, `/compact`, or restart. [Nested CLAUDE.md files in subdirectories](memory.md) and [rules with `paths:` frontmatter](memory.md#path-specific-rules) load later, when Claude first reads a matching file. Editing one before it loads does take effect. After it loads, the content is part of the conversation history, so a mid-session edit doesn’t retroactively change it.
[](#changing-permission-mode)
Changing permission mode
Switching between [permission modes](permission-modes.md), such as from Manual to accept edits, does not change the system prompt or tool definitions, so mode changes are cache-safe. The exception is plan mode with the [`opusplan`](model-config.md#opusplan-model-setting) model setting, which switches the model between Opus and Sonnet as you enter or leave plan mode. That makes the mode toggle a [model switch](#switching-models).
[](#changing-output-style)
Changing output style
When you switch [output styles](output-styles.md) mid-session with [`/output-style`](output-styles.md#change-your-output-style), `/config`, or the `outputStyle` setting, Claude uses the new style starting with your next message. Claude Code delivers the new style’s instructions as a message in the conversation, so that request still reads the system prompt and the earlier conversation from the cache. Before v2.1.251, a mid-session style switch kept the cache but didn’t apply until you ran `/clear` or started a new session.
[](#invoking-skills-and-commands)
Invoking skills and commands
[Skills](../08-Plugins-Skills/skills.md) and [commands](commands.md) inject their instructions as user messages at the point of invocation. Nothing earlier in the conversation changes. A skill or command whose frontmatter names a `model` can be a [model switch](#switching-models) for that turn.
[](#running-/recap)
Running `/recap`
[`/recap`](interactive-mode.md#session-recap) generates a summary for display in your terminal. Unlike `/compact`, it appends the summary as command output rather than replacing your message history, so the cached prefix stays intact.
[](#rewinding-the-conversation)
Rewinding the conversation
[`/rewind`](checkpointing.md) truncates your conversation back to an earlier turn. The remaining history is the same content the cache was built from at that point, and the system prompt and project context layers are unchanged, so the next request hits the earlier cache entry. Every turn since then has read through that prefix, which kept the entry warm even if the original turn was longer ago than the TTL. Restoring file checkpoints alongside the conversation has no separate effect on the cache. File contents enter context only when Claude reads them, the same as [editing files in your repository](#editing-files-in-your-repository).
[](#resuming-a-session)
Resuming a session
When you [resume a session](sessions.md#resume-a-session), Claude Code sends the whole conversation again, and the request reads from the cache whatever part of its prefix is unchanged and still within the [cache lifetime](#cache-lifetime). The layer table at the top of this page says what changes each layer. The system prompt would change after a [Claude Code upgrade](#upgrading-claude-code) or with different [`--append-system-prompt`](cli-reference.md#system-prompt-flags) text on the resume. By default, the resumed conversation keeps the system prompt it started with, so its history still sits behind the same prompt, and the change takes effect once the conversation is compacted or in a new conversation. [System prompt flags in resumed conversations](cli-reference.md#system-prompt-flags-in-resumed-conversations) covers the cases where Claude Code rebuilds the prompt on every request instead.
[](#cache-lifetime)
Cache lifetime
Cached prefixes expire after a period of inactivity. Each request that hits the cache resets the timer, so the cache stays warm as long as you keep working. After a long enough gap, the next request recomputes the full input and re-establishes the cache, which is why the first turn back after stepping away can be noticeably slower. On a Pro or Max plan, when you resume a large session after a long break, Claude Code [offers to resume from a summary](sessions.md#resume-from-a-summary) so later requests don’t carry the full history. The time to live (TTL) controls how long a gap the cache survives. The API offers two: a five-minute TTL, and a [one-hour TTL](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#1-hour-cache-duration) that keeps the cache warm through longer breaks but [bills cache writes at a higher rate](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#pricing). The longer TTL helps when you leave a session idle and come back to it, because you skip the reprocessing an expired prefix costs. It costs more on short bursts of work that never idle past five minutes, where the higher write rate applies and the longer cache lifetime goes unused.
[](#which-ttl-each-request-gets)
Which TTL each request gets
Claude Code decides the TTL per request, and every request falls in one of two fixed buckets:
- **Main conversation**: your interactive turns, non-interactive `-p` runs, and Agent SDK turns, plus the helpers Claude Code runs inline with them
- **Everything else**: the requests Claude Code makes outside that conversation, such as [subagents](../09-Agents-Patterns/sub-agents.md), [workflows](workflows.md), in-process [teammates](../09-Agents-Patterns/agent-teams.md), forks, compaction, and session titles
Unless you choose a TTL yourself, Claude Code requests the one-hour TTL only on a Claude subscription within your plan’s included usage. There it requests the hour for the main conversation, plus a small set of helper requests that Anthropic controls server-side. This table gives each bucket’s default TTL under both kinds of billing.
| Request bucket | Claude subscription, within plan usage | Usage credits, API key, or cloud provider |
|-------------------|--------------------------------------------------------------------------------|-------------------------------------------|
| Main conversation | One hour | Five minutes |
| Everything else | Five minutes, except the server-controlled helper requests, which get one hour | Five minutes |
Once you go over your plan’s usage limit and Claude Code draws on [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans), you are billed for that usage, so Claude Code drops the main conversation to the cheaper five-minute TTL. To keep the one-hour TTL there, [choose the TTL yourself](#choose-the-ttl-yourself).
[](#choose-the-ttl-yourself)
Choose the TTL yourself
You can set a TTL for either bucket. Each control takes `5m` or `1h`, and Claude Code ignores any other value.
- **Main conversation**: the [`promptCacheTtl`](settings-reference.md#promptcachettl) setting, or the `CLAUDE_CODE_PROMPT_CACHE_TTL` [environment variable](env-vars.md)
- **Everything else**: the [`subagentPromptCacheTtl`](settings-reference.md#subagentpromptcachettl) setting, or the `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL` environment variable
Both settings and both environment variables require Claude Code v2.1.242 or later. If you sign in with an API key or use a cloud provider, set `promptCacheTtl` to `1h` to give the main conversation a one-hour cache. Requests outside it keep the five-minute default until you choose a TTL for that bucket too. When more than one control applies, Claude Code takes the first match in this order:
1. `FORCE_PROMPT_CACHING_5M=1`, which forces five minutes for both buckets
2. The bucket’s environment variable
3. The bucket’s setting
4. For a subagent’s requests, the `cacheTtl` value in the subagent’s [`experimental` frontmatter field](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields), which requires Claude Code v2.1.248 or later. Claude Code ignores a `1h` there while your Claude subscription is using usage credits
5. `ENABLE_PROMPT_CACHING_1H=1`, which requests one hour for both buckets
6. The [default for the request’s bucket](#which-ttl-each-request-gets)
Set `FORCE_PROMPT_CACHING_5M=1` when you’re debugging cache behavior, comparing the two TTLs, or overriding a longer TTL set in [managed settings](../13-Enterprise-Admin/managed-settings.md). To confirm which TTL your main conversation’s cache writes used, run `claude -p "hello" --output-format json` and read `usage.cache_creation` in the result. Claude Code reports one-hour cache writes under `ephemeral_1h_input_tokens` and five-minute cache writes under `ephemeral_5m_input_tokens`. Through an LLM gateway you set with `ANTHROPIC_BASE_URL`, part of the one-hour request travels in the `anthropic-beta` header, so configure the gateway to [forward that header unchanged](../13-Enterprise-Admin/llm-gateway-protocol.md#request-headers). The one-hour TTL isn’t available through the [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md#availability-and-limitations). On Amazon Bedrock, prompt caching support, minimum cacheable prefix length, and one-hour TTL availability all vary by model. If cache token counts stay at zero, check [supported models, regions, and limits](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html#prompt-caching-models) in the Amazon Bedrock documentation.
[](#cache-scope)
Cache scope
In Claude Code, the cache is effectively scoped to one machine and directory. The system prompt embeds your auto memory paths, and the conversation opens with an announcement of the working directory, platform, shell, and OS version. Two sessions in different directories therefore build different prefixes and miss each other’s cache. Sessions you run in parallel in the same directory build matching prefixes and read each other’s cache. Sequential sessions share the prefix only when the git status snapshot taken at startup matches, since each conversation also carries the branch and recent commits from that snapshot. The underlying API cache is broader. Caches are isolated between organizations, and on some providers, [between workspaces within an organization](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#cache-storage-and-sharing). Within those boundaries, any two requests with the same model and prefix read the same cache. For Agent SDK callers running fleets of automated processes, see [improve prompt caching across users and machines](../05-Agent-SDK/agent-sdk-modifying-system-prompts.md#improve-prompt-caching-across-users-and-machines) to move the auto memory location out of the system prompt and share the system prompt’s cache entry across users and machines.
[](#check-cache-performance)
Check cache performance
Cache performance shows up as two token counts the API reports on every response. The most direct way to watch them live is a [statusline script](statusline.md) that reads the `current_usage` object:
| Field | Meaning |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `cache_creation_input_tokens` | Tokens written to the cache on this turn, billed at the cache write rate |
| `cache_read_input_tokens` | Tokens served from cache on this turn, billed at the model’s [cached token rate](../17-Billing-Plans/about-claude-pricing.md), below the standard input rate |
A high read-to-creation ratio means caching is working well. If creation stays high turn after turn, something is changing in your prefix. The [actions that invalidate the cache](#actions-that-invalidate-the-cache) section lists the usual causes. For a per-session summary, run `/usage`. After the main conversation’s first response, Claude Code adds a [`Prompt cache (main)` line](../17-Billing-Plans/costs.md#prompt-cache-statistics) to the Session block, showing the session’s hit ratio, miss count, and whether the cache is warm right now. A status line script can read the same numbers from the [`prompt_cache` object](statusline.md#prompt-cache-fields). Both require Claude Code v2.1.251 or later. The `Prompt cache (main)` line also names the likely cause of the last miss when Claude Code can identify one, for example `likely cause: tool definitions changed`. The likely-cause text requires Claude Code v2.1.260 or later. For visibility across an organization, the OpenTelemetry exporter reports cache read and creation tokens per user and session. See [Monitor usage](../13-Enterprise-Admin/monitoring-usage.md) for the metric and event attribute reference.
[](#subagents-and-the-cache)
Subagents and the cache
A [subagent](../09-Agents-Patterns/sub-agents.md) starts its own conversation with its own system prompt and tool set, separate from the parent’s. Its first request doesn’t read the parent’s cache, because the two prefixes differ, and it warms a cache of its own across its turns. Subagents fall outside the main-conversation [TTL bucket](#which-ttl-each-request-gets), so they get five minutes even on a subscription until you [choose a longer one](#choose-the-ttl-yourself). The parent’s cache is unaffected. From the parent’s side, the subagent’s call and result append to the conversation, leaving the parent’s prefix intact. A [fork](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), by contrast, inherits the parent’s system prompt, tools, and conversation history exactly, so its first request reads the parent’s cache. Other requests can also read a prefix that an earlier request cached:
- **Session copies**: a session you [copy with `/fork`](../09-Agents-Patterns/agent-view.md#copy-the-session-with-%2Ffork) receives its isolation instruction as a message at the end of the copied conversation, so the cache that the original conversation built stays intact.
- **Compaction**: the summarization call described in [Compacting the conversation](#compacting-the-conversation) uses the same prefix-sharing approach.
- **Resumed subagents**: when Claude [resumes a subagent](../09-Agents-Patterns/sub-agents.md#resume-subagents), the resumed run’s first request can read the cache the original run warmed.
- **Workflow fan-outs**: in a [workflow fan-out](workflows.md#prompt-caching-in-a-fan-out) of same-prefix agents, Claude Code holds all but the first for up to 5 seconds by default, so their first requests can read the prefix that the first agent cached.
[](#disable-prompt-caching)
Disable prompt caching
Disabling caching is occasionally useful when debugging caching behavior with a specific model or provider. To turn it off, set one of these environment variables to `1`:
| Variable | Effect |
|---------------------------------|--------------------------------------|
| `DISABLE_PROMPT_CACHING` | Disable for all models |
| `DISABLE_PROMPT_CACHING_HAIKU` | Disable for the default Haiku model |
| `DISABLE_PROMPT_CACHING_SONNET` | Disable for the default Sonnet model |
| `DISABLE_PROMPT_CACHING_OPUS` | Disable for the default Opus model |
| `DISABLE_PROMPT_CACHING_FABLE` | Disable for Fable only |
`DISABLE_PROMPT_CACHING_HAIKU` applies to the default Haiku model, the model the `haiku` alias resolves to. It disables caching wherever that model runs, including the main conversation when it is your main model. Covering the main conversation requires Claude Code v2.1.283 or later. The variable also covers a background model you set with the deprecated `ANTHROPIC_SMALL_FAST_MODEL` variable, when that model differs from your main model. A different Haiku version that you pin as your main model keeps caching; set `DISABLE_PROMPT_CACHING` to disable caching for it. `DISABLE_PROMPT_CACHING_SONNET` and `DISABLE_PROMPT_CACHING_OPUS` each apply to the model the `sonnet` or `opus` alias resolves to. If you set any other Sonnet or Opus model ID as your main model, that model keeps caching. For example, a session on `claude-sonnet-5` keeps caching while `sonnet` resolves to `claude-sonnet-5-5`. To disable caching for that model, set `DISABLE_PROMPT_CACHING`. To set caching policy across an organization, put any of these or the [TTL variables](#cache-lifetime) in the `env` block of [managed settings](../13-Enterprise-Admin/managed-settings.md). For normal use, leave caching enabled.
[](#related-resources)
Related resources
- [Lessons from building Claude Code: Prompt caching is everything](https://claude.com/blog/lessons-from-building-claude-code-prompt-caching-is-everything): the design rationale for plan mode, deferred tool loading, and compaction
- [Explore the context window](context-window.md): what loads into context and when
- [Reduce token usage](../17-Billing-Plans/costs.md#reduce-token-usage): strategies beyond caching for managing context size
- [Track and reduce costs](../05-Agent-SDK/agent-sdk-cost-tracking.md): cache token tracking and TTL configuration for Agent SDK callers
- [Prompt caching](../04-API-Reference/Guides/build-with-claude-prompt-caching.md): the underlying API mechanism, breakpoints, and pricing
---
## Prompt library - Claude Code Docs
Source: https://code.claude.com/docs/en/prompt-library
Path: 02-Claude-Code-CLI/prompt-library.md
## On this page
- [What makes these prompts work](#what-makes-these-prompts-work)
- [Where these come from](#where-these-come-from)
- [Related resources](#related-resources)
Use Claude Code
# Prompt library
Copy pageCopy page
Copy-paste prompts for Claude Code, tagged by task and role.
Copy pageCopy page
This is a library of prompts to copy into Claude Code. Use it to explore ways of working you haven’t tried, or when you’re not sure where to start. The prompts are collected from various Anthropic guides, including [Common workflows](common-workflows.md), [Best practices](best-practices.md), and [How Anthropic teams use Claude Code](https://claude.com/blog/how-anthropic-teams-use-claude-code). They’re starting points rather than scripts. Open **Why this works** under any prompt to see the pattern behind it so you can write your own.
[](#what-makes-these-prompts-work)
What makes these prompts work
The prompts above share a few patterns. Recognizing them helps you adapt any prompt here to your own task. **Describe the outcome, not the steps.** Say what you want and let Claude find the files. The prompt below works without naming a single file path.
```python
add rate limiting to the public API and make sure existing tests still pass
```
**Give it a way to check its own work.** Ask for run, test, compare, or verify in the same prompt so Claude iterates instead of stopping after one attempt. To check the finished change against the running app, run [`/verify`](../08-Plugins-Skills/skills.md#run-and-verify-your-app).
```python
write the migration, run it against the dev database, and confirm the schema matches
```
**Point at a reference.** Name an existing file, test, or pattern to match so the new code is consistent with what you already have.
```python
add a settings page that follows the same layout as the profile page
```
**State the measurable target.** When the goal is performance or coverage, give the metric and threshold so completion is unambiguous.
```python
get the bundle size under 200KB and show me what you removed
```
**Give it the artifact.** Paste errors, logs, screenshots, and plan output directly in the prompt, or type `@` to reference a file. Claude reads the source instead of your description of it.
```python
why is the build failing? @build.log
```
**Say how you want the answer.** Name the format, length, or audience so the explanation fits how you’ll use it. To make a format the default for every response, set an [output style](output-styles.md).
```python
explain how the payment retry logic works as an HTML page with a diagram, then open it in my browser
```
For more on each pattern, see [best practices](best-practices.md).
[](#where-these-come-from)
Where these come from
These prompts are based on patterns from published Anthropic resources. Each card links to its source:
- [Common workflows](common-workflows.md): step-by-step guides for the core tasks
- [Best practices](best-practices.md): prompting patterns and project setup
- [How Anthropic teams use Claude Code](https://claude.com/blog/how-anthropic-teams-use-claude-code): real workflows from engineering, product, design, and data teams, with deep dives on [legal](https://claude.com/blog/how-anthropic-uses-claude-legal), [marketing](https://claude.com/blog/how-anthropic-uses-claude-marketing), and [cybersecurity](https://claude.com/blog/how-anthropic-uses-claude-cybersecurity)
- [Scaling agentic coding guide](https://resources.anthropic.com/hubfs/Scaling%20agentic%20coding%20across%20your%20organization.pdf): the enterprise adoption guide
For video walkthroughs of these patterns, see the free [Claude Code in Action](https://academy.claude.com/courses/claude-code-in-action) course on [Claude Academy](https://academy.claude.com/).
[](#related-resources)
Related resources
The prompts on this page are starting points. Once one works for your project, the next step is making it repeatable: save it as a [skill](../08-Plugins-Skills/skills.md) so anyone on your team can run it as a `/command`, and record the conventions Claude learned in [CLAUDE.md](memory.md) so every session starts with that context instead of Claude relearning it. For larger or riskier changes, [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) shows you the file list before any edits happen. If you’re introducing Claude Code across a team, see [administration](../13-Enterprise-Admin/admin-setup.md) for managed settings and policy, and [costs and usage](../17-Billing-Plans/costs.md) for how this work is billed on your plan.
---
## Continue local sessions from any device with Remote Control - Claude Code Docs
Source: https://code.claude.com/docs/en/remote-control
Path: 02-Claude-Code-CLI/remote-control.md
## On this page
- [Requirements](#requirements)
- [Start a Remote Control session](#start-a-remote-control-session)
- [Check connection status](#check-connection-status)
- [Connect from another device](#connect-from-another-device)
- [What connected devices see](#what-connected-devices-see)
- [Enable Remote Control for all sessions](#enable-remote-control-for-all-sessions)
- [Resume sessions after stopping the server](#resume-sessions-after-stopping-the-server)
- [Connection and security](#connection-and-security)
- [Trusted Devices](#trusted-devices)
- [Enable Trusted Devices for a Team or Enterprise organization](#enable-trusted-devices-for-your-organization)
- [What members see](#what-members-see)
- [Manage enrolled devices](#manage-enrolled-devices)
- [Remote Control vs cloud sessions](#remote-control-vs-cloud-sessions)
- [Mobile push notifications](#mobile-push-notifications)
- [Limitations](#limitations)
- [Troubleshooting](#troubleshooting)
- [”Remote Control requires a claude.ai subscription”](#%E2%80%9Dremote-control-requires-a-claude-ai-subscription%E2%80%9D)
- [”Remote Control requires a full-scope login token”](#%E2%80%9Dremote-control-requires-a-full-scope-login-token%E2%80%9D)
- [”Unable to determine your organization for Remote Control eligibility”](#%E2%80%9Dunable-to-determine-your-organization-for-remote-control-eligibility%E2%80%9D)
- [”Remote Control isn’t enabled for this account”](#%E2%80%9Dremote-control-isn%E2%80%99t-enabled-for-this-account%E2%80%9D)
- [”Couldn’t verify Remote Control eligibility”](#%E2%80%9Dcouldn%E2%80%99t-verify-remote-control-eligibility%E2%80%9D)
- [”Remote Control requires feature-flag evaluation”](#%E2%80%9Dremote-control-requires-feature-flag-evaluation%E2%80%9D)
- [”Remote Control is only available when using Claude via api.anthropic.com”](#%E2%80%9Dremote-control-is-only-available-when-using-claude-via-api-anthropic-com%E2%80%9D)
- [”Remote Control is disabled by your organization’s policy”](#%E2%80%9Dremote-control-is-disabled-by-your-organization%E2%80%99s-policy%E2%80%9D)
- [“Couldn’t verify your organization’s policy for remote control”](#couldnt-verify-your-organizations-policy-for-remote-control)
- [”Remote credentials fetch failed”](#%E2%80%9Dremote-credentials-fetch-failed%E2%80%9D)
- [“Couldn’t reconnect to your Remote Control session”](#couldnt-reconnect-to-your-remote-control-session)
- [“Previous session is unavailable — run /remote-control to start a new one”](#previous-session-is-unavailable)
- [”Remote Control got an unexpected server response”](#%E2%80%9Dremote-control-got-an-unexpected-server-response%E2%80%9D)
- [”Your organization requires Trusted Devices for Remote Control, but this device is not enrolled”](#%E2%80%9Dyour-organization-requires-trusted-devices-for-remote-control-but-this-device-is-not-enrolled%E2%80%9D)
- [”session expired for trusted-device check”](#%E2%80%9Dsession-expired-for-trusted-device-check%E2%80%9D)
- [Related resources](#related-resources)
Platforms and integrations
# Continue local sessions from any device with Remote Control
Copy pageCopy page
Continue a local Claude Code session from your phone, tablet, or any browser using Remote Control. Works with claude.ai/code and the Claude mobile app.
Copy pageCopy page
Remote Control connects [claude.ai/code](https://claude.ai/code) or the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) and [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) 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 your code execution and filesystem access stay on your machine. With Remote Control you can:
- **Use your full local environment remotely**: your filesystem, [MCP servers](../06-MCP-Tools/General/mcp.md), tools, and project configuration all stay available, and typing `@` autocompletes file paths from your local project.
- **Work from both surfaces at once**: the conversation and the progress of [subagents](../09-Agents-Patterns/sub-agents.md) and [dynamic workflows](workflows.md) stay in sync across all connected devices, so you can send messages from your terminal, browser, and phone interchangeably.
- **Send images and files from your phone or browser**: attach a photo or file in the Claude app or at claude.ai/code, with or without a caption. Claude sees attached photos directly as part of your message. Claude Code downloads other files to your machine and passes them to Claude as `@` file references.
- **Survive interruptions**: if your laptop sleeps or your network drops, Claude Code reconnects automatically when your machine comes back online.
Unlike [cloud sessions](claude-code-on-the-web.md), which run on cloud infrastructure, Remote Control sessions run directly on your machine and interact with your local filesystem. The web and mobile interfaces are a window into that local session, so your computer has to stay on and the `claude` process has to keep running.
[](#requirements)
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 Owner must first enable the Remote Control toggle in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).
- **Authentication**: run `claude` and use `/login` to sign in through claude.ai if you haven’t already. Without an eligible login, `claude remote-control` exits with an error, while `claude --remote-control` still starts an interactive session and shows a Remote Control failure notification shortly after launch.
- **API endpoint**: not available in any of these configurations:
- You use Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry.
- You point [`ANTHROPIC_BASE_URL`](env-vars.md) at a host other than `api.anthropic.com`, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) or proxy. Unset the variable to use Remote Control.
- You sign in through an enterprise [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md).
- **Feature-flag evaluation**: if you set an [environment variable that turns off feature-flag evaluation](env-vars.md#features-that-need-feature-flag-fetching), whether Remote Control is available depends on which one:
- If you set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` or `DISABLE_GROWTHBOOK`, Remote Control is unavailable. Unset the variable wherever it’s set, in your shell environment or in the `env` block of a [`settings.json` file](settings-reference.md#all-settings), to use Remote Control.
- If you set only `DISABLE_TELEMETRY` or `DO_NOT_TRACK`, Remote Control stays available unless your organization requires [Trusted Devices](#trusted-devices). If it does, unset the variable to use Remote Control. Using Remote Control with either variable set requires Claude Code v2.1.283 or later.
- **Workspace trust**: in a directory you haven’t trusted yet, `claude remote-control` prints what trusting it turns on and asks `Trust <directory>? [y/N]` before it starts. Answering `y` saves the choice, except in your home directory, where trust is never saved and the question returns on every run. When its standard input or output isn’t a terminal, the command can’t ask and exits with a [`Workspace not trusted`](errors.md#workspace-not-trusted-when-starting-remote-control) error.
[](#start-a-remote-control-session)
Start a Remote Control session
You can start a Remote Control session from the CLI, the [Claude Desktop app](../16-Mobile-Desktop/desktop.md), or the VS Code extension. The CLI offers three invocation modes; the Desktop app and VS Code use the `/remote-control` command.
- Server mode
- Interactive session
- From an existing session
- VS Code
- Desktop app
In your project directory, run:
```python
claude remote-control
```
Until you accept Remote Control’s one-time confirmation, `claude remote-control` explains what it does and asks `Enable Remote Control? (y/n)` before starting the server. Answer `y` to accept and start the server. If you decline, Claude Code exits without starting the server and asks again the next time you run the command.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](#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:
[TABLE]
Give these flags after `remote-control`.If you pass a global `claude` flag before `remote-control`, or a wrapper script adds one, Claude Code doesn’t carry the flag over to the sessions the server creates. Claude Code lets the flag through only when dropping it is known not to change what those sessions can do, such as `--verbose` or `--model`. For any other flag, such as `--settings`, Claude Code [refuses to start](errors.md#not-carried-over-to-the-sessions-remote-control-starts) and names the flag to remove.Claude Code checks Remote Control eligibility before printing help, so `claude remote-control --help` returns an error instead of this flag list when you aren’t signed in with an eligible account.
To start a normal interactive Claude Code session with Remote Control enabled, use the `--remote-control` flag (or `--rc`):
```python
claude --remote-control
```
Optionally pass a name for the session:
```python
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:
```python
/remote-control
```
Pass a name as an argument to set a custom session title:
```python
/remote-control My Project
```
This starts a Remote Control session that carries over your current conversation history.Until you accept Remote Control’s one-time confirmation, a dialog appears before `/remote-control` connects. Select **Enable Remote Control** to accept and connect. If you select **Never mind** or press Esc, Claude Code doesn’t connect and asks again the next time you run `/remote-control`.The `--verbose`, `--sandbox`, and `--no-sandbox` flags are not available with this command.
In the [Claude Code VS Code extension](../03-IDE-Integrations/vs-code.md), type `/remote-control` or `/rc` in the prompt box.
```python
/remote-control
```
While Remote Control is on, Claude Code shows a **Remote Control** indicator in the prompt box footer. Once the session connects, click the indicator to go directly to the session, or find it in the session list at [claude.ai/code](https://claude.ai/code). Claude Code also posts the session URL in the conversation. To disconnect, 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.
In a local session in the [Claude Desktop app’s](../16-Mobile-Desktop/desktop.md) Code tab, type `/remote-control` or `/rc` in the prompt box.
```python
/remote-control
```
Once the session connects, find it in the session list at [claude.ai/code](https://claude.ai/code). To disconnect, run `/remote-control` again.To turn Remote Control on for every session by default instead, see [Enable Remote Control for all sessions](#enable-remote-control-for-all-sessions).
[](#check-connection-status)
Check connection status
In an interactive session, while Remote Control is connected, the terminal shows an `/rc active` indicator that links to the session on claude.ai. The indicator is hidden when the terminal is too narrow to fit it. To see the session URL and a QR code for [connecting from another device](#connect-from-another-device), run `/remote-control` again to open the status panel. The panel also lets you disconnect Remote Control while your local session keeps running. If the connection fails in an interactive session, the indicator changes to show the failure, and Claude Code shows the reason in a notification and adds it to the conversation. Run `/remote-control` to reconnect, unless the reason says the session changed somewhere else:
- **Another connection took over this session**: another device or Claude Code session has it now. Run `/remote-control` only if you want to take it back.
- **This session was ended or archived from another device or app**: run `/remote-control` only if you want the session back. Claude Code reopens an archived session.
- **The server no longer reports this session**: it may have been deleted from another device or app.
[](#connect-from-another-device)
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](https://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](https://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.
When you connect, the device shows any subagents and workflows the session already has running in the background. Stop one of them from the device, and Claude Code stops that task on your machine. The remote session title is chosen in this order:
1. The name you passed to `--name`, `--remote-control`, or `/remote-control`
2. The title you set with `/rename`
3. The last meaningful message in existing conversation history
4. 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, Claude Code updates the title to reflect your prompt once you send one. When you rename a session from claude.ai or the Claude app, Claude Code also updates the local title shown in `claude --resume`. If you don’t have the Claude app yet, run `/mobile` inside Claude Code to show a QR code for [claude.ai/mobile](https://claude.ai/mobile), which opens the right app store for your phone.
[](#what-connected-devices-see)
What connected devices see
A connected device shows the conversation in your terminal as it happens. These cases go beyond ordinary messages:
- **Compaction and `/clear`**: while Claude Code [compacts the conversation](context-window.md#what-survives-compaction), connected devices show the progress and then where the conversation was compacted. When you run `/clear`, the conversation resets on connected devices too.
- **Switching conversations with `/resume`**: the connected device doesn’t receive the switched-to conversation’s title or earlier history, but new messages in both directions go to and from whichever conversation is open in your terminal. To work on the original conversation from the device again, run `/resume` in your terminal and switch back to it.
- **Pulling a session with `/teleport`**: when you pull a [cloud session](claude-code-on-the-web.md#from-cloud-to-terminal) into your terminal with `/teleport`, the connected device doesn’t receive the pulled conversation’s earlier history. New messages in both directions go to and from the pulled conversation, which is now the one open in your terminal.
- **Messages from your other sessions**: with [cross-session messaging](cross-session-messaging.md), the same connection carries messages between your own sessions on different machines and from your [cloud sessions](claude-code-on-the-web.md).
- **Diff of your changes**: when the session’s directory is in a git repository, a connected device’s diff pane shows your changes. On a branch that has commits ahead of the repository’s default branch, the pane shows the changes since the branch split from it, including your uncommitted edits. On the default branch itself, or on a branch that isn’t ahead of it, the pane shows only your uncommitted changes.
- **Model**: when you pick a [model](model-config.md) from a connected device, Claude Code runs the session on that model. Requires Claude Code v2.1.238 or later. A model you pick from the device’s model control applies to the current session only. When you send `/model <name>` from the device to an interactive session, Claude Code also sets your default for new sessions.
- **Effort level**: when you set the [effort level](model-config.md#adjust-effort-level) from a connected device, with `/effort` or the device’s effort control, Claude Code applies it to the session on your machine. If you pinned a level with `CLAUDE_CODE_EFFORT_LEVEL`, the session keeps that level, and Claude Code refuses a different pick from the effort control. Picking a level from the effort control requires Claude Code v2.1.234 or later on your machine.
- **Reconnecting after a connection failure**: run `/remote-control` to reconnect. If compaction rewrote the conversation or you switched conversations with `/resume` in the meantime, Claude Code archives the server session it was using instead of leaving it in the session list. You can still find it by [filtering for archived sessions](claude-code-on-the-web.md#archive-sessions). Switching conversations while a device is still connected doesn’t archive the session.
[](#enable-remote-control-for-all-sessions)
Enable Remote Control for all sessions
Remote Control only activates when you explicitly run `claude remote-control`, `claude --remote-control`, or `/remote-control`, unless auto-connect is turned on. To turn auto-connect on for every interactive session, run `/config` inside Claude Code and set **Enable Remote Control for all sessions**. The toggle takes three values:
- **`true`**: connect automatically when an interactive session starts.
- **`false`**: turn auto-connect off, though a `true` from [managed settings](../13-Enterprise-Admin/managed-settings.md) outranks it, because Claude Code saves the choice to your user settings. A `false` in project or local settings (`.claude/settings.json`, `.claude/settings.local.json`) turns auto-connect off even over a managed `true`.
- **`default`**: clear your choice and follow your organization’s admin default if one is set, otherwise Claude Code’s current default.
The same toggle appears outside the CLI:
- **Desktop app**: **Settings \> Claude Code \> Connect new sessions to Remote Control**.
- **VS Code extension**: **Enable Remote Control for all sessions** in the [command menu’s](../03-IDE-Integrations/vs-code.md#use-the-prompt-box) Settings section.
To turn auto-connect on from a settings file instead, set [`remoteControlAtStartup`](settings-reference.md#remotecontrolatstartup) to `true` in your user `~/.claude/settings.json` or in [managed settings](../13-Enterprise-Admin/managed-settings.md). In project or local settings (`.claude/settings.json`, `.claude/settings.local.json`), Claude Code honors a `false` and turns auto-connect off for that repository, but ignores a `true`, so a checked-in file can’t turn on Remote Control for everyone who opens the repository. Auto-connect signs in with your own claude.ai account, so a session it starts appears only in your own account’s Claude apps and grants no one else access. With this setting on, each interactive Claude Code process registers one remote session. If you run multiple instances, each one gets its own remote session. To run multiple concurrent sessions from a single process, use [server mode](#start-a-remote-control-session) instead.
[](#resume-sessions-after-stopping-the-server)
Resume sessions after stopping the server
When you stop `claude remote-control` with Ctrl+C, the sessions it was serving stop responding from your phone or browser. As long as you weren’t running another `claude remote-control` in the same directory and didn’t start this one with `--no-create-session-in-dir`, Claude Code doesn’t archive them. To bring them back, run one of these commands in the same directory:
- **`claude remote-control`**: brings back every session the server was serving.
- **`claude remote-control --continue`**: brings back only the session the server started with, and exits when that session ends. If this directory has no record, Claude Code uses the newest one from this repository’s other git worktrees.
- **`claude remote-control --session-id <id>`**: brings back only the session whose ID you pass, and exits when that session ends. The ID is the part of the session’s URL at claude.ai/code between `/code/` and any `?`.
These commands work for about four hours after the server stopped. After that, run `claude remote-control` to start a new session. If you archived a session in the meantime, `--continue` and `--session-id` unarchive it on Claude Code v2.1.228 or later. To bring back a session you started with `claude --remote-control` or `/remote-control`, resume the conversation with `claude --continue` or `claude --resume`. If Remote Control doesn’t reconnect, see [Couldn’t reconnect to your Remote Control session](#couldnt-reconnect-to-your-remote-control-session). If you resume the conversation in a second terminal while the first one still has Remote Control on, Claude Code prints a `Remote Control not started here` notice in the second terminal and leaves Remote Control off there instead of taking the session away from the first. Run `/remote-control` in the second terminal to move Remote Control to it. When you resume a conversation in Claude Desktop or an IDE extension that had Remote Control on, Claude Code reattaches it to the existing claude.ai session instead of adding a new one to the session list.
[](#connection-and-security)
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. While Remote Control is connected, the session transcript, including your messages, Claude’s responses, and tool activity, is stored on Anthropic servers. The stored transcript keeps the conversation in sync across your devices and lets the session reconnect after a network drop. Execution and filesystem access stay on your machine, and stored transcripts are retained under the [Data usage](../13-Enterprise-Admin/data-usage.md) policy. To turn Remote Control off entirely, use the [`disableRemoteControl`](settings-reference.md#disableremotecontrol) setting. Organizations with compliance requirements such as Zero Data Retention can’t enable Remote Control.
[](#trusted-devices)
Trusted Devices
Trusted Devices is currently in beta. Features and functionality may evolve as the experience is refined.Trusted Devices is available on Pro, Max, Team, and Enterprise plans and is off by default. On Team and Enterprise plans, an Owner turns it on for the organization. On Pro and Max plans, you turn on **Require trusted devices** yourself in your settings, on the Cowork or Account page.
Trusted Devices requires each member of your organization, or you alone on a Pro or Max plan, to verify their device before they can view or steer Remote Control sessions from claude.ai, the Claude mobile apps, or Claude Desktop. It ties Remote Control access to a known device and a recent authentication, not just a signed-in account. When the setting is on, interacting with a Remote Control session requires both of the following:
- **An enrolled device**: each browser, phone, or desktop app a member uses for Remote Control enrolls its own credential. Enrollment is only offered shortly after a full sign-in, so a device joins the trusted list as part of a real authentication rather than silently in the background.
- **A recent sign-in**: the member’s sign-in must be no more than 18 hours old. Instead of signing in again each day, members confirm presence with Face ID, Touch ID, Windows Hello, or a passkey. This biometric step-up refreshes the session immediately.
Biometric checks run on the device through the operating system or browser, the same mechanism as passkey sign-in. Anthropic never receives or stores fingerprints, face data, or any other biometric information. Only the device’s public key and basic metadata such as display name, platform, and enrollment time are stored. The setting applies only to Remote Control. Regular Claude chat, Claude Code in the terminal, and API usage are unaffected.
[](#enable-trusted-devices-for-your-organization)
Enable Trusted Devices for a Team or Enterprise organization
An Owner enables the setting from the claude.ai organization settings.
1
Go to the Capabilities page
Go to [**Organization settings \> Capabilities \> Remote sessions**](https://claude.ai/admin-settings/capabilities). The **Require trusted devices** toggle appears in that section.
2
Turn on Require trusted devices
The setting applies to every member of the organization and to Remote Control sessions started after you enable it. Sessions that were already running before the toggle was turned on are not retroactively protected and continue without the device requirement until they end. Per-team or per-project scoping is not available.
3
Tell members what to expect
The first time a member views or steers a new Remote Control session from a browser, phone, or desktop app after the setting is enabled, they are prompted to enroll that device. Letting them know ahead of time avoids confusion.
[](#what-members-see)
What members see
Enrollment is a one-time step per device. After that, the only visible change is an occasional biometric prompt.
- **First use on each device**: the member is asked to enroll. If their sign-in is not recent, they sign in first through your normal flow, including SSO if configured, then confirm enrollment.
- **Day to day**: members with an enrolled device and a recent sign-in see no prompts. When the sign-in ages past 18 hours, the next Remote Control interaction shows a single Face ID, Touch ID, Windows Hello, or passkey prompt.
- **Unenrolled devices**: Remote Control sessions cannot be viewed or steered until the device is enrolled. Regular Claude chat on that device is unaffected.
- **No platform authenticator**: members on a machine without Face ID, Touch ID, or Windows Hello can use a hardware security key, or sign in again instead of stepping up.
- **In the terminal**: the machine running Claude Code receives its own credential automatically when the developer signs in to the CLI. There is no separate enrollment step in the terminal.
[](#manage-enrolled-devices)
Manage enrolled devices
Members can review and revoke their own devices from account settings. Open [claude.ai/settings/account](https://claude.ai/settings/account#trusted-devices) and find the **Trusted devices** section to see every enrolled device with its name, platform, and enrollment date. Removing a device revokes its credential immediately, and the device can re-enroll later after a fresh sign-in. Credentials also expire on their own if not renewed, so an unused device drops off the trusted list automatically. For a lost or stolen device, the member removes it from this page. If the member cannot sign in, an admin can use **Sign out everywhere** in the admin console to revoke every session and enrolled device for that member, after which the member re-enrolls the devices they still hold.
[](#remote-control-vs-cloud-sessions)
Remote Control vs cloud sessions
Remote Control and [cloud sessions](claude-code-on-the-web.md) 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. A cloud session executes on cloud infrastructure, Anthropic-managed by default. Use Remote Control when you’re in the middle of local work and want to keep going from another device. Use a cloud session when you want to start a task without any local setup, work on a repo you don’t have cloned, or run multiple tasks in parallel. A [project](claude-projects.md) combines the two: its threads run in the cloud, and it uses Remote Control to [run a thread on your computer](claude-projects.md#run-a-thread-on-your-own-computer) when you ask for one there. 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](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch) | Message a task from the Claude mobile app | Your machine (Desktop) | [Pair the mobile app with Desktop](https://support.claude.com/en/articles/13947068) | Delegating work while you’re away, minimal setup |
| [Remote Control](remote-control.md) | Drive a running session from [claude.ai/code](https://claude.ai/code) or the Claude mobile app | Your machine (CLI, Desktop, or VS Code) | Run [`claude remote-control` or `/remote-control`](remote-control.md#start-a-remote-control-session) | Steering in-progress work from another device |
| [Channels](channels.md) | Push events from a chat app like Telegram or Discord, or your own server | Your machine (CLI) | [Install a channel plugin](channels.md#quickstart) or [build your own](channels-reference.md) | Reacting to external events like CI failures or chat messages |
| [Slack](../14-Connectors/slack.md) | Mention `@Claude` in a team channel | Anthropic cloud | [Install the Slack app](../14-Connectors/slack.md#setting-up-claude-code-in-slack) with [Claude Code on the web](claude-code-on-the-web.md) enabled | PRs and reviews from team chat |
| [Self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md) | Start a [cloud session](claude-code-on-the-web.md) and pick your organization’s environment | Your organization’s infrastructure | [Deploy runners](../13-Enterprise-Admin/self-hosted-environments-quickstart.md), on Team and Enterprise plans | Cloud sessions that must run inside your network |
| [Scheduled tasks](scheduled-tasks.md) | Set a schedule | [CLI](scheduled-tasks.md), [Desktop](../16-Mobile-Desktop/desktop-scheduled-tasks.md), or [cloud](web-scheduled-tasks.md) | Pick a frequency | Recurring automation like daily reviews |
[](#mobile-push-notifications)
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 two on/off toggles below, there is no per-event configuration. To set up mobile push notifications:
1
Install the Claude mobile app
Download the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) or [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude).
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** for proactive notifications, **Push when actions required** for permission prompts and questions, or both.
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.
Claude Code skips mobile push notifications while you are typing in or focused on the connected terminal. To extend this to any time you are at the machine, even in another window, set [`CLAUDE_CLIENT_PRESENCE_FILE`](env-vars.md) to a marker file path: notifications are skipped while the file exists. Configure a screen-lock listener or similar tool to create the file when your screen unlocks and delete it when your screen locks.
[](#limitations)
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](#start-a-remote-control-session) 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 the Desktop app or VS Code, or otherwise stop the `claude` process, the session goes offline until you [bring it back](#resume-sessions-after-stopping-the-server). To keep a session running on a remote machine after you disconnect from SSH, start it inside `tmux` or `screen`.
- **Crashed sessions in server mode**: if a session served by `claude remote-control` crashes, send it a message from a connected device. Claude Code serves it again. You don’t have to restart the server. Requires Claude Code v2.1.238 or later.
- **HTTP 403 refusals on a connected session**: once an interactive session is connected, Claude Code keeps retrying for up to three minutes when something between your machine and Anthropic’s servers answers with HTTP 403, as can happen after a VPN or network change. If the refusals last longer, Claude Code disconnects, and the reason names what refused: a network edge, or a proxy, VPN, or firewall on your own network.
- **Extended network outage**: if your machine is awake but can’t reach the network, what you do next depends on the mode:
- **Server mode**: Claude Code gives up after roughly 10 minutes and the `claude remote-control` process exits. Run `claude remote-control` again to start a new session.
- **Interactive session**: keep working locally. Claude Code retries for as long as the outage lasts and reconnects on its own when the network returns.
- **Presence heartbeats failing**: if an interactive session disconnects with `could not reach the Remote Control server for about 30 minutes`, run `/remote-control` to reconnect.
- **Forwarded dialogs expire**: Claude Code keeps permission prompts and `AskUserQuestion` questions open until you answer them. When Claude Code forwards another kind of dialog to the remote session, such as the model-choice prompt shown after a safety refusal, it waits five minutes by default, then closes the dialog and continues with the dialog’s no-action default. Set [`dialogExpiry`](settings-reference.md#dialogexpiry) to adjust or disable the deadline. Requires Claude Code v2.1.224 or later.
- **The Fable usage-credits consent prompt isn’t forwarded**: Claude Code shows the mid-session [Fable usage-credits consent prompt](model-config.md#fable-and-usage-credits) only where the session runs, not on your device. When the session runs in a terminal and nobody there answers before Claude Code closes the prompt, the turn ends without sending the request; see [The prompt to confirm went unanswered](errors.md#the-prompt-to-confirm-went-unanswered).
- **Some commands are local-only**: commands that only run in the terminal interface, such as `/plugin` or `/resume`, work only from the local CLI, whether or not you pass an argument. The following work from mobile and web:
- Text-output commands: `/compact`, `/clear`, `/context`, `/usage`, `/exit`, `/usage-credits`, `/recap`, and `/reload-plugins`. `/usage-credits` prints the billing URL instead of opening a browser. `/reload-plugins` works only when the session runs in an interactive terminal; a session without one declines it.
- `/model`, `/effort`, `/fast`, `/color`, and `/rename`: pass the value as an argument, for example `/model sonnet` or `/effort high`. From mobile and web, `/model` and `/effort` take the argument in place of the terminal picker or slider.
- `/mcp`: from the mobile app, returns a text summary of server status instead of opening the picker. On the web, `/mcp` on its own opens a directory of [claude.ai connectors](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) instead of returning the summary. The `reconnect`, `enable`, and `disable` [subcommands](commands.md#all-commands) work from both. Unlike the local CLI, `/mcp reconnect` without a server name reconnects every server that has failed or needs authentication.
- `/config`: from the mobile app, pass `key=value` to set a setting, or run it with no argument to list the keys you can set. On the web, `/config` opens the Claude Code section of your settings instead, and ignores text after the command.
- On Team and Enterprise, `/usage-credits` from mobile or web doesn’t send a [usage-credits request to your admin](../17-Billing-Plans/costs.md#add-usage-credits-to-your-subscription). Sending requires a confirmation that appears only in the interactive CLI, so the command tells you to run it there instead.
- `/autocompact`, from v2.1.221: pass the window size as an argument, for example `/autocompact 500k`. With no argument, it prints the current window size as text instead of opening the dialog the command shows in a terminal session.
- `/advisor`, from v2.1.260: pass the model as an argument, for example `/advisor opus`, or pass `off` to turn the advisor off. Both forms apply to the current session only and leave your saved default unchanged. With no argument, it prints the current advisor as text instead of opening the picker.
- `/output-style`, from v2.1.269: pass the style name as an argument, for example `/output-style concise`, or run it with no argument to list the styles. From mobile and web, you can list and select only [built-in styles](output-styles.md#built-in-output-styles). To use a [custom style](output-styles.md#create-a-custom-output-style), select it in the session itself.
- `/focus`, from v2.1.281: pass `on` or `off` as an argument, for example `/focus on`, or run it with no argument to toggle the [focus view](commands.md#all-commands). Both forms apply to the current session only and leave your saved selection unchanged.
[](#troubleshooting)
Troubleshooting
[](#”remote-control-requires-a-claude-ai-subscription”)
”Remote Control requires a claude.ai subscription”
You’re not signed in with a claude.ai account, or another credential is taking precedence over your login. The message takes one of these forms:
- Signed out, from `/remote-control` or `--remote-control`: `Remote Control requires a claude.ai subscription.` or `/remote-control requires a claude.ai subscription.`
- Signed out, from `claude remote-control`: `You must be logged in to use Remote Control. Remote Control is only available with claude.ai subscriptions.`
- Signed in, but an API key or token is in use: `Remote Control requires claude.ai subscription auth.` followed by the credential in use, such as `ANTHROPIC_API_KEY is set, so this session is using API-key auth`. An `apiKeyHelper` setting and `ANTHROPIC_AUTH_TOKEN` are named the same way.
Run `claude auth login` and choose the claude.ai option. If the message names `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN`, remove it wherever it’s set: your shell environment or the `env` block of a [settings file](settings-reference.md#env). If it names `apiKeyHelper`, remove that setting.
[](#”remote-control-requires-a-full-scope-login-token”)
”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 can only make model requests, so they can’t 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”)
”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-isn’t-enabled-for-this-account”)
”Remote Control isn’t enabled for this account”
Claude Code checked Remote Control availability for the account you’re signed in with and the check came back off. The usual cause is cached entitlements that are out of date after a plan change. Run `claude auth logout` then `claude auth login` to refresh them, and update Claude Code if you’re on an old version. Run `claude doctor` to see which individual eligibility check failed. Environment-variable conflicts, unreachable checks, and your organization’s Remote Control setting each produce their own message, so this error means the account-level check itself. Before v2.1.239, this message read “Remote Control is not yet enabled for your account”.
[](#”couldn’t-verify-remote-control-eligibility”)
”Couldn’t verify Remote Control eligibility”
Claude Code could not reach the feature-flag service to check whether Remote Control is enabled for your account, typically because you are offline or a proxy is blocking the request. Retry once you have network access, or run `claude doctor` for details. The related message “Couldn’t verify your organization’s Remote Control policy” means Claude Code hit an error reading that policy, and has the same fix.
[](#”remote-control-requires-feature-flag-evaluation”)
”Remote Control requires feature-flag evaluation”
An [environment variable](env-vars.md#features-that-need-feature-flag-fetching) that turns off feature-flag evaluation is set, and the full message names the variable Claude Code found. On versions before 2.1.154, the same configuration produces “Remote Control is not yet enabled for your account” instead. What to do depends on the variable the message names:
- **`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` or `DISABLE_GROWTHBOOK`**: unset the variable wherever it’s set, in your shell environment or in the `env` block of a [`settings.json` file](settings-reference.md#all-settings).
- **`DISABLE_TELEMETRY` or `DO_NOT_TRACK`**: on a Pro, Max, Team, or Enterprise plan with `DISABLE_GROWTHBOOK` unset, these variables leave Remote Control available unless your organization requires [Trusted Devices](#trusted-devices). If it does, unset the variable wherever it’s set to use Remote Control. From v2.1.154 through v2.1.282, either variable produced this message, so update Claude Code to v2.1.283 or later.
[](#”remote-control-is-only-available-when-using-claude-via-api-anthropic-com”)
”Remote Control is only available when using Claude via api.anthropic.com”
The session isn’t talking to the Anthropic API directly, which Remote Control requires. This happens on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry. It also happens when [`ANTHROPIC_BASE_URL`](env-vars.md) points at a host other than `api.anthropic.com`, such as an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md) or proxy, even if you sign in with claude.ai. See the [error reference](errors.md#remote-control-requires-the-anthropic-api) for the full cause list. The message names what routed the session away from the Anthropic API, such as `CLAUDE_CODE_USE_BEDROCK` or a custom `ANTHROPIC_BASE_URL`. If you have an eligible claude.ai login, unset the named variable, remove it from the `env` key in [settings](settings.md) if you set it there, and restart the session.
[](#”remote-control-is-disabled-by-your-organization’s-policy”)
”Remote Control is disabled by your organization’s policy”
A policy blocks Remote Control. Check these causes in order:
- **The error mentions `disableRemoteControl`**: your IT administrator has disabled Remote Control on this device through [managed settings](../13-Enterprise-Admin/managed-settings.md), independent of the organization-wide toggle and of how you’re signed in.
- **Your claude.ai plan is Pro or Max**: Claude Code is still signed in under a Team or Enterprise organization from an earlier login, so it checks that organization’s Remote Control policy. Run `/status` to see which plan and organization your sign-in uses. Run `claude auth logout` then `claude auth login` to sign in again under your current plan.
- **The message doesn’t say to contact your organization admin**: your organization has a HIPAA configuration that is incompatible with Remote Control, and `/status` lists `HIPAA` in its `Compliance` row. In this state the admin panel’s Remote Control toggle is grayed out, so an Owner can’t change it there. Contact Anthropic support to discuss options. Before v2.1.267, this case showed “Remote Control isn’t available for your organization due to its compliance policy” instead.
- **Otherwise, an Owner hasn’t enabled it for your organization**: Remote Control is off by default on Team and Enterprise plans. An Owner can enable it at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) by turning on the **Remote Control** toggle. This toggle is a server-side organization setting.
Before v2.1.281, this message also appeared when Claude Code hadn’t loaded your organization’s policy on this machine, for example after starting offline. Later versions report that state as [`Couldn't verify your organization's policy for remote control`](#couldnt-verify-your-organizations-policy-for-remote-control) instead.
[](#couldnt-verify-your-organizations-policy-for-remote-control)
“Couldn’t verify your organization’s policy for remote control”
Claude Code couldn’t fetch your organization’s policy and has no saved copy on this machine to use instead, so it keeps Remote Control off until it can confirm that your organization allows it. This usually happens when you start Claude Code offline or before a VPN connects, or when a proxy interferes with the request. On a slow connection it can also appear while the first request is still in flight. The message takes one of these forms:
- From `/remote-control`, `claude remote-control`, or `claude --remote-control`: `Couldn't verify your organization's policy for remote control. Check your network connection and try again.`
- From [auto-connect](#enable-remote-control-for-all-sessions) when a session starts: `couldn't verify your organization's policy — check your network connection and try again`, prefixed with `Remote Control failed` in the notification and `Remote Control disconnected` in the conversation. The session then leaves Remote Control off.
Restore your network connection, then run `/remote-control` or run the command again. Each attempt checks for the policy again, so you don’t need to restart Claude Code. If the message keeps appearing, run `claude doctor` and read its `Organization policy` line, which says why the policy didn’t load. Before v2.1.281, this state showed `Remote Control is disabled by your organization's policy` instead.
[](#”remote-credentials-fetch-failed”)
”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:
```python
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.
[](#couldnt-reconnect-to-your-remote-control-session)
“Couldn’t reconnect to your Remote Control session”
When you resume a conversation with `claude --resume` or `claude --continue`, Claude Code reconnects to the Remote Control session recorded in that conversation. This message means the reconnection failed for a reason that may be temporary, such as a network interruption or a server error, so Claude Code can’t confirm whether the remote session still exists. Run `/remote-control` to retry the connection, or start a new session with `claude --remote-control` to create a new Remote Control session. Your local session keeps running without Remote Control in the meantime.
[](#previous-session-is-unavailable)
“Previous session is unavailable — run /remote-control to start a new one”
Claude Code couldn’t bring back the previous Remote Control session and stopped instead of starting a new one on its own. You can see this message after you resume a conversation with `claude --resume` or `claude --continue`, or after Claude Code [reconnects on its own following a disconnect](errors.md#remote-control-couldnt-refresh-your-login). Run `/remote-control` to start a new Remote Control session under the current login; your local session keeps running without Remote Control in the meantime. The related message `Remote Control could not verify the signed-in account — run /remote-control to reconnect` has the same fix. If you run `/remote-control` after `Previous session is unavailable` without restarting Claude Code first, Claude Code leaves the conversation’s earlier messages out of the new session.
[](#”remote-control-got-an-unexpected-server-response”)
”Remote Control got an unexpected server response”
The Remote Control server accepted a request but replied in a form this version of Claude Code couldn’t read, while creating the remote session or fetching its credentials. Retrying on the same version fails the same way. Run `claude update`, then run `/remote-control` to reconnect.
[](#”your-organization-requires-trusted-devices-for-remote-control-but-this-device-is-not-enrolled”)
”Your organization requires Trusted Devices for Remote Control, but this device is not enrolled”
Your organization has [Trusted Devices](#trusted-devices) enabled and this machine has not enrolled yet. Run `/login` in Claude Code. Enrollment happens as part of sign-in, and there is no separate enrollment command.
[](#”session-expired-for-trusted-device-check”)
”session expired for trusted-device check”
Your sign-in is more than 18 hours old. Run `/login` in Claude Code, or confirm with Face ID, Touch ID, Windows Hello, or a passkey when claude.ai or the mobile app prompts you. See [Trusted Devices](#trusted-devices).
[](#related-resources)
Related resources
- [Use Claude Code in the cloud](claude-code-on-the-web.md): run sessions in the cloud instead of your machine, configured through [cloud environments](cloud-environments.md)
- [Cross-session messaging](cross-session-messaging.md): let Claude message your sessions on other machines or your [cloud sessions](claude-code-on-the-web.md)
- [Channels](channels.md): forward Telegram, Discord, or iMessage into a session so Claude reacts to messages while you’re away
- [Dispatch](../16-Mobile-Desktop/desktop.md#sessions-from-dispatch): message a task from your phone and it can spawn a Desktop session to handle it
- [Authentication](../13-Enterprise-Admin/iam.md): set up `/login` and manage credentials for claude.ai
- [CLI reference](cli-reference.md): full list of flags and commands including `claude remote-control`
- [Security](../13-Enterprise-Admin/security.md): how Remote Control sessions fit into the Claude Code security model
- [Data usage](../13-Enterprise-Admin/data-usage.md): what data flows through the Anthropic API during local, Remote Control, and cloud sessions
---
## Using Claude Code Remote Control · Claude Academy
Source: https://www.claude.com/resources/tutorials/using-claude-code-remote-control
Path: 02-Claude-Code-CLI/resources-tutorials-using-claude-code-remote-control.md
# Using Claude Code Remote Control
Learn more about using Claude Code remote control to access Claude Code sessions on the go.
---
## Choose a sandbox environment - Claude Code Docs
Source: https://code.claude.com/docs/en/sandbox-environments
Path: 02-Claude-Code-CLI/sandbox-environments.md
## On this page
- [Compare sandboxing approaches](#compare-sandboxing-approaches)
- [Choose an approach](#choose-an-approach)
- [How isolation relates to permission modes](#how-isolation-relates-to-permission-modes)
- [Sandboxed Bash tool](#sandboxed-bash-tool)
- [Sandbox runtime](#sandbox-runtime)
- [Set up and launch the runtime](#set-up-and-launch-the-runtime)
- [What the runtime blocks on its own](#what-the-runtime-blocks-on-its-own)
- [After unattended runs](#after-unattended-runs)
- [Dev containers](#dev-containers)
- [Custom container](#custom-container)
- [Virtual machine](#virtual-machine)
- [Cloud sessions](#cloud-sessions)
- [Enforce isolation across an organization](#enforce-isolation-across-an-organization)
- [See also](#see-also)
Permissions and sandboxing
# Choose a sandbox environment
Copy pageCopy page
Compare Claude Code sandbox options: the built-in sandboxed Bash tool, sandbox runtime, dev containers, Docker, and VMs. Choose the right isolation for your threat model.
Copy pageCopy page
Isolating Claude Code limits what a session can read, write, and reach on the network. This matters most when you let Claude work with fewer permission prompts, run it unattended, or point it at code you do not fully trust. Claude Code can run in several kinds of isolated environments, ranging from a lightweight per-command sandbox to a fully separate virtual machine. This page compares them by what they isolate and what they require, helps you choose one for your threat model, and shows how to enforce that choice across an organization.
For the broader security model, see [Security](../13-Enterprise-Admin/security.md). For Agent SDK deployments, see [Secure deployment](../05-Agent-SDK/agent-sdk-secure-deployment.md).
[](#compare-sandboxing-approaches)
Compare sandboxing approaches
The first two approaches in the table below run on the host operating system without containers. The rest place Claude Code inside a container or virtual machine.
| Approach | What is isolated | Requires Docker | Setup effort |
|:--------------------------------------------|:----------------------------------------------------------------------------|:----------------|:-------------------------------------------------------------------------------------------------------------|
| [Sandboxed Bash tool](#sandboxed-bash-tool) | Bash, PowerShell, and Monitor commands and their child processes | No | Minimal on macOS; low on Linux and WSL2 |
| [Sandbox runtime](#sandbox-runtime) | The whole Claude Code process, including file tools, MCP servers, and hooks | No | Low |
| [Dev container](#dev-containers) | Full development environment | Yes | Medium |
| [Custom container](#custom-container) | Full development environment | Yes | Medium to high |
| [Virtual machine](#virtual-machine) | Full operating system | No | High |
| [Cloud sessions](#cloud-sessions) | Full operating system, hosted by Anthropic | No | None; requires a Claude subscription, and a connected GitHub account unless you launch with `claude --cloud` |
The [sandboxed Bash tool](sandboxing.md) is built into Claude Code and restricts Bash commands. Built-in file tools, MCP servers, and hooks still run directly on your host. Every other approach in the table puts the whole Claude Code process inside the isolation boundary, so file tools, MCP servers, and hooks are restricted too.
Sandbox isolation reduces the impact of a breach, but it does not eliminate risk. Any approach that allows network egress can still leak data the agent can read, and any approach that mounts your project directory writable can still modify that code. Review the [security limitations](sandboxing.md#security-limitations) before relying on a sandbox as a hard control.Isolation also does not change what is sent to the model. Your prompts and the files Claude reads are transmitted to the Anthropic API or your configured provider with or without a sandbox. See [Data usage](../13-Enterprise-Admin/data-usage.md) for what Claude Code sends and how to reduce it.
[](#choose-an-approach)
Choose an approach
Match your goal to a row below, then read the detail section that follows.
| You want to | Start with |
|:------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Reduce permission prompts during everyday work on your own machine | The [sandboxed Bash tool](sandboxing.md), configured with `/sandbox` |
| Let Claude work unattended with `--dangerously-skip-permissions` or auto mode | The preconfigured [dev container](devcontainer.md), any container or VM, or the [sandbox runtime](#sandbox-runtime) |
| Isolate MCP servers and hooks as well as Bash, without Docker | The sandbox runtime |
| Work on an untrusted repository | A dedicated virtual machine, or a [cloud session](claude-code-on-the-web.md) if you have a Claude subscription; GitHub is not required when you launch with `claude --cloud` |
| Standardize a sandboxed environment across a team | The preconfigured [dev container](devcontainer.md), copied into your repository |
| Use Claude Code from a device with no local setup | A [cloud session](claude-code-on-the-web.md), which requires a Claude subscription and a connected GitHub account |
| Require isolation for every developer in your organization | [Enforce isolation across an organization](#enforce-isolation-across-an-organization) |
| Work on a native Windows host | A container or VM, or run the Bash sandbox inside WSL2 |
[](#how-isolation-relates-to-permission-modes)
How isolation relates to permission modes
[Permission modes](permission-modes.md) decide whether a tool call runs and whether you are prompted first. Isolation restricts what a command can access once it runs. The two work together: when a permission mode lets actions run without asking you, an isolation boundary limits what those actions can reach. When you pass `--dangerously-skip-permissions`, Claude acts without asking you first. The [actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) still apply. With no prompts to catch mistakes, the isolation boundary you choose is what protects your system. Always run `--dangerously-skip-permissions` sessions inside a container, a VM, or the [sandbox runtime](#sandbox-runtime), so that file tools, MCP servers, and hooks are also inside the boundary. On Linux and macOS, Claude Code refuses to start with this flag when running as root, so run the container, VM, or sandbox runtime as a non-root user. [Auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) replaces the prompt with a classifier that reviews actions. The classifier is a per-action control, not an isolation boundary, so an isolation boundary still adds defense in depth for unattended runs, and is not required the way it is for `--dangerously-skip-permissions`. The [sandboxed Bash tool](#sandboxed-bash-tool) on its own constrains only shell commands, so it is not sufficient for fully unattended runs in either mode. You can layer approaches: running the sandboxed Bash tool inside a container or VM gives you OS-level command restrictions on top of the outer environment boundary. For how the Bash sandbox itself interacts with permission rules and modes, see [How sandboxing relates to permissions and permission modes](sandboxing.md#how-sandboxing-relates-to-permissions-and-permission-modes).
[](#sandboxed-bash-tool)
Sandboxed Bash tool
This option does not support native Windows. On Windows hosts, use WSL2 or one of the container or VM approaches below.
The sandboxed Bash tool is built into Claude Code. It uses operating system primitives to restrict the filesystem and network access of every Bash, PowerShell, or Monitor command Claude runs. Run the `/sandbox` command to open the sandbox panel and choose a mode. The [Sandboxing](sandboxing.md) guide covers the approval modes, the default boundary, and how to widen or narrow it. The per-command sandbox does not cover everything that runs in a session:
- Other [built-in tools](tools-reference.md) such as Read, Edit, and WebFetch run inside the Claude Code process and do not spawn arbitrary code. [Permission rules](permissions.md) for path or domain gate them instead.
- [MCP](../06-MCP-Tools/General/mcp.md) servers and [command hooks](../07-Hooks/hooks.md#command-hook-fields) are separate processes that run unconstrained on the host.
To put built-in tools, MCP servers, and hooks all behind one OS boundary, run the whole Claude Code process inside the [sandbox runtime](#sandbox-runtime), the [dev container](#dev-containers), or a [custom container](#custom-container).
[](#sandbox-runtime)
Sandbox runtime
The [`@anthropic-ai/sandbox-runtime`](https://github.com/anthropic-experimental/sandbox-runtime) package wraps an entire process in the same Seatbelt or bubblewrap isolation that the built-in Bash sandbox uses. Running Claude Code through the runtime constrains every tool, hook, and MCP server in the session, not only shell commands. The runtime is a beta research preview, and its configuration format may change as the package evolves. This section covers what you configure and what the runtime enforces on its own. For deploying the runtime in Agent SDK applications, see the [secure deployment guide](../05-Agent-SDK/agent-sdk-secure-deployment.md#sandbox-runtime).
[](#set-up-and-launch-the-runtime)
Set up and launch the runtime
On Linux and WSL2, the runtime relies on the same `bubblewrap` and `socat` packages as the built-in sandbox, plus `ripgrep`, which Claude Code bundles but the standalone runtime resolves from your PATH. Install `bubblewrap` and `socat` as described in [Set up Linux and WSL2](sandboxing.md#set-up-linux-and-wsl2), and `ripgrep` from your distribution’s package manager. On macOS you need no additional packages. The runtime uses the built-in Seatbelt sandbox there. By default the runtime denies network access and confines writes to a small set of built-in runtime paths, so configure it before launching Claude Code through it. Put your configuration in `~/.srt-settings.json`, or in a file you pass with `--settings`. The package [README](https://github.com/anthropic-experimental/sandbox-runtime) documents the full configuration schema. Allow write access to at least:
- Your project directory.
- Claude Code’s configuration paths `~/.claude` and `~/.claude.json`.
- `/tmp`, where Claude Code writes runtime files.
Allow the network domains your session needs:
- `api.anthropic.com`, or your configured provider’s endpoint. On a third-party provider, keep `api.anthropic.com` as well: the WebFetch domain safety check still calls it by default unless you set `skipWebFetchPreflight: true`.
- `claude.ai` and `platform.claude.com`, which [OAuth sign-in and token refresh](../13-Enterprise-Admin/network-config.md#network-access-requirements) require. Runs authenticated with an API key can drop these two.
On Linux and WSL2, the runtime applies write grants only to paths that already exist. In a fresh environment, create Claude Code’s configuration paths before the first launch:
```python
mkdir -p ~/.claude && { [ -f ~/.claude.json ] || echo '{}' > ~/.claude.json; }
```
Once the settings file is in place, launch Claude Code with `npx` and pass `claude` as the command to wrap:
```python
npx @anthropic-ai/sandbox-runtime claude
```
Claude Code starts inside the sandbox with the filesystem and network boundaries you configured. The same command works for sandboxing standalone MCP servers or other helper processes.
[](#what-the-runtime-blocks-on-its-own)
What the runtime blocks on its own
The runtime blocks the highest-risk writes without any configuration from you:
- `denyWrite` takes precedence over `allowWrite`.
- At the project root, the runtime denies `.git/hooks`, denies `.git/config` unless you set `filesystem.allowGitConfig: true`, and denies `.mcp.json`, `.claude/commands`, `.claude/agents`, and shell startup files.
- On macOS, these denies are checked when a write happens, so they also cover nested files and repositories created during the session.
- On Linux and WSL2, the runtime builds the deny list once at launch. It reliably covers the project root, makes a best-effort shallow scan for nested copies that exist at that point, and does not cover anything the session creates later, such as `git init`, `git clone`, or scaffolding. The README’s `mandatoryDenySearchDepth` section describes the scan’s exact semantics.
- Without a valid `~/.srt-settings.json`, the runtime starts anyway, blocks network access, and confines writes to built-in runtime paths such as `/tmp/claude`, `~/.npm/_logs`, and `~/.claude/debug`. Don’t take a clean start as proof your settings loaded.
- When you pass `--settings`, the runtime refuses to start if the file fails to load.
Your write grants still include other paths Claude Code loads configuration from, so deny those with `denyWrite`. A sandboxed session that can write them can persist hooks, permission rules, or MCP servers that run unsandboxed the next time you launch Claude Code.
[](#after-unattended-runs)
After unattended runs
Review the paths you kept writable. On Linux and WSL2, also review anything the session created.
[](#dev-containers)
Dev containers
A dev container runs Claude Code inside a Docker container that VS Code or a compatible editor manages, with your project mounted in. You can define your own with a `.devcontainer/` directory in your repository. The claude-code repository publishes an [example dev container](devcontainer.md) with a default-deny iptables firewall as a starting point. Copy it into your repository and adjust the firewall allowlist, base image, and pinned Claude Code version to fit your environment. Because the firewall blocks unapproved egress, a configuration like this supports running Claude Code with `--dangerously-skip-permissions` for unattended work.
[](#custom-container)
Custom container
You can run Claude Code in any Docker or OCI container image with your own network policies, mounted volumes, and seccomp profiles. This is the most common path for organizations with existing container infrastructure or CI runners. Several managed sandbox and remote execution services can host the container for you. The same checklist applies as for any container you operate: review what is mounted writable, what credentials and tokens are reachable inside it, and what the network egress policy allows. You can layer the built-in Bash sandbox inside the container for per-command restrictions. Unprivileged containers need the nested-sandbox setting described in [Sandboxing troubleshooting](sandboxing.md#troubleshooting).
[](#virtual-machine)
Virtual machine
A dedicated virtual machine provides the strongest separation, with its own kernel and, in cloud or microVM deployments, its own virtualized hardware. Options include cloud instances, local hypervisors, and microVMs such as Firecracker. Use this approach when you are evaluating untrusted code, when your security policy requires kernel-level separation between the agent and the host, or when no host-level approach meets your compliance requirements. [Docker Sandboxes](https://docs.docker.com/ai/sandboxes/) provides a microVM with its own Docker daemon and workspace sync, which can run Claude Code on any host with Docker Sandboxes installed. It is a free, standalone product from Docker that does not require Docker Desktop.
[](#cloud-sessions)
Cloud sessions
A [cloud session](claude-code-on-the-web.md) runs in an isolated, Anthropic-managed virtual machine. A network proxy enforces a default allowlist, and a separate proxy holds your GitHub token outside the sandbox while issuing scoped credentials for repository access inside it. Sessions your organization routes to a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) run on infrastructure you provision instead, where isolation, egress control, and git credentials are your deployment’s responsibility. Use this approach when you want full VM isolation without provisioning infrastructure yourself, or when you are delegating tasks from a device that does not have a local development environment. It requires a Claude subscription. Unless you launch from the CLI, you also need a connected GitHub account so the sandbox can clone your repository. When you launch from the CLI with `--cloud`, Claude Code can [bundle and upload your local repository](claude-code-on-the-web.md#send-local-repositories-without-github) instead. See [Use Claude Code in the cloud](claude-code-on-the-web.md) for plan availability and GitHub authentication options.
[](#enforce-isolation-across-an-organization)
Enforce isolation across an organization
Individual developers can opt into any of the sandboxing approaches on this page. What an organization can enforce, and with which tools, depends on the approach:
- **Built-in Bash sandbox**: the only approach Claude Code enforces itself. Deliver the `sandbox` settings keys through [managed settings](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms), either as a file managed by your MDM or through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) on Claude.ai. See [Enforce sandboxing with managed settings](sandboxing.md#enforce-sandboxing-with-managed-settings) for the keys to deploy and how to keep developers from widening the policy.
- **Dev containers**: commit the [example dev container](devcontainer.md) to your repositories to standardize the environment across a team. This is a convention rather than an enforcement boundary, because Claude Code does not require a container. If developers should not be able to run Claude Code outside it, enforce that with your organization’s device management or software allowlisting tools.
- **Custom containers and VMs**: distribute Claude Code through the approved image and use your organization’s device management or software allowlisting tools to prevent installation outside it.
[](#see-also)
See also
These pages cover configuration and policy details for the sandboxing approaches on this page.
- [Sandboxing](sandboxing.md): configure the built-in sandboxed Bash tool
- [Dev container](devcontainer.md): the preconfigured Docker development container
- [Security](../13-Enterprise-Admin/security.md): the full Claude Code security model
- [Secure deployment](../05-Agent-SDK/agent-sdk-secure-deployment.md): isolation guidance for Agent SDK applications
- [Settings](settings-reference.md#sandbox-settings): all sandbox configuration keys, including managed settings delivery
---
## Configure the sandboxed Bash tool - Claude Code Docs
Source: https://code.claude.com/docs/en/sandboxing
Path: 02-Claude-Code-CLI/sandboxing.md
## On this page
- [Get started](#get-started)
- [Set up Linux and WSL2](#set-up-linux-and-wsl2)
- [Sandbox modes](#sandbox-modes)
- [Auto-allow mode](#auto-allow-mode)
- [Regular permissions mode](#regular-permissions-mode)
- [The unsandboxed retry escape hatch](#the-unsandboxed-retry-escape-hatch)
- [Temporary directories](#temporary-directories)
- [Configure sandboxing](#configure-sandboxing)
- [Disable filesystem isolation](#disable-filesystem-isolation)
- [Which settings can disable it](#which-settings-can-disable-it)
- [What changes when filesystem isolation is off](#what-changes-when-filesystem-isolation-is-off)
- [Protect credentials](#protect-credentials)
- [Mask credentials](#mask-credentials)
- [Mask environment variables](#mask-environment-variables)
- [Re-sign AWS requests](#re-sign-aws-requests)
- [Mask credential files](#mask-credential-files)
- [How sandboxing works](#how-sandboxing-works)
- [Filesystem isolation](#filesystem-isolation)
- [Protected paths](#protected-paths)
- [Network isolation](#network-isolation)
- [Per-command allowed domains in auto mode](#per-command-allowed-domains-in-auto-mode)
- [IPv6 addresses in domain lists](#ipv6-addresses-in-domain-lists)
- [OS-level enforcement](#os-level-enforcement)
- [How sandboxing relates to permissions and permission modes](#how-sandboxing-relates-to-permissions-and-permission-modes)
- [Permission rules](#permission-rules)
- [Permission modes](#permission-modes)
- [Configure the sandbox for your organization](#configure-the-sandbox-for-your-organization)
- [Enforce sandboxing with managed settings](#enforce-sandboxing-with-managed-settings)
- [Keep developers from widening the policy](#keep-developers-from-widening-the-policy)
- [Custom proxy configuration](#custom-proxy-configuration)
- [Troubleshooting](#troubleshooting)
- [Limitations](#limitations)
- [Security limitations](#security-limitations)
- [Platform and tool compatibility](#platform-and-tool-compatibility)
- [Scope](#scope)
- [See also](#see-also)
Permissions and sandboxing
# Configure the sandboxed Bash tool
Copy pageCopy page
Learn how Claude Code’s sandboxed Bash tool provides filesystem and network isolation for safer, more autonomous agent execution.
Copy pageCopy page
The Bash sandbox lets Claude run most shell commands without stopping to ask permission. Instead of approving each command, you define which files and network domains commands can touch, and the operating system enforces that boundary for every Bash, PowerShell, or Monitor command and its child processes.
To compare other isolation approaches such as dev containers, custom containers, and virtual machines, see [Sandbox environments](sandbox-environments.md). To reduce permission prompts for tools other than Bash, see [permission modes](permission-modes.md).
[](#get-started)
Get started
The sandbox is built into Claude Code and runs on macOS, Linux, and WSL2. Native Windows is not supported. On Windows, run Claude Code inside a WSL2 distribution. On macOS, there is nothing to install: sandboxing uses the built-in Seatbelt framework. On Linux and WSL2, the sandbox relies on two packages, covered in [Set up Linux and WSL2](#set-up-linux-and-wsl2). Even if you haven’t installed them yet, you can start with `/sandbox`, because its panel shows whether anything is missing.
1
Run /sandbox
Start a Claude Code session and run the `/sandbox` command:
```python
/sandbox
```
This opens the sandbox panel with three tabs, plus a Dependencies tab on Linux when the optional seccomp filter is missing:
- **Mode**: choose how sandboxed commands are approved, covered in the next step
- **Overrides**: choose whether commands that fail under the sandbox can fall back to running unsandboxed. This is the [`allowUnsandboxedCommands`](settings-reference.md#sandbox-allowunsandboxedcommands) setting
- **Config**: view the resolved sandbox settings
If the panel shows only a Dependencies tab, a required package is missing. Install it as described in [Set up Linux and WSL2](#set-up-linux-and-wsl2), restart Claude Code, and run `/sandbox` again.
2
Choose a mode
On the Mode tab, select auto-allow or regular permissions. Auto-allow runs sandboxed commands without prompting, and regular permissions keeps the regular permission prompts even when commands are sandboxed. See [Sandbox modes](#sandbox-modes) for which commands still prompt in auto-allow mode.
3
Run a Bash command
Ask Claude to run a command, such as a build or a test suite. By default, commands inside the sandbox can write to the working directory, a [per-user temp directory](env-vars.md), and any [directories you’ve added](permissions.md#additional-directories-grant-file-access-not-configuration) with `--add-dir`, `/add-dir`, or `permissions.additionalDirectories`.The first time a command needs a new network domain, Claude Code prompts for approval; in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), Claude instead names the hosts a command needs [on the command itself](#per-command-allowed-domains-in-auto-mode) for the classifier to review with it.Commands that can’t run sandboxed fall back to the regular permission flow. Claude Code titles their permission prompt “Bash command (unsandboxed)” instead of “Bash command”, so you can tell which commands ran outside the sandbox. To widen or narrow what the sandbox allows, see [Configure sandboxing](#configure-sandboxing).If sandboxed commands fail with `Operation not permitted` inside a container, see the Bubblewrap entry under [Troubleshooting](#troubleshooting).
When you select a mode in the panel, Claude Code saves it to your project’s local settings at `.claude/settings.local.json`, which apply to the current project. Claude Code adds that file to your global gitignore when it saves a setting there. To enable the sandbox across all of your projects, set [`sandbox.enabled`](settings-reference.md#sandbox-enabled) to `true` in your user settings at `~/.claude/settings.json`. To enforce sandboxing for every developer in an organization, use [managed settings](#enforce-sandboxing-with-managed-settings). To change the sandbox for one session without writing to a settings file, start Claude Code with [`--settings`](settings.md#change-a-setting-for-one-session). For example, this command starts a sandboxed session in which Claude can’t retry a blocked command outside the sandbox:
```python
claude --settings '{"sandbox": {"enabled": true, "allowUnsandboxedCommands": false}}'
```
By default, if the sandbox cannot start because dependencies are missing or the platform is unsupported, Claude Code shows a warning and runs commands without sandboxing. To make this a hard failure instead, set [`sandbox.failIfUnavailable`](settings-reference.md#sandbox-failifunavailable) to `true`. This is intended for managed deployments that require sandboxing as a security gate.
[](#set-up-linux-and-wsl2)
Set up Linux and WSL2
On Linux and WSL2, the sandbox relies on two packages:
- [`bubblewrap`](https://github.com/containers/bubblewrap): the unprivileged sandboxing tool that enforces filesystem isolation
- [`socat`](http://www.dest-unreach.org/socat/): the relay used to route network traffic through the sandbox proxy
Install them with your distribution’s package manager:
- Ubuntu/Debian
- Fedora
```python
sudo apt-get install bubblewrap socat
```
```python
sudo dnf install bubblewrap socat
```
When a dependency is missing, the Dependencies tab in `/sandbox` lists which of `ripgrep`, `bubblewrap`, `socat`, and the seccomp filter your platform lacks. If you don’t see the tab after installing and restarting Claude Code, all dependencies are present. Ripgrep is bundled with the native Claude Code binary. The seccomp filter is optional and adds Unix domain socket blocking. Install it with `npm install -g @anthropic-ai/sandbox-runtime` if it is missing. When a required dependency is missing, the Dependencies tab is the only tab shown until you install it. When only the optional seccomp filter is missing, the Dependencies tab appears alongside the other tabs. The dependency check runs at startup, so restart Claude Code after installing packages for `/sandbox` to detect them.
Ubuntu 24.04 and later: allow bubblewrap to create user namespaces
On Ubuntu 24.04 and later, the default AppArmor policy prevents bubblewrap from creating the user namespaces it needs for isolation.To check whether your environment enforces this restriction, including inside WSL2, run `sysctl kernel.apparmor_restrict_unprivileged_userns`. If the command returns `0`, skip this step. If it prints a `No such file or directory` error, the key doesn’t exist and you can skip this step. If it returns `1`, add an AppArmor profile that grants `bwrap` this capability:
```python
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:
```python
sudo systemctl reload apparmor
```
WSL2 notes
Check your WSL version with `wsl -l -v` from PowerShell. If you see `Sandboxing requires WSL2`, your distribution is running WSL1. Upgrade it to WSL2 or run Claude Code without sandboxing.On WSL2, WSL hands a launch of a Windows binary such as `cmd.exe`, `powershell.exe`, or anything under `/mnt/c/` to the Windows host over a Unix socket, so whether a sandboxed command can launch one follows the sandbox’s [Unix-socket settings](settings-reference.md#sandbox-network-allowunixsockets): the optional seccomp filter has to be installed to block the socket in the first place. To allow these launches, set `allowAllUnixSockets`; to keep them out of the sandbox entirely, add the command to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands).
[](#sandbox-modes)
Sandbox modes
Claude Code offers two sandbox modes. In both, 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)
Auto-allow mode
When a command can be sandboxed, Claude Code runs it inside the sandbox and approves it automatically, without asking your permission. Commands that cannot be sandboxed, such as those needing network access to non-allowed hosts, fall back to the regular permission flow, where Claude Code checks your [permission rules](permissions.md) and gates any command those rules do not already allow, with a prompt in Manual mode. Even in auto-allow mode, the following still apply:
- Explicit [deny rules](permissions.md) are always respected
- `rm` or `rmdir` commands that target a [critical path](permission-modes.md#critical-paths) still go through the regular permission flow
- Content-scoped [ask rules](permissions.md) like `Bash(git push *)` still force a prompt even for sandboxed commands
- A bare `Bash` ask rule, or the equivalent `Bash(*)` form, is skipped for commands that run sandboxed; it still applies to commands that fall back to the regular permission flow. In [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode), the rule isn’t skipped: it prompts for sandboxed commands too, including read-only ones. Before v2.1.212, the skip applied in plan mode as well
Auto-allow mode works independently of your permission mode setting, with three exceptions: [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode), an auto mode command that carries [per-command allowed domains](#per-command-allowed-domains-in-auto-mode), and [server-side classifier review](permission-modes.md#how-the-classifier-evaluates-actions) of sandboxed commands in auto mode. Even if you’re not in “accept edits” mode, sandboxed Bash commands run automatically when auto-allow is enabled. This means Bash commands that modify files within the sandbox boundaries execute without prompting, even in Manual mode, where the file edit tools would prompt.In plan mode, auto-allow doesn’t widen approvals; see [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) for how Claude Code gates commands while you plan. Before v2.1.212, auto-allow ran sandboxed commands without a prompt in plan mode too.
[](#regular-permissions-mode)
Regular permissions mode
All Bash commands go through the regular permission flow, even when sandboxed. This provides more control but requires more approvals.
[](#the-unsandboxed-retry-escape-hatch)
The unsandboxed retry escape hatch
Some commands can’t run inside the sandbox at all, such as tools that are incompatible with it or that need a host you haven’t allowed. Claude Code reports sandbox violations in the blocked command’s result, naming the path or host the sandbox denied, so Claude sees what the sandbox blocked. Rather than failing the task or requiring you to turn sandboxing off, Claude Code includes an escape hatch: Claude analyzes the violation and may retry the command with the `dangerouslyDisableSandbox` parameter. The retried command runs outside the sandbox, so it goes through the regular permission flow. In Manual mode you get a confirmation prompt. In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), the classifier evaluates the underlying command. While [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) is on, a retry that needs approval to run outside the sandbox prompts you instead. To be prompted on every unsandboxed retry even in auto mode, add an [ask rule](permissions.md#match-by-input-parameter) for `Bash(dangerouslyDisableSandbox:true)`. You can disable this escape hatch by setting `"allowUnsandboxedCommands": false` in your [sandbox settings](settings-reference.md#sandbox-settings). With the escape hatch disabled, Claude Code ignores the `dangerouslyDisableSandbox` parameter, and every command Claude runs must run sandboxed unless you’ve listed it in `excludedCommands`. The `/sandbox` **Overrides** tab shows this setting as **Strict sandbox mode**. Strict sandbox mode applies to the commands Claude runs. Commands you type yourself at the [`!` shell-mode prompt](interactive-mode.md#shell-mode-with-prefix) run outside the sandbox unless the session is one of these:
- **A [background session](../09-Agents-Patterns/agent-view.md)**: strict sandbox mode covers shell-mode commands too
- **A Linux session with [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](env-vars.md#variables) set**: every command runs sandboxed, shell-mode commands included
Before v2.1.260, strict sandbox mode sandboxed shell-mode commands in every session.
[](#temporary-directories)
Temporary directories
A per-user temp directory is writable inside the sandbox by default, alongside the working directory. Unless you [disable filesystem isolation](#disable-filesystem-isolation), Claude Code sets `$TMPDIR` to this directory for sandboxed commands, so tools that write temporary files work without extra configuration. Unsandboxed commands inherit your shell’s `$TMPDIR` when it is set, so while filesystem isolation is on, sandboxed and unsandboxed commands resolve `$TMPDIR` to different directories. If your shell leaves `$TMPDIR` unset or empty, an unsandboxed command that references `$TMPDIR` receives your [`CLAUDE_CODE_TMPDIR`](env-vars.md) override, or the operating system’s temp directory when you haven’t set one or the override is a long path, so the variable doesn’t expand to an empty string. To pass temporary files between the two, write them under the working directory instead.
[](#configure-sandboxing)
Configure sandboxing
Customize sandbox behavior through your `settings.json` file. See [Settings](settings-reference.md#sandbox-settings) for the complete configuration reference. By default, sandboxed commands can write to the current working directory, the per-user temp directory, and any [directories you’ve added](permissions.md#additional-directories-grant-file-access-not-configuration) with `--add-dir`, `/add-dir`, or `permissions.additionalDirectories`. If subprocess commands like `kubectl`, `terraform`, or `npm` need to write outside those directories, use `sandbox.filesystem.allowWrite` to grant access to specific paths:
```python
{
"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 you define the same filesystem array in multiple [settings scopes](settings.md#settings-precedence), Claude Code merges them, combining paths from every scope rather than replacing one scope’s array with another’s. If you exclude a source with [`--setting-sources`](cli-reference.md) on the CLI or [`settingSources`](../05-Agent-SDK/agent-sdk-claude-code-features.md#control-filesystem-settings-with-settingsources) in the Agent SDK, Claude Code ignores its `sandbox.filesystem` entries, its `Edit` permission rules, and its `Read` deny rules when building the sandbox configuration. Requires Claude Code v2.1.246 or later. When you edit these filesystem lists during a session, Claude Code [applies the change to the running session](settings.md#when-edits-take-effect), so the next sandboxed command runs under the new paths. 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` |
This syntax differs from [Read and Edit permission rules](permissions.md#read-and-edit), which use `//path` for absolute and `/path` for project-relative. Sandbox filesystem paths use standard conventions: `/tmp/build` is absolute. For how Claude Code treats a trailing slash or a wildcard in these paths, see [Sandbox path prefixes](settings-reference.md#sandbox-path-prefixes). You can also deny write or read access using `sandbox.filesystem.denyWrite` and `sandbox.filesystem.denyRead`, and re-allow specific paths within a denied region using `sandbox.filesystem.allowRead`. When read rules overlap, the rule with the narrower path applies:
| Example rules | Result |
|:--------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `"denyRead": ["~/"]` with `"allowRead": ["~/projects"]` | `~/projects` is readable and the rest of the home directory stays blocked. The narrower allow re-opens that part of the denied region |
| `"allowRead": ["~/"]` with `"denyRead": ["~/.env"]` | `~/.env` stays blocked and the rest of the home directory is readable. The deny holds inside a wider allow, so a broad allow can’t silently re-expose a secret |
| `"allowRead": ["~/"]` with `"denyRead": ["~/**/.env"]` | Every `.env` under the home directory stays blocked and the rest is readable. A [wildcard deny](settings-reference.md#sandbox-path-prefixes) holds inside a wider allow the same way an exact path does |
The example below blocks reading from the entire home directory while still allowing reads from the current project. Place it in your project’s `.claude/settings.json`, because the relative path `.` resolves to the project root only when the configuration lives in project settings:
```python
{
"sandbox": {
"enabled": true,
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."]
}
}
}
```
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. To deny sandboxed commands read access to home directories and mounted volumes while keeping the working directories readable, set [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) instead of writing path rules.
[](#disable-filesystem-isolation)
Disable filesystem isolation
Set `sandbox.filesystem.disabled` to `true` to skip filesystem isolation while keeping network isolation. The example below turns off filesystem isolation while keeping an allowlist of network domains:
```python
{
"sandbox": {
"enabled": true,
"filesystem": {
"disabled": true
},
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
```
The sandbox has two independent layers: [filesystem isolation](#filesystem-isolation) controls which paths sandboxed commands can read and write, and [network isolation](#network-isolation) controls which domains they can reach. With the filesystem layer off, sandboxed commands get unrestricted read and write access to the host filesystem, while their network egress stays confined to your allowed domains. Turn the layer off when you sandbox to control where commands connect rather than what they write. The setting is off by default and applies on the platforms where the sandbox runs: macOS, Linux, and WSL2. Requires Claude Code v2.1.216 or later.
With filesystem isolation off and commands auto-allowed, a sandboxed command can write files that later commands run or read, such as shell startup files, executables on `$PATH`, or `~/.claude/settings.json`, and use them to widen its own access on the next run. Set `filesystem.disabled` to `true` only for workloads you trust not to escalate their own access. Locking network domains with [`allowManagedDomainsOnly`](#keep-developers-from-widening-the-policy) narrows the risk but doesn’t remove it, since that lock applies only to commands running inside the sandbox.
[](#which-settings-can-disable-it)
Which settings can disable it
Because turning filesystem isolation off widens what sandboxed commands can do, Claude Code honors `filesystem.disabled` from these settings sources only:
- User settings, managed settings, and the `--settings` CLI flag can set it. Project settings in `.claude/settings.json` and `.claude/settings.local.json` can’t, so a checked-out project can’t switch filesystem isolation off.
- When managed settings configure `sandbox.filesystem` at all, or list any `sandbox.credentials.files` entry with `"mode": "deny"`, only managed settings can set the key. This keeps administrator-deployed filesystem restrictions in force; to relax such a deployment, set `"disabled": true` in managed settings.
- When [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](env-vars.md) is set, Claude Code ignores `filesystem.disabled` from every source, including managed settings, and keeps filesystem isolation on.
Whether a managed `credentials.files` entry pins `filesystem.disabled`, locking the key to managed settings so developers can’t turn filesystem isolation off, depends on the entry’s `mode` and what happens to the entry when the sandbox starts:
| Managed entry | Pins `filesystem.disabled` | What protects the file when isolation is off |
|---------------------------------------------------------------------------------------------------------------------|------------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| `"mode": "deny"` | Yes | Nothing: the read block is part of the filesystem layer |
| `"mode": "mask"`, applied as a mask | No | Masking itself: the [sentinel copy and proxy](#mask-credential-files) on Linux and WSL2, the sandbox’s own read rules on macOS |
| `"mode": "mask"`, [fallen back to `deny`](#mask-credential-files) at setup | No | Nothing, same as `deny`. List a path that can’t be masked, such as a directory, as an explicit `deny` entry, which pins the key |
| `"mode": "mask"`, [degraded to `deny` by validation](../13-Enterprise-Admin/managed-settings.md#invalid-entries-in-managed-settings) | Yes, like an explicit `deny` | Nothing, same as `deny` |
A fallback happens when the sandbox starts, after Claude Code has already read the settings the pin check runs on, so a fallen-back entry never pins. Validation rewrites an invalid entry to `deny` while settings load, so a degraded entry pins like one you wrote as `deny`.
[](#what-changes-when-filesystem-isolation-is-off)
What changes when filesystem isolation is off
Setting `filesystem.disabled` lifts the protections the filesystem layer itself enforces. Protections that other layers enforce keep applying:
| Protection | With filesystem isolation off |
|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `filesystem.denyRead` and [`credentials.files`](#protect-credentials) `deny` read blocks | Not enforced. The filesystem layer applies both |
| `credentials.envVars` `deny` and `mask` entries | Enforced. Environment variable scrubbing is independent of the filesystem layer |
| [`credentials.files` `mask` entries](#mask-credential-files) applied as masks | Enforced: masking is independent of the filesystem layer. An entry that [fell back to `deny`](#mask-credential-files) is not enforced, like any `deny` entry |
Two other things change:
- Sandboxed commands inherit your shell’s `$TMPDIR` instead of the per-user temp directory, because every temp directory is writable and Claude Code no longer redirects commands to the per-user one. On Linux the variable is often unset in the parent shell. The Bash tool guidance tells Claude to create scratch directories with `mktemp -d` instead of relying on `$TMPDIR`.
- [`autoAllowBashIfSandboxed`](settings-reference.md#sandbox-autoallowbashifsandboxed) still defaults to `true`, so sandboxed commands keep running without prompts. Set it to `false` to prompt for sandboxed commands.
[](#protect-credentials)
Protect credentials
The `sandbox.credentials` setting declares credential files and environment variables to protect from sandboxed commands. Each entry names a file path or an environment variable and a `mode`. The dedicated `credentials` block keeps credential rules grouped together and separate from general filesystem rules. For entries with `"mode": "deny"`, file paths are denied for reads inside the sandbox, the same restriction that `filesystem.denyRead` applies, and environment variables are unset before each sandboxed command runs. The file protection is part of the filesystem layer, so it doesn’t apply if you [disable filesystem isolation](#disable-filesystem-isolation); the environment variable protection still does. The example below blocks reads of the AWS credentials file and the SSH directory and removes `GITHUB_TOKEN` and `NPM_TOKEN` from the environment of sandboxed commands:
```python
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "NPM_TOKEN", "mode": "deny" }
]
}
}
}
```
Environment variable entries and file entries also accept `"mode": "mask"`, described under [Mask credentials](#mask-credentials). File paths follow the same [prefix rules](settings-reference.md#sandbox-path-prefixes) as `sandbox.filesystem.*` settings. Claude Code merges the `deny` entries from every [settings scope](settings.md#settings-precedence) the session loads. A `deny` entry only ever narrows access, so any scope can add one, but no scope can remove one that another scope added. When you [exclude a settings source](#configure-sandboxing):
- **Project or local settings**: Claude Code applies none of their `credentials` entries. Requires Claude Code v2.1.246 or later.
- **User settings**: Claude Code still applies the `deny` entries in `~/.claude/settings.json` and keeps its [file `mask` entries](#mask-credential-files) as restrictions, but drops its [environment variable `mask` entries](#mask-environment-variables).
There is no built-in credential deny list, so only the files and variables you list are restricted. `sandbox.credentials` affects sandboxed Bash commands only. To strip credentials from all subprocesses regardless of sandboxing, set [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](env-vars.md).
[](#mask-credentials)
Mask credentials
Masking goes further than a `deny` entry under [Protect credentials](#protect-credentials). Instead of blocking a credential, Claude Code shows sandboxed commands a placeholder, the sentinel, and the [sandbox proxy](#network-isolation) swaps in the real value on outbound requests to hosts you allow. For files, the substitution is Linux and WSL2 behavior; [macOS blocks the file instead](#mask-credential-files).
[](#mask-environment-variables)
Mask environment variables
`"mode": "mask"` protects a credential while keeping the tools that authenticate with it working. `deny` removes the variable entirely, which also breaks tools that need it, such as `gh` or `npm`. Requires Claude Code v2.1.199 or later. With `mask`, the sandboxed command sees a per-session sentinel value instead of the real one. Each `mask` entry can list `injectHosts`, the hosts the real value is allowed to reach. When a request leaves the sandbox for one of them, the [sandbox proxy](#network-isolation) replaces the sentinel with the real value. The command and anything it logs never hold the real credential, but its requests still authenticate. The proxy substitutes the credential inside request contents, so it has to see them. Set [`network.tlsTerminate`](settings-reference.md#sandbox-network-tlsterminate) so the proxy terminates TLS itself. Without it, masking fails without exposing anything: the command still sees only the sentinel, but the sentinel reaches the server unchanged and authentication fails. Claude Code reports this misconfiguration at startup. Substitution covers headers and request bodies. Requests that authenticate with a signature derived from the credential, rather than the credential itself, need re-signing at the proxy; [Re-sign AWS requests](#re-sign-aws-requests) covers how that works for AWS. The proxy injects only on connections the [domain allowlist](#network-isolation) admits, so each `injectHosts` destination must also be reachable through `network.allowedDomains`. The example below masks two tokens. `GH_TOKEN` is substituted only on requests to `api.github.com`, while `NPM_TOKEN` has no `injectHosts` and is substituted on requests to every host in `network.allowedDomains`.
```python
{
"sandbox": {
"enabled": true,
"network": {
"tlsTerminate": {},
"allowedDomains": ["*.github.com", "registry.npmjs.org"]
},
"credentials": {
"envVars": [
{ "name": "GH_TOKEN", "mode": "mask", "injectHosts": ["api.github.com"] },
{ "name": "NPM_TOKEN", "mode": "mask" }
]
}
}
}
```
Spell an IPv6 destination differently in the two lists, because each list has its own matcher:
- **`network.allowedDomains`**: the [bracketed form domain lists use](#ipv6-addresses-in-domain-lists), such as `"[::1]"`. The proxy checks this list to admit the connection.
- **`injectHosts`**: the bare address in its canonical compressed form, such as `"::1"` or `"2001:db8::1"`. The proxy matches each entry against the connection’s bare destination address, ignoring ports, so a bracketed, zone-ID, or differently compressed spelling never matches and the proxy never injects the credential there.
`claude doctor` flags `injectHosts` entries that can never match with the warning `Sandbox credential injectHosts entries can never match their destination`. This check requires Claude Code v2.1.229 or later. Unlike `deny`, masking authorizes the proxy to send your real credential to the listed hosts, so Claude Code honors it only from settings you or your administrator control: user settings, managed settings, and the `--settings` CLI flag. Claude Code ignores `mask` entries in a repository’s `.claude/settings.json` or `.claude/settings.local.json`. In those files it also ignores `network.tlsTerminate` and [`credentials.allowPlaintextInject`](settings-reference.md#sandbox-credentials-allowplaintextinject), the setting that lets the proxy inject credentials into unencrypted requests. If you [exclude user settings](#configure-sandboxing), Claude Code drops the environment variable `mask` entries in `~/.claude/settings.json` too. When your administrator delivers `mask` entries, `network.tlsTerminate`, or `credentials.allowPlaintextInject` through server-managed settings, they count as [settings that need approval](../13-Enterprise-Admin/server-managed-settings.md#security-approval-dialogs). When the same variable is listed with `deny` in any scope, `deny` takes precedence. Masking replaces the variable’s entire value by default, which suits a bare token. Optional entry fields, which require Claude Code v2.1.224 or later, handle values with structure:
- `extract`: a regular expression Claude Code applies across the value, replacing only the text captured by group 1 of each match, so a tool that parses the value, such as a `DATABASE_URL` connection string, still works inside the sandbox. The pattern must contain at least one capturing group.
- `onExtractNoMatch` controls what happens when the pattern matches nothing:
- `warn`, the default, warns and passes the variable through unmasked
- `deny` unsets the variable inside the sandbox
- `error` stops sandbox setup until you fix the configuration
- `decode: "jwt"`: for a variable holding a JSON Web Token (JWT). Claude Code verifies the value is a JWT and replaces it with a structurally valid fake token, so code inside the sandbox that decodes the token keeps working. Add `maskClaims` to list top-level payload claims to mask individually instead of replacing the whole token; the other claims stay readable. When the value doesn’t verify as a JWT, or no listed claim matches, Claude Code passes the variable through unmasked with a warning. `decode` can’t be combined with `extract`.
See the [`credentials.envVars[]` rows in the settings reference](settings-reference.md#sandbox-settings) for the full field list.
[](#re-sign-aws-requests)
Re-sign AWS requests
AWS requests carry SigV4 signatures over the request contents, so mask `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` together. The proxy detects a SigV4 request by the access key’s sentinel and re-signs it after substituting the real values. Masking the secret alone leaves requests signed with the placeholder, which the proxy can’t detect, so they fail at AWS; Claude Code warns about this case at startup, but not when only the access key ID is masked. A detected request the proxy can’t re-sign, such as one missing its `x-amz-date` header, fails with a proxy error instead of reaching the server with a broken signature. Claude Code links the conventional `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` variables into one credential automatically when you mask their whole values. If your AWS credential lives in variables with other names, group them yourself with [`credentials.awsPairs`](settings-reference.md#sandbox-credentials-awspairs), which requires Claude Code v2.1.224 or later. This example adds the pairing to a configuration that already masks `MY_KEY_ID`, `MY_SECRET_KEY`, and `MY_SESSION_TOKEN` whole-value, as in the [masking configuration above](#mask-environment-variables):
```python
{
"sandbox": {
"credentials": {
"awsPairs": [
{
"accessKeyIdVar": "MY_KEY_ID",
"secretAccessKeyVar": "MY_SECRET_KEY",
"sessionTokenVar": "MY_SESSION_TOKEN"
}
]
}
}
}
```
Each entry follows these rules:
- `accessKeyIdVar` and `secretAccessKeyVar` name the masked `envVars` entries holding the access key ID and the secret key. The optional `sessionTokenVar` names the entry holding the session token for temporary credentials; when set, the proxy sends the real token as `x-amz-security-token` on re-signed requests.
- Each named variable must be a `mask` entry that masks its entire value, without `extract` or `decode`.
- The proxy re-signs requests on the hosts listed in the access key ID entry’s `injectHosts`.
- Naming any of the conventional variables in a pair replaces the automatic pairing.
Like `mask` entries, `awsPairs` is honored only from user settings, managed settings, and the `--settings` CLI flag. Three AWS request forms carry signatures the proxy can’t recompute. When such a request is signed with a masked pair’s placeholder, the proxy fails it rather than forward a broken signature; requests signed with unmasked credentials are never affected. The [`credentials.sigv4`](settings-reference.md#sandbox-credentials-sigv4) setting, which requires Claude Code v2.1.224 or later, relaxes this per form: setting a form’s key to `passthrough` forwards the request with its placeholder-derived signature, so the calling tool receives AWS’s own rejection response instead of a proxy error. Like `awsPairs`, `sigv4` is honored only from user settings, managed settings, and the `--settings` CLI flag.
| Request form | `sigv4` key | Why the proxy can’t re-sign it |
|:------------------------------|:------------|:--------------------------------------------------------------------------------------------------|
| aws-chunked streaming uploads | `streaming` | Per-chunk signatures chain off the seed signature, so re-signing would require rewriting the body |
| Presigned URLs | `presigned` | The signature lives in the URL itself, with no `Authorization` header |
| SigV4A asymmetric signatures | `sigv4a` | There is no shared-key HMAC to recompute |
[](#mask-credential-files)
Mask credential files
File entries also accept `"mode": "mask"`, which requires Claude Code v2.1.221 or later. What a sandboxed command sees depends on the platform:
- **Linux and WSL2**: sandboxed commands read a sentinel copy of the file, a stand-in whose secret is replaced with a placeholder value, and the [sandbox proxy](#network-isolation) substitutes the real value on egress.
- **macOS**: sandboxed commands can’t read the listed file at all. Claude Code builds no sentinel copy and substitutes nothing on egress, so tools that authenticate with the file don’t work inside the sandbox, the same effect as `deny`. Unlike a `deny` entry, the read block holds even when you [disable filesystem isolation](#disable-filesystem-isolation).
On every platform, Claude Code applies the [`network.tlsTerminate`](settings-reference.md#sandbox-network-tlsterminate) requirement and `injectHosts` the same way as for [masked environment variables](#mask-environment-variables), and ignores repository settings the same way. If you [exclude user settings](#configure-sandboxing), Claude Code keeps the file `mask` entries in `~/.claude/settings.json` as restrictions, but the entries no longer authorize the proxy to substitute the real value. The example below masks a GitHub token stored in `~/.config/gh/hosts.yml`; the `extract` pattern, covered below, tells Claude Code which part of the file is the secret. On Linux and WSL2, sandboxed commands that read the file get a sentinel in place of the token, and the proxy substitutes the real token on requests to `api.github.com`:
```python
{
"sandbox": {
"enabled": true,
"network": {
"tlsTerminate": {},
"allowedDomains": ["*.github.com"]
},
"credentials": {
"files": [
{
"path": "~/.config/gh/hosts.yml",
"mode": "mask",
"extract": "oauth_token:\\s*(\\S+)",
"injectHosts": ["api.github.com"]
}
]
}
}
}
```
To confirm the mask is active, ask Claude to run `cat ~/.config/gh/hosts.yml` in a sandboxed command: on Linux and WSL2 the output shows a sentinel value in place of the token, and on macOS the read fails instead. On Linux and WSL2, the `extract` pattern is what keeps the rest of `hosts.yml` readable. Claude Code applies the regular expression across the whole file and replaces only the text captured by group 1 of each match, so `gh` still parses its config and only the token is a placeholder. Use `extract` for any structured file that tools parse, such as `.netrc`, JSON, or YAML; the pattern must contain at least one capturing group. Without `extract`, Claude Code replaces the entire file content with one sentinel value, which suits a file that holds a single bare secret and nothing else. For a file that holds a JSON Web Token (JWT), set `decode: "jwt"` instead of, or together with, `extract`. `decode` requires Claude Code v2.1.224 or later. Claude Code finds JWT candidates with a built-in pattern, or with your `extract` pattern when set, verifies each candidate is a JWT, and replaces it with a structurally valid fake token, so code that decodes the token inside the sandbox keeps working. Add `maskClaims` to mask only the named top-level payload claims inside each verified token and leave the other claims readable. When no candidate verifies, or no named claim matches, the `onExtractNoMatch` field below governs the outcome, as it does for a pattern that matches nothing. Two optional fields refine how matching behaves. Both apply only when `mode` is `mask` and `extract` or `decode` is set. On macOS, Claude Code applies `mask` entries as `deny` before the pattern runs whenever filesystem isolation is on, so these fields, and the no-match outcomes below, take effect there only when [filesystem isolation is off](#disable-filesystem-isolation):
- `onExtractNoMatch` controls what happens when matching finds nothing to mask in the file:
- `warn`, the default, warns and skips the entry, so sandboxed commands can read the real file unmasked. The default suits credentials that may be legitimately absent; if the secret might be present but the pattern might miss it, use `deny`
- `deny` makes the file unreadable instead
- `error` stops sandbox setup until you fix the configuration
Claude Code treats `deny` as `error` whenever the read block wouldn’t be enforced: when you [disable filesystem isolation](#disable-filesystem-isolation), and when a `filesystem.allowRead` entry from any settings source re-opens the file’s path.
- `maskDuplicates` also replaces verbatim copies of each masked credential value, an `extract` capture or a `decode`-verified token, found outside the matched spans, for a secret repeated where matching doesn’t reach. It matches raw substrings, so a short or common value would be replaced everywhere it appears; reserve it for long, high-entropy secrets. Default: false.
`mask` applies to a single file, so list each credential file individually. Claude Code falls back to `deny` for a `mask` entry it can’t mask safely: a directory path, a glob pattern, a file larger than 8 MiB, or a file that isn’t UTF-8 text. Write directories as explicit `deny` entries instead; the table under [Which settings can disable it](#which-settings-can-disable-it) covers whether each form pins `filesystem.disabled` and how it behaves with filesystem isolation off.
[](#how-sandboxing-works)
How sandboxing works
[](#filesystem-isolation)
Filesystem isolation
The sandboxed Bash tool restricts file system access to specific directories:
- **Default write behavior**: read and write access to the current working directory and its subdirectories, any directories you’ve added with `--add-dir`, `/add-dir`, or [`permissions.additionalDirectories`](settings-reference.md#permissions-additionaldirectories), plus the per-user temp directory that `$TMPDIR` points to
- **Default read behavior**: read access to the entire computer, except certain denied directories. Note that this default still allows reading credential files such as `~/.aws/credentials` and `~/.ssh/`. Use [`sandbox.credentials`](#protect-credentials) to block reads of these files and unset secret environment variables, or add the paths to `denyRead`.
- **Read block**: with [`permissions.blockReadsOutsideWorkingDirectories`](settings-reference.md#permissions-blockreadsoutsideworkingdirectories) on, sandboxed commands also lose read access to your home directory and the other directories that hold user files, apart from the paths that [Sandboxed commands under the block](settings-reference.md#sandboxed-commands-under-the-block) lists. That section also says when this part of the block doesn’t apply.
- **Blocked access**: cannot modify files outside the working directory, added directories, and the per-user temp directory without explicit permission, including shell configuration files such as `~/.bashrc` and system binaries in `/bin/`
- **Git worktrees**: when the working directory is a [linked git worktree](worktrees.md), the sandbox also allows writes to the main repository’s shared `.git` directory so commands such as `git commit` can update refs and the index. Writes to `hooks/` and `config` inside that directory remain denied.
- **Configurable**: define custom allowed and denied paths through settings
To skip filesystem isolation entirely while keeping network isolation, set [`sandbox.filesystem.disabled`](#disable-filesystem-isolation).
[](#protected-paths)
Protected paths
Inside the directories that sandboxed commands can write to, the sandbox still denies writes to the files Claude Code loads configuration and code from. A command that could edit those files could grant itself permissions, or add a hook or MCP server that Claude Code runs outside the sandbox. The permission system has its own [protected paths](permission-modes.md#protected-paths), which control what Claude Code approves before a tool runs; the sandbox’s list applies to a command that is already running. It covers four groups of paths:
- **In your working directory and the directories above it**: the `.claude` settings files, the `.claude/skills`, `.claude/agents`, `.claude/commands`, and `.claude/hooks` directories, `.mcp.json`, and the files Claude Code runs on its own, such as `.claude/workflows` and `.claude/scheduled_tasks.json`
- **In your working directory only**: shell startup files such as `.bashrc` and `.zshrc`, `.gitconfig`, the `.vscode` and `.idea` directories, and `hooks` and `config` inside `.git`
- **Files that would turn your working directory into a bare git repository**: `HEAD`, `objects`, and `refs` at the top level, plus existing `config` and `hooks` entries there when a `HEAD` sits beside them. A file named `config` is denied even with no `HEAD`. On Linux and WSL2, the sandbox deletes a top-level `HEAD` file or `objects` or `refs` directory that appears while a sandboxed command is running
- **In `~/.claude`, or the directory `CLAUDE_CONFIG_DIR` points to**: most of its contents, plus `~/.claude.json` and the `.credentials.json` credential store
If a symlink appears at a protected settings file’s path during the session, the sandbox also denies writes to the file it points to, starting with the next command. There is no way to exempt one of these paths: an `allowWrite` entry or an `Edit` allow rule that covers the path doesn’t lift the protection. The only way to turn the protection off is [`filesystem.disabled`](#disable-filesystem-isolation), which turns off filesystem isolation for every path. To see most of these paths resolved for your machine, run `/sandbox` and open the **Config** tab, which lists them under **Denied within allowed**, mixed in with your own `denyWrite` entries. If `git merge` or `git checkout` fails with `unable to unlink old` on one of these paths, see [Troubleshooting](#troubleshooting).
[](#network-isolation)
Network isolation
Network access is controlled through a proxy server running outside the sandbox:
- **Domain restrictions**: Claude Code pre-allows no domains by default. The first time a command needs a new domain, Claude Code prompts for approval; in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), Claude instead names the hosts a command needs on the command itself, per [Per-command allowed domains](#per-command-allowed-domains-in-auto-mode).
- **Approval choices**: if you choose Yes when prompted, Claude Code allows the host for the rest of the current session and doesn’t prompt again for later connections to the same host. If you choose “Yes, and don’t ask again”, Claude Code saves a `WebFetch(domain:...)` allow rule to your [local settings](permissions.md#permission-system), so the host stays allowed in future sessions.
- **Pre-allowed domains**: pre-allow domains with [`allowedDomains`](settings-reference.md#sandbox-network-alloweddomains) to avoid the prompt entirely. Claude Code also pre-allows domains from `WebFetch(domain:...)` allow rules, as described in [Permission rules](#permission-rules).
- **Strict allowlist**: if you set [`strictAllowlist`](settings-reference.md#sandbox-network-strictallowlist) to `true` in user, managed, or CLI `--settings` settings, Claude Code denies sandboxed commands access to any host outside the allowlist instead of prompting. The allowlist is the same one the sandbox otherwise prompts against: `allowedDomains` plus domains from `WebFetch(domain:...)` allow rules, or only the managed settings entries when `allowManagedDomainsOnly` is set. Claude Code enforces this for sandboxed commands only; in-process tools such as `WebFetch` still follow their [permission rules](#permission-rules). Setting it in a repository’s `.claude/settings.json` or `.claude/settings.local.json` has no effect. Requires Claude Code v2.1.219 or later.
- **Managed lockdown**: if [`allowManagedDomainsOnly`](settings-reference.md#sandbox-network-allowmanageddomainsonly) is set in managed settings, non-allowed domains are blocked automatically instead of prompting, and only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings are honored.
- **Corporate proxy**: when your network requires outbound traffic to go through a corporate proxy, set `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` as [proxy configuration](../13-Enterprise-Admin/network-config.md#proxy-configuration) describes, in the `env` block of your settings so that [background agents](../13-Enterprise-Admin/network-config.md#set-network-variables-in-settings-not-the-shell) get them too, or in the environment you launch Claude Code from. Claude Code enforces the domain allowlist and then tunnels allowed connections through that upstream proxy.
- **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
In a `WebFetch(domain:...)` rule, the sandbox honors two wildcard forms: a leading `*.`, such as `*.example.com`, and a bare `*`. The bare `*` form requires Claude Code v2.1.186 or later. A wildcard in any other position, such as `WebFetch(domain:example.*)`, still matches fetches but has no effect on sandboxed commands.
The built-in proxy enforces the allowlist based on the requested hostname and, by default, does not terminate or inspect TLS traffic. The experimental [`network.tlsTerminate`](settings-reference.md#sandbox-network-tlsterminate) setting, available in Claude Code v2.1.199 and later, makes the built-in proxy terminate TLS itself, which [`mask` credential entries](#mask-credentials) require. See [Security limitations](#security-limitations) for the implications of the default, and [Custom proxy configuration](#custom-proxy-configuration) if your threat model requires TLS inspection.
[](#per-command-allowed-domains-in-auto-mode)
Per-command allowed domains in auto mode
In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) with sandboxing on, Claude names the hosts a command needs on the command itself instead of triggering a network approval for each connection. Each Bash, PowerShell, or [Monitor](tools-reference.md#monitor-tool) command that runs in the sandbox can carry a list of hosts beyond the sandbox’s allowlist: a domain such as `registry.npmjs.org`, a wildcard such as `*.pythonhosted.org`, or an IP address, each with an optional `:port`. The classifier reviews the hosts together with the command. Requires Claude Code v2.1.271 or later. An approved list opens those hosts for that one command alone, for as long as it runs. Nothing is added to your session’s allowed hosts or your settings; the next command names its own hosts. A command that carries hosts goes to the classifier instead of being approved by a permission rule or the sandbox’s [auto-allow mode](#sandbox-modes). If an [ask rule](permissions.md#manage-permissions) forces a prompt for the command, the permission dialog in your terminal lists the hosts beside it, and approving there covers both. A per-command list widens only what the sandbox denies by default. [`deniedDomains`](settings-reference.md#sandbox-network-denieddomains) entries still block. When [`strictAllowlist`](settings-reference.md#sandbox-network-strictallowlist) or [`allowManagedDomainsOnly`](settings-reference.md#sandbox-network-allowmanageddomainsonly) locks the allowlist, Claude Code refuses per-command lists. While per-command lists apply, Claude Code refuses a connection to a host that no approved command listed, without a prompt or a classifier check. The refusal names the host in the command’s result, and Claude re-runs the command with the host added.
[](#ipv6-addresses-in-domain-lists)
IPv6 addresses in domain lists
The sandbox’s domain lists are `allowedDomains`, `deniedDomains`, and the `WebFetch(domain:...)` rules that feed them. To match an IPv6 address in any of them, write the literal in brackets: `"[::1]"` matches that address on every port, and `"[::1]:443"` matches it on port 443 only. Write the port as a number from 1 to 65535 with no leading zeros. The bracketed form requires Claude Code v2.1.229 or later. Before v2.1.229, when the text after an unbracketed entry’s last colon was a port number, Claude Code read it as one, so `::1:443` named the address `::1` on port 443. When you choose “Yes, and don’t ask again” at the network approval prompt for an IPv6 address, Claude Code saves the `WebFetch(domain:...)` rule with the address bracketed, so the rule keeps matching the address in future sessions. An unbracketed entry with two or more colons is ambiguous: `::1:443` is both a complete IPv6 address and an address followed by a port. Claude Code enforces ambiguous spellings conservatively instead of guessing which reading you meant:
- **Deny lists**: Claude Code denies every reading the entry parses as, so whichever reading you meant is blocked. For an entry with no parseable reading, Claude Code blocks nothing.
- **Allow lists**: Claude Code never allows more than you wrote. It rewrites an ambiguous entry to its host-and-port reading when that reading parses cleanly, and may drop the entry entirely rather than widen the allowlist.
Run `claude doctor` in your terminal to find the affected entries: the `Sandbox network domain entries have unreliable spellings` warning names up to three of them and counts the rest. Rewrite each one in the bracketed form to clear the warning. The warning also names entries whose spelling is unreliable for other reasons, such as `@`, path or query characters, or wildcards inside brackets.
[](#os-level-enforcement)
OS-level enforcement
The sandboxed Bash tool uses operating system security primitives:
- **macOS**: uses Seatbelt for sandbox enforcement
- **Linux**: uses [bubblewrap](https://github.com/containers/bubblewrap) for isolation
- **WSL2**: uses bubblewrap, same as Linux
WSL1 is not supported because bubblewrap requires kernel features only available in WSL2. These same primitives are available as the standalone [`@anthropic-ai/sandbox-runtime`](https://github.com/anthropic-experimental/sandbox-runtime) package, which the [Sandbox environments](sandbox-environments.md#sandbox-runtime) page covers as a separate approach for wrapping the entire Claude Code process.
[](#how-sandboxing-relates-to-permissions-and-permission-modes)
How sandboxing relates to permissions and permission modes
Sandboxing, [permission rules](permissions.md), and [permission modes](permission-modes.md) are complementary layers. The sections below cover how the sandbox interacts with each.
[](#permission-rules)
Permission rules
Permission rules and sandboxing control different things:
- **Permission rules** control which tools Claude Code can use and are evaluated before any tool runs. They apply to every tool: Bash, Read, Edit, WebFetch, MCP, and others, except that a deny or ask rule can’t block [`EndConversation`](tools-reference.md#endconversation-tool-behavior) while any other tool remains.
- **Sandboxing** provides OS-level enforcement that restricts what shell commands can access at the filesystem and network level. It applies only to Bash, PowerShell, and [Monitor](tools-reference.md#monitor-tool) commands and their child processes.
The two layers also differ in how they are enforced. Claude Code evaluates permission decisions before a command runs, based on the command string and, in auto mode, a separate classifier’s judgment about whether the command is safe. The operating system enforces the sandbox boundary on the running process, so it holds regardless of what the model chose to run and even if an allowed command does more than its name suggests. Filesystem and network restrictions are configured through both sandbox settings and permission rules:
| Setting or rule | What it does |
|:-----------------------------------------------------------------|:--------------------------------------------------------------------------------------------------|
| `sandbox.filesystem.allowWrite` | Grants subprocess write access to paths outside the working directory |
| `sandbox.filesystem.denyWrite` and `sandbox.filesystem.denyRead` | Block subprocess access to specific paths |
| `sandbox.filesystem.allowRead` | Re-allows reading specific paths within a `denyRead` region |
| [`sandbox.filesystem.disabled`](#disable-filesystem-isolation) | Turns the filesystem layer off entirely while keeping network isolation |
| `Edit` allow rules | Grant write access to specific paths, the same way `sandbox.filesystem.allowWrite` does |
| `Read` and `Edit` deny rules | Block access to specific files or directories |
| `WebFetch(domain:...)` allow and deny rules | Control domain access |
| Sandbox `allowedDomains` | Controls which domains Bash commands can reach |
| Sandbox `deniedDomains` | Blocks specific domains even when a broader `allowedDomains` wildcard would otherwise permit them |
Paths and domains from both sandbox settings and permission rules are merged into the final sandbox configuration. The [claude-code repository’s examples directory](https://github.com/anthropics/claude-code/tree/main/examples/settings) includes starter settings configurations for common deployment scenarios, including sandbox-specific examples. Use these as starting points and adjust them to fit your needs.
[](#permission-modes)
Permission modes
`/sandbox` is not a [permission mode](permission-modes.md). Permission modes decide whether a tool call runs and whether you are prompted first, while the sandbox restricts what a Bash command can access once it runs. They differ in what they control and what replaces the per-action prompt:
| | What it controls | What replaces the prompt |
|:------------------------------------------------------------------------|:--------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/sandbox` | What a Bash command can access once it runs | The sandbox boundary itself, in [auto-allow mode](#sandbox-modes) |
| [Auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) | Whether each tool call runs | A classifier that reviews actions |
| `--dangerously-skip-permissions` | Whether each tool call runs | Nothing. [Protected path](permission-modes.md#protected-paths) checks are also skipped; the [actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) still apply |
The sandbox’s [auto-allow mode](#sandbox-modes) is separate from [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode): auto-allow approves Bash commands because the sandbox boundary contains them, while auto mode uses a classifier to review actions. The two work independently and can be combined, with the exceptions listed under [Sandbox modes](#sandbox-modes). To choose an isolation boundary for unattended runs, see [Sandbox environments](sandbox-environments.md#how-isolation-relates-to-permission-modes). For a table of common permission mode and sandbox pairings with the flags that start each one, see [Common setups](permission-modes.md#common-setups).
[](#configure-the-sandbox-for-your-organization)
Configure the sandbox for your organization
Administrators can require sandboxing for every user, keep developers from widening the policy, and route sandbox traffic through a corporate proxy.
[](#enforce-sandboxing-with-managed-settings)
Enforce sandboxing with managed settings
To require the sandbox for every developer, deliver the `sandbox` keys through [managed settings](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms), either as a file managed by your MDM or through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) on claude.ai. The following managed settings configuration enables the sandbox, refuses to start Claude Code if the sandbox cannot initialize, and prevents the model from retrying commands outside the sandbox:
```python
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false
}
}
```
The two keys beyond `enabled` control what happens when the sandbox cannot run a command:
- **`failIfUnavailable`**: a missing dependency such as bubblewrap on Linux blocks Claude Code from starting rather than showing a warning and falling back to unsandboxed execution
- **`allowUnsandboxedCommands: false`**: Claude Code ignores the `dangerouslyDisableSandbox` escape hatch, so when a command fails under the sandbox, Claude can’t retry it unsandboxed
Two additions are worth considering alongside them. Add `excludedCommands` for any organization-approved tools that must run without isolation. Add [`sandbox.credentials`](#protect-credentials) entries for credential directories such as `~/.aws` and `~/.ssh` and for secret environment variables, since the default read policy still allows them. This configuration sandboxes the commands Claude runs. A developer can still type a command at the [`!` shell-mode prompt](interactive-mode.md#shell-mode-with-prefix) and run it outside the sandbox, with the same access they already have in any terminal outside Claude Code. See [The unsandboxed retry escape hatch](#the-unsandboxed-retry-escape-hatch) for the sessions where typed commands run sandboxed. The sandbox does not run on native Windows, so if your fleet includes Windows hosts, scope this configuration to macOS and Linux or have those users run Claude Code inside WSL2 or a container.
[](#keep-developers-from-widening-the-policy)
Keep developers from widening the policy
For boolean keys such as `enabled` and `failIfUnavailable`, Claude Code uses the managed value and ignores anything a developer sets locally. For array keys such as `excludedCommands` and `allowRead`, Claude Code merges entries from every scope the session loads, so a developer can append entries that widen the policy. Set `allowManagedReadPathsOnly` to `true` in managed settings so that only `allowRead` entries from managed settings are honored. This prevents developers from widening read access beyond the organization-approved paths. To lock network domains to the managed values the same way, set [`allowManagedDomainsOnly`](settings-reference.md#sandbox-network-allowmanageddomainsonly). When managed settings configure `sandbox.filesystem` or list any `sandbox.credentials.files` entry with `"mode": "deny"`, only managed settings can set [`filesystem.disabled`](#disable-filesystem-isolation), so developers can’t switch off administrator-deployed filesystem restrictions. Whether a `mask` entry pins the key depends on how it resolves; the table under [Which settings can disable it](#which-settings-can-disable-it) covers the four cases. `excludedCommands` has no equivalent managed-only lockdown, so a developer can always append entries that run additional commands outside the sandbox. Keep the managed list narrow.
[](#custom-proxy-configuration)
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
To point Claude Code at your proxy, set the proxy ports in [sandbox settings](settings-reference.md#sandbox-settings):
```python
{
"sandbox": {
"network": {
"httpProxyPort": 8080,
"socksProxyPort": 8081
}
}
}
```
[](#troubleshooting)
Troubleshooting
Some commands fail inside the sandbox even though they work outside it. The fixes below cover the most common cases.
- **Commands fail with a host-not-allowed error**: many CLI tools need to reach specific hosts. Granting permission when prompted adds the host to your allowed list so the tool runs inside the sandbox in future.
- **`jest` hangs or fails**: `watchman` is incompatible with the sandbox. Run `jest --no-watchman` instead.
- **Go-based CLIs fail TLS verification on macOS**: tools such as `gh`, `gcloud`, and `terraform` may fail TLS verification under Seatbelt. List these tools in [`excludedCommands`](settings-reference.md#sandbox-excludedcommands). If you are using `httpProxyPort` with a MITM proxy and custom CA, set [`enableWeakerNetworkIsolation`](settings-reference.md#sandbox-enableweakernetworkisolation) to `true` instead.
- **`open`, `osascript`, or browser-based auth flows fail with error `-600` on macOS**: the sandbox blocks Apple Events by default. Set [`allowAppleEvents`](settings-reference.md#sandbox-allowappleevents) to `true` in your user, managed, or CLI settings to allow them. Project settings are ignored for this key. Enabling it removes code-execution isolation, since sandboxed commands can then launch other applications unsandboxed with no user prompt and send AppleScript commands to running applications, subject to the macOS automation-consent prompt (TCC). Alternatively, add the command to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands).
- **`docker` commands fail**: `docker` is incompatible with the sandbox. Add `docker *` to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands).
- **`pbcopy`, `xclip`, or `wl-copy` doesn’t update the clipboard**: these clipboard utilities can fail to reach the system clipboard from inside the sandbox, in which case the text piped to them doesn’t arrive. To put Claude’s output on your clipboard, ask Claude to print it in its response, then run [`/copy`](commands.md). `/copy` writes to the clipboard from the Claude Code process rather than from a sandboxed command. When Claude pipes text to one of these tools, adding the tool to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands) doesn’t take that call out of the sandbox on its own.
- **A git command fails with `unable to unlink old`**: `git merge`, `git checkout`, and similar commands fail this way when they need to replace a file the sandbox denies writes to, whether that file is under a [protected path](#protected-paths) such as `.claude/skills`, under one of your `denyWrite` entries, or outside the directories the sandbox lets commands write to at all. On Linux and WSL2 the error ends with `Read-only file system`. After the failure, Claude may [offer to rerun the command outside the sandbox](#the-unsandboxed-retry-escape-hatch); approve that retry, or run the git command yourself in another terminal. If you’ve set `allowUnsandboxedCommands` to `false`, Claude can’t offer the retry, so run the command yourself. If the same git command fails often, add it to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands).
- **Bubblewrap fails to start inside a container**: in an unprivileged container, bubblewrap can’t mount a fresh `/proc` filesystem, so sandboxed commands fail with a `bwrap` error such as `Can't mount proc on /newroot/proc: Operation not permitted`. Set [`enableWeakerNestedSandbox`](settings-reference.md#sandbox-enableweakernestedsandbox) to `true` so the inner sandbox bind-mounts the container’s existing `/proc` instead. Only use this setting when the outer container already provides the isolation boundary you need, since it exposes process information to sandboxed commands that a fresh `/proc` mount would hide.
- **0-byte read-only files appear at `.claude` settings paths, and “Yes, and don’t ask again” doesn’t save**: on Linux and WSL2, the sandbox holds a write denial on a file that doesn’t exist yet by creating a 0-byte read-only placeholder there while a sandboxed command runs. The sandbox removes the placeholder afterward. If a session is killed before that cleanup runs, for example by SIGKILL, the placeholders stay behind. Later sessions bind them read-only again on every start, so a settings write such as saving a permission choice fails where one sits. Run `claude doctor` to list the leftover placeholder files. The [`Stale sandbox mask files left by a killed session`](errors.md#stale-sandbox-mask-files-left-by-a-killed-session) warning names up to three of them and counts the rest. Delete each file with `rm` while no other Claude Code session is running in that project. Before v2.1.257, Claude Code left the same placeholders behind without flagging them.
- **`--dangerously-skip-permissions` fails as root**: this flag is blocked when running as root or via sudo on Linux and macOS, because root access combined with no permission prompts can modify any file or service on the system. The check is skipped automatically inside a recognized sandbox. To run autonomously in a container, use the [dev container](devcontainer.md) configuration, which runs Claude Code as a non-root user.
[](#limitations)
Limitations
Sandboxing reduces risk but is not a complete isolation boundary. Review the limitations below before relying on it as a hard security control.
[](#security-limitations)
Security limitations
- **Network filtering**: the sandbox restricts which domains processes can connect to. By default the built-in proxy does not terminate or inspect TLS on outbound traffic, so the contents of encrypted connections are not examined. The experimental [`network.tlsTerminate`](settings-reference.md#sandbox-network-tlsterminate) setting terminates TLS at the proxy for [`mask` credential substitution](#mask-credentials) but does not add content filtering. 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 reach hosts outside the allowlist through traffic-shaping techniques. If your threat model requires stronger guarantees, configure a [custom proxy](#custom-proxy-configuration) 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 system services that could lead to sandbox bypasses. For example, allowing access to `/var/run/docker.sock` effectively grants access to the host system through the Docker socket. Consider carefully any Unix sockets that you 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 such as `.bashrc` or `.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 Docker environments without privileged namespaces, or on Linux hosts where unprivileged user namespaces are disabled by sysctl. This option considerably weakens security and should only be used when additional isolation is otherwise enforced.
- **Apple Events on macOS**: the macOS sandbox blocks Apple Events by default. The `allowAppleEvents` setting lifts this restriction so tools such as `open` and `osascript` work, but it removes code-execution isolation: sandboxed commands can launch other applications unsandboxed with no user prompt, and can send AppleScript commands to running applications, subject to the per-app macOS automation-consent prompt (TCC). It is only honored from user, managed, or CLI settings. Project settings cannot enable it.
[](#platform-and-tool-compatibility)
Platform and tool compatibility
- **Platform support**: supports macOS, Linux, and WSL2. WSL1 and native Windows are not supported.
- **Performance overhead**: minimal, but some filesystem operations may be slightly slower.
- **Tool compatibility**: some tools that require specific system access patterns may need configuration adjustments, or may need to be run outside the sandbox.
[](#scope)
Scope
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](permissions.md).
- **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](computer-use.md) or [computer use in Desktop](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer).
- **Environment variables**: sandboxed Bash commands inherit the parent process environment by default, including any credentials set there. Use [`sandbox.credentials`](#protect-credentials) to unset or mask specific variables for sandboxed commands, or set [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](env-vars.md) to strip credentials from all subprocesses.
- **Subagents**: [subagents](../09-Agents-Patterns/sub-agents.md) run in the same process as the parent session and use the same sandbox configuration. Bash commands inside a subagent are sandboxed when sandboxing is enabled in the parent session.
Effective sandboxing requires both filesystem and network isolation. Without network isolation, a compromised agent could exfiltrate sensitive files like SSH keys. Without filesystem isolation, whether from a permissive policy or from [disabling the filesystem layer](#disable-filesystem-isolation), a compromised agent could backdoor system resources to gain network access. When you widen the defaults, check that an `allowWrite` path, a broad `allowedDomains` entry, or an `excludedCommands` exception does not undo a restriction on the other side.
[](#see-also)
See also
- [Sandbox environments](sandbox-environments.md): compare the built-in sandbox with dev containers, containers, and VMs
- [Security](../13-Enterprise-Admin/security.md): comprehensive security features and best practices
- [Permissions](permissions.md): permission configuration and access control
- [All settings](settings-reference.md): every settings key
- [CLI reference](cli-reference.md): command-line options
---
## Run prompts on a schedule - Claude Code Docs
Source: https://code.claude.com/docs/en/scheduled-tasks
Path: 02-Claude-Code-CLI/scheduled-tasks.md
## On this page
- [Compare scheduling options](#compare-scheduling-options)
- [Run a prompt repeatedly with /loop](#run-a-prompt-repeatedly-with-%2Floop)
- [Run on a fixed interval](#run-on-a-fixed-interval)
- [Let Claude choose the interval](#let-claude-choose-the-interval)
- [Run the built-in maintenance prompt](#run-the-built-in-maintenance-prompt)
- [Customize the default prompt with loop.md](#customize-the-default-prompt-with-loop-md)
- [Stop a loop](#stop-a-loop)
- [Set a one-time reminder](#set-a-one-time-reminder)
- [Manage scheduled tasks](#manage-scheduled-tasks)
- [How scheduled tasks run](#how-scheduled-tasks-run)
- [Jitter](#jitter)
- [Seven-day expiry](#seven-day-expiry)
- [Cron expression reference](#cron-expression-reference)
- [Disable scheduled tasks](#disable-scheduled-tasks)
- [Limitations](#limitations)
Automation
# Run prompts on a schedule
Copy pageCopy page
Use /loop and the cron scheduling tools to run prompts repeatedly, poll for status, or set one-time reminders within a Claude Code session.
Copy pageCopy page
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](channels.md): your CI can push the failure into the session directly. To keep the session working turn after turn toward a condition rather than on an interval, see [`/goal`](goal.md). Tasks are session-scoped: they live in the current conversation and stop when you start a new one. When you resume with `--resume` or `--continue`, Claude Code restores tasks that haven’t [expired](#seven-day-expiry), except those listed under [Limitations](#limitations). For scheduling that survives independently of any session, use [Routines](web-scheduled-tasks.md) to create a routine on the cloud, set up a [Desktop scheduled task](../16-Mobile-Desktop/desktop-scheduled-tasks.md), or use [GitHub Actions](github-actions.md).
[](#compare-scheduling-options)
Compare scheduling options
Claude Code offers three ways to schedule recurring or one-off work:
| | [Cloud](web-scheduled-tasks.md) | [Desktop](../16-Mobile-Desktop/desktop-scheduled-tasks.md) | [`/loop`](scheduled-tasks.md) |
|:---------------------------|:------------------------------------|:--------------------------------------------|:--------------------------------------------------------------------------------|
| Runs on | Cloud, Anthropic-managed by default | Your machine | Your machine |
| Requires machine on | No | Yes | Yes |
| Requires open session | No | No | Yes |
| Persistent across restarts | Yes | Yes | Restored on `--resume`, with [exceptions](scheduled-tasks.md#limitations) |
| Access to local files | No (fresh clone) | Yes | Yes |
| MCP servers | Connectors configured per task | [Config files](../06-MCP-Tools/General/mcp.md) 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)
Run a prompt repeatedly with /loop
The `/loop` [bundled skill](commands.md) 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](#run-on-a-fixed-interval) |
| Prompt only | `/loop check the deploy` | Your prompt runs at an [interval Claude chooses](#let-claude-choose-the-interval) each iteration |
| Interval only, or nothing | `/loop` | The [built-in maintenance prompt](#run-the-built-in-maintenance-prompt) runs, or your `loop.md` if one exists |
You can also pass a skill as the prompt, for example `/loop 20m /review-pr 1234`, to re-run that skill each iteration. A scheduled fire only runs skills that Claude is [allowed to invoke on its own](../08-Plugins-Skills/skills.md#control-who-invokes-a-skill). The following reach Claude as plain text instead of executing:
- Built-in commands such as `/permissions`, `/model`, or `/clear`
- Skills marked [`disable-model-invocation: true`](../08-Plugins-Skills/skills.md#frontmatter-reference), including the bundled `/verify` skill
- Skills withheld from Claude by a [`skillOverrides`](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) setting or a `Skill` [deny rule](../08-Plugins-Skills/skills.md#restrict-claude%E2%80%99s-skill-access)
- [MCP prompts](../06-MCP-Tools/General/mcp.md#use-mcp-prompts-as-commands) such as `/mcp__github__list_prs`
[](#run-on-a-fixed-interval)
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.
```python
/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)
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:
```python
/loop check whether CI passed and address any review comments
```
In a session where the [Monitor tool is available](tools-reference.md#monitor-tool), Claude may use it directly when you ask for a dynamic `/loop` schedule. 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](#manage-scheduled-tasks) like any other task, so you can list or cancel it the same way. The [jitter rules](#jitter) don’t apply to it, but the [seven-day expiry](#seven-day-expiry) does.
Dynamically chosen intervals and the [built-in maintenance prompt](#run-the-built-in-maintenance-prompt) work on every provider, and with [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching) turned off. On Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, and Microsoft Foundry, or with fetching turned off, both require Claude Code v2.1.248 or later. In those cases, on earlier versions, a prompt with no interval runs on a fixed 10-minute schedule, and a `/loop` with no prompt prints the usage message.
[](#run-the-built-in-maintenance-prompt)
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.
```python
/loop
```
A bare `/loop` runs this prompt at a [dynamically chosen interval](#let-claude-choose-the-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](#customize-the-default-prompt-with-loop-md).
[](#customize-the-default-prompt-with-loop-md)
Customize the default prompt with loop.md
Create a `loop.md` file to replace the [built-in maintenance prompt](#run-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 Claude Code ignores it whenever you supply a prompt on the command line. To schedule additional prompts alongside it, use `/loop <prompt>` or [ask Claude directly](#manage-scheduled-tasks). 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
```python
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)
Stop a loop
To stop a [self-paced `/loop`](#let-claude-choose-the-interval) 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](#manage-scheduled-tasks) are not affected by `Esc` and stay in place until you delete them. In [self-paced mode](#let-claude-choose-the-interval), Claude can also end the loop on its own once the task is complete. Claude calls the [`ScheduleWakeup` tool](tools-reference.md) with `stop: true`, which cancels the pending wakeup immediately. If an iteration ends without either rescheduling or stopping, Claude Code schedules one fallback wakeup about 20 minutes later and ends the loop when that iteration doesn’t reschedule either. Loops on a fixed interval keep running until you [cancel them like any other scheduled task](#manage-scheduled-tasks) or [seven days elapse](#seven-day-expiry).
[](#set-a-one-time-reminder)
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.
```python
remind me at 3pm to push the release branch
```
```python
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)
Manage scheduled tasks
Ask Claude in natural language to list or cancel tasks, or reference the underlying tools directly.
```python
what scheduled tasks do I have?
```
```python
cancel the deploy check job
```
These are the underlying tools Claude uses:
| 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)
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)
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)
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](web-scheduled-tasks.md) or [Desktop scheduled tasks](../16-Mobile-Desktop/desktop-scheduled-tasks.md) for durable scheduling.
[](#cron-expression-reference)
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)
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](env-vars.md) for the full list of disable flags.
[](#limitations)
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. [Backgrounding the session](../09-Agents-Patterns/agent-view.md#from-inside-a-session) carries `/loop` tasks over to a background session, which keeps running without a terminal.
- 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. When you resume a session with `claude --resume` or `claude --continue`, Claude Code restores the tasks scheduled with `CronCreate`, except recurring tasks that have [expired](#seven-day-expiry) and one-shot tasks whose scheduled time has passed. A [self-paced `/loop`](#let-claude-choose-the-interval) isn’t restored, so run `/loop` again to restart it. Background Bash and monitor tasks are never restored on resume.
- With [feature-flag fetching off](env-vars.md#features-that-need-feature-flag-fetching), Claude Code stores a task you asked to keep across sessions in the project’s `.claude/scheduled_tasks.json` file. When the `.claude` directory or that file is a symlink, Claude Code returns an error instead of scheduling the task. A saved task runs only in the project folder where you created it. If you copy the file into another folder, such as a new worktree, sessions there list the copied tasks but don’t run them, so create the task again in that folder.
For cron-driven automation that needs to run unattended:
- [Routines](web-scheduled-tasks.md): run in the cloud on a schedule, via API call, or on GitHub events
- [GitHub Actions](github-actions.md): use a `schedule` trigger in CI
- [Desktop scheduled tasks](../16-Mobile-Desktop/desktop-scheduled-tasks.md): run locally on your machine
---
## Catch security issues as Claude writes code - Claude Code Docs
Source: https://code.claude.com/docs/en/security-guidance
Path: 02-Claude-Code-CLI/security-guidance.md
## On this page
- [Prerequisites](#prerequisites)
- [Install the plugin](#install-the-plugin)
- [Enable for your team in local sessions](#enable-for-your-team-in-local-sessions)
- [What the plugin checks](#what-the-plugin-checks)
- [On each file edit](#on-each-file-edit)
- [At the end of each turn](#at-the-end-of-each-turn)
- [On each commit or push Claude makes](#on-each-commit-or-push-claude-makes)
- [Review independence and limits](#review-independence-and-limits)
- [Add your own rules](#add-your-own-rules)
- [Add guidance for the model-backed reviews](#add-guidance-for-the-model-backed-reviews)
- [Add custom per-edit patterns](#add-custom-per-edit-patterns)
- [Rule file lookup locations](#rule-file-lookup-locations)
- [Usage cost](#usage-cost)
- [Disable or uninstall](#disable-or-uninstall)
- [How the plugin integrates with Claude Code](#how-the-plugin-integrates-with-claude-code)
- [How this fits with other security tools](#how-this-fits-with-other-security-tools)
- [Troubleshooting](#troubleshooting)
- [Related resources](#related-resources)
Code review & CI/CD
# Catch security issues as Claude writes code
Copy pageCopy page
Install the security-guidance plugin to have Claude review its own code changes for vulnerabilities and fix them in the same session.
Copy pageCopy page
The security guidance plugin makes Claude review its own code changes for common vulnerabilities while it works and fix what it finds in the same session. The plugin catches issues such as injection, unsafe deserialization, and unsafe DOM APIs before the code reaches a pull request, reducing how much security review falls to human reviewers downstream. Once installed, the plugin runs automatically. There is nothing to invoke and no separate command to remember. The plugin is the in-session companion to [Code Review](code-review.md), which runs on pull requests. This plugin reduces what reaches the PR. Code Review catches what does. For how the plugin layers with on-demand review and CI scanning, or to scan code you already have rather than changes Claude is writing, see [How this fits with other security tools](#how-this-fits-with-other-security-tools).
[](#prerequisites)
Prerequisites
- Python 3.7 or later on your `PATH`. The agentic commit review needs Python 3.10 or later, as do all model-backed reviews when Claude Code uses a third-party provider such as Amazon Bedrock or Google Cloud’s Agent Platform. The plugin prefers the versioned interpreters `python3.13` through `python3.10`, then falls back to `python3`, `python`, and `py -3`
- A git repository for the directory you work in. The end-of-turn and commit reviews diff against git state and skip silently outside a repository. The per-edit pattern check works anywhere
On first run the plugin creates a virtual environment under `~/.claude/security/` and installs the Claude Agent SDK into it, which requires `pip` and network access. If that install fails, or the available Python is older than 3.10, the commit review on first-party authentication falls back to a single-shot review instead of the agentic one; on a third-party provider such as Amazon Bedrock or Google Cloud’s Agent Platform the model-backed reviews need the SDK themselves, so they skip. The plugin shows a one-time notice when an older Python is the cause.
[](#install-the-plugin)
Install the plugin
In a terminal Claude Code session, install from the [official Anthropic marketplace](../08-Plugins-Skills/plugins-anthropic-marketplaces.md):
```python
/plugin install security-guidance@claude-plugins-official
```
`/plugin` opens an interactive panel in the terminal CLI. If Claude replies that `/plugin` isn’t available in this environment, install another way:
- **Claude desktop app, local or SSH session**: open the [plugin browser](../16-Mobile-Desktop/desktop.md#install-plugins) by clicking the **+** button next to the prompt, then **Plugins**, then **Add plugin**
- **VS Code extension**: install from the [**Manage plugins** dialog](../03-IDE-Integrations/vs-code.md#manage-plugins)
- **Cloud sessions**: a cloud session doesn’t load plugins from your user settings or from the repository’s `.claude/settings.json`, as [What carries over from your setup](cloud-environments.md#what-carries-over-from-your-setup) explains. For plugins your organization distributes through managed settings, see [Manage plugins for your organization](../08-Plugins-Skills/plugins-org.md)
The terminal install prompts for a scope. Choose user scope to write the plugin to your user settings, so it loads in every new local session you start on this machine. If the install fails, match the message Claude Code reports:
- `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
- The plugin is [not found in the marketplace](../08-Plugins-Skills/discover-plugins.md#install-a-plugin): check the plugin name.
Check the install summary. If it reports `Run /reload-plugins to activate.`, see [Apply plugin changes without restarting](../08-Plugins-Skills/plugins-cli-reference.md#reload-plugins) to activate the plugin in your current session.
[](#enable-for-your-team-in-local-sessions)
Enable for your team in local sessions
To turn the plugin on in the local sessions your teammates start in the repository, declare it in the project’s checked-in settings:
.claude/settings.json
```python
{
"enabledPlugins": {
"security-guidance@claude-plugins-official": true
}
}
```
Administrators can enable the plugin organization-wide by setting [`enabledPlugins`](settings-reference.md#enabledplugins) in [managed settings](../13-Enterprise-Admin/admin-setup.md).
[](#what-the-plugin-checks)
What the plugin checks
The plugin reviews Claude’s work at three points, each at a different depth:
- [On each file edit](#on-each-file-edit): a fast pattern match for risky calls, with no model call
- [At the end of each turn](#at-the-end-of-each-turn): a background model review of everything that turn changed
- [On each commit or push Claude makes](#on-each-commit-or-push-claude-makes): a deeper agentic review that reads surrounding code
You can extend each layer by [adding your own rules](#add-your-own-rules). Built-in checks cannot be removed individually, but you can [disable each layer](#disable-or-uninstall) independently.
[](#on-each-file-edit)
On each file edit
When Claude writes to a file, the plugin scans the new content for known risky patterns. This is a pattern match with no model call, so it adds no usage cost. Example pattern categories:
- Dynamic code execution: `eval(`, `new Function`, `os.system`, `child_process.exec`
- Unsafe deserialization: `pickle`
- DOM injection: `dangerouslySetInnerHTML`, `.innerHTML =`, `document.write`
- Workflow files: edits under `.github/workflows/`, which can grant repository-level permissions
The check runs after the edit lands and appends the warning to Claude’s context for the next step. Each warning fires once per pattern per file per session, so repeat matches in the same file do not flood the conversation. You can [add your own patterns](#add-custom-per-edit-patterns) to this layer with a `security-patterns.yaml` file.
[](#at-the-end-of-each-turn)
At the end of each turn
A turn is one round of Claude responding: you send a message, Claude works and replies, and the turn ends. After each turn, the plugin computes a git diff of everything that changed in the working tree during the turn, including changes from Claude’s edit tools, Bash commands, and subagents, and sends it to a separate Claude review focused on security. The review runs in the background, so Claude’s reply is not delayed. If the review finds issues, Claude is re-prompted with the findings and addresses them as a follow-up. This catches issues a string match cannot, such as:
- Authorization bypass
- Insecure direct object references
- Injection
- Server-side request forgery
- Weak cryptography
You see both the finding and Claude’s resolution directly in your session. The review covers up to 30 changed files per turn and fires at most three times in a row before yielding back to you.
[](#on-each-commit-or-push-claude-makes)
On each commit or push Claude makes
When Claude runs `git commit` or `git push` through its Bash tool, the plugin runs a deeper agentic review of the change in the background. This review reads surrounding code, including callers, sanitizers, and related files, to decide whether a finding is real before reporting it. The extra context keeps false positives low on patterns that look dangerous in isolation but are safe in your codebase. This layer fires only on commits and pushes Claude makes through its Bash tool. Commits you run from your own shell, including the `!` shell escape inside a session, are not reviewed. Commit and push reviews are capped at 20 per rolling hour. If the commit review’s findings duplicate what the end-of-turn review already reported, Claude is not re-prompted, so a clean commit produces no visible output from this layer.
[](#review-independence-and-limits)
Review independence and limits
The plugin does not ask the same Claude instance that wrote the code to grade itself. The per-edit check is a deterministic string match with no model involved. The end-of-turn and commit reviews run as a separate Claude call with a fresh context and a security-focused prompt: the reviewer starts from the diff, has no investment in the original approach, and is instructed only to find problems. None of the layers block writes or commits. Findings reach the writing Claude as instructions, Claude addresses them in the conversation, and the review model can miss issues. Treat the plugin as one layer of defense in depth, not a complete security solution. See [How this fits with other security tools](#how-this-fits-with-other-security-tools).
[](#add-your-own-rules)
Add your own rules
The plugin has two extension points: a Markdown guidance file for the model-backed reviews, and a YAML or JSON patterns file for the per-edit string match. Both are additive. You can add checks but cannot disable built-in ones from these files.
[](#add-guidance-for-the-model-backed-reviews)
Add guidance for the model-backed reviews
Create `.claude/claude-security-guidance.md` in your project and describe your threat model and review checklist in plain language. The model-backed reviews load it as additional context alongside the built-in vulnerability checklist. The following example is for a web service with role-gated admin routes and a customer-data logging policy:
.claude/claude-security-guidance.md
```python
# Security guidance for this repo
- Do not log `customer_id` or `account_number` at INFO level or above.
- All routes under `/admin` must call `require_role("admin")` before any database read.
- Use `crypto.timingSafeEqual` for token comparison instead of `===`.
```
These rules are guidance for the reviewer, not deterministic guardrails. The plugin surfaces violations as findings for Claude to fix, but it does not block writes or guarantee every violation is caught. The guidance is additive only: a rule that says to ignore a vulnerability class does not suppress those findings. For hard enforcement, pair the plugin with a [hook that blocks the edit](../07-Hooks/hooks-guide.md#block-edits-to-protected-files) or a CI check.
[](#add-custom-per-edit-patterns)
Add custom per-edit patterns
Create `.claude/security-patterns.yaml` to add regex or substring rules to the [per-edit pattern check](#on-each-file-edit). These run as deterministic string matches alongside the built-in patterns:
.claude/security-patterns.yaml
```python
patterns:
- rule_name: internal_api_key
substrings: ["sk_live_", "AKIA"]
reminder: "Hardcoded API key prefix. Load credentials from the secret manager."
- rule_name: tenant_unfiltered_query
regex: "\\.objects\\.all\\(\\)"
paths: ["**/src/tenants/**"]
reminder: "Multi-tenant code must filter by org_id."
```
| Field | Type | Description |
|:----------------|:-------|:--------------------------------------------------------------------------------------------------------------------------------------------------------|
| `rule_name` | string | Identifier shown in the warning |
| `reminder` | string | Warning text appended to Claude’s context, capped at 1 KB |
| `regex` | string | Python regex matched against the edited content |
| `substrings` | list | Literal substrings; provide this or `regex` |
| `paths` | list | Optional glob patterns; the rule applies only to matching files. Globs match against the full file path, so prefix project-relative patterns with `**/` |
| `exclude_paths` | list | Optional glob patterns to skip; same matching as `paths` |
The plugin also reads `.claude/security-patterns.yml` and `.claude/security-patterns.json` with the same schema. JSON works on any Python install. The YAML forms require PyYAML to be importable, which the plugin does not install for you. The plugin loads up to 50 custom rules and skips regexes that look prone to catastrophic backtracking.
[](#rule-file-lookup-locations)
Rule file lookup locations
The plugin looks for `claude-security-guidance.md` and `security-patterns.yaml` in the same locations, independently of how the plugin was enabled:
| Scope | Path | Notes |
|:--------------|:--------------------------------------------|:----------------------------------------------------|
| User | `~/.claude/claude-security-guidance.md` | Applies to every project on your machine |
| Project | `.claude/claude-security-guidance.md` | Checked in with the repository |
| Project local | `.claude/claude-security-guidance.local.md` | For personal overrides; add it to your `.gitignore` |
The plugin loads all locations that exist and concatenates them, with a combined cap of 8 KB for the guidance file. Administrators can distribute organization-wide rules by pushing the user-scope file to `~/.claude/` through device management. The same paths apply to `security-patterns.yaml`.
[](#usage-cost)
Usage cost
The [per-edit pattern check](#on-each-file-edit) makes no model call and adds no cost. The [end-of-turn](#at-the-end-of-each-turn) and [commit](#on-each-commit-or-push-claude-makes) reviews each spend additional model usage that counts toward your [usage](../17-Billing-Plans/costs.md) like any other Claude request. The commit review is agentic and may take several model turns per commit. Expect roughly one review call per turn that changes files and one deeper review per commit, both subject to the caps above. Both model-backed reviews use Claude Opus 4.7 by default. Set `SECURITY_REVIEW_MODEL` to choose a different model for the end-of-turn review and `SG_AGENTIC_MODEL` for the commit review. The plugin is available on all plans.
[](#disable-or-uninstall)
Disable or uninstall
To turn off individual layers while keeping the rest, set the matching environment variable:
| Variable | Effect |
|:--------------------------------|:---------------------------------------------------------------------------|
| `ENABLE_PATTERN_RULES=0` | Disable the [per-edit pattern check](#on-each-file-edit) |
| `ENABLE_STOP_REVIEW=0` | Disable the [end-of-turn diff review](#at-the-end-of-each-turn) |
| `ENABLE_COMMIT_REVIEW=0` | Disable the [commit and push review](#on-each-commit-or-push-claude-makes) |
| `ENABLE_CODE_SECURITY_REVIEW=0` | Disable all model-backed reviews at once |
| `SECURITY_GUIDANCE_DISABLE=1` | Disable the plugin entirely without uninstalling |
To pause the plugin in your user scope:
```python
/plugin disable security-guidance@claude-plugins-official
```
To remove it from your user scope:
```python
/plugin uninstall security-guidance@claude-plugins-official
```
If the plugin was enabled through a project’s `.claude/settings.json`, uninstalling it from `/plugin` writes an override to your `.claude/settings.local.json` rather than editing the checked-in file, so the plugin stays off for you while teammates are unaffected. The same dialog also offers to uninstall the plugin for everyone by removing it from the shared `.claude/settings.json`. If it was enabled through [managed settings](../13-Enterprise-Admin/admin-setup.md), only an administrator can disable it.
[](#how-the-plugin-integrates-with-claude-code)
How the plugin integrates with Claude Code
The plugin is built entirely on [hooks](../07-Hooks/hooks.md), the mechanism for running your own code at specific points in Claude’s loop. It registers:
| Hook event | Purpose |
|:-----------------------------------------------------------------|:----------------------------------------------------------------------------|
| `SessionStart` | Bootstrap the plugin’s Python environment |
| `UserPromptSubmit` | Capture the working-tree baseline that the end-of-turn review diffs against |
| `PostToolUse` on `Edit`, `Write`, and `NotebookEdit` | Per-edit pattern match |
| `Stop` | End-of-turn diff review, run in the background |
| `PostToolUse` on `Bash`, filtered to `git commit` and `git push` | Commit and push review, run in the background |
If you build your own hooks, the [plugin’s source](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance) is a working example of running a separate model call from a hook and feeding the result back to the session.
[](#how-this-fits-with-other-security-tools)
How this fits with other security tools
The plugin is one layer in a defense-in-depth approach. It catches issues earliest, while code is still in the editor, but it is not a guarantee and does not replace later checks. A typical stack:
| Stage | Tool | What it covers |
|:-----------------------|:---------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------|
| In session | Security guidance plugin | Common vulnerabilities in code Claude writes, fixed in the same session |
| On demand, single pass | [`/security-review`](commands.md#all-commands) | One-time security pass on the current branch, run when you ask |
| On demand, deep scan | [Claude Security plugin](claude-security.md) | Multi-agent vulnerability scan of a repository or diff, with independently reviewed findings and patches |
| On pull request | [Code Review](code-review.md), Team and Enterprise plans | Multi-agent correctness and security review with full codebase context |
| In CI | Your existing static analysis and dependency scanners | Language-specific rules, supply-chain checks, and policy enforcement the plugin does not attempt |
To find security issues in code you already have, rather than in changes Claude is writing, ask Claude in a session to review a specific file or directory for vulnerabilities, or use the [Claude Security plugin](claude-security.md) for a deeper multi-agent scan of the whole repository; [`/security-review`](commands.md#all-commands) covers only the changes on your current branch. Either way, the review reads the source code in your checkout, not a running site or deployed service.
[](#troubleshooting)
Troubleshooting
The plugin writes runtime diagnostics to `~/.claude/security/log.txt`. Check there first if reviews are not appearing. Common reasons a review layer skips without a message in the conversation:
- The directory is not a git repository: the end-of-turn and commit reviews require git state and skip outside a repository
- The session has no Anthropic authentication and no third-party provider configured: the model-backed reviews skip and only the per-edit pattern check runs
- A `security-patterns.yaml` file is present but PyYAML is not importable: the file is ignored. Use `security-patterns.json` instead
[](#related-resources)
Related resources
To go deeper on the pieces this page touches:
- [Code Review](code-review.md): set up the PR-time multi-agent review
- [Automate actions with hooks](../07-Hooks/hooks-guide.md): build your own checks at the same lifecycle points
- [Find plugins in the official marketplace](../08-Plugins-Skills/plugins-anthropic-marketplaces.md#find-plugins-in-the-official-marketplace): where to browse the other official plugins
---
## Manage sessions - Claude Code Docs
Source: https://code.claude.com/docs/en/sessions
Path: 02-Claude-Code-CLI/sessions.md
## On this page
- [Resume a session](#resume-a-session)
- [What a resumed session restores](#what-a-resumed-session-restores)
- [Permission mode on resume](#permission-mode-on-resume)
- [Resume from a summary](#resume-from-a-summary)
- [Where the session picker looks](#where-the-session-picker-looks)
- [Name your sessions](#name-your-sessions)
- [Use the session picker](#use-the-session-picker)
- [Branch a session](#branch-a-session)
- [Manage context within a session](#manage-context-within-a-session)
- [Export and locate session data](#export-and-locate-session-data)
- [Access conversations from scripts](#access-conversations-from-scripts)
- [Where transcripts are stored](#where-transcripts-are-stored)
- [Delete session data](#delete-session-data)
- [Name the project directory yourself](#name-the-project-directory-yourself)
- [See also](#see-also)
Use Claude Code
# Manage sessions
Copy pageCopy page
Name, resume, branch, and switch between Claude Code conversations. Covers `--continue`, `--resume`, `--from-pr`, the `/resume` picker, session naming, exporting transcripts, and where transcripts are stored.
Copy pageCopy page
A session is a saved conversation tied to a project directory. Claude Code stores it locally as you work, so you can resume where you left off, branch to try a different approach, or switch between tasks. The [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions), [claude.ai/code](claude-code-on-the-web.md), and the [VS Code extension](../03-IDE-Integrations/vs-code.md#resume-past-conversations) each keep their own session list, and the desktop app can also [resume a CLI session](../16-Mobile-Desktop/desktop.md#coming-from-the-cli). This page covers the CLI.
[](#resume-a-session)
Resume a session
Sessions are saved continuously to [local transcript files](#export-and-locate-session-data) as you work, so you can return to one after exiting or running `/clear`. Use these entry points:
| Command | What it does |
|:------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
| `claude --continue` | Reopens the most recent conversation in the current directory |
| `claude --resume` | Opens the [session picker](#use-the-session-picker) |
| `claude --resume <name>` | Resumes the named session directly |
| `claude --resume <transcript-path>` | Resumes the conversation stored in the `.jsonl` [transcript file](#where-transcripts-are-stored) at that absolute path |
| `claude --from-pr <number>` | Opens the session picker filtered to sessions linked to that pull request |
| `/resume` | Switches to a different conversation from inside an active session |
Claude Code leaves sessions created with [`claude -p`](headless.md) or the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) out of the session picker and out of `claude --continue`. You can still resume one by passing its session ID to `claude --resume <session-id>`. With `claude --continue`, Claude Code also skips [sessions whose first prompt was `/loop`](#where-the-session-picker-looks). When you run [`claude -p --continue`](headless.md#continue-conversations), Claude Code includes `-p`, SDK, and `/loop` sessions. `claude --continue` opens a [background session](../09-Agents-Patterns/agent-view.md) that has finished, but not one that is still running; opening finished background sessions requires Claude Code v2.1.257 or later. If your most recent conversation is one you [moved to the background](../09-Agents-Patterns/agent-view.md#send-the-session-to-the-background) and it is still running there, Claude Code exits with `Your most recent conversation is running in the background` and that session’s ID. Attach to the session from [`claude agents`](../09-Agents-Patterns/agent-view.md#attach-to-a-session), or run `claude --resume` to pick another one. You can run `claude --resume <session-id>` from any directory: Claude Code looks for the ID in the current project directory and its git worktrees first, then in every other project on this machine, so it finds a session that started elsewhere or moved with [`/cd`](commands.md). The cross-project search resolves the ID only when exactly one other project holds a transcript with messages for it, so a hand-copied duplicate makes Claude Code report not-found rather than resume an arbitrary copy. If no stored session matches the ID, Claude Code reports `No conversation found with session ID: <session-id>`. Before v2.1.223, the lookup stopped at the current project directory and its git worktrees, so you had to resume from the directory the session last worked in.
[](#what-a-resumed-session-restores)
What a resumed session restores
A resumed session restores the conversation along with the state saved in it:
- Conversation history: the full history, including tool calls and results. A tool that was still running when the previous process ended, for example in a crash, doesn’t finish or run again when you resume. Claude sees the call marked as cut off before its result was recorded and is told to check whether it took effect before running it again, unless [`CLAUDE_CODE_RESUME_INTERRUPTED_TURN`](env-vars.md#variables) is set. Before v2.1.281, Claude Code dropped the cut-off call from the conversation or showed it to Claude as one you interrupted.
- Model: the session continues on the model it was using. The model isn’t restored when it has been retired or isn’t allowed by `availableModels`, when a `--model` flag or `ANTHROPIC_MODEL`-family environment variable picks one at launch, or on providers that use provider-specific deployment IDs, such as [Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry](third-party-integrations.md); see [model configuration](model-config.md#setting-your-model) for the resolution order.
- Agent: a session started with [`--agent`](../09-Agents-Patterns/sub-agents.md#invoke-subagents-explicitly) or the `agent` setting continues as that agent, keeping its tool restrictions and model. Pass `--agent` when resuming to pick a different one; for the system prompt in either case, see [System prompt flags in resumed conversations](cli-reference.md#system-prompt-flags-in-resumed-conversations). Claude Code looks for the agent in two places: the session’s original directory, provided you have [trusted that workspace](permissions.md#project-allow-rules-and-workspace-trust), and then the directory you resume from, so a project-scoped agent still loads when you resume from another directory. If Claude Code doesn’t find the agent in either place, the session resumes with the default tools and shows a [warning naming the agent](errors.md#session-agent-no-longer-available).
- Permission mode: if you resume from a terminal with `claude --continue`, `claude --resume <session-id>`, or `claude --resume <name>` when the name matches one session, without `-p`, Claude Code restores the permission mode the session was in, except in the cases in [permission mode on resume](#permission-mode-on-resume), which also covers the session picker, `/resume`, and resuming with `claude -p`. Pass `--permission-mode` or `--dangerously-skip-permissions` to override the restored mode.
- Active goal: a [goal](goal.md#resume-with-an-active-goal) that was still active when the session ended carries over; its turn count, timer, and token-spend baseline reset.
- Scheduled tasks: [tasks that haven’t expired](scheduled-tasks.md#limitations) are restored. Background Bash and monitor tasks aren’t.
- Background work: a [background subagent](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background), background Bash command, or [workflow](workflows.md) that ended with the previous process shows up in the resumed transcript as a note that it didn’t finish. Claude Code doesn’t start a turn from those notes; Claude reads them with your next prompt.
Not every configuration flag from the original launch is restored. If the session depended on `--mcp-config`, `--settings`, `--plugin-dir`, `--fallback-model`, or directories added with `--add-dir`, pass them again when you resume; directories added mid-session with `/add-dir` aren’t restored either, though the session picker still uses them to locate the session. The standard settings files, such as `settings.json` and `settings.local.json`, are re-read at launch, so configuration that lives in them doesn’t need to be passed again. For `--system-prompt` and `--append-system-prompt`, see [System prompt flags in resumed conversations](cli-reference.md#system-prompt-flags-in-resumed-conversations).
[](#permission-mode-on-resume)
Permission mode on resume
Which permission mode Claude Code starts a resumed session in depends on how you resume:
- Terminal: `claude --continue`, `claude --resume <session-id>`, or `claude --resume <name>` when the name matches one session, without `-p`. Claude Code restores the permission mode the session was in, except in the cases in the table. Pass `--permission-mode` or `--dangerously-skip-permissions` to override the restored mode.
- Non-interactive: `claude -p --resume` or `claude -p --continue`. Claude Code starts the run in the permission mode a new `claude -p` run would start in, except that a session that ended in plan mode resumes in plan mode under the [conditions below](#resume-in-plan-mode-with-p).
- VS Code: the extension’s conversation panel. The table covers only a conversation that ended in plan mode; for the rest, see [resume past conversations](../03-IDE-Integrations/vs-code.md#resume-past-conversations).
- Session picker at launch: a session you select from the [session picker](#use-the-session-picker), whether you opened it with `claude --resume` alone, `claude --from-pr`, or a name that matches more than one session. Claude Code doesn’t restore the stored permission mode. It starts the session in the permission mode it would start a new session in from the same command line.
- `/resume` inside a session, with or without an argument: Claude Code doesn’t restore the stored permission mode. The conversation you switch to continues in the permission mode your current session is in.
Restoring plan mode on the non-interactive and VS Code paths requires Claude Code v2.1.246 or later. Each row names the permission mode the session ended in, which of the terminal, non-interactive, and VS Code paths you resume it by, and the permission mode Claude Code starts the resumed session in.
| Session ended in | How you resume | Permission mode after you resume |
|:--------------------|:---------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `bypassPermissions` | Terminal | The permission mode a new session would start in. To [bypass permissions](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) again, enable it at launch with one of its launch flags or `permissions.defaultMode: "bypassPermissions"` in [user, `--settings`, or managed settings](settings-reference.md#permissions-defaultmode) |
| `plan` | Terminal | The permission mode a new session would start in |
| `auto` | Terminal | `auto`, only when your account still meets the [auto mode requirements](permission-modes.md#eliminate-prompts-with-auto-mode) |
| Manual | Terminal | Manual when a new session would start in auto mode from the [built-in default](permission-modes.md#which-mode-a-session-starts-in). When a `defaultMode` from a settings file [takes effect](permission-modes.md#which-mode-a-session-starts-in), Claude Code starts the resumed session in that mode instead |
| `plan` | Non-interactive, under the [conditions below](#resume-in-plan-mode-with-p) | Plan mode |
| Any mode | Non-interactive, in any other case | The permission mode a new `claude -p` run would start in |
| `plan` | VS Code | Plan mode, with [the exceptions on the VS Code page](../03-IDE-Integrations/vs-code.md#resume-past-conversations) |
A `claude -p --resume` or `claude -p --continue` run resumes in plan mode only when all of these conditions hold:
- You pass [`--permission-prompt-tool`](cli-reference.md#cli-flags) and don’t pass [`--permission-prompts none`](headless.md#turn-off-permission-prompts-in-unattended-runs), so that Claude Code can present the plan for approval
- You don’t pass `--permission-mode` or `--dangerously-skip-permissions`
- You don’t pass `--fork-session`
- The run isn’t started through [channels](channels.md)
[](#resume-from-a-summary)
Resume from a summary
On a Pro or Max plan, when you resume a session that has been inactive for more than about an hour and is over 100,000 tokens, Claude Code restores the conversation and then opens a dialog before you send your first message. The session’s [prompt cache](prompt-caching.md#cache-lifetime) has expired by then, so the next request processes the full history once no matter which of the dialog’s options you pick. The dialog offers three ways to continue the session. They differ in how much of the conversation each one carries forward into later requests, which is a tradeoff between keeping every detail and sending fewer tokens per request:
- **Resume from summary**: runs [`/compact`](context-window.md#what-survives-compaction) immediately. Claude Code sends one summarization request over the full history, then replaces the history with the summary, your most recent exchanges, and up to five recently read files. Later requests carry the summary instead of the full history.
- **Resume full session as-is**: loads the conversation unchanged. After you send your first message, Claude Code reprocesses and re-caches the full history, then re-reads it from the cache on later requests while the cache stays warm.
- **Don’t ask me again**: resumes the full session and stops showing the dialog on all future resumes.
Resuming as-is keeps every detail of the conversation available, at a per-request cost that scales with the conversation’s size. Resuming from the summary costs less on each later request because it carries the summary instead of the full history, but whatever the summary leaves out is no longer in Claude’s context. See [why usage climbs in a long session](../17-Billing-Plans/costs.md#why-usage-climbs-in-a-long-session) for where that per-request cost comes from.
[](#where-the-session-picker-looks)
Where the session picker looks
Claude Code stores sessions per project directory. By default the session picker shows:
- Sessions from the current worktree, including [background sessions](../09-Agents-Patterns/agent-view.md), which are marked `bg` in the list
- Sessions started elsewhere that added the current directory with `/add-dir`
Use `Ctrl+W` to widen to all worktrees of the repository or `Ctrl+A` to widen to every project on this machine. Sessions whose first prompt was a [`/loop`](scheduled-tasks.md#run-a-prompt-repeatedly-with-%2Floop) command don’t appear in the picker, and `claude --continue` skips them too. Running `/loop` later in a conversation doesn’t hide the session. Before v2.1.211, a `/loop` run early in a conversation hid the session from the picker permanently. Moving a session with [`/cd`](commands.md) relocates it to the new directory’s project storage, so it appears in that directory’s picker afterward. As of v2.1.196, a moved session stays out of the old directory’s picker even after a crash or forced exit. On earlier versions, it could also reappear in the old directory’s list after an exit that wasn’t clean when the old path contained special characters such as underscores. When you select a session from another worktree of the same repository, Claude Code resumes it in place; when the session’s own worktree no longer exists, Claude Code [resumes it in your current directory](worktrees.md#resume-a-worktree-session). When you select a session from an unrelated project, Claude Code copies a `cd` and resume command to your clipboard instead. If that project’s directory no longer exists, Claude Code resumes the session in your current directory rather than copying a `cd` command that would fail. Resuming by name resolves across the current repository and its worktrees. Both forms look for an exact match and resume it directly even if it lives in a different worktree:
| Command | Exact match | Ambiguous name |
|:-------------------------|:-----------------|:----------------------------------------------------------------------------|
| `claude --resume <name>` | Resumes directly | Opens the session picker with the name pre-filled as a search term |
| `/resume <name>` | Resumes directly | Reports an error; run `/resume` with no argument to open the session picker |
[](#name-your-sessions)
Name your sessions
Give sessions descriptive names so they’re findable in the session picker and resumable by name. This matters most when you’re working on several tasks in parallel.
| When | How to set the name |
|:---------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| At startup | `claude -n auth-refactor` |
| During a session | `/rename auth-refactor`. The name also appears on the prompt bar |
| From the session picker | Highlight a session and press `Ctrl+R` |
| On plan accept | Accepting a plan in [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) gives the session a generated title based on the plan unless you’ve already named it |
| From claude.ai or the Claude app | Rename a [Remote Control session](remote-control.md#connect-from-another-device); Claude Code applies the same name in the CLI. Requires Claude Code v2.1.221 or later |
| From the desktop app | Rename a session in the [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions) |
Once you name a session through a CLI route or from claude.ai, return to it with `claude --resume <name>` or `/resume <name>`; a desktop-app session resumes in the [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions). See [Resume a session](#resume-a-session) for how name resolution behaves across worktrees. When you start or resume an interactive session with a name that another live session on this machine already uses, or rename a session into such a name, Claude Code leaves the name with the session that already has it, renames yours to a variant with a two-word suffix, such as `auth-refactor-graceful-unicorn`, and tells you. Run `/rename` with a new name if you’d rather pick one yourself. Before v2.1.232, both sessions kept the name. In three cases Claude Code doesn’t rename the duplicate, so you can still see two sessions with the same name in listings:
- It doesn’t check AI-generated titles or default display names.
- It doesn’t check the `--name` of a [background](../09-Agents-Patterns/agent-view.md#from-your-shell) or `-p` session at startup.
- It can’t rename a session on an earlier version of Claude Code.
Sessions you don’t name still get two labels that Claude Code assigns. Only the generated title works as a resume handle:
- Default display name: interactive sessions you never name still get a default display name when they start. Requires Claude Code v2.1.196 or later. The default combines the working directory’s name with a two-character suffix, for example `my-app-3f`, and identifies the session in listings of running sessions, such as [agent view](../09-Agents-Patterns/agent-view.md) and `claude agents --json` output. The default isn’t a resume handle. If you pass it to `claude --resume` or `/resume`, Claude Code doesn’t find the session. Naming the session replaces the default in those listings, and so does accepting a plan.
- Generated title: if you don’t name a session, Claude Code generates a session title for it. The title is a short summary of your first prompt, written by a background request to the small/fast model, normally a Haiku-class model. A `claude -p` run you start directly from a shell or script doesn’t get one. Accepting a plan replaces the generated title with a title based on the plan. Naming the session replaces it as well. You see the first-prompt title in the [session picker](#use-the-session-picker) and in the statusline [`session_name`](statusline.md) field when no name is set. The plan title shows in the same two places and also in the listings of running sessions, where it takes the place of the default display name. You can pass either title to `claude --resume` or `/resume`, and Claude Code resolves it the same way as a name you set.
[](#use-the-session-picker)
Use the session picker
Run `/resume` inside a session, or `claude --resume` with no arguments, to open the interactive session picker. Use these keyboard shortcuts to navigate, search, and widen the list:
| Shortcut | Action |
|:--------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `↑` / `↓` | Navigate between sessions |
| `→` / `←` | Expand or collapse grouped sessions |
| `Enter` | Resume the highlighted session |
| `Space` | Preview the session content. `Ctrl+V` also works on terminals that don’t capture it as paste |
| `Ctrl+R` | Rename the highlighted session |
| `/` or any printable character other than `Space` | Enter search mode and filter sessions. Paste a GitHub, GitHub Enterprise, GitLab, or Bitbucket pull or merge request URL to find the session that created it |
| `Ctrl+A` | Show sessions from all projects on this machine. Press again to return to the current repository |
| `Ctrl+W` | Show sessions from all worktrees of the current repository. Press again to return to the current worktree. Only shown in multi-worktree repositories |
| `Ctrl+B` | Filter to sessions from the current git branch. Press again to show all branches |
| `Esc` | Exit the session picker or search mode |
Each row shows the session name if you set one, otherwise the AI-generated session title, conversation summary, or first prompt, along with time since last activity, git branch, and file size. Widen to all projects with `Ctrl+A` to also see each session’s project path. Sessions created with `/branch` or `--fork-session` get their own session IDs and appear as separate rows. When the picker finds more than one entry for the same session, it groups them under a single row. Press `→` to expand a group. If Claude Code can’t load the session you select from the `claude --resume` picker, it prints [`Failed to resume the conversation`](errors.md#failed-to-resume-the-conversation) with a command to retry, then exits with code 1. From the `/resume` picker inside a session, Claude Code reports the failure and your current conversation keeps running.
[](#branch-a-session)
Branch a session
Branching creates a copy of the conversation so far and switches you into it, leaving the original intact. Use it to try a different approach without losing the path you were on. From inside a session, run `/branch` with an optional name:
```python
/branch try-streaming-approach
```
If you omit the name, Claude Code names the new branch after the first prompt in the conversation. As of v2.1.198 this also applies after [compaction](how-claude-code-works.md#when-context-fills-up); earlier versions fell back to the literal name `Branched conversation` instead of looking past the compaction summary to the original first prompt. From the command line, combine `--continue` or `--resume` with `--fork-session`:
```python
claude --continue --fork-session
```
The `/branch` confirmation prints two session IDs: the new branch you are now in and the original. The original is unchanged on disk and remains in the session picker; return to it with `/resume <original-name>` or by passing its ID to `/resume`. `/branch` copies the transcript and switches the running Claude Code process to write to it. That distinction determines what the branch inherits:
| State | After `/branch` |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Conversation history | Copied into the branch up to the point you ran `/branch` |
| ”Allow for this session” permission grants | Carried over; the branch runs in the same process, so your existing grants still apply. If you fork into a separate process with `--fork-session`, the new process starts without them and you re-approve there |
| In-flight [background subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) and [background Bash commands](interactive-mode.md#background-bash-commands) | Keep running. Their output appears in the new branch you switched into, not in the original session |
| [Remote Control](remote-control.md) connection | Stays connected. A phone or browser connected to the session follows you into the branch and keeps receiving new messages there |
If you resume the same session in two terminals without forking, messages from both interleave into one transcript. For checkpoint-based rewind within a single session, see [Checkpointing](checkpointing.md).
[](#manage-context-within-a-session)
Manage context within a session
These commands control what’s in the context window without leaving the session:
- **`/clear`**: start fresh with an empty context. Claude Code saves the previous conversation; resume it with `/resume`, or, in the same Claude Code process, from [the rewind menu’s previous-session entry](checkpointing.md#rewind-past-a-cleared-conversation). With no argument, the new conversation keeps a name you set with `--name` or `/rename`, but not an AI-generated session title. To name the conversation you’re leaving instead, pass the name, as in `/clear release-prep`; the new conversation then starts unnamed
- **`/compact [instructions]`**: replace history with a summary, optionally focused on what you specify
- **`/context`**: show what is currently consuming context
For how compaction interacts with CLAUDE.md, skills, and rules, see the [context window guide](context-window.md). For strategies on when to clear versus compact, see [Best practices](best-practices.md#manage-your-session).
[](#export-and-locate-session-data)
Export and locate session data
Run `/export` to open a menu that lets you copy the current conversation to your clipboard or save it as a plain-text file, with messages and tool outputs rendered as readable text. Pass a filename to skip the menu and write directly to that file.
[](#access-conversations-from-scripts)
Access conversations from scripts
`/export` produces a rendered transcript for a person to read. The interfaces below produce structured data for a script to parse: a JSON result from a run, the path to a session’s transcript file, or a live stream of events. Pick by what triggers the script:
- **Run Claude once and capture the result**: invoke `claude -p` with [`--output-format json` or `stream-json`](headless.md#get-structured-output) to capture the result, session ID, usage, and cost of a non-interactive run as structured JSON.
- **Ask an existing session a question**: pass a session ID to [`claude -p --resume`](headless.md#continue-conversations) to send a follow-up prompt, such as a summary request, and capture the structured response.
- **React to session events**: read the `transcript_path` field that [hooks](../07-Hooks/hooks.md#common-input-fields) and [status line commands](statusline.md#available-data) receive as input. A `SessionEnd` hook can archive the transcript when a session ends.
- **Embed Claude in a TypeScript or Python app**: use the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) to receive each message programmatically.
The example below uses the second interface. It sends a follow-up prompt to an existing session and reads the answer with `jq`:
```python
claude -p --resume <session-id> --output-format json "summarize what we changed" | jq -r '.result'
```
[](#where-transcripts-are-stored)
Where transcripts are stored
By default, Claude Code stores transcripts as JSONL at `~/.claude/projects/<project>/<session-id>.jsonl`, where `<project>` is your working directory path with non-alphanumeric characters replaced by `-`. For a working directory whose converted name exceeds 200 characters, Claude Code truncates the name to 200 characters and appends a hash of the full path, so the directory name stays within filesystem limits. Each line is a JSON object for a message, tool use, or metadata entry. The entry format is internal to Claude Code and changes between versions, so scripts that parse these files directly can break on any release. To build on session data, use `/export` or the [script interfaces](#access-conversations-from-scripts) instead. The location, retention, and write behavior are configurable:
| To | Set | Where |
|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|--------------------------------------------------|
| Move storage off `~/.claude` | [`CLAUDE_CONFIG_DIR`](env-vars.md) | Environment variable |
| [Name the `<project>` directory yourself](#name-the-project-directory-yourself) | [`CLAUDE_CODE_PROJECT_DIR_NAME`](env-vars.md) | Environment variable |
| Change the 30-day retention | [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays) | `settings.json` |
| Set an age limit for [Claude Desktop and Cowork transcripts](claude-directory.md#cleaned-up-automatically) | [`desktopSessionCleanupPeriodDays`](settings-reference.md#desktopsessioncleanupperioddays) | User settings, managed settings, or `--settings` |
| Suppress transcript writes in all modes | [`CLAUDE_CODE_SKIP_PROMPT_HISTORY`](env-vars.md) | Environment variable |
| Suppress writes for one non-interactive run | [`--no-session-persistence`](cli-reference.md) | CLI flag with `claude -p` |
[](#delete-session-data)
Delete session data
Transcripts age out under the [retention sweep rules](claude-directory.md#cleaned-up-automatically). To delete a project’s transcripts and related state sooner, run [`claude project purge`](claude-directory.md#clear-local-data). If you delete a [background session](../09-Agents-Patterns/agent-view.md) with [`claude rm <id>`](../09-Agents-Patterns/agent-view.md#what-deleting-a-session-removes), its transcript stays on disk and remains available through `claude --resume`.
[](#name-the-project-directory-yourself)
Name the project directory yourself
By default, Claude Code derives the `<project>` name from the whole working directory path. To choose the name yourself, set `CLAUDE_CODE_PROJECT_DIR_NAME` alongside `CLAUDE_CONFIG_DIR`. Claude Code then stores that session’s transcripts and [auto memory](memory.md#auto-memory) under your name. This suits a host that embeds Claude Code and gives each session its own config directory. Requires Claude Code v2.1.234 or later. For example, this launch keeps tenant A’s data under `/srv/tenant-a` and names its project directory `work`:
```python
CLAUDE_CONFIG_DIR=/srv/tenant-a CLAUDE_CODE_PROJECT_DIR_NAME=work claude
```
Claude Code writes the session’s transcripts to `/srv/tenant-a/projects/work/` and its auto memory to `/srv/tenant-a/projects/work/memory/`, whatever the working directory is. Three rules apply when you set it:
- **Set `CLAUDE_CONFIG_DIR` too**: the name doesn’t vary with the working directory, so under the default `~/.claude` it would merge every project’s transcripts and auto memory into one directory. Claude Code ignores `CLAUDE_CODE_PROJECT_DIR_NAME` when `CLAUDE_CONFIG_DIR` is unset.
- **Use 1-64 letters, digits, hyphens, or underscores**: don’t use a Windows device name such as `con`. Claude Code ignores any other value and uses the derived name.
- **Set it in the shell environment that starts `claude`**: Claude Code reads it once at startup from that environment, so an `env` block in a settings file can’t set it.
Once you’ve named a config directory’s project directory, keep launching with that name. If you start Claude Code with the same `CLAUDE_CONFIG_DIR` but without `CLAUDE_CODE_PROJECT_DIR_NAME`, it reads and writes the derived directory again. The sessions stored under your name stay on disk: press `Ctrl+A` in the [session picker](#use-the-session-picker) to list sessions from every project directory under that config directory, the pinned one included, and whichever way you launch, [`claude --resume <session-id>`](#resume-a-session) finds a session stored under either name.
[](#see-also)
See also
These pages cover related session and parallelism mechanics:
- [Worktrees](worktrees.md): run isolated parallel sessions on separate branches
- [Checkpointing](checkpointing.md): rewind code and conversation to an earlier point
- [Context window](context-window.md): what fills context and what survives compaction
- [Non-interactive mode](headless.md): session behavior under `claude -p`
---
## Set up Code Review for Claude Code | Claude Help Center
Source: https://support.claude.com/en/articles/14233555-set-up-code-review-for-claude-code
Path: 02-Claude-Code-CLI/set-up-code-review-for-claude-code.md
# Set up Code Review for Claude Code
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 regressions.
This article covers how to enable Code Review, configure review triggers, customize what gets flagged, and troubleshoot common setup issues.
**Note:** Code Review is in research preview and available on Team and Enterprise plans. It isn’t available for organizations with zero data retention enabled. Code Review usage is billed separately through usage credits and doesn’t count against your plan’s included usage.
------------------------------------------------------------------------
## How Code Review works
Once an organization enables Code Review, it can trigger automatically when a pull request opens, on every push, or only when someone manually requests a review. When a review runs, multiple agents analyze the diff and surrounding code in parallel. Each agent looks for a different class of issue, then a verification step checks results against actual code behavior to filter out false positives.
Findings are deduplicated, ranked by severity, and posted as inline comments on the specific lines where issues were found. If no issues are found, Claude posts a short confirmation comment on the PR. Reviews don’t approve or block your PR, so existing review workflows stay intact.
Reviews scale in cost with PR size and complexity, completing in 20 minutes on average.
### Severity levels
Each finding is tagged with a severity level:
[TABLE]
Findings include a collapsible extended reasoning section you can expand to see why Claude flagged the issue and how it verified the problem.
### 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
The steps below cover setup for repositories on github.com. If your repositories are on a self-hosted GitHub Enterprise Server (GHES) instance, see **[Claude Code with GitHub Enterprise Server](github-enterprise-server.md)** for the full setup guide.
Owners and Primary Owners of Team and Enterprise plans can enable Code Review once for the organization and select which repositories to include. In addition to an owner role within your Claude organization, you’ll need permission to install GitHub Apps in your GitHub organization.
1. Go to **[Organization settings \> Claude Code](https://claude.ai/admin-settings/claude-code)** and find the **Code Review** section.
2. Click “Configure” to begin the GitHub App installation flow.
3. Follow the prompts to install the Claude GitHub App to your GitHub organization. The app requests read and write permissions for contents, issues, and pull requests.
4. Choose which repositories to enable for Code Review. If you don’t see a repository, confirm you gave the Claude GitHub App access to it during installation.
5. Set a review trigger for each repository using the **Review Behavior** dropdown (see the next section for details on each option).
To verify setup, open a test PR. If you chose an automatic trigger, a check run named **Claude Code Review** should appear within a few minutes. If you chose Manual, comment “@claude review” on the PR to start the first review.
------------------------------------------------------------------------
## Choose a review trigger
After setup, the **Code Review** section shows your repositories in a table. For each repository, choose when reviews run:
- **Once after PR creation:** The review runs once when a PR is opened or marked ready for review.
- **After every push:** The review runs on every push to the PR branch, catching new issues as the PR evolves. Claude auto-resolves threads when you fix previously flagged issues. This runs the most reviews and costs the most.
- **Manual:** Reviews start only when someone comments “@claude review” on a PR. Useful for high-traffic repos where you want to select which PRs get reviewed.
The repositories table also shows the average cost per review for each repo based on recent activity.
------------------------------------------------------------------------
## Manually trigger reviews
Comment “@claude review” on a pull request to start a review and opt that PR into push-triggered reviews going forward. This works regardless of the repository’s configured trigger.
For the comment to trigger a review:
- Post it as a top-level PR comment, not an inline comment on a diff line.
- Put “@claude review” at the start of the comment.
- You must have owner, member, or collaborator access to the repository.
- The PR must be open and not a draft.
If a review is already running, the request is queued until the in-progress review completes.
------------------------------------------------------------------------
## Customize reviews
Code Review reads two files from your repository to guide what it flags. Both are additive on top of the default correctness checks.
### CLAUDE.md
Code Review reads your repository’s CLAUDE.md files and treats newly introduced violations as nit-level findings. 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.
### REVIEW.md
Add a REVIEW.md file to your repository root for review-specific rules. Use it to encode:
- Company or team style guidelines
- Language- or framework-specific conventions not covered by linters
- Things Claude should always flag (for example, “any new API route must have an integration test”)
- Things Claude should skip (for example, “don’t comment on generated code”)
Claude auto-discovers REVIEW.md at the repository root. No configuration is needed.
------------------------------------------------------------------------
## Pricing and usage
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 usage credits and doesn’t 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** incurs no cost until someone comments “@claude review.” After that comment, additional pushes to the PR trigger reviews automatically.
Costs appear on your Anthropic bill regardless of whether your organization uses AWS Bedrock or Google Vertex AI for other Claude Code features.
To set a monthly spend cap, go to **[Organization settings \> Usage](https://claude.ai/admin-settings/usage)** and configure the limit for the Claude Code Review service.
Monitor spend via the weekly cost chart in the analytics dashboard or the per-repo average cost column in admin settings.
### View usage
Go to the **[Code Review analytics dashboard](https://claude.ai/analytics/code-review)** to see activity across your organization. The dashboard 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 someone addressed the issue.
- **Repository breakdown:** Per-repo counts of PRs reviewed and comments resolved.
------------------------------------------------------------------------
## Troubleshooting
### Repositories don’t appear after installing the GitHub App
If you’ve installed the Claude GitHub App but your repositories don’t appear in the admin panel:
1. Confirm the Claude GitHub App has access to the repositories you expect. Go to your GitHub organization’s settings, find the Claude GitHub App under **Installed GitHub Apps**, and check whether it has access to all repositories or only selected ones.
2. If your organization uses GitHub Enterprise Cloud with Enterprise Managed Users (EMU), authorize Claude while you're signed in with your managed account and have an active SSO session. There's no separate enterprise-level approval step.
3. Try disconnecting and reconnecting your GitHub account in Claude. Go to **[Customize \> Connectors](https://claude.ai/customize/connectors)**, disconnect GitHub, and connect it again. Which repositories the App can access is managed on GitHub's side, covered in step 1.
4. If the issue persists, **[contact our Support team](https://support.claude.com/en/articles/9015913-how-to-get-support)** with your organization name and GitHub organization name so we can investigate.
### Code Review doesn’t start on a new PR
If no check run appears after opening a PR:
- Confirm the repository is listed and enabled in your admin settings.
- Check the review trigger setting. If it’s set to Manual, you’ll need to comment “@claude review” on the PR to start a review.
- Make sure the PR isn’t a draft. Code Review doesn’t run on draft PRs.
- Verify the Claude GitHub App still has access to the repository in your GitHub organization’s settings.
### GitHub Enterprise Cloud with IP restrictions
If your GitHub Enterprise Cloud organization restricts access by IP address, the Claude GitHub App may be unable to access your repositories. To fix this, **[enable IP allow list inheritance for installed GitHub Apps](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#allowing-access-by-github-apps)** in your GitHub enterprise settings. 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](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#adding-an-allowed-ip-address)** instead, or to configure other firewalls, see the **[Anthropic API IP addresses](../04-API-Reference/Endpoints/ip-addresses.md)**.
### GitHub Enterprise Server (self-hosted)
Self-hosted GitHub Enterprise Server (GHES) is supported through a separate setup flow. See **[Claude Code with GitHub Enterprise Server](github-enterprise-server.md)** for full instructions.
Common GHES setup issues:
- **"Public cannot be private" error during setup:** Your GHES hostname must resolve to a publicly routable IP address. Code Review reaches your server over the internet, so internal or private network addresses won't work. Update DNS or your network configuration so the hostname resolves to a public IP, then retry.
- **GitHub Enterprise Cloud with Data Residency is a different product.** Data Residency tenants (hostnames matching `*.ghe.com`) aren't supported by Code Review. Only self-hosted GitHub Enterprise Server and standard github.com repositories are supported.
------------------------------------------------------------------------
## Frequently asked questions
### Is Code Review available as a capability when creating a custom role?
No, Code Review is not available to add to a **[custom role](https://support.claude.com/en/articles/13930452-manage-custom-roles-on-enterprise-plans)** at this time.
------------------------------------------------------------------------
## Related resources
- **[Plugins](../08-Plugins-Skills/discover-plugins.md)** — Browse the plugin marketplace, including a code-review plugin for running on-demand reviews locally before pushing.
- **[GitHub Actions](github-actions.md)** — Run Claude in your own GitHub Actions workflows for custom automation beyond Code Review.
- **[GitLab CI/CD](gitlab-ci-cd.md)** — Self-hosted Claude integration for GitLab pipelines.
---
## Example settings files - Claude Code Docs
Source: https://code.claude.com/docs/en/settings-example
Path: 02-Claude-Code-CLI/settings-example.md
## On this page
- [Your own settings](#your-own-settings)
- [A team’s shared settings](#a-teams-shared-settings)
- [An organization’s managed settings](#an-organizations-managed-settings)
Settings
# Example settings files
Copy pageCopy page
Realistic settings.json files for a developer, a team, and an organization: copy one, keep the keys you want, and change the values.
Copy pageCopy page
This page holds three example `settings.json` files, one for each place you save a setting:
- A developer’s `~/.claude/settings.json`
- A team’s `.claude/settings.json`, committed to the repository
- An organization’s `managed-settings.json`
Each one is a plausible file for that reader, so you can see the shape and copy the parts you want. None of them is a recommended baseline. Every value comes from the key’s entry on the [settings reference](settings-reference.md), which has its type, default, and where it can be set. Each example has two tabs. **Copyable settings file** is the file as you’d save it. **What each key does** is the same file with a comment above each key; Claude Code doesn’t accept comments in a settings file, so copy from the first tab.
[](#your-own-settings)
Your own settings
One developer’s personal settings. It picks a model and effort, adjusts the terminal, and pre-approves a read-only command and one file read. Everything not listed keeps its default. A file like this goes in `~/.claude/settings.json`, where it applies to every project you open.
- Copyable settings file
- What each key does
Save this as `~/.claude/settings.json`. It’s valid JSON with no comments, so you can paste it as is and delete the keys you don’t want.
~/.claude/settings.json
```python
{
"model": "claude-sonnet-5",
"modelSettings": {
"claude-sonnet-5": { "effortLevel": "xhigh" }
},
"editorMode": "vim",
"theme": "light-daltonized",
"statusLine": {
"type": "command",
"command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'",
"padding": 2
},
"spinnerTipsEnabled": false,
"preferredNotifChannel": "terminal_bell",
"permissions": {
"allow": [
"Bash(git diff *)",
"Read(~/.zshrc)"
]
},
"autoUpdatesChannel": "stable",
"cleanupPeriodDays": 20
}
```
The same file with a comment above each key. Read it here; copy from the other tab, because Claude Code doesn’t accept comments in a settings file.
~/.claude/settings.json
```python
{
// Start every session on Sonnet 5
"model": "claude-sonnet-5",
// Run Sonnet 5 above its default high level; /effort saves a level per model, and --effort sets one for a single session
"modelSettings": {
"claude-sonnet-5": { "effortLevel": "xhigh" }
},
// Vim keybindings in the prompt
"editorMode": "vim",
// The colorblind-friendly light theme
"theme": "light-daltonized",
// A status line below the prompt: model name and context used
"statusLine": {
"type": "command",
"command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'",
"padding": 2
},
// Hide the tips that rotate under the spinner
"spinnerTipsEnabled": false,
// Ring the terminal bell for notifications, such as a finished task or a waiting permission prompt
"preferredNotifChannel": "terminal_bell",
// Let Claude Code run git diff and read your .zshrc without asking
"permissions": {
"allow": [
"Bash(git diff *)",
"Read(~/.zshrc)"
]
},
// Take updates from the stable channel
"autoUpdatesChannel": "stable",
// Delete session transcripts and other local session data older than 20 days
"cleanupPeriodDays": 20
}
```
[](#a-teams-shared-settings)
A team’s shared settings
One team’s shared settings, committed to the repository so everyone who clones it gets the same permissions, hooks, and plugin marketplace. Save a file like this at `.claude/settings.json` at the top of the repository. What to know before you commit one:
- **Cloud sessions read it too.** A [cloud session](settings.md#settings-in-cloud-sessions) starts from a clone of the repository, so the committed file applies there as well.
- **Telemetry goes in managed or personal settings.** Claude Code ignores the [OpenTelemetry exporter variables](settings-reference.md#variables-claude-code-ignores-in-env) in a repository’s settings files, apart from some values that turn telemetry off. Set them in [managed settings](../13-Enterprise-Admin/monitoring-usage.md#administrator-configuration) for your organization, or in each person’s `~/.claude/settings.json`.
- **Allow rules wait for trust.** Allow rules and `extraKnownMarketplaces` entries take effect after each person [trusts this folder itself](permissions.md#project-allow-rules-and-workspace-trust), not only a parent folder; deny and ask rules apply in every session, trusted or not.
- **The hook is a script in the repo.** This file’s hook runs `.claude/hooks/block-rm.sh`; [How a hook resolves](../07-Hooks/hooks.md#how-a-hook-resolves) walks through writing it.
- **Rules match the command and path as written.** `Bash(git push *)` doesn’t match [`git -C . push`](permissions.md#bash-rule-limits). `Read(./.env)` on its own stops the file tools and commands that name the file, such as `cat .env`, but not [`grep -r` run over the directory](permissions.md#read-and-edit); the `sandbox` block in this file closes that gap, because the sandbox [adds your `Read` deny paths](settings-reference.md#sandbox-filesystem-denyread) to what every sandboxed command can’t read.
- Copyable settings file
- What each key does
Save this as `.claude/settings.json` at the top of the repository and commit it. It’s valid JSON with no comments, so you can paste it as is and delete the keys you don’t want.
.claude/settings.json
```python
{
"permissions": {
"allow": [
"Bash(npm run *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
},
"extraKnownMarketplaces": {
"acme-tools": {
"source": {
"source": "github",
"repo": "acme-corp/claude-plugins"
}
}
},
"enabledPlugins": {
"code-formatter@acme-tools": true
},
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": [
"/tmp/build"
]
},
"network": {
"allowedDomains": [
"registry.npmjs.org",
"*.example.com"
]
}
},
"plansDirectory": "./plans"
}
```
The same file with a comment above each key. Read it here; copy from the other tab, because Claude Code doesn’t accept comments in a settings file.
.claude/settings.json
```python
{
"permissions": {
// Run npm scripts without asking
"allow": [
"Bash(npm run *)"
],
// Confirm before git push commands
"ask": [
"Bash(git push *)"
],
// Deny reads of env files and the secrets folder by the file tools and file-reading commands
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
},
// Before every Bash command, run a script in the repo that can block it
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
},
// Register the team's plugin marketplace on every clone
"extraKnownMarketplaces": {
"acme-tools": {
"source": {
"source": "github",
"repo": "acme-corp/claude-plugins"
}
}
},
// Enable one plugin from that marketplace; a plugin from an external source such as a GitHub repository still needs each person to install it once
"enabledPlugins": {
"code-formatter@acme-tools": true
},
// Sandbox commands: writable build dir; npm and example.com pre-allowed, other hosts still prompt
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": [
"/tmp/build"
]
},
"network": {
"allowedDomains": [
"registry.npmjs.org",
"*.example.com"
]
}
},
// Keep plan files inside the repo
"plansDirectory": "./plans"
}
```
[](#an-organizations-managed-settings)
An organization’s managed settings
A `managed-settings.json` file that shows the shape of the managed keys, with one plausible value for each. It isn’t a recommended policy: pick the keys that match your own requirements and set your own values. The example sets these keys:
- `forceLoginMethod` and `forceLoginOrgUUID` pin the login method and organization
- `availableModels` and `enforceAvailableModels` restrict which models sessions can use
- `permissions.deny` denies two file reads and `curl` commands [as Claude writes them](permissions.md#bash-rule-limits), and `disableBypassPermissionsMode` removes the bypass permission mode
- [`allowManagedPermissionRulesOnly`](settings-reference.md#allowmanagedpermissionrulesonly) and [`allowManagedMcpServersOnly`](settings-reference.md#allowmanagedmcpserversonly) make the managed permission and MCP allowlists the only ones that apply
- `allowedMcpServers` pins the MCP server by URL
- `strictKnownMarketplaces` allows one plugin marketplace
- `sandbox` sandboxes commands with a fixed network allowlist and no unsandboxed retry
- `requiredMinimumVersion` sets a minimum Claude Code version
- `cleanupPeriodDays` shortens retention of session transcripts and other local data to seven days
- `companyAnnouncements` shows a message at startup
Administrators deploy a file like this as `managed-settings.json`, or the same JSON through MDM or [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md). One deployed file applies to every machine or account it reaches. To give a group different values, deploy a different file or profile to that group, since [server-managed settings don’t support per-group policy yet](../13-Enterprise-Admin/server-managed-settings.md#current-limitations).
- Copyable settings file
- What each key does
Deploy this as `managed-settings.json`, or the same JSON through MDM or the claude.ai console. It’s valid JSON with no comments; replace the example organization UUID, server URL, and marketplace with your own and delete the keys you don’t want.
managed-settings.json
```python
{
"forceLoginMethod": "claudeai",
"forceLoginOrgUUID": [
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
],
"availableModels": [
"opus",
"sonnet"
],
"enforceAvailableModels": true,
"permissions": {
"deny": [
"Bash(curl *)",
"Read(./.env)",
"Read(./secrets/**)"
],
"disableBypassPermissionsMode": "disable"
},
"allowManagedPermissionRulesOnly": true,
"allowedMcpServers": [
{
"serverUrl": "https://api.githubcopilot.com/*"
}
],
"allowManagedMcpServersOnly": true,
"strictKnownMarketplaces": [
{
"source": "github",
"repo": "acme-corp/approved-plugins"
}
],
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"network": {
"allowedDomains": [
"registry.npmjs.org",
"github.com"
],
"allowManagedDomainsOnly": true
}
},
"requiredMinimumVersion": "2.1.150",
"cleanupPeriodDays": 7,
"companyAnnouncements": [
"Welcome to Acme Corp! Review our code guidelines at docs.example.com"
]
}
```
The same file with a comment above each key. Read it here; copy from the other tab, because Claude Code doesn’t accept comments in a settings file.
managed-settings.json
```python
{
// Only claude.ai logins, and only in this organization
"forceLoginMethod": "claudeai",
"forceLoginOrgUUID": [
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
],
// Only Opus and Sonnet models; with enforceAvailableModels, the Default option obeys the list too
"availableModels": [
"opus",
"sonnet"
],
"enforceAvailableModels": true,
"permissions": {
// Deny curl commands and reads of the project's .env file and secrets folder on every machine
"deny": [
"Bash(curl *)",
"Read(./.env)",
"Read(./secrets/**)"
],
// Remove the bypass-permissions mode from every session
"disableBypassPermissionsMode": "disable"
},
// Ignore permission rules from user, project, and local settings
"allowManagedPermissionRulesOnly": true,
// Only the GitHub MCP server, matched by URL rather than by name, since a user can
// name any server "github". User-added servers that don't match don't load, including
// every stdio server when the list has only URL entries. The allowManagedMcpServersOnly
// key below makes this managed list the only allowlist that applies
"allowedMcpServers": [
{
"serverUrl": "https://api.githubcopilot.com/*"
}
],
"allowManagedMcpServersOnly": true,
// Plugins can come only from this marketplace
"strictKnownMarketplaces": [
{
"source": "github",
"repo": "acme-corp/approved-plugins"
}
],
// Sandbox every command Claude runs, refuse to start if the sandbox can't be
// set up, and never let a blocked command retry outside the sandbox; network
// limited to npm and GitHub, and users can't add domains
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"network": {
"allowedDomains": [
"registry.npmjs.org",
"github.com"
],
"allowManagedDomainsOnly": true
}
},
// Refuse to start on versions older than 2.1.150
"requiredMinimumVersion": "2.1.150",
// Delete session transcripts and other local session data after 7 days
"cleanupPeriodDays": 7,
// A message every user sees at startup
"companyAnnouncements": [
"Welcome to Acme Corp! Review our code guidelines at docs.example.com"
]
}
```
---
## All settings - Claude Code Docs
Source: https://code.claude.com/docs/en/settings-reference
Path: 02-Claude-Code-CLI/settings-reference.md
# All settings
Copy pageCopy page
Complete reference for every Claude Code settings.json key: where each one goes, its type and default, and a paste-ready example, with an index of every key.
Copy pageCopy page
This reference page lists each key Claude Code reads from a settings file, plus the [short group of keys](#global-config-settings) it keeps in `~/.claude.json` instead. To pick a file, or check precedence, start with [Settings files and precedence](settings.md).
[](#settings-index)
Settings index
Every key below links to its entry. Scope lists the [files](settings.md#settings-files-and-who-they-affect) it can go in: `User` is `~/.claude/settings.json`, `Project` is `.claude/settings.json`, `Local` is `.claude/settings.local.json`, and `Managed` is [what your organization deploys](../13-Enterprise-Admin/managed-settings.md). `Any file` means all four, and `Global config` means [`~/.claude.json`](#global-config-settings).
| Key | Description | Topic | Scope |
|:------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------|:------------------------|
| [`advisorModel`](#advisormodel) | Pick which model answers when Claude asks the [advisor tool](advisor.md) | Model and responses | Any file |
| [`agent`](#agent) | Start every session as a named [subagent](../09-Agents-Patterns/sub-agents.md) with its prompt, tools, and model | Agents, sessions, and worktrees | Any file |
| [`agentPushNotifEnabled`](#agentpushnotifenabled) | Let Claude send a [push notification to your phone](remote-control.md#mobile-push-notifications) when it decides to | Remote, desktop, and notifications | Any file |
| [`allowAllClaudeAiMcps`](#allowallclaudeaimcps) | Load the [claude.ai connectors](../06-MCP-Tools/General/mcp.md) Claude Code fetches itself alongside a deployed [`managed-mcp.json`](../06-MCP-Tools/General/managed-mcp.md#exclusive-control-with-managed-mcp-json) | MCP | Managed |
| [`allowClaudeInChromeWithManagedMcp`](#allowclaudeinchromewithmanagedmcp) | Let the built-in [Claude in Chrome](../03-IDE-Integrations/chrome.md) server run alongside a deployed [`managed-mcp.json`](../06-MCP-Tools/General/managed-mcp.md#exclusive-control-with-managed-mcp-json) | MCP | Managed |
| [`allowedChannelPlugins`](#allowedchannelplugins) | Replace the default allowlist of [channel plugins](channels.md#restrict-which-channel-plugins-can-run) that can push messages | Plugins and skills | Managed |
| [`allowedHttpHookUrls`](#allowedhttphookurls) | Limit which URLs [HTTP hooks](../07-Hooks/hooks.md) can target | Hooks and automation | Any file |
| [`allowedMcpServers`](#allowedmcpservers) | Allowlist which [MCP servers](../06-MCP-Tools/General/mcp.md) users can add | MCP | Any file |
| [`allowManagedHooksOnly`](#allowmanagedhooksonly) | Run only the [hooks](../07-Hooks/hooks.md) your organization deploys | Hooks and automation | Managed |
| [`allowManagedMcpServersOnly`](#allowmanagedmcpserversonly) | Make the managed [MCP](../06-MCP-Tools/General/mcp.md) allowlist the only one that applies | MCP | Managed |
| [`allowManagedPermissionRulesOnly`](#allowmanagedpermissionrulesonly) | Make [managed settings](../13-Enterprise-Admin/managed-settings.md) the only settings source of [permission rules](permissions.md#managed-settings) | Permission settings | Managed |
| [`alwaysThinkingEnabled`](#alwaysthinkingenabled) | Turn [extended thinking](model-config.md#extended-thinking) off for every session | Model and responses | Any file |
| [`apiKeyHelper`](#apikeyhelper) | Generate the [API credential](../13-Enterprise-Admin/iam.md#credential-management) with your own command | Authentication and providers | Any file |
| [`askUserQuestionTimeout`](#askuserquestiontimeout) | Let an unanswered question [auto-continue](tools-reference.md#question-auto-continue-timeout) after idle time | Interface and terminal | User or managed |
| [`attribution`](#attribution) | Customize the attribution Claude Code adds to commits and pull requests | Git and attribution | Any file |
| [`attribution.commit`](#attribution-commit) | Change or hide the trailer Claude Code adds to commits | Git and attribution | Any file |
| [`attribution.pr`](#attribution-pr) | Change or hide the attribution line in pull request descriptions | Git and attribution | Any file |
| [`attribution.sessionUrl`](#attribution-sessionurl) | Omit the claude.ai session link from [cloud](claude-code-on-the-web.md) and [Remote Control](remote-control.md) commits | Git and attribution | Any file |
| [`autoCompactEnabled`](#autocompactenabled) | Turn [automatic compaction](context-window.md) off or on | Memory and context | Any file |
| [`autoCompactWindow`](#autocompactwindow) | Set how full the context gets before Claude Code [compacts](context-window.md) | Memory and context | Any file |
| [`autoConnectIde`](#autoconnectide) | Connect to a running [VS Code](../03-IDE-Integrations/vs-code.md) or [JetBrains](../03-IDE-Integrations/jetbrains.md#from-external-terminals) IDE automatically from an external terminal | Global config settings | Global config |
| [`autoContinueAtUsageLimit`](#autocontinueatusagelimit) | Wait in the open session and [continue the task automatically](interactive-mode.md#wait-for-a-usage-limit-to-reset) after a claude.ai usage limit resets | Interface and terminal | User or managed |
| [`autoInstallIdeExtension`](#autoinstallideextension) | Turn off automatic install of the [IDE extension](../03-IDE-Integrations/vs-code.md#install-the-extension) from a VS Code terminal | Global config settings | Global config |
| [`autoMemoryDirectory`](#automemorydirectory) | Store [auto memory](memory.md#auto-memory) in a directory you choose | Memory and context | Any file |
| [`autoMemoryEnabled`](#automemoryenabled) | Turn [auto memory](memory.md#auto-memory) off or on | Memory and context | Any file |
| [`autoMode`](#automode) | Add your own allow and deny rules to the [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) classifier | Permission settings | User or managed |
| [`autoMode.classifyAllShell`](#automode-classifyallshell) | Send every shell command through the [auto mode classifier](permission-modes.md#what-the-classifier-blocks-by-default), even ones a narrow allow rule matches | Permission settings | User or managed |
| [`autoScrollEnabled`](#autoscrollenabled) | [Follow new output](fullscreen.md#auto-follow) to the bottom in fullscreen rendering | Interface and terminal | Any file |
| [`autoUpdatesChannel`](#autoupdateschannel) | Follow the stable [release channel](../01-Getting-Started/setup.md#configure-release-channel) instead of latest | Updates and versioning | Any file |
| [`availableModels`](#availablemodels) | [Restrict which models](model-config.md#restrict-model-selection) people can pick | Model and responses | Any file |
| [`availableModelsMatch`](#availablemodelsmatch) | Make each `availableModels` model ID entry [permit only the version it names](model-config.md#block-specific-models-or-versions) | Model and responses | Managed |
| [`awaySummaryEnabled`](#awaysummaryenabled) | Turn off the [session recap](interactive-mode.md#session-recap) shown when you come back to the terminal | Remote, desktop, and notifications | Any file |
| [`awsAuthRefresh`](#awsauthrefresh) | Refresh expired [Bedrock credentials](amazon-bedrock.md#advanced-credential-configuration) in `.aws` with your own command | Authentication and providers | Any file |
| [`awsCredentialExport`](#awscredentialexport) | Supply [Bedrock credentials](amazon-bedrock.md#advanced-credential-configuration) as JSON from your own command | Authentication and providers | Any file |
| [`axScreenReader`](#axscreenreader) | Render [screen-reader friendly output](accessibility.md) | Interface and terminal | Any file |
| [`bashEditDiffEnabled`](#basheditdiffenabled) | Record the [files that changed while a Bash command ran](../07-Hooks/hooks.md#bash) in every permission mode | Interface and terminal | User or managed |
| [`bashOutputMaxChars`](#bashoutputmaxchars) | Set how much of a successful command’s [output](tools-reference.md#output-limits) Claude receives inline | Memory and context | Any file |
| [`blockedMarketplaces`](#blockedmarketplaces) | Block [plugin marketplace](../08-Plugins-Skills/plugins.md) sources for your organization | Plugins and skills | Managed |
| [`browserExternalPageTools`](#browserexternalpagetools) | Keep Claude’s tools off external pages in the [desktop](../16-Mobile-Desktop/desktop.md) Browser pane | Tools | Managed |
| [`channelsEnabled`](#channelsenabled) | Allow [channels](channels.md#enable-channels-for-your-organization) for your organization | Plugins and skills | Managed |
| [`claudeInChromeDefaultEnabled`](#claudeinchromedefaultenabled) | Turn on [Chrome integration](../03-IDE-Integrations/chrome.md) in every interactive CLI session without passing `--chrome` | Global config settings | Global config |
| [`claudeMd`](#claudemd) | Inject organization-wide [CLAUDE.md](memory.md#deploy-organization-wide-claude-md) instructions from managed settings | Memory and context | Managed |
| [`claudeMdExcludes`](#claudemdexcludes) | Skip specific [CLAUDE.md](memory.md#exclude-specific-claude-md-files) files when memory loads | Memory and context | Any file |
| [`cleanupPeriodDays`](#cleanupperioddays) | Choose how many days Claude Code keeps [transcripts](../13-Enterprise-Admin/data-usage.md#data-retention) before deleting them | Privacy and telemetry | Any file |
| [`companyAnnouncements`](#companyannouncements) | Show your organization’s announcements at startup | Interface and terminal | Any file |
| [`copyFullResponse`](#copyfullresponse) | Make [`/copy`](commands.md) copy the full response without showing the code block picker | Global config settings | Global config |
| [`copyOnSelect`](#copyonselect) | Turn off automatic copying of text you select with the mouse in [fullscreen rendering](fullscreen.md#use-the-mouse) and agent view | Global config settings | Global config |
| [`crossSessionInbound`](#crosssessioninbound) | Choose whether Claude Code delivers [messages from your other sessions](cross-session-messaging.md#control-inbound-messages), shows a notice without delivering them, or refuses them | Agents, sessions, and worktrees | Any file |
| [`defaultShell`](#defaultshell) | Choose whether Bash or PowerShell runs the shell commands you type with the [`!` prefix](interactive-mode.md#shell-mode-with-prefix) | Interface and terminal | Any file |
| [`defaultToAgentsView`](#defaulttoagentsview) | Open [agent view](../09-Agents-Patterns/agent-view.md) instead of a new conversation when you run `claude` with no arguments | Global config settings | Global config |
| [`deniedMcpServers`](#deniedmcpservers) | Block specific [MCP servers](../06-MCP-Tools/General/mcp.md) by URL, command, or name | MCP | Any file |
| [`deniedModels`](#deniedmodels) | [Block specific models](model-config.md#block-specific-models-or-versions), even ones `availableModels` permits | Model and responses | Managed |
| [`desktopSessionCleanupPeriodDays`](#desktopsessioncleanupperioddays) | Set an age limit in days for [Claude Desktop and Cowork transcripts](claude-directory.md#cleaned-up-automatically) | Privacy and telemetry | User or managed |
| [`dialogExpiry`](#dialogexpiry) | Set how long Claude Code waits for [Remote Control](remote-control.md) or an SDK host to answer a forwarded dialog before it cancels the dialog | Interface and terminal | User or managed |
| [`diffTool`](#difftool) | Choose whether Claude’s proposed file changes open in the [VS Code](../03-IDE-Integrations/vs-code.md) or [JetBrains](../03-IDE-Integrations/jetbrains.md#features) diff viewer or stay in the terminal | Global config settings | Global config |
| [`disableAgentView`](#disableagentview) | Turn off background agents and [agent view](../09-Agents-Patterns/agent-view.md) | Agents, sessions, and worktrees | Any file |
| [`disableAllHooks`](#disableallhooks) | Turn off [hooks](../07-Hooks/hooks.md), a custom [status line](statusline.md), and a custom [`@` file suggestion](interactive-mode.md#quick-commands) command at once | Hooks and automation | Any file |
| [`disableArtifact`](#disableartifact) | Deprecated; use `enableArtifact` to turn the [Artifact tool](artifacts.md) off | Remote, desktop, and notifications | Any file |
| [`disableAutoMode`](#disableautomode) | Remove [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) from the permission mode cycle | Permission settings | Any file |
| [`disableBrowserExternalNavigation`](#disablebrowserexternalnavigation) | Limit the [desktop](../16-Mobile-Desktop/desktop.md) Browser pane to localhost for people and Claude | Tools | Managed |
| [`disableBundledSkills`](#disablebundledskills) | Turn off the [skills](../08-Plugins-Skills/skills.md#bundled-skills) and [workflows](workflows.md) included with Claude Code | Plugins and skills | Any file |
| [`disableClaudeAiConnectors`](#disableclaudeaiconnectors) | Turn off [claude.ai connectors](../06-MCP-Tools/General/mcp.md#disable-claude-ai-connectors) so Claude Code doesn’t fetch them | MCP | Any file |
| [`disableCommandPluginSources`](#disablecommandpluginsources) | Block [plugins](../08-Plugins-Skills/plugins.md) that install by running a marketplace-declared command | Plugins and skills | Managed |
| [`disableDeepLinkRegistration`](#disabledeeplinkregistration) | Stop Claude Code from registering the [`claude-cli://` handler](deep-links.md) | Remote, desktop, and notifications | Any file |
| [`disableDesktopLocalSessions`](#disabledesktoplocalsessions) | Turn off [Desktop Code sessions](../16-Mobile-Desktop/desktop.md#local-sessions-on-managed-devices) that run on the device, leaving SSH to other hosts and cloud | Remote, desktop, and notifications | Managed |
| [`disabledMcpjsonServers`](#disabledmcpjsonservers) | Reject specific servers from a project’s [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-scope) | MCP | Any file |
| [`disableMobileSimulatorTools`](#disablemobilesimulatortools) | Block Claude’s tools in the [desktop](../16-Mobile-Desktop/desktop.md) iOS Simulator pane | Tools | Managed |
| [`disableRemoteControl`](#disableremotecontrol) | Turn off [Remote Control](remote-control.md) everywhere it can start | Remote, desktop, and notifications | Any file |
| [`disableSideloadFlags`](#disablesideloadflags) | Reject the CLI flags that sideload [plugins](../08-Plugins-Skills/plugins.md), [subagents](../09-Agents-Patterns/sub-agents.md), and [MCP servers](../06-MCP-Tools/General/mcp.md) | Enterprise and managed settings | Managed |
| [`disableSkillShellExecution`](#disableskillshellexecution) | Stop [skills](../08-Plugins-Skills/skills.md) and custom commands from running inline shell | Plugins and skills | Any file |
| [`disableWorkflows`](#disableworkflows) | Turn [dynamic workflows](workflows.md) off for everyone; use `enableWorkflows` for yourself | Hooks and automation | Any file |
| [`editorMode`](#editormode) | Use [vim key bindings](interactive-mode.md#vim-editor-mode) in the input prompt | Interface and terminal | Any file |
| [`effortLevel`](#effortlevel) | Set a default [effort level](model-config.md#adjust-effort-level) for models without a saved level of their own | Model and responses | Any file |
| [`emojiCompletionEnabled`](#emojicompletionenabled) | Turn off [`:shortcode:` emoji suggestions and replacement](interactive-mode.md#emoji-shortcodes) in the prompt input | Interface and terminal | Any file |
| [`enableAllProjectMcpServers`](#enableallprojectmcpservers) | Approve every server in project [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) files without a prompt | MCP | Any file |
| [`enableArtifact`](#enableartifact) | Turn the [Artifact tool](artifacts.md) off with a `false` in any file; no file can turn it back on | Remote, desktop, and notifications | Any file |
| [`enabledMcpjsonServers`](#enabledmcpjsonservers) | Approve specific servers from a project’s [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) | MCP | Any file |
| [`enabledPlugins`](#enabledplugins) | Turn individual [plugins](../08-Plugins-Skills/plugins.md) on or off per scope | Plugins and skills | Any file |
| [`enableWorkflows`](#enableworkflows) | Turn [dynamic workflows](workflows.md) on or off against your plan’s default | Hooks and automation | Any file |
| [`enforceAvailableModels`](#enforceavailablemodels) | Keep the [`/model` Default choice](model-config.md#enforce-the-allowlist-for-the-default-model) inside your `availableModels` allowlist | Model and responses | Any file |
| [`env`](#env) | Set [environment variables](env-vars.md#in-settings-files) for every session and its subprocesses | Memory and context | Any file |
| [`externalEditorContext`](#externaleditorcontext) | Show Claude’s last response as comments when you press [Ctrl+G](interactive-mode.md#general-controls) to edit | Global config settings | Global config |
| [`extraKnownMarketplaces`](#extraknownmarketplaces) | Register [marketplaces](../08-Plugins-Skills/plugins.md) for a repository or an organization | Plugins and skills | Any file |
| [`fallbackModel`](#fallbackmodel) | Name [backup models](model-config.md#fallback-model-chains) for when the primary is overloaded | Model and responses | Any file |
| [`fastMode`](#fastmode) | Turn [fast mode](fast-mode.md) on for sessions where it’s available | Model and responses | Any file |
| [`fastModePerSessionOptIn`](#fastmodepersessionoptin) | Require people to turn [fast mode](fast-mode.md) on each session | Model and responses | Any file |
| [`feedbackDrafts`](#feedbackdrafts) | Control whether Claude queues [feedback drafts](tools-reference.md#sendfeedback-tool-behavior) for you to review | Privacy and telemetry | User or managed |
| [`feedbackSurveyRate`](#feedbacksurveyrate) | Change how often the [session quality survey](../13-Enterprise-Admin/data-usage.md#session-quality-surveys) appears | Privacy and telemetry | Any file |
| [`fileCheckpointingEnabled`](#filecheckpointingenabled) | Turn off or on the file snapshots that [`/rewind`](checkpointing.md) restores | Memory and context | Any file |
| [`fileSuggestion`](#filesuggestion) | Supply [`@` file autocomplete](interactive-mode.md#quick-commands) from your own command | Interface and terminal | Any file |
| [`footerLinksRegexes`](#footerlinksregexes) | Make issue or review IDs in output into [clickable links](statusline.md#clickable-links) below the input box | Interface and terminal | User or managed |
| [`forceLoginGatewayUrl`](#forcelogingatewayurl) | Set the [gateway URL](../13-Enterprise-Admin/claude-apps-gateway.md#set-the-gateway-url) the login screen connects to | Authentication and providers | Managed |
| [`forceLoginMethod`](#forceloginmethod) | [Restrict login](../13-Enterprise-Admin/iam.md#restrict-login-to-your-organization) to claude.ai, Claude Console, or a [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md) | Authentication and providers | Any file |
| [`forceLoginOrgUUID`](#forceloginorguuid) | [Pin claude.ai logins to your organization](../13-Enterprise-Admin/iam.md#restrict-login-to-your-organization); only a managed source enforces it | Authentication and providers | Any file |
| [`forceRemoteSettingsRefresh`](#forceremotesettingsrefresh) | Block startup until [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) are freshly fetched | Enterprise and managed settings | Managed |
| [`gatewayInternalNetworks`](#gatewayinternalnetworks) | Let `/login` reach a [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md#allow-a-gateway-on-public-address-space-you-own) on public IPv4 space your organization uses internally | Authentication and providers | Managed |
| [`gcpAuthRefresh`](#gcpauthrefresh) | Refresh [Google Cloud credentials](google-vertex-ai.md#advanced-credential-configuration) with your own command | Authentication and providers | Any file |
| [`hooks`](#hooks) | Run your own commands as [hooks](../07-Hooks/hooks.md) at points in Claude Code’s lifecycle | Hooks and automation | Any file |
| [`httpHookAllowedEnvVars`](#httphookallowedenvvars) | Limit which env vars [HTTP hooks](../07-Hooks/hooks.md) can put in headers | Hooks and automation | Any file |
| [`includeCoAuthoredBy`](#includecoauthoredby) | Deprecated; use `attribution` to hide or change commit and PR attribution | Git and attribution | Any file |
| [`includeGitInstructions`](#includegitinstructions) | Remove the built-in commit and PR instructions from Claude’s context | Git and attribution | Any file |
| [`inputNeededNotifEnabled`](#inputneedednotifenabled) | Get a [push notification](remote-control.md#mobile-push-notifications) when Claude is waiting on you | Remote, desktop, and notifications | Any file |
| [`isolatePeerMachines`](#isolatepeermachines) | Ask you before Claude [messages one of your sessions on another machine](cross-session-messaging.md#require-approval-for-cross-machine-messages) | Agents, sessions, and worktrees | Any file |
| [`keybindingFlavor`](#keybindingflavor) | Deprecated and has no effect; the word-editing shortcuts always [follow readline conventions](interactive-mode.md#make-ctrl-w-delete-back-to-whitespace) | Interface and terminal | Any file |
| [`language`](#language) | Have Claude respond in a language other than English | Model and responses | Any file |
| [`leftArrowOpensAgents`](#leftarrowopensagents) | Turn off the `←` shortcut that [backgrounds the session and opens agent view](../09-Agents-Patterns/agent-view.md#switch-sessions-without-leaving-the-terminal) | Global config settings | Global config |
| [`managedMcpServers`](#managedmcpservers) | Provide remote [MCP servers](../06-MCP-Tools/General/managed-mcp.md#provide-servers-through-managed-settings) to every user alongside the ones they add | MCP | Managed |
| [`managedSourcesBehavior`](#managedsourcesbehavior) | Compose every [managed source](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) you deploy instead of using the highest-priority one alone | Enterprise and managed settings | Managed |
| [`maxEffortLevel`](#maxeffortlevel) | Cap the [effort level](model-config.md#adjust-effort-level) for every model or per model, on every provider | Model and responses | Any file |
| [`maxProseWidth`](#maxprosewidth) | Cap how wide the prose in Claude’s responses runs in a wide terminal | Interface and terminal | Any file |
| [`minimumVersion`](#minimumversion) | Keep [auto-updates](../01-Getting-Started/setup.md#pin-a-minimum-version) from installing anything below a version | Updates and versioning | Any file |
| [`model`](#model) | Change the [model](model-config.md#set-a-default-model-for-new-sessions) Claude Code starts with | Model and responses | Any file |
| [`modelOverrides`](#modeloverrides) | [Map model IDs](model-config.md#override-model-ids-per-version) to your provider’s IDs, such as Bedrock ARNs | Model and responses | Any file |
| [`modelPicker`](#modelpicker) | Choose which models the [`/model` picker](model-config.md#available-models) lists, in your own order and with your own labels | Model and responses | User or managed |
| [`modelPricing`](#modelpricing) | Report spend at your organization’s contracted rates instead of list price | Model and responses | Managed |
| [`modelSettings`](#modelsettings) | Keep a saved [effort level](model-config.md#adjust-effort-level) per model, or cap one model’s effort | Model and responses | Any file |
| [`otelHeadersHelper`](#otelheadershelper) | Generate rotating [OpenTelemetry](../13-Enterprise-Admin/monitoring-usage.md#dynamic-headers) headers with your own command | Authentication and providers | Any file |
| [`outputStyle`](#outputstyle) | Change Claude’s role, tone, and output format with an [output style](output-styles.md) | Model and responses | Any file |
| [`parentSettingsBehavior`](#parentsettingsbehavior) | Apply or drop restrictions an [SDK or IDE host](../13-Enterprise-Admin/managed-settings.md#let-an-embedding-host-add-policy) passes when you deploy [managed settings](../13-Enterprise-Admin/managed-settings.md) | Enterprise and managed settings | Managed |
| [`permissionExplainerEnabled`](#permissionexplainerenabled) | Removed in v2.1.257, together with the `Ctrl+E` command explanation on shell permission prompts | Global config settings | Global config |
| [`permissions`](#permissions) | Set allow, ask, and deny rules and the starting [permission mode](permission-modes.md) | Permission settings | Any file |
| [`permissions.additionalDirectories`](#permissions-additionaldirectories) | Give Claude file access to [directories outside the current one](permissions.md#working-directories) | Permission settings | Any file |
| [`permissions.allow`](#permissions-allow) | Approve listed [tool uses](permissions.md#permission-rule-syntax) without a prompt | Permission settings | Any file |
| [`permissions.ask`](#permissions-ask) | Always prompt before listed [tool uses](permissions.md#permission-rule-syntax) | Permission settings | Any file |
| [`permissions.blockReadsOutsideWorkingDirectories`](#permissions-blockreadsoutsideworkingdirectories) | Make the file tools refuse reads outside the [working directories](permissions.md#working-directories) in every permission mode | Permission settings | Any file |
| [`permissions.defaultMode`](#permissions-defaultmode) | Set the [permission mode](permission-modes.md#which-mode-a-session-starts-in) new sessions start in | Permission settings | Any file |
| [`permissions.deny`](#permissions-deny) | Block listed [tool uses](permissions.md#permission-rule-syntax), including reads of files that hold secrets | Permission settings | Any file |
| [`permissions.disableBypassPermissionsMode`](#permissions-disablebypasspermissionsmode) | Prevent anyone from entering [bypassPermissions mode](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) | Permission settings | Any file |
| [`plansDirectory`](#plansdirectory) | Choose where [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode) writes plan files | Memory and context | Any file |
| [`pluginConfigs`](#pluginconfigs) | Store the answers you gave a [plugin](../08-Plugins-Skills/plugins.md)’s configuration dialog | Plugins and skills | User or managed |
| [`pluginSuggestionMarketplaces`](#pluginsuggestionmarketplaces) | Choose which [marketplaces](../08-Plugins-Skills/plugins-org.md#restrict-what-users-can-install) can surface plugin install suggestions in `/plugin` | Plugins and skills | Managed |
| [`pluginTrustMessage`](#plugintrustmessage) | Add your own text to the [plugin](../08-Plugins-Skills/plugins.md) trust warning | Plugins and skills | Managed |
| [`policyHelper`](#policyhelper) | Run an executable that computes [managed settings](../13-Enterprise-Admin/managed-settings.md#compute-the-policy-with-a-helper-program) at startup | Enterprise and managed settings | Managed |
| [`policyHelper.path`](#policyhelper-path) | Name the [helper executable](../13-Enterprise-Admin/managed-settings.md#compute-the-policy-with-a-helper-program) Claude Code runs | Enterprise and managed settings | Managed |
| [`policyHelper.refreshIntervalMs`](#policyhelper-refreshintervalms) | Re-run the [helper](../13-Enterprise-Admin/managed-settings.md#compute-the-policy-with-a-helper-program) in the background on an interval | Enterprise and managed settings | Managed |
| [`policyHelper.timeoutMs`](#policyhelper-timeoutms) | Set how long Claude Code waits for the [helper](../13-Enterprise-Admin/managed-settings.md#compute-the-policy-with-a-helper-program) | Enterprise and managed settings | Managed |
| [`preferredNotifChannel`](#preferrednotifchannel) | Choose a [terminal bell or desktop notification](terminal-config.md#get-a-terminal-bell-or-notification) for task completion | Remote, desktop, and notifications | Any file |
| [`prefersReducedMotion`](#prefersreducedmotion) | [Reduce or turn off](accessibility.md#accessibility-settings) spinner, shimmer, and flash animations | Interface and terminal | Any file |
| [`processWrapper`](#processwrapper) | Run Claude Code’s background processes through a [corporate launcher](../13-Enterprise-Admin/corporate-launcher.md) on macOS and Linux | Agents, sessions, and worktrees | User or managed |
| [`promptCacheTtl`](#promptcachettl) | Choose the [prompt cache lifetime](prompt-caching.md#cache-lifetime) for the main conversation | Model and responses | Any file |
| [`promptSuggestionEnabled`](#promptsuggestionenabled) | Hide the grayed-out [prompt suggestions](interactive-mode.md#prompt-suggestions) in the input box | Interface and terminal | Any file |
| [`prStatusFooterEnabled`](#prstatusfooterenabled) | Turn off the prompt footer’s [PR review status](interactive-mode.md#pr-review-status) badge and the pull request check behind it | Global config settings | Global config |
| [`prUrlTemplate`](#prurltemplate) | Point PR links at an internal code-review tool instead of github.com | Git and attribution | Any file |
| [`remote.defaultEnvironmentId`](#remote-defaultenvironmentid) | Pick the default [cloud environment](cloud-environments.md) for `claude --cloud`; a self-hosted `ccpool_` ID is read only from user and managed settings and `--settings` | Remote, desktop, and notifications | Any file |
| [`remoteControlAtStartup`](#remotecontrolatstartup) | Connect [Remote Control](remote-control.md#enable-remote-control-for-all-sessions) automatically when a session starts | Remote, desktop, and notifications | Any file |
| [`requiredMaximumVersion`](#requiredmaximumversion) | [Refuse to start](../01-Getting-Started/setup.md#pin-a-minimum-version) on a version newer than your organization allows | Updates and versioning | Managed |
| [`requiredMinimumVersion`](#requiredminimumversion) | [Refuse to start](../01-Getting-Started/setup.md#pin-a-minimum-version) on a version older than your organization requires | Updates and versioning | Managed |
| [`respectGitignore`](#respectgitignore) | Keep gitignored files out of the [`@` file picker](interactive-mode.md#quick-commands) | Interface and terminal | Any file |
| [`respondToBashCommands`](#respondtobashcommands) | Stop Claude from responding after a [`!` shell command](interactive-mode.md#shell-mode-with-prefix) runs | Interface and terminal | Any file |
| [`sandbox`](#sandbox) | [Isolate Bash commands](sandboxing.md) from your filesystem and network on macOS, Linux, and WSL2 | Sandbox settings | Any file |
| [`sandbox.allowAppleEvents`](#sandbox-allowappleevents) | Let [sandboxed](sandboxing.md) commands send Apple Events on macOS | Sandbox settings | User or managed |
| [`sandbox.allowUnsandboxedCommands`](#sandbox-allowunsandboxedcommands) | Let Claude retry a blocked command outside the [sandbox](sandboxing.md#the-unsandboxed-retry-escape-hatch), or forbid it | Sandbox settings | Any file |
| [`sandbox.autoAllowBashIfSandboxed`](#sandbox-autoallowbashifsandboxed) | Run [sandboxed](sandboxing.md#auto-allow-mode) commands without a permission prompt | Sandbox settings | Any file |
| [`sandbox.bwrapPath`](#sandbox-bwrappath) | Point the [sandbox](sandboxing.md) at a bubblewrap binary outside `PATH` | Sandbox settings | Managed |
| [`sandbox.credentials`](#sandbox-credentials) | Hide or mask credential files and variables inside the [sandbox](sandboxing.md#protect-credentials) | Sandbox settings | Any file |
| [`sandbox.credentials.allowPlaintextInject`](#sandbox-credentials-allowplaintextinject) | Let [masked credentials](sandboxing.md#mask-credentials) reach plain HTTP services on trusted test networks | Sandbox settings | User or managed |
| [`sandbox.credentials.awsPairs`](#sandbox-credentials-awspairs) | Link custom-named AWS key variables into one credential for [re-signing](sandboxing.md#re-sign-aws-requests) | Sandbox settings | User or managed |
| [`sandbox.credentials.envVars`](#sandbox-credentials-envvars) | Unset or mask an environment variable inside the [sandbox](sandboxing.md#mask-environment-variables) | Sandbox settings | Any file |
| [`sandbox.credentials.files`](#sandbox-credentials-files) | Block or mask reads of a credential file inside the [sandbox](sandboxing.md#mask-credential-files) | Sandbox settings | Any file |
| [`sandbox.credentials.sigv4`](#sandbox-credentials-sigv4) | Choose whether streaming, presigned, or [SigV4A AWS requests](sandboxing.md#re-sign-aws-requests) fail or pass through | Sandbox settings | User or managed |
| [`sandbox.enabled`](#sandbox-enabled) | Turn on [Bash sandboxing](sandboxing.md#get-started) on macOS, Linux, and WSL2 | Sandbox settings | Any file |
| [`sandbox.enableWeakerNestedSandbox`](#sandbox-enableweakernestedsandbox) | Run the Linux [sandbox](sandboxing.md) inside an unprivileged container | Sandbox settings | Any file |
| [`sandbox.enableWeakerNetworkIsolation`](#sandbox-enableweakernetworkisolation) | Let `gh`, `gcloud`, and `terraform` verify TLS behind a MITM proxy inside the [sandbox](sandboxing.md#troubleshooting) on macOS | Sandbox settings | Any file |
| [`sandbox.excludedCommands`](#sandbox-excludedcommands) | Name commands Claude Code can run outside the [sandbox](sandboxing.md) | Sandbox settings | Any file |
| [`sandbox.failIfUnavailable`](#sandbox-failifunavailable) | Refuse to start when the [sandbox](sandboxing.md) can’t, instead of running unsandboxed | Sandbox settings | Any file |
| [`sandbox.filesystem`](#sandbox-filesystem) | Control which paths [sandboxed](sandboxing.md#filesystem-isolation) commands can read and write | Sandbox settings | Any file |
| [`sandbox.filesystem.allowManagedReadPathsOnly`](#sandbox-filesystem-allowmanagedreadpathsonly) | Stop developers from re-opening [read paths your organization blocked](sandboxing.md#keep-developers-from-widening-the-policy) | Sandbox settings | Managed |
| [`sandbox.filesystem.allowRead`](#sandbox-filesystem-allowread) | Re-open reading inside a region [`denyRead`](#sandbox-filesystem-denyread) blocks | Sandbox settings | Any file |
| [`sandbox.filesystem.allowWrite`](#sandbox-filesystem-allowwrite) | Add paths [sandboxed](sandboxing.md) commands can write to | Sandbox settings | Any file |
| [`sandbox.filesystem.denyRead`](#sandbox-filesystem-denyread) | Block [sandboxed](sandboxing.md) commands from reading specific paths | Sandbox settings | Any file |
| [`sandbox.filesystem.denyWrite`](#sandbox-filesystem-denywrite) | Block [sandboxed](sandboxing.md) commands from writing to specific paths | Sandbox settings | Any file |
| [`sandbox.filesystem.disabled`](#sandbox-filesystem-disabled) | [Turn off filesystem isolation](sandboxing.md#disable-filesystem-isolation) while keeping network isolation | Sandbox settings | User or managed |
| [`sandbox.ignoreViolations`](#sandbox-ignoreviolations) | Silence violation reports for paths a command is expected to probe | Sandbox settings | Any file |
| [`sandbox.network`](#sandbox-network) | Control which hosts, ports, and sockets [sandboxed](sandboxing.md#network-isolation) commands reach | Sandbox settings | Any file |
| [`sandbox.network.allowAllUnixSockets`](#sandbox-network-allowallunixsockets) | Let [sandboxed](sandboxing.md) commands connect to every Unix socket | Sandbox settings | Any file |
| [`sandbox.network.allowedDomains`](#sandbox-network-alloweddomains) | Pre-allow domains so [sandboxed](sandboxing.md) commands don’t prompt for them | Sandbox settings | Any file |
| [`sandbox.network.allowLocalBinding`](#sandbox-network-allowlocalbinding) | Let [sandboxed](sandboxing.md) commands bind to localhost ports on macOS | Sandbox settings | Any file |
| [`sandbox.network.allowMachLookup`](#sandbox-network-allowmachlookup) | Let macOS [sandboxed](sandboxing.md) tools like the iOS Simulator or Playwright reach their XPC services | Sandbox settings | Any file |
| [`sandbox.network.allowManagedDomainsOnly`](#sandbox-network-allowmanageddomainsonly) | Lock the network allowlist to [managed settings](sandboxing.md#keep-developers-from-widening-the-policy) | Sandbox settings | Managed |
| [`sandbox.network.allowUnixSockets`](#sandbox-network-allowunixsockets) | List Unix socket paths [sandboxed](sandboxing.md) commands can use on macOS | Sandbox settings | Any file |
| [`sandbox.network.deniedDomains`](#sandbox-network-denieddomains) | Block domains for [sandboxed](sandboxing.md) commands, even inside an allowed wildcard | Sandbox settings | Any file |
| [`sandbox.network.httpProxyPort`](#sandbox-network-httpproxyport) | Route [sandbox](sandboxing.md#custom-proxy-configuration) HTTP traffic through your own proxy | Sandbox settings | Any file |
| [`sandbox.network.socksProxyPort`](#sandbox-network-socksproxyport) | Route [sandbox](sandboxing.md#custom-proxy-configuration) SOCKS traffic through your own proxy | Sandbox settings | Any file |
| [`sandbox.network.strictAllowlist`](#sandbox-network-strictallowlist) | Deny hosts outside the [allowlist](sandboxing.md#network-isolation) instead of prompting | Sandbox settings | User or managed |
| [`sandbox.network.tlsTerminate`](#sandbox-network-tlsterminate) | Have the [sandbox](sandboxing.md#network-isolation) proxy terminate TLS so it can read HTTPS requests | Sandbox settings | User or managed |
| [`sandbox.ripgrep`](#sandbox-ripgrep) | Use your own ripgrep binary inside the [sandbox](sandboxing.md) | Sandbox settings | User or managed |
| [`sandbox.socatPath`](#sandbox-socatpath) | Point the [sandbox](sandboxing.md) proxy at a `socat` binary outside `PATH` | Sandbox settings | Managed |
| [`showClearContextOnPlanAccept`](#showclearcontextonplanaccept) | Show a “clear context” option on the [plan accept screen](permission-modes.md#review-and-approve-a-plan) | Interface and terminal | Any file |
| [`showThinkingSummaries`](#showthinkingsummaries) | See summaries of Claude’s [thinking](model-config.md#extended-thinking) instead of a collapsed stub | Model and responses | Any file |
| [`showTurnDuration`](#showturnduration) | Hide the “Cooked for” duration after each response | Interface and terminal | Any file |
| [`skillListingBudgetFraction`](#skilllistingbudgetfraction) | Reserve more or less context for the [skill listing](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short) | Memory and context | Any file |
| [`skillListingMaxDescChars`](#skilllistingmaxdescchars) | Cap each skill’s description length in the [skill listing](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short) | Memory and context | Any file |
| [`skillOverrides`](#skilloverrides) | [Hide or collapse a skill](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) without editing its SKILL.md | Plugins and skills | Any file |
| [`skipAutoPermissionPrompt`](#skipautopermissionprompt) | Skip the one-time notice Claude Code shows when you first enter [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) yourself rather than through the built-in default | Permission settings | User or managed |
| [`skipDangerousModePermissionPrompt`](#skipdangerousmodepermissionprompt) | Skip the confirmation dialog before [bypassPermissions mode](permission-modes.md#skip-all-checks-with-bypasspermissions-mode) | Permission settings | User, local, or managed |
| [`skipWebFetchPreflight`](#skipwebfetchpreflight) | Skip the [WebFetch hostname check](tools-reference.md#webfetch-tool-behavior) when Anthropic is unreachable | Privacy and telemetry | Any file |
| [`spellcheck`](#spellcheck) | Underline misspelled words in the prompt input with a [spell checker](interactive-mode.md#check-spelling-as-you-type) you install | Interface and terminal | User or managed |
| [`spinnerTipsEnabled`](#spinnertipsenabled) | Hide tips in the spinner while Claude works | Interface and terminal | Any file |
| [`spinnerTipsOverride`](#spinnertipsoverride) | Add your own tips to the spinner rotation, or replace the built-in tips | Interface and terminal | Any file |
| [`spinnerVerbs`](#spinnerverbs) | Add or replace the verbs shown while a turn runs | Interface and terminal | Any file |
| [`sshConfigs`](#sshconfigs) | Add [SSH connections](../16-Mobile-Desktop/desktop.md#pre-configure-ssh-connections-for-your-team) to the Desktop environment dropdown | Remote, desktop, and notifications | User or managed |
| [`sshHostAllowlist`](#sshhostallowlist) | Limit which hosts [Desktop SSH sessions](../16-Mobile-Desktop/desktop.md#restrict-which-ssh-hosts-users-can-connect-to) can reach | Remote, desktop, and notifications | Managed |
| [`statusLine`](#statusline) | Run your own command to render a [status line](statusline.md) below the prompt | Interface and terminal | Any file |
| [`strictKnownMarketplaces`](#strictknownmarketplaces) | Allowlist the [marketplace](../08-Plugins-Skills/plugins.md) sources users can add and install from | Plugins and skills | Managed |
| [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) | Block [skills](../08-Plugins-Skills/skills.md), [agents](../09-Agents-Patterns/sub-agents.md), [hooks](../07-Hooks/hooks.md), and [MCP servers](../06-MCP-Tools/General/mcp.md) from user and project sources | Plugins and skills | Managed |
| [`strictPluginOnlyCustomization.agents`](#strictpluginonlycustomization-agents) | Lock [agents](../09-Agents-Patterns/sub-agents.md) to plugin and managed sources | Plugins and skills | Managed |
| [`strictPluginOnlyCustomization.hooks`](#strictpluginonlycustomization-hooks) | Lock [hooks](../07-Hooks/hooks.md) to plugin and managed sources | Plugins and skills | Managed |
| [`strictPluginOnlyCustomization.mcp`](#strictpluginonlycustomization-mcp) | Lock [MCP servers](../06-MCP-Tools/General/mcp.md) to plugin and managed sources | Plugins and skills | Managed |
| [`strictPluginOnlyCustomization.skills`](#strictpluginonlycustomization-skills) | Lock [skills](../08-Plugins-Skills/skills.md) to plugin and managed sources | Plugins and skills | Managed |
| [`subagentPromptCacheTtl`](#subagentpromptcachettl) | Choose the [prompt cache lifetime](prompt-caching.md#cache-lifetime) for subagents and other requests outside the main conversation | Model and responses | Any file |
| [`subagentStatusLine`](#subagentstatusline) | Rewrite rows in the [subagent](../09-Agents-Patterns/sub-agents.md) task display with your own command | Interface and terminal | Any file |
| [`switchModelsOnFlag`](#switchmodelsonflag) | Switch models automatically or pause when a [safety classifier](model-config.md#ask-before-switching) flags a request | Model and responses | Any file |
| [`syncClaudeAiPlugins`](#syncclaudeaiplugins) | Stop loading the [plugins enabled on your claude.ai account](../08-Plugins-Skills/plugins-loading.md#synced-plugins) and stop downloading new ones | Plugins and skills | User, local, or managed |
| [`syncClaudeAiSkills`](#syncclaudeaiskills) | Stop loading the [skills enabled on your claude.ai account](../08-Plugins-Skills/skills.md#how-synced-skills-behave) and stop downloading new ones | Plugins and skills | User, local, or managed |
| [`syntaxHighlightingDisabled`](#syntaxhighlightingdisabled) | Turn off syntax highlighting in diffs and code blocks | Interface and terminal | Any file |
| [`taskOutputMaxChars`](#taskoutputmaxchars) | Removed in v2.1.277, together with the `TaskOutput` tool it sized | Memory and context | Any file |
| [`teammateDefaultModel`](#teammatedefaultmodel) | Removed in v2.1.234; see [Specify teammates and models](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) for how Claude Code picks a teammate’s model | Global config settings | Global config |
| [`teammateMode`](#teammatemode) | Choose how [agent team teammates display](../09-Agents-Patterns/agent-teams.md#choose-a-display-mode) | Agents, sessions, and worktrees | Any file |
| [`terminalProgressBarEnabled`](#terminalprogressbarenabled) | Hide the terminal progress bar in terminals that support it | Interface and terminal | Any file |
| [`terminalTitleFromRename`](#terminaltitlefromrename) | Stop [`/rename`](sessions.md#name-your-sessions) and `--name` from changing the terminal tab title | Interface and terminal | Any file |
| [`theme`](#theme) | Pick the interface [color theme](terminal-config.md#match-the-color-theme), built-in or custom | Interface and terminal | Any file |
| [`timeFormat`](#timeformat) | Show the times in the interface on a 12-hour or 24-hour clock, in UTC, or with a strftime pattern | Interface and terminal | Any file |
| [`timeZone`](#timezone) | Show the times in the interface in a time zone other than your system’s | Interface and terminal | Any file |
| [`tui`](#tui) | Choose the [fullscreen](fullscreen.md) or classic terminal renderer | Interface and terminal | Any file |
| [`ultracode`](#ultracode) | Have Claude plan a [workflow](workflows.md#let-claude-decide-with-ultracode) for each substantive task without being asked | Model and responses | Any file |
| [`useAutoModeDuringPlan`](#useautomodeduringplan) | Let the [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) classifier review shell commands in [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode); set `false` to get prompts instead | Permission settings | User, local, or managed |
| [`verbose`](#verbose) | Show [full tool output](cli-reference.md#cli-flags) instead of truncated summaries; `viewMode` takes precedence when both are set | Interface and terminal | Any file |
| [`viewMode`](#viewmode) | Start every session in [default, verbose, or focus view](cli-reference.md#cli-flags) | Interface and terminal | Any file |
| [`vimInsertModeRemaps`](#viminsertmoderemaps) | Map a two-key [INSERT-mode sequence](interactive-mode.md#remap-insert-mode-key-sequences) such as `jj` to Escape | Interface and terminal | User or managed |
| [`voice`](#voice) | Turn on [voice dictation](voice-dictation.md) and pick hold or tap mode | Interface and terminal | Any file |
| [`voiceEnabled`](#voiceenabled) | Turn on [voice dictation](voice-dictation.md) with the older single-key form | Interface and terminal | Any file |
| [`wheelScrollAccelerationEnabled`](#wheelscrollaccelerationenabled) | Turn off [mouse-wheel acceleration](fullscreen.md#mouse-wheel-scrolling) in fullscreen rendering | Interface and terminal | Any file |
| [`workflowKeywordTriggerEnabled`](#workflowkeywordtriggerenabled) | Let the word `ultracode` in a prompt start a [workflow](workflows.md); set `false` to type it without starting one | Hooks and automation | Any file |
| [`workflowSizeGuideline`](#workflowsizeguideline) | Set the agent count Claude aims for in [dynamic workflows](workflows.md) | Hooks and automation | Any file |
| [`worktree`](#worktree) | Configure how Claude Code creates git [worktrees](worktrees.md) | Agents, sessions, and worktrees | Any file |
| [`worktree.baseRef`](#worktree-baseref) | Branch new [worktrees](worktrees.md) from the remote default branch or your local HEAD | Agents, sessions, and worktrees | Any file |
| [`worktree.bgIsolation`](#worktree-bgisolation) | Let background sessions edit the working copy without a [worktree](worktrees.md) | Agents, sessions, and worktrees | Any file |
| [`worktree.sparsePaths`](#worktree-sparsepaths) | Check out only the directories you need in each [worktree](worktrees.md) | Agents, sessions, and worktrees | Any file |
| [`worktree.symlinkDirectories`](#worktree-symlinkdirectories) | Symlink large directories into each [worktree](worktrees.md) instead of duplicating them | Agents, sessions, and worktrees | Any file |
| [`wslInheritsWindowsSettings`](#wslinheritswindowssettings) | Have WSL read [managed settings](../13-Enterprise-Admin/managed-settings.md) from the Windows policy chain | Enterprise and managed settings | Managed |
[](#model-and-responses)
Model and responses
Choose which models Claude Code uses and how it responds. For how these settings interact with the `/model` command and environment variables, see [Model configuration](model-config.md).
[](#advisormodel)
`advisorModel`
Pick which model answers when Claude calls the server-side [advisor tool](advisor.md). Unset it to turn the advisor off. The advisor must be at least as capable as your main model. See [Choose an advisor model](advisor.md#choose-an-advisor-model) for the accepted pairings and what happens when you pick one that isn’t accepted. You don’t usually edit this key by hand. Run `/advisor` to open a picker that shows the current choice, the models that can advise, and **No advisor**. Claude Code saves your pick to this key in `~/.claude/settings.json`. If you pick from a [Remote Control](remote-control.md) client or in a session attached to a remote worker, the pick applies to that session only and doesn’t change this key. If your account requires the [usage-credits consent](advisor.md#fable-advisor-and-usage-credits), accept it first by running `/model fable`. Until you do, picking Fable in `/advisor` saves nothing and Claude Code tells you to run `/model fable` first.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of the aliases `"fable"`, `"opus"`, or `"sonnet"`, which resolve to Claude Code’s current default version of that model family, or a full model ID such as `"claude-opus-5-5"`
- **Default**: unset, so the advisor is off
- **Per-session overrides**: `--advisor` takes precedence over this key for one session. [`CLAUDE_CODE_DISABLE_ADVISOR_TOOL`](env-vars.md) turns the advisor off, and this key can’t turn it back on
settings.json
```python
{
"advisorModel": "opus"
}
```
The key has no effect on providers where the advisor [isn’t available](advisor.md#requirements), such as Amazon Bedrock and Claude Platform on AWS. `"fable"` requires [Fable access](advisor.md#choose-an-advisor-model).
[](#alwaysthinkingenabled)
`alwaysThinkingEnabled`
Turn [extended thinking](model-config.md#extended-thinking) off for every session by setting this to `false`. Thinking is on by default, so `true` changes nothing. Most people set this through `/config` rather than by editing the file. On models that always think, such as Opus 5.5, Sonnet 5.5, and the Fable models, `false` has no effect. On [third-party providers](third-party-integrations.md) Claude Code omits the `thinking` parameter instead of turning thinking off, so adaptive-reasoning models may still think. With thinking turned off on the Anthropic API, Claude Code sends effort `high` instead of a higher level to models it knows [don’t accept that combination](errors.md#effort-isnt-available-with-thinking-turned-off), such as Opus 5.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: no effect; thinking is already on
- `false`: Claude Code turns extended thinking off for every session
- **Default**: unset, so thinking is on for models that support it
- **Per-session overrides**: [`MAX_THINKING_TOKENS`](env-vars.md) takes precedence over this key for one session: `0` turns thinking off, under the same model and provider limits as `false`, and a positive value turns thinking on even when this key is `false`. On adaptive-reasoning models the number itself is ignored
settings.json
```python
{
"alwaysThinkingEnabled": false
}
```
[](#availablemodels)
`availableModels`
Restrict which models people can select for the main session, [subagents](../09-Agents-Patterns/sub-agents.md), [skills](../08-Plugins-Skills/skills.md), and the [advisor](advisor.md). A managed list constrains `/model`, `--model`, and the `model` key in a developer’s own files; a model outside it can’t be selected. With the default prefix matching, this doesn’t touch the Default option on its own; pair it with [`enforceAvailableModels`](#enforceavailablemodels) for that.
- **Scope**: [`Any file`](#scopes). Deploy it in managed settings to enforce it for an organization.
- **Type**: array of model aliases or IDs
- **Default**: unset, so every model is available
This example lets people select only Sonnet and Haiku models:
settings.json
```python
{
"availableModels": ["sonnet", "haiku"]
}
```
A model ID entry such as `"claude-opus-5"` also permits later versions that extend it, such as Opus 5.5. To block one of those versions, use [`deniedModels`](#deniedmodels). To make each model ID entry permit only the version it names, use [`availableModelsMatch`](#availablemodelsmatch). See [Restrict model selection](model-config.md#restrict-model-selection).
[](#availablemodelsmatch)
`availableModelsMatch`
Choose how [`availableModels`](#availablemodels) entries match model IDs. By default a model ID entry also permits later versions that extend it, so `"claude-opus-5"` permits Opus 5.5. With `"exact"`, each model ID entry permits only the version it names, so a newer version of that model stays blocked until you list it. Requires Claude Code v2.1.283 or later.
- **Scope**: [`Managed`](#scopes). Claude Code ignores the key in user, project, and local settings and in `--settings`, with a warning
- **Type**: string, one of:
- `"prefix"`: a model ID entry permits its version and any model ID that extends it with another segment
- `"exact"`: a model ID entry permits only the version it names, including that version’s dated IDs, so `"claude-opus-5"` permits Opus 5 but not `claude-opus-5-5`. A family alias such as `"opus"` still permits the whole family, and `best`, `opusplan`, and `default` entries are ignored
- **Default**: `"prefix"`
This example permits Opus 5 and Sonnet 5 and no later release of either:
managed-settings.json
```python
{
"availableModels": ["claude-opus-5", "claude-sonnet-5"],
"availableModelsMatch": "exact"
}
```
With `"exact"`, the Default option is also limited to the listed models whenever the list names at least one model or family. See [Block specific models or versions](model-config.md#block-specific-models-or-versions).
[](#deniedmodels)
`deniedModels`
Block specific models, with or without an [`availableModels`](#availablemodels) allowlist and even when that list permits them. Claude Code hides a blocked model from the `/model` picker, and the model can’t be selected anywhere `availableModels` is enforced. A session on the Default option doesn’t run a blocked model either, as [Block specific models or versions](model-config.md#block-specific-models-or-versions) describes. Requires Claude Code v2.1.283 or later.
- **Scope**: [`Managed`](#scopes). Claude Code ignores the key in user, project, and local settings and in `--settings`, with a warning
- **Type**: array of model aliases or IDs
- A family alias such as `"opus"` blocks every model in that family
- A model ID such as `"claude-opus-5-5"` blocks that version in every spelling, including dated and provider-specific IDs
- A model ID with no minor version, such as `"claude-opus-5"`, also blocks later minor versions such as Opus 5.5. Write `"claude-opus-5-0"` to block Opus 5 alone
- `best`, `opusplan`, and `default` entries are ignored
- **Default**: unset, so no model is blocked
This example permits Opus and Sonnet models and blocks Opus 5.5:
managed-settings.json
```python
{
"availableModels": ["opus", "sonnet"],
"deniedModels": ["claude-opus-5-5"]
}
```
See [Block specific models or versions](model-config.md#block-specific-models-or-versions).
[](#effortlevel)
`effortLevel`
Set a default [effort level](model-config.md#adjust-effort-level) for models you haven’t saved a level for. Lower levels are faster and cheaper on straightforward tasks, and higher levels reason more deeply on complex problems. When you run `/effort low`, `medium`, `high`, or `xhigh` in an interactive session on your machine, Claude Code saves the level for the active model under [`modelSettings`](#modelsettings) rather than writing this key. Before v2.1.251, `/effort` wrote this key. Within the same settings file, Claude Code uses a model’s saved level rather than this key. [`modelSettings`](#modelsettings) states the cross-file precedence. In a session attached to a remote worker, in a `-p` run, and in the Agent SDK, `/effort` applies to that session only. [Adjust effort level](model-config.md#adjust-effort-level) lists the interactive picks that also apply to that session only. The message that `/effort` prints says which happened.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"low"`: the least reasoning, for short, scoped, latency-sensitive tasks that aren’t intelligence-sensitive
- `"medium"`: reduces token usage for cost-sensitive work that can trade off some intelligence
- `"high"`: balances token usage and intelligence
- `"xhigh"`: deeper reasoning at higher token spend
- **Default**: unset
- **Per-session overrides**: `--effort` takes precedence over this key for one session, and [`CLAUDE_CODE_EFFORT_LEVEL`](env-vars.md) takes precedence over both
settings.json
```python
{
"effortLevel": "xhigh"
}
```
In your user settings file, `~/.claude/settings.json`, this key is the older form `/effort` wrote before it saved levels per model, and it keeps applying where it applied before, on Opus 5, Fable 5.1, and earlier models. Opus 5.5 and models released after it ignore it and start at their own default until you save a level for them, which `/effort` writes under [`modelSettings`](#modelsettings). In project, local, and managed settings, and with `--settings`, this key applies to every model.
[](#enforceavailablemodels)
`enforceAvailableModels`
The `/model` picker has a **Default** option, and [`default` model setting](model-config.md#default-model-setting) describes the model it resolves to. An [`availableModels`](#availablemodels) allowlist limits the models you can name, but with the default [prefix matching](#availablemodelsmatch) it doesn’t remap your account type’s default, so **Default** can still resolve to a model outside the list. This key closes that gap. Requires Claude Code v2.1.175 or later. When your organization deploys any managed settings, Claude Code reads this key from the managed source alone and ignores it in your other files.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: when **Default** would resolve to a model outside `availableModels`, Claude Code resolves it to the first available model in the list
- `false`: this key doesn’t change how **Default** resolves
- **Default**: `false`
This example restricts named selections to Sonnet and Haiku models and makes **Default** resolve to the first of them that is available:
settings.json
```python
{
"availableModels": ["sonnet", "haiku"],
"enforceAvailableModels": true
}
```
This key has no effect when `availableModels` is unset or empty. See [Enforce the allowlist for the Default model](model-config.md#enforce-the-allowlist-for-the-default-model). Requires Claude Code v2.1.175 or later.
[](#fallbackmodel)
`fallbackModel`
Name backup models for Claude Code to try, in order, when your primary model is overloaded or unavailable. Claude Code switches to the next available model in the chain for the rest of the turn and shows a notice. Without a chain, Claude Code retries the same model and then surfaces the server’s error, and you retry or switch models yourself. A switch means one turn with a cold [prompt cache](prompt-caching.md#switching-models) on the fallback model; your next message tries the primary model first again.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of model aliases or IDs; `"default"` expands to the default model
- **Default**: unset, so a failed request isn’t retried on another model
- **Per-session overrides**: `--fallback-model` takes precedence over this key for one session
This example tries Sonnet 5 first, then Haiku 4.5, when your primary model fails:
settings.json
```python
{
"fallbackModel": ["claude-sonnet-5", "claude-haiku-4-5"]
}
```
Unlike most array settings, this key doesn’t merge across settings files: the highest-precedence file that defines it supplies the whole chain. If your project file sets `["claude-sonnet-5"]` and your user file sets `["claude-haiku-4-5"]`, the chain is `["claude-sonnet-5"]` only. Claude Code keeps at most three distinct allowed models from the list and ignores the rest. See [Fallback model chains](model-config.md#fallback-model-chains).
[](#fastmode)
`fastMode`
Turn [fast mode](fast-mode.md) on for sessions where it’s available, for interactive work like rapid iteration or live debugging where you want speed at a higher cost per token. You don’t usually edit this key by hand: running `/fast` writes `fastMode: true` to `~/.claude/settings.json`, and running it again to turn fast mode off removes the key. Fast mode runs only on Opus 5.5, Opus 5, and Opus 4.8: turning it on from another model switches you to Opus, and switching to an unsupported model turns it off. See [Switch models while fast mode is on](fast-mode.md#switch-models-while-fast-mode-is-on).
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns fast mode on for sessions where it’s available
- `false`: fast mode stays off
- **Default**: unset, so fast mode is off
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_FAST_MODE`](env-vars.md) turns fast mode off for one session, and this key can’t turn it back on
settings.json
```python
{
"fastMode": true
}
```
[](#fastmodepersessionoptin)
`fastModePerSessionOptIn`
Normally, running `/fast` saves [`fastMode`](#fastmode) to a person’s user settings, so fast mode is on at the start of every later session. Set this key to `true` to stop that: a saved `fastMode: true` no longer turns fast mode on at session start, and each person has to run `/fast` in each session they want it. Claude Code leaves the `fastMode` key in their file, so turning this key off restores the old behavior. Owners on Team or Enterprise plans can deploy it organization-wide through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md). When managed settings set the key, `/fast on` is refused outside interactive terminal sessions and reports that your organization has disabled fast mode. That covers [non-interactive mode](headless.md), the [VS Code extension](../03-IDE-Integrations/vs-code.md), and [cloud sessions](claude-code-on-the-web.md).
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: a saved `fastMode: true` no longer turns fast mode on at session start, so each person runs `/fast` in each session they want it; a `fastMode: true` passed with `--settings` still counts for that session unless managed settings set this key
- `false`: a saved `fastMode: true` turns fast mode on at the start of every later session
- **Default**: `false`
settings.json
```python
{
"fastModePerSessionOptIn": true
}
```
See [Require per-session opt-in](fast-mode.md#require-per-session-opt-in).
[](#language)
`language`
Have Claude respond in a language other than English by default. There is no fixed list for responses: Claude Code passes the value verbatim to Claude as an instruction to always respond in that language, so any language name Claude can read works. Claude Code doesn’t check the value, so a misspelled name reaches Claude as written rather than producing an error. The same value sets the language for [voice dictation](voice-dictation.md#change-the-dictation-language), which does have a fixed list of [supported dictation languages](voice-dictation.md#change-the-dictation-language), and for auto-generated session titles.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, any language name, such as `"japanese"`, `"spanish"`, or `"french"`; Claude Code doesn’t validate it
- **Default**: unset; session titles then match the language of your conversation
settings.json
```python
{
"language": "japanese"
}
```
[](#maxeffortlevel)
`maxEffortLevel`
Cap the [effort level](model-config.md#adjust-effort-level) a session can use, leaving lower levels available. Any higher level runs at the cap instead, including one from `/effort`, the `/model` picker, `--effort`, [`CLAUDE_CODE_EFFORT_LEVEL`](env-vars.md), a skill’s or subagent’s `effort` frontmatter, or the model’s own default. Claude Code applies the cap itself before each request, so it holds on every provider, including Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry. Requires Claude Code v2.1.267 or later.
- **Scope**: [`Any file`](#scopes). Deploy it in managed settings to enforce it for an organization. When several scopes set a cap, the lowest applies, so a cap set in one scope can’t be raised from another
- **Type**: string, one of `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"`. A `"max"` value sets no cap
- **Default**: unset, so no cap applies
- **Per-model caps**: add `maxEffortLevel` to a model’s [`modelSettings`](#modelsettings) entry. That entry replaces this key for the model only within the settings source that sets both, such as your user settings or one [managed source](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources). Set `"max"` there to exempt the model from that source’s cap; Claude Code still applies caps from other sources
This example caps every model at `medium` and exempts Sonnet 4.6:
settings.json
```python
{
"maxEffortLevel": "medium",
"modelSettings": {
"claude-sonnet-4-6": {
"maxEffortLevel": "max"
}
}
}
```
When your organization also sets an [effort limit](model-config.md#organization-effort-limits) for a model, the lower of the two caps applies.
[](#model)
`model`
Set the model every new session uses, so you don’t have to pick one with `/model` each time. Setting it here doesn’t stop you from switching mid-session. If your admin set an [organization default model](model-config.md#organization-default-model) to override user selection, you get that model even when you set this key in user, project, or local settings.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a model alias or full model ID
- **Default**: unset, so Claude Code uses your account’s default model
- **Per-session overrides**: `--model` takes precedence over [`ANTHROPIC_MODEL`](env-vars.md), and both take precedence over this key for one session, including over a managed `model`; an [`availableModels`](#availablemodels) list still applies to the pick
settings.json
```python
{
"model": "claude-sonnet-5"
}
```
A value here outranks [`ANTHROPIC_DEFAULT_MODEL`](model-config.md#set-a-default-model-for-new-sessions), which Claude Code uses only when nothing else selects a model.
[](#modeloverrides)
`modelOverrides`
Map Anthropic model IDs to provider-specific model IDs, such as Amazon Bedrock inference profile ARNs. Each model picker entry then uses its mapped value when calling the provider API. Administrators use this on [Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry](model-config.md#override-model-ids-per-version) to route each model version to a specific inference profile, version name, or deployment for governance, cost allocation, or regional routing.
- **Scope**: [`Any file`](#scopes)
- **Type**: object mapping model ID to provider model ID
- **Default**: unset
This example routes every call for Opus 4.6 to the named Bedrock inference profile:
settings.json
```python
{
"modelOverrides": {
"claude-opus-4-6": "arn:aws:bedrock:us-east-1:123456789012:inference-profile/example"
}
}
```
See [Override model IDs per version](model-config.md#override-model-ids-per-version).
[](#modelpicker)
`modelPicker`
List the models the `/model` picker offers, in the order you write them and under labels you choose, so the picker lists the models your organization runs, after the built-in lineup or instead of it. Each row’s `model` is taken verbatim, so it accepts anything `--model` accepts: an alias such as `opus`, an Anthropic model ID, or a provider-format ID for Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or an LLM gateway. Requires Claude Code v2.1.242 or later.
- **Scope**: [`User or managed`](#scopes). Claude Code reads the key from managed settings, `--settings`, and user settings, and ignores it in project and local settings so a repository you clone can’t relabel the picker. The highest of those three that sets the key supplies the whole lineup, and Claude Code never combines lineups from two sources.
- **Type**: object with an `options` array of rows and an optional `replaceBuiltInOptions` Boolean
- **Default**: unset, so the picker shows the built-in lineup
This example adds two Bedrock deployments after the built-in lineup, under names your team recognizes:
managed-settings.json
```python
{
"modelPicker": {
"options": [
{ "model": "us.anthropic.claude-opus-4-8", "label": "Opus (production)" },
{
"model": "us.anthropic.claude-sonnet-4-6",
"label": "Sonnet (production)",
"description": "Day-to-day work"
}
]
}
}
```
[](#fields-for-modelpicker)
Fields for `modelPicker`
The key takes two fields, one for the rows themselves and one for whether they replace the built-in lineup or add to it.
| Field | Type | What it does |
|:------------------------|:-------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `options` | array of rows, each with a required `model` and optional `label`, `description`, and `behavesAs` | The rows the picker shows, in this order, except that a grayed-out row moves to the bottom. Without a `label`, Claude Code titles the row with the built-in name for a model it knows, or the model ID otherwise, and without a `description` it writes a generic second line |
| `replaceBuiltInOptions` | Boolean, default `false` | Set it to `true` to show only these rows, **Default**, and a row for the model the session is already using. Leave it unset to add these rows after the built-in lineup |
An entry in `options` can also carry an optional `behavesAs` string beside its `model`, which requires v2.1.257 or later. Set it to the ID of a model your Claude Code version already knows, such as `claude-opus-4-8`, on an entry whose `model` is newer than your version. Claude Code then applies that known model’s capabilities and effort defaults to the entry instead of treating its model as unknown. The entry’s label and the model ID Claude Code sends in requests don’t change. With `replaceBuiltInOptions` on, Claude Code hides every other row: the built-in lineup, the rows it adds for [`availableModels`](#availablemodels) entries, the models [gateway discovery](../13-Enterprise-Admin/llm-gateway-protocol.md#model-discovery) found, and [`ANTHROPIC_CUSTOM_MODEL_OPTION`](model-config.md#add-a-custom-model-option). With it off, Claude Code skips a listed model that the built-in lineup already covers. A label changes what the picker shows, not which model Claude Code runs. An [`availableModels`](#availablemodels) allowlist still applies to these rows. Before you add a listed model to the allowlist, read [Merge behavior](model-config.md#merge-behavior): a specific model ID narrows its family’s wildcard entry. Claude Code also checks each row against the session before it shows the picker:
- **Dropped**: a row Claude Code can’t serve, such as a retired model or a model your organization has no access to
- **Grayed out**: a row you can’t select yet, shown with the reason
- **No row survives**: Claude Code keeps the built-in lineup, filtered by the allowlist as usual
Claude Code drops a row it can’t parse and keeps the rest. See [Fix a broken settings file](settings.md#fix-a-broken-settings-file).
[](#modelpricing)
`modelPricing`
Report spend at the rates your organization pays instead of list price. Set it when your organization has contracted rates, so the dollar figures developers see match your bill. Claude Code applies the rates in `/usage`, the [status line](statusline.md), the Agent SDK’s `total_cost_usd`, the [`--max-budget-usd`](cli-reference.md) limit, and the [OpenTelemetry](../13-Enterprise-Admin/monitoring-usage.md) cost metric and events. You supply the rates: Claude Code doesn’t read them from your contract or the Claude Console. Requires Claude Code v2.1.242 or later.
- **Scope**: [`Managed`](#scopes). Deploy the key through server-managed settings, an MDM policy, a `managed-settings.json` file, or a [policy helper](../13-Enterprise-Admin/managed-settings.md#compute-the-policy-with-a-helper-program). Claude Code ignores it in user, project, and local settings, in `--settings`, and on Windows in the user-writable [HKCU registry](../13-Enterprise-Admin/managed-settings.md#where-each-mechanism-stores-the-policy). With server-managed settings, each session reports costs at list price until that session’s [settings fetch](../13-Enterprise-Admin/server-managed-settings.md#fetch-and-caching-behavior) has confirmed the setting. A host application that embeds Claude Code and sets [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](env-vars.md) can supply a table of its own through the SDK [`managedSettings`](../05-Agent-SDK/agent-sdk-typescript.md#options) option, which Claude Code uses only when no managed source sets the key and only in Claude Code v2.1.246 or later.
- **Type**: object with an optional `multiplier` and an optional `overrides` map
- **Default**: unset, so Claude Code reports list price unless a host application supplies a table
Set `multiplier` alone for a flat discount or markup, `overrides` alone for per-model rates, or both. This example sets contracted rates for Sonnet 4.6 and then reduces every figure, the Sonnet row included, by 15%:
managed-settings.json
```python
{
"modelPricing": {
"multiplier": 0.85,
"overrides": {
"claude-sonnet-4-6": {
"input": 2.4,
"output": 12,
"cacheRead": 0.24,
"cacheWrite": 3
}
}
}
}
```
Set `multiplier` above 1, up to 10, to mark every figure up. A markup requires Claude Code v2.1.271 or later. Earlier versions ignore a `multiplier` above 1 with a warning and keep the rest of the setting. For the steps, including how to confirm the rates are in effect, see [Report spend at your contracted rates](../17-Billing-Plans/costs.md#report-spend-at-your-contracted-rates).
[](#fields-for-modelpricing)
Fields for `modelPricing`
| Field | Type | What it does |
|:-------------|:--------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `multiplier` | number greater than 0 and at most 10 | Scales every cost Claude Code computes, whether or not an `overrides` row covers it. Below 1 is a discount, above 1 a markup |
| `overrides` | map of model ID to a rate object with `input`, `output`, `cacheRead`, and `cacheWrite`, each 0 to 10000 | The USD-per-million-token rates for that model, all four required. `cacheWrite` covers both five-minute and one-hour cache writes. See [Which models a row applies to](#which-models-a-modelpricing-row-applies-to) |
Claude Code uses a row’s rates exactly as you wrote them, without adding the fast-mode surcharge or the [US-only-inference rate](../17-Billing-Plans/about-claude-pricing.md). If you also set `multiplier`, Claude Code applies it on top of the row’s rates. Claude Code drops a row with a rate it can’t parse, or a `multiplier` it can’t parse, and keeps the rest; see [Fix a broken settings file](settings.md#fix-a-broken-settings-file).
[](#which-models-a-modelpricing-row-applies-to)
Which models a `modelPricing` row applies to
Claude Code decides which models a row applies to from the row’s key:
- **A built-in model’s ID**: a key Claude Code itself uses for a built-in model, whether that key is the model’s own ID, such as `claude-sonnet-4-6`, or its Bedrock, Agent Platform, or Foundry ID. Claude Code applies the row to every dated snapshot ID and provider-specific ID of that model.
- **Any other key**: a key that isn’t a built-in model’s ID, such as a gateway model alias. Claude Code applies the row to that one ID only. When a model ID matches one of your keys exactly and also falls under a row keyed by a built-in model’s ID, Claude Code uses the exact match.
- **A Bedrock application inference profile**: once Claude Code has resolved the profile to the model it routes to, through your [`modelOverrides`](#modeloverrides) map or the [`bedrock:GetInferenceProfile` lookup](amazon-bedrock.md#iam-configuration), Claude Code applies that model’s row to the profile.
[](#modelsettings)
`modelSettings`
Save an [effort level](model-config.md#adjust-effort-level) for each model you use. Requires Claude Code v2.1.251 or later. In an interactive session on your machine, when you save `low`, `medium`, `high`, or `xhigh` as your default with `/effort` or the `/model` picker’s effort slider, Claude Code writes that level here under the model you’re using, so you rarely edit this key yourself. When you pick one of those levels in the [VS Code extension’s model picker](../03-IDE-Integrations/vs-code.md#use-the-prompt-box), Claude Code saves it here the same way. The [`effortLevel`](#effortlevel) entry lists the sessions where `/effort` applies to that session only. Edit the key by hand to change or remove a level you saved. A model’s `effortLevel` here takes precedence over the top-level [`effortLevel`](#effortlevel) in the same settings file. Across files, Claude Code resolves each model separately: the highest-precedence [settings file](settings.md#settings-precedence) that sets either an `effortLevel` for that model or a top-level `effortLevel` that [applies to that model](#effortlevel) decides, so an `effortLevel` in managed settings outranks a level you saved in user settings. [Adjust effort level](model-config.md#adjust-effort-level) lists what else can override a saved level, such as `--effort` at launch. To cap one model’s effort rather than set its level, add a [`maxEffortLevel`](#maxeffortlevel) field to that model’s entry. The field requires Claude Code v2.1.267 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: object mapping a model name to an object with an `effortLevel` field, one of `"low"`, `"medium"`, `"high"`, or `"xhigh"`, a [`maxEffortLevel`](#maxeffortlevel) field, or both
- **Default**: unset
Claude Code writes each entry under the model’s canonical name, such as `claude-opus-5-5`, and matches that model’s alias, date-suffixed, `[1m]`, and recognized provider-specific IDs to the same entry. This example keeps Opus 5.5 at `high` while other models use their own saved or default levels:
settings.json
```python
{
"modelSettings": {
"claude-opus-5-5": {
"effortLevel": "high"
}
}
}
```
Run `/effort auto` to clear your saved level for the model you’re using. Claude Code leaves the other entries and any top-level `effortLevel` in place.
[](#outputstyle)
`outputStyle`
Select an [output style](output-styles.md) by name. An output style is a saved set of instructions that changes Claude’s role, tone, and output format, such as the built-in Explanatory and Learning styles or one you wrote yourself. If you change this key during a session, Claude uses the new style starting with your next message. For what that message costs in prompt caching, see [Changing output style](prompt-caching.md#changing-output-style). Before v2.1.251, the edit applied only after you ran `/clear` or started a new session.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, the name of a [built-in](output-styles.md#built-in-output-styles) or [custom](output-styles.md#create-a-custom-output-style) output style
- **Default**: unset, so Claude Code uses the default style
This example selects the built-in Explanatory style, which adds educational insights between tasks:
settings.json
```python
{
"outputStyle": "Explanatory"
}
```
[](#promptcachettl)
`promptCacheTtl`
Choose how long the [prompt cache](prompt-caching.md) holds the main conversation. This key applies to your interactive, `-p`, and Agent SDK turns, together with the helpers Claude Code runs inline with them. The one-hour lifetime keeps the cache warm across longer breaks, and the API [bills each cache write at a higher rate](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#pricing) than at the five-minute lifetime. Requires Claude Code v2.1.242 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"5m"`: the cache holds for five minutes
- `"1h"`: the cache holds for an hour
- **Default**: unset, so each main-conversation request gets [its default lifetime](prompt-caching.md#which-ttl-each-request-gets)
- **Per-session overrides**: [`FORCE_PROMPT_CACHING_5M`](env-vars.md) takes precedence over everything else, then [`CLAUDE_CODE_PROMPT_CACHE_TTL`](env-vars.md), then this key, and last [`ENABLE_PROMPT_CACHING_1H`](env-vars.md)
This example keeps the main conversation on the one-hour lifetime and leaves subagents on five minutes:
settings.json
```python
{
"promptCacheTtl": "1h",
"subagentPromptCacheTtl": "5m"
}
```
For what each lifetime costs, see [Cache lifetime](prompt-caching.md#cache-lifetime).
[](#showthinkingsummaries)
`showThinkingSummaries`
See summaries of Claude’s [extended thinking](model-config.md#extended-thinking) in interactive sessions. Set it if you want the full summaries when you expand thinking with `Ctrl+O`. When unset or `false`, the Anthropic API redacts thinking blocks and Claude Code shows a collapsed stub; third-party providers don’t redact.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: you see full thinking summaries when you expand thinking with `Ctrl+O`
- `false`: the Anthropic API redacts thinking blocks and Claude Code shows a collapsed stub
- **Default**: `false`
settings.json
```python
{
"showThinkingSummaries": true
}
```
Redaction changes only what you see, not what the model generates. To reduce thinking spend, [lower the budget or disable thinking](model-config.md#extended-thinking) instead.
[](#subagentpromptcachettl)
`subagentPromptCacheTtl`
Choose how long the [prompt cache](prompt-caching.md) holds the requests Claude Code makes outside the main conversation. This key applies to [subagents](../09-Agents-Patterns/sub-agents.md), [workflows](workflows.md), and Claude Code’s own background and helper requests, such as compaction and session titles. The one-hour lifetime keeps the cache warm across longer breaks, and the API [bills each cache write at a higher rate](../04-API-Reference/Guides/build-with-claude-prompt-caching.md#pricing) than at the five-minute lifetime. Requires Claude Code v2.1.242 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"5m"`: the cache holds for five minutes
- `"1h"`: the cache holds for an hour
- **Default**: unset, so each of these requests gets [its default lifetime](prompt-caching.md#which-ttl-each-request-gets)
- **Per-session overrides**: [`FORCE_PROMPT_CACHING_5M`](env-vars.md) takes precedence over everything else, then [`CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL`](env-vars.md), then this key, then [`ENABLE_PROMPT_CACHING_1H`](env-vars.md), which asks for the one-hour lifetime on every request. For where a subagent’s own frontmatter value ranks, see [Choose the TTL yourself](prompt-caching.md#choose-the-ttl-yourself)
This example gives subagents and the other requests outside the main conversation the one-hour lifetime:
settings.json
```python
{
"subagentPromptCacheTtl": "1h"
}
```
This key covers the requests [`promptCacheTtl`](#promptcachettl) doesn’t, so set both to choose a lifetime for every request Claude Code makes. For how a subagent’s cache differs from the main conversation’s, see [Subagents and the cache](prompt-caching.md#subagents-and-the-cache).
[](#switchmodelsonflag)
`switchModelsOnFlag`
Choose what happens when a [safety classifier flags a request](model-config.md#automatic-model-fallback): switch to the fallback model and continue, or pause so you can choose between switching and editing the prompt.
- **Scope**: [`Any file`](#scopes). Appears in `/config` as **Switch models when a message is flagged**.
- **Type**: Boolean
- `true`: Claude Code switches to the fallback model and continues
- `false`: in an interactive session Claude Code pauses so you can choose between switching and editing the prompt; where no dialog can show, such as a `-p` run, the flagged request ends as an error
- **Default**: `true`, switch automatically
settings.json
```python
{
"switchModelsOnFlag": false
}
```
See [Ask before switching](model-config.md#ask-before-switching).
[](#ultracode)
`ultracode`
Start sessions with [ultracode](workflows.md#let-claude-decide-with-ultracode) on. With it on, Claude plans a workflow for each substantive task instead of waiting for you to ask. Claude plans workflows only when [dynamic workflows](workflows.md) are enabled for you and your model supports `xhigh` effort. The key doesn’t change the session’s effort level: ultracode runs at whichever level the session uses. Claude Code reads this key but never writes it: `/effort ultracode` turns ultracode on for the current session only.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: sessions start with ultracode on when dynamic workflows are enabled for you and your model supports `xhigh`
- `false`: sessions start with ultracode off
- **Default**: unset, so ultracode is off
- **Per-session overrides**: `/effort ultracode` turns ultracode on for one session without this key, and `/effort ultracode off` turns it off for one session when this key is `true`. The `--effort ultracode` flag also turns it on for one session, at `xhigh` effort, and requires Claude Code v2.1.203 or later
settings.json
```python
{
"ultracode": true
}
```
The session’s effort level comes from [`effortLevel`](#effortlevel), [`modelSettings`](#modelsettings), and the other [effort sources](model-config.md#adjust-effort-level), and an [effort cap](model-config.md#organization-effort-limits) such as [`maxEffortLevel`](#maxeffortlevel) lowers that level without turning ultracode off. This and the `/effort ultracode off` form require Claude Code v2.1.284 or later. Before v2.1.284, `ultracode: true` ran the session at `xhigh` effort, and an effort cap below `xhigh` kept ultracode off. An Agent SDK `apply_flag_settings` control request also accepts the key.
[](#permission-settings)
Permission settings
Decide what Claude can do without asking, which permission mode a session starts in, and what auto mode’s classifier allows. For rule syntax and the permission model, see [Configure permissions](permissions.md).
[](#allowmanagedpermissionrulesonly)
`allowManagedPermissionRulesOnly`
Make managed settings the only settings source of permission rules. Claude Code then ignores `allow`, `ask`, and `deny` rules in user, project, local, and `--settings` files, ignores `--allowedTools`, hides the always-allow choices in permission prompts, and stops saving new rules. When [parent settings from an embedding host](../13-Enterprise-Admin/managed-settings.md#let-an-embedding-host-add-policy) apply, Claude Code treats them as part of the managed tier. It drops their `allow` rules and `additionalDirectories`, and keeps their `deny` and `ask` rules except `Read` and `Edit` rules whose pattern starts with `!`. A host can’t carve paths out of the managed rules with a `!` rule, whether or not you set this key. `--disallowedTools` rules and the current session’s `deny` and `ask` rules still apply, including after Claude Code reloads settings mid-session. They only restrict, so they can’t widen what the managed rules grant. Before v2.1.257, Claude Code dropped those command-line and session rules at the first settings reload. For what a `!` pattern in a `--disallowedTools` or session rule can carve out, see [Read and Edit rules](permissions.md#read-and-edit).
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: managed settings become the only settings source of permission rules
- `false`: Claude Code applies permission rules from user, project, local, and `--settings` files in addition to the managed ones
- **Default**: unset, so Claude Code applies permission rules from user, project, and local settings and from `--settings`, in addition to the managed ones
managed-settings.json
```python
{
"allowManagedPermissionRulesOnly": true
}
```
This key doesn’t lock down the MCP server allowlist; for that, set [`allowManagedMcpServersOnly`](#allowmanagedmcpserversonly). See [Managed-only settings](../13-Enterprise-Admin/managed-settings.md#managed-only-settings).
[](#automode)
`autoMode`
Add your own rules to what the [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) classifier blocks and allows. Use it to tell the classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations. The classifier ships with [built-in allow and deny rules](auto-mode-config.md#inspect-the-defaults-and-your-effective-config). Include the literal string `"$defaults"` in an array to keep those built-in rules at that position and add yours around them; leave it out to replace them with yours.
- **Scope**: [`User or managed`](#scopes)
- **Type**: object with `environment`, `allow`, `soft_deny`, and `hard_deny` arrays of prose rules, plus the [`classifyAllShell`](#automode-classifyallshell) Boolean
- **Default**: unset, so the classifier uses only its [built-in rules](auto-mode-config.md#inspect-the-defaults-and-your-effective-config)
This example keeps the built-in `soft_deny` rules, through `"$defaults"`, and adds one more that blocks `terraform apply`:
settings.json
```python
{
"autoMode": {
"soft_deny": ["$defaults", "Never run terraform apply"]
}
}
```
When more than one of those files sets the same array, Claude Code concatenates the entries. For the rule format and how each array is applied, see [Configure auto mode](auto-mode-config.md).
[](#automode-classifyallshell)
`autoMode.classifyAllShell`
Send every Bash and PowerShell command through the auto mode classifier while auto mode is active. By default, auto mode suspends only allow rules that could run arbitrary code: tool-wide and wildcard rules such as `Bash(*)`, and interpreter or shell-wrapper prefixes such as `Bash(python *)`. A command that any other allow rule matches, such as `Bash(npm test)`, skips the classifier unless it carries [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode). When it skips, a destructive argument the rule’s prefix didn’t anticipate can get through unseen. Setting this key suspends every shell allow rule for the session so the classifier sees every command. Requires Claude Code v2.1.193 or later.
- **Scope**: [`User or managed`](#scopes). Read wherever [`autoMode`](#automode) is read.
- **Type**: Boolean
- `true`: while auto mode is active, Claude Code sends every Bash and PowerShell command through the classifier and suspends your shell allow rules; outside auto mode the rules still apply
- `false`: auto mode suspends only allow rules that could run arbitrary code, such as `Bash(*)` and `Bash(python *)`; a command that any other allow rule matches skips the classifier unless it carries [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode), and every other shell command goes through it
- **Default**: `false`
settings.json
```python
{
"autoMode": {
"classifyAllShell": true
}
}
```
See [Route all shell commands through the classifier](auto-mode-config.md#route-all-shell-commands-through-the-classifier). Requires Claude Code v2.1.193 or later.
[](#disableautomode)
`disableAutoMode`
Remove [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) from the `Shift+Tab` cycle. Any session that would otherwise [start in auto mode](permission-modes.md#which-mode-a-session-starts-in), whether from `--permission-mode auto`, a settings file, or the built-in default, starts in `default` instead. Administrators set it in managed settings to prevent developers in their organization from using auto mode.
- **Scope**: [`Any file`](#scopes). Most useful in [managed settings](../13-Enterprise-Admin/managed-settings.md), where users can’t override it. Also accepted under `permissions` as `permissions.disableAutoMode`.
- **Type**: the string `"disable"`
- **Default**: unset
settings.json
```python
{
"disableAutoMode": "disable"
}
```
[](#permissions)
`permissions`
Control which tools Claude can use without asking, which ones always prompt, and which ones are blocked, and set the [permission mode](permission-modes.md) a session starts in. Every `permissions.*` key below nests under this object.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `allow`, `ask`, `deny`, `additionalDirectories`, `blockReadsOutsideWorkingDirectories`, `defaultMode`, `disableBypassPermissionsMode`, and `disableAutoMode`
- **Default**: unset
This example approves `npm run` commands without asking, prompts before `git push`, blocks reads of `.env`, and starts sessions in `acceptEdits`:
settings.json
```python
{
"permissions": {
"allow": ["Bash(npm run *)"],
"ask": ["Bash(git push *)"],
"deny": ["Read(./.env)"],
"defaultMode": "acceptEdits"
}
}
```
The three rule arrays share one syntax; see [Permission rule syntax](#permission-rule-syntax) under `permissions.allow`. For how permission rules from different files combine, see [how permission rules merge across scopes](permissions.md#settings-precedence); for how settings keys in general combine, see [Settings precedence](settings.md#settings-precedence) on the settings guide.
[](#useautomodeduringplan)
`useAutoModeDuringPlan`
Choose whether Claude Code uses the auto mode classifier to review shell commands in plan mode. With the default `true`, the classifier reviews each command during planning when auto mode is available and you see no prompt, except for [critical-path removals](permission-modes.md#critical-paths). Set `false` to get a permission prompt for every command outside the built-in read-only set. Appears in `/config` as **Use auto mode during plan**.
- **Scope**: [`User, local, or managed`](#scopes). A repository can’t turn it off for you.
- **Type**: Boolean
- `true`: the same as unset; when auto mode is available, the classifier reviews each shell command during planning instead of prompting you for it, except [critical-path removals](permission-modes.md#critical-paths). A `false` in any of these files still turns it off
- `false`: you get a permission prompt for every command outside the built-in read-only set
- **Default**: `true`
settings.json
```python
{
"useAutoModeDuringPlan": false
}
```
[](#permissions-allow)
`permissions.allow`
List the tool uses Claude Code approves without asking you. In an MCP rule, `*` can appear only in the tool name after the `mcp__<server>__` prefix, such as `mcp__github__get_*`; it can’t appear in the server name.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of permission rule strings
- **Default**: unset
- **Per-session overrides**: `--allowedTools` adds allow rules for one session, and a deny rule from any settings file still blocks a tool it names
This example approves `git diff` and lets Claude Code read your `.zshrc` without asking:
settings.json
```python
{
"permissions": {
"allow": ["Bash(git diff *)", "Read(~/.zshrc)"]
}
}
```
Claude Code applies `allow` rules from a project’s `.claude/settings.json` only after you accept the [workspace trust dialog](permissions.md#project-allow-rules-and-workspace-trust) for that folder.
[](#permission-rule-syntax)
Permission rule syntax
Permission rules follow the format `Tool` or `Tool(specifier)`. Claude Code evaluates `deny` rules first, then `ask`, then `allow`, and the first match decides regardless of how specific each rule is; see the [permission rule evaluation order](permissions.md#manage-permissions). Each row shows one rule shape and what it matches.
| Rule | What it matches |
|:-------------------------------|:---------------------------------|
| `Bash` | Every Bash command |
| `Bash(npm run *)` | Commands starting with `npm run` |
| `Read(./.env)` | Reads of the `.env` file |
| `WebFetch(domain:example.com)` | Fetch requests to example.com |
For the complete rule syntax, including wildcard behavior, tool-specific patterns for Read, Edit, WebFetch, MCP, and Agent rules, and the security limitations of Bash patterns, see [Permission rule syntax](permissions.md#permission-rule-syntax).
[](#permissions-ask)
`permissions.ask`
List the tool uses that prompt you for confirmation even in a permission mode that would otherwise approve them, such as `acceptEdits` or `bypassPermissions`. In `dontAsk` mode Claude Code denies a matching tool use instead of prompting.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of permission rule strings
- **Default**: unset
settings.json
```python
{
"permissions": {
"ask": ["Bash(git push *)"]
}
}
```
[](#permissions-deny)
`permissions.deny`
List the tool uses Claude Code blocks. Use it for files that hold API keys, secrets, or environment values: Claude Code excludes matching files from file discovery and search results, denies reads of them, and blocks the [Edit and Write tools](permissions.md#read-and-edit) on the matching paths. Read and Edit deny rules apply to Claude’s built-in file tools, to file commands Claude Code recognizes in Bash, such as `cat`, `head`, `tail`, `sed`, and `tee`, and to the targets of Bash [redirections](permissions.md#redirections) such as `> file` and `< file`; they don’t apply to a command that reads files without naming them, such as `grep -r pattern .`, or to arbitrary subprocesses, so for OS-level enforcement [enable the sandbox](sandboxing.md).
- **Scope**: [`Any file`](#scopes)
- **Type**: array of permission rule strings
- **Default**: unset
- **Per-session overrides**: `--disallowedTools` adds deny rules for one session alongside this key
This example denies reads of `.env` files, the `secrets` directory, and a credentials file, and blocks `curl` commands:
settings.json
```python
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.json)",
"Bash(curl *)"
]
}
}
```
Tool names accept glob patterns, so `"*"` denies every tool and `"mcp__*"` denies every MCP tool. Claude Code ignores a deny rule for the [`EndConversation`](tools-reference.md#endconversation-tool-behavior) tool as long as any other tool is still available to Claude. A `Bash` deny rule matches the command as Claude writes it, so `Bash(curl *)` doesn’t stop `/usr/bin/curl` or `sh -c 'curl …'`; see [what a Bash rule doesn’t match](permissions.md#bash-rule-limits). This key replaces the deprecated `ignorePatterns` configuration.
[](#permissions-additionaldirectories)
`permissions.additionalDirectories`
Give Claude file access to directories outside the one you started in, as additional [working directories](permissions.md#working-directories). Most `.claude/` configuration is [not discovered](permissions.md#additional-directories-grant-file-access-not-configuration) from these directories.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of directory paths
- **Default**: unset
- **Per-session overrides**: `--add-dir` and `/add-dir` add directories for one session alongside this key
settings.json
```python
{
"permissions": {
"additionalDirectories": ["../docs/"]
}
}
```
Like `allow` rules, entries in a project’s `.claude/settings.json` take effect only after you accept the [workspace trust dialog](permissions.md#project-allow-rules-and-workspace-trust) for that folder.
[](#permissions-blockreadsoutsideworkingdirectories)
`permissions.blockReadsOutsideWorkingDirectories`
Make Claude’s file tools refuse reads outside your [working directories](permissions.md#working-directories) in every permission mode, including `bypassPermissions`. Claude Code denies `Read`, `Grep`, `Glob`, and `LSP` calls on those paths and tells Claude to ask you to add the directory with `/add-dir`. Files Claude Code itself needs stay readable, such as your skills, plugins, rules, agents, commands, and the `CLAUDE.md` memory file under `~/.claude/`. Requires Claude Code v2.1.257 or later. Claude Code doesn’t refuse shell commands the same way:
- [Actions no mode auto-approves](permission-modes.md#actions-no-mode-auto-approves) covers when a shell command that reads such a path prompts you
- [Sandboxed commands under the block](#sandboxed-commands-under-the-block) covers what a sandboxed command can read
A Bash command the shell parser can’t trace, such as one that changes directory more than once or runs a subshell, prompts you even in auto mode and `bypassPermissions` mode. The prompt appears even when the command names no path outside the working directories. This prompt doesn’t apply when the command runs in the [sandbox](sandboxing.md) and the sandbox enforces the block. Claude Code also writes `true` here when you choose to block such reads on [auto mode’s prompt before the first read outside the working directories](permission-modes.md#first-read-outside-the-working-directories).
- **Scope**: [`Any file`](#scopes). A `true` in any file applies, so a repository can turn the block on for itself but can’t lift yours.
- **Type**: Boolean
- `true`: Claude’s file tools refuse reads outside the working directories
- `false`: the same as unset; the block still applies if another file sets `true`
- **Default**: unset, so reads outside the working directories follow your [permission mode](permission-modes.md)
settings.json
```python
{
"permissions": {
"blockReadsOutsideWorkingDirectories": true
}
}
```
Directories you add with `--add-dir`, `/add-dir`, or `additionalDirectories` in your user or managed settings count as working directories for the block. Directories added only in repository settings don’t count: those in `.claude/settings.json`, and those in `.claude/settings.local.json` unless git reports that file as untracked. In a directory that isn’t a git repository, or when git tracks the file, Claude Code treats `.claude/settings.local.json` as repository settings, so put directories you want to keep readable in your user settings instead. When [`autoMemoryDirectory`](#automemorydirectory) comes from the project’s `.claude/settings.json`, or from a `.claude/settings.local.json` [treated as repository-supplied](permissions.md#when-your-local-settings-file-needs-trust), Claude Code loads no [auto memory](memory.md#storage-location) from that directory and saves none to it. To lift the block, remove the key from every settings file that sets it, then start a new session.
[](#sandboxed-commands-under-the-block)
Sandboxed commands under the block
When [sandboxing](sandboxing.md) is on, the block also covers sandboxed commands. Claude Code denies them read access to your home directory and to the other roots that hold user files: `/Users`, `/home`, `/root`, `/Volumes`, `/mnt`, `/media`, `/run/media`, and `/srv`. It then re-opens the working directories, [worktrees](worktrees.md) Claude Code creates in the session, the session temp directory, and the parts of `~/.claude` that commands need, such as skills and plugins. While the block is in force, `allowRead` and `allowWrite` entries from repository settings don’t count. When the session’s working directory is a linked [git worktree](worktrees.md), including one Claude Code entered mid-session, the repository’s common `.git` directory stays readable and writable to sandboxed commands, so git keeps working there. In these cases the block doesn’t reach sandboxed commands, while Claude’s file tools keep enforcing it:
- Filesystem isolation is off through [`sandbox.filesystem.disabled`](#sandbox-filesystem-disabled)
- [`allowManagedReadPathsOnly`](#sandbox-filesystem-allowmanagedreadpathsonly) is set
- The path of the directory you started Claude Code in contains a glob character such as `*`, `?`, or `[`
Under the block, Claude Code re-opens your global git configuration files to sandboxed commands so `git` keeps your identity and settings:
- `~/.gitconfig`
- The `config`, `ignore`, and `attributes` files under `$XDG_CONFIG_HOME/git`, which defaults to `~/.config/git`
- Files your global git configuration names through `[include]`, `[includeIf]`, `core.excludesFile`, or `core.attributesFile`
Claude Code judges each file separately. When a file lies where a sandboxed command can write, directly or through a symlink, Claude Code doesn’t re-open the files it names. On Linux and WSL2, a configuration file that is a symlink can stay unreadable at its own path, and `git` then runs without it. `~/.git-credentials` and `$XDG_CONFIG_HOME/git/credentials` stay blocked. If a re-opened file holds a secret, such as an `http.extraHeader` token, add its path to [`sandbox.filesystem.denyRead`](#sandbox-filesystem-denyread). A `denyRead` entry that covers a file always takes precedence over this re-open.
[](#permissions-defaultmode)
`permissions.defaultMode`
Set the [permission mode](permission-modes.md) new sessions start in. When you leave it unset, sessions start in the [built-in default](permission-modes.md#which-mode-a-session-starts-in) for your surface.
- **Scope**: [`Any file`](#scopes). `auto` and `bypassPermissions` don’t take effect from project or local settings, so set them in `~/.claude/settings.json` instead. Before v2.1.257, `bypassPermissions` took effect from any file. For conversations the VS Code extension starts, Claude Code reads only user, managed, and `--settings` values.
- **Type**: string, one of:
- `"default"`: Claude Code runs only reads without asking
- `"acceptEdits"`: Claude Code also runs file edits and common filesystem commands such as `mkdir` and `mv` without asking
- `"plan"`: Claude Code reads and plans but blocks edits until you approve a plan
- `"auto"`: Claude Code runs without routine prompts; before actions such as shell commands and network requests run, a background classifier checks that they align with your request
- `"dontAsk"`: Claude Code auto-denies every call that would otherwise prompt; reads, other actions that need no approval, and pre-approved tools still run
- `"bypassPermissions"`: Claude Code runs everything without asking
- `"manual"`: an alias for `"default"`, in Claude Code v2.1.200 or later
- **Default**: unset
- **Per-session overrides**: `--permission-mode`, and its equivalent `--dangerously-skip-permissions` for `bypassPermissions`, take precedence over this key for one session
settings.json
```python
{
"permissions": {
"defaultMode": "acceptEdits"
}
}
```
Permission rules layer on top of every mode: `deny` rules block in every mode, including `bypassPermissions`. See [Permission modes](permission-modes.md). `manual` names the permission mode labeled Manual in the CLI and the VS Code extension; the alias requires Claude Code v2.1.200 or later. In cloud sessions, Claude Code honors only `acceptEdits`, `plan`, `default`, and `auto` from this key. For conversations the VS Code extension starts, see [which setting the extension reads for the starting permission mode](permission-modes.md#switch-permission-modes).
[](#permissions-disablebypasspermissionsmode)
`permissions.disableBypassPermissionsMode`
Prevent anyone from entering `bypassPermissions` mode. Claude Code then rejects the `--dangerously-skip-permissions` flag, and ignores an [agent definition’s](../09-Agents-Patterns/sub-agents.md#permission-modes) `permissionMode: bypassPermissions`, so the subagent runs with the parent session’s permission mode.
- **Scope**: [`Any file`](#scopes). Typically set in [managed settings](../13-Enterprise-Admin/managed-settings.md) to enforce organizational policy.
- **Type**: the string `"disable"`
- **Default**: unset
- **Per-session overrides**: this key takes precedence over `--dangerously-skip-permissions`, which Claude Code rejects while the key is set
settings.json
```python
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
```
Before v2.1.223, Claude Code applied the frontmatter permission mode even with bypass disabled.
[](#skipautopermissionprompt)
`skipAutoPermissionPrompt`
Skip the one-time notice describing [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) that Claude Code shows when you first enter auto mode yourself, for example through your own settings or the mode selector, rather than when the built-in default starts a session in it. Claude Code shows that notice once and then records that it was shown, so this key only matters where the notice hasn’t appeared yet.
- **Scope**: [`User or managed`](#scopes). A repository can’t set it for you.
- **Type**: Boolean
- `true`: Claude Code skips the notice
- `false`: the same as unset; the notice appears once unless another of these files sets `true`
- **Default**: unset, so the notice appears once
settings.json
```python
{
"skipAutoPermissionPrompt": true
}
```
[](#skipdangerousmodepermissionprompt)
`skipDangerousModePermissionPrompt`
Skip the confirmation dialog Claude Code shows before a session enters `bypassPermissions` mode, whether from `--dangerously-skip-permissions` or from `defaultMode: "bypassPermissions"`. Claude Code writes `true` here in your user settings when you accept that dialog once.
- **Scope**: [`User, local, or managed`](#scopes). An untrusted repository can’t skip the dialog for you.
- **Type**: Boolean
- `true`: Claude Code skips the confirmation dialog before a session enters `bypassPermissions` mode
- `false`: the same as unset; the dialog appears unless another of these files sets `true`
- **Default**: unset, so the dialog appears
settings.json
```python
{
"skipDangerousModePermissionPrompt": true
}
```
[](#sandbox-settings)
Sandbox settings
Isolate the commands Claude runs from your filesystem, your network, and your credentials. For how sandboxing works and platform requirements, see [Sandboxing](sandboxing.md).
[](#sandbox)
`sandbox`
Isolate the Bash commands Claude runs from your filesystem and network with [sandboxing](sandboxing.md). Turn the sandbox on with `enabled`, then narrow or widen what sandboxed commands can touch with the `filesystem`, `network`, and `credentials` sub-objects. The sandbox runs on macOS, Linux, and WSL2.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `enabled`, `failIfUnavailable`, `autoAllowBashIfSandboxed`, `excludedCommands`, `allowUnsandboxedCommands`, `enableWeakerNestedSandbox`, `enableWeakerNetworkIsolation`, `allowAppleEvents`, `bwrapPath`, `socatPath`, `ignoreViolations`, and `ripgrep`, plus the `filesystem`, `network`, and `credentials` objects
- **Default**: unset, so Claude Code runs commands without a sandbox
This turns the sandbox on, skips permission prompts for sandboxed commands, runs `docker` outside the sandbox, opens two extra write paths, hides your AWS credentials file, and pre-allows GitHub and npm:
settings.json
```python
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"excludedCommands": ["docker *"],
"filesystem": {
"allowWrite": ["/tmp/build", "~/.kube"],
"denyRead": ["~/.aws/credentials"]
},
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
```
Claude Code takes a Boolean key’s value from the highest-precedence settings scope that sets it, so a managed `enabled` or `failIfUnavailable` overrides anything a developer sets. It merges array keys across every settings scope the session loads, so a developer can append entries; see [Keep developers from widening the policy](sandboxing.md#keep-developers-from-widening-the-policy) for the managed-only locks. To require the sandbox for an organization, see [Enforce sandboxing with managed settings](sandboxing.md#enforce-sandboxing-with-managed-settings).
[](#sandbox-enabled)
`sandbox.enabled`
Turn on [sandboxing](sandboxing.md) for Bash commands. When you pick a mode in the `/sandbox` panel, Claude Code writes this key to `.claude/settings.local.json` for the current project; set it in `~/.claude/settings.json` to sandbox every project.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code sandboxes Bash commands
- `false`: Bash commands run unsandboxed
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"enabled": true
}
}
```
On Linux and WSL2 the sandbox needs `bubblewrap` and `socat`; see [Set up Linux and WSL2](sandboxing.md#set-up-linux-and-wsl2). When the sandbox can’t start, Claude Code shows a warning and runs commands unsandboxed unless you also set [`failIfUnavailable`](#sandbox-failifunavailable).
[](#sandbox-failifunavailable)
`sandbox.failIfUnavailable`
Make Claude Code exit with an error at startup when `sandbox.enabled` is `true` but the sandbox can’t start, because a dependency is missing or the platform is unsupported. Without it, Claude Code shows a warning and runs commands unsandboxed. Use it in managed settings when your organization requires sandboxing as a hard gate.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code exits with an error at startup when `sandbox.enabled` is `true` but the sandbox can’t start
- `false`: Claude Code shows a warning and runs commands unsandboxed
- **Default**: `false`
This makes every managed machine sandbox commands or refuse to start:
managed-settings.json
```python
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true
}
}
```
See [Enforce sandboxing with managed settings](sandboxing.md#enforce-sandboxing-with-managed-settings).
[](#sandbox-autoallowbashifsandboxed)
`sandbox.autoAllowBashIfSandboxed`
Let Claude Code run sandboxed Bash commands without a permission prompt. Commands that can’t run in the sandbox still go through the regular permission flow, and `deny` rules and content-scoped `ask` rules such as `Bash(git push *)` still apply; a bare `Bash` ask rule is skipped for sandboxed commands. Set it to `false` to send sandboxed commands through the regular permission flow too, which the `/sandbox` **Mode** tab calls regular permissions mode.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code runs sandboxed Bash commands without a permission prompt, subject to `deny` rules and content-scoped `ask` rules; `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` turns auto-allow off
- `false`: sandboxed commands go through the regular permission flow, so your allow rules and permission mode decide. The `/sandbox` **Mode** tab calls this regular permissions mode
- **Default**: `true`
This keeps the sandbox on and sends sandboxed commands through the regular permission flow:
settings.json
```python
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": false
}
}
```
See [Sandbox modes](sandboxing.md#sandbox-modes) for what auto-allow mode still prompts on and how it behaves in plan mode.
[](#sandbox-excludedcommands)
`sandbox.excludedCommands`
Name commands that Claude Code runs outside the sandbox, such as tools that don’t work under it. Each entry uses the same syntax as the content of a `Bash(...)` [permission rule](permissions.md#permission-rule-syntax): an exact command, a prefix such as `docker *`, or a wildcard pattern. Your entries take a Bash call out of the sandbox only when they cover every command in it, and some call shapes stay sandboxed even then. A `docker *` entry alone doesn’t take `npm ci && docker build .` out of the sandbox.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of command patterns
- **Default**: unset, so no command is excluded
settings.json
```python
{
"sandbox": {
"excludedCommands": ["docker *"]
}
}
```
Claude Code keeps a Bash call sandboxed when it has one of these shapes, among others:
- A command starting with `sudo`, `eval`, or `xargs`
- A `cd`, `pushd`, or `popd`, wherever it appears in the call
- A command substitution, a subshell, or a control-flow block such as `if` or `for`
- A redirection, such as `docker build . > build.log`, other than one that only duplicates a file descriptor, as `2>&1` does
- A command name that comes from a variable
For example, `cd build && docker compose up` stays sandboxed under a `docker *` entry, and adding a `cd` entry doesn’t change that. Excluded commands still go through the regular permission flow. Exclusion is a convenience, not a security boundary: prefer [`filesystem.allowWrite`](#sandbox-filesystem-allowwrite) when a tool only needs to write somewhere specific. Claude Code merges entries across every settings scope the session loads, and there is no managed-only lock for this list, so keep a managed list narrow.
[](#sandbox-allowunsandboxedcommands)
`sandbox.allowUnsandboxedCommands`
Let Claude retry a command outside the sandbox with the `dangerouslyDisableSandbox` parameter after the sandbox blocks it. Set it to `false` so Claude Code ignores that parameter completely and every command Claude runs must be sandboxed or appear in [`excludedCommands`](#sandbox-excludedcommands). The `/sandbox` **Overrides** tab shows that state as **Strict sandbox mode**. Use `false` in managed settings for policies that require strict sandboxing.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude can retry a command outside the sandbox with the `dangerouslyDisableSandbox` parameter after the sandbox blocks it
- `false`: Claude Code ignores that parameter, so every command Claude runs is sandboxed or appears in `excludedCommands`
- **Default**: `true`
This enforces strict sandbox mode for everyone the managed settings cover:
managed-settings.json
```python
{
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false
}
}
```
An unsandboxed retry goes through the regular permission flow, with a prompt in Manual mode. See [The unsandboxed retry escape hatch](sandboxing.md#the-unsandboxed-retry-escape-hatch). To see when commands you type yourself at the [`!` shell-mode prompt](interactive-mode.md#shell-mode-with-prefix) run sandboxed, see [strict sandbox mode](sandboxing.md#the-unsandboxed-retry-escape-hatch).
[](#sandbox-filesystem)
`sandbox.filesystem`
Control which paths sandboxed commands can read and write. By default they can write to the working directory, the per-user temp directory, and directories you add with `--add-dir`, `/add-dir`, or `permissions.additionalDirectories`, and can read the rest of the filesystem, including credential files. Widen or narrow that with the four path lists, or switch the filesystem layer off with `disabled`. See [Filesystem isolation](sandboxing.md#filesystem-isolation) for the default boundaries.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `allowWrite`, `denyWrite`, `denyRead`, and `allowRead` arrays, plus the `allowManagedReadPathsOnly` and `disabled` Booleans
- **Default**: unset, so the default read and write boundaries apply
This lets sandboxed commands write to a build directory and your kubeconfig, and hides your AWS credentials file:
settings.json
```python
{
"sandbox": {
"filesystem": {
"allowWrite": ["/tmp/build", "~/.kube"],
"denyRead": ["~/.aws/credentials"]
}
}
}
```
Claude Code enforces these lists at the OS sandbox boundary, so they apply to every subprocess a sandboxed command starts, such as `kubectl`, `terraform`, or `npm`. Claude Code adds your [permission rules](sandboxing.md#permission-rules) to the same lists: `Edit` allow and deny rules to `allowWrite` and `denyWrite`, `Read` deny rules to `denyRead`, and `WebFetch(domain:...)` allow and deny rules to the [`network`](#sandbox-network) domain lists. Unless a managed-only lock is set, Claude Code merges every list across the settings files the session loads. [`allowManagedReadPathsOnly`](#sandbox-filesystem-allowmanagedreadpathsonly) limits `allowRead` to entries from managed settings, and [`allowManagedDomainsOnly`](#sandbox-network-allowmanageddomainsonly) does the same for allowed domains. [Configure sandboxing](sandboxing.md#configure-sandboxing) covers sources you exclude with `--setting-sources`. When you edit a list during a session, Claude Code [applies the change to the running session](settings.md#when-edits-take-effect).
[](#sandbox-path-prefixes)
Sandbox path prefixes
Paths in `allowWrite`, `denyWrite`, `denyRead`, `allowRead`, and [`credentials.files`](#sandbox-credentials-files) resolve by their prefix:
| 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 `//path` prefix for absolute paths also works. If you use single-slash `/path` expecting project-relative resolution, switch to `./path`. This syntax differs from [Read and Edit permission rules](permissions.md#read-and-edit), which use `//path` for absolute and `/path` for project-relative: sandbox filesystem paths use standard conventions, so `/tmp/build` is an absolute path. Claude Code strips a trailing slash from a directory path, so `~/.aws` and `~/.aws/` match the same directory. Before v2.1.224, Claude Code passed the trailing slash through to the sandbox, and Claude could still read or write paths under a `denyRead` or `denyWrite` entry written with one. Claude Code also removes a trailing `/**`, so `~/build/**` and `~/build` cover the same directory. Whether a wildcard such as `*` works depends on which list the entry is in and on the platform:
- **`allowWrite` and `denyWrite`**: on macOS, wildcards work. On Linux and WSL2, the sandbox mounts concrete paths, so Claude Code skips an entry that contains `*`, `?`, or `[` once the trailing `/**` is removed, and that entry has no effect. Claude Code adds the paths from your `Edit` permission rules to these lists, so the same limit applies to them, and the **Config** tab of `/sandbox` warns about `Edit` and `Read` permission rules that contain wildcards.
- **`denyRead` and `allowRead`**: wildcards work on every platform. On Linux and WSL2, Claude Code expands a read entry to the concrete paths it matches, which it doesn’t do for the write lists.
[](#sandbox-filesystem-allowwrite)
`sandbox.filesystem.allowWrite`
Add paths where sandboxed commands can write, beyond the working directory, the per-user temp directory, and the directories you’ve added with `--add-dir`, `/add-dir`, or `permissions.additionalDirectories`. Use it when a subprocess such as `kubectl` or a build tool needs to write outside the project.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of path strings, using the [sandbox path prefixes](#sandbox-path-prefixes)
- **Default**: unset, so sandboxed commands can write to the working directory, the per-user temp directory, directories you’ve added with `--add-dir` or `/add-dir`, and directories in [`permissions.additionalDirectories`](#permissions-additionaldirectories)
This lets a build write under `/tmp/build` and lets `kubectl` update your kubeconfig:
settings.json
```python
{
"sandbox": {
"filesystem": {
"allowWrite": ["/tmp/build", "~/.kube"]
}
}
}
```
Claude Code merges `allowWrite` entries and the paths from your `Edit(...)` allow permission rules across every settings scope the session loads, leaving out the ones from repository settings while [`permissions.blockReadsOutsideWorkingDirectories`](#sandboxed-commands-under-the-block) is on. An `allowWrite` entry can’t lift a [protected path](sandboxing.md#protected-paths).
[](#sandbox-filesystem-denywrite)
`sandbox.filesystem.denyWrite`
Block sandboxed commands from writing to specific paths, including paths inside a directory that is otherwise writable.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of path strings, using the [sandbox path prefixes](#sandbox-path-prefixes)
- **Default**: unset
This keeps sandboxed commands from changing system configuration or installing binaries:
settings.json
```python
{
"sandbox": {
"filesystem": {
"denyWrite": ["/etc", "/usr/local/bin"]
}
}
}
```
Claude Code merges entries across every settings scope the session loads, and adds the paths from your `Edit(...)` deny permission rules.
[](#sandbox-filesystem-denyread)
`sandbox.filesystem.denyRead`
Block sandboxed commands from reading specific paths, such as credential files that the default read policy would otherwise expose. To protect a credential file and keep it usable through the sandbox proxy, see [`sandbox.credentials`](#sandbox-credentials) instead.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of path strings, using the [sandbox path prefixes](#sandbox-path-prefixes)
- **Default**: unset, so sandboxed commands keep the [default read access](sandboxing.md#filesystem-isolation), which includes credential files such as `~/.aws/credentials`
settings.json
```python
{
"sandbox": {
"filesystem": {
"denyRead": ["~/.aws/credentials"]
}
}
}
```
Claude Code merges entries across every settings scope the session loads, and adds the paths from your `Read(...)` deny permission rules. When [`filesystem.disabled`](#sandbox-filesystem-disabled) is `true`, Claude Code doesn’t enforce these entries.
[](#sandbox-filesystem-allowread)
`sandbox.filesystem.allowRead`
Re-open reading for specific paths inside a region that [`denyRead`](#sandbox-filesystem-denyread) blocks, to build workspace-only read access. An exact or wildcard `denyRead` entry stays blocked inside a broader `allowRead`, as the [overlap table](sandboxing.md#configure-sandboxing) shows. When a wildcard `denyRead` entry such as `~/**/.env` matches a directory, Claude Code blocks reads of its contents as well. Before v2.1.236 on macOS, Claude Code re-opened the paths a wildcard `denyRead` entry matched wherever a broader `allowRead` entry covered them, and left a matched directory’s contents readable.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of path strings, using the [sandbox path prefixes](#sandbox-path-prefixes)
- **Default**: unset
This blocks reads of your home directory except the project itself:
settings.json
```python
{
"sandbox": {
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."]
}
}
}
```
Claude Code resolves a `.` entry to the project root in project settings and to `~/.claude` in user settings. Claude Code merges entries across every settings file the session loads unless [`allowManagedReadPathsOnly`](#sandbox-filesystem-allowmanagedreadpathsonly) is set, and leaves out entries from repository settings while [`permissions.blockReadsOutsideWorkingDirectories`](#sandboxed-commands-under-the-block) is on.
[](#sandbox-filesystem-allowmanagedreadpathsonly)
`sandbox.filesystem.allowManagedReadPathsOnly`
Honor only the [`allowRead`](#sandbox-filesystem-allowread) entries that come from managed settings, so developers can’t re-open read access to paths your organization blocked. Claude Code still merges `denyRead` entries from every settings scope the session loads.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code honors only the `allowRead` entries from managed settings
- `false`: `allowRead` entries merge from every settings scope the session loads
- **Default**: `false`
This blocks reads of the home directory, re-opens `~/work`, and stops developers from re-opening anything else:
managed-settings.json
```python
{
"sandbox": {
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["~/work"],
"allowManagedReadPathsOnly": true
}
}
}
```
See [Keep developers from widening the policy](sandboxing.md#keep-developers-from-widening-the-policy).
[](#sandbox-filesystem-disabled)
`sandbox.filesystem.disabled`
Skip filesystem isolation while keeping network isolation. Sandboxed commands get unrestricted read and write access to the host filesystem, and their network egress stays confined to [`network.allowedDomains`](#sandbox-network-alloweddomains). Use it when you sandbox to control where commands connect rather than what they write. Requires Claude Code v2.1.216 or later.
- **Scope**: [`User or managed`](#scopes). When managed settings configure `sandbox.filesystem` at all, or list a `sandbox.credentials.files` entry with `"mode": "deny"`, only managed settings can set it.
- **Type**: Boolean
- `true`: Claude Code skips filesystem isolation and keeps network isolation
- `false`: filesystem isolation stays on
- **Default**: `false`, so filesystem isolation stays on
This leaves the filesystem open and confines network egress to GitHub and npm:
settings.json
```python
{
"sandbox": {
"enabled": true,
"filesystem": {
"disabled": true
},
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
```
With the layer off, Claude Code doesn’t enforce `denyRead` or `credentials.files` `deny` entries, while `credentials.envVars` entries and applied `mask` entries keep working. [`autoAllowBashIfSandboxed`](#sandbox-autoallowbashifsandboxed) still defaults to `true`, so set it to `false` to keep prompting. See [Disable filesystem isolation](sandboxing.md#disable-filesystem-isolation) for the full list of sources that can set it and what changes when isolation is off. Requires Claude Code v2.1.216 or later.
[](#sandbox-ignoreviolations)
`sandbox.ignoreViolations`
Silence sandbox violation reports for paths you expect a command to probe and be refused, such as a tool that checks `/etc/hosts` on startup, so those denials don’t show up as violations or in what Claude sees. The sandbox still blocks the access; only the report is suppressed. Keys are substrings to match against the command, with `*` matching every command, and values are substrings of the violation to ignore for that command, such as a filesystem path.
- **Scope**: [`Any file`](#scopes)
- **Type**: object mapping a command substring to an array of violation substrings, usually paths
- **Default**: unset, so every violation is reported
settings.json
```python
{
"sandbox": {
"ignoreViolations": {
"*": ["/etc/hosts"]
}
}
}
```
[](#sandbox-enableweakernestedsandbox)
`sandbox.enableWeakerNestedSandbox`
Run the Linux sandbox inside an unprivileged Docker container, where bubblewrap can’t mount a fresh `/proc`. Instead the inner sandbox bind-mounts the container’s existing `/proc`, which exposes process information that a fresh mount would hide. This reduces security; use it only when the outer container already provides the isolation you need.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the inner sandbox bind-mounts the container’s existing `/proc` instead of mounting a fresh one
- `false`: the sandbox mounts a fresh `/proc`, which doesn’t work in an unprivileged Docker container
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"enabled": true,
"enableWeakerNestedSandbox": true
}
}
```
Linux and WSL2 only. See [Bubblewrap fails to start inside a container](sandboxing.md#troubleshooting).
[](#sandbox-enableweakernetworkisolation)
`sandbox.enableWeakerNetworkIsolation`
Let sandboxed commands on macOS reach the system TLS trust service, `com.apple.trustd.agent`. Go-based tools such as `gh`, `gcloud`, and `terraform` need it to verify TLS certificates when you use [`network.httpProxyPort`](#sandbox-network-httpproxyport) with a MITM proxy and a custom CA. This reduces security by opening a potential data exfiltration path through the trust service.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: sandboxed commands on macOS can reach `com.apple.trustd.agent`
- `false`: sandboxed commands on macOS can’t reach the system TLS trust service
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"enabled": true,
"enableWeakerNetworkIsolation": true
}
}
```
If you don’t use a MITM proxy, list the failing tools in [`excludedCommands`](#sandbox-excludedcommands) instead; see [Go-based CLIs fail TLS verification on macOS](sandboxing.md#troubleshooting).
[](#sandbox-allowappleevents)
`sandbox.allowAppleEvents`
Let sandboxed commands on macOS send Apple Events, which `open`, `osascript`, and tools that open URLs in a browser need; without it they fail with error `-600`. This removes code-execution isolation: sandboxed commands can launch other applications unsandboxed with no user prompt, and can send AppleScript commands to running applications such as Terminal, subject to the per-app macOS automation-consent prompt (TCC).
- **Scope**: [`User or managed`](#scopes)
- **Type**: Boolean
- `true`: sandboxed commands on macOS can send Apple Events
- `false`: sandboxed commands on macOS can’t send Apple Events, so `open` and `osascript` fail with error `-600`
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"enabled": true,
"allowAppleEvents": true
}
}
```
To keep isolation and still run one such tool, add it to [`excludedCommands`](#sandbox-excludedcommands) instead. See [Apple Events on macOS](sandboxing.md#security-limitations).
[](#sandbox-ripgrep)
`sandbox.ripgrep`
Point the sandbox at a ripgrep binary of your own instead of the one Claude Code uses, for example when your platform needs a differently built `rg`.
- **Scope**: [`User or managed`](#scopes)
- **Type**: object with `command`, the path to the ripgrep binary, and optional `args`, an array of arguments to prepend
- **Default**: unset, so the sandbox uses the same ripgrep binary as Claude Code. That is the bundled binary unless you set [`USE_BUILTIN_RIPGREP`](env-vars.md) to `0`
settings.json
```python
{
"sandbox": {
"ripgrep": {
"command": "/usr/local/bin/rg"
}
}
}
```
[](#sandbox-bwrappath)
`sandbox.bwrapPath`
Point the sandbox at a bubblewrap binary installed outside `PATH`, such as a vendored copy on an air-gapped host. Claude Code uses the path both for the startup dependency check and when it wraps each sandboxed command.
- **Scope**: [`Managed`](#scopes). Claude Code reads it only from managed settings so that a user, project, or local file can’t point the sandbox at a different binary.
- **Type**: string, an absolute path; Claude Code drops a relative path and falls back to `PATH` lookup
- **Default**: unset, so Claude Code finds `bwrap` on `PATH`
managed-settings.json
```python
{
"sandbox": {
"enabled": true,
"bwrapPath": "/opt/admin/bwrap"
}
}
```
Linux and WSL2 only.
[](#sandbox-socatpath)
`sandbox.socatPath`
Point the sandbox network proxy at a `socat` binary installed outside `PATH`.
- **Scope**: [`Managed`](#scopes)
- **Type**: string, an absolute path; Claude Code drops a relative path and falls back to `PATH` lookup
- **Default**: unset, so Claude Code finds `socat` on `PATH`
managed-settings.json
```python
{
"sandbox": {
"enabled": true,
"socatPath": "/opt/admin/socat"
}
}
```
Linux and WSL2 only.
[](#sandbox-credentials)
`sandbox.credentials`
Declare the credential files and environment variables to [protect from sandboxed commands](sandboxing.md#protect-credentials). Each entry names a file `path` or a variable `name` and a `mode`: `deny` hides the credential inside the sandbox, and `mask` shows sandboxed commands a placeholder while the [sandbox proxy](sandboxing.md#mask-credentials) substitutes the real value on outbound requests. Claude Code protects only the entries you list; there is no built-in credential deny list.
- **Scope**: [`Any file`](#scopes). Claude Code honors `mask` entries, `allowPlaintextInject`, `awsPairs`, and `sigv4` only from user settings, managed settings, and the `--settings` flag.
- **Type**: object with `files`, `envVars`, `allowPlaintextInject`, `awsPairs`, and `sigv4`
- **Default**: unset, so no credentials are protected
This hides your AWS credentials file and removes `GITHUB_TOKEN` from sandboxed commands:
settings.json
```python
{
"sandbox": {
"credentials": {
"files": [{ "path": "~/.aws/credentials", "mode": "deny" }],
"envVars": [{ "name": "GITHUB_TOKEN", "mode": "deny" }]
}
}
}
```
The `deny` file protection is part of the filesystem layer, so it doesn’t apply when you [disable filesystem isolation](sandboxing.md#disable-filesystem-isolation); the environment variable protection still does.
[](#invalid-credential-entries-in-managed-settings)
Invalid credential entries in managed settings
When a managed `sandbox.credentials` entry fails validation, Claude Code keeps protecting the credential where it can:
- An entry in `files` or `envVars` that still has a valid `path` or `name` and a `mode` of `mask` or `deny`, such as one whose `extract` pattern has no capturing group, is degraded to `mode: "deny"` with a warning, so the credential stays blocked, not masked, until you fix the entry. A degraded `files` entry pins [`filesystem.disabled`](sandboxing.md#disable-filesystem-isolation) like an explicit `deny` entry, and the warning notes that its read block isn’t enforced if managed settings turn filesystem isolation off.
- An entry with an unknown `mode` or an invalid `path` or `name` is stripped.
- Each case warns; whether an entry is degraded or stripped, the remaining valid entries are still enforced, and a wholly invalid `credentials` value is dropped while the rest of `sandbox` still applies.
Applies in v2.1.191 and later; before v2.1.221, every invalid entry was stripped. For the other managed keys with per-field handling, see [Invalid entries in managed settings](../13-Enterprise-Admin/managed-settings.md#invalid-entries-in-managed-settings).
[](#sandbox-credentials-files)
`sandbox.credentials.files`
Protect credential files or directories from sandboxed commands. With `"mode": "deny"`, Claude Code blocks reads of the path inside the sandbox, the same read block as [`sandbox.filesystem.denyRead`](#sandbox-filesystem-denyread). With `"mode": "mask"`, sandboxed commands on Linux and WSL2 read a sentinel copy of the file, and the sandbox proxy substitutes the real value on outbound requests to that entry’s `injectHosts`; on macOS the file is unreadable inside the sandbox instead. `"mode": "mask"` requires Claude Code v2.1.221 or later.
- **Scope**: [`Any file`](#scopes). Claude Code drops `mask` entries from project `.claude/settings.json` and local `.claude/settings.local.json`.
- **Type**: array of objects, each with `path` and a `mode` of `"deny"` or `"mask"`, plus the optional [mask fields for files](#mask-fields-for-files)
- **Default**: unset, so no credential files are protected
This hides your AWS credentials file and masks the `gh` hosts file, substituting the real value only on requests to `api.github.com`:
settings.json
```python
{
"sandbox": {
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.config/gh/hosts.yml", "mode": "mask", "injectHosts": ["api.github.com"] }
]
}
}
}
```
Paths use the same [prefixes](#sandbox-path-prefixes) as the `sandbox.filesystem.*` settings, and Claude Code merges the arrays from every settings scope the session loads. [Protect credentials](sandboxing.md#protect-credentials) covers what still applies from sources you exclude with `--setting-sources`. `mask` entries require Claude Code v2.1.221 or later. `mask` substitution runs only through the sandbox proxy, so set [`sandbox.network.tlsTerminate`](#sandbox-network-tlsterminate), or [`allowPlaintextInject`](#sandbox-credentials-allowplaintextinject) for plain-HTTP test networks. `mask` applies to a single file, so list each credential file individually. Claude Code accepts but ignores the `mask` fields on a `deny` entry. [Mask credential files](sandboxing.md#mask-credential-files) covers which settings sources are honored and when an entry falls back to `deny`.
[](#mask-fields-for-files)
Mask fields for files
A `mask` entry accepts these optional fields. Without `extract` or `decode`, Claude Code replaces the entire file content with one sentinel. On macOS with filesystem isolation on, Claude Code applies a `mask` entry as `deny` before `extract` or `decode` runs; see [Mask credential files](sandboxing.md#mask-credential-files).
| Field | Type | What it does |
|:-------------------|:-------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `extract` | string, a regular expression with at least one capturing group | Mask only the text captured by group 1 of each match, so the rest of the file stays parseable. With `decode` also set, Claude Code checks each capture as a possible JWT instead of replacing it outright. Requires v2.1.221 or later |
| `onExtractNoMatch` | `"warn"`, `"deny"`, or `"error"`; default `"warn"` | What happens when `extract` or `decode` finds nothing to mask. `warn` leaves the file readable as-is inside the sandbox, `deny` makes it unreadable, and `error` stops sandbox setup until you fix the configuration. Claude Code treats `deny` as `error` when the read block wouldn’t be enforced, because you [disable filesystem isolation](sandboxing.md#disable-filesystem-isolation) or a [`sandbox.filesystem.allowRead`](#sandbox-filesystem-allowread) entry re-opens the path. Requires v2.1.221 or later; the `decode` case requires v2.1.224 or later |
| `decode` | the string `"jwt"` | Find JSON Web Tokens (JWTs) in the file, with a built-in pattern or with `extract` when set, verify each candidate, and replace it with a structurally valid fake token, so code inside the sandbox that decodes the token keeps working. When no candidate verifies, `onExtractNoMatch` governs the outcome. Requires v2.1.224 or later |
| `maskClaims` | array of strings, at least one claim name; requires `decode` | Mask only the named top-level payload claims inside each verified JWT and rebuild the token around the modified payload, so the other claims stay readable. When no named claim matches, `onExtractNoMatch` governs the outcome. Requires v2.1.224 or later |
| `maskDuplicates` | Boolean, default `false` | Also replace verbatim copies of each masked value elsewhere in the file, such as a secret pasted into a comment. Claude Code matches raw substrings, so reserve it for long, high-entropy secrets. Consulted only when `extract` or `decode` is set. Requires v2.1.221 or later |
| `injectHosts` | array of strings, each a host that [`sandbox.network.allowedDomains`](#sandbox-network-alloweddomains) also admits | Narrow the hosts where the sandbox proxy substitutes the real value. When unset, the proxy substitutes it on requests to every host in `sandbox.network.allowedDomains`. Requires v2.1.221 or later |
This masks only the `oauth_token` value in the `gh` hosts file, replaces every other copy of it in the file, makes the file unreadable if the pattern matches nothing, and substitutes the real token only on requests to `api.github.com`:
settings.json
```python
{
"sandbox": {
"credentials": {
"files": [
{
"path": "~/.config/gh/hosts.yml",
"mode": "mask",
"extract": "oauth_token:\\s*(\\S+)",
"maskDuplicates": true,
"onExtractNoMatch": "deny",
"injectHosts": ["api.github.com"]
}
]
}
}
}
```
[](#sandbox-credentials-envvars)
`sandbox.credentials.envVars`
Protect environment variables from sandboxed commands. With `"mode": "deny"`, Claude Code removes the variable from the environment of sandboxed commands. With `"mode": "mask"`, sandboxed commands see a per-session sentinel value, and the sandbox proxy substitutes the real value on outbound requests to that entry’s `injectHosts`, so tools such as `gh` and `npm` keep authenticating without ever holding the real credential. `"mode": "mask"` requires Claude Code v2.1.199 or later.
- **Scope**: [`Any file`](#scopes). Claude Code drops `mask` entries from project `.claude/settings.json` and local `.claude/settings.local.json`.
- **Type**: array of objects, each with `name` and a `mode` of `"deny"` or `"mask"`, plus the optional [mask fields for environment variables](#mask-fields-for-environment-variables)
- **Default**: unset, so no environment variables are protected
This removes `NPM_TOKEN` from sandboxed commands and masks `GITHUB_TOKEN`, substituting the real value only on requests to `api.github.com`:
settings.json
```python
{
"sandbox": {
"credentials": {
"envVars": [
{ "name": "NPM_TOKEN", "mode": "deny" },
{ "name": "GITHUB_TOKEN", "mode": "mask", "injectHosts": ["api.github.com"] }
]
}
}
}
```
The `name` must start with a letter or underscore and contain only letters, digits, and underscores. Claude Code merges the arrays from every settings scope the session loads, and applies `deny` when the same variable appears with both modes. [Protect credentials](sandboxing.md#protect-credentials) covers what still applies from sources you exclude with `--setting-sources`. `mask` entries require Claude Code v2.1.199 or later. `mask` substitution runs only through the sandbox proxy, so set [`sandbox.network.tlsTerminate`](#sandbox-network-tlsterminate), or [`allowPlaintextInject`](#sandbox-credentials-allowplaintextinject) for plain-HTTP test networks; see [Mask environment variables](sandboxing.md#mask-environment-variables). Claude Code accepts but ignores the `mask` fields on a `deny` entry.
[](#mask-fields-for-environment-variables)
Mask fields for environment variables
A `mask` entry accepts these optional fields. Without `extract` or `decode`, Claude Code replaces the entire value with one sentinel. `extract` and `decode` can’t be combined on the same entry.
| Field | Type | What it does |
|:-------------------|:-------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `extract` | string, a regular expression with at least one capturing group | Mask only the text captured by group 1 of each match, such as the password inside a `DATABASE_URL` connection string, so the rest of the value stays parseable. Requires v2.1.224 or later |
| `onExtractNoMatch` | `"warn"`, `"deny"`, or `"error"`; default `"warn"`. On an entry with `decode`, only `"warn"` is accepted | What happens when `extract` matches nothing. `warn` passes the variable through unmasked, `deny` unsets it inside the sandbox, and `error` stops sandbox setup until you fix the configuration. Requires v2.1.224 or later |
| `decode` | the string `"jwt"` | Verify the whole value is a JWT and replace it with a structurally valid fake token, so code inside the sandbox that decodes the token keeps working; the proxy substitutes the whole real token on egress. A value that doesn’t verify passes through unmasked with a warning. Requires v2.1.224 or later |
| `maskClaims` | array of strings, at least one claim name; requires `decode` | Mask only the named top-level payload claims inside the decoded JWT and rebuild the token around the modified payload, so the other claims stay readable. When no named claim matches, the variable passes through unmasked with a warning. Requires v2.1.224 or later |
| `injectHosts` | array of strings, each a host that [`sandbox.network.allowedDomains`](#sandbox-network-alloweddomains) also admits | Narrow the hosts where the sandbox proxy substitutes the real value. When unset, the proxy substitutes it on requests to every host in `sandbox.network.allowedDomains`. Write an IPv6 destination as the bare compressed address, such as `"::1"`, not the bracketed form; see [IPv6 destinations in `injectHosts`](sandboxing.md#ipv6-destinations-in-injecthosts). Requires v2.1.199 or later |
This masks only the password inside `DATABASE_URL`, unsets the variable if the pattern matches nothing, and masks a JWT in `SERVICE_JWT` while leaving every claim except `api_key` readable:
settings.json
```python
{
"sandbox": {
"credentials": {
"envVars": [
{
"name": "DATABASE_URL",
"mode": "mask",
"extract": "://[^:]+:([^@]+)@",
"onExtractNoMatch": "deny"
},
{
"name": "SERVICE_JWT",
"mode": "mask",
"decode": "jwt",
"maskClaims": ["api_key"]
}
]
}
}
}
```
[](#sandbox-credentials-allowplaintextinject)
`sandbox.credentials.allowPlaintextInject`
Allow `mask` substitution on plain HTTP requests as well as TLS-terminated HTTPS. On plain HTTP the upstream identity is unverified and the credential travels in cleartext, so leave this off outside trusted test networks. Requires Claude Code v2.1.199 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code allows `mask` substitution on plain HTTP requests as well as TLS-terminated HTTPS
- `false`: Claude Code allows `mask` substitution only on TLS-terminated HTTPS
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"credentials": {
"allowPlaintextInject": true
}
}
}
```
Requires Claude Code v2.1.199 or later.
[](#sandbox-credentials-awspairs)
`sandbox.credentials.awsPairs`
Group masked environment variables that form one AWS credential for [SigV4 re-signing](sandboxing.md#re-sign-aws-requests) when your credential lives in variables with non-standard names. Claude Code links the conventional `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` trio automatically when you mask their whole values, so you need this key only for other names. Requires Claude Code v2.1.224 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: array of objects, each with `accessKeyIdVar`, `secretAccessKeyVar`, and optionally `sessionTokenVar`, naming `sandbox.credentials.envVars` entries
- **Default**: unset, so only the conventional trio is paired
This links three custom-named variables into one AWS credential for re-signing:
settings.json
```python
{
"sandbox": {
"credentials": {
"awsPairs": [
{
"accessKeyIdVar": "MY_KEY_ID",
"secretAccessKeyVar": "MY_SECRET_KEY",
"sessionTokenVar": "MY_SESSION_TOKEN"
}
]
}
}
}
```
Each named variable must be a whole-value `mask` entry in [`sandbox.credentials.envVars`](#sandbox-credentials-envvars), without `extract` or `decode`, and can fill only one slot across all pairs.
[](#sandbox-credentials-sigv4)
`sandbox.credentials.sigv4`
Choose what the sandbox proxy does with AWS request forms it [can’t re-sign](sandboxing.md#re-sign-aws-requests): `streaming` for aws-chunked streaming uploads, `presigned` for presigned URLs, and `sigv4a` for SigV4A asymmetric signatures. This applies only to requests signed with a masked pair’s placeholder access key ID. Requires Claude Code v2.1.224 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: object with `streaming`, `presigned`, and `sigv4a`, each one of:
- `"deny"`: the proxy fails the request
- `"passthrough"`: the proxy forwards the request signed with the masked placeholder, so the tool receives AWS’s own rejection
- **Default**: unset, so every form is `"deny"`
This forwards streaming uploads instead of failing them at the proxy:
settings.json
```python
{
"sandbox": {
"credentials": {
"sigv4": {
"streaming": "passthrough"
}
}
}
}
```
With `deny`, the proxy fails the request. With `passthrough`, the proxy forwards the request with its signature computed from the masked placeholder, so AWS rejects it and the calling tool receives AWS’s own response instead of a proxy error.
[](#sandbox-network)
`sandbox.network`
Control which hosts, ports, and sockets sandboxed commands can reach. The sandbox routes outbound traffic through a proxy that enforces these lists; see [Network isolation](sandboxing.md#network-isolation) for how the proxy decides and when it prompts.
- **Scope**: [`Any file`](#scopes). `strictAllowlist`, `allowManagedDomainsOnly`, and `tlsTerminate` are read from fewer sources, as their entries say.
- **Type**: object with the sub-keys below
- **Default**: unset, so no domains are pre-allowed and the sandbox prompts for each new host
This pre-allows GitHub and npm, blocks `uploads.github.com`, and lets commands bind to localhost:
settings.json
```python
{
"sandbox": {
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"],
"deniedDomains": ["uploads.github.com"],
"allowLocalBinding": true
}
}
}
```
Claude Code merges the array sub-keys across settings scopes and deduplicates them, so a project can add domains to your user list. `WebFetch(domain:...)` allow and deny [permission rules](sandboxing.md#permission-rules) feed the same allow and deny lists.
[](#sandbox-network-allowunixsockets)
`sandbox.network.allowUnixSockets`
List the Unix socket paths sandboxed commands can connect to on macOS. Claude Code ignores this list on Linux and WSL2, where the seccomp filter can’t inspect socket paths; use [`allowAllUnixSockets`](#sandbox-network-allowallunixsockets) there instead.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, each a socket path
- **Default**: unset, so the macOS sandbox blocks every Unix socket
settings.json
```python
{
"sandbox": {
"network": {
"allowUnixSockets": ["~/.ssh/agent-socket"]
}
}
}
```
A socket path can grant broad access: allowing `/var/run/docker.sock`, for example, lets a sandboxed command control the Docker daemon. See [Security limitations](sandboxing.md#security-limitations).
[](#sandbox-network-allowallunixsockets)
`sandbox.network.allowAllUnixSockets`
Let sandboxed commands connect to every Unix socket. On Linux and WSL2, the sandbox’s [seccomp filter](sandboxing.md#set-up-linux-and-wsl2) blocks `socket(AF_UNIX, ...)` calls, so this is the only way to permit Unix sockets there. When the filter is missing, which `/sandbox` reports on its Dependencies tab, the sandbox doesn’t block Unix-socket calls. See [Set up Linux and WSL2](sandboxing.md#set-up-linux-and-wsl2) for where the filter comes from.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: sandboxed commands can connect to every Unix socket
- `false`: the sandbox blocks Unix-socket connections: on macOS except the paths in `allowUnixSockets`, and on Linux and WSL2 through the seccomp filter when it’s present
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"network": {
"allowAllUnixSockets": true
}
}
}
```
On WSL2, `true` also reopens the interop socket that launches Windows binaries such as `cmd.exe` and `powershell.exe`.
[](#sandbox-network-allowlocalbinding)
`sandbox.network.allowLocalBinding`
Let sandboxed commands bind to localhost ports on macOS, for example to start a dev server.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: sandboxed commands can bind to localhost ports on macOS
- `false`: sandboxed commands on macOS can’t bind to localhost ports
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"network": {
"allowLocalBinding": true
}
}
}
```
[](#sandbox-network-allowmachlookup)
`sandbox.network.allowMachLookup`
List additional XPC and Mach service names the macOS sandbox may look up. Tools that communicate over XPC, such as the iOS Simulator or Playwright, need their services listed here.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, each a service name; a single trailing `*` matches a prefix, and `"*"` alone matches every service
- **Default**: unset
This allows every service under the `com.apple.coresimulator.` prefix:
settings.json
```python
{
"sandbox": {
"network": {
"allowMachLookup": ["com.apple.coresimulator.*"]
}
}
}
```
[](#sandbox-network-alloweddomains)
`sandbox.network.allowedDomains`
Pre-allow domains for outbound traffic from sandboxed commands, so the sandbox doesn’t prompt for them. Wildcards such as `*.example.com` match subdomains, and an optional `:port` suffix limits an entry to one port; an entry without a port matches every port.
- **Scope**: [`Any file`](#scopes). Only managed settings when [`allowManagedDomainsOnly`](#sandbox-network-allowmanageddomainsonly) is set.
- **Type**: array of strings, each a domain, wildcard pattern, or IP literal, with an optional `:port` suffix
- **Default**: unset, so the sandbox prompts the first time a command reaches a new host
This pre-allows GitHub on every port, every npm subdomain, and one API host on port 443 only:
settings.json
```python
{
"sandbox": {
"network": {
"allowedDomains": ["github.com", "*.npmjs.org", "api.example.com:443"]
}
}
}
```
Write IPv6 literals bracketed, with an optional port: `"[::1]"` allows every port and `"[::1]:443"` one port. The bracketed form requires Claude Code v2.1.229 or later. See [IPv6 addresses in domain lists](sandboxing.md#ipv6-addresses-in-domain-lists).
[](#sandbox-network-denieddomains)
`sandbox.network.deniedDomains`
Block domains for outbound traffic from sandboxed commands, using the same wildcard, port, and IPv6 syntax as [`allowedDomains`](#sandbox-network-alloweddomains). A denied domain stays blocked even when an `allowedDomains` entry matches it too.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, each a domain, wildcard pattern, or IP literal, with an optional `:port` suffix
- **Default**: unset
settings.json
```python
{
"sandbox": {
"network": {
"deniedDomains": ["sensitive.cloud.example.com"]
}
}
}
```
Claude Code merges this list from every settings source the session loads even when `allowManagedDomainsOnly` is set, so a developer can always tighten the deny list. For IPv6 literals, see [IPv6 addresses in domain lists](sandboxing.md#ipv6-addresses-in-domain-lists). An entry written with the trailing dot that marks a fully qualified domain name, such as `example.com.`, blocks the same connections as `example.com`.
[](#sandbox-network-strictallowlist)
`sandbox.network.strictAllowlist`
Deny sandboxed commands access to hosts outside the allowlist instead of prompting for approval. The allowlist is [`allowedDomains`](#sandbox-network-alloweddomains) plus domains from `WebFetch(domain:...)` allow rules, or only the managed settings entries when [`allowManagedDomainsOnly`](#sandbox-network-allowmanageddomainsonly) is set. Requires Claude Code v2.1.219 or later.
- **Scope**: [`User or managed`](#scopes). A repository can’t turn it on or off.
- **Type**: Boolean
- `true`: Claude Code denies sandboxed commands access to hosts outside the allowlist
- `false`: unless another trusted settings file sets `true`, Claude Code decides a host outside the allowlist by permission mode instead of denying it outright: in auto mode it checks the host against the command’s [per-command allowed domains](sandboxing.md#per-command-allowed-domains-in-auto-mode), in `dontAsk` mode it denies, in `bypassPermissions` mode and in interactive terminal plan-mode sessions where bypass is available it allows, and otherwise it asks you
- **Default**: `false`
settings.json
```python
{
"sandbox": {
"network": {
"strictAllowlist": true
}
}
}
```
Claude Code enforces this for sandboxed commands only; in-process tools such as `WebFetch` still follow their [permission rules](sandboxing.md#permission-rules). When any of the honored sources sets it to `true`, it stays on. See [Network isolation](sandboxing.md#network-isolation). Requires Claude Code v2.1.219 or later.
[](#sandbox-network-allowmanageddomainsonly)
`sandbox.network.allowManagedDomainsOnly`
Lock the network allowlist to what managed settings define. Claude Code then honors only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings, ignores domains from user, project, local, and `--settings` settings, and blocks a non-allowed domain automatically instead of prompting.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code honors only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings and blocks a non-allowed domain instead of prompting
- `false`: domains from user, project, local, and `--settings` settings merge into the allowlist
- **Default**: `false`
This locks the allowlist to GitHub and npm and ignores any domains developers add:
managed-settings.json
```python
{
"sandbox": {
"network": {
"allowManagedDomainsOnly": true,
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
```
Denied domains still merge from every source the session loads. See [Keep developers from widening the policy](sandboxing.md#keep-developers-from-widening-the-policy).
[](#sandbox-network-httpproxyport)
`sandbox.network.httpProxyPort`
Point the sandbox at your own HTTP proxy instead of the one Claude Code runs. Organizations do this to inspect HTTPS traffic, apply their own filtering rules, or log every request. When unset, Claude Code starts its own proxy for HTTP traffic.
- **Scope**: [`Any file`](#scopes)
- **Type**: number, a local TCP port
- **Default**: unset, so Claude Code runs its own proxy
settings.json
```python
{
"sandbox": {
"network": {
"httpProxyPort": 8080
}
}
}
```
Set [`socksProxyPort`](#sandbox-network-socksproxyport) too if your proxy should carry SOCKS traffic as well; with only one of the two set, Claude Code still runs its own proxy for the other protocol. See [Custom proxy configuration](sandboxing.md#custom-proxy-configuration).
[](#sandbox-network-socksproxyport)
`sandbox.network.socksProxyPort`
Point the sandbox at your own SOCKS5 proxy instead of the one Claude Code runs. When unset, Claude Code starts its own proxy for SOCKS traffic.
- **Scope**: [`Any file`](#scopes)
- **Type**: number, a local TCP port
- **Default**: unset, so Claude Code runs its own proxy
settings.json
```python
{
"sandbox": {
"network": {
"socksProxyPort": 8081
}
}
}
```
See [Custom proxy configuration](sandboxing.md#custom-proxy-configuration).
[](#sandbox-network-tlsterminate)
`sandbox.network.tlsTerminate`
Make the sandbox proxy terminate TLS so it can read the contents of HTTPS requests. This is experimental, and `mask` [credential substitution](sandboxing.md#mask-credentials) requires it. Set `{}` to generate an ephemeral certificate authority for the session, or set `caCertPath` and `caKeyPath` to use your own.
- **Scope**: [`User or managed`](#scopes). A repository can’t switch it on or supply a certificate authority.
- **Type**: object with optional `caCertPath` and `caKeyPath` strings, each a file path
- **Default**: unset, so the proxy doesn’t terminate or inspect TLS
settings.json
```python
{
"sandbox": {
"network": {
"tlsTerminate": {}
}
}
}
```
When more than one honored source sets it, Claude Code uses the value from the highest-precedence source: managed settings, then the `--settings` flag, then user settings. Requires Claude Code v2.1.199 or later.
[](#memory-and-context)
Memory and context
Control what Claude Code loads into context, how it compacts, and where it keeps memory and plans. See [Manage context](context-window.md) and [Memory](memory.md).
[](#autocompactenabled)
`autoCompactEnabled`
Have Claude Code [compact the conversation automatically](context-window.md#when-your-context-fills-up) when context approaches the limit. Appears in `/config` as **Auto-compact**, and toggling it there writes this key to your user settings.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code compacts the conversation automatically when context approaches the limit
- `false`: Claude Code doesn’t compact automatically
- **Default**: `true`
- **Per-session overrides**: [`DISABLE_AUTO_COMPACT`](env-vars.md) turns auto-compact off for one session; whichever of the two turns it off, the other can’t turn it back on
settings.json
```python
{
"autoCompactEnabled": false
}
```
The manual `/compact` command keeps working while auto-compact is off.
[](#autocompactwindow)
`autoCompactWindow`
Set how full the context window gets before Claude Code [compacts automatically](context-window.md#when-your-context-fills-up).
- **Scope**: [`Any file`](#scopes)
- **Type**: number of tokens, from `100000` to `1000000`. Claude Code caps the value at your model’s context window; the [models overview](../20-Models/about-claude-models-overview.md) lists each model’s window
- **Default**: unset, so Claude Code picks a window tuned for your model
- **Per-session overrides**: [`--autocompact`](cli-reference.md#cli-flags) takes precedence over this key for one session, and [`CLAUDE_CODE_AUTO_COMPACT_WINDOW`](env-vars.md) takes precedence over both
settings.json
```python
{
"autoCompactWindow": 500000
}
```
Set it with the [`/autocompact`](commands.md#all-commands) command, which writes this key to your user settings. [Set the auto-compact window](model-config.md#set-the-auto-compact-window) covers how the command, flag, variable, and setting interact.
[](#automemorydirectory)
`autoMemoryDirectory`
Store [auto memory](memory.md#storage-location) in a directory of your choice instead of the per-project default.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, an absolute or `~/`-prefixed directory path
- **Default**: unset, so Claude Code uses `~/.claude/projects/<project>/memory/`
settings.json
```python
{
"autoMemoryDirectory": "~/my-memory-dir"
}
```
From project or local settings, Claude Code honors this key under the same [workspace trust rule as hooks](permissions.md#what-runs-before-you-trust-a-folder), since a cloned repository can supply those files.
[](#automemoryenabled)
`autoMemoryEnabled`
Turn [auto memory](memory.md#enable-or-disable-auto-memory) on or off. When `false`, Claude doesn’t read from or write to the auto memory directory. You can also toggle it with `/memory` during a session, which writes this key to your user settings.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the same as unset; auto memory stays on unless something that outranks this key turns it off for the session, such as `--bare`, safe mode, or `CLAUDE_CODE_DISABLE_AUTO_MEMORY`
- `false`: Claude doesn’t read from or write to the auto memory directory
- **Default**: `true`
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_AUTO_MEMORY`](env-vars.md) takes precedence over this key for one session, in either direction
settings.json
```python
{
"autoMemoryEnabled": false
}
```
[](#bashoutputmaxchars)
`bashOutputMaxChars`
Set how many characters of a successful Bash or PowerShell command’s [output Claude receives inline](tools-reference.md#output-limits). When output passes the limit, Claude Code saves it to a file and Claude receives a short preview plus the file’s path. Raise the limit when command output, such as a verbose build or a full test-suite log, routinely overflows the default and you want Claude to read it without opening the file. Requires Claude Code v2.1.261 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: number of characters, a positive integer. Claude Code clamps the value into the range `4000` to `128000`
- **Default**: unset, so Claude receives up to 30,000 characters inline
settings.json
```python
{
"bashOutputMaxChars": 100000
}
```
When you set this key, Claude Code ignores the [`BASH_MAX_OUTPUT_LENGTH`](env-vars.md) environment variable.
[](#claudemd)
`claudeMd`
Inject CLAUDE.md-style instructions as organization-managed memory without deploying a separate file. Claude Code loads the text as a managed memory entry ahead of user and project CLAUDE.md files.
- **Scope**: [`Managed`](#scopes)
- **Type**: string, the text of a CLAUDE.md file; write it as you would the file, Markdown included, with line breaks as `\n`
- **Default**: unset
This example deploys two rules as a short Markdown list:
managed-settings.json
```python
{
"claudeMd": "# Engineering rules\n\n- Always run make lint before committing.\n- Never push directly to main."
}
```
See [Deploy organization-wide CLAUDE.md](memory.md#deploy-organization-wide-claude-md).
[](#claudemdexcludes)
`claudeMdExcludes`
Skip specific `CLAUDE.md` files when Claude Code loads [memory](memory.md#exclude-specific-claude-md-files). In a large monorepo, use it to skip CLAUDE.md files from other teams that aren’t relevant to your work; [Exclude irrelevant CLAUDE.md files](large-codebases.md#exclude-irrelevant-claude-md-files) in the large-codebases guide walks through that case. Patterns match against absolute file paths.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, each a glob pattern or absolute path
- **Default**: unset, so Claude Code loads every CLAUDE.md it finds
settings.json
```python
{
"claudeMdExcludes": ["**/vendor/**/CLAUDE.md"]
}
```
Exclusions apply only to user, project, and local memory files; managed policy CLAUDE.md files can’t be excluded.
[](#env)
`env`
Set environment variables for every session and for the subprocesses Claude Code starts from it. Most variables in the [environment variables reference](env-vars.md) can go here, which is how you apply one to every session or roll it out to your team. Project and local settings can’t set [some of them](#variables-claude-code-ignores-in-env).
- **Scope**: [`Any file`](#scopes)
- **Type**: object mapping variable names to string values
- **Default**: unset
This example turns off automatic compaction and routes API requests through a proxy:
settings.json
```python
{
"env": {
"DISABLE_AUTO_COMPACT": "1",
"ANTHROPIC_BASE_URL": "https://proxy.example.com"
}
}
```
[](#how-env-values-interact-with-your-shell)
How `env` values interact with your shell
- A value here overwrites the same variable exported in your shell, and when more than one settings file sets a variable, the [highest-precedence](settings.md#settings-precedence) one applies. [Variables Claude Code ignores in `env`](#variables-claude-code-ignores-in-env) lists the exceptions for project and local settings.
- When the Claude Desktop app or a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) runner starts the session, the launch environment it builds takes precedence instead: Claude Code ignores an `env` value from any settings file for a variable the launch environment already sets. The [debug log](debug-your-config.md) names each ignored variable.
- To cancel a shell export, set the variable to `""`. Claude Code treats an empty value as unset for provider selection, and subprocesses inherit the empty value.
- `NO_COLOR` and `FORCE_COLOR` set here reach only subprocesses. To change Claude Code’s own interface colors, set them in your shell before launching `claude`.
- Values here are plain text in the settings file and reach every subprocess Claude Code starts. For an OTLP bearer token that rotates, use [`otelHeadersHelper`](#otelheadershelper); for API credentials, use [`apiKeyHelper`](#apikeyhelper).
[](#when-claude-code-applies-env-values)
When Claude Code applies `env` values
- From user settings, `--settings`, and managed settings: at startup, and again in the running session when a saved change alters the merged `env`.
- From project and local settings: after you trust the workspace, or at startup in `-p` mode, which never shows the trust dialog, and again when a saved change alters the merged `env`.
- Variables Claude Code classifies as safe, such as model selection, timeouts and limits, and feature toggles: at startup from every settings file, apart from the [variables project and local settings can’t set](#variables-claude-code-ignores-in-env).
- After you [move the session with `/cd`](permissions.md#move-the-session-to-another-directory) on v2.1.246 or later: the new directory’s project and local `env` values, on top of the previous directory’s.
[](#variables-claude-code-ignores-in-env)
Variables Claude Code ignores in `env`
- Project and local settings can’t set variables that a checked-out repository shouldn’t control; set those in your shell, user settings, or managed settings instead. Claude Code drops each one, apart from a few values that turn telemetry off, and logs a warning you can see with `claude --debug`. They include:
- Variables that choose where Claude Code stores or writes its own files: `CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_TMPDIR`, and the operating-system directory variables such as `HOME`, `TMPDIR`, `TMP`, `TEMP`, and the `XDG_*` family.
- Variables that export session content: [`OTEL_LOG_RAW_API_BODIES`](env-vars.md#variables) and the detailed beta tracing pair `ENABLE_BETA_TRACING_DETAILED` and `BETA_TRACING_ENDPOINT`.
- The [OpenTelemetry exporter](../13-Enterprise-Admin/monitoring-usage.md) variables that turn telemetry on, choose where it goes, or choose what content it captures:
- `CLAUDE_CODE_ENABLE_TELEMETRY`, plus the enhanced telemetry beta pair `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` and `ENABLE_ENHANCED_TELEMETRY_BETA`
- The exporter selectors `OTEL_LOGS_EXPORTER`, `OTEL_METRICS_EXPORTER`, and `OTEL_TRACES_EXPORTER`
- The content variables `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_ASSISTANT_RESPONSES`, `OTEL_LOG_TOOL_CONTENT`, and `OTEL_LOG_TOOL_DETAILS`
- `OTEL_EXPORTER_OTLP_*` variables whose names end in `_ENDPOINT`, `_HEADERS`, `_PROTOCOL`, `_CERTIFICATE`, `_CLIENT_KEY`, or `_INSECURE`, in the generic and per-signal forms, such as `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS`
- `OTEL_EXPORTER_PROMETHEUS_HOST` and `OTEL_EXPORTER_PROMETHEUS_PORT`
Only these values still apply from project and local settings, because they turn something off: `none` for the three exporter selectors, and an off value such as `0` for `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_CONTENT`, and `OTEL_LOG_TOOL_DETAILS`. Such a value overrides the same variable in your user settings, but not one that the environment you start Claude Code from, a `--settings` file, or managed settings sets. When a project or local settings file sets a variable in this group, a local interactive session shows a notice at startup. Run `/status` or `claude doctor` to see which ones Claude Code ignored and which turned telemetry off; both list names, never values. A non-interactive run with `-p` or an Agent SDK session shows no notice, so check that your collector still receives data after you upgrade. If it doesn’t, set the variables in your user settings, managed settings, the job’s environment, or a file you pass with `--settings`. Ignoring this group in project and local settings requires Claude Code v2.1.282 or later.
- Variables that change how Claude Code starts or syncs, such as `CLAUDE_CODE_PROCESS_WRAPPER`, `CLAUDE_CODE_SYNC_SKILLS`, `CLAUDE_CODE_SYNC_PLUGINS`, `CLAUDE_CODE_PLUGIN_CACHE_DIR`, and `CLAUDE_CODE_PLUGIN_SEED_DIR`.
Before v2.1.251, project and local settings could also set the variables in this list that choose where Claude Code writes its files or that export session content, except `HOME` and `XDG_CONFIG_HOME`.
- Identity variables that Claude Code’s hosting environments own, such as `CLAUDE_CODE_REMOTE` and `CLAUDE_CODE_ACCOUNT_UUID`, are ignored from every file.
- [`CLAUDE_CODE_MESSAGING_SOCKET` and `CLAUDE_CODE_MESSAGING_TOKEN`](env-vars.md#variables), which Claude Code exports itself, are ignored from every file. Ignoring the socket variable requires Claude Code v2.1.224 or later, and ignoring the token requires v2.1.228 or later.
- [`CLAUDE_CODE_PROJECT_DIR_NAME`](sessions.md#name-the-project-directory-yourself), which Claude Code reads from the launch environment only, is ignored from every file; requires v2.1.234 or later.
- [`CLAUDE_CODE_RESTRICTED`](env-vars.md#variables), which Claude Code reads from the launch environment only, is ignored from every file.
- [`CLAUDE_CODE_DISABLE_POWERSHELL_CMD_RM_DENY`](env-vars.md#variables), which Claude Code reads from the launch environment only, is ignored from every file. The variable requires Claude Code v2.1.283 or later.
- [`CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT` and `CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT`](env-vars.md#variables), which Claude Code reads from the launch environment only, are ignored from every file.
[](#filecheckpointingenabled)
`fileCheckpointingEnabled`
Have Claude Code snapshot files before each edit so [`/rewind`](checkpointing.md) can restore them. Appears in `/config` as **Rewind code (checkpoints)**, and toggling it there writes this key to your user settings.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code snapshots files before each edit so `/rewind` can restore them
- `false`: Claude Code doesn’t snapshot files, so `/rewind` can’t restore them
- **Default**: `true`
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`](env-vars.md) turns checkpointing off for one session; whichever of the two turns it off, the other can’t turn it back on
settings.json
```python
{
"fileCheckpointingEnabled": false
}
```
In a `-p` run or an Agent SDK session, Claude Code ignores this key. The SDK turns checkpointing on with its `enableFileCheckpointing` option, and a bare `-p` run needs `CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true`. See [File checkpointing in the Agent SDK](../05-Agent-SDK/agent-sdk-file-checkpointing.md).
[](#plansdirectory)
`plansDirectory`
Choose where Claude Code stores the plan files it writes in [plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode). Claude Code resolves the path relative to the project root and keeps the default when the path resolves outside it.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a path relative to the project root
- **Default**: unset, so Claude Code uses `~/.claude/plans`
settings.json
```python
{
"plansDirectory": "./plans"
}
```
[](#skilllistingbudgetfraction)
`skillListingBudgetFraction`
Each turn, Claude sees a [listing of your skills](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short) with their descriptions, and Claude Code caps that listing at a share of the context window. When the listing is over the cap, Claude Code keeps every skill’s name but drops the descriptions of the least-used skills, so Claude can still invoke those skills but is less likely to choose one on its own. Raise this key to keep more descriptions visible at the cost of more context per turn.
- **Scope**: [`Any file`](#scopes)
- **Type**: number, a fraction greater than `0` and at most `1`
- **Default**: `0.01`, which reserves 1% of the context window
settings.json
```python
{
"skillListingBudgetFraction": 0.02
}
```
To see how much context the listing uses and which skills contribute most, run `/doctor`.
[](#skilllistingmaxdescchars)
`skillListingMaxDescChars`
Each turn, Claude sees a [listing of your skills](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short) that shows each skill’s `description` and `when_to_use` text. This key caps how many characters of that text Claude Code shows per skill; longer text is cut at the cap.
- **Scope**: [`Any file`](#scopes)
- **Type**: number of characters, a positive integer
- **Default**: `1536`
settings.json
```python
{
"skillListingMaxDescChars": 2048
}
```
Raise it to keep long descriptions intact at the cost of more context per turn; lower it to fit more skills under [`skillListingBudgetFraction`](#skilllistingbudgetfraction).
[](#taskoutputmaxchars)
`taskOutputMaxChars`
Removed in v2.1.277, together with the `TaskOutput` tool it sized. Setting it has no effect on current versions. Claude reads a background task’s [output file](tools-reference.md#background-commands) with `Read` instead.
Through v2.1.276, you set this key to the number of characters of a [background task’s](tools-reference.md#background-commands) output that Claude received inline when it read the task with the `TaskOutput` tool.
[](#interface-and-terminal)
Interface and terminal
Change how Claude Code looks and behaves in your terminal: theme, editor mode, status line, spinner, notifications inside the session, and accessibility. See [Terminal configuration](terminal-config.md).
[](#askuserquestiontimeout)
`askUserQuestionTimeout`
Let an unanswered [`AskUserQuestion`](tools-reference.md) dialog auto-continue after a period of idle time, submitting whatever options you had already selected. Set it when you step away and want Claude to continue without you. With the default, questions wait until you answer them. Requires Claude Code v2.1.200 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: string, one of `"60s"`, `"5m"`, `"10m"`, or `"never"`
- **Default**: `"never"`
- **Per-session overrides**: [`CLAUDE_AFK_TIMEOUT_MS`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"askUserQuestionTimeout": "5m"
}
```
Appears in `/config` as **Question auto-continue timeout**, which writes this key to user settings; Claude Code hides the row while managed settings or the `--settings` flag set the key. Requires Claude Code v2.1.200 or later.
[](#autocontinueatusagelimit)
`autoContinueAtUsageLimit`
After a claude.ai usage limit stops your session, wait in the open session and continue the task automatically after the reset. See [Turn automatic continue off](interactive-mode.md#turn-automatic-continue-off). Requires Claude Code v2.1.234 or later.
- **Scope**: [`User or managed`](#scopes). Read from user settings, `--settings`, and managed settings only. When none of those sets the key, a project or local settings file that sets it turns the feature off rather than being ignored.
- **Type**: Boolean
- `true`: after a claude.ai usage limit stops your session, Claude Code waits in the open session and continues the task automatically after the reset
- `false`: Claude Code doesn’t start the wait on its own. You can still [start a wait yourself](interactive-mode.md#start-a-wait-yourself) from the usage-limit options menu
- **Default**: `true`
settings.json
```python
{
"autoContinueAtUsageLimit": false
}
```
Appears in `/config` as **Continue automatically at usage limit**, which writes this key to user settings; Claude Code hides the row while managed settings or the `--settings` flag set the key.
[](#autoscrollenabled)
`autoScrollEnabled`
Follow new output to the bottom of the conversation in [fullscreen rendering](fullscreen.md). Turn it off to stay where you scrolled while Claude keeps working; permission prompts still scroll into view.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the conversation follows new output to the bottom
- `false`: you stay where you scrolled while Claude keeps working; permission prompts still appear below the transcript
- **Default**: `true`
settings.json
```python
{
"autoScrollEnabled": false
}
```
Appears in `/config` as **Auto-scroll** when fullscreen rendering is on, which writes this key to user settings.
[](#axscreenreader)
`axScreenReader`
Render screen-reader friendly output: flat text without decorative borders or animations. Screen-reader mode uses the classic renderer, so the `tui` setting has no effect while it is active; attached [background sessions](../09-Agents-Patterns/agent-view.md) still render fullscreen.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code renders flat text without decorative borders or animations, using the classic renderer
- `false`: Claude Code renders normally
- **Default**: unset, so screen-reader mode is off
- **Per-session overrides**: [`--ax-screen-reader`](cli-reference.md#cli-flags) takes precedence over [`CLAUDE_AX_SCREEN_READER`](env-vars.md), and both take precedence over this key for one session
settings.json
```python
{
"axScreenReader": true
}
```
[](#basheditdiffenabled)
`bashEditDiffEnabled`
Choose whether Claude Code records which files changed in a Git repository while a Bash command runs. When it records them, you see their diff in the terminal after the command, and your [PostToolUse Bash hooks](../07-Hooks/hooks.md#bash) receive the changed-file list. A listed file isn’t always one the command changed. A change that another program or another Bash call made while the command ran can appear there too. Set the key to `true` to record them in every permission mode. Requires Claude Code v2.1.269 or later.
- **Scope**: [`User or managed`](#scopes). A `true` counts only from your user settings, JSON passed with `--settings`, or [managed settings](../13-Enterprise-Admin/managed-settings.md), so a `true` in a repository’s `.claude/settings.json` or `.claude/settings.local.json` can’t turn the recording on. A `false` in either repository file still turns it off unless a [higher-precedence](settings.md#settings-precedence) file sets `true`.
- **Type**: Boolean
- **Default**: unset, so Claude Code records changes in auto mode and `bypassPermissions` mode when it directs Claude to edit files through Bash
- **Per-session overrides**: [`CLAUDE_CODE_BASH_EDIT_DIFF`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"bashEditDiffEnabled": true
}
```
[](#companyannouncements)
`companyAnnouncements`
Show your organization’s announcements to users at startup. When you list more than one, Claude Code picks one at random for each session; on a person’s very first launch it shows the first entry.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings
- **Default**: unset, so no announcement shows
settings.json
```python
{
"companyAnnouncements": [
"Welcome to Acme Corp! Review our code guidelines at docs.example.com"
]
}
```
[](#defaultshell)
`defaultShell`
Choose whether Bash or PowerShell runs the shell commands you type with the [`!` prefix](interactive-mode.md#shell-mode-with-prefix) in the input box, the ones Claude Code runs directly and adds to the session. `"powershell"` works only while the [PowerShell tool](tools-reference.md#powershell-tool) is on. The tool is on by default on Windows without Git Bash, and on Windows with Git Bash for claude.ai and Console accounts. In Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry sessions, and on macOS, Linux, and WSL, set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` to turn the tool on. Set that variable to `0` to turn the tool off.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"bash"`: Claude Code runs your `!` commands in Bash
- `"powershell"`: Claude Code runs your `!` commands in PowerShell
- **Default**: `"bash"`, or `"powershell"` on Windows when Bash isn’t available
settings.json
```python
{
"defaultShell": "powershell"
}
```
If the shell you name isn’t available, Claude Code uses the other one: `"powershell"` falls back to Bash when the PowerShell tool is off, and `"bash"` falls back to PowerShell when Bash isn’t installed.
[](#dialogexpiry)
`dialogExpiry`
Set the deadline for dialogs Claude Code [forwards to a remote client](remote-control.md#limitations), such as a Remote Control or SDK host, and for the approval dialog for a [held cross-session message](cross-session-messaging.md#control-inbound-messages). On Claude Code v2.1.236 or later, the same deadline bounds the mid-session [Fable usage-credits consent prompt](model-config.md#fable-and-usage-credits) in a session that may have nobody at the terminal. When no answer arrives before the deadline, Claude Code cancels the dialog and continues with its no-action default. Requires Claude Code v2.1.224 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: string, one of `"60s"`, `"5m"`, `"10m"`, or `"never"`, which disables the deadline
- **Default**: `"5m"`
- **Per-session overrides**: [`CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"dialogExpiry": "10m"
}
```
Permission prompts and [`AskUserQuestion`](tools-reference.md#askuserquestion-tool-behavior) questions use their own flows and aren’t governed by this deadline. Appears in `/config` as **Dialog expiry**, which writes this key to user settings; the row requires Claude Code v2.1.232 or later, and Claude Code hides it while managed settings or the `--settings` flag set the key.
[](#editormode)
`editorMode`
Choose the key binding mode for the input prompt.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"normal"`: standard key bindings in the prompt input
- `"vim"`: vim-style editing with NORMAL, INSERT, and VISUAL modes
- **Default**: `"normal"`
settings.json
```python
{
"editorMode": "vim"
}
```
Appears in `/config` as **Editor mode**, which writes this key to user settings.
[](#emojicompletionenabled)
`emojiCompletionEnabled`
Show emoji suggestions when you type `:` plus a shortcode in the prompt input, and replace a completed shortcode such as `:heart:` with its emoji. Set it to `false` to turn off both.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code shows emoji suggestions after `:` and replaces a completed shortcode with its emoji
- `false`: Claude Code neither suggests emoji nor replaces shortcodes
- **Default**: `true`
settings.json
```python
{
"emojiCompletionEnabled": false
}
```
See [Emoji shortcodes](interactive-mode.md#emoji-shortcodes). Requires Claude Code v2.1.217 or later.
[](#filesuggestion)
`fileSuggestion`
Run your own command to supply `@` file path autocomplete instead of the built-in file suggestion. The built-in suggestion uses fast filesystem traversal; a large monorepo may do better with project-specific indexing such as a pre-built file index.
- **Scope**: [`Any file`](#scopes). Under the [status line and file suggestion gates](#status-line-and-file-suggestion-gates), Claude Code turns the command off or runs only a managed value, and skips yours without warning.
- **Type**: object with `type`, always `"command"`, and `command`, the shell command to run
- **Default**: unset, so Claude Code uses the built-in file suggestion
settings.json
```python
{
"fileSuggestion": {
"type": "command",
"command": "~/.claude/file-suggestion.sh"
}
}
```
After you save this, type `@` followed by part of a path in the prompt: the suggestions come from your command’s output.
[](#command-input-and-output)
Command input and output
Claude Code runs the command with the same environment variables as [hooks](../07-Hooks/hooks.md), including `CLAUDE_PROJECT_DIR`, and stops waiting after five seconds. The command receives JSON on stdin with a `query` field holding what you’ve typed so far:
```python
{"query": "src/comp"}
```
Print newline-separated file paths to stdout. Claude Code shows at most 15:
```python
src/components/Button.tsx
src/components/Modal.tsx
src/components/Form.tsx
```
The following script reads the query and hands it to a repository file index:
```python
#!/bin/bash
query=$(cat | jq -r '.query')
# Replace your-repo-file-index with your own file search command
your-repo-file-index --query "$query" | head -20
```
[](#footerlinksregexes)
`footerLinksRegexes`
Render extra clickable badges in the footer below the input box when a regex matches turn output: tool results, including file contents and fetched pages, and Claude’s own responses. Use it to turn IDs printed by project CLIs, such as review tools and issue trackers, into session links.
- **Scope**: [`User or managed`](#scopes)
- **Type**: array of objects, each with `type` set to `"regex"`, a `pattern` regex, a `url` template, and an optional `label`; `{name}` placeholders in `url` and `label` are filled from named capture groups in `pattern`
- **Default**: unset, so no badges render
This example matches issue keys such as `PROJ-1234` and builds each link from the captured key:
settings.json
```python
{
"footerLinksRegexes": [
{
"type": "regex",
"pattern": "\\b(?<key>PROJ-\\d+)\\b",
"url": "https://issues.example.com/browse/{key}",
"label": "{key}"
}
]
}
```
With this configured, when `PROJ-1234` appears in a tool result or in Claude’s reply, a `PROJ-1234` badge appears in the footer linking to `https://issues.example.com/browse/PROJ-1234`.
[](#badge-constraints)
Badge constraints
Each entry’s URL, label, and badge count are bounded as follows:
| Constraint | Behavior |
|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| URL origin | Captured values are URL-encoded and the constructed URL must share the template’s literal origin. A capture can fill a path segment or query value but can’t change where the link points |
| URL length | Constructed URLs longer than 2048 characters are dropped |
| URL scheme | Must be `https`, `http`, or a recognized editor or workspace deep-link scheme: `vscode`, `vscode-insiders`, `cursor`, `windsurf`, `zed`, `jetbrains`, `idea`, `slack`, `linear`, `notion`, `figma` |
| Label | Defaults to the matched text and is truncated to 28 display columns |
| Badge count | At most 5 badges render. The oldest is displaced by newer matches and `/clear` removes them |
When a turn completes, Claude Code matches each entry’s `pattern` regex against the turn output on the main thread, so a slow regex blocks the UI until it finishes. Nested quantifiers such as `(a+)+$` can take exponentially long against certain inputs and freeze the session, so keep each `pattern` linear and avoid nesting `+` or `*`. Footer badges render alongside a [custom status line](statusline.md) when one is configured; neither replaces the other. Use a status line for a script-driven row that computes its own content from session data, and footer badges to turn IDs from the conversation into links without a script.
[](#keybindingflavor)
`keybindingFlavor`
Deprecated since v2.1.261 and has no effect. The prompt’s word-editing keys always [follow readline conventions](interactive-mode.md#make-ctrl-w-delete-back-to-whitespace), as in Bash. Claude Code still accepts `keybindingFlavor`, so a settings file that sets it stays valid.
In v2.1.238 through v2.1.260, setting it to `"readline"` made `Ctrl+W` delete back to the previous whitespace instead of only the previous word.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, `"classic"` or `"readline"`
- **Default**: unset
[](#maxprosewidth)
`maxProseWidth`
Cap the width of the prose in Claude’s responses so lines stay readable in a wide terminal. Paragraphs, headings, lists, and blockquotes wrap within this many columns, while tables and code blocks keep the full terminal width. Requires Claude Code v2.1.282 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: number of terminal columns, a whole number, minimum `40`. Claude Code ignores any other value
- **Default**: unset, so prose wraps at the terminal edge
settings.json
```python
{
"maxProseWidth": 80
}
```
[](#prefersreducedmotion)
`prefersReducedMotion`
Reduce or turn off interface animations such as the spinner, shimmer, and flash effects. Appears in `/config` as **Reduce motion**.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code reduces or turns off interface animations such as the spinner, shimmer, and flash effects
- `false`: the same as unset; Claude Code shows its animations
- **Default**: `false`
settings.json
```python
{
"prefersReducedMotion": true
}
```
[](#promptsuggestionenabled)
`promptSuggestionEnabled`
Show or hide [prompt suggestions](interactive-mode.md#prompt-suggestions), the grayed-out predictions that appear in your prompt input. Set it to `false`, or turn off **Prompt suggestions** in `/config`, to hide them.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: you see prompt suggestions in your prompt input
- `false`: Claude Code hides prompt suggestions
- **Default**: `true`
- **Per-session overrides**: [`CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"promptSuggestionEnabled": false
}
```
Prompt suggestions need a claude.ai or Console account with telemetry on. On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, or with telemetry turned off, such as by [`DISABLE_TELEMETRY`](env-vars.md), this key has no effect and only `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=1` turns them on.
[](#respectgitignore)
`respectGitignore`
Control whether the `@` file picker leaves out files that match `.gitignore` patterns. Appears in `/config` as **Respect .gitignore in file picker**.
- **Scope**: [`Any file`](#scopes). When no settings file sets it, Claude Code falls back to `respectGitignore` in `~/.claude.json`, which the `/config` toggle writes.
- **Type**: Boolean
- `true`: the `@` file picker leaves out files that match `.gitignore` patterns
- `false`: the `@` file picker includes files that match `.gitignore` patterns
- **Default**: `true`
settings.json
```python
{
"respectGitignore": false
}
```
[](#respondtobashcommands)
`respondToBashCommands`
Choose whether Claude responds after you run a shell command with the [`!` prefix](interactive-mode.md#shell-mode-with-prefix) in the input box. By default, Claude Code adds the command’s output to the conversation and Claude replies to it. Set this key to `false` to add the output to context without a reply, so you can run several commands and ask about them together.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code adds the command’s output to the conversation and Claude replies to it
- `false`: Claude Code adds the output to context without a reply
- **Default**: `true`
settings.json
```python
{
"respondToBashCommands": false
}
```
See [Shell mode with `!` prefix](interactive-mode.md#shell-mode-with-prefix).
[](#showclearcontextonplanaccept)
`showClearContextOnPlanAccept`
When Claude finishes a plan in [plan mode](permission-modes.md#review-and-approve-a-plan), it shows an approval menu. Planning can use a lot of context, so this key adds a first option to that menu, **Yes, clear context and …**, that approves the plan, clears the conversation context, and starts implementing from the plan alone. The rest of the label names the permission mode the session continues in, and shows how much of your context the planning used.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the plan approval menu gets a first option, **Yes, clear context and …**, that approves the plan and clears the conversation context
- `false`: the plan approval menu shows no clear-context option
- **Default**: `false`
settings.json
```python
{
"showClearContextOnPlanAccept": true
}
```
[](#showturnduration)
`showTurnDuration`
Show or hide the turn duration message after each response, such as “Cooked for 1m 6s · done 6:05 PM”. The clock after “done” shows when the turn finished; [`timeFormat`](#timeformat) and [`timeZone`](#timezone) control its format and zone. Appears in `/config` as **Show turn duration**.
- **Scope**: [`Any file`](#scopes). A value in `~/.claude.json` from an older version applies when no settings file sets it.
- **Type**: Boolean
- `true`: you see the turn duration message after each response
- `false`: Claude Code hides the turn duration message
- **Default**: `true`
settings.json
```python
{
"showTurnDuration": false
}
```
[](#spellcheck)
`spellcheck`
Underline misspelled words in the prompt input as you type, using a spell checker you install. Claude Code checks only the text in the input box. [Check spelling as you type](interactive-mode.md#check-spelling-as-you-type) covers installing aspell, hunspell, or ispell and what the checker covers. Requires Claude Code v2.1.235 or later.
- **Scope**: [`User or managed`](#scopes). The block from the highest tier that sets it applies as a whole.
- **Type**: object with `enabled` (Boolean), `checker` (`"aspell"`, `"hunspell"`, `"ispell"`, or `"auto"`), `language` (string, passed to the checker as its dictionary name), and `color` (string, a terminal color name, `#rrggbb`, `rgb(r,g,b)`, `ansi256(n)`, or `ansi:<name>`)
- **Default**: unset, so spell checking is off; `checker` defaults to `"auto"`, the first of the three found on `PATH`; `language` defaults to the checker’s own dictionary; `color` defaults to the theme’s error color
settings.json
```python
{
"spellcheck": { "enabled": true, "language": "en_GB" }
}
```
[](#spinnertipsenabled)
`spinnerTipsEnabled`
While Claude works, the spinner line rotates through short tips about Claude Code features, such as “Use Plan Mode to prepare for a complex request before making changes. Press Shift+Tab twice to enable.” Set this key to `false` to hide them. Appears in `/config` as **Show tips**.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: you see tips in the spinner while Claude is working
- `false`: Claude Code hides spinner tips
- **Default**: `true`
settings.json
```python
{
"spinnerTipsEnabled": false
}
```
[](#spinnertipsoverride)
`spinnerTipsOverride`
Add your own tips to the [spinner tips](#spinnertipsenabled) that Claude Code shows while Claude works, or replace the built-in tips with yours. Claude Code puts your tips in the same rotation as the built-in ones: it picks the tip that has gone unshown the longest, skips tips still in their cooldown, and breaks ties by priority. If you set [`spinnerTipsEnabled`](#spinnertipsenabled) to `false`, Claude Code hides all tips, yours included.
- **Scope**: [`Any file`](#scopes). Claude Code honors tip objects, `tipsFile`, `label`, and `excludeDefault` from user settings, the `--settings` flag, and managed settings; from project and local settings it reads plain string tips only.
- **Type**: object with `tips`, `tipsFile`, `label`, and `excludeDefault` fields, each optional
- **Default**: unset, so Claude Code shows only the built-in tips
Tip objects, `tipsFile`, `label`, and the Scope line’s rule that project and local settings contribute plain strings only require Claude Code v2.1.247 or later. On earlier versions, a project or local file’s `excludeDefault` applies too. Each `tips` entry is a plain string or an object with these fields:
| Field | Required | Description |
|:-------------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | Yes | Up to 64 letters, digits, `.`, `_`, or `-`. Claude Code keys the tip’s show history on it, so the tip’s cooldown survives reordering the list. Of two entries with the same id, Claude Code uses the first |
| `text` | Yes | The tip, one line of up to 500 characters. Claude Code strips ANSI escapes and control characters and collapses whitespace |
| `cooldownSessions` | No | Sessions Claude Code waits before showing the tip again, `0` to `1000`, default `0` |
| `priority` | No | Order among tips that have gone unshown equally long, higher first, `-10` to `10`, default `0` |
Claude Code reads a plain string as a tip with those defaults and a position-based id, so its show history resets when you reorder the list. Give a tip an `id` to keep its history across edits. Claude Code reads at most 200 tips across `tips` and `tipsFile`, and drops an invalid entry with a debug warning instead of rejecting the settings file. Use the remaining fields to name a tips file, set the prefix, and hide the built-in tips:
- `tipsFile`: an absolute or `~/` path to a local JSON file holding an array of the same entries, or an object with a `tips` array, up to 256 KB. Claude Code reads the file once per process, so it loads your edits at the next start. You can’t set it through [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md); deploy inline `tips` there, or deploy the path in an on-disk `managed-settings.json`.
- `label`: the prefix Claude Code shows before tips from user, `--settings`, and managed settings, up to 40 characters. The default is `Tip`, the same prefix as the built-in tips, and tips from project and local settings always use it.
- `excludeDefault`: set it to `true` to hide the built-in tips and show only yours. When Claude Code can’t load any of your tips, for example because `tipsFile` doesn’t exist or every entry is invalid, it keeps the built-in rotation instead of an empty spinner.
When more than one settings file sets the key, Claude Code shows tips from all of them and takes `tipsFile`, `label`, and `excludeDefault` from whichever of managed settings, the `--settings` flag, and user settings is the highest-precedence one that sets each. This example, in your user settings, adds a plain string tip and an object tip to the rotation under the `Acme tip` prefix:
settings.json
```python
{
"spinnerTipsOverride": {
"label": "Acme tip",
"tips": [
"Run /review before opening a PR",
{
"id": "gateway-errors",
"text": "Seeing 5xx errors? Check the gateway status page first",
"cooldownSessions": 5,
"priority": 2
}
]
}
}
```
Each field in the example changes one thing about how Claude Code shows the tips:
- `label`: Claude Code shows both tips as `Acme tip: ...` instead of `Tip: ...`.
- The plain string: Claude Code gives it the defaults, so it can come up again in the very next session.
- `id`: Claude Code keys the second tip’s show history on `gateway-errors`, so its cooldown still applies after you add or reorder tips.
- `cooldownSessions`: after Claude Code shows the `gateway-errors` tip, it doesn’t show that tip again until five sessions later.
- `priority`: when the `gateway-errors` tip and another tip have gone unshown for the same number of sessions, for example when neither has been shown yet, Claude Code shows `gateway-errors` first. The plain string has the default priority, `0`.
While Claude works, Claude Code shows your tips in the spinner with your prefix, such as `Acme tip: Run /review before opening a PR`.
[](#spinnerverbs)
`spinnerVerbs`
While a turn is in progress, the spinner shows a rotating verb such as “Accomplishing”, “Architecting”, or “Baking”. Use this key to add your own verbs to that rotation or replace the built-in list with yours.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with a `verbs` array of strings and `mode`, one of:
- `"append"`: Claude Code adds your verbs to the built-in set
- `"replace"`: Claude Code shows only your verbs
- **Default**: unset, so Claude Code uses the built-in verbs
This example adds two verbs to the built-in set:
settings.json
```python
{
"spinnerVerbs": {
"mode": "append",
"verbs": ["Pondering", "Crafting"]
}
}
```
In `"replace"` mode with an empty `verbs` array, Claude Code keeps the built-in verbs.
[](#statusline)
`statusLine`
Run your own command to render a [status line](statusline.md) below the prompt with context such as the model, cost, or git branch. Optional fields adjust spacing, add periodic re-runs, and hide the built-in vim mode indicator when your script renders `vim.mode` itself.
- **Scope**: [`Any file`](#scopes). When [`allowManagedHooksOnly`](#allowmanagedhooksonly) is on, or [`disableAllHooks`](#disableallhooks) is set outside managed settings, only the managed settings value runs.
- **Type**: object with `type` set to `"command"` and a `command` string, plus optional `padding` as a number of characters, `refreshInterval` as a number of seconds, minimum `1`, and `hideVimModeIndicator` as a Boolean
- **Default**: unset, so no status line
This example prints the model name and context usage, and adds two characters of horizontal spacing:
settings.json
```python
{
"statusLine": {
"type": "command",
"command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'",
"padding": 2
}
}
```
The example needs [`jq`](https://jqlang.org/) installed and runs in a shell. For PowerShell and Git Bash equivalents, see [Windows configuration](statusline.md#windows-configuration); for the full setup, see [Manually configure a status line](statusline.md#manually-configure-a-status-line).
[](#subagentstatusline)
`subagentStatusLine`
When Claude runs [subagents](../09-Agents-Patterns/sub-agents.md), Claude Code lists them in a task display below the prompt, one row per subagent showing `name · description · token count`. This key lets you run your own command to rewrite those rows, for example to show each subagent’s context usage as a percentage. On each refresh, Claude Code sends the visible rows as one JSON object on stdin, with a `tasks` array carrying each subagent’s `id`, `name`, `status`, `model`, `tokenCount`, and more, and replaces the row for each `id` you write back as a `{"id", "content"}` line. Rows you don’t write back keep the default rendering.
- **Scope**: [`Any file`](#scopes). When [`allowManagedHooksOnly`](#allowmanagedhooksonly) is on, or [`disableAllHooks`](#disableallhooks) is set outside managed settings, only the managed settings value runs.
- **Type**: object with `type` set to `"command"` and a `command` string
- **Default**: unset, so Claude Code renders the default rows
settings.json
```python
{
"subagentStatusLine": {
"type": "command",
"command": "jq -c '.tasks[] | {id, content: \"\\(.name): \\(.tokenCount) tokens\"}'"
}
}
```
See [Subagent status lines](statusline.md#subagent-status-lines).
[](#syntaxhighlightingdisabled)
`syntaxHighlightingDisabled`
Claude Code colors code by language in the diffs, code blocks, and file previews it shows in the terminal, with its built-in highlighter; no plugin or language server is involved. Set this key to `true` to show them as plain text instead, for example if the colors clash with your terminal theme or slow a screen reader.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns off syntax highlighting in diffs, code blocks, and file previews
- `false`: Claude Code highlights syntax
- **Default**: `false`
settings.json
```python
{
"syntaxHighlightingDisabled": true
}
```
[](#terminalprogressbarenabled)
`terminalProgressBarEnabled`
Some terminals can show a progress indicator on the tab or in the taskbar for the program running in them. While Claude is working, Claude Code reports an in-progress state to the terminal, so you can see from another tab or window whether the session is still busy. The indicator stays visible after the turn ends while [background subagents](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) or [dynamic workflows](workflows.md) are still running, and clears once the session is idle. Claude Code reports it only in terminals that support the indicator: ConEmu, Ghostty 1.2.0 or later, and iTerm2 3.6.6 or later. Set this key to `false` to stop Claude Code from reporting it. Appears in `/config` as **Terminal progress bar**.
- **Scope**: [`Any file`](#scopes). A value in `~/.claude.json` from an older version applies when no settings file sets it.
- **Type**: Boolean
- `true`: you see the terminal progress bar in terminals that support it
- `false`: Claude Code hides the terminal progress bar
- **Default**: `true`
settings.json
```python
{
"terminalProgressBarEnabled": false
}
```
[](#terminaltitlefromrename)
`terminalTitleFromRename`
Claude Code sets your terminal tab’s title. By default it uses a title it generates from the conversation, and once you give the session a [name](sessions.md#name-your-sessions) with `/rename` or `--name`, the tab shows that name instead. Set this key to `false` to keep the generated title on the tab even after you name the session. The name itself still applies, so `/resume <name>` and the session picker find it.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the terminal tab title shows the session name you set
- `false`: the tab keeps the title Claude Code generates from your conversation
- **Default**: `true`
settings.json
```python
{
"terminalTitleFromRename": false
}
```
To stop Claude Code from updating the terminal title at all, set [`CLAUDE_CODE_DISABLE_TERMINAL_TITLE`](env-vars.md) to `1` instead.
[](#theme)
`theme`
Pick the color theme for the interface. Appears in `/config` as **Theme**.
- **Scope**: [`Any file`](#scopes). A value in `~/.claude.json` from an older version applies when no settings file sets it.
- **Type**: string, one of:
- `"auto"`: matches your terminal’s light or dark background
- `"dark"`: the dark theme
- `"light"`: the light theme
- `"dark-daltonized"`: the dark theme with colorblind-friendly colors
- `"light-daltonized"`: the light theme with colorblind-friendly colors
- `"dark-ansi"`: the dark theme using only your terminal’s ANSI color palette
- `"light-ansi"`: the light theme using only your terminal’s ANSI color palette
- `"custom:<slug>"` or `"custom:<plugin-name>:<slug>"`: a custom theme from `~/.claude/themes/` or a plugin
- **Default**: `"dark"`
settings.json
```python
{
"theme": "light-daltonized"
}
```
See [Create a custom theme](terminal-config.md#create-a-custom-theme).
[](#timeformat)
`timeFormat`
Choose how Claude Code writes the times it shows in the interface, such as the `done 6:05 PM` at the end of each turn duration message and the timestamps in the [transcript viewer](interactive-mode.md#transcript-viewer). To pick a preset, run `/config` and set **Time format**. Requires Claude Code v2.1.257 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"auto"`: the same as unset; each time keeps its built-in format, which follows your locale on the turn duration message
- `"12-hour"`: a 12-hour clock
- `"24-hour"`: a 24-hour clock
- `"24-hour-utc"`: a 24-hour clock in UTC with `Z` after the minutes, such as `18:05Z`; Claude Code ignores [`timeZone`](#timezone) for this preset
- A strftime pattern such as `"%H:%M"`: Claude Code writes each time with the pattern. Any value that contains a `%` is a pattern, and any other value outside the presets counts as `"auto"`
- **Default**: `"auto"`
settings.json
```python
{
"timeFormat": "24-hour"
}
```
`/config` offers only the presets, so to use a strftime pattern, add the key to a settings file. This example shows each time as a two-digit 24-hour clock:
settings.json
```python
{
"timeFormat": "%H:%M"
}
```
The turn duration message and the transcript viewer then show times such as `18:05`. In the transcript viewer, the pattern is the whole timestamp, so add date directives when you want the date there. This example puts the date in front of the clock:
settings.json
```python
{
"timeFormat": "%Y-%m-%d %H:%M"
}
```
The same surfaces then show times such as `2026-09-01 18:05`.
[](#timezone)
`timeZone`
Show the times in the interface in a time zone other than your system’s. Set it to an [IANA time zone name](https://www.iana.org/time-zones), such as `"UTC"` or `"Europe/Dublin"`. The times that [`timeFormat`](#timeformat) controls then show in this zone. If `timeFormat` is `"24-hour-utc"`, times stay in UTC and Claude Code ignores this key. `/config` has no row for this key, so set it in a settings file. Requires Claude Code v2.1.257 or later.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, an IANA time zone name. When Claude Code doesn’t recognize the name, it uses your system time zone
- **Default**: unset, so times show in your system time zone
settings.json
```python
{
"timeZone": "Europe/Dublin"
}
```
[](#tui)
`tui`
Choose the terminal UI renderer. Use `"fullscreen"` for the flicker-free [alt-screen renderer](fullscreen.md) with virtualized scrollback, or `"default"` for the classic main-screen renderer. Running `/tui fullscreen` or `/tui default` writes this key for you.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"default"`: the classic main-screen renderer
- `"fullscreen"`: the flicker-free alt-screen renderer with virtualized scrollback
- **Default**: unset, so Claude Code [picks the renderer for you](fullscreen.md#fullscreen-by-default)
- **Per-session overrides**: [`CLAUDE_CODE_NO_FLICKER`](env-vars.md) and [`CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN`](env-vars.md) take precedence over this key for one session: `CLAUDE_CODE_NO_FLICKER=1` turns fullscreen on, and `CLAUDE_CODE_NO_FLICKER=0` or `CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1` turns it off; when both are set, Claude Code turns it off
settings.json
```python
{
"tui": "fullscreen"
}
```
Under tmux `-CC` or over SSH to Windows, Claude Code keeps the classic renderer unless you set `CLAUDE_CODE_NO_FLICKER=1`. Background sessions opened from [agent view](../09-Agents-Patterns/agent-view.md) always use the fullscreen renderer regardless of this setting.
[](#verbose)
`verbose`
By default, the transcript collapses each tool call to a short summary, such as the command Claude ran and a line count of its output, and you press `Ctrl+O` to switch the whole transcript to the expanded view when you want the details. Set this key to `true` to show every tool call’s full input and output inline as it happens, which is useful when you’re debugging a hook, an MCP server, or a long shell command. Appears in `/config` as **Verbose output**.
- **Scope**: [`Any file`](#scopes). A value in `~/.claude.json` from an older version applies when no settings file sets it.
- **Type**: Boolean
- `true`: you see full tool output
- `false`: you see truncated summaries of tool output
- **Default**: `false`
- **Per-session overrides**: [`--verbose`](cli-reference.md#cli-flags) takes precedence over this key for one session
settings.json
```python
{
"verbose": true
}
```
A [`viewMode`](#viewmode) value or a sticky `/focus` selection overrides this key every session.
[](#viewmode)
`viewMode`
Set the transcript view Claude Code starts in: `"default"`, `"verbose"`, or `"focus"`. When set, it overrides both the sticky `/focus` selection and the [`verbose`](#verbose) setting.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"default"`: the normal transcript with truncated tool output
- `"verbose"`: the transcript with full tool output
- `"focus"`: only your last prompt, a one-line summary of tool calls with edit diffstats, and the final response. Focus view needs the [fullscreen renderer](#tui)
- **Default**: unset, so the `verbose` setting and your last `/focus` choice apply
- **Per-session overrides**: [`--verbose`](cli-reference.md#cli-flags) takes precedence over this key for one session
settings.json
```python
{
"viewMode": "focus"
}
```
[](#viminsertmoderemaps)
`vimInsertModeRemaps`
Map two-key INSERT-mode sequences to Escape in [vim editor mode](interactive-mode.md#vim-editor-mode). Each key is exactly two printable characters typed in sequence, and `"<Esc>"` is the only supported target; Claude Code ignores other entries. Requires Claude Code v2.1.208 or later.
- **Scope**: [`User or managed`](#scopes). A repository can’t remap your keystrokes.
- **Type**: object mapping a two-character sequence to `"<Esc>"`
- **Default**: unset
settings.json
```python
{
"vimInsertModeRemaps": {
"jj": "<Esc>"
}
}
```
Has no effect unless `editorMode` is `"vim"`. See [Remap INSERT-mode key sequences](interactive-mode.md#remap-insert-mode-key-sequences). Requires Claude Code v2.1.208 or later.
[](#voice)
`voice`
Turn on [voice dictation](voice-dictation.md) and choose how the dictation key behaves. Claude Code writes this object for you when you run `/voice`.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `enabled` as a Boolean, `autoSubmit` as a Boolean that applies in hold mode only, and `mode`, one of:
- `"hold"`: you hold the dictation key while speaking and release it to stop
- `"tap"`: you tap the key once to start recording and again to send
- **Default**: unset, so dictation is off; when `enabled` is `true` and `mode` is unset, Claude Code uses `"hold"`
This example turns dictation on and makes the key tap once to start recording and again to send:
settings.json
```python
{
"voice": {
"enabled": true,
"mode": "tap"
}
}
```
`autoSubmit` sends the prompt when you release the key in hold mode. Voice dictation requires a claude.ai account.
[](#voiceenabled)
`voiceEnabled`
Deprecated since v2.1.92, when the [`voice`](#voice) object replaced it. Claude Code still reads it so older settings files keep working, but new configurations should set `voice.enabled`.
Turn voice dictation on with the single Boolean form that predates the `voice` object. When both are set, `voice.enabled` applies.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: voice dictation is on when you’re logged in with a claude.ai account and your organization’s policy allows voice, unless `voice.enabled` is set
- `false`: voice dictation is off, unless `voice.enabled` is set
- **Default**: unset
settings.json
```python
{
"voiceEnabled": true
}
```
[](#wheelscrollaccelerationenabled)
`wheelScrollAccelerationEnabled`
Accelerate mouse-wheel scroll speed during fast scrolls in [fullscreen rendering](fullscreen.md#mouse-wheel-scrolling). Set it to `false` for a constant scroll rate per wheel notch.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code accelerates mouse-wheel scroll speed during fast scrolls
- `false`: Claude Code scrolls at a constant rate per wheel notch
- **Default**: `true`
settings.json
```python
{
"wheelScrollAccelerationEnabled": false
}
```
[](#git-and-attribution)
Git and attribution
Control the attribution Claude Code adds to commits and pull requests and how it works with git.
[](#attribution)
`attribution`
Customize the attribution Claude Code adds to git commits and pull requests. Commits get a [git trailer](https://git-scm.com/docs/git-interpret-trailers) such as `Co-Authored-By` by default; pull request descriptions get plain text. Set each part separately with the sub-keys below.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `commit` and `pr` strings and a `sessionUrl` Boolean, or `false` to hide all attribution. The `false` value requires Claude Code v2.1.281 or later; earlier versions reject it and [skip the whole user, project, or local settings file](settings.md#fix-a-broken-settings-file) that holds it
- **Default**: unset, so Claude Code uses the standard attribution shown under each sub-key
To hide all attribution, set `attribution` to `false`. In a settings file that earlier versions also read, set [`commit`](#attribution-commit) and [`pr`](#attribution-pr) to empty strings and [`sessionUrl`](#attribution-sessionurl) to `false` instead. This example replaces the commit attribution, removes pull request attribution, and drops the session link:
settings.json
```python
{
"attribution": {
"commit": "Generated with AI\n\nCo-Authored-By: AI <ai@example.com>",
"pr": "",
"sessionUrl": false
}
}
```
Once you set `commit` or `pr`, Claude Code ignores the deprecated `includeCoAuthoredBy` setting and uses its default text for whichever of the two you left unset. Claude Code tells Claude that your own instructions about attribution, such as a CLAUDE.md or [memory](memory.md) rule, take precedence over these commit and PR lines, unless the line is set in [managed settings](../13-Enterprise-Admin/managed-settings.md).
[](#includecoauthoredby)
`includeCoAuthoredBy`
Deprecated since v2.0.62, when [`attribution`](#attribution) replaced it. Claude Code still reads it, but new configurations should set `attribution`.
Use [`attribution`](#attribution) instead, which replaces this key and lets you change or hide the commit trailer, the pull request text, and the session link separately. Claude Code still honors `includeCoAuthoredBy: false` from settings files that predate `attribution`, but ignores it once you set `attribution.commit` or `attribution.pr`.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: the same as unset; Claude Code adds the commit trailer and the pull request attribution text
- `false`: Claude Code omits both the commit trailer and the pull request attribution text, unless `attribution` sets `commit` or `pr`, in which case the [`attribution`](#attribution) rules apply
- **Default**: `true`
settings.json
```python
{
"includeCoAuthoredBy": false
}
```
To hide all attribution, see [`attribution`](#attribution).
[](#includegitinstructions)
`includeGitInstructions`
Claude Code gives Claude two git-related pieces of context: its built-in instructions for how to write commits and pull requests, in the Bash tool’s description, and a git status snapshot of your repository. The snapshot holds the current branch, the main branch, `git status` output, and recent commits. Claude Code reads it when a conversation starts. Set this key to `false` to leave both out, for example when you use your own git workflow skills.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code includes its built-in commit and pull request workflow instructions and the git status snapshot. Cloud sessions never include the snapshot
- `false`: Claude Code leaves both out
- **Default**: `true`
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"includeGitInstructions": false
}
```
[](#prurltemplate)
`prUrlTemplate`
Point the PR links Claude Code renders, in the footer badge and in tool-result summaries, at an internal code-review tool instead of `github.com`. Claude Code substitutes `{host}`, `{owner}`, `{repo}`, `{number}`, and `{url}` from the PR URL. [GitLab merge request](interactive-mode.md#gitlab-merge-requests) links on both surfaces keep their GitLab URL.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a URL template using any of the five placeholders
- **Default**: unset
settings.json
```python
{
"prUrlTemplate": "https://reviews.example.com/{owner}/{repo}/pull/{number}"
}
```
Claude Code applies the template only to the links it renders itself; a PR number Claude writes in a message, such as `#123`, stays as Claude wrote it. A URL that doesn’t have the `/pull/<number>` shape is left unchanged.
[](#attribution-commit)
`attribution.commit`
Set the attribution text Claude Code adds to git commits, including any trailers. Set it to an empty string to hide commit attribution.
- **Scope**: [`Any file`](#scopes)
- **Type**: string
- **Default**: unset, so Claude Code adds `Co-Authored-By: <name> <noreply@anthropic.com>`. The name is the model in use when the commit is made, such as `Claude Sonnet 5`. When a [subagent](../09-Agents-Patterns/sub-agents.md) makes the commit, the trailer names the subagent’s model.
- When Claude Code recognizes the model as a Claude model but can’t confirm its exact version, it writes `Claude` alone.
- When it can’t match the model ID to any Claude model, such as a third-party model served through a custom [`ANTHROPIC_BASE_URL`](env-vars.md), it writes `Claude Code`.
This example replaces the default trailer with a custom line and a custom `Co-Authored-By` trailer:
settings.json
```python
{
"attribution": {
"commit": "Generated with AI\n\nCo-Authored-By: AI <ai@example.com>"
}
}
```
[](#attribution-pr)
`attribution.pr`
Set the attribution text Claude Code adds to pull request descriptions. Set it to an empty string to hide pull request attribution.
- **Scope**: [`Any file`](#scopes)
- **Type**: string
- **Default**: unset, so Claude Code adds `🤖 Generated with [Claude Code](https://claude.com/claude-code)`
settings.json
```python
{
"attribution": {
"pr": ""
}
}
```
[](#attribution-sessionurl)
`attribution.sessionUrl`
Choose whether Claude Code appends the claude.ai session link when it commits or opens a pull request from a [cloud](claude-code-on-the-web.md) or [Remote Control](remote-control.md) session. Claude Code adds the link as a `Claude-Session` trailer on commits and as a link in pull request descriptions. Set it to `false` to omit the link.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code appends the claude.ai session link when it commits or opens a pull request from a cloud or Remote Control session
- `false`: Claude Code omits the link
- **Default**: `true`
settings.json
```python
{
"attribution": {
"sessionUrl": false
}
}
```
[](#hooks-and-automation)
Hooks and automation
Register hooks, restrict which hooks run, and control workflows. For hook events and payloads, see the [hooks reference](../07-Hooks/hooks.md).
[](#allowedhttphookurls)
`allowedHttpHookUrls`
Limit which URLs [HTTP hooks](../07-Hooks/hooks.md#http-hook-fields) can target. When you define this key, Claude Code runs an HTTP hook only if its URL matches one of the patterns and blocks the rest without running them; an empty array blocks every HTTP hook.
- **Scope**: [`Any file`](#scopes). Arrays merge across settings files.
- **Type**: array of URL patterns, with `*` as a wildcard
- **Default**: unset, so any URL is allowed
This example allows any URL under `https://hooks.example.com/` and any `http://localhost` URL:
settings.json
```python
{
"allowedHttpHookUrls": ["https://hooks.example.com/*", "http://localhost:*"]
}
```
Hostname matching is case-insensitive and treats `hooks.example.com.`, with the trailing dot that marks a fully qualified domain name, the same as `hooks.example.com`, which is how DNS treats them. The allowlist applies to hooks from every source, including managed settings.
[](#allowmanagedhooksonly)
`allowManagedHooksOnly`
Restrict hook execution to hooks your organization deploys.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: only managed hooks run, plus Agent SDK hooks and hooks from plugins your managed settings force-enable. See [What runs under `allowManagedHooksOnly`](#what-runs-under-allowmanagedhooksonly)
- `false`: hooks from every settings scope and plugin run
- **Default**: unset, so hooks from every settings scope and plugin run
managed-settings.json
```python
{
"allowManagedHooksOnly": true
}
```
[](#what-runs-under-allowmanagedhooksonly)
What runs under `allowManagedHooksOnly`
When you set it to `true`, Claude Code changes which hooks and hook-like commands load:
- **Managed and SDK hooks run**: hooks from managed settings and hooks the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) registers in process
- **Force-enabled plugin hooks run**: hooks from plugins your managed settings force-enable through [`enabledPlugins`](#enabledplugins). Claude Code matches on the full `plugin@marketplace` ID, so a plugin with the same name from a different marketplace stays blocked. This lets you distribute vetted hooks through an organization marketplace while blocking everything else
- **Everything else is blocked**: user, project, and local hooks, hooks from other plugins, and hooks declared in agent frontmatter
- **Command-sourced plugins are disabled**: Claude Code also disables plugins with a [`command` source](../08-Plugins-Skills/plugins-marketplace-reference.md#command-plugin-source), including plugins force-enabled in managed `enabledPlugins`, unless you set [`disableCommandPluginSources`](#disablecommandpluginsources) to `false` explicitly
- **Marketplace `headersHelper` commands are blocked**: Claude Code also blocks marketplace [`headersHelper` commands](../08-Plugins-Skills/plugins-host-marketplace.md#authenticate-archive-downloads) unless [`disableCommandPluginSources`](#disablecommandpluginsources) is explicitly set to `false`, except for a marketplace that managed settings themselves declare. Requires Claude Code v2.1.238 or later
- **Status line and file suggestion narrow to managed settings**: Claude Code reads [`statusLine`](statusline.md), [`fileSuggestion`](#filesuggestion), and [`subagentStatusLine`](statusline.md#subagent-status-lines) from managed settings only, following the [status line and file suggestion gates](#status-line-and-file-suggestion-gates)
The [`/goal`](goal.md) command can’t run while this key is set, because it depends on hooks.
[](#disableallhooks)
`disableAllHooks`
Turn off [hooks](../07-Hooks/hooks.md#disable-or-remove-hooks), any custom [status line](statusline.md), and any custom [file suggestion](#filesuggestion) command. Use it to turn all of these off temporarily without deleting them from your settings.
- **Scope**: [`Any file`](#scopes). Only managed settings can disable managed hooks.
- **Type**: Boolean
- `true`: Claude Code turns off hooks, any custom status line, and any custom file suggestion command
- `false`: hooks, the status line, and the file suggestion command run
- **Default**: unset, so hooks run
settings.json
```python
{
"disableAllHooks": true
}
```
The reach depends on which file carries the key:
- **In managed settings**: Claude Code disables every configured hook, including managed ones, and keeps running the hooks the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) registers in process
- **In any other settings file**: Claude Code disables user, project, local, and plugin hooks; managed hooks, Agent SDK hooks, and hooks from plugins force-enabled in managed [`enabledPlugins`](#enabledplugins) keep running
Keeping Agent SDK hooks running when managed settings set this key requires Claude Code v2.1.242 or later. The [`/goal`](goal.md) command can’t run while hooks are disabled, and the `/hooks` menu shows a notice instead of your hooks.
[](#status-line-and-file-suggestion-gates)
Status line and file suggestion gates
Claude Code makes two decisions for `statusLine`, `fileSuggestion`, and `subagentStatusLine`, in this order:
- **Off entirely**: when managed settings set `disableAllHooks`, or when the folder isn’t trusted under the same [workspace trust rule as hooks in settings files](permissions.md#what-runs-before-you-trust-a-folder)
- **Narrowed to managed settings**: when [`allowManagedHooksOnly`](#allowmanagedhooksonly) is set, when `disableAllHooks` is `true` outside managed settings after [settings precedence](../07-Hooks/hooks.md#disable-or-remove-hooks) applies, or when you start Claude Code with `--safe-mode`
Under narrowing, Claude Code runs a managed value if one is deployed. Otherwise it skips your value without warning: the status line is disabled, and `@` autocomplete falls back to the built-in file suggestion.
[](#disableworkflows)
`disableWorkflows`
Turn off [dynamic workflows](workflows.md#turn-workflows-off) and the bundled workflow commands for everyone your settings reach, such as an organization through managed settings. To turn workflows on or off just for yourself, use [`enableWorkflows`](#enableworkflows) instead, which the **Dynamic workflows** toggle in `/config` writes to your user settings.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns off dynamic workflows and the bundled workflow commands for everyone your settings reach
- `false`: the same as unset; whether workflows are on then follows [`enableWorkflows`](#enableworkflows) and your plan’s default
- **Default**: `false`
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_WORKFLOWS`](env-vars.md) turns workflows off for one session; whichever of the two turns them off, the other can’t turn them back on
settings.json
```python
{
"disableWorkflows": true
}
```
[](#enableworkflows)
`enableWorkflows`
Turn [dynamic workflows](workflows.md) on or off for yourself when your plan’s default isn’t what you want. Appears in `/config` as **Dynamic workflows**, which writes this key to your user settings and removes it again when you toggle back to your plan’s default. To turn workflows off for everyone from managed settings, use [`disableWorkflows`](#disableworkflows) instead.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns dynamic workflows on for you
- `false`: Claude Code turns dynamic workflows off for you
- **Default**: unset, so workflows are on unless you’re on the Pro plan, where they’re off
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_WORKFLOWS`](env-vars.md) turns workflows off for one session, and `true` here can’t turn them back on while it’s set
settings.json
```python
{
"enableWorkflows": true
}
```
[`disableWorkflows`](#disableworkflows) and your organization’s workflows policy also take precedence: `enableWorkflows: true` can’t turn workflows back on while any source turns workflows off. Claude Code hides the `/config` row while a source other than your user settings sets `enableWorkflows`, or sets `disableWorkflows` to `true`.
[](#hooks)
`hooks`
Run your own commands, prompts, agents, HTTP requests, or MCP tools as [hooks](../07-Hooks/hooks.md) at points in Claude Code’s lifecycle, such as before a tool call or when a session starts; the [hooks reference](../07-Hooks/hooks.md#hook-events) lists every event, its payload, and its exit codes. Each event maps to a list of matcher groups, and each group lists the handlers to run when the matcher applies.
- **Scope**: [`Any file`](#scopes). Hooks merge across files rather than replacing each other, and hooks from managed settings can’t be removed from other files.
- **Type**: object keyed by [hook event](../07-Hooks/hooks.md#hook-events); each value is an array of `{ "matcher", "hooks" }` groups whose `hooks` entries have a `type` of `"command"`, `"prompt"`, `"agent"`, `"http"`, or `"mcp_tool"`
- **Default**: unset, so no hooks run
This example runs a script before every Bash tool call:
settings.json
```python
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/check-bash.sh" }
]
}
]
}
}
```
For every event, matcher pattern, and handler field, see the [hooks reference](../07-Hooks/hooks.md#configuration). To turn hooks off, see [`disableAllHooks`](#disableallhooks); to limit hooks to the ones your organization deploys, see [`allowManagedHooksOnly`](#allowmanagedhooksonly).
[](#httphookallowedenvvars)
`httpHookAllowedEnvVars`
An [HTTP hook](../07-Hooks/hooks.md#http-hook-fields) can put the value of an environment variable into a request header, for example an `Authorization: Bearer $HOOK_TOKEN` header, but only for variables the hook lists in its own `allowedEnvVars`. This key sets an outer limit on that list for every HTTP hook: a hook can use a variable only if both its own `allowedEnvVars` and this key name it. Use it to stop a hook from reading a secret it shouldn’t, even when the hook’s definition asks for it.
- **Scope**: [`Any file`](#scopes). Arrays merge across settings files.
- **Type**: array of environment variable names
- **Default**: unset, so each hook’s own `allowedEnvVars` list applies
This example limits header interpolation to `MY_TOKEN` and `HOOK_SECRET`:
settings.json
```python
{
"httpHookAllowedEnvVars": ["MY_TOKEN", "HOOK_SECRET"]
}
```
The allowlist applies to hooks from every source, including managed settings.
[](#workflowkeywordtriggerenabled)
`workflowKeywordTriggerEnabled`
Choose whether typing the keyword `ultracode` in a prompt triggers a [dynamic workflow](workflows.md#ask-for-a-workflow-in-your-prompt). Set it to `false` to type the word without triggering one.
- **Scope**: [`Any file`](#scopes). Appears in `/config` as **Ultracode keyword trigger**.
- **Type**: Boolean
- `true`: typing `ultracode` in a prompt triggers a dynamic workflow
- `false`: you can type the word without triggering one
- **Default**: `true`
settings.json
```python
{
"workflowKeywordTriggerEnabled": false
}
```
The `ultracode` effort setting, `/workflows`, and saved workflow commands are unaffected.
[](#workflowsizeguideline)
`workflowSizeGuideline`
Set the [agent count Claude aims for](workflows.md#set-a-size-guideline) in the dynamic workflows it writes. Claude Code sends the value to Claude as advice, not an enforced cap: `"small"` asks for fewer than 5 agents, `"medium"` fewer than 10, and `"large"` fewer than 50. Choose `"small"` when you want to bound what a workflow spends. Requires Claude Code v2.1.219 or later.
- **Scope**: [`Any file`](#scopes). A value there takes precedence over the **Dynamic workflow size** choice in `/config`, which Claude Code stores in `~/.claude.json`, and Claude Code hides that row while a settings file sets the key.
- **Type**: string, one of:
- `"unrestricted"`: no guideline, so Claude sizes the workflow to the task
- `"small"`: Claude aims for fewer than 5 agents
- `"medium"`: Claude aims for fewer than 10 agents
- `"large"`: Claude aims for fewer than 50 agents
- **Default**: `"medium"`, or `"small"` when you’re signed in on a Pro plan with Claude Code v2.1.271 or later
settings.json
```python
{
"workflowSizeGuideline": "small"
}
```
Requires Claude Code v2.1.219 or later; on v2.1.202 through v2.1.218, set the guideline in `/config` instead.
[](#plugins-and-skills)
Plugins and skills
Enable plugins, register marketplaces, restrict which plugin sources an organization allows, and control which skills load. For installing and building plugins, see [Plugins](../08-Plugins-Skills/plugins.md).
[](#disablebundledskills)
`disableBundledSkills`
Turn off the [skills](../08-Plugins-Skills/skills.md) and workflows included with Claude Code. Claude Code removes bundled skills and workflows entirely, while built-in commands such as `/init` stay typable but are hidden from the model.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code removes bundled skills and workflows and hides built-in commands such as `/init` from the model
- `false`: bundled skills load
- **Default**: unset, so bundled skills load
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_BUNDLED_SKILLS`](env-vars.md) set to `1` turns bundled skills off for one session; whichever of the two turns them off, the other can’t turn them back on
settings.json
```python
{
"disableBundledSkills": true
}
```
Skills from plugins, `.claude/skills/`, and `.claude/commands/` are unaffected. `/doctor` stays typable like the built-in commands; to hide it, set [`DISABLE_DOCTOR_COMMAND`](env-vars.md) instead.
[](#disableskillshellexecution)
`disableSkillShellExecution`
Turn off inline shell execution for `` !`...` `` and ```` ```! ```` blocks in [skills](../08-Plugins-Skills/skills.md) and custom commands from user, project, plugin, or additional-directory sources. Claude Code replaces each command with `[shell command execution disabled by policy]` instead of running it.
- **Scope**: [`Any file`](#scopes). A `true` in managed settings can’t be overridden by `false` elsewhere.
- **Type**: Boolean
- `true`: Claude Code replaces each inline shell command with `[shell command execution disabled by policy]` instead of running it
- `false`: inline shell runs
- **Default**: unset, so inline shell runs
settings.json
```python
{
"disableSkillShellExecution": true
}
```
Bundled skills and skills deployed through managed settings are unaffected.
[](#skilloverrides)
`skillOverrides`
Hide or collapse a [skill](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings) without editing its `SKILL.md`. Claude Code applies the value under each skill’s name to the skill list Claude sees and to your `/` autocomplete.
- **Scope**: [`Any file`](#scopes). The `/skills` menu writes to `.claude/settings.local.json`.
- **Type**: object mapping skill name to one of:
- `"on"`: Claude sees the skill and you can type `/name`
- `"name-only"`: Claude sees the skill by name without its description
- `"user-invocable-only"`: Claude doesn’t see the skill, but you can still type `/name`
- `"off"`: Claude doesn’t see the skill and `/name` is hidden from autocomplete
- **Default**: unset, so every skill is `"on"`
This example lists `legacy-context` to Claude by name only and hides `deploy` from Claude and from `/` autocomplete:
settings.json
```python
{
"skillOverrides": {
"legacy-context": "name-only",
"deploy": "off"
}
}
```
Overrides don’t apply to plugin skills, which you manage through `/plugin`. In managed settings and files passed with `--settings`, a key on a bundled skill’s alias, such as `checkup` for `/doctor`, also applies to the skill; see [how alias keys combine with keys on the skill’s own name](../08-Plugins-Skills/skills.md#override-skill-visibility-from-settings).
[](#syncclaudeaiskills)
`syncClaudeAiSkills`
Turn off the download of the [skills enabled for your claude.ai account](../08-Plugins-Skills/skills.md#how-synced-skills-behave). Claude Code downloads them into `~/.claude/skills/synced/` in [terminal sessions where you sign in with your claude.ai account](../08-Plugins-Skills/skills.md#where-synced-skills-load), interactive or non-interactive, and in Cowork and cloud sessions. Set `false` to stop that download and stop loading the skills it already synced. Claude Code honors only `false`: `true` is the same as unset and doesn’t turn syncing on where it’s otherwise off.
- **Scope**: [`User, local, or managed`](#scopes), and files passed with `--settings`. A repository can’t turn it off for you.
- **Type**: Boolean
- `false`: Claude Code stops downloading synced skills and stops loading the ones already in `~/.claude/skills/synced/`. In user or managed settings, it also moves them to `~/.claude/skills/.trash/`
- `true`: the same as unset
- **Default**: unset, so sessions signed in with your claude.ai account sync your skills
This example keeps a machine from downloading the account’s skills in any session:
settings.json
```python
{
"syncClaudeAiSkills": false
}
```
[](#syncclaudeaiplugins)
`syncClaudeAiPlugins`
Turn off the download of the [plugins enabled for your claude.ai account](../08-Plugins-Skills/plugins-loading.md#synced-plugins). Claude Code downloads them into `~/.claude/plugins/synced/` at the start of terminal sessions where you sign in with your claude.ai account and in Cowork sessions, and loads each one as `<name>@synced`. Set `false` to stop that download and stop loading the plugins it already synced. Claude Code honors only `false`: `true` is the same as unset and doesn’t turn syncing on where it’s otherwise off. Requires Claude Code v2.1.273 or later.
- **Scope**: [`User, local, or managed`](#scopes), and files passed with `--settings`. A repository can’t turn it off for you.
- **Type**: Boolean
- `false`: Claude Code stops downloading synced plugins and stops loading the ones already in `~/.claude/plugins/synced/`. In user or managed settings, it also moves them to `~/.claude/plugins/.trash/`
- `true`: the same as unset
- **Default**: unset, so sessions signed in with your claude.ai account sync your plugins
To turn off one synced plugin rather than all of them, set `"<name>@synced": false` in [`enabledPlugins`](#enabledplugins). This example keeps a machine from downloading the account’s plugins in any session:
settings.json
```python
{
"syncClaudeAiPlugins": false
}
```
[](#allowedchannelplugins)
`allowedChannelPlugins`
Choose which [channel](channels.md) plugins can push messages into sessions in your organization. When you set it, Claude Code uses your list in place of the default Anthropic allowlist; each entry names a plugin and the marketplace it comes from.
- **Scope**: [`Managed`](#scopes)
- **Type**: array of objects, each with `marketplace` and `plugin` strings. An entry can instead be a `"plugin@marketplace"` string such as `"telegram@claude-plugins-official"`, which Claude Code treats as the equivalent object. The string form requires Claude Code v2.1.267 or later; earlier versions reject the whole `allowedChannelPlugins` value when it contains one
- **Default**: unset, so Claude Code uses the default Anthropic allowlist
This example turns channels on and allows only the Telegram plugin from the official Anthropic marketplace:
managed-settings.json
```python
{
"channelsEnabled": true,
"allowedChannelPlugins": [
{ "marketplace": "claude-plugins-official", "plugin": "telegram" }
]
}
```
An empty array blocks every channel plugin. This key takes effect once channels pass the [`channelsEnabled`](#channelsenabled) gate for the account: on Team and Enterprise plans, and on Console accounts with managed settings, that means `channelsEnabled: true`. See [Restrict which channel plugins can run](channels.md#restrict-which-channel-plugins-can-run).
[](#blockedmarketplaces)
`blockedMarketplaces`
Block plugin marketplace sources for your organization. Claude Code checks the blocklist on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace someone added before you set the policy can’t be used to fetch plugins either. Blocked sources are checked before download, so they never touch the filesystem. If you set this key in the [claude.ai admin console](../13-Enterprise-Admin/server-managed-settings.md), claude.ai also applies it when anyone in your organization adds a marketplace from a git repository on claude.ai, as [How restrictions work](../08-Plugins-Skills/plugins-org.md#restrict-what-users-can-install) describes.
- **Scope**: [`Managed`](#scopes)
- **Type**: array of marketplace source objects, in the same forms as [`strictKnownMarketplaces`](#allowed-source-types)
- **Default**: unset, so no marketplace is blocked
This example blocks one GitHub repository as a marketplace source:
managed-settings.json
```python
{
"blockedMarketplaces": [
{ "source": "github", "repo": "untrusted/plugins" }
]
}
```
A `github` entry may use the [owner-wildcard form](#owner-wildcards) `"owner/*"` to block every repository under that GitHub owner, which requires Claude Code v2.1.223 or later. Add `{ "source": "skills-dir" }` to stop Claude Code loading [`@skills-dir` plugins](../08-Plugins-Skills/plugins-loading.md#plugins-shared-through-a-repository) from `~/.claude/skills/` without restricting any marketplace. See [Managed marketplace restrictions](../08-Plugins-Skills/plugins-org.md#restrict-what-users-can-install).
[](#channelsenabled)
`channelsEnabled`
Allow [channels](channels.md) for your organization. On claude.ai Team and Enterprise plans, Claude Code blocks channels until you set this to `true`. For [Anthropic Console](../13-Enterprise-Admin/iam.md#claude-console-authentication) accounts that authenticate with an API key, channels are allowed by default. If your organization deploys managed settings, Claude Code blocks channels on those accounts too until you set this key to `true`.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code allows channels for your organization
- `false`: the same as unset; whether channels are blocked depends on your plan, as the Default says
- **Default**: unset; channels are blocked on Team and Enterprise plans and on Console accounts with managed settings, and allowed on Pro and Max plans and on Console accounts without managed settings
managed-settings.json
```python
{
"channelsEnabled": true
}
```
To restrict which plugins can register as channels once they’re enabled, set [`allowedChannelPlugins`](#allowedchannelplugins). See [Enterprise controls](channels.md#enterprise-controls).
[](#disablecommandpluginsources)
`disableCommandPluginSources`
Block the [`command` plugin source](../08-Plugins-Skills/plugins-marketplace-reference.md#command-plugin-source), which installs a plugin by running a marketplace-declared command on the user’s machine. When you set it to `true`, Claude Code never runs the command, doesn’t install or update command-sourced plugins, and stops loading the ones already installed. Set it to `false` to allow them explicitly. Whenever it blocks command sources, whether you set it to `true` or leave it unset under [`allowManagedHooksOnly`](#allowmanagedhooksonly), it also blocks marketplace [`headersHelper` commands](../08-Plugins-Skills/plugins-host-marketplace.md#authenticate-archive-downloads), except for a marketplace that managed settings themselves declare. Requires Claude Code v2.1.229 or later, and the `headersHelper` block requires v2.1.238 or later.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code never runs the marketplace-declared command, doesn’t install or update command-sourced plugins, and stops loading the ones already installed
- `false`: Claude Code allows command-sourced plugins explicitly
- **Default**: unset, so Claude Code follows [`allowManagedHooksOnly`](#allowmanagedhooksonly): an organization that restricts hook execution to managed settings gets command sources disabled too
managed-settings.json
```python
{
"disableCommandPluginSources": true
}
```
Requires Claude Code v2.1.229 or later.
[](#pluginsuggestionmarketplaces)
`pluginSuggestionMarketplaces`
Name the marketplaces whose plugins can appear as contextual install suggestions, in spinner tips and pinned at the top of the `/plugin` **Discover** tab. The built-in first-party frontend-design tip is unaffected. Suggestions come from each plugin’s `relevance` declaration in its marketplace entry.
- **Scope**: [`Managed`](#scopes)
- **Type**: array of marketplace names
- **Default**: unset, so no marketplace-declared suggestions surface
managed-settings.json
```python
{
"pluginSuggestionMarketplaces": ["acme-corp-plugins"]
}
```
A name takes effect only when the marketplace is registered on the machine and its registered source is also declared in the same managed settings, either as the [`extraKnownMarketplaces`](#extraknownmarketplaces) entry for that name or as an entry of [`strictKnownMarketplaces`](#strictknownmarketplaces). Claude Code ignores a marketplace registered from a different source under an allowlisted name. The official marketplace is exempt from the source requirement: allowlisting its name alone suffices, since that name can only register from the official Anthropic source. See [Suggest plugins by context](../08-Plugins-Skills/plugins-relevance.md).
[](#plugintrustmessage)
`pluginTrustMessage`
Add your organization’s own text to the plugin trust warning Claude Code shows before installation, for example to confirm that plugins from your internal marketplace are vetted.
- **Scope**: [`Managed`](#scopes)
- **Type**: string
- **Default**: unset, so Claude Code shows the standard warning alone
managed-settings.json
```python
{
"pluginTrustMessage": "All plugins from our marketplace are approved by IT"
}
```
[](#strictknownmarketplaces)
`strictKnownMarketplaces`
Restrict which plugin marketplace sources people in your organization can add and install plugins from. Claude Code enforces the allowlist on marketplace add and on plugin install, update, refresh, and auto-update, before any network or filesystem operation, so a marketplace someone added before you set the policy can’t be used to fetch plugins once its source no longer matches. Blocked users see an error naming the managed policy. If you set this key in the [claude.ai admin console](../13-Enterprise-Admin/server-managed-settings.md), claude.ai also applies it when anyone in your organization adds a marketplace from a git repository on claude.ai, as [How restrictions work](../08-Plugins-Skills/plugins-org.md#restrict-what-users-can-install) describes.
- **Scope**: [`Managed`](#scopes)
- **Type**: array of marketplace source objects; see [Allowed source types](#allowed-source-types)
- **Default**: unset, so users can add any marketplace. An empty array is a complete lockdown that blocks every marketplace source, including the official Anthropic marketplace
This example allows two GitHub repositories, one pinned to the `v2.0` ref, and one hosted `marketplace.json` URL:
managed-settings.json
```python
{
"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" }
]
}
```
You can also write this key as `allowedMarketplaces`; [Marketplace key aliases](#marketplace-key-aliases) describes how Claude Code treats the alias and which version accepts it. This key is a policy gate: it controls what users may add but registers nothing. To restrict and pre-register in one file, see [Combine with `extraKnownMarketplaces`](#combine-with-extraknownmarketplaces). For the user-facing view, see [Managed marketplace restrictions](../08-Plugins-Skills/plugins-org.md#restrict-what-users-can-install).
[](#allowed-source-types)
Allowed source types
Each entry below shows one allowlist entry per source type and the fields it accepts. Most types match exactly; `hostPattern` and `pathPattern` match by regex, and `github` entries can use an [owner wildcard](#owner-wildcards).
| Source | Example entry | Fields |
|:--------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------|
| `github` | `{ "source": "github", "repo": "acme-corp/plugins", "ref": "main", "path": "marketplace" }` | `repo` required; `ref` is a branch or tag; `path` is a subdirectory |
| `git` | `{ "source": "git", "url": "https://gitlab.example.com/tools/plugins.git", "ref": "production" }` | `url` required; `ref` and `path` as for `github` |
| `url` | `{ "source": "url", "url": "https://plugins.example.com/marketplace.json", "headers": { "Authorization": "Bearer ${TOKEN}" } }` | `url` required; `headers` adds HTTP headers for authenticated access |
| `file` | `{ "source": "file", "path": "/opt/acme-corp/plugins/marketplace.json" }` | `path` required, the absolute path to a `marketplace.json` file |
| `directory` | `{ "source": "directory", "path": "/opt/acme-corp/approved-marketplaces" }` | `path` required, the absolute path to a directory containing `.claude-plugin/marketplace.json` |
| `hostPattern` | `{ "source": "hostPattern", "hostPattern": "^github\\.example\\.com$" }` | `hostPattern` required, a regex matched anywhere in the marketplace host; anchor it with `^` and `$` to match the whole host |
| `pathPattern` | `{ "source": "pathPattern", "pathPattern": "^/opt/approved/" }` | `pathPattern` required, a regex matched anywhere in the `path` of `file` and `directory` sources; start it with `^` to pin a prefix |
| `skills-dir` | `{ "source": "skills-dir" }` | No fields. Opts the `~/.claude/skills/` plugin scan back in |
Three source types carry rules beyond the table:
- **`url`**: a URL marketplace downloads only the `marketplace.json` file, and Claude Code doesn’t fetch plugin files by relative path from that server, so its plugins must use a [plugin source](../08-Plugins-Skills/plugins-marketplace-reference.md#plugin-sources) other than a relative path, such as an archive URL, which can be on the same host. For plugins with relative paths, use a Git-based marketplace instead. See [Plugins with relative paths fail in URL-based marketplaces](../08-Plugins-Skills/plugins-troubleshooting.md#plugins-with-relative-paths-fail-in-url-based-marketplaces).
- **`hostPattern`**: use it to allow every marketplace on an internal GitHub Enterprise or GitLab server without listing each repository. Claude Code matches `github` sources against `github.com`, takes the hostname from `url` sources, and takes it from `git` sources depending on the [git URL](https://git-scm.com/docs/git-clone#_git_urls)’s form:
- A URL with a scheme, such as `https://` or `ssh://`: the hostname in the URL.
- An SSH address without a scheme, in git’s `user@host:path` form, such as `git@git.example.com:tools/plugins.git`: the host between `@` and `:`, which is the host git connects to.
- Any other form without a scheme: no host, so no `strictKnownMarketplaces` `hostPattern` entry matches it. For a `blockedMarketplaces` `hostPattern`, Claude Code takes a host from a wider set of forms, so a blocklist entry can still match such a form. Before v2.1.234, a `strictKnownMarketplaces` `hostPattern` also matched some forms that git doesn’t treat as SSH addresses.
`file` and `directory` sources have no host and never match a `hostPattern` entry.
- **`pathPattern`**: use it to allow filesystem marketplaces alongside `hostPattern` entries for network sources. `".*"` allows every local path; a narrower pattern such as `"^/opt/approved/"` restricts to a directory.
Any allowlist, even an empty one, also stops Claude Code loading [`@skills-dir` plugins](../08-Plugins-Skills/plugins-loading.md#plugins-shared-through-a-repository) from `~/.claude/skills/`. Add the `{ "source": "skills-dir" }` entry to keep loading them; the entry has no meaning outside this key and `blockedMarketplaces`.
[](#owner-wildcards)
Owner wildcards
A `github` entry whose `repo` value is `"<owner>/*"` matches every repository under that GitHub owner. Owner wildcards require Claude Code v2.1.223 or later and work only in `strictKnownMarketplaces` and `blockedMarketplaces`. Everywhere else a `github` source appears, such as `extraKnownMarketplaces` or `/plugin marketplace add`, the `repo` value must name a single repository. Before v2.1.223, Claude Code compared the entry literally, so an allowlist entry matched no repository and a blocklist entry blocked nothing; single-repository entries are enforced on every version. This entry allows any marketplace repository in the `acme-corp` organization:
managed-settings.json
```python
{
"strictKnownMarketplaces": [
{ "source": "github", "repo": "acme-corp/*" }
]
}
```
Only the whole repository-name position can be a wildcard. Claude Code ignores entries such as `*`, `*/plugins`, or `acme-corp/tools-*` as invalid, so they match no repository. The matching rules differ between the two settings:
| Rule | `strictKnownMarketplaces` | `blockedMarketplaces` |
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| Matching source spellings | `owner/repo` form only. A git URL that clones the same repository doesn’t match | Any spelling, including git URLs that resolve to the same github.com repository |
| Owner case | Case-sensitive, like exact-entry matching | Case-insensitive |
| `ref` | Follows the exact-entry rules: an entry with a `ref` matches only sources with that exact ref, and an entry without one matches only sources that don’t specify a ref | An entry without a `ref` blocks all refs of the repositories it matches |
| `path` | Looser than the exact-entry rules: an entry with a `path` requires that exact value, while an entry without one matches any path inside the repository | An entry without a `path` blocks all paths of the repositories it matches |
[](#exact-matching)
Exact matching
For every source type except owner-wildcard `github` entries and the regex-matched `hostPattern` and `pathPattern` entries, Claude Code allows a user’s addition only when the marketplace source matches an entry exactly. For the git-based sources `github` and `git`, exact matching includes the optional fields:
- The `repo` or `url` must match exactly
- The `ref` field must match exactly, or both must be undefined
- The `path` field must match exactly, or both must be undefined
For example, Claude Code treats each pair below as two different sources:
- `{ "source": "github", "repo": "acme-corp/plugins" }` and `{ "source": "github", "repo": "acme-corp/plugins", "ref": "main" }`
- `{ "source": "github", "repo": "acme-corp/plugins", "path": "marketplace" }` and `{ "source": "github", "repo": "acme-corp/plugins" }`
[](#allow-only-the-official-marketplace)
Allow only the official marketplace
To allow the official Anthropic marketplace and nothing else, list its repository:
managed-settings.json
```python
{
"strictKnownMarketplaces": [
{ "source": "github", "repo": "anthropics/claude-plugins-official" }
]
}
```
With this entry, Claude Code keeps an already-registered official marketplace available and, on a fresh machine, registers the marketplace automatically the first time you start an interactive terminal session. Automatic registration most commonly misses:
- Non-interactive environments that run before the machine’s first interactive terminal session.
- Machines where Claude Code has only run through the VS Code extension.
- Machines where Claude Code already ran an interactive terminal session under a policy that blocked the marketplace, such as the empty-array lockdown. Claude Code records the blocked attempt and doesn’t retry after the policy changes.
On these machines, add the marketplace to [`extraKnownMarketplaces`](#extraknownmarketplaces) in the same `managed-settings.json` so Claude Code registers it automatically, or run `claude plugin marketplace add anthropics/claude-plugins-official`.
[](#combine-with-extraknownmarketplaces)
Combine with `extraKnownMarketplaces`
The two keys do different jobs. This table compares them:
| Aspect | `strictKnownMarketplaces` | `extraKnownMarketplaces` |
|-------------------|------------------------------------------|------------------------------------------------------------------------------------------------------|
| Purpose | Organizational policy enforcement | Team convenience |
| Settings file | Managed settings only | Any settings file |
| Behavior | Blocks non-allowlisted additions | Registers missing marketplaces |
| When enforced | Before network and filesystem operations | Immediately from user or managed settings; after the workspace trust dialog for a repository’s files |
| Can be overridden | No, highest precedence | Yes, by higher-precedence settings |
| Source format | Direct source object | Named marketplace with a nested `source` object |
To both restrict and pre-register a marketplace for all users, set both in `managed-settings.json`:
managed-settings.json
```python
{
"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 an allowed marketplace themselves with `/plugin marketplace add`. The official Anthropic marketplace is the only one Claude Code registers automatically, and only when the allowlist allows it. [Allow only the official marketplace](#allow-only-the-official-marketplace) lists the machines it misses.
[](#strictpluginonlycustomization)
`strictPluginOnlyCustomization`
Block skills, agents, hooks, and MCP servers from user and project sources, so they can come only from plugins or managed settings. Combine it with [`strictKnownMarketplaces`](#strictknownmarketplaces) to control the full customization supply chain: the marketplace allowlist controls which plugins users can install.
- **Scope**: [`Managed`](#scopes)
- **Type**: `true` to lock all four kinds of customization, or an array naming the kinds to lock, from `"skills"`, `"agents"`, `"hooks"`, and `"mcp"`
- **Default**: unset, so nothing is locked
This example locks skills and hooks and leaves agents and MCP servers unlocked:
managed-settings.json
```python
{
"strictPluginOnlyCustomization": ["skills", "hooks"]
}
```
The four sub-key entries below list what each surface blocks and what still loads. Claude Code ignores surface names it doesn’t recognize rather than failing the settings file, so you can add new surface names before every client has updated.
[](#strictpluginonlycustomization-skills)
`strictPluginOnlyCustomization.skills`
Lock the `skills` surface. Claude Code stops loading skills from `~/.claude/skills/` and `.claude/skills/`, custom commands from `~/.claude/commands/` and `.claude/commands/`, skills and commands under `--add-dir` directories, and skills synced from your claude.ai account. It keeps loading plugin skills, bundled skills, and skills in the managed policy directory.
- **Scope**: [`Managed`](#scopes)
- **Type**: the string `"skills"` in the [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) array
- **Default**: not locked
managed-settings.json
```python
{
"strictPluginOnlyCustomization": ["skills"]
}
```
[](#strictpluginonlycustomization-agents)
`strictPluginOnlyCustomization.agents`
Lock the `agents` surface. Claude Code stops loading agents from `~/.claude/agents/`, `.claude/agents/`, and `--add-dir` directories. It keeps loading plugin agents, built-in agents, and agents in the managed policy directory.
- **Scope**: [`Managed`](#scopes)
- **Type**: the string `"agents"` in the [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) array
- **Default**: not locked
managed-settings.json
```python
{
"strictPluginOnlyCustomization": ["agents"]
}
```
[](#strictpluginonlycustomization-hooks)
`strictPluginOnlyCustomization.hooks`
Lock the `hooks` surface. Claude Code stops running hooks from user, project, and local `settings.json`, and keeps running plugin hooks and hooks in managed settings.
- **Scope**: [`Managed`](#scopes)
- **Type**: the string `"hooks"` in the [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) array
- **Default**: not locked
managed-settings.json
```python
{
"strictPluginOnlyCustomization": ["hooks"]
}
```
[](#strictpluginonlycustomization-mcp)
`strictPluginOnlyCustomization.mcp`
Lock the `mcp` surface. Claude Code stops loading MCP servers from `~/.claude.json` and `.mcp.json`, and keeps loading plugin MCP servers, [`managed-mcp.json`](../06-MCP-Tools/General/managed-mcp.md) servers, and servers from [`managedMcpServers`](#managedmcpservers).
- **Scope**: [`Managed`](#scopes)
- **Type**: the string `"mcp"` in the [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) array
- **Default**: not locked
managed-settings.json
```python
{
"strictPluginOnlyCustomization": ["mcp"]
}
```
[](#enabledplugins)
`enabledPlugins`
Turn individual [plugins](../08-Plugins-Skills/plugins.md) on or off, keyed by `plugin-name@marketplace-name`. A plugin with no entry at any scope falls back to its [`defaultEnabled`](../08-Plugins-Skills/plugins-reference.md#fields) value. When you enable or disable a plugin with `/plugin` or `claude plugin enable`, Claude Code writes this key for you.
- **Scope**: [`Any file`](#scopes)
- **Type**: object mapping `plugin-name@marketplace-name` to a Boolean
- **Default**: unset, so each plugin follows its `defaultEnabled` value
This example enables two plugins from the `team-tools` marketplace and disables one from `personal`:
settings.json
```python
{
"enabledPlugins": {
"code-formatter@team-tools": true,
"deployment-tools@team-tools": true,
"experimental-features@personal": false
}
}
```
Each scope serves a different purpose:
- **User settings**: your personal plugin preferences
- **Project settings**: plugins shared with everyone in the repository
- **Local settings**: per-machine overrides, gitignored when Claude Code saves a setting there
- **Managed settings**: organization-wide policy. A plugin set to `false` here is blocked from installation at every scope and hidden from the marketplace
Project settings take precedence over user settings, so setting a plugin to `false` in `~/.claude/settings.json` doesn’t 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 can’t be disabled this way, since managed settings override local settings. Enabling a plugin from an external source such as a GitHub repository or npm package in a project’s `.claude/settings.json` doesn’t install it for other people. On every path that loads plugins, Claude Code reports the plugin as not installed until each user [installs it themselves](../08-Plugins-Skills/plugins-org.md#require-plugins-per-repository).
[](#extraknownmarketplaces)
`extraKnownMarketplaces`
Register additional plugin marketplaces by name, so that people who open the repository, or everyone your managed settings reach, get the marketplace without adding it themselves. Claude Code registers each marketplace it doesn’t already know. Whether a plugin that [`enabledPlugins`](#enabledplugins) names from it installs depends on the plugin’s source and which file enables it; that entry has the rules.
- **Scope**: [`Any file`](#scopes). Claude Code honors entries in a repository’s `.claude/settings.json` or `.claude/settings.local.json` only after you accept the workspace trust dialog for that folder; in a folder you haven’t trusted, including a `-p` run there, it ignores them without a message.
- **Type**: object mapping a marketplace name to an object with a `source` object and an optional `autoUpdate` Boolean
- **Default**: unset
This example registers a GitHub marketplace and a marketplace from a self-hosted git URL:
settings.json
```python
{
"extraKnownMarketplaces": {
"acme-tools": {
"source": {
"source": "github",
"repo": "acme-corp/claude-plugins"
}
},
"security-plugins": {
"source": {
"source": "git",
"url": "https://git.example.com/security/plugins.git"
}
}
}
}
```
[What runs before you trust a folder](permissions.md#what-runs-before-you-trust-a-folder) compares the trust gate with the other content a repository can supply. You can also write this key as `additionalMarketplaces`; see [Marketplace key aliases](#marketplace-key-aliases). Set `"autoUpdate": true` alongside `source` to make Claude Code refresh that marketplace and update its installed plugins in the background after startup. When omitted, `claude-plugins-official` and most other official Anthropic marketplaces default to `true`, and third-party marketplaces default to `false`. See [Configure auto-updates](../08-Plugins-Skills/discover-plugins.md#keep-plugins-updated). When more than one settings file defines a marketplace entry under the same name, Claude Code uses the entry from the [highest-precedence file](settings.md#settings-precedence) whole. That entry replaces the lower-precedence entry and inherits none of its fields, so a redefinition can’t combine one file’s `source.headers` credential with a URL another file controls. Before v2.1.228, Claude Code merged same-name entries field by field, so an entry in a higher-precedence file could inherit fields it didn’t set, including another file’s `headers`.
[](#marketplace-source-types)
Marketplace source types
The `source` object takes one of these forms:
- **`github`**: a GitHub repository, with `repo`
- **`git`**: any git URL, with `url`
- **`url`**: a direct URL to a `marketplace.json` file, with `url` and optional `headers` and `headersHelper` for authenticated access. `headersHelper` names a command that prints headers whose values are too short-lived to list in `headers`, and requires Claude Code v2.1.238 or later
- **`file`**: a local path to a `marketplace.json` file, with `path`
- **`directory`**: a local filesystem path, with `path`, for development only
- **`settings`**: an inline marketplace declared directly in the settings file without a hosted repository, with `name` and `plugins`
The `git` source type works with any git hosting service, including self-hosted GitLab and Bitbucket. Claude Code clones the repository with the same authentication that `git clone` would use on that machine: configured credential helpers or SSH keys. A provider token such as `GITHUB_TOKEN` takes effect through a credential helper that reads it. See [Private repositories](../08-Plugins-Skills/plugins-host-marketplace.md#grant-access-to-a-private-marketplace) for setup details. For `github` and `git` sources, Claude Code never downloads [Git LFS](https://git-lfs.com) content when it clones the marketplace repository to add or update it. LFS-tracked files are checked out as pointer files, and the add or update output reports how many. The `skipLfs` field inside the `source` object is accepted and has no effect. Before v2.1.274, Claude Code downloaded LFS content unless you set `"skipLfs": true`. For a `url` source, set `headersHelper` inside the `source` object when the credential in `headers` expires and a command has to produce a fresh one. Requires Claude Code v2.1.238 or later. For what the command must print and where Claude Code runs it, see [Write the headersHelper command](../08-Plugins-Skills/plugins-host-marketplace.md#write-the-headershelper-command), and for the cases where Claude Code doesn’t run it, see [When Claude Code skips a headersHelper command](../08-Plugins-Skills/plugins-host-marketplace.md#when-claude-code-skips-a-headershelper-command-or-drops-its-output). Once you set `headersHelper` on an `https://` marketplace URL, Claude Code runs the command at two points, reusing one run’s output for up to 60 seconds:
- Before each fetch of that marketplace’s `marketplace.json`, including a later refresh. Claude Code sends the printed headers with that fetch.
- Before each plugin archive download on the marketplace URL’s origin, meaning the same scheme, host, and port. Claude Code sends the output with that download, and no other download gets the headers.
Claude Code ignores any `headersHelper` set in the `.claude/settings.json` or `.claude/settings.local.json` of a directory you add with [`--add-dir`](permissions.md#what-runs-before-you-trust-a-folder), on a `url` source and on an inline plugin entry alike, and sends only the fixed `headers` set in that file. [How users accept a headersHelper command](../08-Plugins-Skills/plugins-host-marketplace.md#how-users-accept-a-headershelper-command) covers the other settings files. Plugins listed in a `settings` source must reference external sources such as GitHub or npm, and the `name` must match the marketplace key. You still enable each plugin separately in `enabledPlugins`. This example declares one plugin inline:
settings.json
```python
{
"extraKnownMarketplaces": {
"team-tools": {
"source": {
"source": "settings",
"name": "team-tools",
"plugins": [
{
"name": "code-formatter",
"source": {
"source": "github",
"repo": "acme-corp/code-formatter"
}
}
]
}
}
}
}
```
A plugin entry under `source: 'settings'` whose own `source` is an [`archive`](../08-Plugins-Skills/plugins-marketplace-reference.md#archive-plugin-source) can set `headers` for the archive download. If the value you would put in `headers` is short-lived, such as a token your registry mints on request, set a `headersHelper` command instead. An entry may set both. Both fields require Claude Code v2.1.238 or later. Claude Code sends the entry’s `headers`, and whatever the command prints, with that plugin’s archive download and with no other download. Claude Code runs the command only when a user [installs or updates that one plugin by itself](../08-Plugins-Skills/plugins-host-marketplace.md#how-users-accept-a-headershelper-command). Three further rules depend on which file holds the entry:
- **`strict`**: unlike an entry in a marketplace’s `marketplace.json`, an entry in settings doesn’t need `"strict": false`, because a settings file carries no manifest fields to inline. See [Strict mode](../08-Plugins-Skills/plugins-marketplace-reference.md#strict-mode).
- **Folder trust**: for an entry in a project’s `.claude/settings.json` or `.claude/settings.local.json`, Claude Code runs the command only after the user has also [trusted that folder](permissions.md#what-runs-before-you-trust-a-folder).
- **Header filter**: Claude Code drops [request-routing and client-identity header names](../08-Plugins-Skills/plugins-host-marketplace.md#when-claude-code-skips-a-headershelper-command-or-drops-its-output) from an entry in a project’s `.claude/settings.json` or `.claude/settings.local.json`, because a repository can supply those files. Claude Code applies the same filter to a catalog entry and to an entry in an `--add-dir` directory’s settings, and no filter to an entry in your user settings, a `--settings` file, or managed settings.
[](#marketplace-key-aliases)
Marketplace key aliases
On Claude Code v2.1.232 or later, you can write `extraKnownMarketplaces` as `additionalMarketplaces` and `strictKnownMarketplaces` as `allowedMarketplaces`. Claude Code treats each alias as follows:
- Earlier versions ignore the alias, so keep the canonical spelling in a file that older versions also read, such as a managed settings file for a fleet with mixed Claude Code versions.
- In any settings file that accepts the canonical key, Claude Code reads the alias exactly as it reads the canonical key.
- Claude Code may rewrite `additionalMarketplaces` to `extraKnownMarketplaces` when it updates the file.
- If you set both spellings in one file, Claude Code uses the canonical value and ignores the alias.
[](#pluginconfigs)
`pluginConfigs`
Store the non-sensitive answers you give a plugin’s [`userConfig`](../08-Plugins-Skills/plugins-reference.md#user-configuration) configuration dialog, keyed by plugin ID. Claude Code writes this key to your user settings when you fill in the dialog, so you don’t need to edit it by hand. Claude Code stores sensitive options in the macOS Keychain instead, falling back to `~/.claude/.credentials.json` when the Keychain rejects the write; on platforms without a supported keychain, it stores them in `~/.claude/.credentials.json`.
- **Scope**: [`User or managed`](#scopes)
- **Type**: object mapping a plugin ID to an object with an `options` field, mapping each option name to a string, number, Boolean, or array of strings, and an optional `mcpServers` field holding per-server user configuration values in the same shape
- **Default**: unset
This example stores the `api_endpoint` option for the `deployer` plugin from `acme-tools`:
settings.json
```python
{
"pluginConfigs": {
"deployer@acme-tools": {
"options": {
"api_endpoint": "https://api.example.com"
}
}
}
}
```
Built-in plugins store their options under the same key with an `@builtin` suffix. For example, the [**Project instructions**](memory.md#choose-which-instruction-files-load) setting that controls whether Claude Code reads `AGENTS.md` files is `pluginConfigs["agents-md@builtin"].options.instructionFiles`. Claude Code ignores project and local entries because it substitutes these values into plugin hook, MCP, and LSP configurations, and a cloned repository must not be able to supply them. Before v2.1.207, project and local settings were also read.
[](#mcp)
MCP
Control which MCP servers Claude Code connects to and which an organization allows. See [Connect to external tools with MCP](../06-MCP-Tools/General/mcp.md) and [Managed MCP configuration](../06-MCP-Tools/General/managed-mcp.md).
[](#allowallclaudeaimcps)
`allowAllClaudeAiMcps`
Load the [claude.ai connectors](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) Claude Code fetches itself alongside a deployed `managed-mcp.json`. Without this key, `managed-mcp.json` takes exclusive control of MCP servers and suppresses those connectors.
- **Scope**: [`Managed`](#scopes). Users can’t re-enable connectors that exclusive control suppressed.
- **Type**: Boolean
- `true`: Claude Code loads the claude.ai connectors alongside a deployed `managed-mcp.json`
- `false`: a deployed `managed-mcp.json` takes exclusive control of MCP servers and suppresses the claude.ai connectors [Claude Code fetches itself](../06-MCP-Tools/General/mcp.md#how-connectors-reach-claude-code)
- **Default**: `false`, so a deployed `managed-mcp.json` suppresses the claude.ai connectors Claude Code fetches itself
managed-settings.json
```python
{
"allowAllClaudeAiMcps": true
}
```
[`allowedMcpServers`](#allowedmcpservers) and [`deniedMcpServers`](#deniedmcpservers) still apply to the connectors this key loads. Connectors delivered to a [cloud session](claude-code-on-the-web.md) whose host carries a `managed-mcp.json`, such as a self-hosted runner, stay suppressed. See [Allow claude.ai connectors alongside the managed set](../06-MCP-Tools/General/managed-mcp.md#allow-claude-ai-connectors-alongside-the-managed-set).
[](#allowclaudeinchromewithmanagedmcp)
`allowClaudeInChromeWithManagedMcp`
Let the built-in [Claude in Chrome](../03-IDE-Integrations/chrome.md) server run alongside a deployed `managed-mcp.json`. Without this key, a deployed `managed-mcp.json` blocks Claude in Chrome in terminal sessions. Requires Claude Code v2.1.282 or later.
- **Scope**: [`Managed`](#scopes), from the device’s own managed settings only: an MDM-deployed plist or HKLM registry key, or a system `managed-settings.json` file. Claude Code ignores it in server-managed settings, in the user-writable HKCU registry, and in user or project settings.
- **Type**: Boolean
- `true`: the built-in Claude in Chrome server can run alongside a deployed `managed-mcp.json`
- `false`: a deployed `managed-mcp.json` blocks Claude in Chrome in terminal sessions
- **Default**: `false`, so a deployed `managed-mcp.json` blocks Claude in Chrome in terminal sessions
managed-settings.json
```python
{
"allowClaudeInChromeWithManagedMcp": true
}
```
A [`deniedMcpServers`](#deniedmcpservers) entry for `claude-in-chrome` still blocks the server with this key on. See [Allow Claude in Chrome alongside the managed set](../06-MCP-Tools/General/managed-mcp.md#allow-claude-in-chrome-alongside-the-managed-set).
[](#allowedmcpservers)
`allowedMcpServers`
Allowlist the MCP servers people can add. Claude Code blocks any server that doesn’t match an entry wherever it’s defined, including plugin servers, servers a user passes with `--mcp-config`, and servers from claude.ai. Built-in servers such as Claude in Chrome, the `ide` server Claude Code connects to in a running [VS Code](../03-IDE-Integrations/vs-code.md#the-built-in-ide-mcp-server) or [JetBrains](../03-IDE-Integrations/jetbrains.md#the-built-in-ide-mcp-server) IDE, and servers the CLI itself configures are exempt from the allowlist, and the denylist still applies to them. On Claude Code v2.1.268 or later, a [Claude Tag](claude-tag.md) session’s Slack tools are also exempt from the allowlist, and the denylist still applies to them. In-process `type: "sdk"` servers are exempt from both lists; the [app that started the session](../06-MCP-Tools/General/mcp.md#how-connectors-reach-claude-code) registers them. Servers your organization delivers are also exempt from the allowlist, and the denylist still applies to them. The exemption covers every [`managedMcpServers`](#managedmcpservers) entry, and any [`managed-mcp.json`](../06-MCP-Tools/General/managed-mcp.md#exclusive-control-with-managed-mcp-json) entry whose values use no `${VAR}` expansion. See [How a server is evaluated](../06-MCP-Tools/General/managed-mcp.md#how-a-server-is-evaluated) for the full check order. Before v2.1.259, servers from `managed-mcp.json` had to match too.
- **Scope**: [`Any file`](#scopes). Entries from every file merge into one allowlist unless [`allowManagedMcpServersOnly`](#allowmanagedmcpserversonly) is set. Deploy it in managed settings to enforce it.
- **Type**: array of objects, each with exactly one key: `serverName`, a string limited to letters, numbers, hyphens, and underscores; `serverCommand`, an array of the command and its arguments matched exactly; or `serverUrl`, a URL pattern with `*` wildcards
- **Default**: unset, so every server is allowed; an empty array blocks every server users add
This example allows only the stdio server that the listed `npx` command starts:
settings.json
```python
{
"allowedMcpServers": [
{ "serverCommand": ["npx", "-y", "@modelcontextprotocol/server-filesystem"] }
]
}
```
A [`deniedMcpServers`](#deniedmcpservers) entry takes precedence, so a server on both lists is blocked. Once the list contains any `serverCommand` entry, a stdio server must match a `serverCommand` entry, and once it contains any `serverUrl` entry, a remote server must match a `serverUrl` entry: a `serverName` match no longer admits that kind of server. See [Policy-based control with allowlists and denylists](../06-MCP-Tools/General/managed-mcp.md#policy-based-control-with-allowlists-and-denylists).
[](#allowmanagedmcpserversonly)
`allowManagedMcpServersOnly`
Make the managed allowlist the only one that applies. Claude Code then reads [`allowedMcpServers`](#allowedmcpservers) from managed settings alone and ignores allowlists in user, project, and local settings; [`deniedMcpServers`](#deniedmcpservers) still merges from every settings scope, so users can still block servers for themselves. Administrators set it so a user’s own settings can’t broaden what the managed allowlist permits.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code reads `allowedMcpServers` from managed settings alone and ignores allowlists in user, project, and local settings
- `false`: allowlists from every settings scope merge
- **Default**: `false`, so allowlists from every settings scope merge
This example locks the allowlist to managed settings and allows only the server named `github`:
managed-settings.json
```python
{
"allowManagedMcpServersOnly": true,
"allowedMcpServers": [
{ "serverName": "github" }
]
}
```
Users can still add MCP servers of their own; only servers that match the managed allowlist load. See [Restrict the allowlist to managed settings only](../06-MCP-Tools/General/managed-mcp.md#restrict-the-allowlist-to-managed-settings-only).
[](#deniedmcpservers)
`deniedMcpServers`
Block specific MCP servers. Claude Code refuses to load a matching server wherever it’s defined, including plugin servers, servers passed with `--mcp-config`, servers from `managed-mcp.json`, servers from [`managedMcpServers`](#managedmcpservers), and the claude.ai connectors [it fetches itself](../06-MCP-Tools/General/mcp.md#how-connectors-reach-claude-code). In-process `type: "sdk"` servers are exempt; the app that started the session registers them.
- **Scope**: [`Any file`](#scopes). Entries from every file merge into one denylist, and [`allowManagedMcpServersOnly`](#allowmanagedmcpserversonly) doesn’t change that. Deploy it in managed settings to enforce it.
- **Type**: array of objects, each with exactly one key: `serverName`, a string, so a claude.ai connector’s display name such as `"claude.ai Slack"` works; `serverCommand`, an array of the command and its arguments matched exactly; or `serverUrl`, a URL pattern with `*` wildcards
- **Default**: unset, so no server is blocked; an empty array also blocks nothing
settings.json
```python
{
"deniedMcpServers": [
{ "serverName": "filesystem" }
]
}
```
The denylist takes precedence over [`allowedMcpServers`](#allowedmcpservers), so a server on both lists is blocked. See [Policy-based control with allowlists and denylists](../06-MCP-Tools/General/managed-mcp.md#policy-based-control-with-allowlists-and-denylists).
[](#disableclaudeaiconnectors)
`disableClaudeAiConnectors`
Turn off the [claude.ai MCP connectors](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) [Claude Code fetches itself](../06-MCP-Tools/General/mcp.md#how-connectors-reach-claude-code), so it neither fetches nor connects them. A `true` in any settings file applies: a checked-in project `.claude/settings.json` can opt a repository out of those connectors, but a project-level `false` can’t override a user- or managed-level `true`.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code neither fetches nor connects those connectors
- `false`: the same as unset; Claude Code fetches your connectors unless another settings file or `ENABLE_CLAUDEAI_MCP_SERVERS` turns them off
- **Default**: `false`, so Claude Code fetches your connectors
- **Per-session overrides**: [`ENABLE_CLAUDEAI_MCP_SERVERS`](env-vars.md) set to `false` turns connectors off for one session; whichever of the two turns them off, the other can’t turn them back on
settings.json
```python
{
"disableClaudeAiConnectors": true
}
```
Servers you pass explicitly with `--mcp-config` are unaffected. To block individual connectors instead of all of them, use [`deniedMcpServers`](#deniedmcpservers). See [Disable claude.ai connectors](../06-MCP-Tools/General/mcp.md#disable-claude-ai-connectors).
[](#disabledmcpjsonservers)
`disabledMcpjsonServers`
Reject specific servers defined in a project’s `.mcp.json` file so Claude Code never connects them or asks you to approve them. A rejection in any settings file applies, including a project `.claude/settings.json` checked into the repository.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, the server names as they appear in `.mcp.json`
- **Default**: unset
settings.json
```python
{
"disabledMcpjsonServers": ["filesystem"]
}
```
Claude Code writes this key to `.claude/settings.local.json` when you reject a server in the approval dialog. `claude mcp get <name>` shows a rejected server as `✘ Rejected (see disabledMcpjsonServers in settings)`. Rejection takes precedence over [`enabledMcpjsonServers`](#enabledmcpjsonservers) and [`enableAllProjectMcpServers`](#enableallprojectmcpservers).
[](#enableallprojectmcpservers)
`enableAllProjectMcpServers`
Approve every MCP server defined in project `.mcp.json` files without a prompt. Claude Code writes this key to `.claude/settings.local.json` when you choose to approve all servers in the approval dialog.
- **Scope**: [`Any file`](#scopes). In a folder whose trust dialog you haven’t accepted, Claude Code honors it from user settings, managed settings, and `--settings` and ignores it in the shared project file, both in the session and for `claude mcp list` and `claude mcp get`; [Project server approvals and workspace trust](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) says when an untracked `.claude/settings.local.json` counts too.
- **Type**: Boolean
- `true`: Claude Code approves every MCP server defined in project `.mcp.json` files without a prompt
- `false`: Claude Code asks you to approve each server. In a trusted folder, a `false` in a higher-precedence file overrides a `true` in a lower one; in a folder you haven’t trusted, a `true` in any honored file is enough
- **Default**: unset, so Claude Code asks you to approve each server
settings.json
```python
{
"enableAllProjectMcpServers": true
}
```
A [`disabledMcpjsonServers`](#disabledmcpjsonservers) entry still rejects a server.
[](#enabledmcpjsonservers)
`enabledMcpjsonServers`
Approve specific servers defined in project `.mcp.json` files so Claude Code connects them without asking. Claude Code writes this key to `.claude/settings.local.json` when you approve a server in the approval dialog.
- **Scope**: [`Any file`](#scopes). In a folder whose trust dialog you haven’t accepted, Claude Code honors it from user settings, managed settings, and `--settings` and ignores it in the shared project file, both in the session and for `claude mcp list` and `claude mcp get`; [Project server approvals and workspace trust](../06-MCP-Tools/General/mcp.md#project-server-approvals-and-workspace-trust) says when an untracked `.claude/settings.local.json` counts too.
- **Type**: array of strings, the server names as they appear in `.mcp.json`
- **Default**: unset
This example approves the `memory` and `github` servers from the project’s `.mcp.json`:
settings.json
```python
{
"enabledMcpjsonServers": ["memory", "github"]
}
```
A [`disabledMcpjsonServers`](#disabledmcpjsonservers) entry still rejects a server.
[](#managedmcpservers)
`managedMcpServers`
Provide remote MCP servers to every user from managed settings. Users keep the servers they add themselves and can’t edit or remove the ones you provide. Requires Claude Code v2.1.259 or later.
- **Scope**: [`Managed`](#scopes). Claude Code drops the key with a warning in user, project, and local settings, and doesn’t read it in the Claude Desktop app’s Code tab on a third-party deployment or in the app’s Cowork sessions, where Claude Desktop supplies and locks those sessions’ MCP servers itself.
- **Type**: object keyed by server name. Each entry has the `.mcp.json` shape for an `http` or `sse` server: a required `https://` `url`, and optionally `headers`, `oauth`, and the other HTTP and SSE options. Claude Code drops entries that fail validation, and [What an entry can contain](../06-MCP-Tools/General/managed-mcp.md#what-an-entry-can-contain) lists the conditions
- **Default**: unset, so managed settings provide no servers
This example provides one HTTP server named `search`:
managed-settings.json
```python
{
"managedMcpServers": {
"search": {
"type": "http",
"url": "https://search.example.com/mcp"
}
}
}
```
For precedence, how provided servers combine with `managed-mcp.json` and the allow and deny lists, and what users see, see [Provide servers through managed settings](../06-MCP-Tools/General/managed-mcp.md#provide-servers-through-managed-settings).
[](#agents-sessions-and-worktrees)
Agents, sessions, and worktrees
Set the default agent, control teammates and cross-session messaging, and configure worktrees. See [Subagents](../09-Agents-Patterns/sub-agents.md) and [Worktrees](worktrees.md).
[](#agent)
`agent`
Run the main thread as a named [subagent](../09-Agents-Patterns/sub-agents.md#invoke-subagents-explicitly), so Claude Code applies that subagent’s system prompt, tool restrictions, and model to your session. The same key sets the default agent for sessions you dispatch from `claude agents`.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, the name of a built-in or custom agent
- **Default**: unset, so the main thread runs as Claude Code’s default agent
- **Per-session overrides**: `--agent` takes precedence over this key for one session
settings.json
```python
{
"agent": "code-reviewer"
}
```
A plugin’s own `settings.json` can also supply this key; see [Ship default settings with your plugin](../08-Plugins-Skills/plugins-components.md#default-settings).
[](#crosssessioninbound)
`crossSessionInbound`
Choose what this session does with [messages arriving from your other Claude Code sessions](cross-session-messaging.md#control-inbound-messages). When no value applies, Claude Code decides per message from the two sessions’ permission-mode classes. Requires Claude Code v2.1.224 or later.
- **Scope**: [`Any file`](#scopes). A project or local value applies only when it’s stricter than the value managed settings, the `--settings` flag, or user settings give.
- **Type**: string, one of:
- `"accept"`: Claude Code delivers the message to Claude
- `"hold"`: Claude Code shows a notice for the message without delivering it
- `"refuse"`: Claude Code drops the message
- **Default**: unset, so Claude Code decides per message
settings.json
```python
{
"crossSessionInbound": "hold"
}
```
Claude Code reads managed settings first, then the `--settings` flag, then user settings, and applies the first value found. `refuse` is stricter than `hold`, and `hold` is stricter than `accept`. When none of the trusted sources sets a value, a project or local `hold` or `refuse` still applies, replacing the per-message default. In sessions with cross-session messaging, this key appears in `/config` as **Messages from your other sessions**, which writes it to user settings; the row requires Claude Code v2.1.232 or later, and Claude Code hides it while the `--settings` flag or managed settings set the key. Claude Code [warns](errors.md#crosssessioninbound-must-be-one-of-accept-hold-refuse) when you set a value it doesn’t recognize. While that value is present in a user, project, local, or `--settings` file, Claude Code holds inbound messages, even when a source that takes precedence sets `accept`. A `refuse` that another source sets still applies. Fix or remove the value to clear the hold. When the unrecognized value is in [managed settings](../13-Enterprise-Admin/managed-settings.md), Claude Code instead treats it as `refuse` until an administrator fixes it. Before v2.1.248, Claude Code ignored an unrecognized value without warning.
[](#disableagentview)
`disableAgentView`
Turn off [background agents and agent view](../09-Agents-Patterns/agent-view.md): `claude agents`, `--bg`, `/background`, and the on-demand supervisor. Set it in [managed settings](../13-Enterprise-Admin/managed-settings.md) to enforce it for an organization.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns off `claude agents`, `--bg`, `/background`, and the on-demand supervisor
- `false`: agent view is available
- **Default**: unset, so agent view is available
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_AGENT_VIEW`](env-vars.md) turns agent view off for one session; whichever of the two turns it off, the other can’t turn it back on
settings.json
```python
{
"disableAgentView": true
}
```
[](#isolatepeermachines)
`isolatePeerMachines`
Require your explicit approval before Claude’s `SendMessage` reaches one of your sessions beyond this machine; see [Require approval for cross-machine messages](cross-session-messaging.md#require-approval-for-cross-machine-messages). The approval prompt appears even in [`bypassPermissions` mode](permission-modes.md#skip-all-checks-with-bypasspermissions-mode).
- **Scope**: [`Any file`](#scopes). A `true` from any scope applies, so a checked-in project file can turn the requirement on but not off.
- **Type**: Boolean
- `true`: Claude Code asks for your approval before Claude’s `SendMessage` reaches one of your sessions beyond this machine
- `false`: cross-machine messages don’t prompt
- **Default**: unset, so cross-machine messages don’t prompt
settings.json
```python
{
"isolatePeerMachines": true
}
```
The cross-machine `SendMessage` approval requires Claude Code v2.1.224 or later.
[](#processwrapper)
`processWrapper`
On macOS and Linux, place a corporate launcher command in front of the [background processes Claude Code starts](../13-Enterprise-Admin/corporate-launcher.md#what-the-launcher-covers). Claude Code runs the launcher with its own command line appended, so the launcher must exec into Claude Code; see [Run Claude Code behind a corporate launcher](../13-Enterprise-Admin/corporate-launcher.md) for the launcher contract. Requires Claude Code v2.1.210 or later.
- **Scope**: [`User or managed`](#scopes)
- **Type**: string, the launcher command as an argv prefix, such as an absolute path with optional arguments
- **Default**: unset, so background processes start unwrapped
- **Per-session overrides**: [`CLAUDE_CODE_PROCESS_WRAPPER`](env-vars.md) takes precedence over this key for one session
settings.json
```python
{
"processWrapper": "/opt/corp/launcher --profile claude"
}
```
Claude Code ignores the launcher on Windows and starts every process unwrapped. Requires Claude Code v2.1.210 or later.
[](#teammatemode)
`teammateMode`
Choose where Claude Code shows [agent team](../09-Agents-Patterns/agent-teams.md) teammates: inside your main terminal pane, or in split panes when your terminal supports them. See [Choose a display mode](../09-Agents-Patterns/agent-teams.md#choose-a-display-mode).
- **Scope**: [`Any file`](#scopes). Claude Code also reads a value left in `~/.claude.json` by older versions.
- **Type**: string, one of:
- `"in-process"`: teammates run inside your main terminal pane
- `"auto"`: split panes when you’re running inside tmux, or inside iTerm2 with `it2` on your `PATH` or tmux installed; in-process otherwise
- `"tmux"`: split panes using tmux or iTerm2, detected from your terminal
- `"iterm2"`: iTerm2 native split panes through the `it2` CLI
- **Default**: `"in-process"`
- **Per-session overrides**: `--teammate-mode` takes precedence over this key for one session
settings.json
```python
{
"teammateMode": "auto"
}
```
[](#worktree)
`worktree`
Configure how Claude Code creates and manages [git worktrees](worktrees.md) for `--worktree`, the `EnterWorktree` tool, and isolated subagents and background sessions.
- **Scope**: [`Any file`](#scopes)
- **Type**: object with `baseRef`, `symlinkDirectories`, `sparsePaths`, and `bgIsolation`
- **Default**: unset
This example branches new worktrees from your current `HEAD` and symlinks `node_modules` into each one:
settings.json
```python
{
"worktree": {
"baseRef": "head",
"symlinkDirectories": ["node_modules"]
}
}
```
To copy gitignored files like `.env` into new worktrees, add a [`.worktreeinclude` file](worktrees.md#copy-gitignored-files-into-worktrees) to your project root instead of a setting.
[](#worktree-baseref)
`worktree.baseRef`
Choose which ref new worktrees branch from. `"fresh"` 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.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"fresh"`: new worktrees branch from `origin/<default-branch>`
- `"head"`: new worktrees branch from your current local `HEAD`, including unpushed commits
- **Default**: `"fresh"`
settings.json
```python
{
"worktree": {
"baseRef": "head"
}
}
```
Inside a linked worktree, `"head"` resolves to that worktree’s `HEAD`, not the main checkout’s.
[](#worktree-symlinkdirectories)
`worktree.symlinkDirectories`
Symlink directories from the main repository into each worktree so you don’t duplicate large directories on disk.
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, directory paths relative to the repository root
- **Default**: unset, so Claude Code symlinks no directories
This example symlinks `node_modules` and `.cache` from the main repository into every new worktree:
settings.json
```python
{
"worktree": {
"symlinkDirectories": ["node_modules", ".cache"]
}
}
```
[](#worktree-sparsepaths)
`worktree.sparsePaths`
Check out only the listed directories in each worktree through git sparse-checkout. Claude Code writes only those directories plus root-level files to disk, which is faster in large monorepos; see [Check out only the directories you need](large-codebases.md#check-out-only-the-directories-you-need).
- **Scope**: [`Any file`](#scopes)
- **Type**: array of strings, directory paths relative to the repository root
- **Default**: unset, so each worktree checks out the whole tree
This example checks out only `packages/my-app` and `shared/utils`, plus root-level files, in each worktree:
settings.json
```python
{
"worktree": {
"sparsePaths": ["packages/my-app", "shared/utils"]
}
}
```
While a sparse worktree exists, git enables `extensions.worktreeConfig` in the repository’s shared `.git/config`.
[](#worktree-bgisolation)
`worktree.bgIsolation`
Choose how [background sessions](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated) isolate their file edits. With `"worktree"`, Claude Code blocks `Edit` and `Write` in the main checkout until the session calls `EnterWorktree`; with `"none"`, background jobs edit the working copy directly. Set `"none"` for a repository where git worktrees are impractical.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, one of:
- `"worktree"`: Claude Code blocks `Edit` and `Write` in the main checkout until the session calls `EnterWorktree`
- `"none"`: background jobs edit the working copy directly
- **Default**: `"worktree"`
settings.json
```python
{
"worktree": {
"bgIsolation": "none"
}
}
```
Outside a git repository, a [`WorktreeCreate` hook](worktrees.md#non-git-version-control) that fails releases the block so the session can edit the working directory in place; that release requires Claude Code v2.1.203 or later.
[](#remote-desktop-and-notifications)
Remote, desktop, and notifications
Configure Remote Control, cloud environments, the desktop app, and the notifications Claude Code sends when it needs you. See [Remote Control](remote-control.md).
[](#agentpushnotifenabled)
`agentPushNotifEnabled`
Allow Claude to send a push notification to your phone when it decides one is worth sending, for example when a long task finishes. Claude Code syncs this choice to your account, and pushes arrive while [Remote Control](remote-control.md) is connected. Appears in `/config` as **Push when Claude decides**.
- **Scope**: [`Any file`](#scopes). Claude Code also reads a value left in `~/.claude.json` by older versions.
- **Type**: Boolean
- `true`: Claude can send a push notification to your phone when it decides one is worth sending
- `false`: Claude doesn’t send those notifications
- **Default**: `false`
settings.json
```python
{
"agentPushNotifEnabled": true
}
```
See [Mobile push notifications](remote-control.md#mobile-push-notifications).
[](#awaysummaryenabled)
`awaySummaryEnabled`
Show a one-line session recap when you return to the terminal after a few minutes away. Set it to `false`, or turn off **Session recap** in `/config`, to stop the recap.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: you see a one-line session recap when you return after a few minutes away
- `false`: Claude Code shows no recap
- **Default**: unset, so the recap is on
- **Per-session overrides**: [`CLAUDE_CODE_ENABLE_AWAY_SUMMARY`](env-vars.md) takes precedence over this key for one session, in either direction
settings.json
```python
{
"awaySummaryEnabled": false
}
```
Claude Code never shows the recap in non-interactive mode.
[](#disableartifact)
`disableArtifact`
Deprecated, and replaced by [`enableArtifact`](#enableartifact). Claude Code still honors `disableArtifact: true` as equivalent to `enableArtifact: false`, and ignores `disableArtifact: false`.
Use [`enableArtifact`](#enableartifact) instead to turn off the [Artifact](artifacts.md) tool, which publishes session output as a private web page on claude.ai. When you turn the **Artifacts** row off in `/config`, Claude Code writes `enableArtifact` to your user settings and clears this key.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns the Artifact tool off for every session the file applies to, and no other file turns it back on. Before v2.1.242, a higher-precedence file could override a lower file’s `true` rather than the key acting as a lock
- `false`: ignored; to leave the tool on, remove the key
- **Default**: unset, so the tool follows your account’s [availability](artifacts.md#availability)
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_ARTIFACT`](env-vars.md) set to `1` turns the tool off for one session
settings.json
```python
{
"disableArtifact": true
}
```
[Disable artifacts](artifacts.md#disable-artifacts) lists every way to turn the tool off.
[](#disabledeeplinkregistration)
`disableDeepLinkRegistration`
Stop Claude Code from registering the `claude-cli://` protocol handler with the operating system, which it otherwise does after you send the first prompt of an interactive session. [Deep links](deep-links.md) let external tools open a Claude Code session with a pre-filled prompt. Set this in environments where protocol handler registration is restricted or managed separately.
- **Scope**: [`Any file`](#scopes)
- **Type**: the string `"disable"`
- **Default**: unset, so Claude Code registers the handler
settings.json
```python
{
"disableDeepLinkRegistration": "disable"
}
```
[](#disabledesktoplocalsessions)
`disableDesktopLocalSessions`
Turn off Code sessions that run on the device in the [desktop app](../16-Mobile-Desktop/desktop.md#local-sessions-on-managed-devices), for deployments where developers should work on remote machines over SSH. In the Code tab, the **Local** environment stays in the environment dropdown but is grayed out and can’t be selected, with a tooltip saying your organization turned it off; on Windows the WSL entry is grayed out the same way, though whether WSL sessions run on a managed device at all is [governed separately](../13-Enterprise-Admin/admin-setup.md#wsl-sessions-in-claude-code-desktop). New sessions default to the first [SSH connection](../16-Mobile-Desktop/desktop.md#ssh-sessions) if one is configured, and the app refuses to start or resume a session on the device, including an SSH connection back to the same machine. SSH sessions to other hosts and cloud sessions are unaffected. The desktop app reads this key; the terminal CLI ignores it. Requires Claude Desktop v1.37937.0 or later.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean; only the JSON Boolean `true` takes effect
- `true`: the desktop app offers no on-device Code sessions; existing local sessions stay listed but can’t continue
- `false`: local sessions stay available
- **Default**: unset, so local sessions are available
managed-settings.json
```python
{
"disableDesktopLocalSessions": true
}
```
The desktop app ignores any other value, and a value that isn’t a Boolean, such as the string `"true"` or `1`, also logs a warning. Pair it with [`sshConfigs`](#sshconfigs) so users land on a working connection, and with [`sshHostAllowlist`](#sshhostallowlist) to limit which hosts they can reach. See [Local sessions on managed devices](../16-Mobile-Desktop/desktop.md#local-sessions-on-managed-devices). Claude Desktop supplies Code sessions with policy derived from your desktop configuration, for example the egress allowlist, filesystem sandbox, and MCP restrictions in third-party deployments. Claude Code ignores those parent settings whenever an [admin source](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) is present: server-managed settings, an MDM or OS-level policy, or a managed settings file. Deploying this key through one of those on a device that had none before, as in third-party deployments, therefore stops the desktop-derived policies from applying. [Let an embedding host add policy](../13-Enterprise-Admin/managed-settings.md#let-an-embedding-host-add-policy) covers when parent settings can still merge; this holds for any key you deploy that way, not only this one.
[](#disableremotecontrol)
`disableRemoteControl`
Turn off [Remote Control](remote-control.md): Claude Code then refuses `claude remote-control`, the `--remote-control` flag, auto-start, and the in-session toggle, and reports that your organization’s policy disabled it. Place it in [managed settings](../13-Enterprise-Admin/managed-settings.md) for per-device MDM enforcement.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code refuses `claude remote-control`, the `--remote-control` flag, auto-start, and the in-session toggle
- `false`: Remote Control stays available
- **Default**: `false`
settings.json
```python
{
"disableRemoteControl": true
}
```
[](#enableartifact)
`enableArtifact`
Turn off the [Artifact](artifacts.md) tool, which publishes session output as a private web page on claude.ai. When you turn the **Artifacts** row off in `/config`, Claude Code writes this key to your user settings, so you don’t usually edit it by hand. Requires Claude Code v2.1.196 or later.
- **Scope**: [`Any file`](#scopes). Every file can turn the tool off, and none can turn it back on.
- **Type**: Boolean
- `false`: Claude Code turns the Artifact tool off for every session the file applies to
- `true`: the same as leaving the key unset, because it never overrides a `false` from another file, from [`CLAUDE_CODE_DISABLE_ARTIFACT`](env-vars.md), or from your organization’s [admin setting](artifacts.md#manage-artifacts-for-your-organization)
- **Default**: unset, so the tool follows your account’s [availability](artifacts.md#availability)
settings.json
```python
{
"enableArtifact": false
}
```
While a source other than your own user settings keeps the tool turned off, Claude Code hides the **Artifacts** row in `/config`, because turning it on there wouldn’t change anything. [Disable artifacts](artifacts.md#disable-artifacts) lists every way to turn the tool off. Before v2.1.242, Claude Code ignored this key in project and local settings, and a file higher in the [precedence stack](settings.md#settings-precedence) could turn the tool back on over a lower file’s off.
[](#inputneedednotifenabled)
`inputNeededNotifEnabled`
Get a push notification on your phone when a permission prompt or question is waiting for your input. Claude Code sends these only while [Remote Control](remote-control.md) is connected. Appears in `/config` as **Push when actions required**.
- **Scope**: [`Any file`](#scopes). Claude Code also reads a value left in `~/.claude.json` by older versions.
- **Type**: Boolean
- `true`: you get a push notification on your phone when a permission prompt or question is waiting, while Remote Control is connected
- `false`: Claude Code sends no such notifications
- **Default**: `false`
settings.json
```python
{
"inputNeededNotifEnabled": true
}
```
See [Mobile push notifications](remote-control.md#mobile-push-notifications).
[](#preferrednotifchannel)
`preferredNotifChannel`
Choose how Claude Code notifies you when a task completes or a permission prompt is waiting. Appears in `/config` as **Local notifications**.
- **Scope**: [`Any file`](#scopes). Claude Code also reads a value left in `~/.claude.json` by older versions.
- **Type**: string, one of:
- `"auto"`: Claude Code sends a desktop notification in iTerm2, Ghostty, and Kitty, rings the bell in Terminal.app only when its audible bell is off, and does nothing elsewhere
- `"terminal_bell"`: Claude Code rings the bell character in any terminal
- `"iterm2"`: Claude Code sends an iTerm2 desktop notification
- `"iterm2_with_bell"`: Claude Code sends an iTerm2 desktop notification and rings the bell
- `"kitty"`: Claude Code sends a Kitty desktop notification
- `"ghostty"`: Claude Code sends a Ghostty desktop notification
- `"notifications_disabled"`: Claude Code sends no notification
- **Default**: `"auto"`
settings.json
```python
{
"preferredNotifChannel": "terminal_bell"
}
```
With `"auto"`, Claude Code sends a desktop notification in iTerm2, Ghostty, and Kitty. In Terminal.app it rings the bell character only when you have turned Terminal’s audible bell off, and in other terminals it does nothing. Set `"terminal_bell"` to ring the bell character in any terminal. See [Get a terminal bell or notification](terminal-config.md#get-a-terminal-bell-or-notification).
[](#remote-defaultenvironmentid)
`remote.defaultEnvironmentId`
Pick the default [cloud environment](cloud-environments.md) for cloud sessions you create from the CLI, such as with `claude --cloud`. Claude Code writes this key to your user settings when you pick an environment with [`/remote-env`](cloud-environments.md#select-an-environment-from-the-cli).
- **Scope**: [`Any file`](#scopes). For a self-hosted environment ID, user or managed settings, or the `--settings` flag only.
- **Type**: string, an environment ID such as `env_...` or `ccpool_...`
- **Default**: unset, so Claude Code uses the Anthropic-hosted environment when your list has one, and otherwise the first environment in your list that isn’t a [Remote Control bridge environment](cloud-environments.md#the-default-environment), or the first environment when every one is a bridge environment
- **Per-session overrides**: `--environment` takes precedence over this key for the one cloud session it creates
settings.json
```python
{
"remote": {
"defaultEnvironmentId": "env_0123abcd"
}
}
```
An Anthropic-hosted environment ID, which starts with `env_`, follows the standard settings precedence, so a value in a repository’s project settings overrides your user-level pick. A [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) ID, which starts with `ccpool_`, is honored only from user settings, managed settings, and the `--settings` flag; Claude Code ignores one in a repository’s project or local settings, and `/remote-env` shows which value it ignored, so a checked-in file can’t steer sessions onto a self-hosted environment you didn’t choose.
[](#remotecontrolatstartup)
`remoteControlAtStartup`
Connect [Remote Control](remote-control.md) automatically when each interactive session starts, instead of waiting for `/remote-control`. Set it to `true` to turn auto-connect on, `false` to turn it off. Appears in `/config` as **Enable Remote Control for all sessions**.
- **Scope**: [`Any file`](#scopes). Claude Code also reads a value left in `~/.claude.json` by older versions.
- **Type**: Boolean
- `true`: Claude Code connects Remote Control automatically when each interactive session starts
- `false`: Claude Code waits for `/remote-control`
- **Default**: unset, so the [auto-connect default](remote-control.md#enable-remote-control-for-all-sessions) applies
- **Per-session overrides**: `--remote-control` turns Remote Control on for one session even when this key is `false`, and no flag turns it off for one session
settings.json
```python
{
"remoteControlAtStartup": true
}
```
Claude Code ignores a `true` from project or local settings, so a repository can turn auto-connect off for its checkout but can’t turn it on. For the full per-scope behavior, see [Enable Remote Control for all sessions](remote-control.md#enable-remote-control-for-all-sessions) and the [security keys where the stricter value applies](settings.md#security-keys-where-the-stricter-value-applies).
[](#sshconfigs)
`sshConfigs`
Add SSH connections to the [Desktop](../16-Mobile-Desktop/desktop.md#pre-configure-ssh-connections-for-your-team) environment dropdown. Administrators use it to distribute shared connections to a team. Connections you define in managed settings show as managed, so users can select them but can’t edit or delete them in the app.
- **Scope**: [`User or managed`](#scopes). The desktop app reads this key.
- **Type**: array of objects, each with required `id`, `name`, and `sshHost` and optional `sshPort` and `sshIdentityFile`
- **Default**: unset
This example adds one connection named `Dev VM` that connects to `user@dev.example.com`:
settings.json
```python
{
"sshConfigs": [
{
"id": "dev-vm",
"name": "Dev VM",
"sshHost": "user@dev.example.com"
}
]
}
```
[](#sshhostallowlist)
`sshHostAllowlist`
Limit the hosts a [Desktop SSH session](../16-Mobile-Desktop/desktop.md#restrict-which-ssh-hosts-users-can-connect-to) can connect to. Only the Desktop app reads this key; the CLI doesn’t. Patterns are case-insensitive: `*` matches any host, `*.example.com` matches `example.com` and every subdomain, and anything else is an exact match against the hostname after `~/.ssh/config` resolution. An empty array turns SSH sessions off.
- **Scope**: [`Managed`](#scopes)
- **Type**: array of hostname patterns
- **Default**: unset, so any host is allowed
This example allows `devboxes.example.com` and its subdomains, plus the exact host `bastion.example.com`:
managed-settings.json
```python
{
"sshHostAllowlist": ["*.devboxes.example.com", "bastion.example.com"]
}
```
[](#authentication-and-providers)
Authentication and providers
Supply credentials through helper scripts and, for organizations, force a login method or organization. See [Authentication](../13-Enterprise-Admin/iam.md).
[](#apikeyhelper)
`apiKeyHelper`
Run your own command to produce the credential Claude Code sends with model requests. Claude Code runs the command through the system shell, `/bin/sh` on macOS and Linux and `cmd` on Windows, and sends its output as both the `X-Api-Key` and `Authorization: Bearer` headers. Use it for dynamic or rotating credentials, such as short-lived tokens fetched from a vault.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a shell command line
- **Default**: unset, so Claude Code doesn’t run a helper
settings.json
```python
{
"apiKeyHelper": "/bin/generate_temp_api_key.sh"
}
```
Claude Code caches the value and reruns the command in these cases:
- After the cache lifetime, five minutes by default or the interval you set with [`CLAUDE_CODE_API_KEY_HELPER_TTL_MS`](env-vars.md).
- When a request to the Anthropic API, directly or through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md), fails with `401` or `403`.
- Before sending a request to the Anthropic API, directly or through an LLM gateway, when the cached output is a JWT that expired after the helper produced it. Requires Claude Code v2.1.246 or later.
The last two cases apply only when the helper’s output is the credential Claude Code sends and `ANTHROPIC_AUTH_TOKEN` isn’t set. In interactive sessions, when the command comes from project or local settings, Claude Code doesn’t run it until you accept the workspace trust prompt. See [Credential management](../13-Enterprise-Admin/iam.md#credential-management).
[](#awsauthrefresh)
`awsAuthRefresh`
Run your own command, such as `aws sso login`, to refresh the credentials in your `.aws` directory when the ones Claude Code has for [Amazon Bedrock](amazon-bedrock.md) stop working. Claude Code checks the current credentials against STS first and runs the command only when that check fails, then reads the refreshed `.aws` directory.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a shell command line
- **Default**: unset, so Claude Code doesn’t refresh AWS credentials for you
settings.json
```python
{
"awsAuthRefresh": "aws sso login --profile myprofile"
}
```
Use this key when your refresh flow writes to `.aws`; use [`awsCredentialExport`](#awscredentialexport) when it prints credentials instead. See [advanced credential configuration](amazon-bedrock.md#advanced-credential-configuration).
[](#awscredentialexport)
`awsCredentialExport`
Run your own command that prints AWS credentials as JSON, so Claude Code can call [Amazon Bedrock](amazon-bedrock.md) with credentials that don’t live in your `.aws` directory. Claude Code accepts the `aws sts` output shape and the flat `aws configure export-credentials` shape, and scopes the credentials to its own Bedrock client, so the shell commands Claude runs still see your ambient credentials.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a shell command line
- **Default**: unset, so Claude Code uses the ambient AWS credential chain
settings.json
```python
{
"awsCredentialExport": "/bin/generate_aws_grant.sh"
}
```
Unlike [`awsAuthRefresh`](#awsauthrefresh), Claude Code always runs this command when it’s set, without checking the ambient credentials first. See [advanced credential configuration](amazon-bedrock.md#advanced-credential-configuration).
[](#forceloginmethod)
`forceLoginMethod`
Restrict which kind of account people can log in with. Set `"claudeai"` to allow only claude.ai accounts, `"console"` to allow only Claude Console accounts, or `"gateway"` to send people to a [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md) instead of a first-party login. Administrators set it in managed settings and pair it with [`forceLoginOrgUUID`](#forceloginorguuid) to keep developers’ claude.ai logins inside one organization. If you set it to `"claudeai"` or `"console"` in any settings file, Claude Code also stops offering the [keyless Console sign-in](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key) in the sessions that file applies to.
- **Scope**: [`Any file`](#scopes). Claude Code honors `"gateway"` only from a managed source on the machine: `managed-settings.json`, the macOS plist or Windows HKLM registry, or a policy helper. It treats `"gateway"` as unset in user, project, local, HKCU, and server-managed settings, the same rule as [`forceLoginGatewayUrl`](#forcelogingatewayurl).
- **Type**: string, one of:
- `"claudeai"`: only claude.ai accounts can log in
- `"console"`: only Claude Console accounts can log in
- `"gateway"`: Claude Code sends people to a cloud gateway instead of a first-party login
- **Default**: unset, so people pick a login method
settings.json
```python
{
"forceLoginMethod": "claudeai"
}
```
Every first-party login path applies the restriction, including the [VS Code extension](../03-IDE-Integrations/vs-code.md), the Agent SDK, `claude setup-token`, and `/install-github-app`, except the terminal’s interactive login screen, reached by `/login` or first-run onboarding, which pre-selects the method without enforcing it. Before v2.1.212, only terminal logins applied it. See [Restrict login to your organization](../13-Enterprise-Admin/iam.md#restrict-login-to-your-organization) for how each login path, environment credentials, and third-party providers are handled. When a managed source on the machine sets `"gateway"`, Claude Code doesn’t use a leftover login, API key, or `apiKeyHelper` credential. See [Administrator policy requires a Cloud gateway sign-in](errors.md#administrator-policy-requires-a-cloud-gateway-sign-in) for the message each one produces. If you select a cloud provider through `CLAUDE_CODE_USE_BEDROCK` or a similar environment variable, the session doesn’t need the gateway sign-in. Before v2.1.261, Claude Code used a leftover login on these machines.
[](#forcelogingatewayurl)
`forceLoginGatewayUrl`
Set the gateway URL the `/login` Cloud gateway screen connects to, so people reach your [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md) without typing its address. The screen has no URL field: with this key set, it shows your gateway URL and connects when the person presses Enter; without it, it tells them to contact their IT administrator. Either this key or `forceLoginMethod: "gateway"` makes the machine gateway-only, except for sessions that select a cloud provider with `CLAUDE_CODE_USE_*`. `/login` then opens on the Cloud gateway screen with no login-method picker. See [Administrator policy requires a Cloud gateway sign-in](errors.md#administrator-policy-requires-a-cloud-gateway-sign-in) for what happens to a leftover first-party login or API key. Set both keys so the screen connects instead of showing an error.
- **Scope**: [`Managed`](#scopes). Read only from a source on the machine: `managed-settings.json`, the macOS plist or Windows HKLM registry, or a policy helper. Claude Code ignores it in HKCU and server-managed settings.
- **Type**: string, a full URL including the scheme
- **Default**: unset, so the Cloud gateway screen shows an error telling people to contact their IT administrator
managed-settings.json
```python
{
"forceLoginGatewayUrl": "https://claude-gateway.example.com"
}
```
If the value isn’t a valid URL, the sign-in screen reports it, and the rest of the managed settings file still applies. See [Set the gateway URL](../13-Enterprise-Admin/claude-apps-gateway.md#set-the-gateway-url).
[](#forceloginorguuid)
`forceLoginOrgUUID`
From a managed source, require claude.ai account logins to belong to one Anthropic organization, given as a single UUID, or to any of several organizations, given as an array. From any settings file, Claude Code also uses a single UUID to pre-select that organization during a claude.ai or Claude Console login, and pre-selects nothing for an array. If you set the key in any settings file, Claude Code also stops offering the [keyless Console sign-in](../13-Enterprise-Admin/iam.md#sign-in-without-an-api-key) in the sessions that file applies to and creates an API key instead.
- **Scope**: [`Any file`](#scopes). Only a managed source enforces the restriction; a single UUID in any other settings file pre-selects the organization during login without restricting it.
- **Type**: string, one UUID, or array of strings, several UUIDs
- **Default**: unset, so any organization can log in
This example accepts logins from either of two organizations without pre-selecting one:
managed-settings.json
```python
{
"forceLoginOrgUUID": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]
}
```
If a managed source sets an empty array, or a value Claude Code can’t parse, Claude Code blocks every login with a misconfiguration message. See [Restrict login to your organization](../13-Enterprise-Admin/iam.md#restrict-login-to-your-organization) for how Claude Code treats Claude Console logins, the other login paths, and environment credentials.
[](#gatewayinternalnetworks)
`gatewayInternalNetworks`
Declare the public IPv4 blocks that your organization numbers its internal network from, so `/login` accepts a [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md) there. Requires Claude Code v2.1.268 or later. Without this key, `/login` connects to any gateway on a private address and nothing else. With it, `/login` also accepts a gateway inside a listed block, over a direct connection only. The machine’s own address on that connection must also be inside the same block.
- **Scope**: [`Managed`](#scopes). Read only from a source on the machine: `managed-settings.json`, the macOS plist or Windows HKLM registry, or a policy helper. Claude Code ignores it in HKCU and server-managed settings.
- **Type**: array of strings, at most four IPv4 CIDR blocks, each `/8` to `/32`, not overlapping one another, and none overlapping private space.
- **Default**: unset, so `/login` accepts only gateways on private addresses
managed-settings.json
```python
{
"gatewayInternalNetworks": ["203.0.113.0/24"]
}
```
Replace the documentation range in the example with your own block. Claude Code refuses the documentation ranges, the ranges that VPN and NAT64 clients use locally, and reserved space that no network is numbered from, such as multicast. If an entry is invalid, or the value isn’t a list of strings, `/login` names the problem and refuses every new gateway sign-in on the machine until you fix the value. Existing sign-ins keep working. See [Allow a gateway on public address space you own](../13-Enterprise-Admin/claude-apps-gateway.md#allow-a-gateway-on-public-address-space-you-own) for the full rules and what developers see.
[](#gcpauthrefresh)
`gcpAuthRefresh`
Run your own command to refresh Google Cloud Application Default Credentials when Claude Code finds they’ve expired or can’t be loaded, so [Google Cloud’s Agent Platform](google-vertex-ai.md) requests keep working without you re-authenticating by hand.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, a shell command line
- **Default**: unset, so Claude Code’s credential error tells you to run `gcloud auth application-default login` yourself
settings.json
```python
{
"gcpAuthRefresh": "gcloud auth application-default login"
}
```
See [advanced credential configuration](google-vertex-ai.md#advanced-credential-configuration).
[](#otelheadershelper)
`otelHeadersHelper`
Run your own command to generate the headers Claude Code sends with OpenTelemetry exports, for backends whose tokens rotate. Claude Code runs it at startup and periodically after that, and expects a JSON object of string header values on stdout.
- **Scope**: [`Any file`](#scopes)
- **Type**: string, an executable path or a shell command line
- **Default**: unset, so Claude Code adds no helper-generated headers
settings.json
```python
{
"otelHeadersHelper": "/bin/generate_otel_headers.sh"
}
```
Set the refresh interval with [`CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS`](env-vars.md). See [Dynamic headers](../13-Enterprise-Admin/monitoring-usage.md#dynamic-headers) for the script requirements and what happens when the helper fails.
[](#updates-and-versioning)
Updates and versioning
Choose an update channel and, for organizations, pin the versions people can run. See [Update Claude Code](../01-Getting-Started/setup.md#update-claude-code).
[](#autoupdateschannel)
`autoUpdatesChannel`
Choose which [release channel](../01-Getting-Started/setup.md#configure-release-channel) background auto-updates and `claude update` follow. Set `"stable"` for a version that is typically about one week old and skips releases with major regressions, or `"latest"` for the most recent release.
- **Scope**: [`Any file`](#scopes). Set it in managed settings to enforce one channel across your organization.
- **Type**: string, one of:
- `"latest"`: updates follow the most recent release
- `"stable"`: updates follow a version that is typically about one week old and skips releases with major regressions
- **Default**: unset, so Claude Code follows `"latest"`
settings.json
```python
{
"autoUpdatesChannel": "stable"
}
```
Claude Code writes `"stable"` to your user settings when you pick it under **Auto-update channel** in `/config`, and removes the key when you switch back to latest there. `claude install stable` and `claude install latest` also save the channel you name. Switching from `"latest"` to `"stable"` in `/config` asks whether to allow a downgrade or stay on your current version; staying sets [`minimumVersion`](#minimumversion). Homebrew installs ignore this key: the `claude-code` cask tracks stable and `claude-code@latest` tracks latest, and `claude update` defers to `brew upgrade`. To turn auto-updates off entirely, set [`DISABLE_AUTOUPDATER`](../01-Getting-Started/setup.md#disable-auto-updates) in `env`.
[](#minimumversion)
`minimumVersion`
Keep background auto-updates and `claude update` from installing any version below this one, so moving to the `"stable"` channel doesn’t downgrade you from a newer `"latest"` build. Claude Code writes this key for you when you choose to stay on your current version while switching channels in `/config`, and clears it when you switch back to `"latest"`.
- **Scope**: [`Any file`](#scopes). Set it in managed settings to pin an organization-wide minimum that user and project settings can’t lower.
- **Type**: string, a version number such as `"2.1.100"`; a value that isn’t a valid version is ignored
- **Default**: unset, so updates can install any version the channel offers
This example follows the stable channel and refuses to install any version below 2.1.100:
settings.json
```python
{
"autoUpdatesChannel": "stable",
"minimumVersion": "2.1.100"
}
```
This key only constrains updates. To make Claude Code refuse to start below a version, use [`requiredMinimumVersion`](#requiredminimumversion) instead. See [Pin a minimum version](../01-Getting-Started/setup.md#pin-a-minimum-version).
[](#requiredmaximumversion)
`requiredMaximumVersion`
Set the newest Claude Code version your organization allows to start. When the running version is newer, Claude Code exits at startup and tells the user to install an approved version through your organization’s approved method; `claude install <version>` may also work. Requires Claude Code v2.1.163 or later.
- **Scope**: [`Managed`](#scopes). Claude Code gives no warning when it ignores the key elsewhere.
- **Type**: string, a version number such as `"2.1.150"`; a value that isn’t a valid version is ignored
- **Default**: unset, so no ceiling applies
managed-settings.json
```python
{
"requiredMaximumVersion": "2.1.150"
}
```
Background auto-updates and `claude update` skip versions above the ceiling, so an installation inside the range stays inside it. `claude update`, `claude install`, and `claude doctor` keep working above the ceiling so users can recover. Pair it with [`requiredMinimumVersion`](#requiredminimumversion) to enforce a range.
[](#requiredminimumversion)
`requiredMinimumVersion`
Set the oldest Claude Code version your organization allows to start. When the running version is older, Claude Code exits at startup and tells the user to update through your organization’s approved method. The check runs at startup only, so a session that’s already running continues. Requires Claude Code v2.1.163 or later.
- **Scope**: [`Managed`](#scopes). Claude Code gives no warning when it ignores the key elsewhere.
- **Type**: string, a version number such as `"2.1.150"`; a value that isn’t a valid version is ignored
- **Default**: unset, so no floor applies
managed-settings.json
```python
{
"requiredMinimumVersion": "2.1.150"
}
```
`claude update`, `claude install`, and `claude doctor` keep working below the floor so users can recover. Unlike [`minimumVersion`](#minimumversion), which only prevents downgrades, this key blocks startup. Pair it with [`requiredMaximumVersion`](#requiredmaximumversion) to enforce a range.
[](#tools)
Tools
Turn off specific tools in the [Claude Code desktop app](../16-Mobile-Desktop/desktop.md). The terminal CLI ignores these keys. For the tools themselves, see [Tools available to Claude](tools-reference.md).
[](#browserexternalpagetools)
`browserExternalPageTools`
Stop Claude from using its tools to read or act on external pages in the desktop app’s [Browser pane](../16-Mobile-Desktop/desktop.md#browse-external-sites). People in your organization can still open external sites themselves, and local dev server previews keep working with Claude’s tools. The desktop app reads this key; the terminal CLI ignores it.
- **Scope**: [`Managed`](#scopes)
- **Type**: string, `"disabled"`; the desktop app also accepts `"disable"`, in either case
- **Default**: unset, so Claude’s tools work on external pages
managed-settings.json
```python
{
"browserExternalPageTools": "disabled"
}
```
Any other value leaves Claude’s tools on, and a non-empty string that isn’t one of the two accepted values logs a warning. To block external sites for people and Claude alike, set [`disableBrowserExternalNavigation`](#disablebrowserexternalnavigation) instead. See [Restrict external browsing for your organization](../16-Mobile-Desktop/desktop.md#restrict-external-browsing-for-your-organization).
[](#disablebrowserexternalnavigation)
`disableBrowserExternalNavigation`
Turn off external browsing in the desktop app’s [Browser pane](../16-Mobile-Desktop/desktop.md#browse-external-sites) for people and Claude alike. Localhost dev server previews keep working. The desktop app reads this key; the terminal CLI ignores it.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean; only the JSON Boolean `true` takes effect
- `true`: the desktop app turns off external browsing in the Browser pane for people and Claude alike; localhost previews keep working
- `false`: external browsing stays on
- **Default**: unset, so external browsing is on
managed-settings.json
```python
{
"disableBrowserExternalNavigation": true
}
```
The desktop app ignores any other value, and a value that isn’t a Boolean, such as the string `"true"` or `1`, also logs a warning. To leave external browsing on but keep Claude’s tools off external pages, set [`browserExternalPageTools`](#browserexternalpagetools) instead. See [Restrict external browsing for your organization](../16-Mobile-Desktop/desktop.md#restrict-external-browsing-for-your-organization).
[](#disablemobilesimulatortools)
`disableMobileSimulatorTools`
Block Claude’s tools for the desktop app’s [iOS Simulator pane](../16-Mobile-Desktop/desktop-ios-simulator.md#turn-off-simulator-access). People keep manual use of the pane; only Claude’s access is removed, and nobody can turn it back on from inside the app. The desktop app reads this key; the terminal CLI ignores it.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean; only the JSON Boolean `true` takes effect
- `true`: the desktop app blocks Claude’s tools for the iOS Simulator pane
- `false`: Claude’s simulator tools follow each person’s settings toggle in the desktop app
- **Default**: unset, so Claude’s simulator tools follow each person’s settings toggle in the desktop app
managed-settings.json
```python
{
"disableMobileSimulatorTools": true
}
```
The desktop app ignores any other value, and a value that isn’t a Boolean, such as the string `"true"` or `1`, also logs a warning.
[](#privacy-and-telemetry)
Privacy and telemetry
Control how long Claude Code keeps session data and what it sends. The switches that turn off usage metrics and error reports are environment variables, not settings keys: set `DISABLE_TELEMETRY`, `DISABLE_ERROR_REPORTING`, or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` in the [`env`](#env) key or in the shell. [Telemetry services](../13-Enterprise-Admin/data-usage.md#telemetry-services) says what each one stops. Two exceptions turn off from a settings file: [`feedbackDrafts`](#feedbackdrafts) below for Claude-drafted feedback, and [`feedbackSurveyRate`](#feedbacksurveyrate) below for the session survey.
[](#cleanupperioddays)
`cleanupPeriodDays`
Set how many days Claude Code keeps [session transcripts and other application data](claude-directory.md#cleaned-up-automatically) before deleting them. Claude Code runs the deletion as a background sweep after a session starts, as long as it can safely determine the retention period. The sweep deletes transcripts without showing a message, so a session you haven’t used for longer than the retention period no longer appears in the [`/resume`](sessions.md#resume-a-session) picker.
- **Scope**: [`Any file`](#scopes)
- **Type**: number of days, a whole number, minimum `1`
- **Default**: `30`
settings.json
```python
{
"cleanupPeriodDays": 20
}
```
Setting `0` fails validation, so pick a large value such as `3650` for long retention. To stop Claude Code from writing transcripts at all, see [Plaintext storage](claude-directory.md#plaintext-storage).
[](#desktopsessioncleanupperioddays)
`desktopSessionCleanupPeriodDays`
Set an age limit in days for the transcripts of sessions you started or most recently continued in Claude Desktop or Cowork. Without this key, Claude Code [keeps those transcripts at any age](claude-directory.md#cleaned-up-automatically). Claude Code deletes each one once it’s older than both this limit and [`cleanupPeriodDays`](#cleanupperioddays), so with `cleanupPeriodDays` at its default of 30, a value of `7` still keeps them 30 days. When managed settings set `cleanupPeriodDays`, that period applies instead and this key is ignored. Requires Claude Code v2.1.248 or later.
- **Scope**: [`User or managed`](#scopes). Claude Code also reads the key from a file you pass with `--settings`, and ignores it in project and local settings.
- **Type**: number of days, a whole number, minimum `0`
- **Default**: `0`, which sets no age limit
settings.json
```python
{
"desktopSessionCleanupPeriodDays": 90
}
```
[](#feedbackdrafts)
`feedbackDrafts`
Control [Claude-drafted feedback](tools-reference.md#sendfeedback-tool-behavior): whether Claude can queue feedback drafts for you to review, and whether Claude Code shows a card when Claude queues one.
- **Scope**: [`User or managed`](#scopes)
- **Type**: string, one of `"notify"`, `"quiet"`, or `"off"`
- `"notify"`: Claude Code shows a card above the prompt when Claude queues a draft, up to [three cards in a session](tools-reference.md#what-you-see-when-claude-drafts) by default
- `"quiet"`: Claude drafts without a card. You see the count of queued drafts in the prompt footer and review them in `/feedback`
- `"off"`: Claude Code removes the SendFeedback tool, so Claude can’t queue drafts
- **Default**: `"notify"`
- **Per-session overrides**: [`CLAUDE_CODE_SEND_FEEDBACK`](env-vars.md) set to `0` turns the feature off for one session
settings.json
```python
{
"feedbackDrafts": "quiet"
}
```
Appears in `/config` as **Claude-drafted feedback**, which writes this key to your user settings. You see the `/config` row only in sessions [where Claude can draft feedback](tools-reference.md#sessions-without-claude-drafted-feedback); setting `"off"` doesn’t hide it, so you can turn the feature back on from the same row. A value in managed settings takes precedence over your user setting, so when an administrator sets this key, the row shows the managed value and changing it has no effect. Claude Code ignores this key in project and local settings.
[](#feedbacksurveyrate)
`feedbackSurveyRate`
Set the probability that the [session quality survey](../13-Enterprise-Admin/data-usage.md#session-quality-surveys) appears when a session is eligible for it. Set `0` to keep the survey from appearing.
- **Scope**: [`Any file`](#scopes)
- **Type**: number between `0` and `1`
- **Default**: unset, so Claude Code uses the rate Anthropic sets remotely, or its built-in rate of `0.005` on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, which don’t receive remote configuration
- **Per-session overrides**: [`CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY`](env-vars.md) set to `1` turns the survey off for one session whatever rate this key sets
settings.json
```python
{
"feedbackSurveyRate": 0.05
}
```
The same rate applies to the survey in the VS Code extension.
[](#skipwebfetchpreflight)
`skipWebFetchPreflight`
Skip the [WebFetch domain safety check](../13-Enterprise-Admin/data-usage.md#webfetch-domain-safety-check), which sends each requested hostname to `api.anthropic.com` before fetching. Set `true` in environments that block traffic to Anthropic, such as Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry deployments with restrictive egress.
- **Scope**: [`Any file`](#scopes)
- **Type**: Boolean
- `true`: Claude Code skips the WebFetch domain safety check
- `false`: the check runs before the first fetch to each hostname in a session, and again for a hostname whose earlier check was blocked or failed
- **Default**: unset, so the check runs before the first fetch to each hostname in a session
settings.json
```python
{
"skipWebFetchPreflight": true
}
```
With the check skipped, WebFetch attempts any URL without consulting the blocklist, so pair it with [`WebFetch` permission rules](permissions.md#webfetch) if you need to restrict which domains Claude can reach.
[](#enterprise-and-managed-settings)
Enterprise and managed settings
Keys an organization uses to compute, refresh, and combine managed settings. See [Set up managed settings](../13-Enterprise-Admin/admin-setup.md).
[](#disablesideloadflags)
`disableSideloadFlags`
Reject the `--plugin-dir`, `--plugin-url`, `--agents`, and `--mcp-config` CLI flags at startup, which users could otherwise pass to bypass [`strictKnownMarketplaces`](#strictknownmarketplaces) for a single run. Claude Code exits with an error naming the rejected flags, and applies the same check to surfaces that start the CLI with these flags internally, currently [Cowork](../16-Mobile-Desktop/desktop.md) local sessions in the desktop app. In [cloud sessions](claude-code-on-the-web.md), Claude Code instead starts the session and drops every server-delivered `--mcp-config` entry except in-process `type: "sdk"` entries and a [Claude Tag](claude-tag.md) session’s Slack tools. Requires Claude Code v2.1.193 or later.
- **Scope**: [`Managed`](#scopes)
- **Type**: Boolean
- `true`: Claude Code rejects `--plugin-dir`, `--plugin-url`, `--agents`, and `--mcp-config` at startup and exits with an error naming them. In cloud sessions, it instead starts the session and drops every server-delivered `--mcp-config` entry except in-process `type: "sdk"` entries and a Claude Tag session’s Slack tools
- `false`: Claude Code accepts those flags
- **Default**: `false`
managed-settings.json
```python
{
"disableSideloadFlags": true
}
```
Claude Code still accepts a `--mcp-config` whose servers are all in-process `type: "sdk"` entries, so the Agent SDK and VS Code extension keep working. Users can still add servers with `claude mcp add` or a `.mcp.json` file; for per-server control, set [`allowedMcpServers`](../06-MCP-Tools/General/managed-mcp.md) as well. Requires Claude Code v2.1.193 or later. The same check covers plugin folders named in the [`CLAUDE_CODE_PLUGIN_DIRS`](env-vars.md#variables) environment variable, which requires Claude Code v2.1.280 or later. When the variable names a folder, Claude Code exits with the same error, and the error says to unset the variable. In cloud sessions, Claude Code also ignores server-delivered mid-session MCP updates, the path behind cloud session configuration and SDK `setMcpServers()` calls that reach those sessions. In-process `type: "sdk"` entries and a Claude Tag session’s Slack tools stay exempt there too. Before v2.1.268, both this drop and the startup drop also removed a Claude Tag session’s Slack tools. Before v2.1.239, a server-delivered `--mcp-config` blocked a cloud session from starting.
[](#forceremotesettingsrefresh)
`forceRemoteSettingsRefresh`
Block CLI startup until Claude Code has freshly fetched [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md). If the fetch fails, Claude Code exits instead of continuing with cached or no settings. Set it when your environment can’t accept even a brief window in which a session runs without its managed policy. When the key is unset, Claude Code doesn’t block startup on the fetch, though when the developer signs in at startup it waits up to five seconds for the fetch. A Cloud gateway session always waits, and exits if the gateway can’t be reached.
- **Scope**: [`Managed`](#scopes). Claude Code honors a `true` from any admin-controlled managed source, even one that isn’t the highest-priority source.
- **Type**: Boolean
- `true`: Claude Code blocks startup until it has freshly fetched server-managed settings, and exits if the fetch fails
- `false`: Claude Code doesn’t block startup on the fetch, though at a sign-in startup it waits up to five seconds for the fetch
- **Default**: `false`
managed-settings.json
```python
{
"forceRemoteSettingsRefresh": true
}
```
Set it in an MDM profile or the managed settings file to enforce fail-closed startup before the first server payload arrives. Claude Code applies the check only in sessions that fetch server-managed settings, so a session that [doesn’t fetch them](../13-Enterprise-Admin/server-managed-settings.md#platform-availability) starts without waiting. The `claude auth` subcommands are exempt, so users can re-authenticate when expired credentials are why the fetch fails. See [Enforce fail-closed startup](../13-Enterprise-Admin/server-managed-settings.md#enforce-fail-closed-startup).
[](#managedsourcesbehavior)
`managedSourcesBehavior`
Choose whether Claude Code applies only the highest-priority [managed source](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) your organization delivers, or combines every admin source it delivers. By default Claude Code takes the highest-priority source that carries a [policy key](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) and ignores the rest. A policy key is any settings key other than this one and `wslInheritsWindowsSettings`. Under that default, once server-managed settings or an MDM policy deliver a policy key, a `managed-settings.json` file contributes only the [keys Claude Code reads from every admin source](../13-Enterprise-Admin/managed-settings.md#keys-read-from-every-admin-source). With `"merge"`, every admin source you deliver contributes its keys to one combined policy. Requires Claude Code v2.1.242 or later. Set `"merge"` only where every source [ranked](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) below your highest one is under an administrator’s control, because Claude Code then adds entries from a lower source, such as `permissions.allow` rules, to the policy.
- **Scope**: [`Managed`](#scopes). Claude Code reads this key from the highest-priority source that carries either this key or a policy key, and ignores this key in every source ranked lower, so a lower source can’t opt itself into combining with the source above it. Neither the Windows HKCU registry nor [parent settings from an embedding host](../13-Enterprise-Admin/managed-settings.md#let-an-embedding-host-add-policy) take part in the merge.
- **Type**: string, one of:
- `"first-wins"`: the highest-priority source that carries a policy key supplies the policy, and lower sources contribute only the [keys Claude Code reads from every admin source](../13-Enterprise-Admin/managed-settings.md#keys-read-from-every-admin-source)
- `"merge"`: every admin source you deliver contributes its keys, combined by the rules below
- **Default**: `"first-wins"`
Deliver the key in the highest-priority source you deploy. A machine that never receives server-managed settings needs the key in its MDM profile too, because Claude Code reads the key from the highest-priority source that carries it or a policy key. A `managed-settings.json` file is the lowest-ranked admin source, so `"merge"` set there has no source below it to combine with. In server-managed settings, the key looks like this:
```python
{
"managedSourcesBehavior": "merge"
}
```
Under `"merge"`, Claude Code combines each key by its kind. This table gives the rule for each kind. The restriction allowlist, values-taken-whole, and highest-source-only rows name every key they cover, and the other rows give examples:
| Kind of key | How Claude Code combines it | Keys |
|:-------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Lists | Combines entries from every source | [`permissions.allow`](#permissions-allow), [`sandbox.network.allowedDomains`](#sandbox-network-alloweddomains), and other list keys |
| Locks | Applies the strictest value any source sets. When no source sets a strict value, applies a looser value only from the highest source | [`allowManagedPermissionRulesOnly`](#allowmanagedpermissionrulesonly), [`permissions.disableBypassPermissionsMode`](#permissions-disablebypasspermissionsmode), and other boolean or enum locks |
| Restriction allowlists | Takes the list whole from the highest source that sets it, without adding entries from lower sources. When the highest source doesn’t set one, takes it whole from the next source down | [`availableModels`](#availablemodels), [`allowedMcpServers`](#allowedmcpservers), [`strictKnownMarketplaces`](#strictknownmarketplaces), [`allowedChannelPlugins`](#allowedchannelplugins), and the [`fallbackModel`](#fallbackmodel) chain |
| Values taken whole | Takes the value whole from the highest source that sets it, without combining entries or fields from lower sources. When the highest source doesn’t set it, takes it whole from the next source down | [`sandbox.credentials.awsPairs`](#sandbox-credentials-awspairs), [`sandbox.ripgrep`](#sandbox-ripgrep) |
| Provided MCP servers | Combines the server names from every source. When two sources set the same name, applies the higher source’s whole entry | [`managedMcpServers`](#managedmcpservers) |
| Read from the highest-priority source only | Reads the key only from the highest-priority source that carries a policy key, so a lower source’s value is ignored even when the highest source sets none | [`apiKeyHelper`](#apikeyhelper), [`awsAuthRefresh`](#awsauthrefresh), [`awsCredentialExport`](#awscredentialexport), [`gcpAuthRefresh`](#gcpauthrefresh), [`otelHeadersHelper`](#otelheadershelper), `proxyAuthHelper`, [`forceLoginOrgUUID`](#forceloginorguuid), the `"claudeai"` and `"console"` values of [`forceLoginMethod`](#forceloginmethod), [`parentSettingsBehavior`](#parentsettingsbehavior), [`modelPicker`](#modelpicker), [`policyHelper`](#policyhelper), [`permissions.defaultMode`](#permissions-defaultmode) |
| `env` | [Merges per variable across admin sources](../13-Enterprise-Admin/managed-settings.md#keys-read-from-every-admin-source), under both `"first-wins"` and `"merge"` | [`env`](#env) |
| Every other key | Takes the value from the highest source that sets it | [`cleanupPeriodDays`](#cleanupperioddays), [`model`](#model) |
Taking `sandbox.credentials.awsPairs` and `sandbox.ripgrep` whole requires Claude Code v2.1.257 or later. A few keys add a condition that the table doesn’t show:
- **[`policyHelper`](#policyhelper)**: Claude Code honors it only when the highest source that carries a policy key is an MDM policy or a managed settings file, so under server-managed settings it doesn’t apply.
- **[`modelOverrides`](#modeloverrides)**: pairs with `availableModels`. Claude Code takes `modelOverrides` from the highest source that sets it, unless a higher source sets `availableModels` without `modelOverrides`. In that case it ignores `modelOverrides` from every source.
- **[`forceLoginGatewayUrl`](#forcelogingatewayurl), [`gatewayInternalNetworks`](#gatewayinternalnetworks), and the `"gateway"` value of [`forceLoginMethod`](#forceloginmethod)**: Claude Code never reads any of them from server-managed settings, so a value there neither applies nor hides one set in an MDM policy or managed settings file. Among the admin sources on the machine, only the highest-ranked one that carries a policy key supplies them, whether or not server-managed settings are also present.
To confirm which sources combined on a machine, run `/status` and [read the `Setting sources` line](../13-Enterprise-Admin/managed-settings.md#read-the-source-in-/status).
[](#parentsettingsbehavior)
`parentSettingsBehavior`
Choose whether Claude Code applies managed settings supplied by an embedding host process, such as the Agent SDK or an IDE extension, when an admin-deployed managed tier is also present. With `"first-wins"`, Claude Code drops the host-supplied settings; with `"merge"`, it applies them under the admin tier through a restrictive-only filter. Set `"merge"` when a host needs to pass its own restrictions to the sessions it launches, for example Claude Desktop delivering a gateway’s egress allowlist.
- **Scope**: [`Managed`](#scopes). Claude Code reads it from the highest-priority admin-controlled managed source.
- **Type**: string, one of:
- `"first-wins"`: Claude Code drops the host-supplied settings when an admin-deployed managed tier is present
- `"merge"`: Claude Code applies the host-supplied settings under the admin tier through a restrictive-only filter
- **Default**: `"first-wins"`
managed-settings.json
```python
{
"parentSettingsBehavior": "merge"
}
```
This key has no effect when no admin-deployed managed tier exists: the host’s settings then apply as the only managed tier, still filtered to restrictive values. For the filter’s limits and how the managed sources interact, see [Parent settings from embedding hosts](../13-Enterprise-Admin/managed-settings.md#parent-settings-from-embedding-hosts) and [Restrict parent settings](../13-Enterprise-Admin/claude-apps-gateway.md#restrict-parent-settings).
[](#policyhelper)
`policyHelper`
Run an executable you deploy that computes managed settings at startup, so you can derive policy from device posture, identity, or a remote service instead of a static file. Claude Code runs the helper before it accepts the first prompt and treats the settings it emits as the managed settings for the session.
- **Scope**: [`Managed`](#scopes). Read from the macOS plist, the Windows HKLM registry, or the managed settings file. Claude Code reads the key from the highest-priority managed source that carries a [policy key](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) and runs the helper only when that source is one of those three; it ignores the key in server-managed settings, the HKCU registry, and host-supplied parent settings.
- **Type**: object with `path`, `timeoutMs`, and `refreshIntervalMs`
- **Default**: unset, so no helper runs
When server-managed settings deliver the policy at launch, they take precedence over the helper’s source and the helper doesn’t run. If a later settings fetch reports the server-managed settings removed, Claude Code runs the helper at that point rather than waiting for the next launch. Its output governs the rest of the session, and a run that fails ends the session with the same message as a [failed startup run](#helper-failures). This example runs the helper with a 5-second timeout and re-runs it every five minutes:
managed-settings.json
```python
{
"policyHelper": {
"path": "/usr/local/bin/claude-policy",
"timeoutMs": 5000,
"refreshIntervalMs": 300000
}
}
```
[](#write-the-helper-output)
Write the helper output
Claude Code runs the helper with no arguments, sets `CLAUDE_CODE_VERSION` in its environment, and reads a JSON envelope from stdout, capped at 1 MiB. Put the settings under a `managedSettings` key. A bare settings object with no `managedSettings` key parses with `managedSettings` undefined and applies nothing, and Claude Code reports no error:
```python
{
"managedSettings": {
"permissions": { "deny": ["Read(//etc/secrets/**)"] }
}
}
```
When the helper emits `managedSettings`, that object becomes the only managed settings source for the run: Claude Code ignores the MDM, file, and HKCU sources, reads the [cross-source keys](../13-Enterprise-Admin/managed-settings.md#keys-read-from-every-admin-source) from the helper’s output alone, and never merges [parent settings](../13-Enterprise-Admin/managed-settings.md#parent-settings-from-embedding-hosts). The startup `forceRemoteSettingsRefresh` check runs before the helper and reads any admin source. A helper that exits `0` with an envelope that omits `managedSettings` contributes no managed settings, and the other sources apply as usual.
[](#helper-failures)
Helper failures
A helper run fails when:
- `path` breaks the rules in [`policyHelper.path`](#policyhelper-path).
- No regular file is at `path`. Claude Code checks for the file before starting the helper, within the same `timeoutMs` budget, so an unresponsive network mount can cause the run to fail.
- The helper exits non-zero, is still running when `timeoutMs` elapses, or doesn’t start at all, for example because it isn’t executable.
- The helper writes more than 1 MiB to stdout or to stderr.
- stdout isn’t a single JSON object, or its `managedSettings` has a [schema violation Claude Code can’t repair](../13-Enterprise-Admin/managed-settings.md#find-entries-claude-code-dropped).
When the startup run fails, Claude Code prints the reason and refuses to start. After a non-zero exit, the reason includes the helper’s stderr, or its stdout when stderr is empty. After a timeout, the reason names the `timeoutMs` limit and includes none of the helper’s output. The refusal covers interactive sessions, `claude -p`, Agent SDK sessions, [background sessions](../09-Agents-Patterns/agent-view.md), and most subcommands. The refusal is deliberate, so a helper that needs outage resilience should serve from its own cache and exit `0`. When a background refresh fails, Claude Code keeps the last successful policy in effect, and `/status` shows the failing refresh with its reason until a refresh succeeds. Each refresh runs under the same `timeoutMs` and failure rules as the startup run. With `--debug`, Claude Code writes the helper’s stderr from every run to the [debug log](debug-your-config.md). Claude Code reports an invalid `policyHelper` value as a [dropped entry](../13-Enterprise-Admin/managed-settings.md#find-entries-claude-code-dropped) and starts the session on the remaining managed settings without running a helper. Invalid values include a bare path string and a `timeoutMs` below [its minimum](#policyhelper-timeoutms). To turn a helper off, remove the key from the source that sets it.
[](#policyhelper-path)
`policyHelper.path`
Name the helper executable Claude Code runs. For what happens when the path breaks the rules below, see [Helper failures](#helper-failures).
- **Scope**: [`Managed`](#scopes). Read from the macOS plist, the Windows HKLM registry, or the managed settings file, wherever [`policyHelper`](#policyhelper) is read.
- **Type**: string, an absolute path in normalized form, without `.` or `..` segments; on Windows, a drive-letter or UNC path that ends in `.exe`
- **Default**: none; required when `policyHelper` is set
managed-settings.json
```python
{
"policyHelper": {
"path": "/usr/local/bin/claude-policy"
}
}
```
[](#policyhelper-timeoutms)
`policyHelper.timeoutMs`
Set how long Claude Code waits for the helper before treating the run as failed. A timed-out run fails the same way as a non-zero exit, so at startup Claude Code refuses to start.
- **Scope**: [`Managed`](#scopes). Read from the macOS plist, the Windows HKLM registry, or the managed settings file, wherever [`policyHelper`](#policyhelper) is read.
- **Type**: integer, milliseconds, minimum `1000`
- **Default**: `10000`
managed-settings.json
```python
{
"policyHelper": {
"path": "/usr/local/bin/claude-policy",
"timeoutMs": 5000
}
}
```
[](#policyhelper-refreshintervalms)
`policyHelper.refreshIntervalMs`
Have Claude Code re-run the helper in the background on an interval so policy changes reach a running session. When a refresh succeeds, its output replaces the previous managed settings without a restart; when a refresh fails, Claude Code keeps the policy it already has.
- **Scope**: [`Managed`](#scopes). Read from the macOS plist, the Windows HKLM registry, or the managed settings file, wherever [`policyHelper`](#policyhelper) is read.
- **Type**: integer, milliseconds: `0` to disable refresh, otherwise at least `60000`
- **Default**: unset, so Claude Code runs the helper once at startup
This example re-runs the helper every five minutes:
managed-settings.json
```python
{
"policyHelper": {
"path": "/usr/local/bin/claude-policy",
"refreshIntervalMs": 300000
}
}
```
[](#wslinheritswindowssettings)
`wslInheritsWindowsSettings`
Have Claude Code on WSL read managed settings from the Windows policy chain, with HKLM and the Windows managed settings file taking priority over `/etc/claude-code` and HKCU below it. While the chain is on, Claude Code reads `/etc/claude-code` only when [no Windows admin document is present](../13-Enterprise-Admin/managed-settings.md#present-admin-documents) in the HKLM registry value or the `C:\Program Files\ClaudeCode\` folder. Set it to extend the policy you already deploy on Windows to WSL sessions on the same machine, so they follow the same rules as host sessions. Claude Code honors it only when set in the HKLM registry key or in a managed settings file or drop-in under `C:\Program Files\ClaudeCode\`, both of which require Windows admin to write.
- **Scope**: [`Managed`](#scopes). In an admin-controlled Windows source.
- **Type**: Boolean
- `true`: Claude Code on WSL reads managed settings from the Windows policy chain, and reads `/etc/claude-code` only when no Windows admin document is present
- `false`: WSL reads only `/etc/claude-code`
- **Default**: `false`, so WSL reads only `/etc/claude-code`
managed-settings.json
```python
{
"wslInheritsWindowsSettings": true
}
```
Once an admin source turns the chain on, HKCU policy joins it on WSL only when HKCU also sets the key to `true`. That copy doesn’t turn the chain on by itself. A Windows source that contains only this key, set to `true` or `false`, doesn’t count as a policy source, so a lower-priority source still supplies the policy. This key has no effect on native Windows. Claude Code reads `true` and `false` with or without quotes and reads `null` as removing the key. An admin-controlled Windows source that holds any other value counts as a [present admin document](../13-Enterprise-Admin/managed-settings.md#present-admin-documents) with the chain turned on: neither `/etc/claude-code` nor HKCU applies, and a startup warning names the key. An HKLM value or Windows-folder file that exists but can’t be read also keeps `/etc/claude-code` from applying whether or not the chain is on. Requires Claude Code v2.1.282 or later.
[](#global-config-settings)
Global config settings
Save these keys in `~/.claude.json`, not in a settings file. Claude Code ignores them anywhere else. Claude Code and `/config` write most of them for you, and you can also edit them by hand.
[](#autoconnectide)
`autoConnectIde`
Connect to a running IDE automatically when you start Claude Code from an external terminal. Appears in `/config` as **Auto-connect to IDE (external terminal)** when you run Claude Code outside a VS Code or JetBrains terminal.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: Claude Code connects to a running IDE automatically when you start it from an external terminal
- `false`: Claude Code doesn’t connect automatically from an external terminal; inside a VS Code or JetBrains terminal, or with `--ide`, it still connects
- **Default**: `false`
- **Per-session overrides**: [`CLAUDE_CODE_AUTO_CONNECT_IDE`](env-vars.md) takes precedence over this key for one session, in either direction
~/.claude.json
```python
{
"autoConnectIde": true
}
```
Claude Code ignores this key in `settings.json`.
[](#autoinstallideextension)
`autoInstallIdeExtension`
Install the Claude Code IDE extension automatically when you run Claude Code from a VS Code terminal. Appears in `/config` as **Auto-install IDE extension** when you run Claude Code inside a VS Code or JetBrains terminal.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: Claude Code installs the IDE extension automatically when you run it from a VS Code terminal
- `false`: Claude Code doesn’t install the extension automatically
- **Default**: `true`
- **Per-session overrides**: [`CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL`](env-vars.md) set to `1` skips the install for one session even when this key is `true`
~/.claude.json
```python
{
"autoInstallIdeExtension": false
}
```
Claude Code ignores this key in `settings.json`.
[](#claudeinchromedefaultenabled)
`claudeInChromeDefaultEnabled`
Start every interactive CLI session with [Chrome integration](../03-IDE-Integrations/chrome.md) on, without passing `--chrome` each time. If you run [`claude remote-control`](remote-control.md), a session it starts for one of your [project](claude-projects.md) threads follows this key too, except in `bypassPermissions` mode. Running `/chrome` and selecting **Enabled by default** sets this key for you, as described in [Enable Chrome by default](../03-IDE-Integrations/chrome.md#enable-chrome-by-default). Appears in `/config` as **Claude in Chrome enabled by default**.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: Claude Code turns on Chrome integration when an interactive CLI session starts, as it does when you pass `--chrome`
- `false`: interactive CLI sessions start with Chrome integration off, and Claude Code stops [offering to set it up](../03-IDE-Integrations/chrome.md#install-the-extension-when-claude-asks). Pass `--chrome` to turn it on for one interactive session
- **Default**: unset, so Chrome integration is off and Claude Code can still offer to set it up
- **Per-session overrides**: `--chrome` and [`--no-chrome`](cli-reference.md) take precedence over this key for one interactive session
~/.claude.json
```python
{
"claudeInChromeDefaultEnabled": true
}
```
Claude Code ignores this key in `settings.json`.
[](#copyfullresponse)
`copyFullResponse`
Make [`/copy`](commands.md) copy the full response every time, without the picker it otherwise shows when the response contains code blocks. Selecting **Always copy full response** in that picker sets this key to `true`. Appears in `/config` as **Skip the /copy picker**.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: `/copy` copies the full response without showing the picker
- `false`: when the response contains code blocks, `/copy` shows a picker where you choose one code block or the full response
- **Default**: `false`
~/.claude.json
```python
{
"copyFullResponse": true
}
```
Claude Code ignores this key in `settings.json`.
[](#copyonselect)
`copyOnSelect`
Copy text to your clipboard automatically when you finish selecting it with the mouse in [fullscreen rendering](fullscreen.md#use-the-mouse) or [agent view](../09-Agents-Patterns/agent-view.md). Appears in `/config` as **Copy on select** while fullscreen rendering is on.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: Claude Code copies text to your clipboard when you finish selecting it
- `false`: selecting text leaves your clipboard unchanged, and you [copy the selection with a keyboard shortcut](fullscreen.md#use-the-mouse) instead
- **Default**: `true`
~/.claude.json
```python
{
"copyOnSelect": false
}
```
Claude Code ignores this key in `settings.json`.
[](#defaulttoagentsview)
`defaultToAgentsView`
Open [agent view](../09-Agents-Patterns/agent-view.md) instead of a new conversation when you run `claude` with no arguments. Appears in `/config` as **Open agents view by default** unless agent view is [turned off](#disableagentview).
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: `claude` with no arguments opens agent view, unless agent view is [turned off](#disableagentview)
- `false`: `claude` with no arguments starts a new conversation
- **Default**: `false`
~/.claude.json
```python
{
"defaultToAgentsView": true
}
```
Claude Code ignores this key in `settings.json`.
[](#difftool)
`diffTool`
Choose where Claude Code shows the diff of an `Edit` or `Write` change it proposes when a [VS Code](../03-IDE-Integrations/vs-code.md) or [JetBrains](../03-IDE-Integrations/jetbrains.md#features) IDE is connected: `"auto"` opens it in the IDE’s diff viewer, `"terminal"` keeps it in the terminal. Appears in `/config` as **Diff tool** only while Claude Code is connected to a VS Code or JetBrains IDE.
- **Scope**: [`Global config`](#scopes)
- **Type**: string, one of:
- `"auto"`: Claude Code opens the diff in the IDE’s diff viewer when a VS Code or JetBrains IDE is connected
- `"terminal"`: Claude Code keeps the diff in the terminal
- **Default**: `"auto"`
~/.claude.json
```python
{
"diffTool": "terminal"
}
```
Claude Code ignores this key in `settings.json`.
[](#externaleditorcontext)
`externalEditorContext`
When you press `Ctrl+G`, Claude Code opens the prompt you’re typing in your [external editor](interactive-mode.md#general-controls). With this key on, the editor buffer starts with Claude’s previous response as `#` comment lines, so you can read it while you write, and Claude Code strips those lines when you save. Appears in `/config` as **Show last response in external editor**.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: the editor buffer starts with Claude’s previous response as `#` comment lines, which Claude Code strips when you save
- `false`: the editor buffer opens with only your prompt
- **Default**: `false`
~/.claude.json
```python
{
"externalEditorContext": true
}
```
With it on, the buffer Claude Code opens looks like this, and only the text below the marker line is sent as your prompt:
```python
# ─── Claude's last response (for reference; removed on save) ───
# I added the retry loop to fetchUser in src/api.ts and a test
# for the timeout case. Want me to wire the same retry into
# fetchOrders?
# ─── Write your reply below this line ──────────────────────────
Yes, and cap it at three attempts.
```
Claude Code keeps the last 50 lines of the response and marks the cut with `# … (earlier output truncated)`. Claude Code ignores this key in `settings.json`.
[](#leftarrowopensagents)
`leftArrowOpensAgents`
Press `←` on an empty prompt to [background the session and open agent view](../09-Agents-Patterns/agent-view.md#switch-sessions-without-leaving-the-terminal). Set this key to `false` to turn the shortcut off. Appears in `/config` as **← opens agents** when agent view is available.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: pressing `←` on an empty prompt in a session you started in the terminal backgrounds it and opens agent view
- `false`: Claude Code turns the shortcut off; in a session you [attached to from agent view](../09-Agents-Patterns/agent-view.md#attach-to-a-session), `←` on an empty prompt still detaches
- **Default**: `true`
~/.claude.json
```python
{
"leftArrowOpensAgents": false
}
```
Claude Code ignores this key in `settings.json`.
[](#permissionexplainerenabled)
`permissionExplainerEnabled`
Removed in v2.1.257, together with the `Ctrl+E` command explanation on Bash and PowerShell permission prompts. Setting it has no effect on current versions.
Through v2.1.256, you could press `Ctrl+E` on a Bash or PowerShell permission prompt to see a model-generated explanation of the command, and set this key to `false` to turn that shortcut off.
- **Scope**: [`Global config`](#scopes). On v2.1.256 and earlier.
- **Type**: Boolean
- **Default**: `true`
[](#prstatusfooterenabled)
`prStatusFooterEnabled`
Show a badge in the prompt footer for the current branch’s open pull request or merge request, with a colored underline that shows its [status](interactive-mode.md#pr-review-status). Appears in `/config` as **Show PR status footer**.
- **Scope**: [`Global config`](#scopes)
- **Type**: Boolean
- `true`: the footer shows the badge under the conditions in [PR review status](interactive-mode.md#pr-review-status)
- `false`: Claude Code skips the footer’s pull request and merge request check and doesn’t show that badge. A session you [attached to from agent view](../09-Agents-Patterns/agent-view.md#attach-to-a-session) can still show a plain link to a pull request [linked to it](../09-Agents-Patterns/agent-view.md#pull-request-status)
- **Default**: `true`
~/.claude.json
```python
{
"prStatusFooterEnabled": false
}
```
Claude Code ignores this key in `settings.json`.
[](#teammatedefaultmodel)
`teammateDefaultModel`
Removed in v2.1.234, together with its `/config` row **Default teammate model**. Setting it has no effect on current versions.
Through v2.1.233, you set this key to the model for [agent team](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models) teammates your prompt didn’t name a model for: an alias such as `"sonnet"`, or `null` to follow the lead’s model. For the model Claude Code picks for such teammates now, see [specify teammates and models](../09-Agents-Patterns/agent-teams.md#specify-teammates-and-models).
- **Scope**: [`Global config`](#scopes). On v2.1.233 and earlier.
- **Type**: string, a model alias or full model ID, or `null`
- **Default**: unset
[](#see-also)
See also
- [Configure permissions](permissions.md): rule syntax, permission modes, and workspace trust
- [Environment variables](env-vars.md): every `CLAUDE_*`, `ANTHROPIC_*`, and provider variable Claude Code reads
- [Tools available to Claude](tools-reference.md): the built-in tools and which need approval
- [Example settings files](settings-example.md): a personal file, a team file, and an organization’s managed file
- [Set up managed settings](../13-Enterprise-Admin/admin-setup.md): how organizations decide what to enforce
- [Deploy managed settings](../13-Enterprise-Admin/managed-settings.md): delivery mechanisms, precedence within the managed tier, and invalid entries in managed settings
- [Debug your configuration](debug-your-config.md): `claude doctor` and the Settings Error dialog
---
## Settings files and precedence - Claude Code Docs
Source: https://code.claude.com/docs/en/settings
Path: 02-Claude-Code-CLI/settings.md
## On this page
- [Settings files and who they affect](#settings-files-and-who-they-affect)
- [Compare the scope of each settings file](#compare-the-scope-of-each-settings-file)
- [Find or create your settings files](#find-or-create-your-settings-files)
- [Share settings with your team](#share-settings-with-your-team)
- [Keep personal settings out of a repository](#keep-personal-settings-out-of-a-repository)
- [Where Claude Code keeps the local file in a git repository](#where-claude-code-keeps-the-local-file-in-a-git-repository)
- [Check what your organization enforces](#check-what-your-organization-enforces)
- [Change a setting](#change-a-setting)
- [Use the /config menu](#use-the-%2Fconfig-menu)
- [Edit a settings file](#edit-a-settings-file)
- [Change a setting for one session](#change-a-setting-for-one-session)
- [When edits take effect](#when-edits-take-effect)
- [Confirm what loaded](#confirm-what-loaded)
- [Fix a broken settings file](#fix-a-broken-settings-file)
- [Settings precedence](#settings-precedence)
- [Lists merge instead of overriding](#lists-merge-instead-of-overriding)
- [Precedence examples](#precedence-examples)
- [Team settings override personal settings](#team-settings-override-personal-settings)
- [Organization settings override everything](#organization-settings-override-everything)
- [The command line overrides your files for one session](#the-command-line-overrides-your-files-for-one-session)
- [A flag or environment variable sets the same thing](#a-flag-or-environment-variable-sets-the-same-thing)
- [Troubleshoot a setting that doesn’t apply](#troubleshoot-a-setting-that-doesn%E2%80%99t-apply)
- [A value you set is ignored](#a-value-you-set-is-ignored)
- [A change you made in Claude Code is lost in new sessions](#a-change-you-made-in-claude-code-is-lost-in-new-sessions)
- [A managed change hasn’t reached you](#a-managed-change-hasn%E2%80%99t-reached-you)
- [A committed key doesn’t reach teammates](#a-committed-key-doesn%E2%80%99t-reach-teammates)
- [Permission rules combine differently than you expected](#permission-rules-combine-differently-than-you-expected)
- [Exceptions to managed settings precedence](#exceptions-to-managed-settings-precedence)
- [Settings in cloud sessions](#settings-in-cloud-sessions)
- [What’s next](#what%E2%80%99s-next)
Settings
# Settings files and precedence
Copy pageCopy page
Change Claude Code settings, pick the scope a key belongs in, verify the change, and learn which value Claude Code uses when a key is set in several places.
Copy pageCopy page
Settings are the JSON keys that change how Claude Code behaves: which model it starts with, what it can run without asking, which files it can’t read, how it looks in your terminal, and what your organization enforces.
To look up a specific key, go to [All settings](settings-reference.md), which lists every key with the file you set it in, its default, and an example.
Claude Code reads settings from JSON settings files such as `~/.claude/settings.json`. It looks for them in a few locations, and [the file it reads a setting from decides who the setting applies to](#settings-files-and-who-they-affect). This page covers those files: which one to put a setting in, how to change a setting and confirm it applied, and which value Claude Code uses when the same key is set in more than one file. [Configure permissions](permissions.md) covers what Claude Code can run without asking and how to write `allow`, `ask`, and `deny` rules.
This page covers Claude Code running on your machine: the terminal, the [VS Code](../03-IDE-Integrations/vs-code.md) and [JetBrains](../03-IDE-Integrations/jetbrains.md) extensions, and the [desktop app](../16-Mobile-Desktop/desktop.md), which all read the same settings files. A [cloud session](claude-code-on-the-web.md) runs on a different machine and reads only some of them; see [Settings in cloud sessions](#settings-in-cloud-sessions).
[](#settings-files-and-who-they-affect)
Settings files and who they affect
Claude Code reads settings from four files, and an organization can also deliver managed settings from the claude.ai console. Each source has a scope: the set of people and projects a setting saved in it applies to, whether that’s just you, everyone in a project, or everyone in your organization.
| Scope | File | Who it affects | Use it for |
|:---------------|:---------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------|
| User | `~/.claude/settings.json` | You, in every project on this machine | Personal preferences: theme, editor mode, default model, your own permission rules |
| Shared project | `.claude/settings.json` | Everyone working in the folder that contains it. In a git repository, commit it so teammates get it | Team permissions, hooks, plugins, and the environment variables the project needs |
| Project local | `.claude/settings.local.json` | You, in this one project only. Claude Code keeps it out of git when it creates the file; if you create it by hand, add it to `.gitignore` yourself | Personal overrides for one project, and testing before you share |
| Managed | `managed-settings.json` and other [managed sources](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) | Everyone your organization deploys it to; nothing you set overrides it, apart from a few [security-sensitive exceptions](#exceptions-to-managed-settings-precedence) | Security policy and compliance requirements |
In the File column, `~/.claude` is the `.claude` folder in your home directory, and a bare `.claude` is the `.claude` folder inside your project.
[](#compare-the-scope-of-each-settings-file)
Compare the scope of each settings file
Suppose you have three projects on your machine, `website/`, `api/`, and `acme-app/`, a teammate has their own clone of `acme-app/`, and you start a [cloud session](#settings-in-cloud-sessions) on `acme-app/`. The graphic below shows which of those folders a setting applies in when you start Claude Code from them. Click a settings file to see the folders it reaches.
- **`~/.claude/settings.json`**: every project on your machine, and nothing on your teammate’s or in the cloud session
- **`acme-app/.claude/settings.json`**: your `acme-app/`. It reaches your teammate’s clone and the cloud session only if you commit the file to version control; until you do, it’s a file on your disk like any other and nobody else has it
- **`acme-app/.claude/settings.local.json`**: your `acme-app/` only. Claude Code adds it to your global git excludes the first time it writes the file, so it stays out of your commits; if you create the file by hand, [add it to `.gitignore` yourself](#keep-personal-settings-out-of-a-repository)
- **Managed settings**, whether a `managed-settings.json` file, an MDM policy, or [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) from the claude.ai console: every project on every machine your organization deploys it to, or that you sign in to with your organization account. Only server-managed settings reach the cloud session
[](#find-or-create-your-settings-files)
Find or create your settings files
Installing Claude Code doesn’t create any settings file. If your machine or project already has one, it came from one of these sources:
- **Managed**: your organization deploys it. You don’t create or edit it.
- **Shared project**: a project that already uses Claude Code may have one committed. If not, create it at `.claude/settings.json` in the project folder.
- **User** and **Project local**: create them yourself, or let Claude Code create them. It writes `~/.claude/settings.json` the first time you change an option in the `/config` menu that it stores in user settings, such as the theme, and `.claude/settings.local.json` the first time you give a standing approval on a permission prompt, such as “Yes, and don’t ask again” for a Bash command. A few `/config` options, including **Show tips**, save to `.claude/settings.local.json` instead of the user file.
On Windows, `~/.claude` means `%USERPROFILE%\.claude`. To keep the home-directory files somewhere else, set [`CLAUDE_CONFIG_DIR`](env-vars.md); Claude Code then stores your settings, session history, and plugins there instead.
Claude Code also keeps a fifth file, [`~/.claude.json`](claude-directory.md#ce-claude-json), that it writes for itself; you don’t need to edit it. It holds your sign-in session, [MCP server](../06-MCP-Tools/General/mcp.md) configurations, per-project state such as trust decisions, and the [global config keys](settings-reference.md#global-config-settings) that `/config` writes for you.
[](#share-settings-with-your-team)
Share settings with your team
Commit `.claude/settings.json` so everyone who clones the repository gets the same permissions, hooks, and plugins. Each teammate can still override it for themselves in their own `.claude/settings.local.json`, so personal exceptions don’t need a commit. For a complete team file, see [a team’s shared settings](settings-example.md#a-teams-shared-settings). Some of what you commit waits until each teammate [trusts the folder](permissions.md#project-allow-rules-and-workspace-trust), and a few keys never take effect from a repository file; [Troubleshoot a setting that doesn’t apply](#common-cases) covers both.
[](#keep-personal-settings-out-of-a-repository)
Keep personal settings out of a repository
To change a setting for yourself in one project without changing it for your teammates, save it in `.claude/settings.local.json` inside the project. Claude Code applies that file over the committed `.claude/settings.json`, so if your team’s file sets `"model": "claude-sonnet-5"` and you want Opus, put `"model": "claude-opus-5-5"` in your local file and only your sessions change. Claude Code also writes to this file, keeps it out of your commits, and applies its allow rules without the trust step:
- **Claude Code writes it too.** When Claude asks permission to run a Bash command and you choose “Yes, and don’t ask again”, Claude Code saves that [permission approval](permissions.md#permission-system) here as an `allow` rule.
- **You don’t need to gitignore it yourself, unless you created it by hand.** The first time Claude Code writes the file in a git repository that doesn’t already ignore it, it adds `**/.claude/settings.local.json` to your global git excludes file, so the file stays out of your commits in every repository. That file is `core.excludesFile` when your global git config sets it to an absolute or `~`-prefixed path; otherwise it’s `$XDG_CONFIG_HOME/git/ignore`, or `~/.config/git/ignore` when `XDG_CONFIG_HOME` is unset. If you created the file by hand and Claude Code hasn’t written to it yet, add it to `.gitignore` yourself.
- **Its allow rules don’t wait for trust while the file stays untracked.** Because the file is yours and not the repository’s, Claude Code applies its `allow` rules without the [workspace trust](permissions.md#project-allow-rules-and-workspace-trust) step it requires for the committed file. If the file is tracked by git, the trust step applies to it too; see [When your local settings file needs trust](permissions.md#when-your-local-settings-file-needs-trust).
[](#where-claude-code-keeps-the-local-file-in-a-git-repository)
Where Claude Code keeps the local file in a git repository
When Claude asks permission to run a Bash command and you choose “Yes, and don’t ask again”, Claude Code saves that approval as an `allow` rule in `.claude/settings.local.json`. If you start Claude Code in a subdirectory of a git repository, it reads and writes that file at the repository root and applies the approval across the whole repository. In a [worktree](worktrees.md), it uses the file at the main checkout’s root. Two rules qualify the root location:
- **When the file stays with `.claude/settings.json` instead**: outside a git repository, when the repository root is your home directory, on Windows, or when the repository root or its `.git` or `.claude` entry isn’t owned by your user.
- **Paths in the file don’t anchor at the repository root**: a permission rule that starts with `/` or a relative sandbox path [anchors at the session’s primary working directory](permissions.md#read-and-edit) instead.
Before v2.1.211, Claude Code kept the file in the starting directory. It still reads a file an earlier version left there alongside the root file; where both set the same key, the root’s value applies, and permission rules from both files apply. The Agent SDK’s [`resolveSettings()`](../05-Agent-SDK/agent-sdk-typescript.md#resolvesettings) helper always reads the file from the starting directory. Claude Code reads the shared `.claude/settings.json` from the session’s [primary working directory](permissions.md#working-directories), so to use a file committed at the repository root, start Claude Code there. After you [move the session with `/cd`](permissions.md#move-the-session-to-another-directory), Claude Code reads both project files from the new directory instead, placing the local file by the same rules. Reading them from the directory you moved to requires Claude Code v2.1.246 or later.
[](#check-what-your-organization-enforces)
Check what your organization enforces
If your organization manages Claude Code, some settings are decided for you and nothing you put in your own files changes them. To see which, run `/status`: the `Setting sources` line names the managed source that applies to you. Managed settings apply wherever Claude Code runs on this machine; [What a developer can change](../13-Enterprise-Admin/managed-settings.md#what-a-developer-can-change) covers local admin rights and tools other than Claude Code. Managed settings reach you through the [delivery mechanisms](../13-Enterprise-Admin/managed-settings.md#delivery-mechanisms) on the managed settings page, most commonly:
- [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md), which Claude Code fetches from the claude.ai admin console or a self-hosted [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md)
- MDM or OS-level policies, and `managed-settings.json` files in a system directory
- An embedding host such as Claude Desktop, through the SDK `managedSettings` option; see [Control policy from an embedding host](../13-Enterprise-Admin/managed-settings.md#parent-settings-from-embedding-hosts)
In a [Cowork](https://claude.com/docs/cowork/overview) session that runs on your machine in the Claude Desktop app, Claude Code doesn’t fetch server-managed settings from the claude.ai admin console, and it reads policy deployed to your device unless your organization’s Claude Desktop configuration sets `requireCoworkFullVmSandbox`. [Where and when a policy applies](../13-Enterprise-Admin/managed-settings.md#where-and-when-a-policy-applies) covers Cowork and cloud sessions. If you’re the administrator, [Set up Claude Code for your organization](../13-Enterprise-Admin/admin-setup.md) walks through choosing what to enforce, and [Deploy managed settings](../13-Enterprise-Admin/managed-settings.md) covers delivery and how to confirm a policy is in force.
[](#change-a-setting)
Change a setting
You can change a setting from the `/config` menu, by editing a settings file, or for one session from the command line. Claude Code’s system prompt isn’t published. To give Claude standing instructions, use [`CLAUDE.md` files](memory.md) or the `--append-system-prompt` flag.
[](#use-the-/config-menu)
Use the /config menu
Run `/config` inside Claude Code and open the **Config** tab. It lists a short set of personal options such as theme, editor mode, and verbose output, not every settings key. Select an option to change it; Claude Code saves it for you:
- **Most options**: `~/.claude/settings.json`
- **A few options, such as Show tips**: `.claude/settings.local.json`
- **The [global config options](settings-reference.md#global-config-settings)**: `~/.claude.json`
To set one option without the menu, pass `key=value`, such as `/config verbose=true`.
`/config` is part of the terminal interface. The [VS Code](../03-IDE-Integrations/vs-code.md) chat panel and the [desktop app](../16-Mobile-Desktop/desktop.md) don’t open it; change settings there by editing a settings file or through those apps’ own settings.
[](#edit-a-settings-file)
Edit a settings file
Open the settings file for the scope you want in your editor and add or change a key. Settings files are strict JSON: a `//` comment or a trailing comma is a syntax error, and Claude Code reports the file as a [Settings Error](#fix-a-broken-settings-file) at the next start. For example, to let Claude Code run your lint and test commands without asking and stop it reading `.env` files, add this to `~/.claude/settings.json`:
~/.claude/settings.json
```python
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
}
}
```
Each entry under `permissions` is a rule that names a tool and what it may do; [Configure permissions](permissions.md) explains the syntax. The `$schema` line points to the [published JSON schema](https://json.schemastore.org/claude-code-settings.json) for Claude Code settings, which gives you autocomplete and inline validation in VS Code, Cursor, and any other editor that supports JSON schema. The schema can lag behind the newest CLI releases, so a validation warning on a recently documented key doesn’t mean your configuration is invalid. After you save, run `/status` inside Claude Code to confirm the file loaded; [Confirm what loaded](#check-what-loaded) says what the `Setting sources` line shows and how a broken file is reported. For a complete personal file, team file, and organization file, each shown with a comment on every key it sets, see the [example settings files](settings-example.md).
[](#change-a-setting-for-one-session)
Change a setting for one session
To try a value without saving it, set it when you start Claude Code. The value applies to that session and your settings files stay as they were. You have three ways to do it:
- **`--settings`**: pass a key as JSON, inline or as a path to a file. Claude Code applies it above your user, project, and local files and below managed settings. It can set any key your user settings file can set; it can’t set `Managed` or `Global config` keys.
- **A flag for that key**: some keys have their own flag, such as `--model` for `model` and `--effort` for `effortLevel` and `modelSettings`.
- **An environment variable**: export the key’s paired variable before you run `claude`, such as `ANTHROPIC_MODEL` for `model`.
Each key’s entry on the [settings reference](settings-reference.md) lists its per-session overrides and which one takes precedence, so check the entry for the key you want to change. Commands you run inside a session mostly save your choice: when you change a setting in `/config`, Claude Code writes it to your settings files, and `/model` saves the value as your default for new sessions. If you press `s` in the `/model` picker, Claude Code switches the model without saving it as your user default. [Adjust effort level](model-config.md#adjust-effort-level) says which `/effort` picks Claude Code saves as your default for the model you’re using and which apply to the current session only. For example, to start one session on Opus without changing your default:
```python
claude --settings '{"model": "claude-opus-5-5"}'
```
[](#when-edits-take-effect)
When edits take effect
Claude Code watches your settings files and reloads them when they change, so it applies most edits to the running session without a restart, including edits to `permissions`, `hooks`, and credential helpers such as `apiKeyHelper`. Claude Code also loads a settings file you create mid-session if its folder existed when the session started. For the project’s `.claude/` folder, it loads the file even when you create the folder in the same session. The reload covers user, project, local, and managed settings, and Claude Code runs the [`ConfigChange` hook](../07-Hooks/hooks.md#configchange) for each settings-file change it detects, not for managed settings that arrive from MDM or the claude.ai console. Managed settings that arrive through MDM or from the claude.ai console reach a running session on a schedule rather than on save; the [delivery table](../13-Enterprise-Admin/managed-settings.md#choose-a-delivery-mechanism) gives it per source. Claude Code reads some keys only once, at session start, so an edit to one of them doesn’t reach the running session. Admin-side keys that also wait for a restart, such as `requiredMinimumVersion`, are listed under [where and when a policy applies](../13-Enterprise-Admin/managed-settings.md#where-and-when-a-policy-applies). The ones you’re most likely to edit mid-session:
- [`model`](settings-reference.md#model): use [`/model`](model-config.md#setting-your-model) to switch mid-session. Each model has its own prompt cache, so the first request after a switch re-reads the whole conversation uncached; see [Switching models](prompt-caching.md#switching-models)
- [`effortLevel`](settings-reference.md#effortlevel) and [`modelSettings`](settings-reference.md#modelsettings): use [`/effort`](model-config.md#adjust-effort-level) to change effort mid-session
[](#confirm-what-loaded)
Confirm what loaded
Run `/status` inside Claude Code to see which settings sources are active. The **Status** tab includes a `Setting sources` line that lists each settings file Claude Code loaded for the current session, such as `User settings` or `Project local settings`. When [managed settings](../13-Enterprise-Admin/admin-setup.md#decide-how-settings-reach-devices) are in effect, the managed settings entry shows in parentheses how they reached your machine. The line confirms which files Claude Code read; it doesn’t show which file supplied each key. To list entries Claude Code rejected, run [`claude doctor`](debug-your-config.md); for a model that project or managed settings set, the startup header names the file that set it. `/status` and `/config` open the same dialog on different tabs, and the **Config** tab isn’t a view of your `settings.json` contents.
[](#fix-a-broken-settings-file)
Fix a broken settings file
If you mistype JSON or set a key to a value Claude Code doesn’t accept, Claude Code tells you at the start of an interactive session. What it shows depends on how much of the file is affected:
- **Settings Error**: a user, project, or local file has invalid JSON or a value the schema rejects. At the start of an interactive session Claude Code shows a dialog that lets you fix the file with Claude’s help, exit, or continue without the broken settings.
- **Settings Warning**: only individual entries fail, such as a malformed permission rule or an unknown hook event name. Claude Code skips those values and keeps the rest of the file in effect.
- **Managed settings**: Claude Code keeps enforcing the rest of the file. [Invalid entries in managed settings](../13-Enterprise-Admin/managed-settings.md#invalid-entries-in-managed-settings) says what it drops and which keys fall back to a stricter value until you fix them. For a managed settings document that isn’t valid JSON, see [Managed settings document could not be parsed](errors.md#managed-settings-document-could-not-be-parsed).
- **Configuration error**: `~/.claude.json` can’t be parsed. Claude Code copies the broken file to `~/.claude/backups/.claude.json.corrupted.<timestamp>` and asks whether to exit and fix it by hand or reset to the default configuration; a `-p` run prints the error and exits. To recover your previous state, copy back one of the five most recent `.claude.json.backup.<timestamp>` files in `~/.claude/backups/`, which Claude Code saves before it writes the file.
After you continue, run `/status` to see the affected files and `claude doctor` for the details of each error. A `-p` run shows no dialog. Unless [a managed settings document can’t be parsed](errors.md#managed-settings-document-could-not-be-parsed), Claude Code skips the broken file or values and continues with the rest, so after a `-p` run that ignores a setting, run `claude doctor` to see what it dropped.
[](#settings-precedence)
Settings precedence
When the same key appears in more than one place, Claude Code uses the value from the highest level that sets it. The stack below shows the levels, highest on top; a key at a higher level overrides the same key anywhere below it. In order, highest precedence first:
1. **Managed settings**: settings your organization deploys, by a `managed-settings.json` file, an MDM policy, or [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) from the claude.ai console. Nothing you set overrides them: a key you pass with `--settings` doesn’t override the same managed key, and a flag such as `--model` picks only from the models your organization allows. A managed `model` sets the model each session starts with, and you can still switch with `/model`; the lock is [`availableModels`](settings-reference.md#availablemodels), which constrains `/model`, `--model`, and the `model` key in your own files. When your organization delivers more than one managed source, the rules for [precedence within the managed tier](../13-Enterprise-Admin/managed-settings.md#precedence-within-the-managed-tier) say what Claude Code reads from each.
2. **Command line arguments**: flags you pass when you start `claude` from a terminal, for one session; see [Change a setting for one session](#change-a-setting-for-one-session). Claude Code merges JSON you pass with `--settings <file-or-json>` with your settings files by the same rules as the other levels: it takes a key you set here over the same key in local, project, or user settings, and keeps the lower-level value for a key you omit.
3. **Project local settings** (`.claude/settings.local.json`): your personal settings for this project.
4. **Shared project settings** (`.claude/settings.json`): settings your team checks into source control.
5. **User settings** (`~/.claude/settings.json`): your personal settings for every project.
Environment variables aren’t a level in this stack. When a behavior has both a shell variable and a settings key, which one applies is decided per pair, not by level: `ANTHROPIC_MODEL` exported in your shell applies over the `model` key from any file, while `ANTHROPIC_DEFAULT_MODEL` applies only when no file sets `model`. The [environment variables reference](env-vars.md#precedence) says which keys have a pair and which one Claude Code reads first. An `env` block inside a settings file is an ordinary key and follows the levels above. For a few security-sensitive keys, Claude Code honors a stricter value from a lower level over a managed value; [Exceptions to managed settings precedence](#exceptions-to-managed-settings-precedence) lists them.
[](#lists-merge-instead-of-overriding)
Lists merge instead of overriding
When you set the same list key, such as `permissions.allow`, in more than one file, Claude Code combines the lists instead of picking one, so each file can add entries without removing another file’s. Four keys that hold model lists or per-model entries follow their own rules:
- [`fallbackModel`](settings-reference.md#fallbackmodel) is an ordered chain where position carries meaning, so Claude Code takes the whole value from the highest-precedence file that defines it.
- [`modelPicker`](settings-reference.md#modelpicker) holds one ordered list of rows plus a replace flag, so Claude Code never merges rows from two sources. It takes the whole value from the highest of managed settings, `--settings`, and user settings that defines it, and ignores the key in project and local settings. Requires Claude Code v2.1.242 or later.
- [`availableModels`](settings-reference.md#availablemodels): when the managed settings Claude Code applies define it, Claude Code applies that list as-is and ignores entries you add in user, project, or local settings, unless an app that embeds Claude Code supplies its own model list; see [Exceptions to managed settings precedence](#exceptions-to-managed-settings-precedence). Across managed sources the list never merges either; [how Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) says which source’s list applies. Across non-managed scopes Claude Code merges the arrays as usual.
- [`modelSettings`](settings-reference.md#modelsettings): Claude Code resolves it one model at a time, together with [`effortLevel`](settings-reference.md#effortlevel). The `modelSettings` entry states which file’s value applies to a model.
[](#precedence-examples)
Precedence examples
While Claude works, Claude Code shows a one-line tip under the spinner, such as “Use /config to change your default permission mode (including Plan Mode)”. Suppose you want those tips off, so you set [`spinnerTipsEnabled`](settings-reference.md#spinnertipsenabled) to `false` in `~/.claude/settings.json`. Each scenario below is something that can turn them back on, and what you can do about it.
[](#team-settings-override-personal-settings)
Team settings override personal settings
Your team’s `.claude/settings.json` sets it to `true`. Claude Code uses the project value because shared project sits above user, so you see tips in that project and nowhere else. You can get your value back: add `"spinnerTipsEnabled": false` to `.claude/settings.local.json` in that project. Project local sits above shared project, so your sessions there stop showing tips and your teammates’ sessions don’t change.
[](#organization-settings-override-everything)
Organization settings override everything
Your organization’s managed settings set it to `true`. Nothing you put in user, project, or local settings turns tips off, and neither does `--settings`. Managed is the top level. You can’t get your value back. Run `/status` to see which managed source applies, and ask your administrator if the policy should change.
[](#the-command-line-overrides-your-files-for-one-session)
The command line overrides your files for one session
You started the session with `claude --settings '{"spinnerTipsEnabled": true}'`. Command line sits above every file except managed, so that session shows tips even though your files say `false`. You get your value back on the next session; `--settings` lasts one session and doesn’t write to any file.
[](#a-flag-or-environment-variable-sets-the-same-thing)
A flag or environment variable sets the same thing
Some keys have a command line flag or an environment variable that overrides the settings value regardless of which file set it: `ANTHROPIC_MODEL` overrides the [`model`](settings-reference.md#model) setting, and `--model` overrides both for a session. Whether you can get your value back depends on the key: unset the variable or drop the flag, and check the key’s entry on the [settings reference](settings-reference.md) and the variable’s row on the [environment variables reference](env-vars.md) for which one Claude Code uses.
[](#troubleshoot-a-setting-that-doesn’t-apply)
Troubleshoot a setting that doesn’t apply
When you set a key and Claude Code doesn’t behave as if you had, start with `/status` to see which files it loaded, then find your symptom below. [Debug your configuration](debug-your-config.md) covers the wider checks, including a clean-configuration test.
[](#a-value-you-set-is-ignored)
A value you set is ignored
Something else is setting the same key, the file can’t set that value, or the file didn’t load:
- **A higher level sets it.** Another settings file, a `--settings` flag, or a managed source sets the key above yours; the [stack](#settings-precedence) says which. A flag or environment variable can also override the key on its own, decided key by key; the key’s entry on the [settings reference](settings-reference.md) says which one Claude Code uses, and the [`env` entry](settings-reference.md#env) covers a managed `env` value versus a shell export.
- **A security key keeps its strict value.** For a few keys Claude Code honors the restrictive value from any file, so a project `true` for [`disableClaudeAiConnectors`](settings-reference.md#disableclaudeaiconnectors) stays on; see [Exceptions to managed settings precedence](#exceptions-to-managed-settings-precedence).
- **The file can’t set that value.** [`permissions.defaultMode`](settings-reference.md#permissions-defaultmode) values `auto` and `bypassPermissions` don’t take effect from project or local settings; set them in user or managed settings instead, or pass `--permission-mode` for one session. Before v2.1.257, `bypassPermissions` took effect from any file. A telemetry export variable in an [`env`](settings-reference.md#env) block doesn’t take effect from project or local settings either, apart from a few off values. [Variables Claude Code ignores in `env`](settings-reference.md#variables-claude-code-ignores-in-env) lists the variables and those values.
- **The file is broken.** Invalid JSON or a rejected value makes Claude Code skip the file or the entry; see [Fix a broken settings file](#fix-a-broken-settings-file).
[](#a-change-you-made-in-claude-code-is-lost-in-new-sessions)
A change you made in Claude Code is lost in new sessions
When you save a choice for new sessions from inside Claude Code, such as a default model with `/model`, Claude Code writes it to your user settings file, `~/.claude/settings.json`. If you can’t write to that file, for example because another tool generates it or links it to a read-only copy, the change applies to the current session and is gone in the next one. Set the key in the tool that generates the file, or replace the file with one you can write to. If you can write to the file and the change still doesn’t last, check whether the change was [for one session only](#change-a-setting-for-one-session) or [a higher level sets the same key](#a-value-you-set-is-ignored). For the `model` key, [A new session starts on a different model than you picked](model-config.md#a-new-session-starts-on-a-different-model-than-you-picked) lists more causes.
[](#a-managed-change-hasn’t-reached-you)
A managed change hasn’t reached you
Managed sources reach a running session on the schedule in the [delivery table](../13-Enterprise-Admin/managed-settings.md#choose-a-delivery-mechanism), so restart the session first. If `/status` then names a different source than the one your administrator changed, a higher-priority source applies; [How Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) gives the order.
[](#a-committed-key-doesn’t-reach-teammates)
A committed key doesn’t reach teammates
Two things keep a key in `.claude/settings.json` from applying for everyone who clones it:
- **Claude Code ignores the key in a repository file.** Look for `User, local, or managed`, `User or managed`, `Managed`, or `Global config` in the Scope column of the [settings index](settings-reference.md#settings-index). Those keys never apply from the shared file, apart from a few that a repository file can still switch off. Each of those entries says so on its Scope line. `Global config` keys apply only from `~/.claude.json`. Inside the `env` key, the telemetry export variables never apply from the shared file either, apart from a few off values; see [Variables Claude Code ignores in `env`](settings-reference.md#variables-claude-code-ignores-in-env).
- **The key waits for trust.** `permissions.allow` rules, `permissions.additionalDirectories`, `extraKnownMarketplaces`, and most [`env`](settings-reference.md#env) values apply only after each teammate [trusts the folder](permissions.md#project-allow-rules-and-workspace-trust). Until then they still see prompts and don’t get plugins from a marketplace the file declares. `deny` and `ask` rules apply right away.
[](#permission-rules-combine-differently-than-you-expected)
Permission rules combine differently than you expected
- **You chose “Yes, and don’t ask again” on a permission prompt but still get prompted for the same tool.** That choice saved an `allow` rule to your local file, and an `allow` rule there doesn’t outrank an `ask` rule from a project or managed file; [how permission rules combine](permissions.md#settings-precedence) explains the order. In the VS Code extension the approval card lets you pick the destination file, including the project’s shared file, which changes the rule for everyone; in the CLI, Claude Code writes only to your local file.
- **Your organization’s allow rules still apply alongside yours.** That’s expected: Claude Code merges [`permissions.allow`](settings-reference.md#permissions-allow) across scopes, unless your organization sets [`allowManagedPermissionRulesOnly`](settings-reference.md#allowmanagedpermissionrulesonly).
[](#exceptions-to-managed-settings-precedence)
Exceptions to managed settings precedence
For a few keys whose values restrict a session, Claude Code honors a restrictive value from a scope that otherwise couldn’t override managed settings. Find the key in this table to see which value it honors and from where.
| Key | Value Claude Code honors | Notes |
|:-------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`disableClaudeAiConnectors`](settings-reference.md#disableclaudeaiconnectors) | `true` from any scope | Honored even when a managed source sets `false` |
| [`enableArtifact`](settings-reference.md#enableartifact) | `false` from any scope, and `disableArtifact: true` from any scope | Honored even when a managed source sets `true`; nothing turns the [Artifact tool](artifacts.md#disable-artifacts) back on. Requires Claude Code v2.1.242 or later |
| [`isolatePeerMachines`](settings-reference.md#isolatepeermachines) | `true` from any scope | Honored even when a managed source sets `false` |
| [`remoteControlAtStartup`](settings-reference.md#remotecontrolatstartup) | `false` from `.claude/settings.json` or `.claude/settings.local.json` | Honored even when a managed source sets `true`; a project or local `true` is ignored |
| [`crossSessionInbound`](settings-reference.md#crosssessioninbound) | A stricter value from `.claude/settings.json` or `.claude/settings.local.json`, on the `accept` \< `hold` \< `refuse` ladder | Honored over managed, `--settings`, and user values; a project or local value that isn’t stricter is ignored |
| [`useAutoModeDuringPlan`](settings-reference.md#useautomodeduringplan) | `false` from any managed source, `--settings`, `~/.claude/settings.json`, or `.claude/settings.local.json` | Honored even when the winning managed source sets `true`; a `false` in `.claude/settings.json` is ignored |
| [`syncClaudeAiSkills`](settings-reference.md#syncclaudeaiskills) | `false` from any managed source, `--settings`, `~/.claude/settings.json`, or `.claude/settings.local.json` | Honored even when the winning managed source sets `true`; a `false` in `.claude/settings.json` is ignored |
| [`syncClaudeAiPlugins`](settings-reference.md#syncclaudeaiplugins) | `false` from any managed source, `--settings`, `~/.claude/settings.json`, or `.claude/settings.local.json` | Honored even when the winning managed source sets `true`; a `false` in `.claude/settings.json` is ignored |
| [`maxEffortLevel`](settings-reference.md#maxeffortlevel) | A lower cap from any scope, including `--settings` | Honored even when the managed settings Claude Code applies set a higher cap; the lowest cap applies. Requires Claude Code v2.1.267 or later |
An app that runs Claude Code inside itself and sets [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](env-vars.md) is also an exception. Claude Code takes that app’s model configuration over the `model`, `fallbackModel`, `modelPicker`, and `modelOverrides` keys from every managed source, and over the model-selection variables in a managed `env` block, such as `ANTHROPIC_MODEL` and the `ANTHROPIC_DEFAULT_*_MODEL` family. Claude Code keeps a managed [`availableModels`](settings-reference.md#availablemodels) allowlist in force unless the app supplies its own.
[](#settings-in-cloud-sessions)
Settings in cloud sessions
A [cloud session](claude-code-on-the-web.md) runs in a [cloud environment](cloud-environments.md) on a fresh clone of your repository, not on your machine. That changes which settings reach it:
- **Shared project settings** (`.claude/settings.json`): read in a session with one repository, because the file is part of the clone and the session starts inside it. Commit a setting there to apply it in those sessions. A session with several repositories starts above the clones and reads only the `enabledPlugins` and `extraKnownMarketplaces` keys from each repository’s `.claude/settings.json`, not permission rules, hooks, `env`, or other keys. The marketplaces and plugins those two keys declare still [don’t load in a cloud session](cloud-environments.md#what-carries-over-from-your-setup).
- **User and project local settings** (`~/.claude/settings.json` and `.claude/settings.local.json`): not read. Both stay on your machine, and the local file isn’t in the clone.
- **Managed settings**: a `managed-settings.json` file or MDM profile on your device doesn’t reach a cloud session. Your organization’s [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) do; [surface coverage](model-config.md#surface-coverage) lists which cloud sessions receive them. A [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) also reads the managed settings file in its runner image. [How Claude Code combines managed sources](../13-Enterprise-Admin/managed-settings.md#how-claude-code-combines-managed-sources) says when that file applies.
- **`/config`**: in your browser at claude.ai/code, opens the Claude Code section of your claude.ai settings instead of changing a value. To change a setting for a cloud session, set an [environment variable](cloud-environments.md#set-environment-variables) on the environment, or in a session with one repository, commit the key to that repository’s `.claude/settings.json`.
[What carries over from your setup](cloud-environments.md#what-carries-over-from-your-setup) lists the rest: `CLAUDE.md`, skills, MCP servers, plugins, and credentials.
[](#what’s-next)
What’s next
- [All settings](settings-reference.md): every key, with where you set it and an example
- [Example settings files](settings-example.md): a personal file, a team file, and an organization’s managed file
- [Configure permissions](permissions.md): allow, ask, and deny rules, and what Claude Code runs without asking
- [Environment variables](env-vars.md): the variables Claude Code reads and the `env` block
- [Debug your configuration](debug-your-config.md): when a setting doesn’t apply
- [Claude directory reference](claude-directory.md): every file Claude Code reads, including subagents, MCP servers, plugins, and `CLAUDE.md`
---
## Customize your status line - Claude Code Docs
Source: https://code.claude.com/docs/en/statusline
Path: 02-Claude-Code-CLI/statusline.md
## On this page
- [Set up a status line](#set-up-a-status-line)
- [Use the /statusline command](#use-the-%2Fstatusline-command)
- [Manually configure a status line](#manually-configure-a-status-line)
- [Disable the status line](#disable-the-status-line)
- [Build a status line step by step](#build-a-status-line-step-by-step)
- [How status lines work](#how-status-lines-work)
- [Available data](#available-data)
- [Context window fields](#context-window-fields)
- [Prompt cache fields](#prompt-cache-fields)
- [Last miss cause](#last-miss-cause)
- [Examples](#examples)
- [Context window usage](#context-window-usage)
- [Git status with colors](#git-status-with-colors)
- [Cost and duration tracking](#cost-and-duration-tracking)
- [Display multiple lines](#display-multiple-lines)
- [Clickable links](#clickable-links)
- [Rate limit usage](#rate-limit-usage)
- [Cache expensive operations](#cache-expensive-operations)
- [Windows configuration](#windows-configuration)
- [Subagent status lines](#subagent-status-lines)
- [Tips](#tips)
- [Troubleshooting](#troubleshooting)
Interface
# Customize your status line
Copy pageCopy page
Configure a custom status bar to monitor context window usage, costs, and git status in Claude Code
Copy pageCopy page
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
The status line renders in its own row above the built-in footer badges and does not replace them. With a custom status line configured, Claude Code stops showing most of the footer’s keyboard hints, including `esc to interrupt`, the `? for shortcuts` fallback, and the `hold space to speak` [voice dictation](voice-dictation.md) hint. To add clickable link badges to the footer when an ID appears in the conversation, without writing a script, configure [`footerLinksRegexes`](settings-reference.md#footerlinksregexes) instead. Here’s an example of a [multi-line status line](#display-multiple-lines) 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](#set-up-a-status-line), explains [how the data flows](#how-status-lines-work) from Claude Code to your script, lists [all the fields you can display](#available-data), and provides [ready-to-use examples](#examples) for common patterns like git status, cost tracking, and progress bars.
[](#set-up-a-status-line)
Set up a status line
Use the [`/statusline` command](#use-the-%2Fstatusline-command) to have Claude Code generate a script for you, or [manually create a script](#manually-configure-a-status-line) and add it to your settings.
[](#use-the-/statusline-command)
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:
```python
/statusline show model name and context percentage with a progress bar
```
Approve the file edit prompts if Claude Code asks for permission during setup.
[](#manually-configure-a-status-line)
Manually configure a status line
Add a `statusLine` field to your user settings (`~/.claude/settings.json`, where `~` is your home directory) or [project settings](settings.md#where-settings-live). 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](#build-a-status-line-step-by-step).
```python
{
"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:
```python
{
"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](#how-status-lines-work). 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`](#available-data) itself, so the mode is not shown twice.
[](#disable-the-status-line)
Disable the status line
Run `/statusline` and ask it to remove or clear your status line (for example, `/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)
Build a status line step by step
This walkthrough shows what `/statusline` sets up for you by manually creating a status line that displays the current model, working directory, and context window usage percentage.
Running [`/statusline`](#use-the-%2Fstatusline-command) 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](#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`](https://jqlang.org/), 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):
```python
#!/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:
```python
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:
```python
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}
```
Your status line appears at the bottom of the interface. Claude Code reloads settings automatically and runs your script as soon as you save the file.
[](#how-status-lines-work)
How status lines work
Claude Code runs your script with [JSON session data](#available-data) on stdin and displays whatever the script prints to stdout. **When it updates** Your script runs once when a session starts, including when you resume one. After that, it runs again when:
- A new assistant message arrives
- `/compact` finishes
- The permission mode changes
- Vim mode toggles
- You change the `command` in your `statusLine` settings
- A [`refreshInterval`](#manually-configure-a-status-line) timer elapses, if you set one
- A [rate-limit window](#rate-limit-usage) in the data your script last received reaches its `resets_at` time
- A warm [prompt cache](#prompt-cache-fields) in the data your script last received reaches its `expires_at` time
Claude Code debounces updates at 300ms, so rapid changes batch together and your script runs once after the changes stop. A change to the `command` itself skips the debounce: Claude Code runs the new command right away. If a new update triggers while your script is still running, Claude Code cancels the in-flight script. If you edit your script, the changes appear the next time an update trigger re-runs it. The event-driven 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`](#manually-configure-a-status-line) 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](#display-multiple-lines).
- **Colors**: use [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) like `\033[32m` for green (terminal must support them). See the [git status example](#git-status-with-colors).
- **Links**: use [OSC 8 escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#OSC) 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](#clickable-links).
**Sizing output to the terminal** Claude Code captures your script’s output instead of connecting it directly to the terminal, so `tput cols` and language-level width detection cannot read the terminal size from inside the script. Read the `COLUMNS` and `LINES` environment variables instead. Claude Code sets these to the current terminal dimensions before running your script.
The status line runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including the help menu and permission prompts.
[](#available-data)
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 is present only while the session is in a [worktree session](worktrees.md) |
| `workspace.repo.host`, `workspace.repo.owner`, `workspace.repo.name` | Repository identity parsed from the `origin` remote, for example, `"github.com"`, `"anthropics"`, `"claude-code"`. Absent outside a git repository or when no `origin` remote is configured. For a gitlab.com project nested in subgroups, `owner` is the full namespace path with slashes, such as `"group/subgroup"`. Before v2.1.260, `workspace.repo` was absent for these projects |
| `cost.total_cost_usd` | Estimated session cost in USD, computed client-side at list price unless a [`modelPricing`](settings-reference.md#modelpricing) table is in effect. May differ from your actual bill. Resets to \$0 when `/clear` starts a new session. Before v2.1.211, the total carried over after `/clear` |
| `cost.total_duration_ms` | Total wall-clock time the session has been running, in milliseconds. Accumulates across resumes and doesn’t include time while the session isn’t running |
| `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 |
| `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](#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. |
| `fast_mode` | Whether [fast mode](fast-mode.md) is enabled for the session |
| `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 |
| `rate_limits.spend_limit.used_percentage`, `rate_limits.spend_limit.resets_at` | Behind a [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway-spend-limits.md#usage-warnings-in-claude-code), the percentage used of the spend limit that applies to you, and the Unix epoch seconds when its period resets. The percentage runs from 0 to 100, or above 100 once you exceed the limit. Requires Claude Code v2.1.251 or later |
| `prompt_cache` | The session’s [prompt cache](prompt-caching.md) statistics for the main conversation: hit ratio, misses, and whether the cache is warm. See [prompt cache fields](#prompt-cache-fields) for every field. Absent until the main conversation’s first API response. Requires Claude Code v2.1.251 or later |
| `session_id` | Unique session identifier |
| `session_name` | Session name. Uses the custom name set with the `--name` flag or `/rename` when one exists, otherwise the AI-generated session title. The [default display name](sessions.md#name-your-sessions), such as `my-app-3f`, doesn’t populate this field. Absent when the session has neither a custom name nor an AI-generated title |
| `prompt_id` | UUID identifying the user prompt currently being processed. Matches the [`prompt.id` attribute on OpenTelemetry events](../13-Enterprise-Admin/monitoring-usage.md#event-correlation-attributes). Absent until the first user input. Requires Claude Code v2.1.196 or later |
| `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](interactive-mode.md#vim-editor-mode) is enabled |
| `agent.name` | Agent name when running with the `--agent` flag or agent settings configured |
| `pr.number`, `pr.url` | Open pull request for the current branch. Mirrors the PR badge in the footer. In a repository with a GitLab remote, Claude Code fills these fields from the branch’s open [merge request](interactive-mode.md#gitlab-merge-requests) instead, so `pr.number` is the merge request number. Merge request data requires Claude Code v2.1.234 or later. Absent when not in a git repository, until a pull request or merge request is found, or once it merges or closes |
| `pr.review_state` | Review status of the open PR: `approved`, `pending`, `changes_requested`, or `draft`. May be independently absent even when `pr` is present |
| `pr.kind` | `mr` when `pr` describes a [GitLab merge request](interactive-mode.md#gitlab-merge-requests). Absent for GitHub pull requests, so scripts written before this field keep working. For a merge request, Claude Code sets `review_state` to `approved` when GitLab reports it mergeable, `pending` for any other open state, and `draft` for a draft. Requires Claude Code v2.1.234 or later |
| `worktree.name` | Name of the active worktree. Present only while the session is in a [worktree session](worktrees.md) |
| `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:
```python
{
"cwd": "/current/working/directory",
"session_id": "abc123...",
"session_name": "my-session",
"prompt_id": "550e8400-e29b-41d4-a716-446655440000",
"transcript_path": "/path/to/transcript.jsonl",
"model": {
"id": "claude-opus-5-5",
"display_name": "Opus"
},
"workspace": {
"current_dir": "/current/working/directory",
"project_dir": "/original/project/directory",
"added_dirs": [],
"git_worktree": "feature-xyz",
"repo": {
"host": "github.com",
"owner": "anthropics",
"name": "claude-code"
}
},
"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,
"prompt_cache": {
"warm": true,
"caching_observed": true,
"ttl": "1h",
"expires_at": 1738429200,
"requests": 14,
"misses": 2,
"expected_rebuilds": 1,
"hit_ratio": 0.91,
"cache_write_tokens": 352000,
"miss_recache_tokens": 310200,
"last_miss_at": 1738425230,
"last_miss_cause": {
"causes": ["tools_changed"],
"tools_added": 2,
"tools_removed": 0
},
"miss_causes": {
"tools_changed": 2
},
"recache_tokens_if_cold": 45000
},
"fast_mode": 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
},
"spend_limit": {
"used_percentage": 62.8,
"resets_at": 1740787200
}
},
"vim": {
"mode": "NORMAL"
},
"agent": {
"name": "security-reviewer"
},
"pr": {
"number": 1234,
"url": "https://github.com/anthropics/claude-code/pull/1234",
"review_state": "pending"
},
"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 when a custom name has been set with `--name` or `/rename`, or once an AI-generated session title exists. The default display name, such as `my-app-3f`, doesn’t populate it
- `prompt_id`: appears only after the first user input
- `workspace.git_worktree`: appears only when the current directory is inside a linked git worktree
- `workspace.repo`: appears only inside a git repository with an `origin` remote configured
- `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
- `pr`: appears only while an open PR or GitLab merge request is found for the current branch, and is removed once it merges or closes. `pr.review_state` and `pr.kind` may be independently absent
- `worktree`: appears only while the session is in a [worktree session](worktrees.md). When present, `branch` and `original_branch` may also be absent for hook-based worktrees
- `rate_limits`: appears only for claude.ai Pro and Max subscribers, or behind a Claude apps gateway that sets a spend limit for you, and only after the first API response in the session. Each window (`five_hour`, `seven_day`, `spend_limit`) may be independently absent, and Claude Code drops a window once its `resets_at` time passes. Use `jq -r '.rate_limits.five_hour.used_percentage // empty'` to handle absence gracefully.
- `prompt_cache`: appears after the main conversation’s first API response. See [prompt cache fields](#prompt-cache-fields)
**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)
Context window fields
The `context_window` object describes the live context window from the most recent API response.
- **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
For what the cache fields mean and how they’re billed, see [check cache performance](prompt-caching.md#check-cache-performance). 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.
[](#prompt-cache-fields)
Prompt cache fields
The `prompt_cache` object summarizes how the session’s main conversation is using the [prompt cache](prompt-caching.md). Claude Code computes it from the cache token counts in the API’s responses, so it works on every provider. The object appears after the main conversation’s first API response. Claude Code doesn’t count subagent requests in these statistics. Requires Claude Code v2.1.251 or later. The table lists each field with its meaning. Timestamps are Unix epoch seconds, the same unit as `rate_limits.*.resets_at`. A short status line usually shows one or two of these; `warm` and `hit_ratio` summarize the cache state most directly.
| Field | Description |
|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `warm` | Whether the cached prefix is still within its TTL. `false` when the last response reported no cache tokens, even while `caching_observed` is `true` |
| `caching_observed` | Whether any response this session reported cache tokens. `false` means prompt caching is off, or your provider or gateway doesn’t report it |
| `ttl` | [Cache lifetime](prompt-caching.md#cache-lifetime) of the current cached prefix: `"5m"` or `"1h"` |
| `expires_at` | When the cached prefix leaves its TTL and goes cold, in epoch seconds. `null` when the last response reported no cache tokens |
| `requests` | API requests recorded for the main conversation this session |
| `misses` | Requests that re-processed content the cache already held: more than 5% and at least 2,000 tokens of what the request could have read from cache, with no compaction or tool-result clearing to explain the shortfall in cache reads |
| `expected_rebuilds` | Cache rebuilds that followed a compaction or a clearing of old tool results |
| `hit_ratio` | Cache read tokens as a fraction of all input tokens this session, from 0 to 1. The denominator counts cache reads, cache writes, and uncached input. `null` while those counts are all zero |
| `cache_write_tokens` | All tokens written to the cache this session, the first request’s initial write included |
| `miss_recache_tokens` | Tokens written to the cache by the requests counted as misses |
| `last_miss_at` | When the last miss happened, in epoch seconds. `null` while the session has no misses |
| `last_miss_cause` | What Claude Code identified as the likely cause of the last miss, described under [Last miss cause](#last-miss-cause). Requires Claude Code v2.1.260 or later |
| `miss_causes` | How many of this session’s diagnosed misses had each cause, keyed by the same cause names as `last_miss_cause`. Requires Claude Code v2.1.260 or later |
| `recache_tokens_if_cold` | Tokens the next request re-caches if the cache has gone cold by then. `null` right after a compaction or a clearing of old tool results, until the next request records the rewritten conversation’s size |
Claude Code shows the same statistics in the terminal, on the [`/usage` command’s `Prompt cache (main)` line](../17-Billing-Plans/costs.md#prompt-cache-statistics).
[](#last-miss-cause)
Last miss cause
The `last_miss_cause` object reports what Claude Code identified as the likely cause of the most recent miss. Its `causes` array holds one or more cause names, such as `tools_changed`, `system_prompt_changed`, `ttl_expired_5m`, or `likely_server_side`. The object is `null` until the session’s first miss, and again whenever Claude Code couldn’t identify a cause for the most recent miss. Requires Claude Code v2.1.260 or later. Two causes add counts to the object:
- `tools_added` and `tools_removed`: with `tools_changed`, how many tools were added to or removed from the request
- `system_char_delta`: with `system_prompt_changed`, the change in the system prompt’s length, in characters
[](#examples)
Examples
These examples show common status line patterns. To use any example:
1. Save the script to a file like `~/.claude/statusline.sh` (or `.py`/`.js`)
2. Make it executable: `chmod +x ~/.claude/statusline.sh`
3. Add the path to your [settings](#manually-configure-a-status-line)
The Bash examples use [`jq`](https://jqlang.org/) to parse JSON. Python and Node.js have built-in JSON parsing.
[](#context-window-usage)
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
```python
#!/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%"
```
```python
#!/usr/bin/env python3
import json, sys
# json.load reads and parses stdin in one step
data = json.load(sys.stdin)
model = data['model']['display_name']
# "or 0" handles null values
pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)
# String multiplication builds the bar
filled = pct * 10 // 100
bar = '▓' * filled + '░' * (10 - filled)
print(f"[{model}] {bar} {pct}%")
```
```python
#!/usr/bin/env node
// Node.js reads stdin asynchronously with events
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
// Optional chaining (?.) safely handles null fields
const pct = Math.floor(data.context_window?.used_percentage || 0);
// String.repeat() builds the bar
const filled = Math.floor(pct * 10 / 100);
const bar = '▓'.repeat(filled) + '░'.repeat(10 - filled);
console.log(`[${model}] ${bar} ${pct}%`);
});
```
[](#git-status-with-colors)
Git status with colors
Show git branch with color-coded indicators for staged and modified files. This script uses [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 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
```python
#!/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
```
```python
#!/usr/bin/env python3
import json, sys, subprocess, os
data = json.load(sys.stdin)
model = data['model']['display_name']
directory = os.path.basename(data['workspace']['current_dir'])
GREEN, YELLOW, RESET = '\033[32m', '\033[33m', '\033[0m'
try:
subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)
branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()
staged_output = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()
modified_output = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()
staged = len(staged_output.split('\n')) if staged_output else 0
modified = len(modified_output.split('\n')) if modified_output else 0
git_status = f"{GREEN}+{staged}{RESET}" if staged else ""
git_status += f"{YELLOW}~{modified}{RESET}" if modified else ""
print(f"[{model}] 📁 {directory} | 🌿 {branch} {git_status}")
except:
print(f"[{model}] 📁 {directory}")
```
```python
#!/usr/bin/env node
const { execSync } = require('child_process');
const path = require('path');
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const dir = path.basename(data.workspace.current_dir);
const GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RESET = '\x1b[0m';
try {
execSync('git rev-parse --git-dir', { stdio: 'ignore' });
const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
let gitStatus = staged ? `${GREEN}+${staged}${RESET}` : '';
gitStatus += modified ? `${YELLOW}~${modified}${RESET}` : '';
console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} ${gitStatus}`);
} catch {
console.log(`[${model}] 📁 ${dir}`);
}
});
```
[](#cost-and-duration-tracking)
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 the total time the session has been running, 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
```python
#!/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"
```
```python
#!/usr/bin/env python3
import json, sys
data = json.load(sys.stdin)
model = data['model']['display_name']
cost = data.get('cost', {}).get('total_cost_usd', 0) or 0
duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0
duration_sec = duration_ms // 1000
mins, secs = duration_sec // 60, duration_sec % 60
print(f"[{model}] 💰 ${cost:.2f} | ⏱️ {mins}m {secs}s")
```
```python
#!/usr/bin/env node
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const cost = data.cost?.total_cost_usd || 0;
const durationMs = data.cost?.total_duration_ms || 0;
const durationSec = Math.floor(durationMs / 1000);
const mins = Math.floor(durationSec / 60);
const secs = durationSec % 60;
console.log(`[${model}] 💰 $${cost.toFixed(2)} | ⏱️ ${mins}m ${secs}s`);
});
```
[](#display-multiple-lines)
Display multiple lines
Your script can output multiple lines to create a richer display.
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
```python
#!/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"
```
```python
#!/usr/bin/env python3
import json, sys, subprocess, os
data = json.load(sys.stdin)
model = data['model']['display_name']
directory = os.path.basename(data['workspace']['current_dir'])
cost = data.get('cost', {}).get('total_cost_usd', 0) or 0
pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)
duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0
CYAN, GREEN, YELLOW, RED, RESET = '\033[36m', '\033[32m', '\033[33m', '\033[31m', '\033[0m'
bar_color = RED if pct >= 90 else YELLOW if pct >= 70 else GREEN
filled = pct // 10
bar = '█' * filled + '░' * (10 - filled)
mins, secs = duration_ms // 60000, (duration_ms % 60000) // 1000
try:
branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True, stderr=subprocess.DEVNULL).strip()
branch = f" | 🌿 {branch}" if branch else ""
except:
branch = ""
print(f"{CYAN}[{model}]{RESET} 📁 {directory}{branch}")
print(f"{bar_color}{bar}{RESET} {pct}% | {YELLOW}${cost:.2f}{RESET} | ⏱️ {mins}m {secs}s")
```
```python
#!/usr/bin/env node
const { execSync } = require('child_process');
const path = require('path');
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const dir = path.basename(data.workspace.current_dir);
const cost = data.cost?.total_cost_usd || 0;
const pct = Math.floor(data.context_window?.used_percentage || 0);
const durationMs = data.cost?.total_duration_ms || 0;
const CYAN = '\x1b[36m', GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RED = '\x1b[31m', RESET = '\x1b[0m';
const barColor = pct >= 90 ? RED : pct >= 70 ? YELLOW : GREEN;
const filled = Math.floor(pct / 10);
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
const mins = Math.floor(durationMs / 60000);
const secs = Math.floor((durationMs % 60000) / 1000);
let branch = '';
try {
branch = execSync('git branch --show-current', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
branch = branch ? ` | 🌿 ${branch}` : '';
} catch {}
console.log(`${CYAN}[${model}]${RESET} 📁 ${dir}${branch}`);
console.log(`${barColor}${bar}${RESET} ${pct}% | ${YELLOW}$${cost.toFixed(2)}${RESET} | ⏱️ ${mins}m ${secs}s`);
});
```
[](#clickable-links)
Clickable links
This example creates a clickable link to your GitHub repository. 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
```python
#!/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
```
```python
#!/usr/bin/env python3
import json, sys, subprocess, re, os
data = json.load(sys.stdin)
model = data['model']['display_name']
# Get git remote URL
try:
remote = subprocess.check_output(
['git', 'remote', 'get-url', 'origin'],
stderr=subprocess.DEVNULL, text=True
).strip()
# Convert SSH to HTTPS format
remote = re.sub(r'^git@github\.com:', 'https://github.com/', remote)
remote = re.sub(r'\.git$', '', remote)
repo_name = os.path.basename(remote)
# OSC 8 escape sequences
link = f"\033]8;;{remote}\a{repo_name}\033]8;;\a"
print(f"[{model}] 🔗 {link}")
except:
print(f"[{model}]")
```
```python
#!/usr/bin/env node
const { execSync } = require('child_process');
const path = require('path');
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
try {
let remote = execSync('git remote get-url origin', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
// Convert SSH to HTTPS format
remote = remote.replace(/^git@github\.com:/, 'https://github.com/').replace(/\.git$/, '');
const repoName = path.basename(remote);
// OSC 8 escape sequences
const link = `\x1b]8;;${remote}\x07${repoName}\x1b]8;;\x07`;
console.log(`[${model}] 🔗 ${link}`);
} catch {
console.log(`[${model}]`);
}
});
```
[](#rate-limit-usage)
Rate limit usage
Display claude.ai subscription rate limit usage in the status line. The `rate_limits` object contains a rolling `five_hour` window and a weekly `seven_day` window. Each window provides `used_percentage`, from 0 to 100, and `resets_at`, the Unix epoch seconds when the window resets. Behind a Claude apps gateway with spend limits, `rate_limits` carries `spend_limit` with the same two fields for the spend limit that applies to you, except that its `used_percentage` can go above 100 once you exceed the limit. Requires Claude Code v2.1.251 or later. The `rate_limits` object is only present for claude.ai Pro and Max subscribers, or behind a Claude apps gateway with spend limits, and only after the first API response. Each script handles the absent field gracefully:
Bash
Python
Node.js
```python
#!/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]"
```
```python
#!/usr/bin/env python3
import json, sys
data = json.load(sys.stdin)
model = data['model']['display_name']
parts = []
rate = data.get('rate_limits', {})
five_h = rate.get('five_hour', {}).get('used_percentage')
week = rate.get('seven_day', {}).get('used_percentage')
if five_h is not None:
parts.append(f"5h: {five_h:.0f}%")
if week is not None:
parts.append(f"7d: {week:.0f}%")
if parts:
print(f"[{model}] | {' '.join(parts)}")
else:
print(f"[{model}]")
```
```python
#!/usr/bin/env node
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const parts = [];
const fiveH = data.rate_limits?.five_hour?.used_percentage;
const week = data.rate_limits?.seven_day?.used_percentage;
if (fiveH != null) parts.push(`5h: ${Math.round(fiveH)}%`);
if (week != null) parts.push(`7d: ${Math.round(week)}%`);
console.log(parts.length ? `[${model}] | ${parts.join(' ')}` : `[${model}]`);
});
```
[](#cache-expensive-operations)
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
```python
#!/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 -c %Y (Linux) or stat -f %m (macOS) prints the file's last-modified
# time. The Linux form must run first: on Linux, the macOS form prints a
# filesystem report to stdout before failing, and that output would be
# captured by the command substitution and break the arithmetic.
[ $(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || stat -f %m "$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
```
```python
#!/usr/bin/env python3
import json, sys, subprocess, os, time
data = json.load(sys.stdin)
model = data['model']['display_name']
directory = os.path.basename(data['workspace']['current_dir'])
session_id = data['session_id']
CACHE_FILE = f"/tmp/statusline-git-cache-{session_id}"
CACHE_MAX_AGE = 5 # seconds
def cache_is_stale():
if not os.path.exists(CACHE_FILE):
return True
return time.time() - os.path.getmtime(CACHE_FILE) > CACHE_MAX_AGE
if cache_is_stale():
try:
subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)
branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()
staged = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()
modified = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()
staged_count = len(staged.split('\n')) if staged else 0
modified_count = len(modified.split('\n')) if modified else 0
with open(CACHE_FILE, 'w') as f:
f.write(f"{branch}|{staged_count}|{modified_count}")
except:
with open(CACHE_FILE, 'w') as f:
f.write("||")
with open(CACHE_FILE) as f:
branch, staged, modified = f.read().strip().split('|')
if branch:
print(f"[{model}] 📁 {directory} | 🌿 {branch} +{staged} ~{modified}")
else:
print(f"[{model}] 📁 {directory}")
```
```python
#!/usr/bin/env node
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const dir = path.basename(data.workspace.current_dir);
const sessionId = data.session_id;
const CACHE_FILE = `/tmp/statusline-git-cache-${sessionId}`;
const CACHE_MAX_AGE = 5; // seconds
const cacheIsStale = () => {
if (!fs.existsSync(CACHE_FILE)) return true;
return (Date.now() / 1000) - fs.statSync(CACHE_FILE).mtimeMs / 1000 > CACHE_MAX_AGE;
};
if (cacheIsStale()) {
try {
execSync('git rev-parse --git-dir', { stdio: 'ignore' });
const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
fs.writeFileSync(CACHE_FILE, `${branch}|${staged}|${modified}`);
} catch {
fs.writeFileSync(CACHE_FILE, '||');
}
}
const [branch, staged, modified] = fs.readFileSync(CACHE_FILE, 'utf8').trim().split('|');
if (branch) {
console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} +${staged} ~${modified}`);
} else {
console.log(`[${model}] 📁 ${dir}`);
}
});
```
[](#windows-configuration)
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. Git Bash treats unquoted backslashes as escape characters, so a Windows-style path such as `C:\Users\username\script.mjs` reaches the script runner with its separators removed and the command fails without a visible error. Write file paths in the `command` string with forward slashes, as shown in the examples below. The `~` shorthand also works and expands to your Windows home directory. To run a PowerShell script as your status line, invoke it via `powershell`. This works whether Claude Code routes the command through Git Bash or PowerShell:
settings.json
statusline.ps1
```python
{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
}
}
```
```python
$input_json = $input | Out-String | ConvertFrom-Json
$cwd = $input_json.cwd
$model = $input_json.model.display_name
$used = $input_json.context_window.used_percentage
$dirname = Split-Path $cwd -Leaf
if ($used) {
Write-Host "$dirname [$model] ctx: $used%"
} else {
Write-Host "$dirname [$model]"
}
```
Or, when Git Bash is installed, run a Bash script directly:
settings.json
statusline.sh
```python
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}
```
```python
#!/usr/bin/env bash
input=$(cat)
cwd=$(echo "$input" | grep -o '"cwd":"[^"]*"' | cut -d'"' -f4)
model=$(echo "$input" | grep -o '"display_name":"[^"]*"' | cut -d'"' -f4)
dirname="${cwd##*[/\\]}"
echo "$dirname [$model]"
```
[](#subagent-status-lines)
Subagent status lines
The `subagentStatusLine` setting renders a custom row body for each [subagent](../09-Agents-Patterns/sub-agents.md) shown in the agent panel below the prompt. Use it to replace the default `name · description · token count` row with your own formatting.
```python
{
"subagentStatusLine": {
"type": "command",
"command": "~/.claude/subagent-statusline.sh"
}
}
```
The command runs once per refresh tick and receives all visible subagent rows as a single JSON object on stdin. The input includes the [base hook fields](../07-Hooks/hooks.md#common-input-fields), a `columns` field with the usable row width, and a `tasks` array. Each task has `id`, `name`, `type`, `status`, `description`, `label`, `startTime`, `model`, `effort`, `contextWindowSize`, `tokenCount`, `tokenSamples`, and `cwd`. The per-task `model` field is the resolved model ID the task runs on. `contextWindowSize` is that model’s context window in tokens, computed the same way as the main status line’s `context_window.context_window_size`, so you can render a per-row percentage from `tokenCount`. Both fields require Claude Code v2.1.205 or later and are omitted for a task whose model isn’t resolved yet. The per-task `effort` field is the reasoning effort set for that subagent, in its [definition frontmatter](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) or on the individual invocation. The value is either one of the effort level strings `low`, `medium`, `high`, `xhigh`, or `max`, or a numeric token budget. The field reports the configured value as written: if the model doesn’t support that level, the effort Claude Code actually applies may differ. The field requires Claude Code v2.1.214 or later and is absent when the subagent inherits the session’s effort level. 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, `disableAllHooks`, and [`allowManagedHooksOnly`](settings-reference.md#allowmanagedhooksonly) gates that apply to `statusLine` apply here. Plugins can ship a default `subagentStatusLine` in their [`settings.json`](../08-Plugins-Skills/plugins-reference.md#standard-layout), but unlike hooks, plugin values don’t run under `allowManagedHooksOnly` even when the plugin is force-enabled in managed settings `enabledPlugins`.
[](#tips)
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](#cache-expensive-operations) for how to handle this.
Community projects like [ccstatusline](https://github.com/sirmalloc/ccstatusline) and [starship-claude](https://github.com/martinemde/starship-claude) provide pre-built configurations with themes and additional features.
[](#troubleshooting)
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
- On Windows with Git Bash installed, backslashes in the `command` path are likely being consumed as escape characters before the script runs. Use forward slashes in the path. See [Windows configuration](#windows-configuration).
- If `disableAllHooks` is `true` outside managed settings after [settings precedence](../07-Hooks/hooks.md#disable-or-remove-hooks) applies, Claude Code runs only a `statusLine` from managed settings, and with no managed `statusLine` the status line is disabled. Remove the setting, or set it to `false` in the file that sets it, to re-enable. See [`disableAllHooks`](settings-reference.md#disableallhooks).
- If your organization sets `allowManagedHooksOnly` in managed settings, your custom status line disappears without warning: you can only get a status line from a `statusLine` value in those managed settings. See [what runs under `allowManagedHooksOnly`](settings-reference.md#what-runs-under-allowmanagedhooksonly) for the full behavior, and ask your administrator whether this setting applies to you.
- Run `claude --debug` to log your script’s stderr on every status line invocation, and its exit code on the first 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
- The status line reports the counts from the last API response, while `/context` adds an estimate for messages added since that response, so `/context` can read higher until the next response
**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. Set the `FORCE_HYPERLINK` environment variable to override detection before launching Claude Code:
``` shiki
FORCE_HYPERLINK=1 claude
```
In PowerShell, set the variable in the current session first:
``` shiki
$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**
- Because `statusLine` executes a shell command, Claude Code runs it under the same [workspace trust rule as hooks in settings files](permissions.md#what-runs-before-you-trust-a-folder). Accepting the dialog for the folder, or for a parent directory whose trust extends to it, is enough.
- Until then, the status line stays blank, and `claude --debug` logs `Status line command skipped: workspace trust not accepted`. Restart Claude Code and accept the trust dialog 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** Outside [fullscreen rendering](fullscreen.md), Claude Code shows notifications on the same row as your status line. In fullscreen rendering, Claude Code gives notifications a row of their own.
- System notifications like MCP server errors and auto-updates display on the right side of the row. 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
---
## Configure your terminal for Claude Code - Claude Code Docs
Source: https://code.claude.com/docs/en/terminal-config
Path: 02-Claude-Code-CLI/terminal-config.md
## On this page
- [Enter multiline prompts](#enter-multiline-prompts)
- [Enable Option key shortcuts on macOS](#enable-option-key-shortcuts-on-macos)
- [Get a terminal bell or notification](#get-a-terminal-bell-or-notification)
- [Play a sound with a Notification hook](#play-a-sound-with-a-notification-hook)
- [Configure tmux](#configure-tmux)
- [Fix Backspace deleting a whole word on Windows](#fix-backspace-deleting-a-whole-word-on-windows)
- [Match the color theme](#match-the-color-theme)
- [Create a custom theme](#create-a-custom-theme)
- [Switch to fullscreen rendering](#switch-to-fullscreen-rendering)
- [Cap response width in wide terminals](#cap-response-width-in-wide-terminals)
- [Paste large content](#paste-large-content)
- [How Claude treats pasted text](#how-claude-treats-pasted-text)
- [Delete and restore a collapsed paste](#delete-and-restore-a-collapsed-paste)
- [Recall a prompt that had pasted text](#recall-a-prompt-that-had-pasted-text)
- [Edit prompts with Vim keybindings](#edit-prompts-with-vim-keybindings)
- [Related resources](#related-resources)
Interface
# Configure your terminal for Claude Code
Copy pageCopy page
Fix Shift+Enter for newlines, get a terminal bell when Claude finishes, configure tmux, match the color theme, and enable Vim mode in the Claude Code CLI.
Copy pageCopy page
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](#enter-multiline-prompts)
- [Option-key shortcuts do nothing on macOS](#enable-option-key-shortcuts-on-macos)
- [No sound or alert when Claude finishes](#get-a-terminal-bell-or-notification)
- [You run Claude Code inside tmux](#configure-tmux)
- [Backspace deletes a whole word on Windows](#fix-backspace-deleting-a-whole-word-on-windows)
- [Display flickers or scrollback jumps](#switch-to-fullscreen-rendering)
- [You want Vim keys in the prompt](#edit-prompts-with-vim-keybindings)
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](keybindings.md) instead.
[](#enter-multiline-prompts)
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 |
| Other terminals that support the kitty keyboard protocol, such as foot and Alacritty 0.16 or later | Works without setup. Requires Claude Code v2.1.269 or later |
| VS Code, Cursor, Devin Desktop, Alacritty before 0.16, 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, Devin Desktop, Alacritty before 0.16, and Zed, `/terminal-setup` writes a Shift+Enter keybinding into the terminal’s configuration file. On the first run you see a confirmation such as `Installed VSCode terminal Shift+Enter key binding`. Existing bindings 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. In VS Code, Cursor, and Devin Desktop, `/terminal-setup` also updates two editor settings: it sets `terminal.integrated.gpuAcceleration` to `"off"` to prevent garbled text in the integrated terminal, and it sets `terminal.integrated.mouseWheelScrollSensitivity` for smoother scrolling in [fullscreen mode](fullscreen.md). To undo the GPU acceleration change, set it back to `"auto"` and reload the editor window. In Zed, `/terminal-setup` updates your `keymap.json` in place:
- If the keymap already has bindings and none of them is a Terminal `shift-enter`, Claude Code first backs it up to a copy in the same directory, such as `keymap.json.1a2b3c4d.bak`, then merges the Shift+Enter binding into your keymap, keeping your other keybindings and comments
- If Claude Code can’t read or parse the keymap, can’t back it up, or can’t verify the merged result, it [leaves the file unchanged and prints the keybinding block to add yourself](errors.md#terminal-setup-left-your-zed-keymap-unchanged)
If you are running inside tmux, Shift+Enter also requires the [tmux configuration below](#configure-tmux) 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](keybindings.md).
[](#enable-option-key-shortcuts-on-macos)
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 terminal setup prompt, this is already done. That prompt runs `/terminal-setup` for you, which enables Option as Meta and turns off the audible bell in your Apple Terminal profile.In [screen reader mode](accessibility.md), `/terminal-setup` leaves the bell setting unchanged so the terminal bell stays audible. Before v2.1.211, `/terminal-setup` turned the bell off even in screen reader mode. If an earlier run turned the bell off, turn it back on under Settings → Profiles → Advanced → “Audible bell”.
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)
Get a terminal bell or notification
When Claude finishes a task or pauses for a permission prompt, and you appear to be away from the terminal, it fires a notification event. See [when each notification type fires](../07-Hooks/hooks.md#notification) for the exact timing. 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`](settings-reference.md#preferrednotifchannel) to `"terminal_bell"` to ring the terminal bell instead, or configure a [Notification hook](#play-a-sound-with-a-notification-hook) for a custom sound or command. The following settings entry turns on the terminal bell:
~/.claude/settings.json
```python
{
"preferredNotifChannel": "terminal_bell"
}
```
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](#configure-tmux).
[](#play-a-sound-with-a-notification-hook)
Play a sound with a Notification hook
In any terminal you can configure a [Notification hook](../07-Hooks/hooks-guide.md#get-notified-when-claude-needs-input) 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
```python
{
"hooks": {
"Notification": [
{
"hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" }]
}
]
}
}
```
[](#configure-tmux)
Configure tmux
When Claude Code runs inside tmux, by default Shift+Enter submits instead of inserting a newline, and desktop notifications and the [progress bar](settings-reference.md#terminalprogressbarenabled) 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
```python
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.
[](#fix-backspace-deleting-a-whole-word-on-windows)
Fix Backspace deleting a whole word on Windows
On Windows, Claude Code reads a Backspace that arrives as `^H` as Ctrl+Backspace, which [deletes the previous word](interactive-mode.md#text-editing), except when `TERM_PROGRAM` is `mintty` or `TERM` is `cygwin`. On macOS and Linux, Claude Code reads it as plain Backspace. If each press of Backspace deletes a whole word, your terminal sends `^H` for plain Backspace. Set [`CLAUDE_CODE_BS_AS_CTRL_BACKSPACE=0`](env-vars.md). Backspace and Ctrl+H then erase one character each. If Ctrl+Backspace erases only one character on macOS or Linux because your terminal sends `^H` for it, set the variable to `1` instead.
[](#match-the-color-theme)
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](statusline.md) that shows the current model, working directory, git branch, or other context.
[](#create-a-custom-theme)
Create a custom theme
In addition to the built-in presets, `/theme` lists any custom themes you have defined and any themes contributed by installed [plugins](../08-Plugins-Skills/plugins-components.md#themes-and-output-styles). 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
```python
{
"name": "Dracula",
"base": "dark",
"overrides": {
"claude": "#bd93f9",
"error": "#ff5555",
"success": "#50fa7b"
}
}
```
Claude Code watches `~/.claude/themes/` and reloads when a file is added or changed, so edits made in your editor apply to a running session without a restart. If the `~/.claude/themes/` folder itself didn’t exist when Claude Code started, restart once after creating your first theme file. After that, changes apply 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 message background.
~/.claude/themes/midnight.json
```python
{
"name": "Midnight",
"base": "dark",
"overrides": {
"claude": "#a78bfa",
"planMode": "#38bdf8",
"diffAdded": "#14532d",
"diffRemoved": "#7f1d1d",
"userMessageBackground": "#1e1b4b"
}
}
```
[](#text-and-accent-colors)
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)
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 indicator |
| `merged` | Merged pull request status |
[](#input-box-and-mode-indicators)
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 |
| `planMode` | Plan mode accent, plan messages, and plan-mode dialogs |
| `autoAccept` | Accept-edits mode accent |
| `bashBorder` | Input box border when entering a `!` shell command |
| `ide` | IDE connection indicator |
| `fastMode` | Fast mode indicator |
| `effortUltra` | The `ultracode` tag on the input box border while [ultracode](model-config.md#adjust-effort-level) is on. Your override of this color takes effect on Claude Code v2.1.239 or later |
[](#diff-rendering)
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 added lines in the dimmed diff shown after you reject an edit |
| `diffRemovedDimmed` | Background of removed lines in the dimmed diff shown after you reject an edit |
| `diffAddedWord` | Word-level highlight within an added line |
| `diffRemovedWord` | Word-level highlight within a removed line |
[](#fullscreen-mode)
Fullscreen mode
Claude Code paints `userMessageBackground`, `bashMessageBackgroundColor`, and `memoryBackgroundColor` in both the default and fullscreen renderers. It uses `userMessageBackgroundHover` and `selectionBg` only in [fullscreen rendering mode](fullscreen.md).
| Token | Controls |
|:-----------------------------|:--------------------------------------------------------------|
| `userMessageBackground` | Background behind your messages in the transcript |
| `userMessageBackgroundHover` | Background behind a message while hovered or expanded |
| `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)
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)
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](../09-Agents-Patterns/sub-agents.md) 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.Claude Code renders the [`ultrathink`](model-config.md#use-ultrathink-for-one-off-deep-reasoning) keyword in the prompt input 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)
Switch to fullscreen rendering
In [screen reader mode](accessibility.md), this section doesn’t apply. Claude Code always renders as plain scrolling text except in attached [background sessions](../09-Agents-Patterns/agent-view.md), and if you run `/tui fullscreen` in any other session, Claude Code prints an explanation instead of switching. If the display flickers or the scroll position jumps while Claude is working, switch to [fullscreen rendering mode](fullscreen.md). 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](fullscreen.md#search-and-review-the-conversation) for how to search and copy. If flicker is the only problem and your terminal supports synchronized output but isn’t auto-detected, such as Emacs `eat`, set [`CLAUDE_CODE_FORCE_SYNC_OUTPUT=1`](env-vars.md) to stop the flicker without changing renderers. Run `/tui fullscreen` to switch and save the preference. Your conversation relaunches intact and future sessions start in fullscreen unless a [fullscreen start fails](fullscreen.md#fullscreen-renderer-didnt-finish-starting). You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:
Bash and Zsh
PowerShell
~/.claude/settings.json
```python
CLAUDE_CODE_NO_FLICKER=1 claude
```
```python
$env:CLAUDE_CODE_NO_FLICKER = "1"; claude
```
```python
{
"env": {
"CLAUDE_CODE_NO_FLICKER": "1"
}
}
```
[](#cap-response-width-in-wide-terminals)
Cap response width in wide terminals
In a wide terminal, each line of prose in Claude’s responses runs the full width of the window. To wrap the prose at a set number of columns instead, set [`maxProseWidth`](settings-reference.md#maxprosewidth) in your settings.
[](#paste-large-content)
Paste large content
When you paste more than 800 characters or more than three lines into the prompt, Claude Code collapses the input to a placeholder such as `[Pasted text #1 +120 lines]` so the input box stays usable, and still sends the full content when you submit. 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. The conversation transcript stays readable and Claude can refer to the file by path in later turns. The VS Code integrated terminal can also drop characters from very large pastes before they reach Claude Code, so use a file there. If the paste carries [invisible Unicode characters](interactive-mode.md#invisible-characters-in-prompts), Claude Code removes them when you press Enter and puts the cleaned prompt back in the input box for you to send with another Enter.
[](#how-claude-treats-pasted-text)
How Claude treats pasted text
When you submit, Claude sees the content behind each `[Pasted text #N]` placeholder marked as text you pasted from somewhere else rather than typed. Claude is told that a paste can contain instructions you didn’t write, and to follow instructions inside it only where the message you typed asks it to. In sessions that don’t [fetch feature flags](env-vars.md#features-that-need-feature-flag-fetching), pastes aren’t marked.
[](#delete-and-restore-a-collapsed-paste)
Delete and restore a collapsed paste
When you delete with a word or line shortcut such as `Ctrl+W` or `Ctrl+K`, or with a vim delete through an `f`/`t` motion such as `df]`, and the deleted range reaches inside a `[Pasted text #N]` placeholder, Claude Code removes the placeholder whole. To restore it, paste the deletion back with [`Ctrl+Y`](interactive-mode.md#text-editing) after a word or line shortcut, or with [`p` in NORMAL mode](interactive-mode.md#editing-normal-mode) after a vim delete.
[](#recall-a-prompt-that-had-pasted-text)
Recall a prompt that had pasted text
Claude Code keeps the content behind each `[Pasted text #N]` placeholder under `~/.claude/paste-cache/`, so when you recall a prompt from [command history](interactive-mode.md#command-history) and resubmit it, the full pasted content is sent again, including in a later session. Cache files older than [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays) are deleted under the [retention sweep rules](claude-directory.md#cleaned-up-automatically), so a recalled prompt can reference pasted text that no longer exists. When you submit such a prompt, Claude Code never sends the literal `[Pasted text #N]` string, and shows a notification naming the missing paste:
- In a plain prompt with text remaining, Claude Code removes the placeholder and sends the remaining text.
- In a [shell mode](interactive-mode.md#shell-mode-with-prefix) command or a `/` command, where the removal would change what runs, and in any prompt the removal leaves empty, Claude Code cancels the submission and keeps the original text in the input, with the placeholder still in it. Delete the placeholder or edit the command, then resubmit.
[](#edit-prompts-with-vim-keybindings)
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`](settings-reference.md#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](interactive-mode.md#vim-editor-mode) for the full key table. Vim motions aren’t remappable through the keybindings file. To map a two-key INSERT-mode sequence such as `jj` to Escape, set [`vimInsertModeRemaps`](interactive-mode.md#remap-insert-mode-key-sequences) in your user settings. 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)
Related resources
- [Interactive mode](interactive-mode.md): full keyboard shortcut reference and the Vim key table
- [Keybindings](keybindings.md): remap any Claude Code shortcut, including Enter and Shift+Enter
- [Fullscreen rendering](fullscreen.md): details on scrolling, search, and copy in fullscreen mode
- [Hooks guide](../07-Hooks/hooks-guide.md): more Notification hook examples for Linux and Windows
- [Troubleshooting](troubleshooting.md): fixes for issues outside terminal configuration
---
## Terminal guide for new users - Claude Code Docs
Source: https://code.claude.com/docs/en/terminal-guide
Path: 02-Claude-Code-CLI/terminal-guide.md
## On this page
- [macOS and Linux](#macos-and-linux)
- [Windows](#windows)
- [What’s next?](#what%E2%80%99s-next)
- [Build something](#build-something)
- [Work with files on your computer](#work-with-files-on-your-computer)
- [Ask questions](#ask-questions)
- [Other ways to use Claude Code](#other-ways-to-use-claude-code)
- [Learn more](#learn-more)
- [Troubleshooting](#troubleshooting)
- [macOS and Linux troubleshooting](#macos-and-linux-troubleshooting)
- [Windows troubleshooting](#windows-troubleshooting)
# Terminal guide for new users
Copy pageCopy page
A step-by-step guide to installing Claude Code for first-time terminal users on macOS, Linux, and Windows.
Copy pageCopy page
You can use Claude Code even if you’ve never used a terminal before. This guide walks you through opening a terminal, installing Claude Code, and your first interactions.
- [macOS and Linux](#macos-and-linux)
- [Windows](#windows)
Don’t want to use the terminal? The Claude Code desktop app lets you skip the terminal entirely. Download it for [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs) or [Windows](https://claude.com/download?utm_source=claude_code&utm_medium=docs), then see the [Desktop quickstart](../16-Mobile-Desktop/desktop-quickstart.md) to get started. On Linux, install the app with apt by following the [Linux install instructions](../16-Mobile-Desktop/desktop-linux.md).
[](#macos-and-linux)
macOS and Linux
Follow these steps to install and start Claude Code from a macOS or Linux terminal. Claude Code requires macOS 13.0 or later. See the [system requirements](../01-Getting-Started/setup.md#system-requirements) for supported Linux distributions.
1
Open a terminal
**macOS**: Press `Cmd + Space` to open Spotlight Search, type `Terminal`, and press `Enter`.**Linux**: Open your terminal app. On most distributions, press `Ctrl + Alt + T` or search for “Terminal” in your application menu.A window will appear with a blinking cursor. This is your terminal, where you type commands.
2
Install Claude Code
Copy this line, paste it into your terminal (`Cmd + V` on macOS, `Ctrl + Shift + V` on Linux), and press `Enter`:
```python
curl -fsSL https://claude.ai/install.sh | bash
```
This downloads and runs the Claude Code installer from claude.ai. You’ll see text scrolling as it works. When it’s done, you’ll see “Claude Code successfully installed!” If you see an error instead, check the [troubleshooting section](#macos-and-linux-troubleshooting) below.
3
Start Claude Code
Type `claude` and press `Enter`:
```python
claude
```
If you see `command not found: claude`, the install directory isn’t on your PATH yet. Follow the [‘command not found: claude’](#macos-and-linux-troubleshooting) fix below, then open a new terminal window and try again.You’ll be prompted to [log in](../13-Enterprise-Admin/iam.md) with your Claude account. Follow the on-screen instructions. A browser window will open for you to sign in.
4
Start using Claude Code
Once logged in, you can start asking Claude questions about your code or anything else. Claude Code runs entirely in text. You type messages and press `Enter` to send them. A few things to know:
- You can’t click on things in the terminal. Use the arrow keys to move around.
- Press `Esc` to interrupt Claude if it’s running.
- Type `exit` or press `Ctrl + D` twice on an empty prompt to leave Claude Code.
- Type `/help` to see available commands.
------------------------------------------------------------------------
[](#windows)
Windows
Follow these steps to optionally install Git for Windows, set up PowerShell, and start Claude Code on Windows. Claude Code requires Windows 10 version 1809 or later. See the [system requirements](../01-Getting-Started/setup.md#system-requirements) for full details.
1
Install Git for Windows (optional)
Git for Windows provides Git Bash, which enables the Bash tool. Without it, Claude Code uses PowerShell instead. You won’t need to learn Git yourself.If you don’t already have it:
1. Go to [git-scm.com/downloads/win](https://git-scm.com/downloads/win) and download the installer
2. Run the installer. Click Next on each screen to accept the defaults. The installer has many screens, but you don’t need to change anything.
3. If it asks you to choose an editor, keep the default and click Next.
4. When you see “Adjusting your PATH environment,” keep the recommended option selected.
Already have Git? You can skip this step. If you’re not sure, install it anyway. Reinstalling won’t cause problems.
2
Open PowerShell
PowerShell is Windows’ built-in terminal for typing commands. It comes pre-installed on every Windows computer.Press `Win + X` and select **Windows PowerShell** (or **Terminal**) from the menu. A window with a blinking cursor will appear. This is where you’ll type commands.
Windows has two command-line programs: PowerShell and CMD. They look similar but use different commands. Make sure you’re in PowerShell for the next step.How to tell which one you’re in:
- **PowerShell**: shows `PS C:\Users\YourName>` at the start of each line
- **CMD**: shows `C:\Users\YourName>` without the `PS`
3
Install Claude Code
Copy this line, paste it into PowerShell with `Ctrl + V` or right-click, and press `Enter`:
```python
irm https://claude.ai/install.ps1 | iex
```
This downloads and runs the Claude Code installer. `irm` fetches the file and `iex` runs it. You’ll see text scrolling as it works. When it’s done, you’ll see “Claude Code successfully installed!” If you see an error instead, check the [troubleshooting section](#windows-troubleshooting) below.
If you’re in CMD instead of PowerShell, use this command:
```python
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
4
Start Claude Code
Run `claude`. If PowerShell says `'claude' is not recognized`, the install directory isn’t on your PATH yet. Follow the [‘claude is not recognized’](#windows-troubleshooting) fix below, then open a new PowerShell window and try again.
```python
claude
```
You’ll be prompted to [log in](../13-Enterprise-Admin/iam.md) with your Claude account. Follow the on-screen instructions. A browser window will open for you to sign in.
5
Start using Claude Code
Once logged in, you can start asking Claude questions about your code or anything else. Claude Code runs entirely in text. You type messages and press `Enter` to send them. A few things to know:
- You can’t click on things in the terminal. Use the arrow keys to move around.
- Press `Esc` to interrupt Claude if it’s running.
- Type `exit` or press `Ctrl + D` twice on an empty prompt to leave Claude Code.
- Type `/help` to see available commands.
------------------------------------------------------------------------
[](#what’s-next)
What’s next?
Once you see the Claude Code welcome screen, you’re ready to go. You don’t need to know how to code. Describe what you want in plain English, and Claude writes the code for you.
[](#build-something)
Build something
Claude can create projects from a description:
```python
make me a simple webpage that says hello world
```
Before creating or changing files, Claude asks for your permission. Press `Enter` to choose **Yes** and approve. Once Claude creates the files, double-click the HTML file to open it in your browser.
[](#work-with-files-on-your-computer)
Work with files on your computer
Claude can read and organize files you already have:
```python
look at the screenshots on my Desktop and rename them based on what's in each image
```
[](#ask-questions)
Ask questions
Claude can explain things, help you learn, or plan out a project:
```python
I want to build a personal budget tracker. What would I need?
```
If you don’t have a project yet, that’s fine. Claude can help you start a new one.
[](#other-ways-to-use-claude-code)
Other ways to use Claude Code
You don’t have to use the terminal. Claude Code is also available in:
- [VS Code](../03-IDE-Integrations/vs-code.md) and [JetBrains IDEs](../03-IDE-Integrations/jetbrains.md) as editor extensions
- The [desktop app](../16-Mobile-Desktop/desktop-quickstart.md), with no terminal required
- The [web](claude-code-on-the-web.md) at claude.ai/code for cloud sessions
- [GitHub Actions](github-actions.md) and [GitLab CI/CD](gitlab-ci-cd.md) for automation
[](#learn-more)
Learn more
- [Quickstart](../01-Getting-Started/quickstart.md): a guided walkthrough of your first project with Claude Code
- [How Claude Code works](how-claude-code-works.md): understand how Claude reads your files, runs commands, and makes edits
- [Best practices](best-practices.md): get better results with effective prompting and project setup
- [Common workflows](common-workflows.md): step-by-step guides for debugging, testing, refactoring, and more
- [Terminal configuration](terminal-config.md): customize your terminal for the best Claude Code experience
------------------------------------------------------------------------
[](#troubleshooting)
Troubleshooting
[](#macos-and-linux-troubleshooting)
macOS and Linux troubleshooting
If you run into problems installing on macOS or Linux, check these common issues:
'command not found: claude'
If you see `command not found: claude` after installing, the folder where the installer put `claude` isn’t in your PATH. The installer prints the exact fix under `Setup notes` at the end of the install, so run that command, or use the one for your shell below.For Zsh, the macOS default shell:
```python
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
For Bash on Linux:
```python
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```
For Bash on macOS, follow the macOS Bash step in [fix your PATH](troubleshoot-install.md#verify-your-path) instead.Then open a new terminal and try `claude` again. If it still isn’t found, check that the file `~/.local/bin/claude` exists. If it doesn’t, the install didn’t finish. For more details, see [fix your PATH](troubleshoot-install.md#verify-your-path).
Error with HTML code or 'syntax error near unexpected token'
If you see `bash: line 1: syntax error near unexpected token '<'` or HTML code like `<!DOCTYPE html>` in your terminal, the install URL returned a web page instead of the installer script.If the page says “App unavailable in region,” Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries).Otherwise, try running the command again. If it keeps happening, install with [Homebrew](https://brew.sh) instead:
```python
brew install --cask claude-code
```
When it finishes, open a new terminal window, type `claude --version`, and press Enter: the command prints a version number such as `2.1.211 (Claude Code)` when the install worked.
'dyld' error or 'built for Mac OS X 13.0'
If you see `dyld: cannot load`, `dyld: Symbol not found`, or `built for Mac OS X 13.0`, your macOS version is likely older than Claude Code supports.Open the Apple menu and select About This Mac to check your version. If it’s older than 13.0, update macOS through Software Update. See the [macOS troubleshooting guide](troubleshoot-install.md#dyld-cannot-load-on-macos) for more details.
For other errors, see the full [installation troubleshooting guide](troubleshoot-install.md).
[](#windows-troubleshooting)
Windows troubleshooting
If you run into problems installing on Windows, check these common issues:
'irm is not recognized'
You’re in CMD, not PowerShell. Close this window and open PowerShell instead (`Win + X` then select Windows PowerShell).Alternatively, use the CMD install command:
```python
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
SSL/TLS error or 'Could not create SSL/TLS secure channel'
This usually happens on older Windows 10 systems. Run this line first, then retry the install:
```python
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
irm https://claude.ai/install.ps1 | iex
```
'Claude Code on Windows requires either Git for Windows (for bash) or PowerShell'
Neither PowerShell nor Git Bash was found. Claude Code needs at least one shell.
1. Ensure `powershell.exe` is on your `PATH`. Its default location is `C:\Windows\System32\WindowsPowerShell\v1.0\`. Alternatively, install [PowerShell 7](https://aka.ms/powershell), which provides `pwsh`.
2. If you’d rather use Git Bash, install [Git for Windows](https://git-scm.com/downloads/win) per the [first step in the Windows section](#windows).
3. If Git is installed but Claude Code can’t find it, tell it where to look:
``` shiki
$env:CLAUDE_CODE_GIT_BASH_PATH="C:\Program Files\Git\bin\bash.exe"
```
Then run `claude` again. If your Git is installed somewhere else, find the path by running:
``` shiki
Get-Command git | Select-Object Source
```
Look for the `Git\bin` folder in that path and use it instead.
To make this permanent so you don’t have to set it every time, see [configure Git Bash path](troubleshoot-install.md#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell).
'claude is not recognized'
This error means the install directory isn’t in your PATH. Run these commands in PowerShell to add it:
```python
$currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')
[Environment]::SetEnvironmentVariable('PATH', "$currentPath;$env:USERPROFILE\.local\bin", 'User')
```
Close PowerShell, open a new window, and try `claude` again. You should see the Claude Code welcome screen. See [verify your PATH](troubleshoot-install.md#verify-your-path) for more details.
'Claude Code does not support 32-bit Windows'
On a 64-bit machine, this error means you opened `Windows PowerShell (x86)` instead of `Windows PowerShell`. The x86 entry runs as a 32-bit process. Close it, open the Start menu entry without `(x86)` in its name, and run the install command again. If you’re not sure your machine is 64-bit, or the error persists, see [the full explanation](troubleshoot-install.md#claude-code-does-not-support-32-bit-windows).
For other errors, see the full [installation troubleshooting guide](troubleshoot-install.md).
---
## Enterprise deployment overview - Claude Code Docs
Source: https://code.claude.com/docs/en/third-party-integrations
Path: 02-Claude-Code-CLI/third-party-integrations.md
## On this page
- [Compare deployment options](#compare-deployment-options)
- [Configure proxies and gateways](#configure-proxies-and-gateways)
- [Best practices for organizations](#best-practices-for-organizations)
- [Invest in documentation and memory](#invest-in-documentation-and-memory)
- [Simplify deployment](#simplify-deployment)
- [Start with guided usage](#start-with-guided-usage)
- [Pin model versions for cloud providers](#pin-model-versions-for-cloud-providers)
- [Configure security policies](#configure-security-policies)
- [Use MCP for integrations](#leverage-mcp-for-integrations)
- [Next steps](#next-steps)
Deployment
# Enterprise deployment overview
Copy pageCopy page
Learn how Claude Code can integrate with various third-party services and infrastructure to meet enterprise deployment requirements.
Copy pageCopy page
Organizations can deploy Claude Code through Anthropic directly or through a cloud provider. This page helps you choose the right configuration.
[](#compare-deployment-options)
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, SSO, billing management, and [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) for organization-wide Claude Code configuration. Best for smaller teams that need to get started quickly. **Claude for Enterprise** adds domain capture, role-based permissions, and compliance API access. Best for larger organizations with security and compliance requirements. Learn more about [Team plans](../17-Billing-Plans/what-is-the-team-plan.md) and [Enterprise plans](../17-Billing-Plans/what-is-the-enterprise-plan.md). The deployment options compared below cover where model inference runs. To run Claude Code [cloud sessions](claude-code-on-the-web.md) on compute your organization operates, see [self-hosted environments](../13-Enterprise-Admin/self-hosted-environments.md). If your organization has specific infrastructure requirements, compare the options below:
[TABLE]
For a feature-by-feature breakdown of what’s available on each option, see [Feature availability](feature-availability.md). Select a deployment option to view setup instructions:
- [Claude for Teams or Enterprise](../13-Enterprise-Admin/iam.md#claude-for-teams-or-enterprise)
- [Anthropic Console](../13-Enterprise-Admin/iam.md#claude-console-authentication)
- [Claude apps gateway](../13-Enterprise-Admin/claude-apps-gateway.md), a self-hosted gateway that adds IdP sign-in in front of Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, Microsoft Foundry, or the Anthropic API
- [Amazon Bedrock](amazon-bedrock.md)
- [Claude Platform on AWS](claude-platform-on-aws.md)
- [Google Cloud’s Agent Platform](google-vertex-ai.md)
- [Microsoft Foundry](microsoft-foundry.md)
For Amazon Bedrock and Google Vertex AI, you can also run `claude` and select **3rd-party platform** at the login prompt to launch an interactive setup wizard.
[](#configure-proxies-and-gateways)
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](../13-Enterprise-Admin/network-config.md).
- **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`, `ANTHROPIC_VERTEX_BASE_URL`, or `ANTHROPIC_FOUNDRY_BASE_URL` environment variables. Learn more in [LLM gateways](../13-Enterprise-Admin/llm-gateway.md).
For the per-provider environment variables that route Amazon Bedrock, Microsoft Foundry, or Google Cloud’s Agent Platform through an LLM gateway, see [route to a cloud provider through a gateway](../13-Enterprise-Admin/llm-gateway-connect.md#route-to-a-cloud-provider-through-a-gateway). Run `/status` in Claude Code to verify which provider, base URL, and proxy a session is using. If your organization uses [customer-managed encryption keys](../04-API-Reference/Other/manage-claude-cmek.md) (CMEK) and routes Claude Code through an LLM gateway or a custom `ANTHROPIC_BASE_URL`, CMEK doesn’t apply to Claude Code’s operational telemetry on those sessions. To turn telemetry off for every developer, deliver `DISABLE_TELEMETRY` through managed settings as shown in [Turn telemetry off for your organization](../13-Enterprise-Admin/managed-settings.md#turn-telemetry-off-for-your-organization).
[](#best-practices-for-organizations)
Best practices for organizations
[](#invest-in-documentation-and-memory)
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. See [where CLAUDE.md files can live](memory.md#choose-where-to-put-claude-md-files) and [how to deploy an organization-wide CLAUDE.md](memory.md#deploy-organization-wide-claude-md).
[](#simplify-deployment)
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)
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)
Pin model versions for cloud providers
If you deploy through [Amazon Bedrock](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), [Microsoft Foundry](microsoft-foundry.md), or [Claude Platform on AWS](claude-platform-on-aws.md), pin specific model versions using `ANTHROPIC_DEFAULT_FABLE_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL`. Without pinning, model aliases resolve to Claude Code’s built-in default for that provider, which can lag the newest release and may not yet be enabled in your account. Pinning lets you control when your users move to a new model. See [Model configuration](model-config.md#pin-models-for-third-party-deployments) for what each provider does when the default is unavailable.
[](#configure-security-policies)
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](../13-Enterprise-Admin/security.md).
[](#leverage-mcp-for-integrations)
Use 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](../06-MCP-Tools/General/mcp.md).
[](#next-steps)
Next steps
Once you’ve chosen a deployment option and configured access for your team:
1. **Roll out to your team**: Share installation instructions and have team members [install Claude Code](../01-Getting-Started/setup.md) and authenticate with their credentials.
2. **Set up shared configuration**: Create a [CLAUDE.md file](memory.md) in your repositories to help Claude Code understand your codebase and coding standards.
3. **Configure permissions**: Review [security settings](../13-Enterprise-Admin/security.md) to define what Claude Code can and cannot do in your environment.
---
## Tools reference - Claude Code Docs
Source: https://code.claude.com/docs/en/tools-reference
Path: 02-Claude-Code-CLI/tools-reference.md
## On this page
- [Configure tools with permission rules and hooks](#configure-tools-with-permission-rules-and-hooks)
- [Agent tool behavior](#agent-tool-behavior)
- [AskUserQuestion tool behavior](#askuserquestion-tool-behavior)
- [Question auto-continue timeout](#question-auto-continue-timeout)
- [Bash tool behavior](#bash-tool-behavior)
- [What persists between commands](#what-persists-between-commands)
- [Timeout and output limits](#timeout-and-output-limits)
- [Output limits](#output-limits)
- [Background commands](#background-commands)
- [Memory limit on Linux and WSL](#memory-limit-on-linux-and-wsl)
- [Edit tool behavior](#edit-tool-behavior)
- [EndConversation tool behavior](#endconversation-tool-behavior)
- [Glob tool behavior](#glob-tool-behavior)
- [Grep tool behavior](#grep-tool-behavior)
- [LSP tool behavior](#lsp-tool-behavior)
- [Monitor tool](#monitor-tool)
- [WebSocket source](#websocket-source)
- [NotebookEdit tool behavior](#notebookedit-tool-behavior)
- [PowerShell tool](#powershell-tool)
- [Enable the PowerShell tool](#enable-the-powershell-tool)
- [Shell selection in settings, hooks, and skills](#shell-selection-in-settings-hooks-and-skills)
- [Windows encoding and exit codes](#windows-encoding-and-exit-codes)
- [Preview limitations](#preview-limitations)
- [Read tool behavior](#read-tool-behavior)
- [SendFeedback tool behavior](#sendfeedback-tool-behavior)
- [What you see when Claude drafts](#what-you-see-when-claude-drafts)
- [Review and edit a draft](#review-and-edit-a-draft)
- [Send a draft](#send-a-draft)
- [Discard or keep a draft](#discard-or-keep-a-draft)
- [Turn Claude-drafted feedback off](#turn-claude-drafted-feedback-off)
- [Sessions without Claude-drafted feedback](#sessions-without-claude-drafted-feedback)
- [Task tool availability](#task-tool-availability)
- [WebFetch tool behavior](#webfetch-tool-behavior)
- [WebSearch tool behavior](#websearch-tool-behavior)
- [Session search limit](#session-search-limit)
- [Write tool behavior](#write-tool-behavior)
- [Check which tools are available](#check-which-tools-are-available)
- [See also](#see-also)
Reference
# Tools reference
Copy pageCopy page
Complete reference for the tools Claude Code can use, including permission requirements and per-tool behavior.
Copy pageCopy page
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](permissions.md#tool-specific-permission-rules), [subagent tool lists](../09-Agents-Patterns/sub-agents.md), and [hook matchers](../07-Hooks/hooks.md). To control which tools Claude can use and when it asks first, configure [permission rules](permissions.md#tool-specific-permission-rules) in your settings, [hooks](../07-Hooks/hooks.md), or a [subagent’s tool list](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields). See [Configure tools with permission rules and hooks](#configure-tools-with-permission-rules-and-hooks) for each place that accepts a tool name. To add custom tools, connect an [MCP server](../06-MCP-Tools/General/mcp.md). To extend Claude with reusable prompt-based workflows, write a [skill](../08-Plugins-Skills/skills.md), which runs through the existing `Skill` tool rather than adding a new tool entry.
In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), a classifier decides most permission prompts instead of you. The `Permission required` column shows whether the tool prompts in [Manual mode](permission-modes.md) for paths inside the working directory. File-access tools marked No, including `Read`, `Grep`, and `Glob`, still prompt for paths outside the [working directory and additional directories](permissions.md#working-directories). `Bash` is marked Yes but runs a built-in set of [read-only commands](permissions.md#read-only-commands) without prompting.
| Tool | Description | Permission required |
|:-----------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------|
| `Agent` | Spawns a [subagent](../09-Agents-Patterns/sub-agents.md) with its own context window to handle a task. With [agent teams](../09-Agents-Patterns/agent-teams.md) enabled, a call that carries a `name` can launch a [teammate](../09-Agents-Patterns/agent-teams.md#how-claude-starts-agent-teams) instead. See [Agent tool behavior](#agent-tool-behavior) | No |
| `Artifact` | Publishes an HTML or Markdown file as an [artifact](artifacts.md): a private, interactive page on claude.ai. You can share it with a public link, or inside your organization on Team and Enterprise plans, where public sharing requires an Owner to [enable it](artifacts.md#control-public-sharing). Requires a Pro, Max, Team, or Enterprise plan and `/login` authentication; see [Availability](artifacts.md#availability) | Yes |
| `AskUserQuestion` | Asks multiple-choice questions to gather requirements or clarify ambiguity. Questions stay open until you answer them by default. See [AskUserQuestion tool behavior](#askuserquestion-tool-behavior) | No |
| `Bash` | Executes shell commands in your environment. See [Bash tool behavior](#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](scheduled-tasks.md) | 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](#edit-tool-behavior) | Yes |
| `EndConversation` | Ends the session, in rare cases of sustained abusive input or when you ask Claude to demonstrate the tool. Requires Claude Code v2.1.213 or later. See [EndConversation tool behavior](#endconversation-tool-behavior) | No |
| `EnterPlanMode` | Switches to plan mode to design an approach before coding | No |
| `EnterWorktree` | Creates an isolated [git worktree](worktrees.md) and switches into it. Pass a `path` to switch into an existing worktree instead of creating a new one. On first entry the target may be a worktree of the current repository or, in a multi-repo workspace, of a repository nested inside it. Before v2.1.203, a nested repository’s worktree was rejected. A `path` outside `.claude/worktrees/` prompts for your approval before entering, since it moves the session’s working directory and write access to that location. New-worktree creation and paths under `.claude/worktrees/` don’t prompt. Before v2.1.206, Claude entered paths outside `.claude/worktrees/` without a prompt. From within a worktree session, or from a subagent with a pinned working directory such as [`isolation: worktree`](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields), only the `path` form is available and the target must be under `.claude/worktrees/` of the session’s repository | Yes |
| `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 that already run in their own working directory, such as with [`isolation: worktree`](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) | No |
| `Glob` | Finds files based on pattern matching. Absent by default on macOS, Linux, and WSL. See [Glob tool behavior](#glob-tool-behavior) | No |
| `Grep` | Searches for patterns in file contents. Absent by default on macOS, Linux, and WSL. See [Grep tool behavior](#grep-tool-behavior) | No |
| `ListAgents` | Lists the agents Claude can message with `SendMessage`: subagents in the session, [agent team](../09-Agents-Patterns/agent-teams.md) teammates, your other local Claude Code sessions, and, while this session is connected to [Remote Control](remote-control.md), your [cloud sessions](claude-code-on-the-web.md) and your Remote Control sessions on other machines. Backs the `/list-agents` command. See [cross-session messaging](cross-session-messaging.md). Requires Claude Code v2.1.224 or later, and appears only in sessions where [cross-session messaging is enabled](cross-session-messaging.md#availability). Teammate rows and the first line showing this session’s own name require v2.1.239 or later | No |
| `ListMcpResourcesTool` | Lists resources exposed by connected [MCP servers](../06-MCP-Tools/General/mcp.md), leaving out [MCP Apps UI resources](../06-MCP-Tools/General/mcp.md#reference-mcp-resources), which are pages for a host application to render | No |
| `LSP` | Code intelligence via language servers: jump to definitions, find references, report type errors and warnings. See [LSP tool behavior](#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. Can also open a WebSocket and treat each incoming message as an event. See [Monitor tool](#monitor-tool) | Yes |
| `NotebookEdit` | Modifies Jupyter notebook cells. See [NotebookEdit tool behavior](#notebookedit-tool-behavior) | Yes |
| `PowerShell` | Executes PowerShell commands natively. See [PowerShell tool](#powershell-tool) for availability | Yes |
| `PushNotification` | Sends a desktop notification, and a phone push when [Remote Control](remote-control.md) is connected, so a long-running task or [scheduled task](scheduled-tasks.md) can reach you when you step away. Push delivery runs through Anthropic-hosted infrastructure, which is not accessible from Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry | No |
| `Read` | Reads the contents of files. See [Read tool behavior](#read-tool-behavior) | No |
| `ReadMcpResourceTool` | Reads a specific MCP resource by URI | No |
| `RemoteTrigger` | Creates, updates, runs, and lists [Routines](web-scheduled-tasks.md) on claude.ai. Backs the `/schedule` command. The [`RemoteTrigger` input reference](../05-Agent-SDK/agent-sdk-typescript.md#remotetrigger) documents every action and the organization policies that remove the tool. Routines live on claude.ai and require a Pro, Max, Team, or Enterprise plan, so this tool is not accessible from Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry | No |
| `ReportFindings` | Reports code-review findings as a structured list, with a file, summary, and failure scenario per finding, so Claude Code can render them instead of printing them as text. Claude calls it when active code-review instructions tell it to. Requires Claude Code v2.1.196 or later. As of v2.1.199, a finding can also carry an optional `category` slug, such as `correctness` or `test-coverage`, shown next to the file location in the rendered list | No |
| `ScheduleWakeup` | Reschedules the next iteration of a [self-paced `/loop`](scheduled-tasks.md#let-claude-choose-the-interval). Claude calls this at the end of each iteration to pick when the next one runs, between one minute and one hour out; you don’t call it directly. To end the loop instead, Claude calls it with `stop: true`, which cancels the pending wakeup. The `stop` field requires Claude Code v2.1.202 or later. The pending wakeup appears in `session_crons` in [Stop hook input](../07-Hooks/hooks.md#stop-input) | No |
| `SendFeedback` | Drafts a feedback report about Claude Code, covering a product problem or Claude’s own behavior in the session, and queues it on your machine for you to review. Claude Code sends nothing until you choose to send the draft. See [SendFeedback tool behavior](#sendfeedback-tool-behavior). Requires Claude Code v2.1.238 or later | No |
| `SendMessage` | Sends a message to another agent: an [agent team](../09-Agents-Patterns/agent-teams.md) teammate, a [subagent it resumes](../09-Agents-Patterns/sub-agents.md#resume-subagents) by agent ID or name, or one of your other Claude Code sessions, on this machine or beyond it. Messaging other sessions requires Claude Code v2.1.224 or later. [Cross-session messaging](cross-session-messaging.md) covers which sessions Claude can reach, [what a message looks like when it arrives](cross-session-messaging.md#what-a-message-looks-like), and [how Claude gets a notice when another session goes idle](cross-session-messaging.md#get-a-notice-when-another-session-goes-idle). Claude can include an optional `summary` input, typically 5-10 words, that Claude Code shows as a one-line preview. When Claude omits it on a [plain-text message](cross-session-messaging.md#limitations), Claude Code uses the first line of the message as the summary. Claude Code truncates a summary longer than 200 characters with an ellipsis | No |
| `SendUserFile` | Sends files from the session to you with an optional caption, so a generated report, diagram, screenshot, or built artifact reaches your device instead of only being mentioned in the transcript. As of v2.1.196, the optional `display` input controls presentation: `render` opens the file inline in the client, `attach` shows a download card only, and when unset the client decides by file type. Available when a [Remote Control](remote-control.md) client is connected or in a [cloud session](claude-code-on-the-web.md). Delivery runs through Anthropic-hosted infrastructure, so the tool is not available on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry | 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](../08-Plugins-Skills/skills.md#control-who-invokes-a-skill) within the main conversation | Yes |
| `SubagentHandback` | Delivers a subagent’s final report to whichever conversation receives that subagent’s result. Provided only in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), to subagents that the Agent tool runs locally other than [forks](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation), and available in the terminal CLI, IDE extensions, cloud sessions, and the Agent SDK; the classifier reviews the report before it’s delivered. Requires Claude Code v2.1.271 or later | No |
| `TaskCreate` | Creates a new task in the task list. Provided by default only on the models listed under [Task tool availability](#task-tool-availability), and on other models when you opt in | No |
| `TaskGet` | Retrieves full details for a specific task. Provided by default only on the models listed under [Task tool availability](#task-tool-availability), and on other models when you opt in | No |
| `TaskList` | Lists all tasks with their current status. Provided by default only on the models listed under [Task tool availability](#task-tool-availability), and on other models when you opt in | No |
| `TaskOutput` | Retrieves output from a background task. Deprecated in favor of `Read` on the task’s output file path. When no task matches the ID, the error lists the running background agents by ID and description. Before v2.1.203, the error named only the missing ID | No |
| `TaskStop` | Stops a running background task by ID. It also accepts an [agent-team teammate](../09-Agents-Patterns/agent-teams.md) or a named background agent by agent ID or name. Before v2.1.198, it accepted only a background task ID. When no task matches the ID, the error lists the running background agents by ID and description, including agents that another agent spawned. Before v2.1.203, the error listed running teammates and named agents but not background agents another agent spawned, so those couldn’t be identified or stopped from the main conversation | No |
| `TaskUpdate` | Updates task status, dependencies, details, or deletes tasks. Provided by default only on the models listed under [Task tool availability](#task-tool-availability), and on other models when you opt in | No |
| `TodoWrite` | Manages the session task checklist. Disabled by default in favor of `TaskCreate`, `TaskGet`, `TaskList`, and `TaskUpdate`. Set `CLAUDE_CODE_ENABLE_TASKS=0` to re-enable it in [sessions that have the task-tracking tools](#task-tool-availability) | No |
| `ToolSearch` | Searches for and loads deferred tools when [tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is enabled | No |
| `WaitForMcpServers` | Waits for one or more [MCP servers](../06-MCP-Tools/General/mcp.md) that are still connecting in the background, so a request can use their tools without restarting the session. Claude calls it when a needed server isn’t connected yet. Only appears when [tool search](../06-MCP-Tools/General/mcp.md#scale-with-mcp-tool-search) is disabled, since `ToolSearch` handles the wait when it’s enabled | No |
| `WebFetch` | Fetches content from a specified URL. See [WebFetch tool behavior](#webfetch-tool-behavior) | Yes |
| `WebSearch` | Performs web searches. See [WebSearch tool behavior](#websearch-tool-behavior) | Yes |
| `Workflow` | Runs a [dynamic workflow](workflows.md): a script that orchestrates many subagents in the background and returns one consolidated result | Yes |
| `Write` | Creates or overwrites files. See [Write tool behavior](#write-tool-behavior) | Yes |
[](#configure-tools-with-permission-rules-and-hooks)
Configure tools with permission rules and hooks
For the most part, Claude decides when to use these tools and you don’t need to name them yourself when interacting with Claude. You reference tool names directly when defining permissions and other configuration:
- in [`permissions.allow`](settings-reference.md#permissions-allow) and [`permissions.deny`](settings-reference.md#permissions-deny) in settings, and the `/permissions` interface
- in the `--allowedTools` and `--disallowedTools` [CLI flags](cli-reference.md)
- in the Agent SDK’s [`allowedTools` and `disallowedTools`](../05-Agent-SDK/agent-sdk-permissions.md#allow-and-deny-rules) options
- in a [skill’s `allowed-tools`](../08-Plugins-Skills/skills.md#frontmatter-reference) frontmatter
- in a hook’s [`if` condition](../07-Hooks/hooks-guide.md#filter-by-tool-name-and-arguments-with-the-if-field)
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](permissions.md#bash) |
| `PowerShell(Get-ChildItem *)` | PowerShell | [Command pattern matching](permissions.md#powershell) |
| `Read(~/secrets/**)` | Read, Grep, Glob, LSP | [Path pattern matching](permissions.md#read-and-edit) |
| `Edit(/src/**)` | Edit, Write, NotebookEdit | [Path pattern matching](permissions.md#read-and-edit) |
| `Skill(deploy *)` | Skill | [Skill name matching](../08-Plugins-Skills/skills.md#restrict-claude%E2%80%99s-skill-access) |
| `Agent(Explore)` | Agent | [Subagent type matching](permissions.md#agent-subagents) |
| `WebFetch(domain:example.com)` | WebFetch | [Domain matching](permissions.md#webfetch) |
| `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 don’t need a matching `Read(...)` rule. A `Read(...)` deny rule also blocks the Edit and Write tools on the same path, including creating a new file there, because both tools change content Claude has to be able to read back. The `Read` deny check requires Claude Code v2.1.208 or later on edits, and v2.1.228 or later on writes. Hook `matcher` fields use bare tool names, not the parenthesized rule format. See [matcher patterns](../07-Hooks/hooks.md#matcher-patterns) for the matching rules. For the field names each tool passes to `tool_input` in hooks, see the [PreToolUse input reference](../07-Hooks/hooks.md#pretooluse-input).
[](#agent-tool-behavior)
Agent tool behavior
The Agent tool spawns a subagent in a separate context window. The subagent works through its task autonomously, then returns its result to the parent conversation. The parent doesn’t see the subagent’s intermediate tool calls or outputs, only that final result. With [agent teams](../09-Agents-Patterns/agent-teams.md) enabled, a call that carries a `name` can launch a [teammate](../09-Agents-Patterns/agent-teams.md#how-claude-starts-agent-teams) instead, which reports back through team messages rather than by returning a result. To cap how many turns a subagent runs, set `maxTurns` in the [subagent definition](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields). When the subagent reaches the limit, Claude Code marks the returned result as partial output, and Claude can [resume the subagent](../09-Agents-Patterns/sub-agents.md#resume-subagents) to continue. The same Agent tool also launches [forked subagents](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) wherever [fork mode](../09-Agents-Patterns/sub-agents.md#turn-fork-mode-on-or-off) is on. A fork inherits the full parent conversation instead of starting fresh, runs in the background apart from the [cases that stay in the foreground](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background), and still surfaces permission prompts in your terminal. The rest of this section describes non-fork subagents. Which tools a non-fork subagent can use depends on the `tools` and `disallowedTools` fields in the [subagent definition](../09-Agents-Patterns/sub-agents.md):
- **Neither field set**: the subagent inherits every [tool available to subagents](../09-Agents-Patterns/sub-agents.md#available-tools).
- **`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.
In every case, the resolved set is limited to the [tools available to subagents](../09-Agents-Patterns/sub-agents.md#available-tools): a tool that isn’t available to subagents is never granted, even when listed in `tools`. Where the conditions in the `SubagentHandback` tools-table entry hold, Claude Code also gives the subagent that tool, even if you leave it out of `tools` or list it in `disallowedTools`. If every entry in a subagent’s `tools` list fails to match a usable tool, the Agent tool usually returns an error naming the entries instead of launching the subagent; see [Agent would be spawned with zero tools](errors.md#agent-would-be-spawned-with-zero-tools) for the message and how to fix each entry. Launching the subagent doesn’t itself prompt for permission. Claude Code checks the subagent’s own tool calls against your permission rules as it runs. Where you see a subagent’s permission prompts depends on whether it runs in the foreground or the background. Claude Code runs subagents in the background by default, apart from the [cases that run in the foreground](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background).
- **Foreground subagents** show the same permission prompts you would see in the main conversation, at the moment each tool call happens.
- **Background subagents** surface permission prompts in your main session as of v2.1.186. The prompt names which subagent is asking, and pressing Esc denies that one tool call without stopping the subagent. Before v2.1.186, background subagents auto-denied any tool call that would otherwise prompt and continued without that tool.
To [limit what a subagent can reach](../09-Agents-Patterns/sub-agents.md#control-subagent-capabilities) in the first place, narrow its `tools` field, for example by leaving Bash off the list, or set deny rules in your settings.
[](#askuserquestion-tool-behavior)
AskUserQuestion tool behavior
Claude uses `AskUserQuestion` to ask you multiple-choice questions when it needs a decision or a clarification. Answer by picking an option, or type your own text through the `Other` row or the notes field. When you answer by typing your own text, Claude Code relays the answer with neutral wording so Claude follows what you wrote, including a request to wait or explain first.
[](#question-auto-continue-timeout)
Question auto-continue timeout
Questions stay open until you answer them. If you want a question you leave unanswered to eventually close and let Claude continue without you, set the [`askUserQuestionTimeout`](settings-reference.md#askuserquestiontimeout) setting to `60s`, `5m`, or `10m`, either in your user `settings.json` or from the **Question auto-continue timeout** row in `/config`. After a question sits that long with no input, the dialog closes on its own: it submits any options you’d already selected and tells Claude you may be away from your keyboard, so Claude proceeds on its own judgment and can re-ask later. You see a countdown for the last 20 seconds. Press any key to restart the timer; on terminals that report focus, switching to the window restarts it too. The timeout applies only to `AskUserQuestion`’s multiple-choice questions; permission prompts, including plan approval, never auto-resolve on idle.
[](#bash-tool-behavior)
Bash tool behavior
The Bash tool runs each command in a separate process.
[](#what-persists-between-commands)
What persists between commands
- 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](permissions.md#working-directories) you added with `--add-dir`, `/add-dir`, or `additionalDirectories` in settings. This includes commands Claude runs in response to your later messages.
- 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 don’t persist. An `export` in one command won’t be available in the next.
- Aliases and shell functions defined in your shell startup file are available. At session start, Claude Code sources `~/.zshrc`, `~/.bashrc`, or `~/.profile` depending on your shell, captures the resulting aliases, functions, and shell options, and applies them to every Bash command.
Activate your virtualenv or conda environment before launching Claude Code. To make environment variables persist across Bash commands, set [`CLAUDE_ENV_FILE`](env-vars.md) to a shell script before launching Claude Code, or use a [SessionStart hook](../07-Hooks/hooks.md#persist-environment-variables) to populate it dynamically.
[](#timeout-and-output-limits)
Timeout and output limits
Each command runs under a timeout, and Claude manages it: when it wants longer than the default for a command, it passes the `timeout` parameter with that call — you never set a per-command timeout. Two [environment variables](env-vars.md) bound what Claude gets:
- `BASH_DEFAULT_TIMEOUT_MS` — the default when Claude passes no timeout; two minutes out of the box
- `BASH_MAX_TIMEOUT_MS` — with the default, sets the ceiling that caps whatever Claude requests: the effective ceiling is the larger of the two, ten minutes out of the box
[](#output-limits)
Output limits
Claude Code streams a command’s output to a working file as the command runs; a command whose output passes 5 GB is killed. When the command finishes, Claude Code reads the output back from that file, up to the read-back window described below. How much of the output reaches Claude inline depends on whether Claude Code treats the result as a failure:
| Result | What Claude gets |
|:--------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Valid | Inline up to roughly 30,000 characters by default; past that, the path of a file saved to the session directory and truncated past 64 MiB, plus a preview of up to the first 2,000 characters, and Claude reads or searches the file when it needs the rest |
| Failure | Inline up to roughly 10,000 characters; past that, a head-and-tail excerpt of that size cut from the read-back window, with no file path |
A command that exits 1 counts as a valid result for the Bash tool only when Claude Code recognizes exit code 1 as a benign outcome for that command: `grep`, `rg`, `egrep`, `fgrep`, `find`, `diff`, `test`, and `[`, plus `git diff` and `git grep`. Every other command that exits 1 counts as a failure, even when exit 1 is a benign informational outcome: no matches for `pgrep` and `jq -e`, files that differ for `cmp`. [`BASH_MAX_OUTPUT_LENGTH`](env-vars.md) sets how many characters of output Claude Code reads back from the working file into a command’s result: 30,000 by default, up to a hard ceiling of 150,000. Raise it when your commands routinely overflow that window, such as a verbose build or a full test-suite log. Raising it enlarges the read-back window, which is also the window a failing command’s excerpt is cut from. It doesn’t raise the inline ceilings: a valid result over the inline ceiling arrives as a file path plus preview regardless of this variable. To change how much of a valid result Claude receives inline, set the [`bashOutputMaxChars`](settings-reference.md#bashoutputmaxchars) setting instead, up to 128,000 characters. It sizes the inline ceiling and the read-back window together, and Claude Code then ignores `BASH_MAX_OUTPUT_LENGTH`. Requires Claude Code v2.1.261 or later.
[](#background-commands)
Background commands
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`. After you stop one there, or from a connected client such as the desktop app, Claude moves on instead of waiting for it. If a subagent started the command, it’s that subagent that moves on. A command that a [foreground subagent](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background) started stops when that subagent gives its final response. A command that the main conversation or a background subagent started keeps running after a final response. In non-interactive mode with the `-p` flag, [background commands end shortly after the run’s final result](headless.md#background-tasks-at-exit). When a command reaches its timeout without finishing, Claude Code moves it to the background instead of stopping it, unless the command starts with `sleep`. Claude keeps working while the command continues. Claude Code applies the same lifetime rules to a moved command as to any other background command, so it still ends a foreground subagent’s command at that subagent’s final response. Setting [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1`](env-vars.md#variables) disables auto-backgrounding along with the rest of the background task functionality. The result of a command moved to the background states what happened:
- When the timeout triggers the move, the result reports it explicitly: `Command did not complete within its 120s timeout and was moved to the background`, with the seconds matching the timeout that applied, followed by the task ID and the path of the file the output is being written to.
- A `cd`, `pushd`, `popd`, or `chdir` inside a command that is moved to the background never carries over: the result states `Session cwd remains <dir>; directory changes made by the backgrounded command do not apply to subsequent commands.`, so Claude doesn’t act on a directory change that didn’t happen.
[](#memory-limit-on-linux-and-wsl)
Memory limit on Linux and WSL
On Linux and WSL, set [`CLAUDE_CODE_TOOL_MEMORY_LIMIT`](env-vars.md#variables) to a size such as `4G` to cap the memory that Bash, PowerShell, and [Monitor](#monitor-tool) tool commands can use, so one runaway build can’t take the memory the rest of the session needs. Requires Claude Code v2.1.233 or later. Before v2.1.246, Monitor tool commands ran outside the cap.
- Write the size as a number of bytes or with a `K`, `M`, `G`, or `T` suffix. Set `0`, `off`, `false`, `no`, or `none` to turn the cap off. Claude Code ignores any other value it can’t read as a size, such as `4e9`.
- Claude Code counts all of a session’s Bash, PowerShell, and Monitor commands against the one cap, not each command on its own.
- Claude Code applies the cap with a memory cgroup. When it can’t set the cgroup up, commands run without a cap, and the debug log from `claude --debug` says why.
- After the first process Claude Code starts has turned the cap on, or has turned it off because of an off value or a failed cgroup setup, Claude Code holds that result until you relaunch. To apply a changed or removed value, or a fixed setup, launch `claude` again.
- When commands can’t stay under the cap, the kernel kills a command, and nothing in its result names the cap.
Claude Code can also count other kinds of processes it starts against the same limit. Set [`CLAUDE_CODE_TOOL_MEMORY_CGROUP_EXCLUDE`](env-vars.md#variables) to a comma-separated list of the kinds to exempt from the cap; Claude Code applies the cap to every kind not on your list. Set it to `none` to cap every kind, or to `all-new` to cap only Bash, PowerShell, and Monitor tool commands. Requires Claude Code v2.1.246 or later. The kinds you can name:
- `mcp`: local [MCP servers](../06-MCP-Tools/General/mcp.md)
- `lsp`: [language servers](#lsp-tool-behavior)
- `hooks`: [hook](../07-Hooks/hooks.md) commands
- `plugin`: commands that [plugins](../08-Plugins-Skills/plugins.md) run
- `helper`: Claude Code’s own helper commands, such as `git`
- `agent`: child Claude Code processes, such as [agent teammates](../09-Agents-Patterns/agent-teams.md)
Whatever you list, these rules apply:
- **Unknown names**: Claude Code ignores names it doesn’t recognize
- **Bash, PowerShell, and Monitor**: Claude Code keeps Bash, PowerShell, and Monitor tool commands under the cap whatever you list
- **Variable unset**: Claude Code takes the set of other capped kinds from configuration Anthropic delivers from the server, and that set can change over time, so set the variable when you need a set that doesn’t change
- **Permission-gating hooks**: even with every kind capped, Claude Code excludes from the cap a hook that can block or change the outcome of an action, and any MCP server that such a hook calls, so the kernel killing a permission-gating hook can’t allow the action it was blocking
[](#edit-tool-behavior)
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 doesn’t use regex or fuzzy matching. Three checks must pass for an edit to apply. Before any of them, a path matched by a [`Read` deny rule](permissions.md#tool-specific-permission-rules) is refused, including creating a new file there. The refusal requires Claude Code v2.1.208 or later.
- **Read-before-edit**: Claude reads the file in the current conversation before editing it, and a read cut short with a [`PARTIAL view` notice](#read-tool-behavior) doesn’t count. Claude Opus 4.6, Claude Haiku 4.5, and older models always require the read. Newer models can edit an unread file when reading it wouldn’t need a permission prompt and the Read tool is available.
- **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.
A file that changed on disk after Claude last read it can still be edited when `old_string` matches the current content exactly and unambiguously and Claude Code can read the file without prompting. Matching against the file’s current content keeps this safe, and the result notes that the file carries other changes so Claude re-reads it before edits that depend on surrounding content. In any other case, such as a stale `old_string` or one that matches more than once without `replace_all`, Claude reads the file again before editing. The relaxed handling of unread and changed files requires Claude Code v2.1.208 or later; before that, Claude Code refused any edit to a file it hadn’t read in the conversation or that changed on disk after the read. Viewing a file with Bash also satisfies the read-before-edit requirement when the command is `cat`, `nl`, `bat`, `batcat`, `head`, `tail`, `sed -n 'X,Yp'`, `grep`, `egrep`, `fgrep`, or `rg` on a single file with no pipes or redirects. Piped output and other Bash commands don’t count toward the read-before-edit check. Viewing a file with Bash affects edit eligibility only, not permissions. See [Read and Edit permission rules](permissions.md#read-and-edit) for which Bash commands your `Read` and `Edit` deny rules cover.
[](#endconversation-tool-behavior)
EndConversation tool behavior
The EndConversation tool ends the current session. Claude uses it only in two situations:
- as a last resort against sustained abusive input, after attempts to redirect the conversation have failed and after a clear warning in an earlier message
- when you explicitly ask to see the tool demonstrated and confirm that you want the session to end
General frustration, profanity, or a task going badly don’t qualify, and neither do requests for harmful content, which Claude declines instead of ending the session. Claude Code follows the same approach as claude.ai, which can [end a rare subset of chats](../19-Reference/end-subset-conversations.md). After Claude ends an interactive session, the session locks. New prompts and most commands return `Claude ended this conversation. Start a new session (or /clear) to continue.`, and only `/clear`, `/resume`, `/help`, `/exit`, and `/feedback` still run. Claude Code records the end in the session’s transcript, so resuming an ended session restores the lock; the session’s history isn’t deleted. Resuming an ended session in [non-interactive mode](headless.md) with the `-p` flag errors and exits with code 1, so a script doesn’t read the ended run as a success. The tool never prompts for permission, and [PreToolUse hooks](../07-Hooks/hooks.md#pretooluse) don’t run for it. While any other tool remains, you can’t block it either: [deny and ask rules](permissions.md#tool-specific-permission-rules) naming `EndConversation` have no effect, and neither `--disallowedTools` nor a `--tools` list can remove it. The exemption is deliberate: the tool does nothing except end the conversation, never reading or modifying files or data, and a safeguard of this kind holds only if the session it applies to can’t turn it off. When your deny rules remove every other tool and also match `EndConversation`, as `"*"` does, Claude Code removes it too rather than leaving it as the only tool, unless an allow rule names `EndConversation` explicitly. A deny list that removes every other tool without matching `EndConversation` leaves it in place. [Subagents](../09-Agents-Patterns/sub-agents.md) never get the tool. Background tasks that share the main conversation’s tool list see it, but calling it there ends nothing. The tool appears only when all of the following are true:
- **Version**: Claude Code v2.1.213 or later.
- **Model**: the session’s model is Claude Opus 4.8, Claude Sonnet 5, Claude Fable 5, or a later version of one of those families.
- **Surface**: an interactive terminal session, including a `claude` session in an IDE’s integrated terminal, which is how the [JetBrains plugin](../03-IDE-Integrations/jetbrains.md) runs it. Other surfaces don’t include the tool, such as:
- non-interactive `-p` runs
- sessions through the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) TypeScript and Python packages
- the [VS Code extension](../03-IDE-Integrations/vs-code.md) panel, which bundles its own CLI
- [GitHub Actions](github-actions.md)
- [cloud sessions](claude-code-on-the-web.md)
- **Startup mode**: not a [`--bare`](headless.md#start-faster-with-bare-mode) session. Bare mode loads only shell and file tools, so the tool is never registered there.
- **Provider**: not available on [Amazon Bedrock](amazon-bedrock.md), [Claude Platform on AWS](claude-platform-on-aws.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md), or on sessions signed in through a [cloud gateway](../13-Enterprise-Admin/claude-apps-gateway.md).
[](#glob-tool-behavior)
Glob tool behavior
The Glob tool finds files by name pattern. On Windows, it’s part of the default tool set. On macOS, Linux, and WSL, Claude Code leaves Glob and [Grep](#grep-tool-behavior) out of the default tool set, and Claude searches with `find` and `grep` through the Bash tool instead. In Claude’s shell those two commands run embedded versions of `bfs` and `ugrep`, and the searches reach your hooks and permission rules as `Bash` calls. On macOS, Linux, and WSL, you get the Glob and Grep tools back in these cases:
- You name `Glob` or `Grep` in [`--tools` or `--allowedTools`](cli-reference.md#cli-flags) when you start the session, or in the equivalent [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) options. With `--tools` you get the ones you list, and naming either tool in `--allowedTools` restores both. An allow rule in a settings file doesn’t have this effect.
- A permissions [deny rule](permissions.md#match-all-uses-of-a-tool), the `--disallowedTools` flag, or [`--restricted`](cli-reference.md#cli-flags) removes `Bash` from the session.
- A [subagent](../09-Agents-Patterns/sub-agents.md#available-tools) lists `Glob` or `Grep` in its `tools` field and leaves out `Bash`. The listed tools come back for that subagent only, or for the whole session when it runs as the main session agent through [`--agent`](../09-Agents-Patterns/sub-agents.md#invoke-subagents-explicitly) or the `agent` setting.
Glob 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 doesn’t respect `.gitignore` by default, so it finds gitignored files alongside tracked ones. This differs from [Grep](#grep-tool-behavior), which skips gitignored files. To make Glob respect `.gitignore`, set `CLAUDE_CODE_GLOB_NO_IGNORE=false` before launching Claude Code. Claude Code decides permission for a Glob call before it checks whether the search directory exists. It still runs the read-permission check for a missing `path` outside the [working directories](permissions.md#working-directories), so a permission prompt for a path doesn’t mean the path exists. A `pattern` or `path` value that contains a null byte returns an error asking Claude to remove it.
[](#grep-tool-behavior)
Grep tool behavior
The Grep tool searches file contents for patterns. Where [Glob](#glob-tool-behavior) finds files by name, Grep finds lines inside them. On macOS, Linux, and WSL, Grep is absent by default under the same conditions as Glob. See [Glob tool behavior](#glob-tool-behavior) for when both tools are available. Grep is built on [ripgrep](https://github.com/BurntSushi/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\{\}`. A pattern, glob, or file type that ripgrep rejects returns an error that includes ripgrep’s diagnostic, so Claude can correct the input and search again. Before v2.1.208, Claude Code reported a rejected input as `No files found` instead of an error, even when the searched-for text existed in the target files. 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. When the tool’s `offset` parameter points past the last match for a pattern that has matches, Grep returns `No entries at this offset`, so Claude widens or resets the offset instead of concluding the pattern doesn’t match.
- `count`: match count per file, followed by a total across all matching files. The total covers every match even when the tool’s `head_limit` or `offset` parameters truncate the listed per-file entries. Before v2.1.208, the total only summed the listed entries.
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. Claude Code decides permission for a Grep call before it checks whether the search `path` exists. It still runs the read-permission check for a missing `path` outside the [working directories](permissions.md#working-directories), so a permission prompt for a path doesn’t mean the path exists.
[](#lsp-tool-behavior)
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
- Search for a symbol by name across the workspace
- Find implementations of an interface
- Trace call hierarchies
Claude Code keeps the tool inactive until you install a [code intelligence plugin](../08-Plugins-Skills/plugins-code-intelligence.md) for your language. In [cloud sessions](claude-code-on-the-web.md), Claude Code doesn’t start plugin language servers, so the LSP tool stays inactive there. Claude Code takes the language server’s configuration from the plugin, and you install the server binary yourself. Claude Code returns an error result for each LSP call on a file whose language server it can’t start.
[](#monitor-tool)
Monitor tool
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
- Connect to a WebSocket feed and report each message as it arrives
For most watches, Claude writes a small script, runs it in the background, and receives each output line as it arrives. For a server that already pushes events, Claude can open a [WebSocket](#websocket-source) instead of running a script. You keep working in the same session and Claude interjects when an event arrives. Every watch Claude starts has a deadline: 5 minutes by default, at most 30 minutes, and at most 10 minutes in a [non-interactive](headless.md) run given a single prompt with `-p`. At the deadline the watch ends. Claude gets one notice, so it can start the watch again if it’s still needed. Stop a monitor by asking Claude to cancel it or by ending the session. When you stop a [subagent](../09-Agents-Patterns/sub-agents.md) that started monitors, for example from `/tasks`, those monitors stop with it. When Monitor runs a command, it uses the same [permission rules as Bash](permissions.md#tool-specific-permission-rules), so `allow` and `deny` patterns you have set for Bash apply here too. While [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) is active, Claude Code sets aside allow rules that name `Monitor` itself, along with the other [broad allow rules it drops](permission-modes.md#how-the-classifier-evaluates-actions), so the classifier reviews Monitor commands the same way it reviews Bash commands. The [WebSocket source](#websocket-source) has its own approval prompt, which the classifier also decides in auto mode. The tool is not available on Amazon Bedrock, Google Cloud’s Agent Platform, 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](../08-Plugins-Skills/plugins-components.md#monitors).
[](#websocket-source)
WebSocket source
When a server already pushes events over a WebSocket, Claude can connect to it directly instead of writing a polling script. Each kind of socket activity either becomes an event or ends the watch:
- **Text messages**: each one becomes one event, even when the message spans multiple lines.
- **Binary messages**: not passed through. Claude receives a placeholder line such as `[binary frame, 512 bytes]` instead.
- **Messages larger than 1 MiB**: the watch ends, so subscribe to a filtered feed where one exists.
- **Socket close**: the watch ends and Claude receives the close code.
A WebSocket watch takes a `ws` input in place of `command`, and a single Monitor call can’t combine the two. The `ws` input has two fields:
| Field | Required | Description |
|:------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `url` | Yes | The endpoint to connect to. Must be a `ws://` or `wss://` URL with no embedded credentials or whitespace, using ASCII characters only |
| `protocols` | No | WebSocket subprotocol names to offer during the handshake. Each entry must be a valid subprotocol token, and the list can’t contain duplicates |
The `timeout_ms` deadline applies to a WebSocket watch too: the watch ends at the deadline, and `TaskStop` cancels it early. Opening a WebSocket prompts for approval; in [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode) the classifier decides instead. The prompt doesn’t offer an option to skip future prompts for the same host. Claude Code denies URLs that point at a private, link-local, or cloud-metadata address, including hostnames that resolve to one. It also denies hosts in `sandbox.network.deniedDomains`, and when [`allowManagedDomainsOnly`](settings-reference.md#sandbox-network-allowmanageddomainsonly) is set in managed settings, any host outside the managed allowlist.
[](#notebookedit-tool-behavior)
NotebookEdit tool behavior
NotebookEdit modifies a Jupyter notebook one cell at a time, targeting cells by their `cell_id`. It doesn’t perform string replacement across the notebook the way [Edit](#edit-tool-behavior) 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)
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. How the tool becomes available depends on your platform:
- **Windows without Git Bash**: the tool is enabled automatically.
- **Windows with Git Bash installed**: the tool is on by default for claude.ai and Console accounts; set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` to enable it in Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry sessions, or `0` to turn it off.
- **Linux, macOS, and WSL**: the tool is opt-in.
Your [PreToolUse hooks](../07-Hooks/hooks.md#powershell) receive the tool’s command string in `tool_input.command`, with the same fields as the Bash tool. Match `Bash|PowerShell` in hooks that inspect shell commands; the [PowerShell hook input section](../07-Hooks/hooks.md#powershell) explains why matching `Bash` alone is not enough.
[](#enable-the-powershell-tool)
Enable the PowerShell tool
Set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` in your environment or in `settings.json`:
```python
{
"env": {
"CLAUDE_CODE_USE_POWERSHELL_TOOL": "1"
}
}
```
On Windows, set the variable to `0` to turn the tool off. 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. Claude Code spawns PowerShell with `-ExecutionPolicy Bypass` at process scope only, so `.ps1` scripts and module imports work on default Windows installs without changing the machine’s policy. Process-scope bypass doesn’t override Group Policy `MachinePolicy` or `UserPolicy`, so enterprise policies still apply. To respect the machine’s effective execution policy instead, set `CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY=1`.
[](#shell-selection-in-settings-hooks-and-skills)
Shell selection in settings, hooks, and skills
Three additional settings control where PowerShell is used:
- `"defaultShell": "powershell"` in [`settings.json`](settings-reference.md#all-settings): routes interactive `!` commands through PowerShell. Requires the PowerShell tool to be enabled.
- `"shell": "powershell"` on individual [command hooks](../07-Hooks/hooks.md#command-hook-fields): runs that hook in PowerShell. Hooks spawn PowerShell directly, so this works regardless of `CLAUDE_CODE_USE_POWERSHELL_TOOL`.
- `shell: powershell` in [skill frontmatter](../08-Plugins-Skills/skills.md#frontmatter-reference): 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. As of v2.1.196, exit code 1 from `grep`, `rg`, `egrep`, `fgrep`, `findstr`, and `git grep` means no matches. Exit code 1 from `git diff` means differences exist. Neither result is reported to Claude as a command failure. For `robocopy`, exit codes 0 through 7 are informational results, such as files copied or extra files detected. Exit codes of 8 or higher count as failures.
[](#windows-encoding-and-exit-codes)
Windows encoding and exit codes
On Windows, the following PowerShell encoding and exit-code behaviors require Claude Code v2.1.214 or later:
- Redirection with `>` and `>>` writes UTF-8 files on PowerShell 5.1
- Claude Code encodes text piped to a native command’s standard input as UTF-8
- Claude Code captures error output without ANSI escape sequences
- A command whose child process waits on standard input receives end-of-file instead of hanging
- Exit code 1 from `where.exe` means no match, and from `fc.exe` and `diff.exe` it means the files differ, so when the command produces output, Claude Code treats that exit code as a valid negative answer rather than a command error. Claude Code still reports a silenced form, such as `where.exe /Q` or a redirect to `$null`, as a failure on exit code 1
Before v2.1.214, `>` on PowerShell 5.1 wrote UTF-16LE files, non-ASCII piped input arrived as `?`, and Python scripts could crash with a `UnicodeEncodeError` when printing non-ASCII characters.
[](#preview-limitations)
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)
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. When a whole-file read exceeds the token limit, Read returns the first page with a `PARTIAL view` notice that tells Claude how much of the file it received and how to read more with `offset` and `limit`. A read that passes an explicit `offset` or `limit` and still exceeds the token limit returns an error. A read with an explicit `limit` stops as soon as the selected lines exceed what the token limit could ever fit and returns an error without loading the rest of the range. The error tells Claude to use a smaller `limit`, or to search for specific content with [Grep](#grep-tool-behavior) instead when a single line is that large. Before v2.1.208, Claude Code loaded the whole range into memory before rejecting it, so reading a file with an extremely long single line could run it out of memory. Reading an empty file returns a notice that the file exists but its contents are empty, and an `offset` past the last line returns a notice giving the file’s line count. Before v2.1.208, reading an empty file returned the past-the-end notice instead. 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. As of v2.1.196, an image that is still larger than 500KB after that resize is re-encoded as a JPEG at reduced quality with its pixel dimensions unchanged. 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. Page-range reads render pages with `pdftoppm` from poppler-utils, so install it with `brew install poppler` on macOS or `apt-get install poppler-utils` on Debian and Ubuntu. On Windows and other platforms, install a poppler build that puts `pdftoppm` on your `PATH`. Without it, a page-range read fails with `pdftoppm is not installed`.
- **Jupyter notebooks**: `.ipynb` files return all cells with their outputs, including code, markdown, and visualizations. Claude Code refuses to read a notebook file over 100 MB; the error tells Claude how to read a portion of the notebook instead, such as a slice of cells, with a shell command.
Read only reads files, not directories. Claude lists directory contents with a shell command such as `ls`.
[](#sendfeedback-tool-behavior)
SendFeedback tool behavior
Claude-drafted feedback is a feedback report about Claude Code that Claude writes for you. It requires Claude Code v2.1.238 or later. Claude Code saves each draft on your machine under `~/.claude/feedback/drafts/`, and nothing reaches Anthropic until you send it. Claude drafts one with the SendFeedback tool when:
- A tool or command keeps failing
- It can’t help with something you asked for
- You point out a mistake it made, or it notices one
- You ask it to file feedback
[](#what-you-see-when-claude-drafts)
What you see when Claude drafts
After Claude queues a draft, you see a card above your prompt with the draft’s title. Press `1` to review the draft, press `2` twice to send it as written, or press `0` to dismiss it. A dismissed draft stays in your queue. After you dismiss a card, Claude Code asks whether to turn Claude-drafted feedback off. It stops asking once you’ve declined twice. By default, you see at most three cards in a session; Anthropic can adjust that limit from the server without a release. After the limit, and whenever you set [`feedbackDrafts`](settings-reference.md#feedbackdrafts) to `quiet`, you see only a count of queued drafts in the prompt footer.
[](#review-and-edit-a-draft)
Review and edit a draft
Run `/feedback` with no argument to open your queue. It lists every queued draft from all your sessions, including drafts whose cards you dismissed or never saw. Select a draft to open it for review, where you can:
- Edit the title, area, and details
- Set **Send transcript** to `yes` or `no`. When the transcript from the session where Claude queued the draft is still available, it starts at `yes`, which sends that conversation to Anthropic; `no` sends the report only
- Send the draft, discard it, or leave it in the queue for later
To write a report yourself instead, press `w` for the standard feedback dialog. `/feedback` with text after it, and `/bug`, open that dialog directly.
[](#send-a-draft)
Send a draft
When you send a draft, Claude Code submits it the same way as a `/feedback` report, with the same [retention](../13-Enterprise-Admin/data-usage.md#feedback-using-the-%2Ffeedback-command), and deletes the draft from your machine. When you send from the card, it shows `✓ Sent`; when you send from the queue, it closes with a receipt ID. The report carries:
- Your title, area, and details
- Environment info, such as your Claude Code version, operating system, and model
- The IDs of recent API requests
- The conversation transcript, when you left **Send transcript** at `yes` in the review screen. Sending from the card never includes the transcript
Claude Code keeps your working directory in the local draft so it can find the transcript, and doesn’t send the directory. In [organizations with zero data retention](zero-data-retention.md#features-disabled-under-zdr), Claude Code leaves the tool out, as it does for `/feedback`. If a session in such an organization still offers the tool, drafts stay on your machine, and sending fails with `Feedback collection is not available for organizations with custom data retention policies.`
[](#discard-or-keep-a-draft)
Discard or keep a draft
When you discard a draft, Claude Code deletes it from your machine. A draft you leave in the queue expires after 30 days, or after [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays) when that’s shorter. The queue holds 10 drafts across all your sessions, and when Claude queues an eleventh, Claude Code deletes the oldest. When you run `/exit` with drafts from the session still in the queue, Claude Code asks whether to review them or discard them before exiting.
[](#turn-claude-drafted-feedback-off)
Turn Claude-drafted feedback off
Set **Claude-drafted feedback** to `off` in `/config`, which writes the [`feedbackDrafts`](settings-reference.md#feedbackdrafts) setting, or set [`CLAUDE_CODE_SEND_FEEDBACK=0`](env-vars.md) for one session. With either, Claude can’t queue drafts. To keep drafting on without cards, set `feedbackDrafts` to `quiet` instead. Administrators can set `feedbackDrafts` in [managed settings](../13-Enterprise-Admin/managed-settings.md), which takes precedence over your own setting.
[](#sessions-without-claude-drafted-feedback)
Sessions without Claude-drafted feedback
Claude Code includes the tool in interactive terminal sessions on your own machine that use the Claude API rather than a cloud provider. It leaves the tool out of:
- Non-interactive `-p` runs and [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md) sessions, which have no screen to review the queue on
- [Cloud sessions](claude-code-on-the-web.md), which can’t write to the queue on your machine
- Sessions on [Amazon Bedrock](amazon-bedrock.md), [Claude Platform on AWS](claude-platform-on-aws.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md)
- Sessions where you set [`CLAUDE_CODE_SEND_FEEDBACK=0`](env-vars.md) or [`DISABLE_FEEDBACK_COMMAND=1`](env-vars.md), set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` to any non-empty value, or turned off [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching)
- Organizations that have turned off product feedback, and [organizations with zero data retention](zero-data-retention.md#features-disabled-under-zdr)
[](#task-tool-availability)
Task tool availability
The task-tracking tools, `TaskCreate`, `TaskGet`, `TaskUpdate`, `TaskList`, and `TodoWrite`, are available by default only on Claude 3.x models, Opus 4 through 4.7, Sonnet 4 through 4.6, and Haiku 4.5. Wherever the tools are available, you get the four Task tools, or `TodoWrite` instead when you set [`CLAUDE_CODE_ENABLE_TASKS=0`](env-vars.md). On every other model, Claude Code leaves the tools out unless you opt in. The same applies to a model ID Claude Code doesn’t recognize, such as a custom model name served through an [LLM gateway](../13-Enterprise-Admin/llm-gateway.md). On newer models, Claude keeps track of multi-step work without a written checklist, and the tools’ definitions and reminders take up context. Without the tools, Claude adds nothing to the [task list](interactive-mode.md#task-list) while it works. If you’d like to use these tools on a model that doesn’t have them by default, do one of the following:
- Export [`CLAUDE_CODE_ENABLE_TODO_TOOLS=1`](env-vars.md) before you start Claude Code, for example `CLAUDE_CODE_ENABLE_TODO_TOOLS=1 claude`. Claude Code then provides the same tools on every model and every provider
- Name one of the tools in [`--allowedTools`](cli-reference.md#cli-flags), for example `claude --allowedTools TaskCreate`
- List the tools in [`--tools`](cli-reference.md#cli-flags), which restricts the session’s built-in tools to the ones it names. Include the tools you want alongside the other built-in tools you use
- In the Agent SDK, the [`allowedTools` and `tools` options](../05-Agent-SDK/agent-sdk-todo-tracking.md#model-availability) work the same way as the two flags
In [background sessions](../09-Agents-Patterns/agent-view.md) and in [cloud sessions](claude-code-on-the-web.md), Claude Code provides the same tools on every model, listed or not. Claude Code gives a subagent the tools only when your session has them, even when the subagent runs a different model. An in-process [agent team](../09-Agents-Patterns/agent-teams.md) teammate follows your session the same way, while a teammate in its own [split pane](../09-Agents-Patterns/agent-teams.md#choose-a-display-mode) runs as a separate Claude Code process, so its own model decides. Without the Task tools, an agent coordinates with its team through messages instead of the [shared task list](../09-Agents-Patterns/agent-teams.md#assign-and-claim-tasks). The default set described here applies in Claude Code v2.1.268 and later.
[](#webfetch-tool-behavior)
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 doesn’t mention something may only mean the prompt didn’t 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:
- WebFetch refuses `localhost` and any other hostname without a dot, such as a bare intranet name, before making a request. The [error it returns](errors.md#webfetch-cannot-fetch-localhost) tells Claude to reach local servers with `curl` through Bash instead.
- HTTP URLs are automatically upgraded to HTTPS.
- Large pages are truncated to a fixed character limit before processing.
- WebFetch caches each response for 15 minutes by default, so repeated fetches of the same URL return quickly. On Claude Code v2.1.233 or later, set [`CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS`](env-vars.md#variables) to change how long WebFetch keeps each response.
- A page that hasn’t finished downloading within five minutes, including any redirects WebFetch follows, fails with a deadline error. On Claude Code v2.1.268 or later, set [`CLAUDE_CODE_WEBFETCH_DEADLINE_MS`](env-vars.md#variables) to change the limit, or to `0` to remove it.
- 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.
- When the extraction step hits an overloaded API, Claude Code retries it with backoff; a fetch that still fails returns an error result. Before v2.1.212, the API error text could reach Claude as if it were the extracted page content.
In Manual and `acceptEdits` [permission modes](permission-modes.md), WebFetch prompts before fetching, except for domains your [permission rules](permissions.md#manage-permissions) already allow or deny and a built-in set of preapproved documentation domains that fetch without a prompt. Whatever your rules allow, a fetch also passes the [WebFetch domain safety check](../13-Enterprise-Admin/data-usage.md#webfetch-domain-safety-check) first; that section covers what the check sends and the setting that skips it. The prompt offers three options:
- **Yes**: approves this fetch only. The next WebFetch call prompts again, even for the same domain.
- **Yes, and don’t ask again for `<domain>`**: approves the fetch and saves a `WebFetch(domain:...)` allow rule for that domain to `.claude/settings.local.json` for that repository. See [how saved approvals persist](permissions.md#permission-system). When your organization sets [`allowManagedPermissionRulesOnly`](permissions.md#managed-only-settings), Claude Code hides this option.
- **No, and tell Claude what to do differently**: rejects the fetch.
To allow a domain in advance without a prompt, add an allow rule like `WebFetch(domain:example.com)`; `WebFetch(domain:*)` allows every domain. The `auto` and `bypassPermissions` [permission modes](permissions.md#permission-modes) skip the prompt, except for a domain an explicit `ask` rule matches. An explicit `WebFetch(domain:...)` rule in `deny`, `ask`, or `allow` takes precedence over the preapproved set, so you can block a preapproved domain or require a prompt for it. 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. Sandboxed commands don’t inherit WebFetch’s built-in set of preapproved documentation domains. To let a sandboxed command reach a domain without a prompt, add the domain to [`allowedDomains`](settings-reference.md#sandbox-network-alloweddomains) or allow it with a `WebFetch(domain:...)` rule, which the [sandbox also honors](sandboxing.md#network-isolation). WebFetch never reads the sandbox allowlist in return, so adding a domain to a sandbox or organization network allowlist doesn’t stop WebFetch from prompting for it.
[](#websearch-tool-behavior)
WebSearch tool behavior
WebSearch runs a query against Anthropic’s [web search](../04-API-Reference/Agents-Tools/agents-and-tools-tool-use-web-search-tool.md) backend and returns result titles and URLs. It doesn’t fetch the result pages. To read a page Claude finds in search results, it follows up with [WebFetch](#webfetch-tool-behavior). 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 can’t be combined in a single call. When the search request hits an overloaded API, Claude Code retries it with backoff; a call that still fails returns an error result. Before v2.1.212, the API error text could reach Claude as if it were search results. WebSearch permission rules take no specifier. A bare `WebSearch` entry in `allow` or `deny` is the only form. The search backend is not configurable. To search with a different provider, add an [MCP server](../06-MCP-Tools/General/mcp.md) that exposes a search tool.
WebSearch is available on the Claude API and [Claude Platform on AWS](claude-platform-on-aws.md). On Microsoft Foundry it requires a [deployment hosted on Anthropic](../04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md#hosting-options): deployments hosted on Azure don’t support server-side tools, so the WebSearch call fails. On Google Cloud’s Agent Platform it works with Claude 4 and later models, including Opus, Sonnet, and Haiku. Amazon Bedrock doesn’t expose the server-side web search tool.
[](#session-search-limit)
Session search limit
A session can make at most 200 WebSearch calls, counted across the main conversation and every [subagent](../09-Agents-Patterns/sub-agents.md) it spawns, so searches made by parallel research fan-outs count against the same limit. The limit requires Claude Code v2.1.212 or later. When Claude reaches the limit, further calls return a notice telling Claude to continue with the information it already gathered, rather than an error that would invite a retry. You don’t see the notice: a capped call appears in the conversation as a search that did nothing, and if Claude needs more searches, the notice tells it to ask you to raise the limit. Set the [`CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION`](env-vars.md) environment variable to change the cap; it accepts a positive whole number, so the cap can be raised but not turned off. Running [`/clear`](commands.md#all-commands) resets the count. If work that can still spawn [subagents](../09-Agents-Patterns/sub-agents.md) survives the clear, such as a running workflow, the count carries over instead.
[](#write-tool-behavior)
Write tool behavior
The Write tool creates a new file or overwrites an existing one with the full content provided. It doesn’t append or merge. Whether Claude must read an existing file in the current conversation before overwriting it depends on the model and the file:
- Claude Opus 4.6, Claude Haiku 4.5, and older models always require the read, so a Write to an unread existing file fails with an error.
- Newer models can overwrite a file they never read this session under the same conditions as [read-before-edit](#edit-tool-behavior): reading it wouldn’t need a permission prompt and the Read tool is available.
- Jupyter notebooks, and files Claude has read only partially with a [`PARTIAL view` notice](#read-tool-behavior), require the read on every model.
This constraint doesn’t apply to new files. Before v2.1.228, every model required the read before overwriting an existing file. Viewing the file with Bash also satisfies this requirement under the same rules described in [Edit tool behavior](#edit-tool-behavior). For partial changes to an existing file, Claude uses Edit instead of Write.
[](#check-which-tools-are-available)
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:
```python
What tools do you have access to?
```
Claude gives a conversational summary. For exact MCP tool names, run `/mcp`.
The [advisor tool](advisor.md) is a [server tool](../04-API-Reference/Agents-Tools/agents-and-tools-tool-use-advisor-tool.md) that the API runs, rather than a tool that Claude Code implements. It has no name you can reference in permission rules or hook matchers.
[](#see-also)
See also
- [MCP servers](../06-MCP-Tools/General/mcp.md): add custom tools by connecting external servers
- [Permissions](permissions.md): permission system, rule syntax, and tool-specific patterns
- [Subagents](../09-Agents-Patterns/sub-agents.md): configure tool access for subagents
- [Hooks](../07-Hooks/hooks-guide.md): run custom commands before or after tool execution
---
## Troubleshoot Claude Code installation and authentication | Claude Help Center
Source: https://support.claude.com/en/articles/14552646-troubleshoot-claude-code-installation-and-authentication
Path: 02-Claude-Code-CLI/troubleshoot-claude-code-installation-and-authentication.md
# Troubleshoot Claude Code installation and authentication
April 15, 2026
These ten issues account for the large majority of installation and authentication support tickets related to Claude Code. Each entry includes the most reliable fix.
## 1. **claude: command not found** right after installing.
The installer added `claude` to your PATH, but your current shell has not picked it up yet. Open a new terminal, or run `source ~/.zshrc` (or `~/.bashrc`). On Windows, close and reopen PowerShell.
## 2. npm install fails with `EACCES` / permission denied.
This usually means the install was run with `sudo`, or your global npm directory is root-owned. Do not use sudo. Instead, use the native installer (`curl -fsSL https://claude.ai/install.sh | bash`), or fix npm's prefix with `npm config set prefix ~/.npm-global` and add that `bin` directory to your PATH.
## 3. "Node version not supported" or silent crash on launch.
Claude Code requires **Node 18 or later**. Check your version with `node -v`. If it is older, install a current version via `nvm install --lts`, or use the native installer, which bundles its own runtime and avoids this issue entirely.
## 4. WSL: **claude** runs the Windows Node instead of Linux Node.
Windows PATH leaks into WSL and overrides nvm. Prepend your Linux node to PATH in `~/.bashrc`: `export PATH="$HOME/.nvm/versions/node/$(nvm current)/bin:$PATH"`
## 5. Installer hangs or fails behind a corporate network.
The download host (`storage.googleapis.com`) is likely blocked. Set your proxy first with `export HTTPS_PROXY=http://proxy.example.com:port`, then re-run the installer. If that is not possible, ask your IT team for the offline package.
## 6. **SELF_SIGNED_CERT_IN_CHAIN** or other TLS errors.
Your company injects its own certificate. Point Node at the corporate CA bundle: `export NODE_EXTRA_CA_CERTS=/path/to/company-ca.pem` Add it to your shell profile so it persists.
## 7. **/login** opens a browser but the terminal never finishes ("Waiting for authentication…").
This usually means the localhost callback is blocked, which is common over remote SSH, in devcontainers, or behind a strict firewall. Use the manual flow instead: copy the URL printed in the terminal, complete login in any browser, then paste the returned code back into the terminal.
## 8. "Not authenticated" even though you set `ANTHROPIC_API_KEY`.
There are three common causes: the key was exported in a different shell (run `echo` `$ANTHROPIC_API_KEY` to check), Claude Code has not yet been told to trust this key (it prompts once on first use; until you approve, `ANTHROPIC_API_KEY` takes precedence over any OAuth session only after that approval), or the key is a Console key but your organization requires SSO login instead.
## 9. Bedrock / Vertex: "Could not load credentials."
Claude Code uses the standard provider SDKs, so the fix is the same as for any AWS/GCP CLI tool. For Bedrock, confirm `aws sts get-caller-identity` works and `AWS_REGION` is set to a region where your model is enabled. For Vertex, confirm `gcloud auth application-default login` has been run and that `ANTHROPIC_VERTEX_PROJECT_ID` and `CLOUD_ML_REGION` are set.
## 10. It installed and authenticated, but every request errors with 403 / "model not available."
Your account exists but does not have access to the model Claude Code is requesting. For Enterprise seats, confirm that your seat is active in your organization's admin settings. On Bedrock or Vertex, confirm that the specific Claude model is enabled in that region or project. As a quick workaround, run `/model` and select a model you know you have access to.
## Still stuck?
Run `claude doctor` from your normal shell (not from inside a Claude session). It prints a diagnostic report you can attach to a support ticket. For the full list of known issues, see the **[troubleshooting guide](troubleshooting.md)**.
---
## Troubleshoot installation and login - Claude Code Docs
Source: https://code.claude.com/docs/en/troubleshoot-install
Path: 02-Claude-Code-CLI/troubleshoot-install.md
## On this page
- [Find your error](#find-your-error)
- [Run diagnostic checks](#run-diagnostic-checks)
- [Check network connectivity](#check-network-connectivity)
- [Verify your PATH](#verify-your-path)
- [Check for conflicting installations](#check-for-conflicting-installations)
- [Check directory permissions](#check-directory-permissions)
- [Verify the binary works](#verify-the-binary-works)
- [Common installation issues](#common-installation-issues)
- [Install script returns HTML instead of a shell script](#install-script-returns-html-instead-of-a-shell-script)
- [command not found: claude after installation](#command-not-found-claude-after-installation)
- [curl: (56) Failure writing output to destination](#curl-56-failure-writing-output-to-destination)
- [Homebrew cask unavailable or outdated](#homebrew-cask-unavailable-or-outdated)
- [TLS or SSL connection errors](#tls-or-ssl-connection-errors)
- [Failed to fetch version from downloads.claude.ai](#failed-to-fetch-version-from-downloads-claude-ai)
- [Wrong install command on Windows](#wrong-install-command-on-windows)
- [running scripts is disabled on this system](#running-scripts-is-disabled-on-this-system)
- [The process cannot access the file during Windows install](#the-process-cannot-access-the-file-during-windows-install)
- [claude.exe missing after an update on Windows](#claude-exe-missing-after-an-update-on-windows)
- [Install killed on low-memory Linux servers](#install-killed-on-low-memory-linux-servers)
- [Install hangs in Docker](#install-hangs-in-docker)
- [Raw mode is not supported during install](#raw-mode-is-not-supported-during-install)
- [claude update or claude doctor hangs](#claude-update-or-claude-doctor-hangs)
- [Claude Desktop overrides the claude command on Windows](#claude-desktop-overrides-the-claude-command-on-windows)
- [Claude Code on Windows requires either Git for Windows (for bash) or PowerShell](#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell)
- [Claude Code does not support 32-bit Windows](#claude-code-does-not-support-32-bit-windows)
- [Linux musl or glibc binary mismatch](#linux-musl-or-glibc-binary-mismatch)
- [Illegal instruction](#illegal-instruction)
- [dyld: cannot load on macOS](#dyld-cannot-load-on-macos)
- [Exec format error on WSL1](#exec-format-error-on-wsl1)
- [npm install errors in WSL](#npm-install-errors-in-wsl)
- [Permission errors during installation](#permission-errors-during-installation)
- [Native binary not found after npm install](#native-binary-not-found-after-npm-install)
- [npm ENOTEMPTY error during update or reinstall](#npm-enotempty-during-update-or-reinstall)
- [Login and authentication](#login-and-authentication)
- [Reset your login](#reset-your-login)
- [OAuth error: Invalid code](#oauth-error-invalid-code)
- [403 Forbidden after login](#403-forbidden-after-login)
- [Claude Code access has not been granted for this account](#claude-code-access-has-not-been-granted-for-this-account)
- [This organization has been disabled with an active subscription](#this-organization-has-been-disabled-with-an-active-subscription)
- [OAuth login fails in WSL2, SSH, or containers](#oauth-login-fails-in-wsl2-ssh-or-containers)
- [Not logged in or token expired](#not-logged-in-or-token-expired)
- [Bedrock, Agent Platform, or Foundry credentials not loading](#bedrock-agent-platform-or-foundry-credentials-not-loading)
- [Still stuck](#still-stuck)
Troubleshooting
# Troubleshoot installation and login
Copy pageCopy page
Fix command not found, PATH, permission, network, and authentication errors when installing or signing in to Claude Code.
Copy pageCopy page
If installation fails or you can’t sign in, find your error below. For runtime issues after Claude Code is working, see [Troubleshooting](troubleshooting.md). For configuration problems such as settings not applying or hooks not firing, see [Debug your configuration](debug-your-config.md).
[](#find-your-error)
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](#command-not-found-claude-after-installation) |
| `syntax error near unexpected token '<'` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |
| `curl: (22) The requested URL returned error: 403` | [Install script returned 403](#install-script-returns-html-instead-of-a-shell-script) |
| `curl: (23)` or `curl: (56) Failure writing output to destination` | [Check connectivity or use an alternative installer](#curl-56-failure-writing-output-to-destination) |
| `Killed` during install on Linux, or `Installation was killed before it could finish (exit code 137)` | [Free memory or add swap space](#install-killed-on-low-memory-linux-servers) |
| `Raw mode is not supported` during install | [Rerun the installer](#raw-mode-is-not-supported-during-install) |
| `TLS connect error` or `SSL/TLS secure channel` | [Update CA certificates](#tls-or-ssl-connection-errors) |
| `Failed to fetch version` or can’t reach download server | [Check network and proxy settings](#check-network-connectivity) |
| `irm is not recognized` or `The token '&&' is not a valid statement separator` | [Use the right command for your shell](#wrong-install-command-on-windows) |
| `Cask 'claude-code' is unavailable: No Cask with this name exists` | [Update Homebrew](#homebrew-cask-unavailable-or-outdated) |
| `'bash' is not recognized as the name of a cmdlet` | [Use the Windows installer command](#wrong-install-command-on-windows) |
| `A parameter cannot be found that matches parameter name 'fsSL'` | [Use the Windows installer command](#wrong-install-command-on-windows) |
| `Claude Code on Windows requires either Git for Windows (for bash) or PowerShell` | [Install a shell](#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell) |
| `Claude Code does not support 32-bit Windows` | [Open Windows PowerShell, not the x86 entry](#claude-code-does-not-support-32-bit-windows) |
| `The process cannot access the file ... because it is being used by another process` | [Clear the downloads folder and retry](#the-process-cannot-access-the-file-during-windows-install) |
| `Error loading shared library` | [Wrong binary variant for your system](#linux-musl-or-glibc-binary-mismatch) |
| `Illegal instruction` | [Architecture or CPU instruction set mismatch](#illegal-instruction) |
| `cannot execute binary file: Exec format error` in WSL | [WSL1 native-binary regression](#exec-format-error-on-wsl1) |
| PowerShell installer completes but `claude` is not found or shows an old version | [Add the install directory to your PATH](#verify-your-path), then open a new terminal |
| `dyld: Symbol not found`, `dyld: cannot load`, or `Abort trap` on macOS | [Binary incompatibility](#dyld-cannot-load-on-macos) |
| `claude update` hangs after `Checking for updates`, or `claude doctor` hangs with no output | [Move the directory at a shell config path](#claude-update-or-claude-doctor-hangs) |
| `Invoke-Expression` or `iex` parse errors quoting HTML tags or CSS, or `ParserError` with `ParseException` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |
| `running scripts is disabled on this system` or `PSSecurityException` | [Allow the npm shims to run](#running-scripts-is-disabled-on-this-system) |
| `Error: claude native binary not installed` | [Complete the npm install](#native-binary-not-found-after-npm-install) |
| `npm error code ENOTEMPTY` during update or reinstall | [Remove the leftover package directory](#npm-enotempty-during-update-or-reinstall) |
| `'claude' is not recognized` right after an update on Windows | [Restore `claude.exe` from its backup](#claude-exe-missing-after-an-update-on-windows) |
| On Windows, the install command prints script text and nothing installs | [Run the complete install command](#wrong-install-command-on-windows) |
| `App unavailable in region` | Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries). |
| `unable to get local issuer certificate` | [Configure corporate CA certificates](#tls-or-ssl-connection-errors) |
| `OAuth error` or `403 Forbidden` | [Fix authentication](#login-and-authentication) |
| `Claude Code access has not been granted for this account` | [Get a role that includes Claude Code](#claude-code-access-has-not-been-granted-for-this-account) |
| `Unable to connect to Anthropic services` during setup | See [Unable to connect to Anthropic services](errors.md#unable-to-connect-to-anthropic-services) in the Error reference |
| `Could not load the default credentials` or `Could not load credentials from any providers` | [Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry credentials](#bedrock-agent-platform-or-foundry-credentials-not-loading) |
| `ChainedTokenCredential authentication failed` or `CredentialUnavailableError` | [Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry credentials](#bedrock-agent-platform-or-foundry-credentials-not-loading) |
| `API Error: 500`, `529 Overloaded`, `429`, or other 4xx and 5xx errors not listed above | See the [Error reference](errors.md) |
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](../16-Mobile-Desktop/desktop-quickstart.md) lets you install and use Claude Code through a graphical interface. Download it for [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs) or [Windows](https://claude.com/download?utm_source=claude_code&utm_medium=docs) and start coding without any command-line setup. On Linux, install the app with apt by following the [Linux install instructions](../16-Mobile-Desktop/desktop-linux.md).
[](#run-diagnostic-checks)
Run diagnostic checks
[](#check-network-connectivity)
Check network connectivity
The installer downloads from `downloads.claude.ai`. Verify you can reach it:
- macOS/Linux
- Windows PowerShell
```python
curl -sI https://downloads.claude.ai/claude-code-releases/latest
```
```python
curl.exe -sI https://downloads.claude.ai/claude-code-releases/latest
```
PowerShell aliases `curl` to `Invoke-WebRequest`, which rejects the `-sI` flags, so call `curl.exe` explicitly.
You reached the server if the first line shows a `200` status. You see `HTTP/2 200` on macOS and Linux, and `HTTP/1.1 200 OK` from the `curl.exe` included with Windows. Other results point to the cause:
- `403`: usually a proxy or network filter blocking the host, or Claude Code is [not available in your region](https://www.anthropic.com/supported-countries)
- `5xx`: usually a temporary service issue; wait a few minutes and retry
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
```python
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
curl -fsSL https://claude.ai/install.sh | bash
```
```python
$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)
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.
The [VS Code extension](../03-IDE-Integrations/vs-code.md) does not place `claude` at this location. It bundles a private copy of the CLI inside the extension directory for its own chat panel and does not add it to PATH. If you have only installed the extension, `~/.local/bin/claude` will not exist. Run the [standalone install](../01-Getting-Started/setup.md) to use `claude` from a terminal, then continue below.
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
```python
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](#check-for-conflicting-installations). If there’s no output, add it to your shell configuration.For Zsh, the default on macOS:
```python
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
For Bash on Linux, where it’s the default on most distributions:
```python
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```
For Bash on macOS, add the line to `~/.bash_profile` instead. Terminal on macOS starts Bash as a login shell, which ignores `~/.bashrc` and reads only the first of `~/.bash_profile`, `~/.bash_login`, or `~/.profile` that exists. If you already have a `~/.bash_login` or `~/.profile` and no `~/.bash_profile`, put the line in that file rather than creating `~/.bash_profile`:
```python
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
```
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:
```python
claude --version
```
```python
$env:PATH -split ';' | Select-String '\.local\\bin'
```
If there’s no output, add the install directory to your User PATH:
```python
$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:
```python
claude --version
```
```python
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:
```python
claude --version
```
[](#check-for-conflicting-installations)
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:
```python
which -a claude
```
If this prints nothing, no `claude` is on your PATH yet. Go back to [Verify your PATH](#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:
```python
ls -la ~/.local/bin/claude
```
A native install shows a symlink into `~/.local/share/claude/versions/`. A script or a symlink you created yourself at this path is a custom launcher, which [auto-update leaves in place](../01-Getting-Started/setup.md#auto-updates).If either `ls` command prints `No such file or directory`, that’s not an error. It means nothing is installed at that location, so move on to the next check.
```python
ls -la ~/.claude/local/
```
```python
npm -g ls @anthropic-ai/claude-code 2>/dev/null
```
List all `claude` binaries found in your PATH:
```python
where.exe claude
```
Check whether the native installer placed a binary:
```python
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:
```python
npm uninstall -g @anthropic-ai/claude-code
```
Remove the legacy local npm install:
- macOS/Linux
- Windows PowerShell
```python
rm -rf ~/.claude/local
```
```python
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:
```python
brew uninstall --cask claude-code
```
Remove a WinGet install on Windows:
```python
winget uninstall Anthropic.ClaudeCode
```
[](#check-directory-permissions)
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:
```python
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:
```python
sudo mkdir -p ~/.local/bin
sudo chown -R $(whoami) ~/.local
```
[](#verify-the-binary-works)
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](#verify-your-path) first; the commands below assume `claude` is on your PATH. Confirm the binary exists and is executable:
- macOS/Linux
- Windows PowerShell
```python
ls -la "$(command -v claude)"
```
```python
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](../01-Getting-Started/setup.md#alpine-linux-and-musl-based-distributions).
```python
ldd "$(command -v claude)" | grep "not found"
```
Confirm the binary can execute:
```python
claude --version
```
[](#common-installation-issues)
Common installation issues
These are the most frequently encountered installation problems and their solutions.
[](#install-script-returns-html-instead-of-a-shell-script)
Install script returns HTML instead of a shell script
When running the install command, you may see one of these errors:
```python
bash: line 1: syntax error near unexpected token `<'
bash: line 1: `<!DOCTYPE html>'
```
On PowerShell, the same problem appears as parse errors pointing into the returned page, with `iex` trying to run HTML and CSS as PowerShell:
```python
iex : At line:1 char:2310
+ ... igin="anonymous"/><script type="text/javascript">!function(o,c){var n ...
Missing argument in parameter list.
...
```
The wording varies with the PowerShell version and system language: you may see `Missing expression after unary operator '--'` or a `ParserError` with `ParseException` instead. HTML tags or CSS in the quoted text identify this failure. If you download with `-OutFile install.ps1` instead, the saved file is the same web page, so that doesn’t help either. Depending on how the request was routed, you may instead see a 403 with no HTML body:
```python
curl: (22) The requested URL returned error: 403
```
These all mean the install URL returned an HTML page or an error status 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](https://www.anthropic.com/supported-countries). A bare 403 with no body often has the same cause, but it can also come from a corporate proxy or firewall blocking the download. If you are in a supported country and still see the 403, work through [Check network connectivity](#check-network-connectivity) before trying the alternative installers below, since those reach the same hosts. Otherwise, this can happen due to network issues, regional routing, or a temporary service disruption. **Solutions:**
1. **Use an alternative install method**: On macOS, install via Homebrew:
``` shiki
brew install --cask claude-code
```
On Windows, install via WinGet:
``` shiki
winget install Anthropic.ClaudeCode
```
Then run `claude --version` to confirm: the command prints a version number such as `2.1.211 (Claude Code)`. If the shell reports `claude` isn’t found, open a new terminal window and retry: the session you installed from keeps its old `PATH`.
2. **Retry after a few minutes**: the issue is often temporary. Wait and try the original command again.
[](#command-not-found-claude-after-installation)
`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](#verify-your-path) for the fix on each platform.
[](#curl-56-failure-writing-output-to-destination)
`curl: (56) Failure writing output to destination`
The `curl ... | bash` command downloads the script and pipes it to Bash for execution. This error, and the related `curl: (23) Failure writing output to destination`, means Bash did not receive the complete script. Exit code 56 indicates the download itself was interrupted, and exit code 23 indicates curl could not write what it received to the pipe, usually because Bash exited early. Test that you can reach `downloads.claude.ai` with the check in [Check network connectivity](#check-network-connectivity). If you reached the server, the original failure was likely intermittent; retry the install command. You can also [try an alternative install method](../01-Getting-Started/setup.md#install-claude-code).
[](#homebrew-cask-unavailable-or-outdated)
Homebrew cask unavailable or outdated
Homebrew reports `Error: Cask 'claude-code' is unavailable: No Cask with this name exists` when your local copy of the Homebrew cask index predates the cask’s publication. Refresh the index and retry:
```python
brew update
brew install --cask claude-code
```
If Homebrew installs an older Claude Code version than you expect, the same stale index is usually the cause. The `claude-code` cask tracks the stable channel and is typically about one week behind the latest release; for the newest version run `brew install --cask claude-code@latest` instead. See [Configure release channel](../01-Getting-Started/setup.md#configure-release-channel) for the difference between the two casks.
[](#tls-or-ssl-connection-errors)
TLS or SSL connection errors
Errors such as these mean the TLS handshake failed:
- `curl: (35) TLS connect error`
- `schannel: next InitializeSecurityContext failed`
- PowerShell’s `Could not create SSL/TLS secure channel`
- PowerShell’s `Could not establish trust relationship for the SSL/TLS secure channel`
**Solutions:**
1. **Update your system CA certificates**: On Ubuntu/Debian:
``` shiki
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.
2. **On Windows, enable TLS 1.2** in PowerShell before running the installer:
``` shiki
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
irm https://claude.ai/install.ps1 | iex
```
3. **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, make the install download trust your corporate proxy’s CA:
- macOS/Linux
- Windows PowerShell
``` shiki
curl --cacert /path/to/corporate-ca.pem -fsSL https://claude.ai/install.sh | bash
```
The PowerShell installer downloads through .NET, which validates TLS against the Windows certificate store. Ask your IT team to add the proxy’s CA certificate to the Windows store if it isn’t already there, then run the installer:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
For Claude Code itself once installed, set `NODE_EXTRA_CA_CERTS` so API requests trust the same bundle:
- macOS/Linux
- Windows PowerShell
``` shiki
export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem
```
``` shiki
$env:NODE_EXTRA_CA_CERTS = 'C:\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.
4. **On Windows, work around blocked revocation checks**. The errors `CRYPT_E_NO_REVOCATION_CHECK (0x80092012)` and `CRYPT_E_REVOCATION_OFFLINE (0x80092013)` mean curl reached the server but your network blocks the certificate revocation lookup, which is common behind corporate firewalls. If the failing command is the `curl` that downloads `install.cmd`, rerun it from a Command Prompt with `--ssl-revoke-best-effort` added:
``` shiki
curl --ssl-revoke-best-effort -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
When the script’s own downloads hit the same errors, it retries them with best-effort revocation checking automatically, so the flag is only needed on the command you run yourself. Best-effort checking tolerates an unreachable revocation server but still rejects a certificate that is known to be revoked, matching how browsers handle revocation. You can also avoid curl’s revocation check entirely by running the PowerShell installer from PowerShell, which downloads through .NET and doesn’t fail when the revocation server is unreachable:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
You can also install with `winget install Anthropic.ClaudeCode`, which avoids curl entirely.
[](#failed-to-fetch-version-from-downloads-claude-ai)
`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. See [Check network connectivity](#check-network-connectivity).
[](#wrong-install-command-on-windows)
Wrong install command on Windows
If you see `'irm' is not recognized`, `The token '&&' is not a valid statement separator`, `A parameter cannot be found that matches parameter name 'fsSL'`, or `'bash' is not recognized as the name of a cmdlet`, you copied the install command for a different shell or operating system. If the command prints the script’s text instead of installing anything, you ran only part of it.
- **`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:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
Or stay in CMD and use the CMD installer instead:
``` shiki
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
- **`&&` not a valid statement separator**: you’re in PowerShell but ran the CMD installer command. Use the PowerShell installer:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
- **`A parameter cannot be found that matches parameter name 'fsSL'`**: you ran the macOS/Linux `curl -fsSL ... | bash` installer in Windows PowerShell, where `curl` is an alias for `Invoke-WebRequest` and rejects the `-fsSL` flags. Use the PowerShell installer instead:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
- **`bash` not recognized**: you ran the macOS/Linux installer on Windows. Use the PowerShell installer instead:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
- **The command prints script text instead of installing**: you ran the download half of the command without the part that executes it. `irm https://claude.ai/install.ps1` on its own prints the downloaded script to the terminal. Pipe it to `iex` to run it:
``` shiki
irm https://claude.ai/install.ps1 | iex
```
In CMD, `curl -fsSL https://claude.ai/install.cmd` without `-o` prints the batch script instead of saving it. Run the complete command:
``` shiki
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
Whichever installer you use, confirm it worked: open a new terminal and run `claude --version`, which prints a version number such as `2.1.211 (Claude Code)`.
[](#running-scripts-is-disabled-on-this-system)
`running scripts is disabled on this system`
Installing or running Claude Code through npm on Windows can fail with a `SecurityError`:
```python
npm : File C:\Program Files\nodejs\npm.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
...
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
```
The same error names `claude.ps1` when you run `claude` after an npm install. PowerShell’s execution policy is blocking the `.ps1` launcher scripts that npm creates for its commands. The policy applies to script files, so it doesn’t affect the PowerShell installer `irm https://claude.ai/install.ps1 | iex`, which runs the downloaded text directly. **Solutions:**
1. **Allow locally created scripts for your user**, then retry:
``` shiki
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
2. **Call the `.cmd` launcher instead**: `npm.cmd` and `claude.cmd` do the same job, and the policy doesn’t cover them.
3. **Use the [PowerShell installer](../01-Getting-Started/setup.md#install-claude-code)** instead of npm. It installs a binary rather than a `.ps1` script.
[](#the-process-cannot-access-the-file-during-windows-install)
`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:
```python
Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\downloads"
irm https://claude.ai/install.ps1 | iex
```
[](#claude-exe-missing-after-an-update-on-windows)
`claude.exe` missing after an update on Windows
If your terminal reports `'claude' is not recognized` right after Claude Code updated on Windows, check whether `%USERPROFILE%\.local\bin` still contains `claude.exe`. If that directory isn’t on your PATH at all, see [Fix your PATH](#command-not-found-claude-after-installation) instead. To update on Windows, Claude Code renames the existing `claude.exe` aside to a backup and moves the new version into its place. If moving the new version into place fails and Claude Code can’t rename the backup back either, the directory keeps the backup but has no `claude.exe`. The backup is a file in the same directory whose name begins with `claude.exe.old.` followed by a numeric timestamp. Run the following in PowerShell to rename the newest backup back to `claude.exe`:
```python
Get-ChildItem "$env:USERPROFILE\.local\bin\claude.exe.old.*" | Sort-Object Name | Select-Object -Last 1 | Rename-Item -NewName claude.exe
```
Then run `claude --version` to confirm the fix. A restored `claude.exe` prints a version number. If there’s no `claude.exe.old.*` file, or `claude` still fails after the rename, reinstall instead:
```python
irm https://claude.ai/install.ps1 | iex
```
Before v2.1.281, Claude Code could delete the backup while `claude.exe` was still missing.
[](#install-killed-on-low-memory-linux-servers)
Install killed on low-memory Linux servers
A `Killed` message during install usually means the Linux out-of-memory (OOM) killer terminated the `claude install` step because the system ran out of free memory. This is common on small VPS and cloud instances. The install script reports the cause and exits with code 137. In this example, the line number and process ID vary by release and run:
```python
Setting up Claude Code...
bash: line 183: 34803 Killed "$binary_path" install ${TARGET:+"$TARGET"}
Installation was killed before it could finish (exit code 137). This usually means the system ran out of memory.
Claude Code needs roughly 512MB of free memory to install. Free up memory, then run this script again.
```
Installing needs roughly 512 MB of free memory, and running Claude Code needs more. See the [system requirements](../01-Getting-Started/setup.md#system-requirements). **Solutions:**
1. **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:
``` shiki
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```
Then retry the installation:
``` shiki
curl -fsSL https://claude.ai/install.sh | bash
```
2. **Close other processes** to free memory before installing.
3. **Use a larger instance** if possible. Claude Code requires at least 4 GB of RAM.
[](#install-hangs-in-docker)
Install hangs in Docker
When installing Claude Code in a Docker container, installing as root into `/` can cause hangs. **Solutions:**
1. **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:
``` shiki
WORKDIR /tmp
RUN curl -fsSL https://claude.ai/install.sh | bash
```
2. **Give Docker more memory** if using Docker Desktop. Build containers share the memory allocated to the Docker Desktop virtual machine, so open **Settings \> Resources** in Docker Desktop, raise the memory limit, and rerun the build.
[](#raw-mode-is-not-supported-during-install)
`Raw mode is not supported` during install
When your organization’s [server-managed settings](../13-Enterprise-Admin/server-managed-settings.md) include changes that need [security approval](../13-Enterprise-Admin/server-managed-settings.md#security-approval-dialogs), Claude Code versions before 2.1.246 try to show the approval dialog during `claude install`. The dialog needs a terminal on stdin. When the installer runs `claude install` from a pipe, as `curl -fsSL https://claude.ai/install.sh | bash` does, stdin is the pipe rather than a terminal, so the install fails with an error containing `Raw mode is not supported`. Claude Code v2.1.246 and later don’t show the dialog during `claude install` or `claude update`. The command runs with the settings you last approved, and Claude Code shows the dialog in your next interactive session. If your organization’s startup configuration [waits for the settings fetch](../13-Enterprise-Admin/server-managed-settings.md#enforce-fail-closed-startup), such as when it sets `forceRemoteSettingsRefresh`, the dialog still appears during these commands, and an install run from a pipe still fails. In every other configuration, rerunning the installer gets past this error, because the script runs the latest release’s `install` command even when you ask it to install an older version. Rerun the command for your platform:
- macOS/Linux
- Windows PowerShell
```python
curl -fsSL https://claude.ai/install.sh | bash
```
```python
irm https://claude.ai/install.ps1 | iex
```
`claude --version` prints the version the rerun installed.
[](#claude-update-or-claude-doctor-hangs)
`claude update` or `claude doctor` hangs
`claude update` and `claude doctor` scan your shell configuration files for an outdated `claude` alias: `~/.zshrc`, `~/.bashrc`, and `~/.config/fish/config.fish`, plus on macOS the first of `~/.bash_profile`, `~/.bash_login`, or `~/.profile` that exists. If you set `ZDOTDIR`, the Zsh file is `$ZDOTDIR/.zshrc` instead. When one of those paths is a directory, Claude Code skips it and both commands complete normally. Before v2.1.214, a directory at one of those paths made both commands hang and left the System diagnostics section of `/status` blank. `claude doctor` hung with no output; `claude update` hung right after printing `Checking for updates`. If you hit the hang on an earlier version, find the directory. In this command’s output, a line starting with `d` marks that path as a directory. A `No such file or directory` line means nothing exists at that path and isn’t the cause:
```python
ls -ld ~/.zshrc ~/.bashrc ~/.bash_profile ~/.bash_login ~/.profile ~/.config/fish/config.fish
```
Move the directory aside, or update to v2.1.214 or later. Since `claude update` hangs on the affected versions, update by rerunning the [install script](../01-Getting-Started/setup.md#install-claude-code) instead.
[](#claude-desktop-overrides-the-claude-command-on-windows)
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 Windows requires either Git for Windows (for bash) or PowerShell
Git for Windows is optional. Claude Code uses the [PowerShell tool](tools-reference.md#powershell-tool) when Git Bash is absent, so this error means neither shell was found. **If PowerShell is missing from your PATH**, its default location is `C:\Windows\System32\WindowsPowerShell\v1.0\`. Add that directory to your `PATH`, or install [PowerShell 7](https://aka.ms/powershell), which provides `pwsh`. **To install Git for Windows instead**, download it from [git-scm.com/downloads/win](https://git-scm.com/downloads/win). During setup, select “Add to PATH.” Restart your terminal after installing. Installing it enables the Bash tool, useful when working with Bash-based scripts and tooling. **If Git is already installed** but Claude Code can’t find it, compare its location against the places Claude Code checks. When `CLAUDE_CODE_GIT_BASH_PATH` isn’t set, Claude Code looks for `bash.exe` in this order:
1. The default install locations `C:\Program Files\Git` and `C:\Program Files (x86)\Git`.
2. The `git` on your `PATH`, using the `bin\bash.exe` from that Git installation.
In step 2, Claude Code skips a `git` that sits in the folder you launched Claude Code from, or below it in a path that contains `node_modules` or a virtual-environment folder such as `.venv` or `env`, for example `C:\dev\env\myproject\Git` when you launched from `C:\dev\env\myproject`. This keeps Claude Code from running an executable that a project placed there. If your Git is in a location like that, point `CLAUDE_CODE_GIT_BASH_PATH` at it. **To point Claude Code at a specific Git installation**, find it by running `where.exe git` in PowerShell, then set the `bin\bash.exe` path from that installation as `CLAUDE_CODE_GIT_BASH_PATH` in your [settings.json file](settings.md):
```python
{
"env": {
"CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"
}
}
```
**If `CLAUDE_CODE_GIT_BASH_PATH` is set to the correct path and the file exists** but Claude Code still doesn’t use it, check the file’s name first. Claude Code accepts only a file named `bash.exe`, `sh.exe`, `bash`, or `sh`; with any other name, such as Git for Windows’ `git-bash.exe` launcher, it ignores the variable and auto-detects Git Bash as if it were unset, logging a warning visible with `--debug`. A path that doesn’t exist gets the same fallback and warning. Before v2.1.219, Claude Code used any existing file as the shell without checking its name, and exited at startup with `Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path` when the path didn’t exist. If the file’s name is right, endpoint security software such as AppLocker, Group Policy software restriction policies, or EDR agents may be interfering. Ask your IT team to allowlist `claude.exe` and the processes it spawns, including `cmd.exe` and `bash.exe`, in your endpoint protection policy.
[](#claude-code-does-not-support-32-bit-windows)
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:
```python
[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](../01-Getting-Started/setup.md#system-requirements).
[](#linux-musl-or-glibc-binary-mismatch)
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.
```python
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:**
1. **Check which libc your system uses**:
``` shiki
ldd --version 2>&1 | head -1
```
Output mentioning `GNU libc` or `GLIBC` means glibc. Output mentioning `musl` means musl.
2. **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](https://github.com/anthropics/claude-code/issues) with the output of `ldd --version` and `ls /lib/libc.musl*`.
3. **If you’re actually on musl**, such as Alpine Linux, install the required packages:
``` shiki
apk add libgcc libstdc++ ripgrep
```
On Alpine, `ripgrep` is in the community repository. If `apk` reports that the package is missing, see [Alpine Linux setup](../01-Getting-Started/setup.md#alpine-linux-and-musl-based-distributions).
[](#illegal-instruction)
`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](https://github.com/anthropics/claude-code/issues) 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](https://github.com/anthropics/claude-code/issues/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)
`dyld: cannot load` on macOS
If you see `dyld: Symbol not found`, `dyld: cannot load`, or `Abort trap: 6` during installation, the binary is incompatible with your macOS version or hardware. A `Symbol not found` error that references `libicucore` means your macOS version is older than the binary supports:
```python
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
```
The loader can instead reject the binary’s load commands, which also means your macOS version is too old:
```python
dyld: cannot load 'claude-2.1.42-darwin-x64' (load command 0x80000034 is unknown)
Abort trap: 6
```
**Solutions:**
1. **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.
2. **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)
`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](https://github.com/anthropics/claude-code/issues/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:
```python
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:
```python
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)
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](../01-Getting-Started/setup.md), 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`](https://github.com/nvm-sh/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`:
```python
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:
```python
source ~/.nvm/nvm.sh
```
If nvm is loaded but Windows paths still take priority, prepend your Linux Node path explicitly:
```python
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)
Permission errors during installation
If the native installer fails with permission errors, the target directory may not be writable. See [Check directory permissions](#check-directory-permissions). If you previously installed with npm and are hitting npm-specific permission errors, switch to the native installer:
```python
curl -fsSL https://claude.ai/install.sh | bash
```
[](#native-binary-not-found-after-npm-install)
Native binary not found after npm install
The `@anthropic-ai/claude-code` npm package downloads the native binary as a per-platform optional dependency, such as `@anthropic-ai/claude-code-darwin-arm64`. npm then runs the package’s postinstall script, which copies that binary into place as the `claude` command; until it runs, `claude` is a placeholder script. If either the download or the postinstall step is skipped, the placeholder stays in place, and running `claude` on macOS and Linux prints:
```python
Error: claude native binary not installed.
Either postinstall did not run (--ignore-scripts, some pnpm configs)
or the platform-native optional dependency was not downloaded
(--omit=optional).
Run the postinstall manually (adjust path for local vs global install):
node node_modules/@anthropic-ai/claude-code/install.cjs
Or reinstall without --ignore-scripts / --omit=optional.
```
On Windows, `bin/claude.exe` is that same shell-script placeholder rather than a real executable, so PowerShell and CMD report that they can’t run the file instead of printing this message. 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, and running `install.cjs` again can’t place a binary that was never downloaded.
- **Install scripts are disabled.** `--ignore-scripts` and some pnpm configurations skip the postinstall step but still download the platform package. Run `node node_modules/@anthropic-ai/claude-code/install.cjs` as the message suggests, or reinstall without the flag. If postinstall can’t run in your environment at all, `node node_modules/@anthropic-ai/claude-code/cli-wrapper.cjs` finds the downloaded package and launches it, at the cost of an extra Node process on each start. If the wrapper prints `Could not find native binary package` instead, the platform package was never downloaded, so fix the optional-dependencies cause above first.
- **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](../01-Getting-Started/setup.md#system-requirements). On FreeBSD, the installer reports the platform as unsupported. Before v2.1.205, it treated FreeBSD as Linux and downloaded a binary that couldn’t run.
- **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.
[](#npm-enotempty-during-update-or-reinstall)
npm `ENOTEMPTY` error during update or reinstall
When you run `npm install -g @anthropic-ai/claude-code` over an existing installation, npm can fail while moving the old package directory aside:
```python
npm error code ENOTEMPTY
npm error syscall rename
npm error path /home/you/.nvm/versions/node/v22.13.1/lib/node_modules/@anthropic-ai/claude-code
npm error dest /home/you/.nvm/versions/node/v22.13.1/lib/node_modules/@anthropic-ai/.claude-code-tVWAnUUt
npm error errno -39
npm error ENOTEMPTY: directory not empty, rename '...'
```
The `npm error path` line names the directory npm couldn’t move. Delete that directory and any leftover `.claude-code-*` directories next to it, which earlier interrupted runs can leave behind. The commands below find your global package directory with `npm root -g`; if the directory the `npm error path` line names is not under the directory `npm root -g` prints, for example because you switched Node versions with nvm, delete the directories the error names instead:
- macOS/Linux
- Windows PowerShell
```python
rm -rf "$(npm root -g)/@anthropic-ai/claude-code"
```
Then remove any leftover temp directories. If Zsh prints `no matches found`, there were none to remove:
```python
rm -rf "$(npm root -g)/@anthropic-ai/.claude-code-"*
```
```python
Remove-Item -Recurse -Force "$(npm root -g)/@anthropic-ai/claude-code", "$(npm root -g)/@anthropic-ai/.claude-code-*"
```
Then reinstall:
```python
npm install -g @anthropic-ai/claude-code
```
Confirm with `claude --version`, which prints a version number such as `2.1.211 (Claude Code)`.
[](#login-and-authentication)
Login and authentication
These sections address login failures, OAuth errors, and token issues.
[](#reset-your-login)
Reset your login
When login fails and the cause isn’t obvious, a clean re-authentication resolves most cases:
1. Run `/logout` to sign out completely
2. Close Claude Code
3. 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)
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)
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](https://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](../13-Enterprise-Admin/network-config.md) for proxy setup.
[](#claude-code-access-has-not-been-granted-for-this-account)
Claude Code access has not been granted for this account
If the sign-in page shows `Authorization failed` with the message `Claude Code access has not been granted for this account. Contact your administrator.` after you log in from Claude Code, your Claude Enterprise organization has set your role to Custom and none of the [custom roles](../17-Billing-Plans/manage-custom-roles-on-enterprise-plans.md) assigned to your groups grants Claude Code. On the Custom role, you get access only from those custom roles, so nothing you change in Claude Code resolves this error. To get access:
1. Ask an Owner of your Claude organization to assign a custom role that grants Claude Code access to one of your groups, or to change your role from Custom to a standard role such as User. Owners manage roles in the organization’s [role settings](https://claude.ai/admin-settings/roles).
2. After the Owner makes the change, run `claude` and log in again.
[](#this-organization-has-been-disabled-with-an-active-subscription)
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](../13-Enterprise-Admin/iam.md#authentication-precedence) for the full resolution order. To use your subscription instead, unset the environment variable and remove it from your shell profile:
- macOS/Linux
- Windows PowerShell
```python
unset ANTHROPIC_API_KEY
claude
```
```python
Remove-Item Env: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)
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:
```python
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:
```python
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)
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. Parallel sessions on one machine share a saved login and coordinate its renewal so that only one process refreshes the token at a time. Before v2.1.211, waking the machine from sleep could cause two sessions to renew with the same token, which revoked the saved login and prompted every open session to log in again at once. On macOS, Claude Code saves credentials to the login Keychain. When the Keychain rejects the write, such as when it’s locked in an SSH session or its password is out of sync with your account password, Claude Code saves your login to the plaintext `~/.claude/.credentials.json` file instead. A Console login that creates an API key fails until the Keychain is writable again. To make the Keychain writable again and move your login back into the encrypted Keychain:
1
Check Keychain access
Run `claude doctor` to check Keychain access. When the Keychain rejects writes, the report lists a warning that starts with `macOS Keychain is not writable`, followed by a suggested fix. When the report lists no Keychain warning, the Keychain is writable and you can skip to the last step.
2
Unlock the Keychain
```python
security unlock-keychain ~/Library/Keychains/login.keychain-db
```
Enter your Keychain password when the command asks for it, then run `claude doctor` again. When the unlock worked, the report no longer lists the Keychain warning.
3
Resync the Keychain password 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. Then run `claude doctor` again. Go on to the next step once the report no longer lists the Keychain warning.
4
Log out and back in
Once the Keychain is writable again, Claude Code moves the credentials back the next time it writes a credential. To force it now, run `/logout` and then `/login`. Logging out removes all stored credentials, including the plaintext file’s contents, saved MCP server logins, and plugin sensitive values, so expect to re-authorize MCP servers and re-enter plugin secrets afterwards. Logging in again stores your login in the Keychain.
[](#bedrock-agent-platform-or-foundry-credentials-not-loading)
Bedrock, Agent Platform, 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 Amazon Bedrock, `Could not load the default credentials` on Google Cloud’s Agent Platform, or `ChainedTokenCredential authentication failed` on Microsoft Foundry, your cloud provider CLI is likely not authenticated in the current shell. For Amazon Bedrock, confirm your AWS credentials are valid:
```python
aws sts get-caller-identity
```
For Google Cloud’s Agent Platform, confirm `ANTHROPIC_VERTEX_PROJECT_ID` and `CLOUD_ML_REGION` are set in your shell, then set application default credentials:
```python
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:
```python
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](amazon-bedrock.md), [Google Cloud’s Agent Platform](google-vertex-ai.md), or [Microsoft Foundry](microsoft-foundry.md) for full provider setup.
[](#still-stuck)
Still stuck
If none of the above resolves your issue:
1. Check the [GitHub repository](https://github.com/anthropics/claude-code/issues) for known issues, or open a new one with your operating system, the install command you ran, and the full error output
2. If `claude --version` works but something else is wrong, run `claude doctor` for an automated diagnostic report
3. If you can start a session, use `/feedback` inside Claude Code to report the problem
4. If the problem is with your account rather than the install, such as a login loop, a subscription that isn’t recognized, or a disabled organization, contact Anthropic support: sign in at [claude.ai](https://claude.ai) (Console users: [platform.claude.com](../04-API-Reference/Other/usage-limits.md)), click your initials in the lower left, and select **Get help**. See [How to get support](https://support.claude.com/en/articles/9015913-how-to-get-support) for the full flow.
---
## Troubleshooting - Claude Code Docs
Source: https://code.claude.com/docs/en/troubleshooting
Path: 02-Claude-Code-CLI/troubleshooting.md
## On this page
- [Performance and stability](#performance-and-stability)
- [High CPU or memory usage](#high-cpu-or-memory-usage)
- [Large tables are cut off in the terminal](#large-tables-are-cut-off-in-the-terminal)
- [Auto-compaction stops with a thrashing error](#auto-compaction-stops-with-a-thrashing-error)
- [Command hangs or freezes](#command-hangs-or-freezes)
- [Garbled or corrupted text in an editor’s integrated terminal](#garbled-or-corrupted-text-in-an-editor%E2%80%99s-integrated-terminal)
- [Mouse wheel scrolls one line at a time in fullscreen rendering](#mouse-wheel-scrolls-one-line-at-a-time-in-fullscreen-rendering)
- [Clipboard commands such as pbcopy fail inside the sandbox](#clipboard-commands-such-as-pbcopy-fail-inside-the-sandbox)
- [Copied text doesn’t reach your local clipboard over SSH](#copied-text-doesn%E2%80%99t-reach-your-local-clipboard-over-ssh)
- [Search and discovery issues](#search-and-discovery-issues)
- [Slow or incomplete search results on WSL](#slow-or-incomplete-search-results-on-wsl)
- [Get more help](#get-more-help)
Troubleshooting
# Troubleshooting
Copy pageCopy page
Fix high CPU or memory usage, hangs, auto-compact thrashing, and search problems in Claude Code, and find the right page for other issues.
Copy pageCopy page
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](troubleshoot-install.md) |
| Update or install download fails with `The connection dropped while downloading the update` or `aborted` | [Error reference](errors.md#the-connection-dropped-while-downloading-the-update) |
| Login loops, OAuth errors, `403 Forbidden`, “organization disabled”, Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry credentials | [Troubleshoot installation and login](troubleshoot-install.md#login-and-authentication) |
| Settings not applying, hooks not firing, MCP servers not loading | [Debug your configuration](debug-your-config.md) |
| Session started in auto mode, or Claude edits files and runs commands without asking | [Which mode a session starts in](permission-modes.md#which-mode-a-session-starts-in) |
| `API Error: 5xx`, `529 Overloaded`, `429`, request validation errors | [Error reference](errors.md) |
| `model not found` or `you may not have access to it` | [Error reference](errors.md#theres-an-issue-with-the-selected-model) |
| A command Claude runs fails with `Your disk quota is full`, `is full (ENOSPC)`, or `Command output was lost` | [Error reference](errors.md#disk-quota-or-temp-filesystem-is-full) |
| VS Code extension not connecting or detecting Claude | [VS Code integration](../03-IDE-Integrations/vs-code.md#fix-common-issues) |
| `Claude Code process exited with code 1` in VS Code or an SDK app | [Error reference](errors.md#claude-code-process-exited-with-code-n) |
| JetBrains plugin or IDE not detected | [JetBrains integration](../03-IDE-Integrations/jetbrains.md#troubleshooting) |
| High CPU or memory, slow responses, hangs, search not finding files | [Performance and stability](#performance-and-stability) below |
If you’re not sure which applies, run `/doctor` inside Claude Code for an automated check of your installation, settings, extensions, and context usage; it proposes fixes it can apply after you confirm. If `claude` won’t start at all, run `claude doctor` from your shell instead. Run `/mcp` to check MCP server status.
[](#performance-and-stability)
Performance and stability
These sections cover issues related to resource usage, responsiveness, and search behavior.
[](#high-cpu-or-memory-usage)
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:
1. Use `/compact` regularly to reduce context size. If it returns `Not enough messages to compact.`, the conversation has too few turns to summarize; that can happen even with a full context when a single large paste filled it
2. Close and restart Claude Code between major tasks
3. Consider adding large build directories to your `.gitignore` file
4. Restart with [`claude --safe-mode`](cli-reference.md#cli-flags) to check whether a plugin, MCP server, or hook is the source. It disables all customizations for the session; if usage drops, see [Debug your configuration](debug-your-config.md#test-against-a-clean-configuration) to find which one
If a session’s heap memory passes 2.5GB, a critical memory usage warning appears. To free the memory, restart Claude Code and run [`claude --continue`](cli-reference.md#cli-flags) to resume the conversation in a fresh process. Outside [fullscreen rendering](fullscreen.md), running `/compact` frees memory too. The warning disappears once memory use drops back below 2.5GB. If memory usage stays high after these steps, run `/heapdump` to write two files to `~/Desktop`: a JavaScript heap snapshot named `<session-id>.heapsnapshot` and a memory breakdown named `<session-id>-diagnostics.json`. Claude Code [hides the command from the command menu](commands.md#how-the-command-menu-matches-what-you-type); type it in full. On Linux without a Desktop folder, the files are written to your home directory.
The `.heapsnapshot` file contains every string in the process, including your full conversation and credentials. Don’t attach it to a public issue or share it.
The command also prints a summary in the conversation, showing the process’s total memory, how much of it is in the JS heap, and how much sits outside the heap. The summary also lists any leak indicators, such as a high memory growth rate or an unusually high number of open handles. The summary says whether most memory is in the JS heap, which the snapshot captures, or in native memory, which it doesn’t. Report the output or investigate it yourself:
- **Report it**: open a [GitHub issue](https://github.com/anthropics/claude-code/issues) and attach only the `-diagnostics.json` file, which carries the statistics behind the printed summary and no conversation content or credentials
- **Investigate it yourself**: if the summary says most memory is JS heap, open the `.heapsnapshot` file in Chrome DevTools under Memory → Load and sort by retained size to see what’s holding the memory
If the summary says most memory is native, the snapshot can’t show it; include the summary’s leak indicators in your report instead.
[](#large-tables-are-cut-off-in-the-terminal)
Large tables are cut off in the terminal
A Markdown table with more than 200 rows renders its first 200 rows followed by a `… N more rows not shown` line. Only the display is capped: the full table stays in the conversation, and [`/copy`](commands.md) copies every row. For a table too large to read in the terminal, ask Claude to write it to a file instead. Before v2.1.208, Claude Code rendered every row, so resuming a session that contained a very large table could stall while it re-rendered.
[](#auto-compaction-stops-with-a-thrashing-error)
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:
1. Ask Claude to read the oversized file in smaller chunks, such as a specific line range or function, instead of the whole file
2. Run `/compact` with a focus that drops the large output, for example `/compact keep only the plan and the diff`
3. Move the large-file work to a [subagent](../09-Agents-Patterns/sub-agents.md) so it runs in a separate context window
4. Run `/clear` if the earlier conversation is no longer needed
[](#command-hangs-or-freezes)
Command hangs or freezes
If Claude Code seems unresponsive:
1. Press Ctrl+C to attempt to cancel the current operation
2. 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.
[](#garbled-or-corrupted-text-in-an-editor’s-integrated-terminal)
Garbled or corrupted text in an editor’s integrated terminal
If characters render as boxes, smears, or the wrong glyphs when running Claude Code in the VS Code, Cursor, or Devin Desktop integrated terminal, the terminal’s GPU renderer is likely the cause. Run `/terminal-setup` inside Claude Code to set `terminal.integrated.gpuAcceleration` to `"off"`, or set it manually in your editor settings and reload the window. See [Terminal configuration](terminal-config.md) for the other settings `/terminal-setup` writes.
[](#mouse-wheel-scrolls-one-line-at-a-time-in-fullscreen-rendering)
Mouse wheel scrolls one line at a time in fullscreen rendering
In [fullscreen rendering](fullscreen.md), Claude Code scrolls the conversation itself rather than leaving it to your terminal. If each wheel notch moves fewer lines than you want, run `/scroll-speed` to raise the number of lines per notch and save it, or set the `CLAUDE_CODE_SCROLL_SPEED` environment variable, except in the JetBrains IDE terminal, where Claude Code applies its own scroll handling and neither takes effect. See [Mouse wheel scrolling](fullscreen.md#mouse-wheel-scrolling) for the values each accepts. To move faster without changing the speed, press `PgUp` and `PgDn` to scroll half a screen at a time. To use your terminal’s native scrollback instead, run `/tui default` to switch to the classic renderer.
[](#clipboard-commands-such-as-pbcopy-fail-inside-the-sandbox)
Clipboard commands such as `pbcopy` fail inside the sandbox
When [sandboxing](sandboxing.md) is on, clipboard utilities such as `pbcopy`, `xclip`, and `wl-copy` can fail to reach the system clipboard from inside a sandboxed Bash command, leaving your clipboard unchanged after Claude pipes text to them. To put Claude’s output on your clipboard, ask Claude to print the content in its response, then run [`/copy`](commands.md). `/copy` writes to the clipboard from the Claude Code process itself rather than from a sandboxed command, so sandboxing doesn’t block it. It can copy a single code block instead of the whole response, and it also writes what it copied to a file and prints the path, which gives you a fallback when the clipboard write doesn’t reach your terminal, for example over SSH. When Claude pipes text to one of these tools, adding `pbcopy *`, `wl-copy *`, or `xclip *` to [`excludedCommands`](settings-reference.md#sandbox-excludedcommands) doesn’t take that call out of the sandbox on its own.
[](#copied-text-doesn’t-reach-your-local-clipboard-over-ssh)
Copied text doesn’t reach your local clipboard over SSH
When Claude Code runs on a remote machine over SSH, it can’t run a clipboard tool on your local machine. Outside tmux, when you select text in [fullscreen rendering](fullscreen.md) or run `/copy`, Claude Code sends the text to your terminal as an OSC 52 escape sequence instead. Your terminal decides whether to put it on your clipboard. `/copy` reports `Copied to clipboard` whether or not the text arrived, and outside tmux the selection notice reads `sent N chars via OSC 52`. Some terminals don’t act on OSC 52. iTerm2 ignores it until you turn on **Settings \> General \> Selection \> Applications in terminal may access clipboard**, and macOS Terminal.app doesn’t support it. To get the text without OSC 52:
- Hold your terminal’s native-selection key while you drag, then copy with your terminal’s usual shortcut, such as `Cmd+C`. The key is `Fn` in Terminal.app and `Option` in iTerm2. [Keep native text selection](fullscreen.md#keep-native-text-selection) lists it for other terminals.
- Set [`CLAUDE_CODE_DISABLE_MOUSE=1`](env-vars.md) on the remote machine so your terminal handles selection for the whole session.
[](#search-and-discovery-issues)
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
```python
brew install ripgrep
```
```python
sudo apt install ripgrep
```
```python
apk add ripgrep
```
`ripgrep` is in Alpine’s community repository. If `apk` reports that the package is missing, see [Alpine Linux setup](../01-Getting-Started/setup.md#alpine-linux-and-musl-based-distributions).
```python
pacman -S ripgrep
```
```python
winget install BurntSushi.ripgrep.MSVC
```
Then set `USE_BUILTIN_RIPGREP` to `0`, either in your shell [environment](env-vars.md) or in the `env` block of your [`settings.json`](settings-reference.md#all-settings):
```python
{
"env": {
"USE_BUILTIN_RIPGREP": "0"
}
}
```
To confirm the switch took effect, run `claude doctor` in your terminal and check that the Search line shows the path of your system ripgrep instead of `OK (bundled)`.
[](#slow-or-incomplete-search-results-on-wsl)
Slow or incomplete search results on WSL
Disk read performance penalties when [working across file systems on WSL](https://learn.microsoft.com/en-us/windows/wsl/filesystems) 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.
`claude doctor` shows Search as OK in this case.
**Solutions:**
1. **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”.
2. **Move project to Linux filesystem**: if possible, ensure your project is located on the Linux filesystem (`/home/`) rather than the Windows filesystem (`/mnt/c/`).
3. **Use native Windows instead**: consider running Claude Code natively on Windows instead of through WSL, for better file system performance.
[](#get-more-help)
Get more help
If you’re experiencing issues not covered here:
1. Run `/doctor` for a setup checkup and `/mcp` to check MCP server status
2. Use the `/feedback` command within Claude Code to report problems directly to Anthropic
3. Check the [GitHub repository](https://github.com/anthropics/claude-code) for known issues
4. Ask Claude directly about its capabilities and features. Claude has built-in access to its documentation.
For account, billing, or subscription problems, contact Anthropic support instead: sign in at [claude.ai](https://claude.ai) (Console users: [platform.claude.com](../04-API-Reference/Other/usage-limits.md)), click your initials in the lower left, and select **Get help**. See [How to get support](https://support.claude.com/en/articles/9015913-how-to-get-support) for the full flow, including who can reach a human agent on each plan.
---
## Plan in the cloud with ultraplan - Claude Code Docs
Source: https://code.claude.com/docs/en/ultraplan
Path: 02-Claude-Code-CLI/ultraplan.md
## On this page
- [Launch ultraplan from the CLI](#launch-ultraplan-from-the-cli)
- [Review and revise the plan in your browser](#review-and-revise-the-plan-in-your-browser)
- [Choose where to execute](#choose-where-to-execute)
- [Execute on the web](#execute-on-the-web)
- [Send the plan back to your terminal](#send-the-plan-back-to-your-terminal)
- [Related resources](#related-resources)
Claude Code on the web
# Plan in the cloud with ultraplan
Copy pageCopy page
Start a plan from your CLI, draft it on Claude Code on the web, then execute it remotely or back in your terminal
Copy pageCopy page
Ultraplan is in research preview. Behavior and capabilities may change based on feedback.
Ultraplan hands a planning task from your local CLI to a [Claude Code on the web](claude-code-on-the-web.md) session running in [plan mode](permission-modes.md#analyze-before-you-edit-with-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](claude-code-on-the-web.md) account and a GitHub repository. Because it runs on Anthropic’s cloud infrastructure, it is not available when using Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry. The cloud session runs in your default [cloud environment](cloud-environments.md); use [`/remote-env`](cloud-environments.md#select-an-environment-from-the-cli) in your terminal to change which environment that is. If you don’t have a cloud environment yet, ultraplan creates one automatically when it first launches.
[](#launch-ultraplan-from-the-cli)
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:
```python
/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](remote-control.md) 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 cloud 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)
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)
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)
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](claude-code-on-the-web.md#review-changes) and create a pull request from the web interface.
[](#send-the-plan-back-to-your-terminal)
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)
Related resources
- [Claude Code on the web](claude-code-on-the-web.md): the cloud infrastructure ultraplan runs on
- [Plan mode](permission-modes.md#analyze-before-you-edit-with-plan-mode): how planning works in a local session
- [Find bugs with ultrareview](ultrareview.md): the code review counterpart to ultraplan for catching issues before merge
- [Remote Control](remote-control.md): use the claude.ai/code interface with a session running on your own machine
---
## Find bugs with ultrareview - Claude Code Docs
Source: https://code.claude.com/docs/en/ultrareview
Path: 02-Claude-Code-CLI/ultrareview.md
## On this page
- [Run ultrareview from the CLI](#run-ultrareview-from-the-cli)
- [Review against a different base](#review-against-a-different-base)
- [Review a pull request](#review-a-pull-request)
- [Post findings to the pull request](#post-findings-to-the-pull-request)
- [Pass a request in plain words](#pass-a-request-in-plain-words)
- [Diff limits and fallbacks](#diff-limits-and-fallbacks)
- [Pricing and free runs](#pricing-and-free-runs)
- [Track a running review](#track-a-running-review)
- [Run ultrareview non-interactively](#run-ultrareview-non-interactively)
- [How ultrareview compares to /code-review](#how-ultrareview-compares-to-%2Fcode-review)
- [Related resources](#related-resources)
Claude Code in the cloud
# Find bugs with ultrareview
Copy pageCopy page
Run a deep, multi-agent code review in the cloud with /code-review ultra to find and verify bugs before you merge.
Copy pageCopy page
Ultrareview is a research preview feature. The feature, pricing, and availability may change based on feedback. The command is `/code-review ultra`. When ultrareview is available to your account, `/ultrareview` is an alias.
Ultrareview is a deep code review that runs as a [cloud session](claude-code-on-the-web.md) on Anthropic’s infrastructure. When you run `/code-review ultra`, Claude Code launches a fleet of reviewer agents in a cloud sandbox to find bugs in your branch or pull request. Compared to a local `/code-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**: a larger fleet of reviewer agents explores the change in parallel, which surfaces issues that a local review can miss
- **No local resource use**: the review runs entirely in a cloud sandbox, so your terminal stays free for other work while it runs
Ultrareview requires authentication with a claude.ai account because it runs as a cloud session on Anthropic’s 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’s Agent Platform, or Microsoft Foundry, and it is not available to organizations that have enabled Zero Data Retention. When ultrareview is not available, `/code-review ultra` runs a local review in your session instead.
[](#run-ultrareview-from-the-cli)
Run ultrareview from the CLI
Start a review from any git repository:
```python
/code-review ultra
```
Without arguments, ultrareview reviews the diff between your current branch and the default branch, including uncommitted and staged changes. For uncommitted changes to files named like credentials or keys, such as `.env` and `*.tfvars` files, Claude Code follows the rules for [uploading a local repository to a cloud session](claude-code-on-the-web.md#send-local-repositories-without-github). For a branch review, Claude Code bundles the repository state and uploads it to a cloud sandbox; when you [review a pull request](#review-a-pull-request), Claude Code uploads nothing from your machine. Before launching, Claude Code shows a confirmation dialog with the review scope, your remaining free runs, and the estimated cost; for a branch review, the scope includes the file and line count. After you confirm, the review continues in the background while you keep using your session. The command runs only when you invoke it with `/code-review ultra`; Claude doesn’t start an ultrareview on its own.
[](#review-against-a-different-base)
Review against a different base
To compare against a base other than the default branch, pass the branch name. This example reviews your current branch against `develop` instead:
```python
/code-review ultra develop
```
The base branch doesn’t need to exist in your local clone; Claude Code fetches it from `origin`. If the name has a typo, Claude Code suggests the closest branch name in the error. A commit id or tag also works as the base, and the review then covers the changes on your branch since that commit.
[](#review-a-pull-request)
Review a pull request
To review a GitHub pull request instead of a local branch, pass the PR number:
```python
/code-review ultra 1234
```
The command also accepts `#1234`, `PR 1234`, and pasted PR URLs; a pasted URL must point to the repository in your current directory. In PR mode, the cloud sandbox clones the pull request directly from the host rather than bundling your local working tree. PR mode works with repositories on `github.com` and on [GitHub Enterprise Server](github-enterprise-server.md) instances that an Owner has connected to Claude Code. For repositories on `github.com`, the sandbox clones with the GitHub account connected to your Claude account, so the account must be able to read the PR’s repository. Claude Code checks this before creating the cloud session, unless you’ve set [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](env-vars.md#variables), and refuses the launch when [no account is connected](errors.md#no-github-account-is-connected-to-your-claude-account) or [the account can’t see the repository](errors.md#your-connected-github-account-cant-see-the-repository); the refusal names the fix. Before v2.1.248, Claude Code didn’t check this before launch. Run [`/web-setup`](web-quickstart.md#connect-from-your-terminal) to connect your GitHub CLI login to your Claude account.
[](#post-findings-to-the-pull-request)
Post findings to the pull request
On Claude Code v2.1.227 or later, when you review a pull request on `github.com`, you can have Claude post the finished findings to the PR as a single plain comment from your own GitHub account. The comment isn’t a review or an approval, and it ends with a “Generated by Claude Code” note. When you review a branch or a GitHub Enterprise Server pull request, Claude Code shows the findings in your session only. Claude Code never posts unless you choose to on that run, and `--no-post` is the default. Posting is a choice you make for each run:
- **Interactive**: in the launch dialog, select **Run and post the findings to the PR as me**. If you add `--post` to the command, as in `/code-review ultra 1234 --post`, Claude Code preselects that choice and still asks before launching.
- **Non-interactive**: run the [`claude ultrareview` subcommand](#run-ultrareview-non-interactively) with `--post`. You consent to the post by running the subcommand with the flag, so Claude Code posts without asking. In a `claude -p '/code-review ultra'` run, Claude Code exits before the findings arrive, so it posts nothing; use the subcommand instead.
Claude Code doesn’t post from your machine. It sends the review’s session ID to the Anthropic API, which posts the review’s stored findings as the comment through the GitHub account you’ve connected to Claude. Posting requires the same claude.ai sign-in as the review itself, and it isn’t available on third-party providers or when you set [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](env-vars.md). In an interactive session, Claude Code starts the post when the findings arrive, so keep the session open until the review finishes. Claude Code keeps the posting choice only in that session. If the session ends before the review finishes, Claude Code posts nothing, even if you resume the conversation later. When the post finishes, Claude tells you the outcome:
- **Posted**: Claude gives you a link to the comment.
- **Already posted**: an earlier post of the same review already put the comment on the PR, so Claude links you to the pull request instead of posting again.
- **Failed**: Claude tells you why, and the findings stay in your terminal so you can post them by hand.
[](#pass-a-request-in-plain-words)
Pass a request in plain words
On Claude Code v2.1.218 or later, you can also describe what you’re working on in plain words:
```python
/code-review ultra check my auth changes
```
The review still covers your current branch, the same scope as running with no argument. Claude keeps your text as a note, shown in the launch dialog, and relates the findings to it when they arrive. Claude Code treats your text as a note only when it has more than one word and isn’t a branch name or PR reference. It reads a single word as a branch name or PR reference, so a mistyped branch name gets the closest-branch error from [Review against a different base](#review-against-a-different-base) instead of launching with a note. If your text combines a PR reference with other words, such as `check PR 123 again`, Claude Code doesn’t launch either; it asks you to rerun with the PR number alone to review that PR, or without the reference to review your current branch.
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 `/code-review ultra <PR-number>`.
[](#diff-limits-and-fallbacks)
Diff limits and fallbacks
Ultrareview checks the diff before any review work runs and tells you when it can’t review it as-is:
- **Diff too large**: a branch review can include up to 500 changed files and 8,000 changed lines by default. The exact values can change, and the [refusal](errors.md#diff-is-too-large-for-ultrareview) names the ones in effect, the size of your diff, and the files with the most changed lines. Claude Code refuses a too-large pull request the same way, naming its file and line counts but not the per-file breakdown
- **Nothing to review**: when the diff against the base is empty, ultrareview refuses and names the branch or commit it compared against and the case you’re in, such as being on the base branch itself with nothing uncommitted, or a branch whose commits are all part of the base already. It also suggests the way out for that case, such as switching to the branch with your work, staging or committing local edits, or passing a different base
- **First commit**: a repository’s first commit has nothing earlier to compare with, so ultrareview reviews every file in it after you confirm in the launch dialog. If you have untracked files, it refuses instead and tells you to `git add` the ones you want reviewed. The same size limits apply. A first commit is reviewed whole only after that confirmation, so the `claude ultrareview` subcommand and `claude -p` refuse it and point you to an interactive session instead. Requires Claude Code v2.1.277 or later
- **No merge base**: when your branch shares no history with the base branch, or the repository has no base branch to compare with, ultrareview reviews every tracked file in the repository instead. The fallback requires a full clone and applies the same size limits. It launches only when you confirm in the launch dialog or run the `claude ultrareview` subcommand yourself. In `claude -p` and anywhere else neither happens, ultrareview refuses, says the review would cover every file, and points you to an interactive session. On a checkout with no branches or other refs, such as a detached HEAD created by checking out `FETCH_HEAD` after fetching a URL, Claude Code [refuses the review](errors.md#your-checkout-has-no-branches) and suggests creating a branch first
[](#pricing-and-free-runs)
Pricing and free runs
Ultrareview is a premium feature that bills against usage credits rather than your plan’s included usage.
| Plan | Included free runs | After free runs |
|---------------------|--------------------|--------------------------------------------------------------------------------------------------------------|
| Pro | 3 free runs | billed as [usage credits](https://code.claude.com/docs/17-Billing-Plans/extra-usage-for-paid-claude-plans-32418755be.md) |
| Max | 3 free runs | billed as [usage credits](https://code.claude.com/docs/17-Billing-Plans/extra-usage-for-paid-claude-plans-32418755be.md) |
| Team and Enterprise | none | billed as [usage credits](https://code.claude.com/docs/17-Billing-Plans/extra-usage-for-paid-claude-plans-32418755be.md) |
- **Free runs**: the three Pro and Max runs are a one-time allotment per account and don’t refresh.
- **Cost per review**: after you use the free runs, typically \$5 to \$25 in usage credits depending on the size of the change, matching the estimate the launch dialog shows before each run.
- **When a run counts**: once the cloud session starts. A review you stop early or that fails to complete still uses a free run; a paid review bills only for the portion that ran.
Because ultrareview always bills as usage credits outside the free runs, your account or organization must have usage credits turned on before you can launch a paid review. If usage credits aren’t turned on, Claude Code blocks the launch, and how you turn them on depends on your billing access:
- If you can manage billing for your account, Claude Code links you to the billing settings where you can turn on usage credits.
- On Team and Enterprise plans, members without billing access send a request from the CLI asking their admin to turn on usage credits.
You can also run `/usage-credits` to check or change your usage-credits setting. Claude Code asks you to confirm usage-credits billing once per conversation: when you start a new conversation, for example with `/clear`, Claude Code shows the confirmation again for the next paid review.
[](#track-a-running-review)
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. If you chose to [post the findings to the pull request](#post-findings-to-the-pull-request), keep the session open until the review finishes; if the session ends first, Claude Code posts nothing. Use `/tasks` to see running and completed reviews, open the detail view for a review, or stop a review that is in progress. If you stop a review, Claude Code archives the cloud session and doesn’t return partial findings. Claude can also tell you that a review was stopped or that its session wasn’t found:
- If the review’s cloud session is stopped or [archived](claude-code-on-the-web.md#archive-sessions) on claude.ai before the review finishes, Claude tells you it was stopped.
- If the review’s cloud session was deleted, or you’ve signed in to a different Claude account or organization since launching it, Claude tells you the session wasn’t found.
- If you switched accounts, the review may still finish under the account that started it. If the review is still running, sign back in as that account and resume the conversation with `claude --resume` to re-attach it.
When the review finishes, Claude Code shows the verified findings 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)
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 `/code-review ultra`, blocks until the remote review finishes, and prints the findings to stdout.
```python
claude ultrareview
claude ultrareview 1234
claude ultrareview origin/main
```
Without arguments, the subcommand reviews the diff between your current branch and the default branch, with the same [whole-repository fallback](#diff-limits-and-fallbacks) as `/code-review ultra` when no merge base exists. Pass a PR number to review a pull request, or a base branch to review against it; [base-branch handling](#review-against-a-different-base) matches the interactive command. You consent to the whole-repository fallback and to the billing and terms prompt when you run the subcommand, so the run starts without waiting for input. Running it yourself is what counts as consent. When Claude runs the subcommand for you instead, for example through the Bash tool, Claude Code refuses the whole-repository review. On Claude Code v2.1.218 or later, you can also start the cloud review by running `/code-review ultra` in a non-interactive session, for example `claude -p '/code-review ultra'`. Claude Code launches the review and prints a tracking link without waiting for the findings, unlike `claude ultrareview`, which blocks until they arrive. When the review would bill usage credits, Claude Code stops before launching and points you to `claude ultrareview`, because the billing confirmation needs an interactive session. Before v2.1.218, `/code-review ultra` in a non-interactive session ran a local review. Progress messages and the live session URL go to stderr so stdout stays parseable. Use these flags to control the output, the timeout, and whether to post the findings:
| 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 45 |
| `--post` | [Post the finished findings](#post-findings-to-the-pull-request) to the pull request as one plain comment from your GitHub account. Works on `github.com` pull request targets; on other targets, Claude Code ignores the flag and says so. Requires Claude Code v2.1.227 or later |
| `--no-post` | Don’t post the findings. This is the default, and if you pass both flags, Claude Code doesn’t post. Requires Claude Code v2.1.227 or later |
Running `claude ultrareview` requires the same authentication and usage-credits configuration as `/code-review ultra`. The subcommand exits with one of three codes:
- **0**: the review completed, with or without findings
- **1**: the review failed to launch or was stopped before it finished, the cloud session errored, or the timeout elapsed
- **130**: you interrupted the subcommand with Ctrl-C
If you interrupt the subcommand, the remote review keeps running; follow the session URL printed to stderr to watch it in the browser. With `--post`, the subcommand starts the post right after printing the findings, and prints the link to stderr.
- If the run fails, is stopped, or times out, or if you interrupt it, the subcommand posts nothing.
- If the review completes but the comment isn’t posted, Claude Code prints the reason to stderr, and the findings stay on stdout so you can post them by hand.
For automatic reviews on GitHub pull requests, [Code Review](code-review.md) integrates with your repository directly and posts findings as inline PR comments without a CLI step.
[](#how-ultrareview-compares-to-/code-review)
How ultrareview compares to /code-review
Both reviews examine code, but you use them at different stages of your workflow.
| | `/code-review` | `/code-review ultra` |
|----------|--------------------------------------------------------|-----------------------------------------------------------------|
| Target | your working diff, a pull request, a branch, or a path | your working diff or a pull request |
| Runs | locally in your session | in a cloud sandbox |
| Depth | scales with the effort argument | 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 \$25 per review as usage credits |
| Best for | quick feedback while iterating | pre-merge confidence on substantial changes |
Use `/code-review` for fast feedback as you work, or pass a PR number to review a teammate’s pull request before approving it. Use `/code-review ultra` before merging a substantial change when you want a deeper pass that catches issues a local review might miss.
[](#related-resources)
Related resources
- [Use Claude Code in the cloud](claude-code-on-the-web.md): learn how cloud sessions and cloud sandboxes work
- [Manage costs effectively](../17-Billing-Plans/costs.md): track usage and set spending limits
---
## Use Claude Code CLI with a screen reader | Claude Help Center
Source: https://support.claude.com/en/articles/15924927-use-claude-code-cli-with-a-screen-reader
Path: 02-Claude-Code-CLI/use-claude-code-cli-with-a-screen-reader.md
# Use Claude Code CLI with a screen reader
July 13, 2026
The screen reader mode brings Claude Code back to the basic terminal experience: plain, sequential text with added labels and cues and no visual embellishments. It was built with and for screen reader users, and it's useful to anyone who wants plain output for braille displays, slow connections, or transcripts.
## Turn on the screen reader mode
The screen reader mode requires Claude Code version 2.1.181 or later and it can be enabled in multiple ways:
- For one session: run `claude --ax-screen-reader`
- For every session in a terminal: set the environment variable `CLAUDE_AX_SCREEN_READER=1`
- Permanently: add `"axScreenReader": true` to your Claude Code settings file (`~/.claude/settings.json`)
The first line of the session announces that the screen reader mode is on. In Claude Code v2.1.206 and later it announces: `[Screen Reader Mode: on via flag]` (or `via env` / `via settings`).
## What to expect
- **Your prompts and Claude’s responses are labeled.** Your messages start with `you:` and Claude's replies start with `claude:`. Tool activity starts with `tool:` and permission prompts with `Permission Required:`. The labels are also searchable, so you can use your terminal's search to jump between parts of the conversation.
- **Menus become numbered lists.** Instead of moving a highlight with the arrow keys, you hear each option as a numbered line, then type the number of the option you want and press Enter. For yes-or-no prompts, type `y` or `n` and press Enter.
- **Visual decorations are removed.** Spinners, progress animations, and in-place redraws become plain text that reads in order, and decorative characters such as box-drawing lines are removed.
- **A terminal bell tells you when Claude needs you.** You'll hear your terminal's alert sound when Claude finishes a reply, when a permission prompt appears, and when a long-running tool finishes. If you don't hear it, check the bell setting in your terminal application—some terminals keep the alert sound off by default. Claude Code's own notification channel can be set with `/config` under notifications.
To explore comprehensive documentation regarding line markers, list navigation, and existing constraints, visit the **[Accessibility section of the Claude Code guide](accessibility.md)**.
## Report an issue
If something doesn't work with your screen reader or terminal, open an issue at **[the Claude Code GitHub repository](https://github.com/anthropics/claude-code/issues)** and mention your screen reader in the title. Please include your operating system, terminal application, and screen reader name and version.
**Note:** One setting that's easy to mix up: `CLAUDE_CODE_ACCESSIBILITY=1` is a different, unrelated setting—it keeps the terminal cursor visible for screen magnifiers and does not turn on screen reader mode. For a screen reader, use the methods above.
---
## Use skills in Claude | Claude Help Center
Source: https://support.claude.com/en/articles/12512180-use-skills-in-claude
Path: 02-Claude-Code-CLI/using-skills-in-claude.md
# Use skills in Claude
Skills extend Claude's capabilities by giving it access to specialized knowledge and workflows. This guide shows you how to enable, discover, and use skills in Claude.
Skills are available for users on Free, Pro, Max, Team, and Enterprise plans. This feature requires **[code execution to be enabled](../15-Claude-AI-Features/create-and-edit-files-with-claude.md#h_1c99382190)**. Skills are also available in Claude Code, and in beta for all API users using the code execution tool.
## Prerequisites
**For Enterprise plans:** Owners must check that both **Code execution and file creation** and **Skills** are enabled in **[Organization settings \> Plugins & skills](https://claude.ai/admin-settings/skills)** in the “Policy” tab. Owners can also upload skills to provision them organization-wide—these skills automatically appear for all users. Once skills are enabled at the organization level, individual members can toggle on example skills, access provisioned skills, and upload their own personal skills in **[Customize \> Skills](https://claude.ai/customize/skills)**.
**For Team plans:** This feature is enabled by default at the organization level. Once enabled, individual members can toggle on example skills and upload their own in **[Customize \> Skills](https://claude.ai/customize/skills)**.
**For Max, Pro, and Free plans:** You can enable example skills and upload your own in **[Customize \> Skills](https://claude.ai/customize/skills)**.
------------------------------------------------------------------------
## How to enable skills
1. For Team / Enterprise plans: Navigate to **[Organization settings \> Plugins & skills](https://claude.ai/admin-settings/skills)**, click the “Policy” tab, and ensure that both **Cloud code execution and file creation** and **Skills** are enabled.
2. For individual Free, Pro, and Max plans: Navigate to **[Settings \> Capabilities](https://claude.ai/settings/capabilities)** and ensure that **Code execution and file creation** is enabled.
3. Go to **[Customize \> Skills](https://claude.ai/customize/skills)**.
4. Toggle individual skills on or off as needed.
## Provision skills organization-wide
Owners of Team and Enterprise organizations can provision skills for all users. These skills appear in your individual Skills list with a team indicator—you can toggle them on or off based on your preferences. For information on provisioning skills for your organization, see **[Provision and manage skills for your organization](../15-Claude-AI-Features/provisioning-and-managing-skills-for-your-organization.md#h_4dea113421)**.
## Use Anthropic skills
Anthropic provides several built-in skills that are available to all users, including:
- Enhanced Excel spreadsheet creation and manipulation
- Professional Word document creation
- PowerPoint presentation generation
- PDF creation and processing
With **Code execution and file creation** on, Claude will automatically use these tools when relevant. You don't need to explicitly invoke them—Claude determines when each skill is needed based on your request.
For example, if you ask Claude to "Create a PowerPoint presentation about Q3 results," Claude will automatically use the PowerPoint skill if the capability is enabled.
## Add and use custom skills
You can also create and upload your own skills to teach Claude your specific workflows:
1. Create a skill following the skill structure (see **[How to create custom skills](https://support.claude.com/en/articles/12512198-creating-custom-skills)** for detailed instructions).
2. Package your skill folder as a ZIP file.
3. Navigate to **[Customize \> Skills](https://claude.ai/customize/skills)**.
4. To add custom skills, click the "+" button, then “+ Create skill.”
5. Select "Upload a skill.”
6. Upload a ZIP file containing your skill folder.
7. Your skill will appear in your skills list and can be toggled on or off.
**Note:** Custom skills you upload aren't visible to colleagues until you share them. Admins can see their names and sharing status, but not their files On Team and Enterprise plans, you can share skills (see **Share a skill** below), or provision skills for your organization. Learn more about **[provisioning skills for your organization](https://support.claude.com/en/articles/13119606-managing-skills-as-an-admin#h_4dea113421)**.
------------------------------------------------------------------------
## Share a skill
On Team and Enterprise plans, you can share skills you've created with specific colleagues, groups. To make a skill available to your entire organization, publish it instead. Skill sharing works in both chat and Cowork.
**Note:** The **Skill sharing** toggle is on by default for Team plans and for Enterprise plans that haven't set a skills preference. For organizations with HIPAA readiness or other regulated configurations, skills and skill sharing are off by default and an admin can enable them. The **Share with organization** and **Share with groups** toggles are also off by default. An owner must navigate to **[Organization settings \> Plugins & skills](https://claude.ai/admin-settings/skills)**, click the “Policy” tab, and enable at least one of the toggles before the "Share" button appears. If your organization uses custom roles, your role must also have the **Share skills with groups** capability enabled. If you don't see the option to share, check with your organization owner.
To share a skill:
1. Navigate to **[Customize \> Skills](https://claude.ai/customize/skills)**.
2. Find the skill you created.
3. Click the three-dot menu (...) next to it, then select "Share."
4. Choose who to share with:
- **Specific people:** Enter names or emails to share directly. Sharing creates a link that opens the item for anyone it's shared with. The skill appears in each recipient's skills list, grayed out until they enable it, and shows your name as the owner.
- **A group (Enterprise plans only):** Share with a group your organization has already set up. The skill appears in every group member's skills list, grayed out until they enable it. Requires the **Share with groups** toggle.
5. Click "Share."
Shared skills are view-only. Recipients can enable and use the skill, but they can't edit the contents. If you update the skill later, recipients automatically get the updated version at next use. You can remove someone's access at any time, and access is removed automatically if they leave the organization.
------------------------------------------------------------------------
## Publish a skill to your organization
On Team and Enterprise plans, you can submit a skill you've created to your organization's library, so anyone in your organization can install it. Sharing gives a skill to specific people or groups, and you keep control of it. Publishing hands it to your organization.
To publish a skill:
1. Navigate to **[Customize \> Skills](https://claude.ai/customize/skills)**.
2. Open the skill you want to publish.
3. Click "Publish to org."
4. If your organization requires review, choose how you'd like the skill offered: Available to install, Installed by default, or Required. Add release notes for the reviewer if you'd like, then submit.
If your organization requires review, an owner (or someone with permission to review requests) checks the skill before it's published. Your choice of how it's offered is a proposal. The reviewer sees it preselected and can change it, and they also choose who gets the skill: everyone or specific groups. You can keep using and editing your copy while you wait, and you can withdraw the submission. The skill shows its status: pending, changes requested (with the reviewer's note), or published. You'll get an email when it's approved. If your organization doesn't require review, the skill is published to the library and available to everyone in your organization to install. If your organization has security scanning turned on, the skill isn't listed for others until it passes the scan, which usually takes a few minutes.
Once published, the skill is managed by your organization. To update it, publish again. The new version goes through the same review, and everyone who uses the skill stays on the approved version until the update is approved.
------------------------------------------------------------------------
## Use skills shared with you
On Team and Enterprise plans, your skills list in **[Customize \> Skills](https://claude.ai/customize/skills)** is organized into three sections:
- **Personal skills:** Skills you've created or uploaded yourself.
- **Shared with you:** Skills colleagues have shared with you directly. These stay off until you turn them on.
- **Organization skills:** Skills published to your organization and skills your owner has provisioned. You install these from the directory rather than enabling them from the list.
### Enable a skill shared with you directly
1. Find the skill in the **Shared with you** section of your skills list.
2. Toggle it on.
You can toggle the skill off again at any time, or delete it from your list entirely if you don't want it.
### Install a skill from your organization's directory
1. In Cowork, click **Customize** in the left sidebar, then click the "+" button to open the directory.
2. Click the **Skills** tab.
3. Find the skill you want and click "Install."
Skills you install from the directory can be toggled off, which removes them from your sidebar. They remain in the directory so you can re-enable them later. For more on browsing the directory, see **[Browse skills, connectors, and plugins in one directory](../14-Connectors/browse-skills-connectors-and-plugins-in-one-directory.md)**.
------------------------------------------------------------------------
## Use skills in Microsoft 365 add-ins
Skills you've enabled in your Claude settings are also available in the Claude for Excel, PowerPoint, Word, and Outlook add-ins. Claude applies relevant skills automatically while you work—you don't need to invoke them separately.
**How triggering works in the add-ins:**
- Type `/` in the sidebar to see available skills and select one (for example, `/debug` or `/deck-check`).
- Or describe your task naturally—Claude recognizes when a skill applies and uses it.
Claude adapts skills to the surface it’s in. A research skill may produce a Word document in Cowork, but detailed data breakdowns in Excel. Some skills may work better on one surface than others. If you let Claude work across apps, Claude can orchestrate another app to apply the skill. If you build a skill with a specific Excel or PowerPoint template, Claude for Excel and Powerpoint can load that template exactly into the current open file.
------------------------------------------------------------------------
## Use skills in Claude Code
Skills you've enabled in your Claude settings also load in Claude Code in your terminal when you sign in with the same Claude account. This includes skills you created or turned on and skills an owner provisioned for your organization. It needs Claude Code v2.1.273 or later.
Run `/skills` in Claude Code to see them listed under **claude.ai sync**.
- Skills sync when a Claude Code session starts, then check for changes about every 10 minutes.
- The sync is one-way. It reads from your Claude account and never changes anything in it.
- Skills don't sync when Claude Code is signed in with an API key or runs on a cloud provider such as Amazon Bedrock.
To stop skills from syncing, set `syncClaudeAiSkills` to `false` in your Claude Code settings. Learn more about **[how synced skills behave](../08-Plugins-Skills/skills.md#how-synced-skills-behave)** in the Claude Code docs.
------------------------------------------------------------------------
## Manage your skills
### View your skills
All your skills are listed in **[Customize \> Skills](https://claude.ai/customize/skills)**. You can see:
- Anthropic skills (created, tested, and maintained by Anthropic)
- Custom skills you've uploaded
- When each skill was enabled or uploaded
- A brief description of what each skill does
### Enable/disable your skills
Toggle any skill on or off using the switch next to it. Disabled skills won't be available to Claude.
### Delete custom skills
To remove a custom skill you've uploaded:
1. Navigate to **[Customize \> Skills](https://claude.ai/customize/skills)**.
2. Find the skill in your skills list and click on it to view the details.
3. Use the toggle in the upper right corner to disable the skill.
4. To delete the custom skill entirely, click the "..." button next to the toggle, then select "Delete":
5. Click "Delete" in the confirmation prompt.
If you change your mind, you can add the skill again by re-uploading the file.
------------------------------------------------------------------------
## Privacy and security details
For Team and Enterprise plans, organization owners can provision skills for all users through organization settings. Individuals can share skills with colleagues if an owner has enabled sharing, or publish them to the organization if an owner has turned on publishing. On all other plans, each person uploads skills to their own account.
Note that skills may include, or instruct Claude to install, third-party packages and software for Claude to use when completing a task. See **[our guidance on Claude's container environment](../15-Claude-AI-Features/create-and-edit-files-with-claude.md#h_0ee9d698a1)** for details on Claude's container environment and **[the API documentation](https://docs.claude.com/en/docs/agents-and-tools/tool-use/code-execution-tool#containers)** for API's container environment.
**Note:** If you're on the Enterprise plan and your organization has skill scanning turned on, each third-party skill you upload or edit is checked for malicious content before it can run. Most scans finish in about one to two minutes. If a skill is blocked, you can't use it until you fix what was flagged and upload it again. Learn more about **[skill and plugin scanning](../15-Claude-AI-Features/get-started-with-skill-and-plugin-scanning-claude-help-center.md)**.
### What are the primary risks of using skills?
The most significant risks are prompt injection, which allows Claude to be manipulated to execute unintended actions, and data exfiltration, caused by malicious package code or prompt-injected data leaks. We’ve implemented several mitigations to these risks. Refer to **[our security considerations for code execution](../15-Claude-AI-Features/create-and-edit-files-with-claude.md#h_0ee9d698a1)** for more information.
**Important:** Only install skills only from trusted sources.
When installing a skill from a less-trusted source—including one shared by a colleague—review it before enabling. Start by reading the contents of the files bundled in the skill to understand what it does, paying particular attention to code dependencies and bundled resources like images or scripts. Similarly, pay attention to instructions or code within the skill that instruct Claude to connect to potentially untrusted external network sources.
------------------------------------------------------------------------
## Troubleshooting
### Skills section not visible
Ensure code execution is enabled in **[Settings \> Capabilities](https://claude.ai/settings/capabilities)** (Free, Pro, Max) or **[Organization settings \> Plugins & skills](https://claude.ai/admin-settings/skills)** in the “Policy” tab (Team, Enterprise). Then navigate to **[Customize \> Skills](https://claude.ai/customize/skills)** to access your skills. Skills require the code execution environment to function.
### Claude isn’t using a skill
- Verify the skill is toggled on in **[Customize \> Skills](https://claude.ai/customize/skills)**.
- Check that the skill's description field clearly explains when it should be used.
- Ensure the skill's instructions are clear and well-structured.
- Try being more explicit in your request (e.g., "Use my brand guidelines skill to create a presentation").
### Can't create or upload a skill
On Team and Enterprise plans, an organization owner can turn off skill creation for users. If the option to create or upload a skill is missing, your organization may have **User-created skills** turned off, or—on Enterprise plans with custom roles—your role may not include the **Create skills** capability. You can still enable and use skills your owner has provisioned. Contact your organization owner if you need to create your own.
### Skills greyed out
If skills appear greyed out, code execution may be disabled at the organization level (for Team and Enterprise plans) or individually. Check with your organization's Owner (Team, Enterprise) or make sure to enable code execution in **[Settings \> Capabilities](https://claude.ai/settings/capabilities)** (Free, Pro, Max).
### Upload errors
Common reasons for upload failures:
- ZIP file exceeds size limits
- Skill folder name doesn't match the skill name
- Missing required skill.md file
- Invalid characters in skill name or description
### Group doesn't appear when I try to share a skill
The group needs the **Share resources with this group** visibility setting turned on by an organization owner. Contact your organization owner if a group you expect to see is missing.
### Share button not visible
The **Skill sharing** toggle is on by default for Team plans and for Enterprise plans that haven't set a skills preference. For organizations with HIPAA readiness or other regulated configurations, skills and skill sharing are off by default and an admin can enable them. The **Share with organization** and **Share with groups** toggles are also off by default. An owner must navigate to **[Organization settings \> Skills](https://claude.ai/admin-settings/skills)** and enable at least one of the toggles before the "Share" button appears. If your organization uses custom roles, your role must also have the **Share skills with groups** capability enabled. If you don't see the option to share, check with your organization owner.
### "Publish to org" button not visible
Your organization's **Publishing** setting may be turned off, or the skill may not be one you created. You can't publish skills that were shared with you, Anthropic's built-in skills, or skills you installed from your organization's library. If it's your own skill and you don't see the button, check with your organization owner.
------------------------------------------------------------------------
## Best practices
**Start simple.** Begin with Anthropic's pre-built skills to understand how they work before creating custom skills.
**Be specific.** Write clear descriptions when writing custom skills. A specific description tells Claude when to invoke your skill.
**Test your skills.** After uploading a custom skill, test it with a few different prompts to ensure it works as expected.
**Organize by purpose.** Create separate skills for different purposes rather than a single skill that’s meant to do everything.
------------------------------------------------------------------------
## Learn more about using skills
For more information and video demonstrations, refer to **[Teach Claude your way of working using skills](https://claude.com/resources/tutorials/teach-claude-your-way-of-working-using-skills).**
---
## Voice dictation - Claude Code Docs
Source: https://code.claude.com/docs/en/voice-dictation
Path: 02-Claude-Code-CLI/voice-dictation.md
## On this page
- [Requirements](#requirements)
- [Enable voice dictation](#enable-voice-dictation)
- [Hold to record](#hold-to-record)
- [Tap to record and send](#tap-to-record-and-send)
- [Cancel a recording](#cancel-a-recording)
- [Change the dictation language](#change-the-dictation-language)
- [Rebind the dictation key](#rebind-the-dictation-key)
- [Troubleshooting](#troubleshooting)
- [Terminal not listed in macOS Microphone settings](#terminal-not-listed-in-macos-microphone-settings)
- [See also](#see-also)
Interface
# Voice dictation
Copy pageCopy page
Speak your prompts in the Claude Code CLI with hold-to-record or tap-to-record voice dictation.
Copy pageCopy page
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. Dictation also works in [agent view](../09-Agents-Patterns/agent-view.md#peek-and-reply). Hold or tap your push-to-talk key while the dispatch input or a peek-panel reply is focused to dictate to a background session.
[](#requirements)
Requirements
Voice dictation streams your recorded audio to Anthropic’s servers for transcription. Audio is not processed locally. It needs all of the following:
- **A Claude.ai account**: the speech-to-text service is only available when you authenticate with one, and is not available when Claude Code is configured to use an Anthropic API key directly, Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry.
- **A local microphone**: voice dictation does not work in [cloud sessions](claude-code-on-the-web.md) or SSH sessions.
- **WSLg, if you run Claude Code in WSL**: 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.
Transcription does not consume Claude messages or tokens and does not count toward the limits shown in `/usage`. See [data usage](../13-Enterprise-Admin/data-usage.md) for how Anthropic handles your data. 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](../03-IDE-Integrations/vs-code.md) 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)
Enable voice dictation
Run `/voice` to enable dictation. When 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.
```python
/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](#hold-to-record) |
| `/voice tap` | Enable in [tap mode](#tap-to-record-and-send) |
| `/voice off` | Disable |
Voice dictation persists across sessions. Set it directly in your [user settings file](settings.md) instead of running `/voice`:
```python
{
"voice": {
"enabled": true,
"mode": "tap"
}
}
```
For the first three sessions with voice dictation 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](#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](statusline.md) 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 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 `listening…` once recording is active. While recording, the prompt cursor becomes a bar that rises and falls with your microphone level, unless you have [`prefersReducedMotion`](settings-reference.md#prefersreducedmotion) turned on. 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. Holding or tapping `Space` starts dictation only where the keypress would otherwise type into the prompt. In the [transcript viewer](interactive-mode.md#transcript-viewer), `Space` pages through the conversation, and in [vim mode](interactive-mode.md#vim-editor-mode) outside INSERT it is a command. A [rebound modifier combination](#rebind-the-dictation-key) like `meta+k` never types text, so it starts dictation from those places too.
To skip the warmup, switch to [tap mode](#tap-to-record-and-send) with `/voice tap`, or [rebind to a modifier combination](#rebind-the-dictation-key) 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:
```python
> 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, when you release the key, Claude Code 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 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 don’t 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 `● REC · tap to send` 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 three-word threshold counts words for languages written without spaces. Japanese, Chinese, and Thai transcripts count individual words, so they auto-submit in tap mode and in hold mode with `autoSubmit`. 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.
[](#cancel-a-recording)
Cancel a recording
Press `Esc` or `Ctrl+C` to cancel a dictation instead of finalizing it. Claude Code stops the microphone, discards the transcript, and restores the prompt to what it held before the recording started. Both keys also cancel while a finished recording’s transcript is still processing. A prompt you edited or submitted during processing stays as you left it. Neither key does anything else in the press that cancels: `Esc` doesn’t interrupt Claude’s response, and `Ctrl+C` doesn’t clear the prompt or count as the first of the [two presses that exit Claude Code](interactive-mode.md#general-controls).
[](#change-the-dictation-language)
Change the dictation language
Voice dictation uses the same [`language` setting](settings-reference.md#language) 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](https://en.wikipedia.org/wiki/IETF_language_tag) or the language name:
```python
{
"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)
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`](keybindings.md):
```python
{
"bindings": [
{
"context": "Chat",
"bindings": {
"meta+k": "voice:pushToTalk",
"space": null
}
}
]
}
```
The `voice:pushToTalk` action uses one key at a time. When you bind a custom key, it replaces the default `Space` binding rather than adding a second trigger, so the `"space": null` line in this example is for clarity and can be omitted without changing behavior. 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 can’t be bound at all. For example, `Caps Lock` shows an error if you try to bind it. See [customize keyboard shortcuts](keybindings.md) for the full keybinding syntax and the list of reserved shortcuts.
[](#troubleshooting)
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.
- **`Voice mode is disabled by your organization's policy`**: an administrator policy for your organization turns off voice dictation. Contact your organization administrator to confirm whether voice dictation is available for your organization.
- **`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](#terminal-not-listed-in-macos-microphone-settings).
- **`Voice mode requires SoX for audio recording` 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 requires a microphone, but SoX could not open an audio capture device`**: SoX is installed, but the host has no audio capture device, for example a headless server or a container. Run Claude Code on a machine with a microphone. As of v2.1.195, Claude Code on Linux reports this message in that situation; earlier versions asked you to install SoX even when it was already installed.
- **`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 three failures within 10 seconds. Claude Code pauses dictation until 10 seconds have passed since the first of those failures. 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. Before v2.1.202, only start-up failures counted toward the pause.
- **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 can’t 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.
- **`Voice connection failed`**: your recording never reached the transcription service because the connection failed. Check your network and try again. A recording that captures no audio reports `No audio detected from microphone` instead of this message. Before v2.1.200, a silent microphone could report a connection failure, which suggested a network problem when the actual issue was the input device.
- **`Voice stream error: WebSocket upgrade rejected with HTTP <status>`**: a server refused your connection with the HTTP status shown, so this isn’t a network outage. A status in the 400 range usually means a stale sign-in, or a proxy or bot-protection service answering in place of the transcription service. Run `/login` to refresh your sign-in, and check for a VPN or proxy on your network path if the status persists. If you’re still recording when the rejection arrives, Claude Code retries a status outside the 400 range once before showing this message; it doesn’t retry a status in the 400 range. In v2.1.229 through v2.1.231, native builds didn’t show this message: Claude Code kept recording, the hold-mode footer still showed `listening…`, and it reported `Voice connection failed` after you stopped recording.
- **`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](#change-the-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](#change-the-dictation-language).
[](#terminal-not-listed-in-macos-microphone-settings)
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)
See also
- [Customize keyboard shortcuts](keybindings.md): rebind `voice:pushToTalk` and other CLI keyboard actions
- [All settings](settings-reference.md#voice): the `voice`, `language`, and other settings keys
- [Interactive mode](interactive-mode.md): keyboard shortcuts, input modes, and session controls
- [Commands](commands.md): reference for `/voice`, `/config`, and all other commands
---
## Get started with Claude Code in the cloud - Claude Code Docs
Source: https://code.claude.com/docs/en/web-quickstart
Path: 02-Claude-Code-CLI/web-quickstart.md
## On this page
- [How sessions run](#how-sessions-run)
- [Compare ways to run Claude Code](#compare-ways-to-run-claude-code)
- [Connect GitHub](#connect-github)
- [Connect from your terminal](#connect-from-your-terminal)
- [Remove the /web-setup token](#remove-the-web-setup-token)
- [Start a task](#start-a-task)
- [Pre-fill sessions](#pre-fill-sessions)
- [Review and iterate](#review-and-iterate)
- [Troubleshoot setup](#troubleshoot-setup)
- [No repositories appear after connecting GitHub](#no-repositories-appear-after-connecting-github)
- [The page only shows a GitHub login button](#the-page-only-shows-a-github-login-button)
- [”Claude Code isn’t available on your account”](#%E2%80%9Dclaude-code-isn%E2%80%99t-available-on-your-account%E2%80%9D)
- [/web-setup says “Not signed in to Claude”](#%2Fweb-setup-says-%E2%80%9Cnot-signed-in-to-claude%E2%80%9D)
- [/web-setup warns that your token doesn’t have the workflow scope](#%2Fweb-setup-warns-that-your-token-doesn%E2%80%99t-have-the-workflow-scope)
- [/web-setup shows “No commands match” or “Unknown command”](#web-setup-shows-no-commands-match-or-unknown-command)
- [”Could not create a cloud environment” or “No cloud environment available” when using --cloud](#%E2%80%9Dcould-not-create-a-cloud-environment%E2%80%9D-or-%E2%80%9Cno-cloud-environment-available%E2%80%9D-when-using-cloud)
- [Setup script failed](#setup-script-failed)
- [New sessions hang or time out during setup](#new-sessions-hang-or-time-out-during-setup)
- [Session keeps running after closing the tab](#session-keeps-running-after-closing-the-tab)
- [Next steps](#next-steps)
Claude Code in the cloud
# Get started with Claude Code in the cloud
Copy pageCopy page
Run Claude Code in the cloud from your browser or phone. Connect a GitHub repository, submit a task, and review the PR without local setup.
Copy pageCopy page
Cloud sessions are available on Pro, Max, and Team plans, and for Enterprise users with premium seats or Chat + Claude Code seats.
A cloud session runs Claude Code on cloud infrastructure instead of your machine, Anthropic-managed by default. This quickstart starts one from [claude.ai/code](https://claude.ai/code) in your browser. You can also start one from the Claude mobile app, the Desktop app, or your terminal with `claude --cloud`. You’ll need a GitHub repository to [get started](#connect-github). 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. Cloud sessions work 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](remote-control.md) is a better fit.
[](#how-sessions-run)
How sessions run
The steps below describe Anthropic-hosted sessions. In a [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md), the clone and everything after it run on your organization’s own runners, where network boundaries, setup, and push behavior are operator-configured. When you submit a task:
1. **Clone and prepare**: your repository is cloned to an Anthropic-managed VM, and your [setup script](cloud-environments.md#setup-scripts) runs if configured.
2. **Configure network**: internet access is set based on your environment’s [access level](cloud-environments.md#access-levels).
3. **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.
4. **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)
Compare ways to run Claude Code
Claude Code behaves the same everywhere. What changes is where the session runs and whether your local configuration is available:
| | Cloud session | Local session | Local session with [Remote Control](remote-control.md) |
|:--------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------|
| **Code runs on** | Cloud VM, Anthropic-managed by default | Your machine | Your machine |
| **You start it from** | claude.ai/code, the Claude mobile app, the Desktop app with **Cloud** selected, or `claude --cloud` | Your terminal, your IDE, or the Desktop app with **Local** selected | Your terminal, the VS Code extension, or the Desktop app |
| **You chat from** | claude.ai, the mobile app, or the Desktop app | Where you started it | claude.ai or the mobile app, as well as where you started it |
| **Uses your local config** | No, repo only | Yes | Yes |
| **Requires GitHub** | Yes, or [bundle a local repo](claude-code-on-the-web.md#send-local-repositories-without-github) via `--cloud` | No | No |
| **Keeps running if you disconnect** | Yes | No | While the session stays open on your machine |
| **[Permission modes](permission-modes.md)** | Accept edits, Plan, Auto | All modes in the terminal; see [Switch permission modes](permission-modes.md#switch-permission-modes) for the IDE and Desktop app | Manual, Accept edits, or Plan from claude.ai and the mobile app |
| **Network access** | Configurable per environment | Your machine’s network | Your machine’s network |
See the [terminal quickstart](../01-Getting-Started/quickstart.md), [Desktop app](../16-Mobile-Desktop/desktop.md), or [Remote Control](remote-control.md) docs to set up local sessions.
[](#connect-github)
Connect GitHub
Connecting GitHub is a one-time step. If you already use the GitHub CLI, you can [do this from your terminal](#connect-from-your-terminal) instead of the browser.
On Team and Enterprise plans, the **Sign in with GitHub** step works only after an [Owner](../13-Enterprise-Admin/server-managed-settings.md#access-control) of your Claude organization turns on the GitHub connector at [**Admin settings \> Connectors**](https://claude.ai/admin-settings/connectors). Until then, that step shows “GitHub access is required for Claude Code on the web” instead of a sign-in button. After the connector is on, reload [claude.ai/code](https://claude.ai/code) and start again from the first step. A second toggle, [Quick web setup](claude-code-on-the-web.md#github-authentication-options) at [**Admin settings \> Claude Code**](https://claude.ai/admin-settings/claude-code), is optional: with it on, `/web-setup` works and onboarding creates the environment for members.
1
Visit claude.ai/code
Go to [claude.ai/code](https://claude.ai/code) and sign in with your claude.ai account.
2
Sign in with GitHub
After you sign in, claude.ai/code prompts you to connect GitHub. Follow the prompt, and claude.ai/code sends you to GitHub’s authorization page. Approve the authorization request, and GitHub returns you to claude.ai/code. Cloud sessions work with existing GitHub repositories. To start a new project, [create an empty repository on GitHub](https://github.com/new) first.With this connection, a session can clone any public repository, but can work in a private repository only when the Claude GitHub App is installed on it. [Install the Claude GitHub App](https://github.com/apps/claude/installations/new) on each GitHub account or organization whose private repositories you want to use. On a GitHub organization, an organization owner may need to approve the installation. Installing it also enables [Auto-fix](claude-code-on-the-web.md#auto-fix-pull-requests), which lets Claude respond to CI failures and review comments on pull requests in those repositories.If onboarding prompts you to install the Claude GitHub App at this point and you’d rather do it later, click **Skip**.
3
Set up your Default environment
A [cloud environment](cloud-environments.md) is the saved configuration that controls what network access Claude has during sessions and what runs when a session starts. What happens after you connect GitHub depends on your plan:
- **Pro and Max**: onboarding creates an environment named **Default** for you.
- **Team and Enterprise**: onboarding shows a **Create your first cloud environment** form. Leave the prefilled name and network access unchanged and click **Create & finish** to create the **Default** environment. If an Owner has turned on [Quick web setup](claude-code-on-the-web.md#github-authentication-options), onboarding creates **Default** for you instead.
**Default** uses [`Trusted` network access](cloud-environments.md#access-levels): sessions reach [common package registries](cloud-environments.md#default-allowed-domains) and other allowlisted domains, and nothing else through the session’s network. See [Installed tools](cloud-environments.md#installed-tools) for what’s available without any configuration.For a first project, the **Default** environment works as is. To change its network access, add environment variables, or run a [setup script](cloud-environments.md#setup-scripts) before sessions start, [edit it or create additional environments](cloud-environments.md#configure-your-environment).
[](#connect-from-your-terminal)
Connect from your terminal
If you already use the GitHub CLI (`gh`), you can connect GitHub for cloud sessions from your terminal. This requires the [Claude Code CLI](../01-Getting-Started/quickstart.md). On Team and Enterprise plans, `/web-setup` is available only after an Owner turns on [Quick web setup](claude-code-on-the-web.md#github-authentication-options). When you run `/web-setup`, Claude Code reads the token that `gh auth token` prints, asks you to confirm, and sends the token to Anthropic. Anthropic stores it encrypted with your claude.ai account, and your cloud sessions use it for GitHub access until you [remove it](#remove-the-web-setup-token). A cloud session you start yourself can then access any repository that token can access, with no Claude GitHub App installation. Threads in a [project](claude-projects.md#set-up-github-access) still need the Claude GitHub App. If you already connected GitHub in the browser, `/web-setup` warns you that continuing replaces that connection for your cloud sessions.
Organizations with [Zero Data Retention](zero-data-retention.md) enabled cannot use `/web-setup` or other cloud session features. If the GitHub CLI isn’t installed or isn’t authenticated, Claude Code opens the browser onboarding flow instead.
1
Authenticate with the GitHub CLI
In your shell, authenticate the GitHub CLI if you haven’t already:
```python
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 with a claude.ai account. Authenticating with an API key doesn’t count. To check, run `/status` and confirm the **Login method** row shows a claude.ai account.
3
Run /web-setup
In the Claude Code CLI, run:
```python
/web-setup
```
Confirm the prompt to send your `gh` token to your Claude account. On success, Claude Code prints `Connected as <your-github-username>` and opens [claude.ai/code](https://claude.ai/code) in your browser. 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](cloud-environments.md#configure-your-environment) afterward. Once `/web-setup` completes, you can start cloud sessions from your terminal with [`--cloud`](claude-code-on-the-web.md#from-terminal-to-cloud) or set up recurring tasks with [`/schedule`](web-scheduled-tasks.md).
[](#remove-the-web-setup-token)
Remove the `/web-setup` token
To remove the token from your Claude account, disconnect GitHub at [claude.ai/customize/connectors](https://claude.ai/customize/connectors). Disconnecting deletes the GitHub credentials your cloud sessions use, whether they came from the browser or from `/web-setup`, so cloud sessions lose GitHub access until you connect again. Your local `gh` stays signed in, and the token remains valid on GitHub. To invalidate the token itself, revoke it on GitHub. If you signed in to `gh` through the browser, the token belongs to the **GitHub CLI** entry under [**Settings \> Applications \> Authorized OAuth Apps**](https://github.com/settings/applications) on GitHub, and revoking that entry also signs the GitHub CLI out on your machines. Cloud sessions then lose GitHub access until you run `gh auth login` and `/web-setup` again.
[](#start-a-task)
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](https://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 shows the mode the session will run in:
- **Auto**: a classifier reviews Claude’s actions instead of asking you. Appears when your organization allows auto mode and the selected model supports it
- **Accept edits**: Claude makes changes and pushes a branch without stopping for approval
- **Plan**: Claude proposes an approach and waits for you to approve it before editing files
Cloud sessions don’t offer Manual or Bypass permissions. See the [full list of permission modes](permission-modes.md#available-modes) for what each one allows.
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)
Pre-fill sessions
You can prefill the prompt, repositories, and environment for a new session by adding query parameters to the [claude.ai/code](https://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](#connect-github) to preselect. |
URL-encode each value. The example below opens the form with a prompt and a repository already selected:
```python
https://claude.ai/code?prompt=Fix%20the%20login%20bug&repositories=acme/webapp
```
[](#review-and-iterate)
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.The diff compares the session’s changes against its base branch by default. To compare against a different branch, select **Compare against** and pick one.
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](claude-code-on-the-web.md#auto-fix-pull-requests).
[](#troubleshoot-setup)
Troubleshoot setup
[](#no-repositories-appear-after-connecting-github)
No repositories appear after connecting GitHub
If you connected GitHub in the browser, sessions can clone any public repository, but a private repository appears only when the Claude GitHub App is installed on the account or organization that owns it and the installation’s repository access includes it. [Install the Claude GitHub App](https://github.com/apps/claude/installations/new) there, or ask an organization owner to install or approve it. If you connected with `/web-setup`, sessions reach every repository your `gh` token can access. Run `gh repo view OWNER/REPO` in your shell to check that your GitHub CLI login can see the repository, and run `/web-setup` again if you’ve switched `gh` accounts since connecting.
[](#the-page-only-shows-a-github-login-button)
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](remote-control.md) to run Claude Code on your own machine and monitor it from your browser or phone.
[](#”claude-code-isn’t-available-on-your-account”)
”Claude Code isn’t available on your account”
Your seat in the selected organization doesn’t include Claude Code. If you belong to another organization, click **Switch organization** on that page. Otherwise, ask an Owner of the organization to assign you a [seat that includes Claude Code](../17-Billing-Plans/using-claude-code-with-your-team-or-enterprise-plan.md).
[](#/web-setup-says-“not-signed-in-to-claude”)
`/web-setup` says “Not signed in to Claude”
If `/web-setup` responds with “Not signed in to Claude. Run /login first.”, the CLI doesn’t have a valid claude.ai sign-in. This can also happen when a previous sign-in has expired. Run `/login`, sign in with your claude.ai account, then run `/web-setup` again.
[](#/web-setup-warns-that-your-token-doesn’t-have-the-workflow-scope)
`/web-setup` warns that your token doesn’t have the `workflow` scope
If `/web-setup` says your GitHub CLI token doesn’t have the `workflow` scope, you can continue, but GitHub can reject some pushes made with that token, such as pushes that change GitHub Actions workflow files. To add the scope, run `gh auth refresh -s workflow` in your shell, then run `/web-setup` again.
[](#web-setup-shows-no-commands-match-or-unknown-command)
`/web-setup` shows “No commands match” or “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 the command menu shows `No commands match "/web-setup"`, or submitting it returns `Unknown command: /web-setup`, the command is hidden because a requirement isn’t met. The cause is usually that you’re authenticated with an API key or third-party provider instead of a claude.ai subscription. Run `/login` to sign in with your claude.ai account. On Team and Enterprise plans, the command is hidden by default: the [Quick web setup toggle](claude-code-on-the-web.md#github-authentication-options) is off until an Owner turns it on. While it’s off, [connect GitHub from the browser](#connect-github) instead. The command is also hidden in two other cases:
- An administrator has disabled cloud sessions for your organization. In this case, submitting `/web-setup` returns [`Cloud sessions are disabled by your organization's policy`](errors.md#cloud-sessions-are-disabled-by-your-organizations-policy). Before v2.1.268, this case also returned `Unknown command: /web-setup`.
- Your Enterprise organization has [Zero Data Retention](zero-data-retention.md) enabled, which makes cloud sessions unavailable.
[](#”could-not-create-a-cloud-environment”-or-“no-cloud-environment-available”-when-using-cloud)
”Could not create a cloud environment” or “No cloud environment available” when using `--cloud`
Cloud 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, or add an environment from the [environment selector](cloud-environments.md#configure-your-environment) at [claude.ai/code](https://claude.ai/code).
[](#setup-script-failed)
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](cloud-environments.md#access-levels). `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)
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](cloud-environments.md#environment-caching). 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](cloud-environments.md#setup-scripts-vs-sessionstart-hooks) 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)
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](claude-code-on-the-web.md#archive-sessions) to hide it from your list, or [delete it](claude-code-on-the-web.md#delete-sessions) to remove it permanently.
[](#next-steps)
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 in the cloud](claude-code-on-the-web.md): the full reference, including teleporting sessions to your terminal, session sharing, and auto-fixing pull requests
- [Configure cloud environments](cloud-environments.md): network access levels, environment variables, and setup scripts for cloud sessions
- [Routines](web-scheduled-tasks.md): automate work on a schedule, via API call, or in response to GitHub events
- [CLAUDE.md](memory.md): give Claude persistent instructions and context that load at the start of every session
- Install the Claude mobile app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) or [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) to monitor sessions from your phone. From the Claude Code CLI, `/mobile` shows a QR code for [claude.ai/mobile](https://claude.ai/mobile) that opens the right app store for your phone.
---
## Automate work with routines - Claude Code Docs
Source: https://code.claude.com/docs/en/web-scheduled-tasks
Path: 02-Claude-Code-CLI/web-scheduled-tasks.md
## On this page
- [Example use cases](#example-use-cases)
- [Create a routine](#create-a-routine)
- [Create from the web](#create-from-the-web)
- [Create from the CLI](#create-from-the-cli)
- [Configure triggers](#configure-triggers)
- [Add a schedule trigger](#add-a-schedule-trigger)
- [Schedule a one-off run](#schedule-a-one-off-run)
- [Add an API trigger](#add-an-api-trigger)
- [Trigger a routine](#trigger-a-routine)
- [API reference](#api-reference)
- [Add a GitHub trigger](#add-a-github-trigger)
- [Supported events](#supported-events)
- [Filter pull requests](#filter-pull-requests)
- [Manage routines](#manage-routines)
- [View and interact with runs](#view-and-interact-with-runs)
- [Edit and control routines](#edit-and-control-routines)
- [Manage routines from the CLI](#manage-routines-from-the-cli)
- [Repositories and branch permissions](#repositories-and-branch-permissions)
- [Connectors](#connectors)
- [Environments and network access](#environments-and-network-access)
- [Usage and limits](#usage-and-limits)
- [Troubleshooting](#troubleshooting)
- [/schedule returns “Unknown command”](#schedule-returns-unknown-command)
- [“Routines are disabled by your organization’s policy”](#routines-are-disabled-by-your-organizations-policy)
- [Related resources](#related-resources)
Claude Code in the cloud
# Automate work with routines
Copy pageCopy page
Put Claude Code on autopilot. Define routines that run on a schedule, trigger on API calls, or react to GitHub events from cloud infrastructure.
Copy pageCopy page
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](../06-MCP-Tools/General/mcp.md), packaged once and run automatically. Routines execute on Anthropic-managed cloud infrastructure, or on your organization’s [self-hosted environment](../13-Enterprise-Admin/self-hosted-environments.md) when routed there, 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. Create and manage them at [claude.ai/code/routines](https://claude.ai/code/routines), or from the CLI with `/schedule`. Team and Enterprise Owners can disable routines for all members with the Routines toggle at [claude.ai/admin-settings/claude-code](https://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)
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’s prompt tells Claude to investigate the alert in the fire payload, so it 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.
[](#create-a-routine)
Create a routine
Create a routine from the web at [claude.ai/code/routines](https://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’s **Code** tab, click **Routines** in the sidebar or in the sidebar’s **More** menu, then **New routine**, and choose **Cloud**; choosing **Local** instead creates a [Desktop scheduled task](../16-Mobile-Desktop/desktop-scheduled-tasks.md), 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 the session runs shell commands, uses [skills](../08-Plugins-Skills/skills.md) committed to the cloned repository, and calls any connectors you include, all without stopping for approval apart from some [artifact](artifacts.md) actions. What a routine can reach is determined by the repositories you select, the [environment’s](cloud-environments.md) network access and variables, and the connectors you include. Scope each of those to what the routine actually needs. When the routine’s schedule or **Run now** starts a run, Claude republishes an existing artifact without asking only when all of these hold:
- You can edit the artifact and it belongs to your own organization
- The artifact isn’t shared publicly
- If the artifact is shared with specific people or your organization, its viewers don’t automatically see each new version
- The publish carries only the page, with no supporting files or anything else added, and doesn’t force over a newer version
- The page holds no grant that reaches beyond the page, such as [connector calls](artifacts.md#pull-live-data-with-mcp-connectors)
In every other case, including publishing a new artifact, Claude asks first. When a routine’s job is to keep a page current, give it an artifact you already published. Routines belong to your individual claude.ai account. They are not shared with teammates, and their runs count against your account’s [usage and limits](#usage-and-limits). 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)
Create from the web
1
Open the creation form
Visit [claude.ai/code/routines](https://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.When a trigger fires, the session receives the routine’s saved prompt as its assigned task and carries it out, rather than treating it as untrusted content that arrived mid-conversation. The trigger attests only that the prompt was stored ahead of time by an authorized session on your account, so the fired prompt is not live user input and can’t act as approval or consent for actions during the run. Content the session fetches during the run keeps its normal handling. Before v2.1.213, the session received the same prompt framed as an untrusted background notification and could refuse to act on it.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](cloud-environments.md) 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 values Claude can use during each run. They’re [visible to anyone who uses the environment](cloud-environments.md#what-carries-over-from-your-setup), so on Pro and Max plans, store keys for the APIs Claude calls during a run as [API credentials](cloud-environments.md#add-api-credentials) instead. That section also lists the requests that never get a credential
- **Setup script**: install dependencies and tools the routine needs. The result is [cached](cloud-environments.md#environment-caching), so the script doesn’t re-run on every session
A **Default** environment is provided with **Trusted** network access, which allows only the [default allowlist](cloud-environments.md#default-allowed-domains) of package registries, cloud provider APIs, container registries, and common development domains through the session’s network. Connectors you add to the routine reach their services through Anthropic’s servers, so they don’t need allowlist changes. If your routine needs to reach your own services directly, or a domain outside that list, edit the environment’s [network access](cloud-environments.md#network-access) before running. To use a separate environment, [create one](cloud-environments.md#configure-your-environment) 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](#add-a-schedule-trigger) for timezone handling, late starts, custom cron intervals, and one-off runs.
Select the repository, the event to react to, and optional filters. See [Add a GitHub trigger](#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](#add-an-api-trigger) to copy the URL and generate a token.
6
Review connectors
Under **Connectors** at the bottom of the form, all of your connected [MCP connectors](../06-MCP-Tools/General/mcp.md) 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.
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)
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. The command is also available under the alias `/routines`. A successful start looks like a conversation: Claude asks follow-up questions about the schedule, repositories, and prompt before saving. If Claude instead replies that you need to authenticate or that it can’t connect to your remote claude.ai account, no routine was created; see [Troubleshooting](#troubleshooting). `/schedule` in the CLI creates scheduled routines. To add an API trigger, edit the routine on the web at [claude.ai/code/routines](https://claude.ai/code/routines). You can add a [GitHub trigger](#add-a-github-trigger) from the web or from the CLI. The CLI path requires Claude Code v2.1.225 or later. A routine with no schedule trigger, such as one started only by API calls or GitHub events, has no next run time, and the CLI shows none when Claude saves or updates it. Before v2.1.211, the CLI reported a next run time in the year 1 for these routines.
[](#configure-triggers)
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)
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. If you schedule a run exactly on the hour, such as 9:00, it can start several minutes late. To start close to the scheduled time, pick a few minutes past the hour, for example 9:07. 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)
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 start a follow-up task after an upstream change ships. 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.
```python
/schedule tomorrow at 9am, summarize yesterday's merged PRs
```
```python
/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 count against the same hourly limit as other scheduled runs. See [Usage and limits](#usage-and-limits) for details.
[](#add-an-api-trigger)
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](https://claude.ai/code/routines), click the routine you want to trigger via API, then open the menu next to the routine’s name and select **Edit**.
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](#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)
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 `text` value doesn’t reach the routine as a bare message. It arrives wrapped in a `<routine-fire-payload>` block that labels it as untrusted data and tells Claude not to follow instructions inside it unless the routine’s own prompt says to. The same wrapping applies to text supplied with **Run now** in the web UI. This means a routine’s saved prompt must opt in to acting on fire text: write the prompt to reference the payload explicitly, for example “Investigate the alert described in the routine-fire-payload block”, or the routine treats the text as inert context. Anyone holding the bearer token can send `text`, so the wrapper makes fire text from a leaked token arrive labeled as untrusted data rather than as direct instructions to your routine. The example below triggers a routine from a shell. The routine ID and token shown are placeholders: replace them with the URL and token you copied when [adding the API trigger](#add-an-api-trigger), or the request fails with a `401` authentication error:
```python
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:
```python
{
"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)
API reference
For the full API reference, including all error responses, validation rules, and field limits, see [Trigger a routine via API](../04-API-Reference/Endpoints/claude-code-routines-fire.md) 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)
Add a GitHub trigger
A GitHub trigger starts a new session automatically when a matching event occurs on a connected repository. Claude Code doesn’t reuse sessions across events, so two PR updates produce two independent sessions.
The Claude GitHub App must be installed on the repository you want to subscribe to, whichever surface you configure the trigger from.
- Configure GitHub triggers from the web UI, which prompts you to install the app when it’s missing. Follow the steps below to configure one on the web.
- From the CLI, install the app from the [GitHub App page](https://github.com/apps/claude) first, then ask Claude to attach a GitHub trigger to an existing routine, for example `/schedule add a GitHub trigger to my nightly review for pull requests opened in acme/webapp`. The CLI path requires Claude Code v2.1.225 or later. When Claude adds the trigger, it replies with a link to the routine the trigger fires.
1
Open the routine for editing
Go to [claude.ai/code/routines](https://claude.ai/code/routines), click the routine, then open the menu next to the routine’s name and select **Edit**.
2
Add a GitHub event trigger
Scroll to the **Select a trigger** section, click **Add another trigger**, and choose **GitHub event**.
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.
3
Configure the trigger
Select the repository, choose an event from the [supported events](#supported-events) list, and optionally add filters. Save the trigger.
[](#supported-events)
Supported events
| 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)
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.
[](#manage-routines)
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)
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)
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. You can optionally supply run-specific text, which reaches the routine the same way as the API trigger’s `text` field.
- Use the on/off switch at the top of the page to pause or resume the schedule. Paused routines keep their configuration but don’t run until you re-enable them.
- Open the menu next to the routine’s name and select **Edit** to 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.
- Open the same menu and select **Delete** to delete the routine.
[](#manage-routines-from-the-cli)
Manage routines from the CLI
The CLI supports managing existing routines. Run `/schedule list` to see all routines, `/schedule update` to change one, or `/schedule run` to trigger it immediately. You can also ask about a routine’s run history, for example `/schedule why did my nightly review do nothing this morning?`. Claude lists the routine’s recent runs with their status and a link to [open each run on the web](#view-and-interact-with-runs), and reads a run’s log to explain what happened, including tool errors, permission denials, and the final result. Requires Claude Code v2.1.227 or later.
[](#repositories-and-branch-permissions)
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 access for the repository you ran it from and, if it doesn’t, adds a setup note naming how to grant it. See [GitHub authentication options](claude-code-on-the-web.md#github-authentication-options) for the two ways to grant access. If your GitHub connection is missing or expired when a run is due, the routine skips runs until you reconnect, for up to 72 hours. Reconnect GitHub within that window and the routine resumes on its own. After 72 hours without a connection, the routine turns off, and you turn it back on after reconnecting GitHub. Each repository you add is cloned on every run. Claude starts from the repository’s default branch unless your prompt specifies otherwise. Claude pushes its work to branches prefixed with `claude/`, which are always accepted. When your prompt directs Claude to push to another branch, Claude Code checks the push first and rejects it if any of the following is true:
- The branch is protected on GitHub
- Someone else has an open pull request from that branch
- The branch carries commits authored by someone other than you
[](#connectors)
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](../06-MCP-Tools/General/mcp.md#use-mcp-servers-from-claude-ai) 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](https://claude.ai/customize/connectors). For a routine with one repository, you can instead declare it in a committed [`.mcp.json`](../06-MCP-Tools/General/mcp.md#project-scope) 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 [claude.ai/customize/connectors](https://claude.ai/customize/connectors) or use `/schedule update` in the CLI.
[](#environments-and-network-access)
Environments and network access
Each routine uses a [cloud environment](cloud-environments.md) 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, which allows only the [default allowlist](cloud-environments.md#default-allowed-domains) through the session’s network. Requests on that path to hosts outside the allowlist fail with `403` and `x-deny-reason: host_not_allowed`. MCP connector traffic is routed through Anthropic’s servers rather than that path, 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](#connectors). To allow additional domains on one of your own environments, follow these steps. An [organization-shared environment](cloud-environments.md#organization-shared-environments) opens read-only here, so an Owner changes its network access from the **Cloud environments** page in [admin settings](https://claude.ai/admin-settings) instead.
1
Open the routine for editing
On the routine’s detail page, open the menu next to the routine’s name and select **Edit**.
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](cloud-environments.md#default-allowed-domains) 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](cloud-environments.md#network-access) for details on access levels and the default allowlist.
[](#usage-and-limits)
Usage and limits
Routines draw down subscription usage the same way interactive sessions do. See your current consumption at [claude.ai/settings/usage](https://claude.ai/settings/usage). Separately from subscription usage, each way of starting a run has an hourly limit:
| Action | Limit | Counted for | Over the limit |
|:-------------------------------------------------------------------|:--------------------------------------------------|:--------------------------------------------------|:----------------------------------------|
| Scheduled runs, including one-off runs | 100 per hour | Your account | The run waits until the limit resets |
| **Run now**, API fires, and setting a one-off routine to run again | 30 per hour | Each routine, one count shared by all three | The action fails until the limit resets |
| **Run now** and setting a one-off routine to run again | 100 per hour | Your account | Same |
| API fires | 100 per hour | Your account, counted separately from **Run now** | Same |
| GitHub events | See [Add a GitHub trigger](#add-a-github-trigger) | | |
None of these hourly limits has overage. When a routine hits your subscription usage limit, organizations with usage credits turned on can keep running routines on metered overage. Without usage credits, additional runs are rejected until your usage window resets. Turn on usage credits at [claude.ai/settings/usage](https://claude.ai/settings/usage). On Team and Enterprise plans, an admin turns them on for the organization at [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage). While your subscription is paused, your routines are put on hold and don’t run. Once your subscription is active again, turn them back on.
[](#troubleshooting)
Troubleshooting
[](#schedule-returns-unknown-command)
`/schedule` returns “Unknown command”
The CLI hides `/schedule` when one of its requirements isn’t met: the command menu shows `No commands match "/schedule"` while you type. Submitting it returns `Unknown command: /schedule`, except in the cases below that note a different answer. The cause is usually one of the following:
- You are authenticated with a Console API key, an [Anthropic profile or federation credential](../13-Enterprise-Admin/iam.md#anthropic-profiles-and-federation-credentials), or a cloud provider such as Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry. `/schedule` requires a claude.ai subscription login. With a Console API key or a profile, and feature-flag fetching enabled, submitting `/schedule` instead shows `/schedule is available with Claude for Enterprise — ask your admin about migrating from API-key access`. With a cloud-provider login, you still see `Unknown command: /schedule`. If `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` is set in your shell, or `apiKeyHelper` is set in `settings.json`, remove it first, since these take precedence over a claude.ai login. A profile or federation credential takes precedence too, so switch that off as well
- You are fully signed out, with no API key or other credential. With feature-flag fetching enabled, submitting `/schedule` shows `/schedule requires a claude.ai subscription. Run /login to sign in with your claude.ai account.` Before v2.1.268, a signed-out session showed the same Claude for Enterprise message as a Console API key
- You are inside a cloud session, where submitting `/schedule` answers that the command isn’t available in that environment. Manage routines from the [web UI](https://claude.ai/code/routines) instead
- Your organization’s policy disables [cloud sessions](claude-code-on-the-web.md), which routines require. In this case, submitting `/schedule` answers [`Cloud sessions are disabled by your organization's policy`](errors.md#cloud-sessions-are-disabled-by-your-organizations-policy) instead. Before v2.1.268, it returned `Unknown command: /schedule`
- An Owner [turned off routines](#routines-are-disabled-by-your-organizations-policy) for your Team or Enterprise organization. Before v2.1.227, the command still appeared in this case, and claude.ai rejected the routine when Claude tried to create or run it
Unless your organization’s policy disables routines or cloud sessions, you can create and manage routines at [claude.ai/code/routines](https://claude.ai/code/routines) regardless of how the CLI is configured.
[](#routines-are-disabled-by-your-organizations-policy)
“Routines are disabled by your organization’s policy”
An Owner in your Team or Enterprise organization has likely turned off the **Routines** toggle at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code). On Claude Code v2.1.227 or later, the same toggle also hides `/schedule` in the CLI. This is a server-side organization setting, so it cannot be overridden from your local configuration. Ask an Owner to enable routines for your organization.
[](#related-resources)
Related resources
- [`/loop` and in-session scheduling](scheduled-tasks.md): schedule local tasks within an open CLI session
- [Desktop scheduled tasks](../16-Mobile-Desktop/desktop-scheduled-tasks.md): local scheduled tasks that run on your machine with access to local files
- [Cloud environments](cloud-environments.md): configure network access, environment variables, and setup scripts for cloud sessions
- [Projects](claude-projects.md): ongoing work Claude coordinates across parallel cloud sessions; routines created from a project appear on its **Routines** tab
- [MCP connectors](../06-MCP-Tools/General/mcp.md): connect external services like Slack, Linear, and Google Drive
- [GitHub Actions](github-actions.md): run Claude in your CI pipeline on repository events
---
## What are skills? | Claude Help Center
Source: https://support.claude.com/en/articles/12512176-what-are-skills
Path: 02-Claude-Code-CLI/what-are-skills.md
# What are skills?
Skills are folders of instructions, scripts, and resources that Claude loads dynamically to improve performance on specialized tasks. Skills teach Claude how to complete specific tasks in a repeatable way, whether that's creating documents with your company's brand guidelines, analyzing data using your organization's specific workflows, or automating personal tasks.
Skills are available for users on Free, Pro, Max, Team, and Enterprise plans. This feature requires **[code execution to be enabled](../15-Claude-AI-Features/create-and-edit-files-with-claude.md#h_1c99382190)**. Skills are also available in Claude Code, and in beta for all API users using the code execution tool.
------------------------------------------------------------------------
## How do skills work?
Skills improve Claude’s consistency, speed, and performance on many tasks. Skills work through progressive disclosure—Claude determines which skills are relevant and loads the information it needs to complete that task, helping to prevent context window overload.
When you ask Claude to complete a task, it reviews available skills, loads relevant ones, and applies their instructions.
------------------------------------------------------------------------
## Types of skills
### Anthropic skills
These are skills created and maintained by Anthropic, such as enhanced document creation for Excel, Word, PowerPoint, and PDF files. Anthropic skills are available to all users and Claude invokes them automatically when relevant.
### Custom skills
These are skills you or your organization create for specialized workflows and domain-specific tasks. Here are some potential workflows you could enable using custom skills:
- Apply brand style guidelines to documents and presentations.
- Generate communications following company email templates.
- Structure meeting notes with company-specific formats.
- Create tasks in company tools (JIRA, Asana, Linear) following team conventions.
- Execute company-specific data analysis workflows.
- Automate personal workflows and customize Claude to match your work style.
### Organization provisioned skills
For Team and Enterprise plans, organization Owners can provision skills for all users. Skills provisioned in this way appear automatically in every team member's skills list and can be set as enabled or disabled by default. This allows organizations to:
- Distribute approved workflows consistently across all employees
- Ensure teams use standardized procedures and best practices
- Deploy new capabilities without requiring individual uploads
Learn more about provisioning skills in **[Provision and manage skills for your organization](https://support.claude.com/en/articles/13119606-managing-skills-as-an-admin)**.
### Partner skills
The Skills Directory features professionally-built skills from partners like Notion, Figma, Atlassian, and others. These skills are designed to work seamlessly with their respective MCP connectors, enabling powerful integrated workflows.
------------------------------------------------------------------------
## Key benefits
**Improvement in Claude’s performance of specific tasks**: Skills provide specialized capabilities for tasks like document creation, data analysis, and domain-specific work that requires supplementing Claude's general knowledge.
**Organizational knowledge capture**: Package your company's workflows, best practices, and institutional knowledge for Claude to use consistently across your team.
**Easy customization**: Anyone can create skills by writing instructions in Markdown—no coding required for simple skills, though you can attach executable scripts to custom skills for more advanced functionality.
**Centralized management for organizations:** Team and Enterprise plan Owners can provision skills organization-wide, ensuring consistent workflows across teams without requiring individual setup from each user.
------------------------------------------------------------------------
## Agent Skills open standard
The Agent Skills specification is published as an open standard at **[agentskills.io](https://agentskills.io)**. This means skills you create aren't locked to Claude—the same skill format works across AI platforms and tools that adopt the standard. A reference Python SDK is also available for developers implementing skills support in their own platforms.
------------------------------------------------------------------------
## Skills compared to other Claude capabilities
### Skills vs. projects
**[Projects](https://support.claude.com/en/articles/9517075-what-are-projects)** provide static background knowledge that's always loaded when you start chats within them. Skills provide specialized procedures that activate dynamically when needed and work everywhere across Claude.
### Skills vs. MCP (Model Context Protocol)
MCP connects Claude to external services and data sources. Skills provide procedural knowledge—instructions for how to complete specific tasks or workflows. You can use both together: MCP connections give Claude access to tools, while skills teach Claude how to use those tools effectively.
### Skills vs. custom instructions
**[Custom instructions](../15-Claude-AI-Features/understanding-claude-s-personalization-features.md)** apply broadly to all your conversations. Skills are task-specific and only load when relevant, making them better for specialized workflows.
------------------------------------------------------------------------
## Learn more about skills
To discover available skills, check out the directory by clicking "Customize" in your account and navigating to "Skills." You can click "+" then "Browse skills" to open the directory. For more information, see **[Browse skills, connectors, and plugins in one directory](../14-Connectors/browse-skills-connectors-and-plugins-in-one-directory.md)**.
On the Enterprise plan, organizations can turn on skill scanning to check uploaded skills and plugins for malicious content. Learn more about **[skill and plugin scanning](../15-Claude-AI-Features/get-started-with-skill-and-plugin-scanning-claude-help-center.md)**.
For more details about how skills work, see **[Agent Skills](../04-API-Reference/Agents-Tools/agents-and-tools-agent-skills-overview.md)** in our Claude Docs.
---
## Week 13 · March 23–27, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w13
Path: 02-Claude-Code-CLI/whats-new-2026-w13.md
# Week 13 · March 23–27, 2026
Copy pageCopy page
Auto mode for hands-off permissions, computer use built in, PR auto-fix in the cloud, transcript search, and a PowerShell tool for Windows.
Copy pageCopy page
Releases [v2.1.83 → v2.1.85](changelog.md#2-1-83)6 features · March 23–27
Auto moderesearch 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
```python
{
"permissions": {
"defaultMode": "auto"
}
}
```
[Permission modes guide](permission-modes.md)
Computer useDesktop
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
```python
Open the iOS simulator, tap through the onboarding flow, and screenshot each step
```
[Computer use guide](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer)
PR auto-fixWeb
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](claude-code-on-the-web.md#auto-fix-pull-requests)
Transcript searchv2.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
```python
Ctrl+O # open transcript
/migrate # search for "migrate"
n # next match
N # previous match
```
[Fullscreen guide](fullscreen.md#search-and-review-the-conversation)
PowerShell toolpreviewv2.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
```python
{
"env": {
"CLAUDE_CODE_USE_POWERSHELL_TOOL": "1"
}
}
```
[PowerShell tool docs](tools-reference.md#powershell-tool)
Conditional hooksv2.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
```python
{
"hooks": {
"PreToolUse": [{
"hooks": [{
"if": "Bash(git commit *)",
"type": "command",
"command": ".claude/hooks/lint-staged.sh"
}]
}]
}
}
```
[Hooks reference](../07-Hooks/hooks.md)
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 →](changelog.md#2-1-83)
---
## Week 14 · March 30 – April 3, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w14
Path: 02-Claude-Code-CLI/whats-new-2026-w14.md
# Week 14 · March 30 – April 3, 2026
Copy pageCopy page
Computer use in the CLI, interactive in-product lessons, flicker-free rendering, per-tool MCP result-size overrides, and plugin executables on PATH.
Copy pageCopy page
Releases [v2.1.86 → v2.1.91](changelog.md#2-1-86)5 features · March 30 – April 3
Computer use in the CLIresearch 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.
Requires macOS and a Pro or Max plan; otherwise, `computer-use` won’t appear in `/mcp`. Run `/mcp`, find `computer-use`, and toggle it on. Then ask Claude to verify a change end to end:
Claude Code
```python
Open the iOS simulator, tap through onboarding, and screenshot each step
```
[Computer use guide](computer-use.md)
/powerupv2.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
```python
/powerup
```
[Commands reference](commands.md)
Flicker-free renderingv2.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:
```python
export CLAUDE_CODE_NO_FLICKER=1
claude
```
[Fullscreen rendering](fullscreen.md)
MCP result-size overridev2.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:
```python
{
"name": "get_schema",
"description": "Returns the full database schema",
"_meta": {
"anthropic/maxResultSizeChars": 500000
}
}
```
[MCP reference](../06-MCP-Tools/General/mcp.md#raise-the-limit-for-a-specific-tool)
Plugin executables on PATHv2.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:
```python
my-plugin/
├── .claude-plugin/
│ └── plugin.json
└── bin/
└── my-tool
```
[Plugins reference](../08-Plugins-Skills/plugins-reference.md#standard-layout)
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` → Recently denied 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. An April Fools’ joke, no longer available
`disableSkillShellExecution` setting blocks inline shell from skills, custom 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 →](changelog.md#2-1-86)
---
## Week 15 · April 6–10, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w15
Path: 02-Claude-Code-CLI/whats-new-2026-w15.md
# Week 15 · April 6–10, 2026
Copy pageCopy page
Ultraplan cloud planning, the Monitor tool with self-pacing /loop, /team-onboarding for packaging your setup, and /autofix-pr from your terminal.
Copy pageCopy page
Releases [v2.1.92 → v2.1.101](changelog.md#2-1-92)4 features · April 6–10
Ultraplanresearch 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
```python
/ultraplan migrate the auth service from sessions to JWTs
```
[Ultraplan guide](ultraplan.md)
Monitor toolv2.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
```python
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
```python
/loop check CI on my PR
```
[Monitor tool reference](tools-reference.md#monitor-tool)
/autofix-prCLI
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
```python
/autofix-pr
```
[Auto-fix pull requests](claude-code-on-the-web.md#auto-fix-pull-requests)
/team-onboardingv2.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
```python
/team-onboarding
```
[Commands reference](commands.md)
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 [Amazon Bedrock](amazon-bedrock.md) and [Google Cloud’s Agent Platform](google-vertex-ai.md) 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, Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft 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 →](changelog.md#2-1-92)
---
## Week 16 · April 13–17, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w16
Path: 02-Claude-Code-CLI/whats-new-2026-w16.md
# Week 16 · April 13–17, 2026
Copy pageCopy page
Claude Opus 4.7 with the new xhigh effort level, Routines on Claude Code on the web, mobile push notifications that ping your phone when Claude needs you, a /usage breakdown that shows what’s driving your limits, and native binaries replacing the bundled JavaScript.
Copy pageCopy page
Releases [v2.1.105 → v2.1.113](changelog.md#2-1-105)5 features · April 13–17
Claude Opus 4.7new 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
```python
> /model opus
> /effort xhigh
```
[Model config: effort levels](model-config.md#adjust-effort-level)
Routinesweb
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
```python
> /schedule daily PR review at 9am
```
[Routines guide](web-scheduled-tasks.md)
/usage breakdownCLI
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
```python
> /usage
```
[Commands reference](commands.md)
Mobile push notificationsmobile
With [Remote Control](remote-control.md) 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
```python
> notify me when the tests pass
```
[Remote Control: mobile push notifications](remote-control.md#mobile-push-notifications)
Native binariesv2.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:
```python
claude update
claude --version
```
[Setup guide](../01-Getting-Started/setup.md)
Other wins
New [`/ultrareview`](ultrareview.md): 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](permission-modes.md#eliminate-prompts-with-auto-mode) is now available for Max subscribers on Opus 4.7, and the `--enable-auto-mode` flag is no longer required
[Session recap](interactive-mode.md#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, Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft 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 →](changelog.md#2-1-105)
---
## Week 17 · April 20–24, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w17
Path: 02-Claude-Code-CLI/whats-new-2026-w17.md
# Week 17 · April 20–24, 2026
Copy pageCopy page
/ultrareview opens as a research preview, automatic session recaps when you return to a terminal, custom color themes you can build and ship in plugins, and a redesigned Claude Code on the web.
Copy pageCopy page
Releases [v2.1.114 → v2.1.119](changelog.md#2-1-114)4 features · April 20–24
/ultrareviewresearch 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
```python
> /ultrareview
```
Or point it at a PR:
Claude Code
```python
> /ultrareview 1234
```
[Ultrareview guide](ultrareview.md)
Session recapCLI
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
```python
> /recap
```
[Interactive mode: session recap](interactive-mode.md#session-recap)
Custom themesv2.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
```python
> /theme
```
[Terminal config: create a custom theme](terminal-config.md#create-a-custom-theme)
Claude Code on the webweb
A new look for [claude.ai/code](https://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](claude-code-on-the-web.md)
Other wins
[Vim visual mode](interactive-mode.md#vim-editor-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”`](../07-Hooks/hooks.md#mcp-tool-hook-fields), so a hook can hit an already-connected server without spawning a process
`/cost` and `/stats` are merged into [`/usage`](commands.md); 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](settings.md)
[Forked subagents](../09-Agents-Patterns/sub-agents.md#fork-the-current-conversation) 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](model-config.md#adjust-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`](auto-mode-config.md) to add custom rules alongside the built-in list instead of replacing it
New [`claude plugin tag`](../08-Plugins-Skills/plugins-dependencies.md#tag-plugin-releases-for-version-resolution) 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 →](changelog.md#2-1-114)
---
## Week 18 · April 27 – May 1, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w18
Path: 02-Claude-Code-CLI/whats-new-2026-w18.md
# Week 18 · April 27 – May 1, 2026
Copy pageCopy page
Claude Code on Windows runs without Git Bash, claude auth login accepts a pasted OAuth code when the browser callback can’t reach localhost, claude project purge cleans up local state per project, and pasting a PR URL into /resume finds the session that created it.
Copy pageCopy page
Releases [v2.1.120 → v2.1.126](changelog.md#2-1-120)4 features · April 27 – May 1
Sign in without a browser callbackv2.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:
```python
claude auth login
```
[CLI reference](cli-reference.md#cli-commands)
claude project purgev2.1.124
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:
```python
claude project purge --dry-run
```
Then run it for real:
```python
claude project purge
```
[CLI reference](cli-reference.md)
Resume by PR URLv2.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
```python
> /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
```python
https://github.com/your-org/your-repo/pull/1234
```
To open the picker already filtered to the PR, pass the PR number on the command line:
```python
claude --from-pr 1234
```
[Sessions: use the session picker](sessions.md#use-the-session-picker)
Windows without Git BashWindows
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](../01-Getting-Started/setup.md)
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`](ultrareview.md) 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 an Amazon Bedrock service tier: `default`, `flex`, or `priority`
`/terminal-setup` enables iTerm2’s clipboard access setting so `/copy` works, including from tmux
Google Cloud’s Agent Platform 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 →](changelog.md#2-1-120)
---
## Week 19 · May 4–8, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w19
Path: 02-Claude-Code-CLI/whats-new-2026-w19.md
# Week 19 · May 4–8, 2026
Copy pageCopy page
Load plugins from .zip archives and URLs, search command history across every project with Ctrl+R, branch new worktrees from local HEAD or the remote default, and block actions unconditionally with auto mode hard deny rules.
Copy pageCopy page
Releases [v2.1.128 → v2.1.136](changelog.md#2-1-128)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
```python
claude --plugin-url https://example.com/my-plugin.zip
```
[Plugins guide](../08-Plugins-Skills/plugins.md)
History search across all your projectsv2.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](interactive-mode.md#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 →](changelog.md#2-1-128)
---
## Week 20 · May 11–15, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w20
Path: 02-Claude-Code-CLI/whats-new-2026-w20.md
# Week 20 · May 11–15, 2026
Copy pageCopy page
Manage every Claude Code session from one screen with agent view, keep Claude working toward a goal until a condition holds, and run fast mode on Opus 4.7 by default.
Copy pageCopy page
Releases [v2.1.139 → v2.1.142](changelog.md#2-1-139)3 features · May 11–15
Agent viewresearch preview
`claude agents` opens one screen for every Claude Code session: what’s running, what’s blocked on your input, and what’s done. Dispatch a bug fix, a pull request review, and a flaky-test investigation as three rows, keep working in another window, and step in only when a row needs you. Attach to any row to drop into its full conversation, then press `←` to return to the list. Each background session keeps running without a terminal attached.
Open the dashboard from your shell:
terminal
```python
claude agents
```
[Agent view](../09-Agents-Patterns/agent-view.md)
/goalv2.1.139
Set a completion condition and Claude keeps working toward it across turns without you prompting each step. After every turn, a fast model checks whether the condition holds; if not, Claude starts another turn instead of handing control back. Useful for substantial work with a verifiable end state, like migrating a module until every call site compiles and tests pass. The goal clears once the condition is met, and works in interactive, `-p`, and Remote Control.
Set a goal and let Claude run until it holds:
Claude Code
```python
> /goal all tests in test/auth pass and the lint step is clean
```
[Goals](goal.md)
Fast mode on Opus 4.7research preview
`/fast` now runs on Opus 4.7 by default instead of Opus 4.6. Fast mode is a high-speed Opus configuration: the same model quality at about 2.5x the speed for a higher per-token cost, useful for rapid iteration and live debugging. Pricing is unchanged at \$30/\$150 per MTok, the same as Opus 4.6 fast mode. To pin fast mode to Opus 4.6, set `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE=1`.
Toggle fast mode, now running on Opus 4.7:
Claude Code
```python
> /fast
```
[Fast mode on Opus 4.7](fast-mode.md#understand-the-cost-tradeoff)
Other wins
`claude agents` gained dispatch flags (`--add-dir`, `--settings`, `--mcp-config`, `--plugin-dir`, `--permission-mode`, `--model`, `--effort`, `--dangerously-skip-permissions`) to configure background sessions, and `claude agents --cwd <path>` scopes the session list to a directory
New hook `args: string[]` exec form spawns the command directly without a shell, so path placeholders never need quoting
New `continueOnBlock` config option for `PostToolUse` hooks feeds the hook’s rejection reason back to Claude and continues the turn instead of ending it
New `terminalSequence` field in hook JSON output lets hooks emit desktop notifications, window titles, and bells without a controlling terminal
The Rewind menu added “Summarize up to here” to compress earlier context while keeping recent turns intact
Remote Control, `/schedule`, claude.ai MCP connectors, and notification preferences are now disabled when `ANTHROPIC_API_KEY`, `apiKeyHelper`, or `ANTHROPIC_AUTH_TOKEN` is set, even alongside a claude.ai login; unset the API key to use these features
MCP stdio servers now receive `CLAUDE_PROJECT_DIR` in their environment, matching hooks, and plugin configs can reference `$CLAUDE_PROJECT_DIR` in commands
`claude plugin details <name>` shows a plugin’s component inventory and projected per-session token cost, and the `/plugin` details pane now also lists the LSP servers a plugin provides
Plugins with a root-level `SKILL.md` and no `skills/` subdirectory are now surfaced as a skill
`/feedback` can now include recent sessions from the last 24 hours or 7 days for issues spanning more than the current session
Agent tool `subagent_type` now matches case- and separator-insensitively, so `“Code Reviewer”` resolves to `code-reviewer`
[Full changelog for v2.1.139–v2.1.142 →](changelog.md#2-1-139)
---
## Week 21 · May 18–22, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w21
Path: 02-Claude-Code-CLI/whats-new-2026-w21.md
# Week 21 · May 18–22, 2026
Copy pageCopy page
Use auto mode on the Pro plan and with Sonnet 4.6, see which skills, subagents, and MCP servers drive your plan limits in /usage, and review diffs with the new /code-review command.
Copy pageCopy page
Releases [v2.1.143 → v2.1.149](changelog.md#2-1-143)1 feature · May 18–22
Auto mode on the Pro planCLI
Auto mode is now available on the Pro plan and supports Sonnet 4.6 alongside Opus. It replaces permission prompts with background safety checks: routine actions run without interrupting you, and destructive or suspicious ones are blocked and surfaced.
Update Claude Code, then cycle modes with Shift+Tab; auto mode appears in the cycle once your account meets the requirements:
terminal
```python
claude update
```
The command prints `Successfully updated` with the new version number, or `Claude Code is up to date` if no update is needed. Once auto mode is active, the prompt footer shows `auto mode on`.
[Auto mode requirements](permission-modes.md#eliminate-prompts-with-auto-mode)
Other wins
[`/usage`](../17-Billing-Plans/costs.md#track-your-costs) now shows a per-category breakdown of what’s driving your plan limits, attributing recent usage to skills, subagents, plugins, and individual MCP servers
”Extra usage” is renamed to “usage credits” across the CLI, and `/extra-usage` is now `/usage-credits`. The old name still works. The command requires signing in with your claude.ai subscription through `/login` and isn’t available with API key authentication.
New [`/code-review`](code-review.md) command reports correctness bugs at a chosen effort level such as `/code-review high`, and `--comment` posts findings as inline GitHub PR comments. `/simplify` remains as a separate cleanup-only review.
Background sessions now appear in `/resume` alongside interactive ones, marked with `bg`, and sessions pinned with `Ctrl+T` in `claude agents` stay alive when idle
`claude agents --json` lists live sessions as JSON for scripting, such as status bars and session pickers
The PowerShell tool is now enabled by default on Windows for Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry users; opt out with `CLAUDE_CODE_USE_POWERSHELL_TOOL=0`
`claude plugin disable` now refuses when another enabled plugin depends on the target, and `claude plugin enable` force-enables transitive dependencies
The `/plugin` marketplace browse pane shows projected context cost, and the Discover and Browse screens list a plugin’s commands, agents, skills, hooks, and MCP/LSP servers before installation
New `worktree.bgIsolation: “none”` setting lets background sessions edit the working copy directly without `EnterWorktree`, for repos where worktrees are impractical
Markdown output renders GFM task list checkboxes, and the `/diff` detail view scrolls with the keyboard
Status line JSON input now includes GitHub repo and PR information when detected
Enterprise: the `allowAllClaudeAiMcps` managed setting loads claude.ai cloud MCP connectors alongside `managed-mcp.json`
[Full changelog for v2.1.143–v2.1.149 →](changelog.md#2-1-143)
---
## Week 22 · May 25–29, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w22
Path: 02-Claude-Code-CLI/whats-new-2026-w22.md
# Week 22 · May 25–29, 2026
Copy pageCopy page
Run Claude Code on Claude Opus 4.8, orchestrate large tasks with dynamic workflows, catch security issues with the security-guidance plugin, and use fast mode on Opus 4.8 at a lower price.
Copy pageCopy page
Releases [v2.1.150 → v2.1.157](changelog.md#2-1-150)4 features · May 25–29
Claude Opus 4.8new model
Opus 4.8 is now the default on Max, Team Premium, Enterprise pay-as-you-go, and the Anthropic API. It defaults to high effort; use `/effort xhigh` for harder tasks. Requires v2.1.154 or later.
Switch to Opus 4.8 by name, or pick it from the model picker:
Claude Code
```python
/model claude-opus-4-8
```
[Model configuration](model-config.md#available-models)
Dynamic workflowsresearch preview
A workflow is an orchestration script Claude writes for your task and runs across many subagents in the background. Use one when a task is too large for one conversation to coordinate: a codebase-wide audit, a large migration, a research question that needs cross-checking. Manage runs with `/workflows`.
Describe the task and ask for a workflow:
Claude Code
```python
create a workflow that migrates every internal fetch() call to the new HttpClient wrapper
```
[Dynamic workflows](workflows.md)
Security guidance pluginplugin
The security-guidance plugin reviews Claude’s code changes for vulnerabilities and fixes them in the same session. It runs a fast pattern check on each edit, a model review at the end of each turn, and a deeper agentic review on commit or push. Add project rules in `.claude/claude-security-guidance.md`.
Install it from the official Anthropic marketplace:
Claude Code
```python
/plugin install security-guidance@claude-plugins-official
```
Then activate it in the current session:
Claude Code
```python
/reload-plugins
```
[Security guidance plugin](security-guidance.md)
Fast mode on Opus 4.8research preview
Fast mode now defaults to Opus 4.8 at \$10/\$50 per MTok: 2x the standard rate for about 2.5x the speed. Opus 4.7 and 4.6 stay at \$30/\$150. Opus 4.6 fast mode is deprecated.
Toggle fast mode, now on Opus 4.8:
Claude Code
```python
/fast
```
[Fast mode pricing](fast-mode.md#understand-the-cost-tradeoff)
Other wins
In `claude agents`, prefix a shell command with `!` to run it as a background job you can attach to and detach from; also available as `claude --bg --exec 'pytest -x'`
Plugins in `.claude/skills` directories are now loaded automatically, no marketplace required, and `claude plugin init <name>` scaffolds a new plugin
New `/reload-skills` command re-scans skill directories without restarting, and `SessionStart` hooks can return `reloadSkills: true` to make skills they install available in the same session
Skills and commands can set `disallowed-tools` in frontmatter to remove tools from the model while the skill is active
New `MessageDisplay` hook event lets hooks transform or hide assistant message text as it is displayed
Claude Code now switches to your configured `--fallback-model` for the rest of the session when the primary model is not found, instead of failing every request
Plugins can declare `defaultEnabled: false` in `plugin.json` or a marketplace entry, so they install without turning on until you enable them
Vim mode: `/` in NORMAL mode opens reverse history search, matching Bash and Zsh vi-mode
Streaming tool execution is now always enabled, including with telemetry disabled and on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry
`←←` to open the agents view now works on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and with telemetry disabled
Claude in Chrome: pick which connected browser to use via `/chrome` → “Select browser…”, or in-chat when a browser action runs with multiple connected
`claude mcp list` and `claude mcp get` now show unapproved `.mcp.json` servers as pending approval instead of auto-approving and connecting when output is piped
[Full changelog for v2.1.150–v2.1.157 →](changelog.md#2-1-150)
---
## Week 23 · June 1–5, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w23
Path: 02-Claude-Code-CLI/whats-new-2026-w23.md
# Week 23 · June 1–5, 2026
Copy pageCopy page
Run auto mode on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, prompt before writing files that can run code in acceptEdits mode, list installed plugins with /plugin list, and require an approved version range for managed deployments.
Copy pageCopy page
Releases [v2.1.158 → v2.1.165](changelog.md#2-1-158)4 features · June 1–5
Auto mode on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundryv2.1.158
Auto mode is now available on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry for Opus 4.7 and Opus 4.8, replacing permission prompts with background safety checks on third-party providers. Opt in by setting `CLAUDE_CODE_ENABLE_AUTO_MODE=1`.
Opt in on a third-party provider, then cycle to auto mode with Shift+Tab:
terminal
```python
export CLAUDE_CODE_ENABLE_AUTO_MODE=1
```
[Auto mode on third-party providers](permission-modes.md#enable-auto-mode-on-bedrock-agent-platform-or-foundry)
Safer automatic editsv2.1.160
Claude Code now prompts before writing files that can run code, even in `acceptEdits` mode. The protected set covers shell startup files such as `.zshenv` and `.bash_login`, git config under `~/.config/git/`, and build-tool configs such as `.npmrc`, `.bazelrc`, and `.pre-commit-config.yaml`. These writes are never auto-approved in any mode except `bypassPermissions`.
Work in acceptEdits mode; Claude now pauses before writing these files:
terminal
```python
claude --permission-mode acceptEdits
```
[Protected paths](permission-modes.md#protected-paths)
List installed plugins with /plugin listv2.1.163
The new `/plugin list` command prints your installed plugins inline, without opening the `/plugin` menu, and is also available as `claude plugin list` from the shell. In the interactive form, add `--enabled` or `--disabled` to show only plugins in that state.
List the plugins that are currently turned on:
Claude Code
```python
> /plugin list --enabled
```
[Plugin commands](../08-Plugins-Skills/plugins-cli-reference.md#plugin-list)
Version requirements for managed deploymentsv2.1.163
Two managed settings, `requiredMinimumVersion` and `requiredMaximumVersion`, let your organization require an approved Claude Code version range. A client outside the range exits at startup and tells the user to update through the organization’s method. `claude update`, `claude install`, and `claude doctor` keep working so users can still recover.
Add a floor to your managed settings so older clients refuse to start:
managed-settings.json
```python
{
"requiredMinimumVersion": "2.1.163"
}
```
[Decide what to enforce](../13-Enterprise-Admin/admin-setup.md#decide-what-to-enforce)
Other wins
The trigger keyword for [dynamic workflows](workflows.md) changed from `workflow` to `ultracode`; asking for a workflow in your own words still works, and the keyword is highlighted in violet in the prompt
[Stop and SubagentStop hooks](../07-Hooks/hooks.md) can return `hookSpecificOutput.additionalContext` to give Claude feedback and keep the turn going instead of being treated as an error
`claude mcp` list, get, and add no longer print secrets: environment-variable references are not expanded, and credential headers and URL secrets are redacted
A failed Bash command in a parallel tool batch no longer cancels the others; each tool returns its own result independently
Editing a file no longer needs a separate Read first when you viewed it with a single-file `grep`, `egrep`, or `fgrep`
Clicking a command in the autocomplete menu now fills it into your prompt instead of running it immediately; press Enter to run
Listing `Grep` or `Glob` in `--tools` now provides the dedicated search tools on native builds with embedded search, instead of silently ignoring those names
`/effort` now confirms when your chosen level will persist as the default for new sessions
`OTEL_RESOURCE_ATTRIBUTES` values are now attached as labels on metric datapoints, so you can slice usage metrics by custom dimensions like team or repo
Windsurf is renamed to Devin Desktop in `/ide`, `/terminal-setup`, and `/scroll-speed`, following the editor’s rebrand
`/btw` gains a `c to copy` shortcut that copies the raw markdown answer to the clipboard
[Full changelog for v2.1.158–v2.1.165 →](changelog.md#2-1-158)
---
## Week 24 · June 8–12, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w24
Path: 02-Claude-Code-CLI/whats-new-2026-w24.md
# Week 24 · June 8–12, 2026
Copy pageCopy page
Move a session to a new directory with /cd, let subagents spawn their own subagents, and troubleshoot a broken configuration with safe mode.
Copy pageCopy page
Releases [v2.1.166 → v2.1.176](changelog.md#2-1-166)3 features · June 8–12
Move a session with /cdv2.1.169
The new `/cd` command moves the current session to a different working directory without rebuilding the prompt cache: the new directory’s `CLAUDE.md` is appended as a message instead of replacing the system prompt. The session relocates to the new directory’s project storage, so `--resume` and `--continue` find it there. Claude prompts you to trust the directory if you haven’t worked in it before.
Move the session into another project without restarting:
Claude Code
```python
> /cd ../other-project
```
[Commands reference](commands.md#all-commands)
Subagents can spawn subagentsv2.1.172
Subagents can now spawn their own subagents. The subagent panel below the prompt shows the full tree: each row carries a count of its descendants and a path back to `main`. Subagent chains are capped at five levels deep to prevent runaway concurrent trees.
Open the agents view to watch the nested tree as work fans out:
Claude Code
```python
> /agents
```
[Spawn nested subagents](../09-Agents-Patterns/sub-agents.md#let-subagents-spawn-their-own-subagents)
Troubleshoot with safe modev2.1.169
Start Claude Code with `--safe-mode`, or set `CLAUDE_CODE_SAFE_MODE`, to launch with all customizations disabled: `CLAUDE.md`, skills, plugins, hooks, MCP servers, and custom commands and agents do not load. Authentication, model selection, built-in tools, and permissions still work. If a problem disappears in safe mode, one of those surfaces is the cause.
Launch a clean session to isolate a broken configuration:
terminal
```python
claude --safe-mode
```
[Test against a clean configuration](debug-your-config.md#test-against-a-clean-configuration)
Other wins
[`fallbackModel`](model-config.md#fallback-model-chains) configures up to three fallback models tried in order when the primary is overloaded or unavailable, and `--fallback-model` now applies to interactive sessions too
Session titles are now generated in the language of your conversation; pin a specific one with the `language` setting
`claude agents --json` adds `--all` to include completed sessions plus new `id` and `state` fields, and no longer omits blocked or newly dispatched sessions
Browsing a marketplace’s plugins in `/plugin` now has a search bar
New `disableBundledSkills` setting and `CLAUDE_CODE_DISABLE_BUNDLED_SKILLS` hide bundled skills, workflows, and built-in commands from the model
Deny rules accept a glob in the tool-name position, so `”*”` denies all tools, and unknown tool names in deny rules now warn at startup
Agent messaging is hardened: messages relayed via `SendMessage` from other agents no longer carry user authority, and auto mode blocks them
Amazon Bedrock reads the AWS region from `~/.aws` config files when `AWS_REGION` is unset, and `/status` shows where the region came from
New `enforceAvailableModels` managed setting makes the `availableModels` allowlist also constrain the Default model
Claude in Chrome browser tools now load in a single batched call instead of one per tool
`claude update` announces the target version before downloading instead of going silent
New `footerLinksRegexes` setting adds regex-matched link badges to the footer row
[Full changelog for v2.1.166–v2.1.176 →](changelog.md#2-1-166)
---
## Week 25 · June 15–19, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w25
Path: 02-Claude-Code-CLI/whats-new-2026-w25.md
# Week 25 · June 15–19, 2026
Copy pageCopy page
Publish a live, shareable page from your session with Artifacts, match tool parameters in deny and ask rules, and set any setting from the prompt with /config.
Copy pageCopy page
Releases [v2.1.178 → v2.1.183](changelog.md#2-1-178)3 features · June 15–19
Artifacts
An artifact is a live, interactive page that Claude Code publishes from your session to a private URL on claude.ai, and it updates in place as the session keeps working. Ask for one when terminal text is the wrong medium, such as a PR walkthrough with the diff annotated inline or a dashboard built from session data. Artifacts are in beta on Team and Enterprise plans.
Ask Claude for a page, then approve the publish prompt:
Claude Code
```python
Make an artifact that walks through this PR with the diff annotated inline.
```
[Create an artifact](artifacts.md#create-an-artifact)
Match by input parameterv2.1.178
Deny and ask permission rules can now match a tool’s input parameters with the `Tool(param:value)` syntax. For example, `Agent(model:opus)` matches subagent spawns that request the Opus model tier. The value accepts `*` as a wildcard, so `Agent(isolation:*)` matches any explicit isolation value.
Add a parameter rule to the deny list in `settings.json`:
.claude/settings.json
```python
{
"permissions": {
"deny": ["Agent(model:opus)"]
}
}
```
[Match by input parameter](permissions.md#match-by-input-parameter)
Set any setting from the promptv2.1.181
Pass `key=value` to `/config` to change a setting directly without opening the Settings interface. The syntax also works in non-interactive mode with the `-p` flag and from Remote Control.
Set the `thinking` setting from the prompt:
Claude Code
```python
/config thinking=false
```
[Commands reference](commands.md#all-commands)
Other wins
Auto mode now blocks destructive git commands (`git reset --hard`, `git clean -fd`, `git stash drop`) when you didn’t ask to discard local work, and blocks `terraform destroy` unless you asked for the specific stack
Set the new `attribution.sessionUrl` setting to `false` to omit the claude.ai session link from commits and PRs in web and Remote Control sessions
In the `/config` interface, Enter and Space both change the selected setting, and Esc now saves and closes instead of reverting
New `sandbox.allowAppleEvents` opt-in setting lets sandboxed commands send Apple Events on macOS
Point `CLAUDE_CLIENT_PRESENCE_FILE` at a marker file to suppress mobile push notifications while you’re at the machine
Long paragraphs now stream line by line instead of waiting for the first line break
API connection drops mid-thinking now retry automatically instead of showing “Connection closed while thinking”
With `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` set, every session has one implicit team, so you spawn teammates directly with the Agent tool’s `name` parameter
Skills in nested `.claude/skills` directories load when working on files there; on a name clash the nested skill appears as `<dir>:<name>` so both stay available
Fixed prompt caching not reading on a custom `ANTHROPIC_BASE_URL` and on Microsoft Foundry
Fixed Write and Edit producing zero-byte or truncated files on network drives and cloud-synced folders
[Full changelog for v2.1.178–v2.1.183 →](changelog.md#2-1-178)
---
## Week 26 · June 22–26, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w26
Path: 02-Claude-Code-CLI/whats-new-2026-w26.md
# Week 26 · June 22–26, 2026
Copy pageCopy page
Authenticate MCP servers from your shell with claude mcp login, get a response to shell mode command output with the ! prefix, and resume a conversation from before /clear with /rewind.
Copy pageCopy page
Releases [v2.1.185 → v2.1.193](changelog.md#2-1-185)2 features · June 22–26
Authenticate MCP servers from the CLIv2.1.186
New `claude mcp login <name>` and `claude mcp logout <name>` commands authenticate a configured MCP server from your shell instead of the interactive `/mcp` menu. `claude mcp login` runs the server’s OAuth flow directly, and `claude mcp logout` clears the stored credentials.
Run the OAuth flow for a configured server without opening a session:
terminal
```python
claude mcp login sentry
```
[Authenticate from the command line](../06-MCP-Tools/General/mcp.md#authenticate-from-the-command-line)
Shell mode responds to command outputv2.1.186
Commands you run with the `!` prefix now get a response from Claude once the output lands in the transcript, so you can run `! npm test` and get an explanation of the failures without a second prompt. The response costs the same as sending a normal prompt. To keep the earlier behavior, where the output is added to context without a response, set `respondToBashCommands` to `false` in `settings.json`.
Run a command and get a response to its output:
Claude Code
```python
> ! npm test
```
[Shell mode with the ! prefix](interactive-mode.md#shell-mode-with-prefix)
Other wins
`/rewind` can now resume a conversation from before `/clear` was run
New `sandbox.credentials` setting blocks sandboxed commands from reading credential files and secret environment variables
Org-configured model restrictions now apply to the model picker, `--model`, `/model`, and `ANTHROPIC_MODEL`, with a “restricted by your organization’s settings” message when a restricted model is selected
New `autoMode.classifyAllShell` setting routes all Bash and PowerShell commands through the auto-mode classifier, and denial reasons now show in the transcript, the denial toast, and `/permissions`
New `claude_code.assistant_response` OpenTelemetry log event carries the model’s response text; deployments that already log prompt content start receiving it on upgrade, so set `OTEL_LOG_ASSISTANT_RESPONSES=0` to keep prompts only
Background subagents now surface permission prompts in the main session instead of auto-denying; the dialog shows which agent is asking, and Esc denies only that tool
`/install-github-app` can now install only the GitHub App and skip the Actions workflow and secret steps
Hosts you allow in the sandbox network permission dialog are remembered for the rest of the session instead of re-prompting on every connection
Streaming responses use about 37% less CPU, and long-session memory growth from the terminal output cache is reduced
`/review <pr>` now uses the same review engine as `/code-review medium`
Bash mode `!` commands get live file path autocomplete
[Full changelog for v2.1.185–v2.1.193 →](changelog.md#2-1-185)
---
## Week 27 · June 29 – July 3, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w27
Path: 02-Claude-Code-CLI/whats-new-2026-w27.md
# Week 27 · June 29 – July 3, 2026
Copy pageCopy page
Claude Sonnet 5 becomes the default model, Claude in Chrome reaches general availability, subagents run in the background by default, Claude Desktop arrives on Linux in beta, and /radio tunes into Claude FM.
Copy pageCopy page
Releases [v2.1.195 → v2.1.201](changelog.md#2-1-195)5 features · June 29 – July 3
Claude Sonnet 5new model
Sonnet 5 is the new default model for Pro, Team Standard, and Enterprise subscription seats: top-tier coding and tool use at Sonnet pricing, with a native 1M-token context window and adaptive thinking on by default. API pricing is promotional at \$2/\$10 per MTok through August 31. Requires v2.1.197 or later.
Switch to Sonnet 5 by name, or pick it from the model picker:
Claude Code
```python
> /model claude-sonnet-5
```
[Model configuration](model-config.md#available-models)
Claude in Chrome is generally availablev2.1.198
The Chrome integration is out of preview for everyone on a direct Anthropic plan. Claude Code drives your browser through the Claude in Chrome extension: it opens tabs, clicks through pages, fills forms, reads console logs, and shares your login state, so it can test the app it builds without you switching contexts.
[Use Claude Code with Chrome](../03-IDE-Integrations/chrome.md)
Subagents run in the background by defaultv2.1.198
Claude now keeps working while subagents run and picks up their results when they finish, instead of pausing the conversation to wait. Claude still runs a subagent in the foreground when it needs the result before continuing, and background subagents surface every permission prompt in your main session. Pin a subagent’s behavior with the `background` frontmatter field.
[Run subagents in foreground or background](../09-Agents-Patterns/sub-agents.md#run-subagents-in-foreground-or-background)
Claude Desktop on LinuxDesktop
The Claude desktop app is now available on Ubuntu 22.04+ and Debian 12+ in beta, on x86_64 and arm64. You get the same Chat, Cowork, and Claude Code experience as macOS and Windows: parallel sessions, visual diff review, an integrated terminal and editor, and live app preview. Installs from Anthropic’s apt repository, so updates arrive through regular package updates.
[Claude Desktop on Linux](../16-Mobile-Desktop/desktop-linux.md)
/radioCLI
Claude FM is on the air. `/radio` opens the lo-fi radio stream in your browser for something to code to, and prints the stream URL when no browser is available. Not available on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry.
Tune in from any session:
Claude Code
```python
> /radio
```
[All commands](commands.md#all-commands)
Other wins
[Artifacts](artifacts.md) are now generally available and included on Pro and Max plans, joining Team and Enterprise
Admins can set an [organization default model](model-config.md#organization-default-model) in the org console; it shows as “Org default” in `/model` when you haven’t picked a model yourself
Stacked skill invocations like `/skill-a /skill-b do XYZ` now load all leading skills (up to 5), not only the first
`AskUserQuestion` dialogs no longer auto-continue by default; opt into an idle timeout via `/config`
The “default” permission mode is now named “Manual” across the CLI, `--help`, VS Code, and JetBrains; `--permission-mode manual` is accepted alongside `default`
New `/dataviz` skill gives chart and dashboard design guidance, with a runnable color-palette validator
The built-in Explore agent now inherits the main session’s model (capped at Opus) instead of running on Haiku
Background agents launched from `claude agents` now commit, push, and open a draft PR when they finish code work in a worktree, instead of stopping to ask
Hook matchers with hyphenated identifiers like `code-reviewer` now exact-match instead of substring-matching; use `mcp__brave-search__.*` to match all tools from a hyphenated MCP server
Transient server rate-limit errors unrelated to your usage limit are now retried automatically with backoff for subscribers instead of failing the turn
The streaming idle watchdog is now on by default for all providers: it aborts and retries when a response stream produces no events for 5 minutes (`CLAUDE_ENABLE_STREAM_WATCHDOG=0` to disable)
[Full changelog for v2.1.195–v2.1.201 →](changelog.md#2-1-195)
---
## Week 28 · July 6–10, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w28
Path: 02-Claude-Code-CLI/whats-new-2026-w28.md
# Week 28 · July 6–10, 2026
Copy pageCopy page
Browse external sites from the Desktop app’s built-in browser, run a full setup checkup with /doctor, and pick up auto mode transcript protections and agent view upgrades.
Copy pageCopy page
Releases [v2.1.202 → v2.1.206](changelog.md#2-1-202)2 features · July 6–10
In-app browser on DesktopDesktop
Claude Code on desktop now has a built-in browser. Claude can pull up docs, designs, or any other site, and read, click through, and interact with pages the same way it does with your local dev server previews. The browser is sandboxed and configurable: you choose whether browsing sessions persist, and safety classifiers review actions on external sites.
[Browse external sites](../16-Mobile-Desktop/desktop.md#browse-external-sites)
/doctor is a full setup checkupv2.1.205
`/doctor` now diagnoses issues and can fix them, instead of printing a read-only report. It checks installation health, finds unused skills, MCP servers, and plugins versus their context cost, deduplicates local `CLAUDE.md` files against checked-in ones, proposes trimming `CLAUDE.md` content Claude could derive from the codebase, and flags slow hooks. It reports findings first and asks for confirmation before changing anything. `/checkup` is its alias.
Run a checkup from any session:
Claude Code
```python
> /doctor
```
[All commands](commands.md#all-commands)
Other wins
Auto mode now blocks tampering with session transcript files, and asks before running `rm -rf` on a variable it can’t resolve from context
`/cd` now suggests directory paths as you type, matching `/add-dir`
`/commit-push-pr` auto-allows `git push` to the repo’s configured push remote in addition to `origin`
Gateway: `/login` now supports Anthropic-operated public gateway endpoints
`EnterWorktree` asks for confirmation before entering a git worktree outside the project’s `.claude/worktrees/` directory
Background agents upgrade to a new version in the background right after a Claude Code update, instead of paying a slow stale-session upgrade when you attach
Agent view rows now show a colored state word and a classifier-written headline instead of raw tool call text, and sessions that edit, merge, comment on, or push to an existing PR link it in `claude agents`
Auto-update binary downloads now stream to disk instead of buffering in memory, cutting the updater’s peak memory usage by roughly 400 MB
Background task notifications now explicitly state that no human input has occurred, preventing fabricated in-transcript approvals from being acted on
Improved `/code-review` findings quality on Opus 4.8 across all effort levels
[Full changelog for v2.1.202–v2.1.206 →](changelog.md#2-1-202)
---
## Week 29 · July 13–17, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w29
Path: 02-Claude-Code-CLI/whats-new-2026-w29.md
# Week 29 · July 13–17, 2026
Copy pageCopy page
Pull live data into published artifacts through MCP connectors, and use Claude Code with a screen reader in the new screen reader mode.
Copy pageCopy page
Releases [v2.1.207 → v2.1.212](changelog.md#2-1-207)2 features · July 13–17
Artifacts call your MCP connectorsweb
A published artifact can now call MCP connectors each time someone views it, so a dashboard shows live data and can take actions on demand rather than a snapshot from the session that built it. Each call runs through the viewing account’s own connections, and viewers approve access before the page’s first connector call. This week also adds public sharing links, editor roles for shared editing on Team and Enterprise plans, and artifacts created from Claude Tag sessions.
Name the connector and the data you want in your prompt:
Claude Code
```python
Build a dashboard artifact of open pull requests that pulls the live list through my GitHub connector when the page loads.
```
[Pull live data with MCP connectors](artifacts.md#pull-live-data-with-mcp-connectors)
Screen reader modeCLI
Screen reader mode replaces the visual terminal interface with plain, linear text: instead of boxes, spinners, and in-place redraws, Claude Code prints labeled lines that a screen reader such as VoiceOver or NVDA reads in order, so you can approve permissions and review output end to end. Turn it on per session with a flag, per shell with the `CLAUDE_AX_SCREEN_READER` environment variable, or everywhere with the `axScreenReader` setting.
Start a session in screen reader mode:
terminal
```python
claude --ax-screen-reader
```
[Turn on screen reader mode](accessibility.md#turn-on-screen-reader-mode)
Other wins
`/fork` now copies your conversation into a new background session with its own row in `claude agents` while you keep working; the in-session forked subagent it used to launch is now `/subtask`
[Auto mode](permission-modes.md#enable-auto-mode-on-bedrock-agent-platform-or-foundry) no longer needs the `CLAUDE_CODE_ENABLE_AUTO_MODE` opt-in on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry; administrators can turn it off with `disableAutoMode`
MCP tool calls that run longer than two minutes now move to the background automatically so the session stays usable; tune or disable the threshold with `CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`
New `claude auto-mode reset` restores the default auto-mode configuration, and `--yes` skips the confirmation prompt
New [corporate launcher](../13-Enterprise-Admin/corporate-launcher.md) support: `CLAUDE_CODE_PROCESS_WRAPPER` or the `processWrapper` setting runs the processes Claude Code starts from its own binary, such as the background service and agent view sessions, through a required wrapper executable
`vimInsertModeRemaps` setting maps two-key insert-mode sequences such as `jj` to Escape in vim mode
`--forward-subagent-text` and `CLAUDE_CODE_FORWARD_SUBAGENT_TEXT` include subagent text and thinking blocks in [stream-json output](headless.md)
Session-wide caps stop runaway loops: WebSearch calls and subagent spawns each default to 200, tunable with `CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION` and `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION`
”Always allow” permission rules save at the repository root, so approvals granted in a git worktree persist across sessions and worktrees
Amazon Bedrock, Google Cloud’s Agent Platform, and Claude Platform on AWS now default to Claude Opus 4.8
The collapsed tool summary line shows a live elapsed-time counter, so long-running tool calls visibly tick instead of looking stuck
[Full changelog for v2.1.207–v2.1.212 →](changelog.md#2-1-207)
---
## Week 30 · July 20–24, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w30
Path: 02-Claude-Code-CLI/whats-new-2026-w30.md
# Week 30 · July 20–24, 2026
Copy pageCopy page
Opus 5 becomes the default Opus model, Claude Code Desktop adds an iOS Simulator pane, and the Claude Security plugin scans your code for vulnerabilities.
Copy pageCopy page
Releases [v2.1.214 → v2.1.219](changelog.md#2-1-214)3 features · July 20–24
Claude Opus 5new model
Claude Opus 5 is the new default Opus model in Claude Code. It’s the default on Max, Team Premium, Enterprise pay-as-you-go, and the Anthropic API, and on Claude Platform on AWS, Amazon Bedrock, and Google Cloud’s Agent Platform. On the Anthropic API and on Max, Team, and Enterprise plans, Opus 5 runs with a [1M-token context window](model-config.md#extended-context); on Amazon Bedrock and Google Cloud’s Agent Platform, select the 1M model variant. Fast mode moves to Opus 5 at \$10/\$50 per MTok. Requires v2.1.219 or later.
Switch to Opus 5 by name, or pick it from the model picker:
Claude Code
```python
> /model claude-opus-5
```
[Model configuration](model-config.md#available-models)
iOS Simulator in Claude Code DesktopDesktop
Claude Code Desktop on macOS gets an iOS Simulator pane, in public beta on Pro, Max, and Team plans. When Claude builds, launches, or checks your app in a simulator, the pane opens next to the conversation and streams the device screen live, so you can watch Claude tap through the app to verify its changes or drive the device yourself. Requires Xcode with the iOS platform installed, and Claude Desktop v1.24012.0 or later.
Ask Claude to run or test your app, and the pane opens when the app launches:
Claude Code
```python
> Build the app and run it in the simulator to check the onboarding flow.
```
[Test iOS apps in the simulator](../16-Mobile-Desktop/desktop-ios-simulator.md#run-your-app-in-the-simulator)
Claude Security pluginplugin
The Claude Security plugin runs a multi-agent vulnerability scan of your codebase inside a Claude Code session: agents map your architecture, build a threat model, hunt for vulnerabilities, and independently review every finding before writing the report to a `CLAUDE-SECURITY-<timestamp>/` directory. Scan a whole repository or only a branch’s diff, a pull request, or a single commit, then turn the findings you choose into reviewed patches that you apply yourself.
Install the plugin from the official Anthropic marketplace, run `/reload-plugins`, then start a scan with `/claude-security`:
Claude Code
```python
> /plugin install claude-security@claude-plugins-official
```
[Scan and fix your codebase](claude-security.md#scan-and-fix-your-codebase)
Other wins
[`/code-review`](code-review.md#review-a-diff-locally) now runs as a background subagent with its own context window, so review work stays out of your conversation and the findings arrive when it completes
`/verify`, `/code-review`, and `/deep-research` run only when you invoke them; Claude no longer launches them on its own
[Emoji shortcodes](interactive-mode.md#emoji-shortcodes) autocomplete in the prompt input: type `:heart:` to insert an emoji, or two or more characters after `:` for suggestions; turn it off with `emojiCompletionEnabled`
Skills with `context: fork` [run in the background](../08-Plugins-Skills/skills.md#run-skills-in-a-subagent) by default, and `background: false` in the skill’s frontmatter waits for the result in the same turn
A session runs up to 20 subagents concurrently by default; change the [limit](../09-Agents-Patterns/sub-agents.md#concurrent-subagent-limit) with `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`
`--max-budget-usd` now enforces the cap on subagents: once spend reaches it, Claude can’t start more and running background subagents stop
New [`sandbox.filesystem.disabled`](sandboxing.md#disable-filesystem-isolation) setting skips filesystem isolation while keeping network egress control
In auto mode, the checks for dangerous `rm` commands, background jobs, and suspicious Windows paths no longer open permission dialogs; the auto-mode classifier adjudicates them instead
Bash permission checks fail closed on more shell forms, including file-descriptor redirects, Zsh variable subscripts in `[[ ]]` comparisons, `help` and `man` invocations that could run unsafe options, and commands over 10,000 characters
[Fast mode](fast-mode.md) no longer supports Opus 4.7: `/fast` now applies to Opus 5 and Opus 4.8
Long-running tool calls emit a periodic progress heartbeat instead of going silent
[Full changelog for v2.1.214–v2.1.219 →](changelog.md#2-1-214)
---
## Week 32 · August 3–7, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w32
Path: 02-Claude-Code-CLI/whats-new-2026-w32.md
# Week 32 · August 3–7, 2026
Copy pageCopy page
Claude Code sessions message each other, self-hosted environments run cloud sessions on your infrastructure, and auto mode becomes the default permission mode.
Copy pageCopy page
Releases [v2.1.220 → v2.1.224](changelog.md#2-1-220)3 features · August 3–7
Cross-session messagingv2.1.224
Your Claude Code sessions can now message each other. Claude discovers your other sessions with the `ListAgents` tool and sends with `SendMessage`, either when you ask it to or on its own, such as after a change in one session affects what another is working on. A message is text Claude writes for the other session, never your conversation history or files. Available on macOS and Linux. Requires v2.1.224 or later.
With two sessions open on the same machine, ask one of them to pass something along:
Claude Code
```python
Tell the session working on the payments API that users.name is now users.display_name
```
The other session shows a `Message from` row once Claude has read the message; press `Ctrl+O` to expand it. To see which sessions Claude can reach, run `/list-agents`.
[Message another session](cross-session-messaging.md#message-another-session)
Self-hosted environmentsv2.1.224
Self-hosted environments run Claude Code cloud sessions on your organization’s own infrastructure, in public beta on Team and Enterprise plans. Run `claude self-hosted-runner` on your machines or containers to turn them into runners. When someone picks your environment while starting a session from claude.ai, the mobile or desktop apps, or `claude --cloud`, that session runs inside your network, with access to your internal services. An Owner turns on **Allow self-hosted environments** in [admin settings](https://claude.ai/admin-settings/cloud-environments) first.
Signed in as an Owner, run the guided setup, which walks you through creating the environment and starts a runner:
terminal
```python
claude self-hosted-runner setup
```
The environment shows **Healthy** in admin settings once the runner registers.
[Self-hosted environments quickstart](../13-Enterprise-Admin/self-hosted-environments-quickstart.md#set-up-an-environment-and-runner)
Auto mode becomes the defaultCLI
Starting August 14, auto mode is the default permission mode for new sessions on Pro, Max, and Team plans. If you set a default mode yourself, it stays in place unless you accept the one-time switch prompt, and a default your organization manages doesn’t change. You can still switch modes at any time. Already in effect on those plans: the classifier calls auto mode makes no longer count toward your usage limits.
To start every session in auto mode before the switch, set it as your default in your user settings:
~/.claude/settings.json
```python
{
"permissions": {
"defaultMode": "auto"
}
}
```
New sessions then show `auto mode on` in the status bar.
[Auto mode requirements and controls](permission-modes.md#eliminate-prompts-with-auto-mode)
Other wins
The VS Code extension gets [Focus view](../03-IDE-Integrations/vs-code.md#extension-settings), which hides tool activity behind one expandable row per turn; toggle it from the command menu or with `Ctrl+Alt+F` (`Ctrl+Option+F` on Mac)
Sandbox credential files accept [`mode: “mask”`](sandboxing.md#mask-credential-files) on Linux and WSL2, so sandboxed commands read a sentinel copy while the sandbox proxy substitutes the real value on egress; credential masking also gains `extract`, JWT-aware `decode`, and AWS SigV4 re-signing options
Marketplaces can distribute a plugin as a [zip archive](../08-Plugins-Skills/plugins-marketplace-reference.md#archive-plugin-source) with the new `archive` source, downloaded over HTTPS with an optional SHA-256 pin, so installs work without git or npm
`/review` is now an alias of [`/code-review`](code-review.md#review-a-diff-locally), and `/code-review` with no effort level reuses the level you typed last
A session you copy with [`/fork`](../09-Agents-Patterns/agent-view.md#copy-the-session-with-%2Ffork) now makes its code changes in a worktree of its own instead of the original session’s checkout
Plugins you install from [`/plugin`](../08-Plugins-Skills/discover-plugins.md#install-a-plugin) activate in the current session when it’s safe to do so; the install summary reports `Plugin is now active.` or tells you to run `/reload-plugins`
[Background sessions](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated) that changed code in a worktree now commit and push before finishing, open a draft pull request only when the task calls for one, and follow the git instructions in your `CLAUDE.md`
The 200-subagent-per-session cap is removed, so long-running sessions no longer refuse new subagents; the [concurrency](../09-Agents-Patterns/sub-agents.md#concurrent-subagent-limit) and depth limits still apply
A repository’s checked-in settings can no longer turn on [Remote Control auto-connect](remote-control.md#enable-remote-control-for-all-sessions); set `remoteControlAtStartup` in your user or managed settings instead, and project and local settings can only turn it off
[Worktree isolation](worktrees.md#how-claude-code-enforces-isolation) now blocks not only file edits but also Bash commands and git redirects that reach the main checkout, in every session type and in the session’s subagents
A Bash command can no longer hide part of itself from permission checks, and tab or invisible-Unicode padding no longer hides part of a command from the approval dialog
PreToolUse auto-allow hooks no longer bypass tool restrictions in Claude Code’s internal side tasks such as summaries and compaction
The [Ultraplan](ultraplan.md) research preview is removed, including the `/ultraplan` command and the `ultraplan` keyword; use plan mode or Claude Code on the web instead
[Full changelog for v2.1.220–v2.1.224 →](changelog.md#2-1-220)
---
## Week 33 · August 10–14, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w33
Path: 02-Claude-Code-CLI/whats-new-2026-w33.md
# Week 33 · August 10–14, 2026
Copy pageCopy page
Claude Code Desktop auto-continues after a usage limit resets, fork mode turns on by default, and GitLab merge requests and marketplaces join GitHub.
Copy pageCopy page
Releases [v2.1.225 → v2.1.233](changelog.md#2-1-225)3 features · August 10–14
Auto-continue after a usage limit on DesktopDesktop
When you hit your session limit in the Code tab of Claude Code Desktop, the limit card now offers an **Auto-continue when limits reset** checkbox. Check it, and the Desktop app retries the interrupted turn after the reset. The card shows the retry time. The weekly-limit card doesn’t offer it.
The next time a session-limit card appears, check **Auto-continue when limits reset** and leave the session open. The card shows `Auto-resuming at` followed by the reset time, and the turn picks up on its own once the limit resets.
[What to do when you hit a usage limit](errors.md#youve-hit-your-session-limit)
Fork mode on by defaultv2.1.232
Fork mode is now on by default in interactive sessions. Claude can request the `fork` subagent type, which inherits the full conversation and prompt cache instead of starting fresh, so you don’t have to re-explain the context for a side task. Subagents Claude spawns in interactive sessions, apart from the ones an agent-team teammate spawns, also run in the background by default.
Start a fork yourself with a task that needs everything you’ve discussed so far:
Claude Code
```python
> /subtask draft unit tests for the parser changes so far
```
The fork appears in the panel below your prompt and its result arrives in your conversation when it finishes. To turn fork mode off, set `CLAUDE_CODE_FORK_SUBAGENT=0`.
[Turn fork mode on or off](../09-Agents-Patterns/sub-agents.md#turn-fork-mode-on-or-off)
GitLab merge requests and marketplacesv2.1.232
Plugin marketplaces clone bare `gitlab.com` URLs, including nested subgroups. On v2.1.233 or later, pass a GitLab merge request URL to `--worktree` to branch from it, and the `claude agents` view labels sessions linked to a merge request as `!N`. Claude Code also redacts GitLab token families such as `glpat-` and `glrt-`, and protects the `glab` CLI’s config store the same way it protects `gh`.
Start a session in a worktree branched from a merge request:
terminal
```python
claude --worktree https://gitlab.com/group/project/-/merge_requests/42
```
When `origin` is on gitlab.com, Claude Code fetches `merge-requests/42/head` and opens the session on that branch in its own worktree.
[Branch a worktree from a pull or merge request](worktrees.md#branch-from-a-pull-request)
Other wins
Type `@` in the prompt to [mention another Claude session](cross-session-messaging.md#message-another-session) by name, and Claude messages it directly with `SendMessage`; a bare name that matches exactly one live session now delivers without a confirmation step
Interactive sessions on one machine keep [unique names](cross-session-messaging.md#see-which-sessions-claude-can-reach): if you start or rename a session with a name another live session already uses, Claude Code gives yours a `name-word-word` variant and tells you
Plugin marketplaces accept [`command` sources](../08-Plugins-Skills/plugins-marketplace-reference.md#command-plugin-source): a local command prints the plugin directory, which Claude Code re-resolves each session and applies without a restart
On Linux and WSL, set [`CLAUDE_CODE_TOOL_MEMORY_LIMIT`](tools-reference.md#memory-limit-on-linux-and-wsl) to a size such as `4G` to cap the memory Bash and PowerShell tool commands can use
The task-tracking tools, such as `TaskCreate`, `TaskUpdate`, and `TodoWrite`, are [no longer available on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, and later models in those families](tools-reference.md#task-tool-availability); set `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` to re-enable them
[`/code-review`](code-review.md#review-a-diff-locally) at high, xhigh, and max effort now runs in a background agent like the other levels
[`/plugin install plugin@marketplace`](../08-Plugins-Skills/discover-plugins.md#install-a-plugin) refreshes the marketplace first, so newly published plugins install without a manual marketplace update
Settings accept [`additionalMarketplaces` and `allowedMarketplaces`](settings-reference.md#marketplace-key-aliases) as aliases for `extraKnownMarketplaces` and `strictKnownMarketplaces`
On newer models, Claude can [overwrite an existing file with the Write tool](tools-reference.md#write-tool-behavior) without reading it first this session, matching the Edit tool’s rules; older models require the read
The VS Code extension can [organize the sessions list into groups](../03-IDE-Integrations/vs-code.md#organize-sessions-into-groups): right-click to create, rename, or delete a group, and Cmd/Ctrl- or Shift-click to move several sessions at once
If your organization routes Claude Code through a [Claude apps gateway with spend limits](../13-Enterprise-Admin/claude-apps-gateway-spend-limits.md), Claude Code shows the limit period, its reset time, and the operator’s message when you reach the limit
[Full changelog for v2.1.225–v2.1.233 →](changelog.md#2-1-225)
---
## Week 34 · August 17–21, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w34
Path: 02-Claude-Code-CLI/whats-new-2026-w34.md
# Week 34 · August 17–21, 2026
Copy pageCopy page
Draft editable UI artboards with the /design skill, set the Concise output style, and start a Claude Code session on your machine from your phone.
Copy pageCopy page
Releases [v2.1.234 → v2.1.239](changelog.md#2-1-234)3 features · August 17–21
/designresearch preview
The `/design` skill brings Claude Design’s artboard workflow into the CLI and Claude Code Desktop, built on artifacts. Run it with a brief and Claude publishes a canvas of editable artboards for your UI. Pick one, tweak it, then have Claude implement it. Available on Pro, Max, Team, and Enterprise. Requires v2.1.234 or later.
Describe what you want designed and let Claude draft the options:
Claude Code
```python
> /design redesign the composer based on what people actually use it for
```
Claude prints a link to the published canvas. Open it, pick an artboard, and tell Claude which option to implement.
[Where artifacts are available](artifacts.md#availability)
Concise output stylev2.1.237
Concise is a new built-in output style. Claude leads with the result and skips preamble and narration, while doing the work as thoroughly as in the Default style. When you ask for an explanation or more detail, Claude answers in full. Error reports, security warnings, and confirmations for destructive actions keep their complete content.
Turn it on under **Output style** in `/config`, or set it in your settings file:
~/.claude/settings.json
```python
{
"outputStyle": "Concise"
}
```
Run `/clear` or start a new session, and Claude’s replies lead with the result.
[Built-in output styles](output-styles.md#built-in-output-styles)
Start a session on your machine from your phonemobile
Any machine running `claude remote-control` now shows up as a device card at the top of the Code tab in the Claude app. Remote Control is also out of research preview.
Start Remote Control on the machine you want to reach, then open the Code tab on your phone:
terminal
```python
claude remote-control
```
Your machine appears as a device card at the top of the Code tab. Tap it to pick a directory and start a session there.
[Start a Remote Control session](remote-control.md#start-a-remote-control-session)
Other wins
Claude Code now continues your session automatically when a claude.ai usage limit resets; turn it off from the **Continue automatically at usage limit** row in `/config`
The optional [`spellcheck` setting](interactive-mode.md#check-spelling-as-you-type) underlines misspelled words in the prompt input as you type, using your installed `aspell`, `hunspell`, or `ispell`
On a branch with an open GitLab merge request, with the `glab` CLI authenticated through `glab auth login`, the footer shows an [`MR !N` badge](interactive-mode.md#gitlab-merge-requests) colored by whether the merge request is a draft, open, or mergeable
Change the effort level from your phone or claude.ai/code and it [applies to the session on your machine](remote-control.md#what-connected-devices-see); Remote Control sessions hosted by Desktop or VS Code also show connected devices the session’s current permission mode
You can open [`/permissions`](permissions.md#manage-permissions) or run `/add-dir <path>` while Claude is working; permission rule changes apply to the rest of the current turn
When background tasks keep a [`/goal`](goal.md#background-work-defers-evaluation) waiting, Claude checks in on them after 30 minutes instead of waiting indefinitely and keeps checking in, at longer intervals while the session sits idle; set `CLAUDE_CODE_GOAL_CHECKIN_MINUTES=0` to opt out
Your own prompts now render markdown in the transcript, with highlighted code blocks, inline code, and lists, the same way replies do
The new [`ANTHROPIC_DEFAULT_MODEL`](model-config.md#set-a-default-model-for-new-sessions) environment variable sets the model new sessions start on; a `/model` pick still overrides it and persists across restarts
With the `notify_when_idle` input on `SendMessage`, Claude can ask another Claude Code session on the same machine to [send one notice when it next goes idle](cross-session-messaging.md#get-a-notice-when-another-session-goes-idle)
Set [`keybindingFlavor`](interactive-mode.md#make-ctrl-w-delete-back-to-whitespace) to `“readline”` to make `Ctrl+W` in the prompt delete back to the previous whitespace, as Bash does, instead of stopping at punctuation such as `/`
On native Windows, your Claude Code sessions can now [message each other](cross-session-messaging.md#availability) with `SendMessage` and find each other with `ListAgents`, as on macOS and Linux
Self-hosted runners accept `--defer-shutdown-max-min`, which [keeps serving attached sessions](../13-Enterprise-Admin/self-hosted-environments-deploy.md#defer-the-drain-past-the-first-signal) for a set number of minutes after SIGTERM
Self-hosted runners accept `--proxy-authorization-command` or `--proxy-authorization-file` to supply a fresh `Proxy-Authorization` header for [egress proxies that require one](../13-Enterprise-Admin/self-hosted-environments-deploy.md#authenticate-to-an-egress-proxy)
[Full changelog for v2.1.234–v2.1.239 →](changelog.md#2-1-234)
---
## Week 35 · August 24–28, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w35
Path: 02-Claude-Code-CLI/whats-new-2026-w35.md
# Week 35 · August 24–28, 2026
Copy pageCopy page
Resume terminal sessions in the Claude Code Desktop app, review feedback reports that Claude drafts for you, and start a session in restricted mode.
Copy pageCopy page
Releases [v2.1.240 → v2.1.250](changelog.md#2-1-240)3 features · August 24–28
Resume terminal sessions in the Desktop appDesktop
Type `/resume` in the Claude Code Desktop prompt box to pick up any session you started from the CLI and continue it in the app with the full conversation and context intact. Search your sessions by title, folder, or branch, and preview where you left off before you resume.
In a Desktop session, run the command to list your terminal sessions:
Claude Code
```python
> /resume
```
Select a session and press `Enter`. The conversation opens in the app where you left off.
[Move between the CLI and Desktop](../16-Mobile-Desktop/desktop.md#coming-from-the-cli)
Claude-drafted feedbackCLI
When a tool keeps failing, Claude can’t help with a request, or you point out a mistake, Claude now drafts a feedback report for you with the `SendFeedback` tool. A card above your prompt shows the draft, and you can review, send, or dismiss it from there. Nothing reaches Anthropic until you send it. Requires v2.1.238 or later.
Run `/feedback` with no argument to open your queue of drafts from every session:
Claude Code
```python
> /feedback
```
Select a draft, then edit, send, or discard it. To turn drafting off, set **Claude-drafted feedback** to `off` in `/config`.
[SendFeedback tool behavior](tools-reference.md#sendfeedback-tool-behavior)
Restricted modev2.1.248
Restricted mode starts Claude Code without the built-in tools that run commands or code. Use it when an evaluation harness drives `claude` on a shared machine. Start it with `--restricted` or set `CLAUDE_CODE_RESTRICTED=1`. Claude Code also removes `WebFetch`, confines the file tools to the working directories, loads only managed settings and `--settings`, and refuses the `bypassPermissions` permission mode.
Run a non-interactive query without the command-running tools:
terminal
```python
claude --restricted -p "review src/ for SQL injection risks"
```
To give Claude one of the removed tools back, list it in `--tools` together with the other built-in tools you want, for example `--tools "Bash,Read,Edit"`. `--tools` is an allowlist, and its `default` preset doesn’t restore the removed tools.
[CLI flags](cli-reference.md#cli-flags)
Other wins
Set the new [`modelPicker`](settings-reference.md#modelpicker) setting to extend or replace the `/model` picker’s built-in list with your own ordered, labeled entries, including Amazon Bedrock or Google Cloud’s Agent Platform model IDs
Set [`promptCacheTtl`](prompt-caching.md#choose-the-ttl-yourself) to `1h` to keep a one-hour prompt cache on the main conversation when you use an API key or a cloud provider; `subagentPromptCacheTtl` sets the TTL for subagents and all other requests outside the main conversation
On Pro, Max, Team, and Enterprise plans, [`/usage`](../17-Billing-Plans/costs.md#plan-usage-breakdown) adds a Loops breakdown: run count, total tokens, tokens per run, and last run for the `/loop` and scheduled tasks that used the most tokens
Organizations on contracted rates can set the [`modelPricing`](../17-Billing-Plans/costs.md#report-spend-at-your-contracted-rates) managed setting so `/usage`, the status line, and OpenTelemetry report cost at those rates instead of list price
`/login` offers **Sign in with your Console account** under the **Anthropic Console account** option, so members of Console organizations that don’t allow API keys can sign in without creating one
Run `/permissions` and open the new [**Auto mode** tab](auto-mode-config.md#edit-rules-from-permissions) to view and edit auto mode classifier rules without opening a settings file
When auto mode is available, Bash permission prompts in the Manual and `acceptEdits` permission modes offer a [**Yes, and switch to auto mode**](permission-modes.md#switch-permission-modes) option; select it to approve the command and switch the session to auto mode
After you [move a session with `/cd`](permissions.md#move-the-session-to-another-directory), the new directory’s project settings, hooks, `.mcp.json` servers, skills, and subagents take effect immediately instead of on the next `--resume`
In non-interactive sessions, including `-p` runs, Agent SDK runs, and cloud sessions, Claude Code [continues a response](errors.md#the-response-above-may-be-incomplete) that a server error, dropped connection, or stall cut off mid-stream, when the partial response contains text and no tool calls
A subagent that stops at its `maxTurns` limit returns its output marked as partial, with a hint that Claude can [continue it with `SendMessage`](../09-Agents-Patterns/sub-agents.md#resume-subagents), instead of appearing finished
On Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry, sessions on the same machine can now [message each other](cross-session-messaging.md#availability), `/loop` can [choose its own interval](scheduled-tasks.md#let-claude-choose-the-interval), and `/model` and `/effort` apply immediately instead of after the turn ends
The native installer and auto-updater download a zstd-compressed build, about 75 MB instead of 340 MB on Linux x64, and native builds load code on demand, using roughly 40 to 70 MB less memory per session
[Full changelog for v2.1.240–v2.1.250 →](changelog.md#2-1-240)
---
## Week 36 · August 31 – September 4, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w36
Path: 02-Claude-Code-CLI/whats-new-2026-w36.md
# Week 36 · August 31 – September 4, 2026
Copy pageCopy page
Switch to Claude Fable 5.1, let computer use run in the background on Desktop, and watch Claude’s edits in a live /diff panel.
Copy pageCopy page
Releases [v2.1.251 → v2.1.261](changelog.md#2-1-251)4 features · August 31 – September 4
Claude Fable 5.1new model
Claude Fable 5.1 is available in Claude Code with a 1M-token context window, and the `fable` alias now selects it. In Claude apps gateway sessions, `fable` still selects Fable 5. If your gateway serves Fable 5.1, run `/model claude-fable-5-1`. Requires v2.1.257 or later.
Switch the current session to Fable 5.1 and save it as your default:
Claude Code
```python
> /model fable
```
On the Anthropic API, the picker lists Fable only once the server reports it available for your organization, but typing `/model fable` checks with the server directly.
[Work with Fable](model-config.md#work-with-fable)
Computer use runs in the background on DesktopDesktop
On macOS, computer use in the Claude Code Desktop app now works in the background: Claude sees and acts in the apps you’ve approved while you keep working. Background computer use is in beta on Pro and Max plans.
[Let Claude use your computer](../16-Mobile-Desktop/desktop.md#let-claude-use-your-computer)
Live diff panel in fullscreen renderingv2.1.260
In fullscreen rendering, `/diff` now opens a panel beside the conversation instead of a viewer you have to close. The panel lists the changed files with their added and removed line counts and refreshes each time Claude edits a file or runs a shell command. Select lines in the panel with the mouse to attach them to your next prompt.
With fullscreen rendering on, inside a git repository, and in a terminal at least 110 columns wide, toggle the panel:
Claude Code
```python
> /diff
```
Run `/diff` again or click the `✕` in its header to close it.
[Diff panel](interactive-mode.md#diff-panel)
Find unused skills with /skill-doctorCLI
`/skill-doctor` shows what each of your skills costs in context and how often it gets used, so you can decide which ones to turn off. Every skill in the [skill listing](../08-Plugins-Skills/skills.md#skill-descriptions-are-cut-short) adds to your context on every turn, whether or not Claude ever uses it. Requires v2.1.252 or later and isn’t available in sessions that skip [feature-flag fetching](env-vars.md#features-that-need-feature-flag-fetching).
Run it in an interactive session to open the report in the `/plugin` manager’s **Stats** tab:
Claude Code
```python
> /skill-doctor
```
In non-interactive mode with `-p`, Claude Code prints the report as text instead.
[Find unused skills](../08-Plugins-Skills/skills.md#find-unused-skills)
Other wins
A [`PreModelSwitch`](../07-Hooks/hooks.md#premodelswitch) hook can block a model switch you request, and a [`PostModelSwitch`](../07-Hooks/hooks.md#postmodelswitch) hook can add context for Claude after the session’s model changes
[`/cost`](../17-Billing-Plans/costs.md#prompt-cache-statistics) adds a `Prompt cache (main)` line: the share of input tokens served from cache, the cache misses, whether the cache is warm, and a likely cause for the last miss when Claude Code can name one. Status line scripts get a matching `prompt_cache` object
Organizations can list HTTP and SSE MCP servers under the [`managedMcpServers`](../06-MCP-Tools/General/managed-mcp.md#provide-servers-through-managed-settings) managed setting to give them to every user, in addition to the servers that users add on their own
`/effort` and the `/model` picker now [save a separate effort level for each model](model-config.md#adjust-effort-level); press `s` instead of `Enter` to apply a level to the current session only
By default, the auto mode classifier [now also blocks](permission-modes.md#what-the-classifier-blocks-by-default) actions such as requesting credentials from the cloud instance-metadata endpoint or connecting to sibling containers that Claude didn’t start
In auto mode, Claude Code asks you before Claude [first reads a file outside your working directories](permission-modes.md#first-read-outside-the-working-directories), with an option to block such reads from then on
Raise [`bashOutputMaxChars`](settings-reference.md#bashoutputmaxchars) and [`taskOutputMaxChars`](settings-reference.md#taskoutputmaxchars), up to 128,000 characters, so Claude receives more of the output from a successful command or background task inline
The prompt’s [word-editing shortcuts follow readline](interactive-mode.md#make-ctrl-w-delete-back-to-whitespace) for everyone, and the `keybindingFlavor` setting no longer has any effect. `Ctrl+W` deletes back to the previous whitespace, and `Alt+B`, `Alt+F`, and `Alt+D` treat punctuation such as `/` and `.` as word breaks
If you set `defaultMode` to `“bypassPermissions”` in a project’s `.claude/settings.json` or `.claude/settings.local.json`, it [no longer takes effect](permission-modes.md#which-mode-a-session-starts-in) and the session starts in Manual mode; set `“bypassPermissions”` in user or managed settings instead, or pass `--permission-mode`
Seat-based Enterprise plans now [default to Opus 5](model-config.md#default-model-setting)
In the VS Code extension, click the model name at the bottom of the prompt box to [open the model picker](../03-IDE-Integrations/vs-code.md#use-the-prompt-box)
In the VS Code extension, select **Output styles** in the command menu’s Customize section to [pick an output style](../03-IDE-Integrations/vs-code.md#use-the-prompt-box), including your custom ones
[Full changelog for v2.1.251–v2.1.261 →](changelog.md#2-1-251)
---
## Week 37 · September 7–11, 2026 - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new/2026-w37
Path: 02-Claude-Code-CLI/whats-new-2026-w37.md
# Week 37 · September 7–11, 2026
Copy pageCopy page
Test your plugins with claude plugin eval and pop Claude Code Desktop panes out into their own windows.
Copy pageCopy page
Releases [v2.1.263 → v2.1.269](changelog.md#2-1-263)2 features · September 7–11
Test plugins with claude plugin evalv2.1.269
`claude plugin eval` runs your plugin against a suite of test cases, scores the results, and by default runs each case again without the plugin so you can see what it contributes. `claude plugin eval init` asks you what a good result looks like, then proposes test cases and the checks that score them, tries the suite once, and writes the files. Every run, and every check that has a second model judge the reply, is a real model call on your account.
From your plugin’s root directory, have Claude draft the suite:
terminal
```python
claude plugin eval init
```
When Claude tells you the suite is ready, exit the session that `claude plugin eval init` opened and run `claude plugin eval .` to score every case. The summary table prints in your terminal, and `report.html` under `evals/results/` has the per-run detail.
[Test plugins with evals](../08-Plugins-Skills/plugin-evals.md)
Pop Desktop panes out into their own windowsDesktop
In the Claude Code Desktop app, you can pop any pane out into its own window. Drag the diff or terminal to a second screen while Claude keeps working in the main window, then dock the pane back when you’re done.
[Arrange your workspace](../16-Mobile-Desktop/desktop.md#arrange-your-workspace)
Other wins
Set [`maxEffortLevel`](settings-reference.md#maxeffortlevel) at the top level or per model under `modelSettings` to cap the effort level on every provider, including Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry; any higher level runs at the cap
Point `--plugin-dir` at a folder of plugins to [load each immediate subfolder that has a manifest](../08-Plugins-Skills/plugins-create.md#load-a-directory-or-archive-for-one-session)
If WebFetch hasn’t finished downloading a page within five minutes, [the fetch fails with a deadline error](tools-reference.md#webfetch-tool-behavior) instead of hanging; set `CLAUDE_CODE_WEBFETCH_DEADLINE_MS` to change the deadline, or to `0` to remove the limit
Pass `--json` to `claude plugin install`, `uninstall`, `update`, `enable`, or `disable` to print the result as [one JSON object on the last line of stdout](../08-Plugins-Skills/plugins-cli-reference.md#plugin-json-result)
When the auto mode classifier blocks an action, the reason Claude receives [usually names the rule that matched](auto-mode-config.md#fix-a-denial-with-an-allow-rule-an-environment-entry-or-a-retry), such as `[Data Exfiltration]`
When you type `/` partway through a prompt, you can now pick from [a list of matching commands](interactive-mode.md#complete-a-command-mid-prompt) instead of a single suggestion. The list opens as you type in fullscreen rendering. A plugin skill also matches on its name without the plugin prefix
In the VS Code extension, click the agent count at the bottom of the prompt box to open the [agent map](../03-IDE-Integrations/vs-code.md#use-the-prompt-box), where you can open a subagent’s read-only transcript or stop it
In the VS Code extension, select **Hooks** or **Permissions** in the command menu’s Customize section to [add or remove hooks and permission rules](../03-IDE-Integrations/vs-code.md#use-the-prompt-box) in your user, project, and local settings
Claude can pick a [browser-tab icon](artifacts.md#create-an-artifact) to match each artifact it publishes
In Claude Code on the web, take back a queued message in a cloud session before Claude reads it: remove it from the queue, or press `Esc` or `Up`, and the text returns to the message box
[Full changelog for v2.1.263–v2.1.269 →](changelog.md#2-1-263)
---
## What's new
Source: https://code.claude.com/docs/en/whats-new/index
Path: 02-Claude-Code-CLI/whats-new-index.md
# What's new
> A weekly digest of notable Claude Code features, with code snippets, demos, and context on why they matter.
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](https://code.claude.com/docs/en/19-Reference/changelog-claude-code-docs-3d68ad8e13.md).
<Update label="Week 15" description="April 6–10, 2026" tags={["v2.1.92–v2.1.101"]}>
**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 →](https://code.claude.com/en/whats-new/2026-w15)
</Update>
<Update label="Week 14" description="March 30 – April 3, 2026" tags={["v2.1.86–v2.1.91"]}>
**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 →](https://code.claude.com/en/whats-new/2026-w14)
</Update>
<Update label="Week 13" description="March 23–27, 2026" tags={["v2.1.83–v2.1.85"]}>
**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 →](https://code.claude.com/en/whats-new/2026-w13)
</Update>
---
## What's new - Claude Code Docs
Source: https://code.claude.com/docs/en/whats-new
Path: 02-Claude-Code-CLI/whats-new.md
# What's new
Copy pageCopy page
A weekly digest of notable Claude Code features, with code snippets, demos, and context on why they matter.
Copy pageCopy page
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](changelog.md).
[](#week-37)
Week 37
v2.1.263–v2.1.269
September 7–11, 2026
**`claude plugin eval`**: run your plugin against a suite of test cases, score the results, and compare against a no-plugin baseline. `claude plugin eval init` drafts the cases and graders for you.Also this week: pop any **Claude Code Desktop pane** out into its own window and dock it back later; the **`maxEffortLevel`** setting caps the effort level on every provider; and a page that **WebFetch** hasn’t finished downloading within five minutes fails instead of hanging.[Read the Week 37 digest →](whats-new-2026-w37.md)
[](#week-36)
Week 36
v2.1.251–v2.1.261
August 31 – September 4, 2026
**Claude Fable 5.1**: available in Claude Code with a 1M-token context window.Also this week: on Pro and Max plans, **computer use in the Desktop app** works in the background on macOS while you keep working; in fullscreen rendering, **`/diff`** opens a live panel beside the conversation that refreshes as Claude edits; and **`/skill-doctor`** shows what each of your skills costs in context and how often it gets used.[Read the Week 36 digest →](whats-new-2026-w36.md)
[](#week-35)
Week 35
v2.1.240–v2.1.250
August 24–28, 2026
**Resume terminal sessions in the Desktop app**: type `/resume` in the Claude Code Desktop prompt box to pick up any session you started from the CLI, with the full conversation and context intact.Also this week: **Claude-drafted feedback** has Claude write up a feedback report when something goes wrong in a session, which you review and send from `/feedback`; **`--restricted`** starts a session without the command-running tools or your user and project settings, for evaluation harnesses on shared machines; and the **`modelPicker`** setting controls which models the `/model` picker lists.[Read the Week 35 digest →](whats-new-2026-w35.md)
[](#week-34)
Week 34
v2.1.234–v2.1.239
August 17–21, 2026
**`/design`**: a research preview that brings Claude Design’s artboard workflow into the CLI and Claude Code Desktop, built on artifacts, so Claude drafts editable artboards for your UI and implements the one you pick.Also this week: the built-in **Concise output style** makes Claude lead with the result and skip preamble; any machine running `claude remote-control` shows up as a **device card** on your phone so you can start a session on it from the Code tab; and **`ANTHROPIC_DEFAULT_MODEL`** sets the model new sessions start on.[Read the Week 34 digest →](whats-new-2026-w34.md)
[](#week-33)
Week 33
v2.1.225–v2.1.233
August 10–14, 2026
**Auto-continue after a usage limit on Desktop**: when you hit your session limit in Claude Code Desktop, check **Auto-continue when limits reset** on the limit card and the app retries the interrupted turn once the limit resets.Also this week: **fork mode** is on by default in interactive sessions, so Claude can delegate a side task to a subagent that inherits the full conversation; **GitLab** merge request URLs work with `--worktree` and the `claude agents` view, and marketplaces clone bare `gitlab.com` URLs; and typing **`@`** in the prompt mentions another Claude session by name.[Read the Week 33 digest →](whats-new-2026-w33.md)
[](#week-32)
Week 32
v2.1.220–v2.1.224
August 3–7, 2026
**Cross-session messaging**: on macOS and Linux, your Claude Code sessions can now message each other, so Claude passes a finding or a decision from one session to another instead of you re-explaining it.Also this week: **self-hosted environments** run Claude Code cloud sessions on infrastructure your organization operates, in public beta on Team and Enterprise plans; **auto mode** becomes the default permission mode for new sessions on Pro, Max, and Team plans starting August 14; and the **VS Code extension** gets Focus view.[Read the Week 32 digest →](whats-new-2026-w32.md)
[](#week-30)
Week 30
v2.1.214–v2.1.219
July 20–24, 2026
**Claude Opus 5**: the new default Opus model in Claude Code, with a 1M-token context window and fast mode at \$10/\$50 per MTok.Also this week: **Claude Code Desktop** opens an iOS Simulator pane in public beta so Claude can run your app and tap through it while you watch; the **Claude Security plugin** runs a multi-agent vulnerability scan of your codebase and turns the findings you pick into patches you apply yourself; and **`/code-review`** runs as a background subagent.[Read the Week 30 digest →](whats-new-2026-w30.md)
[](#week-29)
Week 29
v2.1.207–v2.1.212
July 13–17, 2026
**Artifacts call your MCP connectors**: a published artifact can pull live data and take actions through each viewer’s own MCP connectors when they open the page, and this week also adds public sharing links, editor roles on Team and Enterprise, and artifacts created from Claude Tag sessions.Also this week: **screen reader mode** replaces the visual terminal interface with plain, linear text for screen readers such as VoiceOver and NVDA; **`/fork`** copies your conversation into a new background session while you keep working; and **auto mode** no longer needs an opt-in variable on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry.[Read the Week 29 digest →](whats-new-2026-w29.md)
[](#week-28)
Week 28
v2.1.202–v2.1.206
July 6–10, 2026
**In-app browser on Desktop**: Claude Code on desktop gets a built-in browser, so Claude can pull up docs, designs, or any other site and interact with pages the same way it does with your local dev server previews.Also this week: **`/doctor`** is a full setup checkup that diagnoses issues and can fix them, with `/checkup` as its alias; **auto mode** blocks transcript tampering and asks before `rm -rf` on unresolved variables; and **agent view rows** show a colored state word and a classifier-written headline.[Read the Week 28 digest →](whats-new-2026-w28.md)
[](#week-27)
Week 27
v2.1.195–v2.1.201
June 29 – July 3, 2026
**Claude Sonnet 5**: the new default model for Pro, Team Standard, and Enterprise subscription seats, with top-tier coding and tool use at Sonnet pricing, a native 1M-token context window, and adaptive thinking on by default.Also this week: **Claude in Chrome** is generally available on all direct Anthropic plans; **subagents run in the background by default** so Claude keeps working while they run; **Claude Desktop on Linux** lands in beta on Ubuntu and Debian; and **`/radio`** tunes into Claude FM lo-fi radio.[Read the Week 27 digest →](whats-new-2026-w27.md)
[](#week-26)
Week 26
v2.1.185–v2.1.193
June 22–26, 2026
**`claude mcp login`**: authenticate a configured MCP server from your shell instead of the interactive `/mcp` menu, and clear its stored credentials later with `claude mcp logout`.Also this week: **shell mode responds to command output** (`! npm test` gets an explanation without a second prompt); **`/rewind`** can resume a conversation from before `/clear` was run; and **background subagents** now surface permission prompts in the main session instead of auto-denying.[Read the Week 26 digest →](whats-new-2026-w26.md)
[](#week-25)
Week 25
v2.1.178–v2.1.183
June 15–19, 2026
**Artifacts**: turn a session’s output into a live, shareable page on claude.ai that updates in place as the session works, now in beta on Team and Enterprise plans.Also this week: **deny and ask rules match tool parameters** with `Tool(param:value)`, for example `Agent(model:opus)`; **`/config key=value`** sets any setting from the prompt, in `-p` mode, and from Remote Control; and **auto mode blocks destructive git commands** when you didn’t ask to discard local work.[Read the Week 25 digest →](whats-new-2026-w25.md)
[](#week-24)
Week 24
v2.1.166–v2.1.176
June 8–12, 2026
**`/cd`**: move the current session to a new working directory mid-conversation without rebuilding the prompt cache.Also this week: **sub-agents can spawn their own sub-agents** (background chains are capped at five levels deep); **`--safe-mode`** starts Claude Code with all customizations disabled for troubleshooting; and **`fallbackModel`** configures up to three fallback models tried in order.[Read the Week 24 digest →](whats-new-2026-w24.md)
[](#week-23)
Week 23
v2.1.158–v2.1.165
June 1–5, 2026
**Auto mode on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry**: auto mode is now available on third-party providers for Opus 4.7 and Opus 4.8, replacing permission prompts with background safety checks.Also this week: **safer automatic edits** prompt before writing files that can run code in `acceptEdits` mode; **`/plugin list`** prints your installed plugins inline; and **version requirements** let managed deployments require an approved Claude Code version range.[Read the Week 23 digest →](whats-new-2026-w23.md)
[](#week-22)
Week 22
v2.1.150–v2.1.157
May 25–29, 2026
**Claude Opus 4.8**: the new default model for Max, Team Premium, Enterprise pay-as-you-go, and Anthropic API accounts, with high effort by default and `/effort xhigh` for the hardest tasks.Also this week: **dynamic workflows** orchestrate dozens to hundreds of subagents from a script Claude writes; the **security-guidance plugin** reviews Claude’s changes for vulnerabilities as it works; and **fast mode** runs on Opus 4.8 at \$10/\$50 per MTok.[Read the Week 22 digest →](whats-new-2026-w22.md)
[](#week-21)
Week 21
v2.1.143–v2.1.149
May 18–22, 2026
**Auto mode on the Pro plan**: auto mode now runs on Pro accounts and supports Sonnet 4.6 alongside Opus, replacing permission prompts with background safety checks.Also this week: **`/usage`** breaks down what drives your plan limits by skill, subagent, plugin, and MCP server; the new **`/code-review`** command reports correctness bugs; and **background sessions** appear in `/resume` and stay alive when pinned.[Read the Week 21 digest →](whats-new-2026-w21.md)
[](#week-20)
Week 20
v2.1.139–v2.1.142
May 11–15, 2026
**Agent view**: `claude agents` opens one screen for every Claude Code session, showing what’s running, what’s blocked on you, and what’s done.Also this week: **`/goal`** keeps Claude working across turns until a completion condition holds; **fast mode** now runs on Opus 4.7 by default; and the **Rewind menu** can compress earlier context with “Summarize up to here”.[Read the Week 20 digest →](whats-new-2026-w20.md)
[](#week-19)
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 →](whats-new-2026-w19.md)
[](#week-18)
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 →](whats-new-2026-w18.md)
[](#week-17)
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 →](whats-new-2026-w17.md)
[](#week-16)
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 →](whats-new-2026-w16.md)
[](#week-15)
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 →](whats-new-2026-w15.md)
[](#week-14)
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 →](whats-new-2026-w14.md)
[](#week-13)
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 →](whats-new-2026-w13.md)
---
## Why was my card declined? | Claude Help Center
Source: https://support.claude.com/en/articles/9402418-why-was-my-card-declined
Path: 02-Claude-Code-CLI/why-was-my-card-declined.md
# Why was my card declined?
July 10, 2026
There are several reasons your card may have been declined when trying to process this transaction. While we don't receive detailed information from issuing banks regarding the specific reasons for a decline, there are several common factors that may contribute to this issue. A few ideas to try are:
## Ensure supported billing location
Please review our list of **[supported billing locations](https://www.anthropic.com/supported-countries)** to confirm that your payment method's billing address and origin country are eligible for processing. Ensure that your payment method’s billing address matches the origin country.
## Verify billing address
Ensure that the billing address associated with your payment method matches the address on file with your bank. Even minor discrepancies, such as a missing accent mark or a misspelled street name, can trigger a decline.
## Complete 3DS verification (if applicable)
If your transaction requires 3D Secure (3DS) verification, ensure that you have successfully completed the authentication process. This may involve entering a one-time password sent to your registered mobile device or confirming the transaction through your bank's app or website.
## Use an accepted payment method
We accept credit cards and debit cards for all purchases. For **[self-serve Enterprise plans](../17-Billing-Plans/what-is-the-enterprise-plan.md#h_634d59a83f)** and API accounts on monthly invoicing, we also accept to ACH bank transfers.
Please note that we do not accept third-party payment processors such as PayPal or Venmo. If you attempt to use an unsupported payment method, your transaction will likely be declined.
## Confirm sufficient funds
Verify that your payment method has sufficient funds to cover the total amount of your purchase. If you're unsure about your account balance, we recommend contacting your bank directly for assistance.
## Retry the payment
If you have access to another payment method, consider using it to complete your purchase. It may be worthwhile to attempt the transaction again at a later time as temporary technical issues or network disruptions can sometimes cause declines, which may resolve on their own.
## Contact your bank
Reach out to your issuing bank directly to inquire about the reason for the decline. They may be able to provide additional information or insights that can help you resolve the issue.
If you've tried the troubleshooting steps above and are still encountering difficulties, contact **[our support team](https://support.claude.com/en/articles/9015913-how-to-get-support)** for further assistance.
---
## Orchestrate subagents at scale with dynamic workflows - Claude Code Docs
Source: https://code.claude.com/docs/en/workflows
Path: 02-Claude-Code-CLI/workflows.md
## On this page
- [When to use a workflow](#when-to-use-a-workflow)
- [Run a bundled workflow](#run-a-bundled-workflow)
- [Bundled workflows](#bundled-workflows)
- [Watch the run](#watch-the-run)
- [Have Claude write a workflow](#have-claude-write-a-workflow)
- [Ask for a workflow in your prompt](#ask-for-a-workflow-in-your-prompt)
- [Dismiss or turn off the keyword](#dismiss-or-turn-off-the-keyword)
- [Where the keyword works](#where-the-keyword-works)
- [Let Claude decide with ultracode](#let-claude-decide-with-ultracode)
- [Approve the plan before it runs](#approve-the-plan-before-it-runs)
- [Save the workflow for reuse](#save-the-workflow-for-reuse)
- [Distribute a workflow in a plugin](#distribute-a-workflow-in-a-plugin)
- [Pass input to a saved workflow](#pass-input-to-a-saved-workflow)
- [Example workflow prompts](#example-workflow-prompts)
- [Audit many files for the same issue](#audit-many-files-for-the-same-issue)
- [Keep fixing until a check passes](#keep-fixing-until-a-check-passes)
- [Migrate many files in parallel](#migrate-many-files-in-parallel)
- [Review every changed file and write one summary](#review-every-changed-file-and-write-one-summary)
- [Research a topic across many sources](#research-a-topic-across-many-sources)
- [Find issues until the list stops growing](#find-issues-until-the-list-stops-growing)
- [What the saved script looks like](#what-the-saved-script-looks-like)
- [Edit a saved script](#edit-a-saved-script)
- [How a workflow runs](#how-a-workflow-runs)
- [Prompt caching in a fan-out](#prompt-caching-in-a-fan-out)
- [Behavior and limits](#behavior-and-limits)
- [Manage runs](#manage-runs)
- [Resume after a pause](#resume-after-a-pause)
- [When a run hits your usage limit](#when-a-run-hits-your-usage-limit)
- [Cost](#cost)
- [Set a size guideline](#set-a-size-guideline)
- [Turn workflows off](#turn-workflows-off)
- [Related resources](#related-resources)
Agents and parallel work
# Orchestrate subagents at scale with dynamic workflows
Copy pageCopy page
Dynamic workflows orchestrate many subagents from a script Claude writes and you can rerun. Use them for codebase audits, large migrations, and cross-checked research.
Copy pageCopy page
Dynamic workflows are available on all paid plans, with Anthropic API access, and on Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry. On Pro, turn them on from the Dynamic workflows row in `/config`.
A dynamic workflow is a JavaScript script that orchestrates many [subagents](../09-Agents-Patterns/sub-agents.md) at once. Claude writes the script for the task you describe, and a runtime executes it in the background while your session stays responsive. Reach for a workflow when a task needs more agents than one conversation can coordinate, or when you want the orchestration codified as a script you can read and rerun. Examples include a codebase-wide bug sweep, a 500-file migration, a research question that needs sources cross-checked against each other, and a hard plan worth drafting from several independent angles before you commit to one.
[](#when-to-use-a-workflow)
When to use a workflow
[Subagents](../09-Agents-Patterns/sub-agents.md), [skills](../08-Plugins-Skills/skills.md), [agent teams](../09-Agents-Patterns/agent-teams.md), and workflows can all run a multi-step task. The difference is who holds the plan:
| | Subagents | Skills | Agent teams | Workflows |
|:--------------------------------|:-------------------------------|:-----------------------------|:---------------------------------------|:-------------------------------------|
| What it is | A worker Claude spawns | Instructions Claude follows | A lead agent supervising peer sessions | A script the runtime executes |
| Who decides what runs next | Claude, turn by turn | Claude, following the prompt | The lead agent, turn by turn | The script |
| Where intermediate results live | Claude’s context window | Claude’s context window | A shared task list | Script variables |
| What’s repeatable | The worker definition | The instructions | The team definition | The orchestration itself |
| Scale | A few delegated tasks per turn | Same as subagents | A handful of long-running peers | Dozens to hundreds of agents per run |
| Interruption | Restarts the turn | Restarts the turn | Teammates keep running | Resumable in the same session |
A workflow moves the plan into code. With subagents, skills, and agent teams, Claude is the orchestrator: it decides turn by turn what to spawn or assign next, and every result goes into a context window. A workflow script holds the loop, the branching, and the intermediate results itself, so Claude’s context holds only the final answer. Moving the plan into code also lets a workflow apply a repeatable quality pattern, not just run more agents: it can have independent agents adversarially review each other’s findings before they’re reported, or draft a plan from several angles and weigh them against each other, so you get a more trustworthy result than a single pass.
[](#run-a-bundled-workflow)
Run a bundled workflow
The quickest way to see a workflow in action is to run `/deep-research`, the [built-in workflow](#bundled-workflows) Claude Code includes for investigating a question across many sources. You’ll see agents work through a set of phases in the background while your session stays free, and get one report at the end instead of a turn-by-turn transcript.
1
Run the workflow
Run `/deep-research` with a question you want investigated. It fans out web searches across several angles, fetches and cross-checks the sources it finds, and synthesizes a cited report.
```python
/deep-research What changed in the Node.js permission model between v20 and v22?
```
2
Allow workflows
Claude Code asks whether to allow the workflow. Select **Yes** to continue. The exact prompt depends on your permission mode. See [Approve the plan before it runs](#approve-the-plan-before-it-runs) for the per-mode options.
3
Watch progress
The run starts in the background. Run `/workflows`, use the arrow keys to select the run, and press Enter to open its progress view:
```python
/workflows
```
The view shows each phase with its agent count, token total, and elapsed time. Drill into any phase to see its agents and what each one found. See [Watch the run](#watch-the-run) for the full set of controls.You can also watch from the task panel below the input box: a one-line progress summary appears there while the run is going. Press the down arrow to focus it, then Enter to expand.
4
Read the report
When the run finishes, the report appears in your session. It cites the sources each claim came from, with claims that didn’t survive cross-checking already filtered out.When the verifier agents can’t check a claim, such as after a rate limit or API error, the report lists that claim as unverified instead of counting it as refuted.
To run a workflow for your own task, [have Claude write one](#have-claude-write-a-workflow), and once a run does what you wanted you can [save it](#save-the-workflow-for-reuse) as a command of your own.
[](#bundled-workflows)
Bundled workflows
Claude Code includes `/deep-research` as a built-in workflow:
| Command | What it does |
|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/deep-research <question>` | Fans out web searches on a question across several angles, fetches and cross-checks the sources it finds, votes on each claim, and returns a cited report with claims that didn’t survive cross-checking filtered out. Requires the [WebSearch tool](tools-reference.md#websearch-tool-behavior) to be available |
`/deep-research` runs only when you invoke it. [Workflows you save](#save-the-workflow-for-reuse) yourself become commands the same way and appear in `/` autocomplete alongside the bundled ones.
[](#watch-the-run)
Watch the run
Workflows run in the background, so the session stays responsive while agents work. Run `/workflows` at any time to list running and completed workflows, then select one to open its progress view. To stop a running workflow without opening it, select it in the list and press `x`. The progress view shows each phase with its agent counts, token totals, and elapsed time. The footer lists the key for each action:
| Key | Action |
|:---------------|:----------------------------------------------------------------------------------------------------------------------------|
| `↑` / `↓` | Select a phase or agent |
| `Enter` or `→` | Drill into the selected phase, then into an agent’s detail. In the detail, `Enter` expands or collapses it |
| `Esc` or `←` | Back out one level. In v2.1.203 through v2.1.205, `←` didn’t step back out of a phase or agent; use `Esc` on those versions |
| `j` / `k` | Scroll within the agent detail when it overflows |
| `f` | Filter the agent list in the selected phase by status. Press again to cycle |
| `p` | Pause or resume the run |
| `x` | Stop the selected agent, or stop the whole workflow when focus is on the run |
| `r` | Restart the selected running agent |
| `s` | [Save](#save-the-workflow-for-reuse) the run’s script as a command |
The agent detail lists the agent’s prompt, its recent tool calls, and its result. Each call shows its state, such as still running or failed. When the agent keeps a task list of its own, the detail shows it too, with each task’s status. Press `Enter` to expand the detail. The prompt and result then show in full, and each listed call shows its input and the start of its result.
[](#have-claude-write-a-workflow)
Have Claude write a workflow
You can have Claude write a workflow for your task in two ways:
- [Ask for a workflow](#ask-for-a-workflow-in-your-prompt) in your prompt, either in your own words or by including the keyword `ultracode`, and Claude writes one for the task.
- [Let Claude decide with ultracode](#let-claude-decide-with-ultracode): set `/effort ultracode` and Claude plans a workflow for every substantive task in the session.
You can also run a workflow command that already exists: a [bundled workflow](#bundled-workflows) like `/deep-research`, or one you’ve [saved](#save-the-workflow-for-reuse).
[](#ask-for-a-workflow-in-your-prompt)
Ask for a workflow in your prompt
To run a single task as a workflow without changing the session’s effort level, include the keyword `ultracode` in your prompt. Asking in your own words, for example “use a workflow” or “run a workflow”, also works: Claude treats a direct request as the same opt-in.
```python
ultracode: audit every API endpoint under src/routes/ for missing auth checks
```
Claude Code highlights the keyword in your input and Claude writes a workflow script for the task instead of working through it turn by turn. The keyword only chooses how Claude structures the work: the agents’ tool calls receive the same permission checks and [sandboxing](sandboxing.md) as any other tool call in the session. If the run does what you wanted, you can [save it as a command](#save-the-workflow-for-reuse) afterward. If you already have an orchestrator built another way, such as a folder of subagent prompts or a skill that fans work out, you can point Claude at it and ask for a workflow that does the same thing.
[](#dismiss-or-turn-off-the-keyword)
Dismiss or turn off the keyword
If you didn’t mean to start a workflow, press `Option+W` on macOS or `Alt+W` on Windows and Linux to dismiss the highlight for this prompt, or press backspace while the cursor is right after the highlighted keyword. To stop the keyword from triggering at all, turn off Ultracode keyword trigger in `/config`.
[](#where-the-keyword-works)
Where the keyword works
The keyword is an opt-in only in a prompt you type yourself: at the interactive prompt, in an IDE extension panel, in a [Remote Control](remote-control.md) client, or in an Agent SDK application that stamps your keyboard input’s [`origin`](../05-Agent-SDK/agent-sdk-typescript.md#sdkmessageorigin) as `{ kind: "human" }`. It doesn’t start a workflow when it reaches the session another way:
- a prompt passed with `-p`
- a prompt an Agent SDK application sends without stamping it as human input
- a scheduled task prompt
- a webhook payload or pull request comment relayed into the conversation
Before v2.1.210, the keyword started a workflow from any of these routes too, including a webhook payload or pull request comment relayed into the conversation.
[](#let-claude-decide-with-ultracode)
Let Claude decide with ultracode
Ultracode is a Claude Code setting that turns on automatic workflow orchestration for the session, at whichever [effort level](model-config.md#adjust-effort-level) the session runs at. With it on, Claude plans a workflow for each substantive task instead of waiting for you to ask. Turn it on at the Claude Code prompt:
```python
/effort ultracode
```
To start a session with ultracode already on, launch with `claude --effort ultracode`, which also sets the effort level to `xhigh`. Requires Claude Code v2.1.203 or later. To turn it on from the `/effort` slider, press `Tab` to flip the **Ultracode** toggle, then `Enter` to apply it. [Adjust effort level](model-config.md#adjust-effort-level) lists the routes that turn ultracode on. With ultracode on, Claude decides when a task warrants a workflow. A single request can turn into several workflows in a row: one to understand the code, one to make the change, and one to verify it. This applies to every task in the session, so each request uses more tokens and takes longer than the same request without a workflow. On a subscription plan those tokens draw on your usage limits, so a session with ultracode on reaches a session or weekly limit sooner than the same work with it off. Turning ultracode on already opts you in to large runs, so these checks don’t apply while it’s on:
- The [`Large workflow` warning](#cost) doesn’t appear on a workflow run
- The session’s [concurrent subagent limit](../09-Agents-Patterns/sub-agents.md#concurrent-subagent-limit) isn’t enforced for the subagents Claude spawns with the Agent tool
- In auto permission mode, you aren’t asked to [approve the first workflow launch](#approve-the-plan-before-it-runs)
`/effort ultracode` lasts for the current session; to have every session start with it, set the [`ultracode`](settings-reference.md#ultracode) setting. Turn it off with `/effort ultracode off` when you return to routine work. The `/effort` slider offers the toggle only [when ultracode is available](model-config.md#when-ultracode-is-available).
[](#approve-the-plan-before-it-runs)
Approve the plan before it runs
In the CLI, the per-run prompt shows the planned phases and these options:
- **Yes, run it**: start the run
- **Yes, and don’t ask again for `<name>` in `<path>`**: start, and skip this prompt for this workflow in this project from now on. Claude Code offers this option when you run a bundled, saved, or plugin workflow by name, not for a script Claude wrote for the current task.
- **View raw script**: read the script before deciding
- **No**: cancel
`Ctrl+G` opens the script in your editor. `Tab` lets you adjust the prompt before the run starts. Whether you see this prompt depends on your [permission mode](permission-modes.md):
| Permission mode | When you’re prompted |
|:-----------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Auto | First launch only. Any **Yes** records consent in your user settings, and later launches start without prompting. Skipped entirely when ultracode is on |
| Manual, accept edits | Every run, unless you’ve selected **Yes, and don’t ask again** for that workflow in this project |
| Bypass permissions | Claude Code doesn’t prompt you. The run starts immediately |
| `claude -p`, Agent SDK | Claude Code doesn’t prompt you |
In `claude -p` and the Agent SDK, Claude Code never shows this prompt. It runs the Workflow tool call through the same [permission evaluation](../05-Agent-SDK/agent-sdk-permissions.md#how-permissions-are-evaluated) as the rest of the session, so deny rules, ask rules, and `dontAsk` mode apply to the launch as they apply to every tool call. To let the workflow start in these runs, use one of these:
- **Permission rule**: `Workflow` in your allow rules approves every workflow, and `Workflow(<name>)` approves one saved workflow by name.
- **Auto permission mode**: the [classifier](permission-modes.md#eliminate-prompts-with-auto-mode) reviews the call and can approve it.
- **Bypass permissions mode**: Claude Code approves the call.
- **A `PreToolUse` hook**: a [hook](../07-Hooks/hooks.md#pretooluse) that returns `allow` for the call approves it.
- **Your host**: a [`--permission-prompt-tool`](cli-reference.md#cli-flags) approves it, or, with the Agent SDK, a [`canUseTool`](../05-Agent-SDK/agent-sdk-permissions.md) callback or a [`PermissionRequest` hook](../07-Hooks/hooks.md#permissionrequest) approves it.
In the Desktop app, an approval card shows the workflow name, the phase list, and a token-usage caution, with **Once**, **Always**, and **Deny** actions. The progress view appears in the Background tasks side pane. The subagents the workflow spawns use your [permission rules](settings-reference.md#permission-settings), and Claude Code picks their permission mode by the rules under [which permission mode a subagent runs in](../09-Agents-Patterns/sub-agents.md#permission-modes). To avoid prompts on a long run, add the tools the agents need to your allow rules before starting.
[](#save-the-workflow-for-reuse)
Save the workflow for reuse
When Claude writes a workflow for a task you’ll repeat, you can save that run’s script as a command. A process like a review you run on every branch then runs the same orchestration each time. Run `/workflows`, select the run you want to keep, and press `s`. In the save dialog, Tab toggles between the two save locations:
- `.claude/workflows/` in your project: shared with everyone who clones the repo
- `~/.claude/workflows/` in your home directory: available in every project, visible only to you. If you set [`CLAUDE_CONFIG_DIR`](env-vars.md), this location is the `workflows/` directory under that path.
The save dialog shows the resolved path for the personal location. Press Enter to save. The workflow runs as `/<name>` in future sessions from either location. Claude Code checks the save location for symlinks before writing, and shows an error instead of writing through one. What it checks depends on where you save:
- Project location: Claude Code refuses if `.claude`, `.claude/workflows`, or the target file is a symlink.
- Personal location: Claude Code refuses only if the target file itself is a symlink, so a `~/.claude` directory managed by a dotfiles tool still works.
Before v2.1.216, Claude Code followed the link, which could place the file outside the location you chose. In a monorepo with several `.claude/` directories, you can keep workflows alongside the package they apply to. Saving to the project location writes to the closest `.claude/workflows/` directory that already exists between your working directory and the repository root, or to the repository root if none exists yet. Project workflows also load from every `.claude/workflows/` along that path, and when more than one defines the same name Claude Code runs the one closest to the working directory. If a project workflow and a personal workflow share a name, the project one runs.
[](#distribute-a-workflow-in-a-plugin)
Distribute a workflow in a plugin
To share a workflow across teams or repositories, include it in a [plugin](../08-Plugins-Skills/plugins.md). Place the script in a `workflows/` directory at the plugin root, or point to a different location with the [`workflows` manifest field](../08-Plugins-Skills/plugins-reference.md#fields). Plugin workflows are namespaced by the plugin name. A plugin called `acme-tools` containing a script whose `meta.name` is `release-audit` runs as `/acme-tools:release-audit`.
[](#pass-input-to-a-saved-workflow)
Pass input to a saved workflow
A saved workflow can accept input through the `args` parameter. The script reads it as a global named `args`. Use this to supply a research question, a list of target paths, or a configuration object at invocation time instead of editing the script for each run. The following prompt runs a saved workflow with a list of issue numbers:
```python
Run /triage-issues on issues 1024, 1025, and 1030
```
Claude passes the list as structured data, so the script can call array and object methods on `args` directly without parsing it first. If `args` is omitted, the global is `undefined` inside the script.
[](#example-workflow-prompts)
Example workflow prompts
A workflow fits best when the task is larger than one agent can hold in context, or when the same step needs to run across many items. The prompts below show common shapes. Each one asks Claude to write and run a workflow for that task; you don’t write the script yourself.
[](#audit-many-files-for-the-same-issue)
Audit many files for the same issue
Fan out one agent per file, then collect and verify the findings.
```python
use a workflow to audit every route handler under src/routes/ for missing authentication checks, and adversarially verify each finding before reporting it
```
[](#keep-fixing-until-a-check-passes)
Keep fixing until a check passes
Run a checker, fix what failed, and repeat until it passes or stops making progress.
```python
use a workflow to run npx tsc --noEmit and keep fixing the reported errors until the type check passes or two rounds in a row make no progress
```
[](#migrate-many-files-in-parallel)
Migrate many files in parallel
Discover the files to migrate, transform each one in an isolated copy so edits don’t conflict, and verify each result.
```python
use a workflow to migrate every component under src/components/ from JavaScript to TypeScript, working on each file in its own isolated copy
```
[](#review-every-changed-file-and-write-one-summary)
Review every changed file and write one summary
Run a reviewer per file, then pass all the findings to one agent that ranks and deduplicates them.
```python
use a workflow to review every file changed in this PR for correctness issues, then merge the per-file findings into one ranked summary
```
[](#research-a-topic-across-many-sources)
Research a topic across many sources
Fan out readers across changelogs, issues, and docs, then synthesize. The bundled `/deep-research` workflow does this; you can also describe a narrower version.
```python
use a workflow to research how our three competitors handle rate limiting: read their public docs and recent changelog entries in parallel, then compare the approaches
```
[](#find-issues-until-the-list-stops-growing)
Find issues until the list stops growing
Keep searching in rounds and stop when new rounds turn up nothing new.
```python
use a workflow to find flaky tests in this repo: run the suite repeatedly, record which tests fail intermittently, and stop once two rounds in a row find nothing new
```
[](#what-the-saved-script-looks-like)
What the saved script looks like
When you [save a workflow](#save-the-workflow-for-reuse), the file in `.claude/workflows/` holds a `meta` block followed by a script body that orchestrates subagents. You usually don’t need to edit it, but here is the shape of a small one so you can recognize what Claude generated:
```python
export const meta = {
name: 'audit-routes',
description: 'Audit every route handler for missing auth checks',
}
const found = await agent('List every .ts file under src/routes/.', {
schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})
const audits = await pipeline(found.files, file =>
agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)
return audits.filter(Boolean)
```
The body is plain JavaScript with top-level `await`. `agent()` spawns one subagent, `pipeline()` runs one per item in a list, and `parallel()` runs a set of agent tasks at the same time and waits for all of them. An `agent()` call resolves to `null` if you stop it mid-run or it hits an unrecoverable API error. `pipeline()` keeps each `null` in the results array, which is why the example ends with `.filter(Boolean)` to drop those entries. In [auto mode](permission-modes.md#eliminate-prompts-with-auto-mode), the prompt your script passes to `agent()` doesn’t count as a request from you when the classifier reviews that subagent’s actions, because Claude Code marks it as text the script computed. If you pass a `schema` on an `agent()` call, that subagent returns JSON matching the shape instead of prose. Claude Code checks the schema before starting the subagent: when it can prove the schema contradicts itself, the call fails with an error naming the contradiction, and the subagent never starts. One contradiction it can prove is a `required` key that `additionalProperties: false` rules out. If the subagent’s output still fails validation after five attempts, the call fails with an error that includes the last validation failure. To change the attempt count, set [`MAX_STRUCTURED_OUTPUT_RETRIES`](env-vars.md).
[](#edit-a-saved-script)
Edit a saved script
To change a [workflow you saved](#save-the-workflow-for-reuse), edit its `.js` file or ask Claude to make the change. Before you edit or ask, run the `/workflow-authoring` [bundled skill](../08-Plugins-Skills/skills.md#bundled-skills) to load the script-writing reference Claude works from. The skill requires Claude Code v2.1.248 or later. To run the edited version in the current session, run [`/reload-skills`](commands.md#all-commands) to re-read the workflow directories, then run `/<name>` again. Claude Code applies these rules to each part of the file when it loads and runs the script:
- **`meta` block**: keep `export const meta` as the first statement, and keep it a plain object literal with a `name` and a `description`. If it contains anything other than literal values, such as a variable, a function call, or a spread, Claude Code drops `/<name>` from `/` autocomplete.
- **Body**: besides `agent()`, `pipeline()`, and `parallel()`, you can call `phase()` to group the agents that follow under a title in the progress view, call `log()` to show a message above the phases, and read the [`args`](#pass-input-to-a-saved-workflow) global. If the body has a syntax error, Claude Code reports it when you run the workflow.
- **`phases`**: if you list them in `meta`, give each entry exactly the title you pass to `phase()`. A `phase()` title with no entry gets a progress group of its own.
- **Timestamps and randomness**: Claude Code makes `Date.now()`, `Math.random()`, and a no-argument `new Date()` throw inside the script, so that a [relaunched run](#resume-after-a-pause) repeats the same `agent()` calls. Pass a timestamp in through `args` instead.
You can also edit [the script of a single run](#how-a-workflow-runs) rather than the saved copy. [Resume after a pause](#resume-after-a-pause) covers which agents run again when you relaunch an edited script. For the Workflow tool’s inputs, see its entry in the [Agent SDK reference](../05-Agent-SDK/agent-sdk-typescript.md#workflow).
[](#how-a-workflow-runs)
How a workflow runs
The workflow runtime executes the script in an isolated environment, separate from your conversation. Intermediate results stay in script variables instead of landing in Claude’s context. Every run writes its script to a file under your session’s directory in `~/.claude/projects/`. Claude receives the path when the run starts, so you can ask for it. You can open that file to read the orchestration Claude wrote, diff it against a previous run’s script, or edit it and ask Claude to relaunch from the edited version. Claude can start a workflow only from a script file the session is already allowed to read. To run a script kept outside your working directory, add its directory with [`/add-dir`](permissions.md#working-directories) or a [Read allow rule](permissions.md#read-and-edit) first. The runtime tracks each agent’s result as the run progresses, which is what makes a run [resumable](#resume-after-a-pause) within the same session.
[](#prompt-caching-in-a-fan-out)
Prompt caching in a fan-out
Agents in the same run can read each other’s [prompt cache](prompt-caching.md#subagents-and-the-cache). Two agents that run with the same model, effort level, agent type, tools, output schema, and working directory build the same tools-and-system-prompt prefix, so an agent that starts after a matching sibling’s response has begun reads that sibling’s cache on its first request. A workflow agent’s requests fall outside the main conversation’s [cache TTL bucket](prompt-caching.md#which-ttl-each-request-gets), so its cache holds for five minutes by default, including on a Claude subscription. To keep it for an hour, set [`subagentPromptCacheTtl`](settings-reference.md#subagentpromptcachettl) to `1h`. The API bills 1-hour cache writes at a higher rate. When a fan-out starts several matching agents at once, Claude Code holds all but the first until the first agent’s response begins, then releases the held agents together so their first requests read the shared prefix instead of each processing it uncached. Claude Code caps the hold at [`CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS`](env-vars.md) milliseconds, `5000` by default. Set it to `0` to disable the hold.
[](#behavior-and-limits)
Behavior and limits
The runtime applies the following constraints:
| Constraint | Why |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| No mid-run user input | A run pauses on its own only for agent permission prompts and a [usage-limit wait](#when-a-run-hits-your-usage-limit). For sign-off between stages, run each stage as its own workflow |
| No direct filesystem or shell access from the workflow itself | Agents read, write, and run commands. The script coordinates the agents |
| No module loading: a script that contains `import()` fails before the run starts | The script body is plain JavaScript. Put work that needs a library in an agent’s task |
| Up to 16 concurrent agents by default, fewer when Claude Code has fewer CPUs available, including inside a CPU-limited container. To change the limit, set [`CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS`](env-vars.md#variables) to a value from 1 to 256, which requires Claude Code v2.1.269 or later | Bounds local resource use |
| In a fan-out, agents that share the first agent’s prompt-cache prefix start up to 5 seconds after it by default | All but the first read the [prefix the first agent cached](#prompt-caching-in-a-fan-out) instead of each processing it uncached |
| Up to 4,096 items in a single `parallel()` or `pipeline()` call: the runtime rejects a longer list with an error | A silent cap would drop part of the workload without telling the script |
| 1,000 agents total per run | Prevents runaway loops |
[](#manage-runs)
Manage runs
Once a run starts, you manage it from the `/workflows` view, or by expanding its progress line in the task panel below the input box. When you stop a run, it stays in the task panel while any of its agents’ processes are still running. If you stop it again, Claude Code re-signals those processes.
[](#resume-after-a-pause)
Resume after a pause
Resume a paused run from `/workflows` by selecting it and pressing `p`. For a run you stopped, ask Claude to relaunch the workflow with the same script. If agents from the stopped run haven’t exited yet, Claude Code refuses the relaunch until they have, so a second copy of those agents can’t run alongside them. Claude Code replays the run in the order agents started, and each agent either returns its saved result or runs again:
- **Completed**: returns its saved result. The first agent whose prompt differs from the previous run, because you edited the script or an earlier agent returned something different, runs again, and so does every agent after it, even ones that completed.
- **Still running when you stopped**: starts over. Stopping the whole run doesn’t count any agent as failed.
- **Failed**: runs again, and so does every agent that started after it, even ones that completed. Stopping one agent alone, by selecting it in [`/workflows`](#watch-the-run) and pressing `x`, counts as failing.
That last case means a failure in the middle of a fan-out reruns work that already finished. If a script starts A, B, C, and D in that order and B fails, relaunching returns A from cache and runs B, C, and D again. You can resume a run within the same Claude Code session. What happens to a running workflow when you leave the session depends on how you leave:
- If you [background the session](../09-Agents-Patterns/agent-view.md#what-carries-over-when-you-background), Claude Code replays the run the same way in the background session and continues it.
- If you exit Claude Code while a workflow is running and [agent view is on](../09-Agents-Patterns/agent-view.md#from-inside-a-session), the exit dialog offers `Move to background and exit`, which carries the run over the same way. If you choose `Exit and stop tasks` instead, or the option isn’t offered, the run stops with the session. Claude Code keeps the run’s saved results under that session’s directory in `~/.claude/projects/`, so a session you resume with `claude --resume` can replay them when you ask Claude to relaunch the workflow. In a session you start fresh, Claude has no earlier run to relaunch and starts the workflow over as a new run.
In a [cloud session](claude-code-on-the-web.md), Claude Code also saves the run’s results with the session’s conversation history, which survives when the session’s VM is reclaimed. When you [reopen such a session](claude-code-on-the-web.md#environment-expired) and ask Claude to relaunch the workflow, completed agents still return their saved results. In local and cloud sessions alike, when Claude relaunches an earlier run and Claude Code can’t find that run’s saved results at all, the relaunch fails with a `nothing to resume` error instead of starting the run over on its own. Ask Claude to start the workflow over as a new run.
[](#when-a-run-hits-your-usage-limit)
When a run hits your usage limit
When an agent hits your claude.ai [usage limit](interactive-mode.md#wait-for-a-usage-limit-to-reset), the run pauses rather than failing that agent: the agents that hit the limit wait for the reset, and no new agents start. Shortly after the limit resets, the waiting agents run again and the run continues on its own. Requires Claude Code v2.1.271 or later; on earlier versions, the affected agents fail. While the run waits, its progress line in the task panel and the [`/workflows`](#watch-the-run) header show when the limit resets. The run pauses only when all of these hold; when one doesn’t, the affected agent fails instead:
- The session is interactive and signed in with a claude.ai subscription. A run doesn’t pause in [non-interactive mode](headless.md) with `claude -p` or the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md), in a [background session](../09-Agents-Patterns/agent-view.md), or in a [Remote Control](remote-control.md) or [agent team](../09-Agents-Patterns/agent-teams.md) teammate session.
- [`autoContinueAtUsageLimit`](settings-reference.md#autocontinueatusagelimit) is on, the same setting that lets the session itself [wait for a usage limit to reset](interactive-mode.md#wait-for-a-usage-limit-to-reset). If you turn it off during a wait, the wait ends and the waiting agents fail.
- The limit resets within 24 hours. A weekly limit can reset further out.
- The run hasn’t already waited twice. When it hits the limit a third time, the agent fails.
[](#cost)
Cost
A workflow spawns many agents, so a single run can use meaningfully more tokens than working through the same task in conversation. Runs count toward your plan’s usage and rate limits. To gauge the spend before committing to a large task, run the workflow on a small slice first: one directory instead of the whole repo, or a narrow question instead of a broad one. The `/workflows` view shows each agent’s token usage as the run progresses, and you can stop the run there at any time, usually without losing completed work. [Resume after a pause](#resume-after-a-pause) covers what a stopped run keeps. The runtime’s [agent caps](#behavior-and-limits) limit how many agents a single run can spawn, which bounds the cost of a runaway script. To keep runs to fewer agents, choose the `small` [size guideline](#set-a-size-guideline). Claude Code also flags a run that grows unusually large. When a workflow schedules more than 25 agents, or its projected token total passes 1.5 million, its progress line in the task panel below the input box shows a `Large workflow` warning. The warning points you to [`/workflows`](#watch-the-run), where you can stop the run. The warning is advisory: it doesn’t pause or limit the run. Two settings change when you see it:
- If you choose a [size guideline](#set-a-size-guideline) yourself, its agent count replaces the 25-agent threshold. The built-in default guideline leaves the threshold at 25.
- Sessions with [ultracode](#let-claude-decide-with-ultracode) on don’t show the warning, because turning ultracode on already opts you in to large runs.
Claude Code picks each workflow agent’s model in the same [order it uses for subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model). A model the script names for a stage counts as the per-invocation model in that order. When nothing else assigns one, the agent runs on your session’s model. To control the model cost:
- Check `/model` before a large run if you usually switch to a smaller model for routine work
- Ask Claude to use a smaller model for stages that don’t need the strongest one when you describe the task
When your organization’s [`availableModels` allowlist](model-config.md#restrict-model-selection) blocks a model the script requests for an agent, that agent runs on a substituted model instead, following the same [substitution rules as subagents](../09-Agents-Patterns/sub-agents.md#choose-a-model). The run’s progress view in [`/workflows`](#watch-the-run) shows a warning naming both the requested and substituted models.
[](#set-a-size-guideline)
Set a size guideline
A size guideline tells Claude how many agents to aim for when it writes a dynamic workflow. Claude Code sends the guideline to Claude as advice, not a cap, so a prompt that calls for a different scale still overrides it. Requires Claude Code v2.1.202 or later. Each value maps to an agent count:
| Value | Agent count Claude aims for |
|:---------------|:----------------------------------------------------|
| `unrestricted` | No guideline: Claude sizes the workflow to the task |
| `small` | Fewer than 5 agents |
| `medium` | Fewer than 10 agents |
| `large` | Fewer than 50 agents |
The default is `medium`, or `small` when you’re signed in on a Pro plan with Claude Code v2.1.271 or later. Until you choose a value, the `/config` row marks the value as the default, and the workflow’s `Running in background` line names the size in force. Requires Claude Code v2.1.219 or later; earlier versions default to `unrestricted`. To change the guideline, pick a value for the Dynamic workflow size setting in `/config`, or run `/config workflowSizeGuideline=small`. On v2.1.219 and later, you can also set the [`workflowSizeGuideline` key](settings-reference.md#workflowsizeguideline) in any settings file; that value takes precedence over `/config`, and Claude Code hides the `/config` row while a settings file provides one. Changes take effect on the next prompt. The [runtime agent caps](#behavior-and-limits) still apply regardless of the setting.
[](#turn-workflows-off)
Turn workflows off
Workflows are available in the CLI, the Desktop app, the IDE extensions, [non-interactive mode](headless.md) with `claude -p`, and the [Agent SDK](../05-Agent-SDK/agent-sdk-overview.md). The same disable settings apply on every surface. To turn workflows off for yourself:
- Toggle Dynamic workflows off in `/config`. Persists across sessions.
- Set `"disableWorkflows": true` in `~/.claude/settings.json`. Persists across sessions.
- Set `CLAUDE_CODE_DISABLE_WORKFLOWS=1`. Read at startup, so it applies wherever you set it.
To turn workflows off for your whole organization, set `"disableWorkflows": true` in [managed settings](../13-Enterprise-Admin/server-managed-settings.md), or use the toggle on the [Claude Code admin settings](https://claude.ai/admin-settings/claude-code) page. When workflows are disabled, the bundled workflow commands and the `/workflow-authoring` skill are unavailable, the `ultracode` keyword no longer triggers a run, and the **Ultracode** toggle is removed from `/effort`. A run that was already in progress keeps going. Turning workflows off also makes [ultracode](#let-claude-decide-with-ultracode) unavailable. No managed setting rules out ultracode alone: wherever it’s [available](model-config.md#when-ultracode-is-available), users can turn it on with `/effort ultracode`. An [effort cap](model-config.md#organization-effort-limits) lowers the effort level a session with ultracode on runs at, but doesn’t turn ultracode off.
[](#related-resources)
Related resources
- [Run agents in parallel](../09-Agents-Patterns/agents.md): compare subagents, agent view, agent teams, and workflows
- [Create custom subagents](../09-Agents-Patterns/sub-agents.md): the worker primitive workflows orchestrate
- [Manage costs](../17-Billing-Plans/costs.md): how multi-agent runs count toward usage limits
---
## Run parallel sessions with worktrees - Claude Code Docs
Source: https://code.claude.com/docs/en/worktrees
Path: 02-Claude-Code-CLI/worktrees.md
## On this page
- [Start Claude in a worktree](#start-claude-in-a-worktree)
- [Set up the worktree environment](#set-up-the-worktree-environment)
- [Ask Claude to create a worktree](#ask-claude-to-create-a-worktree)
- [Clean up worktrees](#clean-up-worktrees)
- [Resume a worktree session](#resume-a-worktree-session)
- [How Claude Code enforces isolation](#how-claude-code-enforces-isolation)
- [Isolate subagents with worktrees](#isolate-subagents-with-worktrees)
- [Clean up subagent and background-session worktrees](#clean-up-subagent-and-background-session-worktrees)
- [Customize worktree creation](#customize-worktree-creation)
- [Choose the base branch](#choose-the-base-branch)
- [Branch from a pull request](#branch-from-a-pull-request)
- [Copy gitignored files into worktrees](#copy-gitignored-files-into-worktrees)
- [Reuse a worktree name](#reuse-a-worktree-name)
- [Replace worktree creation with a hook](#replace-worktree-creation-with-a-hook)
- [What worktrees share with the main checkout](#what-worktrees-share-with-the-main-checkout)
- [Manage worktrees manually](#manage-worktrees-manually)
- [Non-git version control](#non-git-version-control)
- [Troubleshooting](#troubleshooting)
- [Claude Code can’t enter the worktree at startup](#claude-code-can%E2%80%99t-enter-the-worktree-at-startup)
- [Worktree creation fails on a symlinked path](#worktree-creation-fails-on-a-symlinked-path)
- [Git LFS files are pointer files in a worktree Claude Code created](#git-lfs-content-is-missing-from-a-worktree-claude-code-created)
- [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree)
- [The session resumes outside its worktree](#the-session-resumes-outside-its-worktree)
- [See also](#see-also)
Agents and parallel work
# Run parallel sessions with worktrees
Copy pageCopy page
Isolate parallel Claude Code sessions in separate git worktrees so changes don’t collide. Covers the `--worktree` flag, subagent isolation, `.worktreeinclude`, cleanup, and non-git VCS hooks.
Copy pageCopy page
A [git worktree](https://git-scm.com/docs/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 one session can build a feature while a second fixes a bug.
Worktrees require a git repository; for other version control systems, [configure hooks to replace the git logic](#non-git-version-control). In the [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions), select the **worktree** option when you start a session to give it its own worktree.
Worktrees are one of several ways to run Claude in parallel. They isolate file edits. [Subagents](../09-Agents-Patterns/sub-agents.md) split work up inside one session, and [cross-session messaging](cross-session-messaging.md) lets Claude pass findings between the sessions in your worktrees. See [Run agents in parallel](../09-Agents-Patterns/agents.md) to compare the approaches, or skip ahead to [Isolate subagents with worktrees](#isolate-subagents-with-worktrees) to use worktrees and subagents together. Most sessions need only the first two sections: [start Claude in a worktree](#start-claude-in-a-worktree), then [clean up when you exit](#clean-up-worktrees). Return to the rest of the page when you need to [resume a session](#resume-a-worktree-session), [change how worktrees are created](#customize-worktree-creation), or [debug a failure](#troubleshooting).
[](#start-claude-in-a-worktree)
Start Claude in a worktree
Pass `--worktree` or `-w` with a name to create an isolated worktree and start Claude in it. By default, the worktree is created under `.claude/worktrees/<name>/` at your repository root, on a new branch named `worktree-<name>`:
```python
claude --worktree feature-auth
```
Run the command again with a different name in another terminal to start a second isolated session. If you omit the name, Claude generates one such as `bright-running-fox`. Interactive runs require [workspace trust](../13-Enterprise-Admin/security.md): if you haven’t run Claude in the directory before, run `claude` once there to accept the trust dialog, or `--worktree` exits with an error prompting you to. Non-interactive runs with `-p` skip the trust check, so `claude -p --worktree` proceeds without it.
Add `.claude/worktrees/` to your `.gitignore` so worktree contents don’t appear as untracked files in your main checkout.
[](#set-up-the-worktree-environment)
Set up the worktree environment
A worktree is a fresh checkout, so initialize your development environment there: ask Claude to install dependencies, or run your project’s setup yourself in the worktree directory under `.claude/worktrees/`. To carry gitignored files such as `.env` into every new worktree automatically, add a [`.worktreeinclude` file](#copy-gitignored-files-into-worktrees).
[](#ask-claude-to-create-a-worktree)
Ask Claude to create a worktree
You can also ask Claude to “work in a worktree” during a session, and it creates one with the [`EnterWorktree`](tools-reference.md) tool. Once in a worktree, Claude can switch directly to another one under `.claude/worktrees/` by calling `EnterWorktree` with the target path; the previous worktree stays on disk untouched. When Claude enters a path outside the repository’s `.claude/worktrees/` directory, Claude Code asks for your approval first, because the move takes the session’s working directory, write access, and project configuration such as `CLAUDE.md` and settings to that location. An `EnterWorktree` [permission rule](permissions.md) or choosing “don’t ask again” doesn’t suppress this prompt; only `bypassPermissions` mode skips it. Before v2.1.206, Claude could enter any existing worktree path without asking.
**Hook paths don’t follow the worktree.** After Claude enters a worktree, Claude Code keeps `${CLAUDE_PROJECT_DIR}` in your [hooks](../07-Hooks/hooks.md#reference-scripts-by-path) where it was and passes the worktree path to them a different way:
- **`${CLAUDE_PROJECT_DIR}` stays put**: it still points at the project root where the session started, so a hook command such as `${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh` still runs the script in the main checkout.
- **`cwd` follows Claude**: the `cwd` field in the hook’s [input JSON](../07-Hooks/hooks.md#common-input-fields) is the worktree root, and it moves again when Claude runs `cd`. Read it when a hook needs the worktree path.
[](#clean-up-worktrees)
Clean up worktrees
When you exit an interactive worktree session, Claude checks the worktree for work that removal would delete: changed or untracked files, uncommitted work inside checked-out submodules, and new commits. These rules apply to worktrees Claude created with git. For a worktree your [WorktreeCreate hook](../07-Hooks/hooks.md#worktreecreate) created, see [WorktreeRemove](../07-Hooks/hooks.md#worktreeremove) instead.
- **The worktree is clean**: for an unnamed session, Claude removes the worktree and its branch automatically. A [named](sessions.md#name-your-sessions) session prompts you first so you can keep the worktree for later
- **The worktree has work in it**: Claude prompts you to keep or remove the worktree. Keeping preserves the directory and branch. To return later, run the `claude --worktree <name> --resume` command that Claude Code prints on exit. Removing deletes the worktree directory and its branch, along with all the work in them
- **The worktree’s state can’t be verified**: when Claude Code can’t count the worktree’s changes or can’t inspect its submodule checkouts, it prompts you rather than removing the worktree automatically. The prompt names what it couldn’t check
Non-interactive runs with `-p` have no exit prompt, so Claude doesn’t clean up their worktrees, and Claude Code leaves the lock it took on each one at creation in place until a later session’s [stale-lock sweep](#clean-up-subagent-and-background-session-worktrees) releases it. To remove one, run `git worktree remove`; if git refuses because the worktree is locked, run `git worktree unlock` on it first. On Windows, removing a worktree doesn’t delete files outside it. If a folder inside the worktree is a link to somewhere else, such as an NTFS junction or a directory symlink, Claude Code deletes only the link and keeps the folder it points to. Before v2.1.205, removing a worktree with a link nested in a subdirectory could delete the folder it pointed to.
[](#resume-a-worktree-session)
Resume a worktree session
When you resume a session that ended inside a worktree without [exiting it](#clean-up-worktrees), Claude Code returns the session to that worktree. This holds for interactive resumes, for `--continue` and `--resume` in [non-interactive mode](headless.md) with `-p`, and for the Agent SDK. `--continue` picks the most recent session recorded under the directory you launch from. Back inside the worktree, Claude can still exit it with the [`ExitWorktree`](tools-reference.md) tool. Before returning the session to its worktree, Claude Code verifies that the worktree is still a checkout separate from the main one, and declines to re-enter a worktree that fails the check. For a git worktree, the check reads its git metadata. A worktree without git metadata, such as one a [`WorktreeCreate` hook](#non-git-version-control) created, can pass the check; the cases Claude Code still refuses are listed with their recoveries under [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree). For the messages and how to recover from each, see [The session resumes outside its worktree](#the-session-resumes-outside-its-worktree). Where you launch from, and how you resume, change what Claude Code re-enters:
- **Launch directory**: resume with `--resume` from the main checkout or another directory of the repository. Claude Code re-enters a worktree it created with git under `.claude/worktrees/` even when you launch from inside it. When you launch from inside any other worktree, Claude Code re-enters it only if it can vouch for it from there: a worktree that is its own repository, one without git metadata, or a launch from a subdirectory of a worktree you created with `git worktree add` declines, so launch those from the main checkout.
- **`--fork-session`**: the forked session starts in the directory you launched Claude from, and Claude Code leaves the original session’s worktree untouched.
- **Deleted worktree**: if the worktree directory no longer exists, Claude Code resumes the session in the directory you launched Claude from. It tells you the worktree is gone and clears the session’s worktree binding.
Before v2.1.212, a non-interactive resume stayed in the starting directory and `ExitWorktree` reported that there was no active worktree session to exit.
When Claude enters or exits a worktree that Claude Code created with git, the transcript follows: Claude Code records the session under the session’s new working directory, the same way [`/cd`](commands.md) does, so `/desktop` and `--resume` find it there. Exiting moves it back the same way. A worktree created by a [`WorktreeCreate` hook](#non-git-version-control) keeps its transcript at the launch directory. Requires Claude Code v2.1.198 or later.
[](#how-claude-code-enforces-isolation)
How Claude Code enforces isolation
While a session is isolated in a worktree, Claude Code blocks the tool calls the checks below define. The same rules apply whether you started the session with `--worktree`, Claude entered a worktree with `EnterWorktree`, or you resumed a worktree session. The same enforcement covers every subagent Claude spawns from the isolated session. It applies whether the session is interactive or runs in the [background](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated). [Subagents that run in their own worktree](#isolate-subagents-with-worktrees) carry the same checks. Their version history is under [Write subagent files](../09-Agents-Patterns/sub-agents.md#write-subagent-files). Claude Code applies four checks:
- **File edits**: Claude Code blocks an `Edit`, `Write`, or `NotebookEdit` that targets a path in the main checkout.
- **Command working directory**: Claude Code blocks a Bash, PowerShell, or Monitor command whose working directory resolves to the main checkout, or whose working directory it can’t verify stays outside it.
- **Git redirects**: Claude Code blocks a Bash or Monitor command that redirects git into the main checkout. The redirect can come through `git -C`, `--git-dir`, a `GIT_DIR` or `GIT_WORK_TREE` variable, or a `cd` into the main checkout before running git.
- **Command shape**: Claude Code blocks a Bash or Monitor command when it can’t verify from the command text that any git the command runs stays inside the worktree. That happens, for example, when the command name is computed at runtime, when the syntax can’t be parsed, or when an expansion such as `${!name}` or `${ command; }` could run a command the text doesn’t spell out. Claude Code tells Claude how to rewrite the refused command, such as splitting it into plain, separate commands. You can’t turn this check off.
The checks apply to the repository you launched Claude Code from. They also cover the main checkout a linked worktree is linked from. For PowerShell commands, Claude Code applies only the working-directory check. Claude sees each refusal as a tool error that names the worktree and says how to proceed. For a refused command, see [what the refusal message means and how to clear it](errors.md#command-blocked-by-the-worktree-isolation-checks).
[](#isolate-subagents-with-worktrees)
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 make the isolation permanent for a [custom subagent](../09-Agents-Patterns/sub-agents.md#supported-frontmatter-fields) by adding `isolation: worktree` to its frontmatter. This subagent in `.claude/agents/` always runs in its own worktree:
```python
---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---
Apply the requested refactor across every affected file, then run the tests
and report the results.
```
Each subagent gets a temporary worktree that Claude Code removes automatically when the subagent finishes without changes; a worktree with changes stays on disk until the [periodic sweep below](#clean-up-subagent-and-background-session-worktrees) can remove it without losing work. Subagent worktrees use the same [base branch](#choose-the-base-branch) as `--worktree`, so they branch from your repository’s default branch unless `worktree.baseRef` is set to `"head"`.
[](#clean-up-subagent-and-background-session-worktrees)
Clean up subagent and background-session worktrees
Claude Code runs a periodic sweep that removes worktrees that Claude created for subagents and [background sessions](../09-Agents-Patterns/agent-view.md#how-file-edits-are-isolated) once they are older than your [`cleanupPeriodDays`](settings-reference.md#cleanupperioddays) setting, following the [retention sweep rules](claude-directory.md#cleaned-up-automatically). When you [background](../09-Agents-Patterns/agent-view.md#send-the-session-to-the-background) a `--worktree` session, its worktree becomes a background-session worktree that the sweep can remove. The sweep leaves a worktree in place in these cases:
- The worktree still holds work: changed or untracked files, or unpushed commits.
- A checked-out submodule in the worktree holds changed or untracked files, or Claude Code can’t inspect the worktree’s submodules. This check requires Claude Code v2.1.274 or later.
- One of the [four cases that also block worktree creation](#git-lfs-content-is-missing-from-a-worktree-claude-code-created) applies: Claude Code can’t determine which filter drivers the repository config defines, or finds a setting there it can’t switch off.
- The worktree belongs to a `--worktree` session you haven’t backgrounded, whatever its age.
- You created the worktree yourself with `git worktree add`, even if you then ran a `--worktree <name>` session in it and backgrounded that session.
Claude Code writes a marker into the git metadata of every worktree it creates with git, and the sweep keeps any worktree without one, including a worktree a [`WorktreeCreate` hook](#non-git-version-control) created. Before v2.1.246, the sweep didn’t check for the marker, and could remove a worktree you created yourself when an old background-session record pointed at it. While an agent is running, Claude Code holds a `git worktree lock` on its worktree so that concurrent cleanup can’t remove it, and releases the lock when the agent finishes. Claude Code holds the same lock on the worktree it created for a backgrounded session while the session runs, so the sweep leaves the worktree in place and `git worktree remove` refuses to remove it. The sweep also releases a lock Claude Code set for a session whose process has exited, so a killed background session doesn’t leave its worktree permanently locked. The sweep never releases a lock you set yourself with `git worktree lock`. Before v2.1.210, a lock left by a killed session stayed in place until you ran `git worktree unlock`. To clean up a worktree that the sweep keeps, run `git worktree remove`, adding `--force` if the worktree has uncommitted changes or untracked files. If git refuses because the worktree is locked, run `git worktree unlock` on it first.
[](#customize-worktree-creation)
Customize worktree creation
Claude Code’s defaults for creating worktrees cover most sessions: it creates them under `.claude/worktrees/`, branches them from your repository’s default branch, and checks out only tracked files. The options in this section change those defaults.
[](#choose-the-base-branch)
Choose the base branch
New worktrees branch from the repository’s default branch, so most sessions don’t need this setting. Set `worktree.baseRef` in [settings](settings-reference.md#worktree) to branch from your current work instead. The setting accepts two values:
- `"fresh"` (default): branch from the repository’s default branch on the remote, usually `main`, so the worktree starts from a clean tree matching the remote.
- `"head"`: branch from your current local `HEAD`, so the worktree carries your unpushed commits and feature-branch state. Use this when isolating subagents that need to operate on in-progress work. Inside a worktree, `"head"` resolves to that worktree’s `HEAD`, not the main checkout’s.
You can’t set `worktree.baseRef` to a branch name. To start a worktree from a specific existing branch, [create it with git directly](#manage-worktrees-manually). For a `"fresh"` base, Claude Code keeps `origin/HEAD` current: when the repository hasn’t been fetched in the last 24 hours, it fetches the default branch, capped at five seconds, and uses the locally cached ref if the fetch fails. If no remote is configured, or `origin/HEAD` isn’t cached locally and can’t be fetched, the worktree falls back to your current local `HEAD`. Before v2.1.208, a fresh worktree used whatever `origin/HEAD` was already cached locally. This example makes every new worktree branch from your current work:
```python
{
"worktree": {
"baseRef": "head"
}
}
```
[](#branch-from-a-pull-request)
Branch from a pull request
To branch from a specific pull request or merge request, pass `--worktree` the number prefixed with `#`, a GitHub pull request URL, or a GitLab merge request URL such as `https://gitlab.com/group/repo/-/merge_requests/123`. Claude Code fetches that change’s head commit from `origin` and creates the worktree at `.claude/worktrees/pr-<number>`. Quote the argument so your shell doesn’t treat `#` as the start of a comment:
```python
claude --worktree "#1234"
```
Claude Code reads only the number from the URL. It always fetches from your repository’s `origin` remote, and picks the fetch path by `origin`’s host:
- **github.com**: fetches `pull/<number>/head`
- **gitlab.com**: fetches `merge-requests/<number>/head`
- **GitHub Enterprise, self-managed GitLab, or any other host**: tries `pull/<number>/head` first, then `merge-requests/<number>/head`
Before v2.1.233, Claude Code accepted only `#<number>` and GitHub-style pull request URLs for `--worktree`, and always fetched `pull/<number>/head`.
[](#copy-gitignored-files-into-worktrees)
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. If you write a pattern that starts with `**/` and the files you want are inside a directory that is gitignored as a whole, Claude Code copies them only when that directory itself matches the pattern, or when the first name after the `**/` is one of the names in the directory’s path. For example, if you write `**/.claude/skills/*.md`, that first name is `.claude`, so Claude Code copies the matching files out of an ignored `.claude/` directory. To copy files out of an ignored directory that a `**/` pattern doesn’t reach, name the directory in the pattern instead: write `vendor/**/config.json` rather than `**/config.json`. Before v2.1.239, Claude Code copied files out of a wholly ignored directory for a `**/` pattern only when the directory itself matched the pattern. This `.worktreeinclude` copies two env files and a secrets config into each new worktree:
.worktreeinclude
```python
.env
.env.local
config/secrets.json
```
This applies to every worktree Claude Code creates with git: `--worktree` worktrees, [subagent worktrees](#isolate-subagents-with-worktrees), and parallel sessions in the [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions). With a [`WorktreeCreate` hook](#non-git-version-control), copy the files inside the hook script.
[](#reuse-a-worktree-name)
Reuse a worktree name
Passing `--worktree` a name whose directory already exists opens that existing worktree instead of creating a new one. With the default `"fresh"` [base](#choose-the-base-branch), a reopened worktree resets to the repository’s default branch instead of continuing at its old tip when all of the following hold:
- It has no uncommitted changes or untracked files.
- It is still on the branch Claude Code created for it.
- It has no commits of its own, or its pull request or merge request was merged and its remote branch deleted.
Claude Code detects the merged case from git state alone: the remote branch the worktree pushed to no longer exists, and every commit in the worktree is already on the default branch. In every other case, Claude Code reopens the worktree at its old tip:
- The worktree fails any of the conditions.
- Claude Code can’t verify the worktree’s state.
- `worktree.baseRef` is `"head"`.
- The name is a pull request or merge request reference.
Before v2.1.208, when you reused a name, Claude Code always reopened the old worktree at its old tip.
[](#replace-worktree-creation-with-a-hook)
Replace worktree creation with a hook
Configure a [`WorktreeCreate` hook](../07-Hooks/hooks.md#worktreecreate) to replace the default `git worktree` logic entirely, including placing worktrees somewhere other than `.claude/worktrees/`. For a complete example, see [Non-git version control](#non-git-version-control).
[](#what-worktrees-share-with-the-main-checkout)
What worktrees share with the main checkout
A worktree gets its own files and branch, but it shares the following with the main checkout:
- **The repository’s `.git` directory**: git commands in a worktree write to the main repository’s shared `.git` directory, and [sandboxing](sandboxing.md#filesystem-isolation) allows those writes, so commands such as `git commit` work from inside a worktree with the sandbox enabled.
- **Plugins**: plugins installed at [project scope](../08-Plugins-Skills/plugins-loading.md#find-where-a-plugin-is-enabled) from the main checkout also load in worktrees of the same repository, so you don’t need to reinstall them per worktree. Requires Claude Code v2.1.200 or later.
- **Permission approvals**: choosing “Yes, and don’t ask again” for a Bash command in a worktree session saves the rule to the main checkout’s `.claude/settings.local.json`, so it applies in the main checkout and in every other worktree of the repository, and it survives the worktree’s removal. On Windows and in the other cases where Claude Code [doesn’t use the repository root](settings.md#where-claude-code-looks-for-each-file), the rule stays with that worktree. Before v2.1.211, an approval granted in a worktree was saved inside that worktree, didn’t apply elsewhere, and was lost when the worktree was removed. See [where approvals are saved](permissions.md#permission-system).
- **Untracked skills, agents, and commands**: when the worktree checkout has no `.claude/skills` directory at its root, for example because your `.claude/skills` is gitignored, Claude Code loads the main checkout’s [project skills](../08-Plugins-Skills/skills.md#where-skills-live) in the worktree session. In a worktree with its own `.claude/skills` directory, only that copy loads. The same read-through covers `.claude/agents` and `.claude/commands`. For skills, the read-through requires Claude Code v2.1.277 or later.
All of these apply whether you create the worktree with `--worktree`, with `git worktree add`, or through the [desktop app](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions).
[](#manage-worktrees-manually)
Manage worktrees manually
Create worktrees with Git directly when you need to check out a specific existing branch or place the worktree outside the repository. Create a worktree on a new branch:
```python
git worktree add ../project-feature-a -b feature-a
```
Create a worktree from an existing branch, replacing `fix-issue-456` with a branch that already exists in your repository:
```python
git worktree add ../project-bugfix fix-issue-456
```
Start Claude in the worktree:
```python
cd ../project-feature-a
claude
```
List your worktrees:
```python
git worktree list
```
Remove one when you’re done with it:
```python
git worktree remove ../project-feature-a
```
See the [Git worktree documentation](https://git-scm.com/docs/git-worktree) for the full command reference.
[](#non-git-version-control)
Non-git version control
Worktree isolation uses git by default. For SVN, Perforce, Mercurial, or other systems, configure [`WorktreeCreate` and `WorktreeRemove` hooks](../07-Hooks/hooks.md#worktreecreate) to provide custom creation and cleanup logic. Because the hook replaces the default git behavior, [`.worktreeinclude`](#copy-gitignored-files-into-worktrees) 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 the JSON on stdin with `jq`, checks out a fresh SVN working copy, and prints the directory path so Claude Code can use it as the session’s working directory. Add the configuration to your [`settings.json`](settings.md#where-settings-live):
```python
{
"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](../07-Hooks/hooks.md#worktreecreate) for the input schema and a removal example. A `WorktreeCreate` hook also lets you run [`/batch`](commands.md#all-commands) outside a git repository. Each `/batch` subagent then publishes its change with your project’s version-control commands and, when it can’t open a pull request, reports what it published instead. Running `/batch` outside a git repository requires Claude Code v2.1.281 or later.
[](#troubleshooting)
Troubleshooting
Claude Code reports the errors below when it creates a worktree, enters one at startup, or returns a resumed session to one.
[](#claude-code-can’t-enter-the-worktree-at-startup)
Claude Code can’t enter the worktree at startup
When Claude Code can’t enter the worktree directory at startup, it prints an error naming the path and exits with code 1. This can happen when a [`WorktreeCreate` hook](../07-Hooks/hooks.md#worktreecreate) prints something other than the directory it created, or when the directory was deleted after it was set up.
[](#worktree-creation-fails-on-a-symlinked-path)
Worktree creation fails on a symlinked path
Claude Code refuses to create a worktree when `.claude`, `.claude/worktrees`, or the worktree directory itself is a symlink, and the error names the symlinked path. Remove the symlink and retry. Before v2.1.212, if the repository already contained a committed symlink at one of those paths, worktree creation followed it and could create files outside the repository.
[](#git-lfs-content-is-missing-from-a-worktree-claude-code-created)
Git LFS files are pointer files in a worktree Claude Code created
If you set up [Git LFS](https://git-lfs.com) with `git lfs install --local`, a worktree that Claude Code creates contains LFS pointer files instead of the real files. The `--local` flag writes the LFS filter into the repository’s own `.git/config` rather than your global git config. A plain `git lfs install` writes to your global config and isn’t affected. The same applies to any other [filter driver](https://git-scm.com/docs/gitattributes) defined in the repository’s own config. Claude Code skips the repository’s own filter drivers when it creates a worktree because a filter driver is a shell command, and anything that can write to the repository, including Claude, could have put one there. Before v2.1.247, Claude Code ran those drivers during worktree creation. To get the real files, run `git lfs pull` inside the worktree. In four rare cases, Claude Code creates no worktree at all: it can’t tell which filter drivers the repository’s config defines, or it finds a setting there it can’t switch off. Match the error to its fix:
- **`Could not read the repository git config to neutralize filter drivers`**: Claude Code couldn’t read the repository’s `.git/config`, for example because of its permissions. Fix that and retry.
- **`The repository git config defines a filter driver whose name cannot be neutralized (contains "=" or a newline)`**: rename or remove that filter driver in `.git/config` and retry.
- **`The repository git config has a conditional include (includeIf)`**: move the settings the `includeIf` in `.git/config` pulls in directly into that file, remove the `includeIf`, and retry. An `includeIf` in your global git config doesn’t trigger this.
- **`Git was not run: the repository's own git config sets <key>`**: the message names a key that points Git LFS at a program to run, such as `lfs.customtransfer.<name>.path` or `lfs.standalonetransferagent`. If that setting is yours, move it to your global git config. If you don’t recognize it, remove it from the repository’s git config, since a tool or checkout you don’t trust may have written it. Retry once the key is gone from the repository’s config.
[](#claude-code-refuses-to-use-a-worktree)
Claude Code refuses to use a worktree
An error starting `Refusing to use <path> as an isolation worktree` means Claude Code checked the directory’s git identity before adopting it as a session’s or subagent’s isolated checkout, and declined it. The check runs whether Claude Code is creating the worktree, entering an existing one, or reusing one from an earlier run. In most cases the rest of the message says the directory’s git metadata resolves into the main checkout: for example, its `.git` file points at the main repository’s own `.git` directory, or git resolves its working tree to the main checkout through a `core.worktree` redirect. From such a directory, an ordinary git command such as `git reset --hard` would act on the main checkout instead of the worktree. Claude Code also refuses when the directory has a `.git` entry it can’t read, rather than assuming the worktree is safe. A directory with no git metadata at all, such as one your [`WorktreeCreate` hook](#non-git-version-control) creates, passes the check only when no git repository contains it. If the hook creates the directory inside a repository, git resolves it to that repository’s checkout and Claude Code refuses it with the `git resolves its working tree to` message, so have the hook create its directories outside any repository. Claude Code leaves the refused directory in place, since it may hold work. Match the message to its recovery, whether it follows `Refusing to use <path>` or appears in a [resume message](#the-session-resumes-outside-its-worktree); some endings occur only in resume messages:
- **Says `launch from the parent checkout` or `Run the resume from the project checkout`**: you launched Claude Code from inside the worktree. Launch from the main checkout instead; the worktree needs no recreation.
- **Says `it cannot be resumed or re-entered`**: nothing in this session vouches for the worktree from where you launched. Recreate it; the directory and its work remain on disk for manual recovery, and when the worktree has a parent checkout, resuming from there also works.
- **Says `it contains the protected checkout`**: the refused directory is a parent of your main checkout, such as your home directory. Don’t delete it. Change the worktree path, such as the path your `WorktreeCreate` hook returns or the `EnterWorktree` target, so the worktree doesn’t contain the checkout.
- **Says `the protected checkout <path> has a .git entry that could not be examined` or `has git metadata that could not be resolved`**: the problem is the main checkout’s git metadata, not the worktree’s. Don’t delete the worktree, and ignore the message’s trailing advice to recreate it, which doesn’t apply to these two endings. Repair the main checkout, for example a permissions problem or a git `dubious ownership` refusal on its `.git`, and retry.
- **Says `its recorded path has a network spelling`**: Claude Code never resumes into a worktree at a network path. Recreate the worktree at a local path.
- **Any other ending**: the message names the problem and its fix, such as removing a `core.worktree` redirect or recreating the worktree; follow it. Before deleting a directory whose message says its git identity could not be verified, address the named cause first, for example a symbolic link in the worktree’s path or git itself failing to run, since the directory may be healthy. When you do recreate, salvage any changes you need from the old directory first; it stays on disk.
[](#the-session-resumes-outside-its-worktree)
The session resumes outside its worktree
When you resume a session interactively and Claude Code can’t return it to its worktree, Claude Code says so with one of the messages below. When Claude Code clears the worktree binding, it records the clear in the session transcript. If you [suppress transcript writes](sessions.md#where-transcripts-are-stored), the message says instead that the binding could not be cleared and that Claude Code will re-check the worktree on a later resume.
| Message starts with | What happened and what to do |
|:--------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Your worktree <path> no longer exists` | The worktree directory was removed. The session continues in the current directory without isolation, and Claude Code clears the worktree binding. No action needed. |
| `Could not verify your worktree <path> this time` | Claude Code couldn’t verify the worktree, usually for a transient reason; the binding is kept, and the session continues in the current directory without isolation. Resume again to retry; if it keeps happening, enter the worktree in a new session and match the refusal message under [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree), which can name the main checkout’s metadata rather than the worktree’s. |
| `Did not re-enter your worktree <path>` | Claude Code refused the worktree binding as unsafe; it clears the binding and the session continues without isolation. The message includes the specific refusal: match it under [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree), since the fix is recreation for some refusals and a path change for others. |
| `Could not re-enter your worktree <path>` | Claude Code couldn’t vouch for the worktree from where you launched, most commonly because you launched from inside it; the binding is kept. The rest of the message names the fix; match it under [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree). |
In [non-interactive mode](headless.md) with `-p`, and on resumes that the [Agent SDK](../05-Agent-SDK/agent-sdk-sessions.md) runs, Claude Code stops the resume with a stderr error for every refusal except a gone worktree, instead of continuing without isolation. With `--output-format stream-json`, the refusal also arrives on stdout as a `result` message with subtype `error_during_execution` whose `errors` array carries the same text, so an Agent SDK application receives the reason rather than only a non-zero exit. Before v2.1.260, a worktree-resume refusal produced no `result` message. The messages take different shapes from the interactive messages in the table:
- `Error: cannot resume into worktree <path>: ...This session was not started.` for a refusal the table shows as `Did not re-enter`. Claude Code clears the worktree binding before exiting, and the error says so; the next time you resume the conversation, the session continues in the current directory without worktree isolation. Before v2.1.260, Claude Code didn’t write the cleared binding, so every retry of the same resume failed with the same error. If you [suppress transcript writes](sessions.md#where-transcripts-are-stored), the clear can’t be saved. The error then says the same command will be refused again, and names `--fork-session` and starting a new conversation as ways to continue without the worktree.
- `Error: could not verify worktree <path> for this resume, so the resume was aborted...` for `Could not verify`
- `Error: ...The worktree binding is kept.` for `Could not re-enter`
- `Notice: the worktree <path> for this session no longer exists...` for a gone worktree; Claude Code prints it and continues the session, as an interactive resume does
The refusal ending embedded in each error is shared with the interactive notices, so it still matches its entry under [Claude Code refuses to use a worktree](#claude-code-refuses-to-use-a-worktree). In the stream-json result, [`startup_failure_reason`](../05-Agent-SDK/agent-sdk-typescript.md#startup_failure_reason) is `worktree_unverified` for the `could not verify worktree` error and `worktree_resume_refused` for the `cannot resume into worktree` and `The worktree binding is kept` errors. An application can branch on it instead of matching the error text. Before v2.1.274, the result carried no `startup_failure_reason` field.
[](#see-also)
See also
Worktrees handle file isolation. The related pages below cover delegating work into those isolated checkouts, passing findings between them, and switching between the sessions you create:
- [Subagents](../09-Agents-Patterns/sub-agents.md): delegate work to isolated agents within a session
- [Cross-session messaging](cross-session-messaging.md): let the sessions in your worktrees pass findings to each other
- [Agent teams](../09-Agents-Patterns/agent-teams.md): coordinate multiple Claude sessions automatically
- [Manage sessions](sessions.md): name, resume, and switch between conversations
- [Desktop parallel sessions](../16-Mobile-Desktop/desktop.md#work-in-parallel-with-sessions): worktree-backed sessions in the desktop app
---
## Your first day in Claude Code | Claude Help Center
Source: https://support.claude.com/en/articles/14552382-your-first-day-in-claude-code
Path: 02-Claude-Code-CLI/your-first-day-in-claude-code.md
# Your first day in Claude Code
April 15, 2026
**Goal:** In about 15 minutes, you will install Claude Code, sign in, and complete your first AI-assisted change. This guide covers only what is needed on day one; links to deeper material appear at the end.
------------------------------------------------------------------------
## Step 1: Install Claude Code (2 minutes)
Pick the command that matches your machine and paste it into a terminal.
[TABLE]
**Tip:** Do not run the npm install with `sudo`, as this causes file-permission problems later.
Verify the installation:
claude --version
------------------------------------------------------------------------
## Step 2: Sign in (2 minutes)
How you authenticate depends on how your organization has provisioned access. Pick one of the following:
[TABLE]
If you are unsure which method applies, check with your administrator or try `/login` first, which is the default for most organizations.
------------------------------------------------------------------------
## Step 3: Open a project (1 minute)
cd path/to/your/project claude
Claude Code reads your files on demand, so there is nothing to upload or attach. Simply start it from inside the repository you want to work on.
------------------------------------------------------------------------
## Step 4: Understand the one safety rule (1 minute)
Claude will **always ask before changing a file or running a command.** When it proposes a change, you will see a diff and three choices:
- **Yes** — apply this single change.
- **Yes, and don't ask again for edits** — auto-approve file edits for the remainder of the session.
- **No** — reject the change and explain why.
You can press **Shift+Tab** at any time to cycle between modes (Plan → Accept Edits → default). If a change produces an unexpected result, your git history remains untouched until you commit, so `git checkout` will undo it.
------------------------------------------------------------------------
## Step 5: Five things to try first
Copy and paste these into the prompt one at a time. Each example demonstrates a different core capability.
### 1. Get oriented
Give me a 5-bullet summary of what this codebase does and where the entry point is.
*Why this is useful:* It shows how Claude explores files on its own, without being pointed at specific paths.
### 2. Find something
Where is user authentication handled? Show me the file and the key function.
*Why this is useful:* It is often faster than `grep` when you do not know the exact symbol or filename.
### 3. Make a safe edit
Add a docstring to the function <name> in <file>. Keep it to 2 lines.
*Why this is useful:* It lets you practice reviewing and approving a diff on a low-risk change.
### 4. Fix something real
This test is failing: <paste the error>. Find the cause and fix it.
*Why this is useful:* This is the primary workflow—you describe the symptom, and Claude investigates and proposes a fix.
### 5. Let it handle git
Stage my changes and write a commit message that follows our existing style.
*Why this is useful:* Claude can run `git` on your behalf (with approval) and will match your repository's existing commit conventions.
------------------------------------------------------------------------
## Step 6: Before you finish for the day
Run this once per project:
/init
This generates a `CLAUDE.md` file at your project root that captures your codebase's conventions. Claude reads it automatically at the start of every session, so future responses will already be tailored to your project. It is the single highest-value setup step you can take.
------------------------------------------------------------------------
## Next steps
You have now installed Claude Code, authenticated, made an edit, and set up project memory. When you are ready to go further, the official documentation covers **[memory and CLAUDE.md](memory.md)**, **[built-in commands](commands.md)**, and **[interactive-mode shortcuts](interactive-mode.md)** in depth.
If you ran into problems during install or login, see the **[troubleshooting guide](troubleshooting.md)**.
---
## Zero data retention - Claude Code Docs
Source: https://code.claude.com/docs/en/zero-data-retention
Path: 02-Claude-Code-CLI/zero-data-retention.md
## On this page
- [ZDR scope](#zdr-scope)
- [Route Claude Code traffic to your ZDR organization](#route-claude-code-traffic-to-your-zdr-organization)
- [What ZDR covers](#what-zdr-covers)
- [What ZDR does not cover](#what-zdr-does-not-cover)
- [Features disabled under ZDR](#features-disabled-under-zdr)
- [Model availability under ZDR](#model-availability-under-zdr)
- [Data retention for policy violations](#data-retention-for-policy-violations)
- [Request ZDR](#request-zdr)
Security and data
# Zero data retention
Copy pageCopy page
Learn about Zero Data Retention (ZDR) for Claude Code, available to qualified accounts on Claude for Enterprise, including scope, disabled features, and how to request enablement.
Copy pageCopy page
Zero Data Retention (ZDR) for Claude Code is available to qualified accounts on 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 is not included in the standard Claude for Enterprise plan and cannot be enabled from your admin settings. It is available to qualified accounts and requires separate enablement by Anthropic. If your organization requires ZDR, [contact sales](https://www.anthropic.com/contact-sales?utm_source=claude_code&utm_medium=docs&utm_content=zero_data_retention_request) or your Anthropic account team to confirm eligibility.
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](../13-Enterprise-Admin/analytics.md) dashboard
- [Server-managed settings](../13-Enterprise-Admin/server-managed-settings.md)
- Audit logs
ZDR for Claude Code on Claude for Enterprise applies only to Anthropic’s direct platform. For Claude deployments on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry, refer to those platforms’ data retention policies.
[](#zdr-scope)
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.
[](#route-claude-code-traffic-to-your-zdr-organization)
Route Claude Code traffic to your ZDR organization
ZDR applies to requests that authenticate into a ZDR-enabled organization. If a developer signs in to Claude Code with a personal account or with an API key from a different organization, those sessions are not covered. To require that developers’ claude.ai logins belong to your ZDR organization, deploy the `forceLoginMethod` and `forceLoginOrgUUID` managed settings; see [Restrict login to your organization](../13-Enterprise-Admin/iam.md#restrict-login-to-your-organization), which also explains how these keys treat Claude Console logins.
[](#what-zdr-covers)
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 to every model available to your ZDR organization. Some models require data retention by default; see [Model availability under ZDR](#model-availability-under-zdr).
[](#what-zdr-does-not-cover)
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](../13-Enterprise-Admin/data-usage.md#data-retention):
| 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](../13-Enterprise-Admin/analytics.md) 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)
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 |
|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|
| [Cloud sessions](claude-code-on-the-web.md), including those started from the [Desktop app](../16-Mobile-Desktop/desktop.md#cloud-sessions) | Requires server-side storage of session data, including conversation history with prompts and completions. |
| [Claude Tag](https://claude.com/docs/claude-tag) | Retains channel memory and session transcripts. |
| [Artifacts](artifacts.md) | Requires storing published page content on Anthropic-operated infrastructure. |
| Feedback submission (`/feedback`, `/bug`, `/share`) | Submitting feedback sends conversation data to Anthropic. |
| [Remote Control](remote-control.md) | Stores the session transcript on Anthropic servers to sync the conversation across devices. |
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.
[](#model-availability-under-zdr)
Model availability under ZDR
Claude Fable 5.1 and Fable 5 are [Covered Models](https://code.claude.com/docs/20-Models/covered-models-9b5d036943.md) that [require data retention](../04-API-Reference/Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements) by default, and whether a ZDR organization or workspace can use them is governed by the Covered Models policies rather than by Claude Code. Where your organization can’t use them, the models are either absent from the `/model` picker or shown as disabled, and the server rejects requests for them regardless of client configuration. Other models remain available under ZDR. Fable models are not the default, and the `best` alias, which resolves to the latest Fable model where it is available, resolves to Opus for organizations where it is not.
[](#data-retention-for-policy-violations)
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)
Request ZDR
To request ZDR for Claude Code on Claude for Enterprise, [contact sales](https://www.anthropic.com/contact-sales?utm_source=claude_code&utm_medium=docs&utm_content=zero_data_retention_request) 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.