Follow Discord
Sweep 22 Oct 2026 · 04:32Z Build v2.1.308 527 read Stable v2.1.308 Latest v2.1.308 Next v2.1.308 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · claude-code

One read of Claude Code CLIclaude-code-20261020T183702Z

212 pages moved out of 228 read.

Pages moved 212 significant first
Pages read 228 in this capture
Captured 18:37 UTC
Corpus hash f4a7dc09bf09 corpus-hash

What this read moved

101-125 of 212, page 5 of 9

This capture is too large to show at once. Changes 101-125 of 212 are below, significant first; the rest are on the following screens.

llm-gateway-connect Changed · +192 / -214 lines

from line 6
66 
77This page is for developers running Claude Code through a gateway their organization operates. It covers two paths: [checking whether your administrator already configured it for you](#check-for-an-existing-configuration), and [configuring it yourself](#configure-claude-code-yourself) when they haven't.
88 
9<Note>
10 * To deploy a gateway for your organization, see [Roll out an LLM gateway](/docs/en/llm-gateway-rollout)
11 * For what Claude Code sends to a gateway, see the [gateway compatibility guide](/docs/en/llm-gateway-protocol)
12</Note>
9> [!NOTE]
10>
11> * To deploy a gateway for your organization, see [Roll out an LLM gateway](/docs/en/llm-gateway-rollout)
12> * For what Claude Code sends to a gateway, see the [gateway compatibility guide](/docs/en/llm-gateway-protocol)
1313 
1414## Check for an existing configuration
1515 
1616Administrators can distribute the gateway address and credential through [managed settings](/docs/en/managed-settings), device management, or an [`apiKeyHelper`](#rotate-credentials-with-apikeyhelper), so Claude Code picks them up at startup with nothing for you to set. To check whether your organization already did this:
1717 
18<Steps>
19 <Step title="Start Claude Code">
20 Run `claude`. If it opens to the login screen instead of a session, no gateway credential was distributed; [configure it yourself](#configure-claude-code-yourself) below.
21 </Step>
18**1. Start Claude Code**
2219 
23 <Step title="Check the Status tab">
24 If Claude Code started a session without showing the login screen, run `/status`, which opens on the **Status** tab, and check two lines:
20Run `claude`. If it opens to the login screen instead of a session, no gateway credential was distributed; [configure it yourself](#configure-claude-code-yourself) below.
2521 
26 * `Anthropic base URL`: this line only appears when a gateway address is set. If it isn't there, Claude Code isn't pointed at the gateway; [configure it yourself](#configure-claude-code-yourself) below.
27 * `Auth token` or `API key`: a line naming `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY`, or an `apiKeyHelper` confirms a gateway credential is active. A `Login method` line naming a claude.ai account instead means the credential wasn't distributed; [set it yourself](#set-the-credential-variable).
28 </Step>
22**2. Check the Status tab**
2923 
30 <Step title="Send a test message">
31 Close the `/status` menu and send any prompt in Claude Code. A normal response from Claude, with no error, confirms the gateway connection works.
32 </Step>
33</Steps>
24If Claude Code started a session without showing the login screen, run `/status`, which opens on the **Status** tab, and check two lines:
3425 
26* `Anthropic base URL`: this line only appears when a gateway address is set. If it isn't there, Claude Code isn't pointed at the gateway; [configure it yourself](#configure-claude-code-yourself) below.
27* `Auth token` or `API key`: a line naming `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY`, or an `apiKeyHelper` confirms a gateway credential is active. A `Login method` line naming a claude.ai account instead means the credential wasn't distributed; [set it yourself](#set-the-credential-variable).
28 
29**3. Send a test message**
30 
31Close the `/status` menu and send any prompt in Claude Code. A normal response from Claude, with no error, confirms the gateway connection works.
32 
3533If both lines in the `/status` menu look right but the message to Claude fails, see the [troubleshooting table](#troubleshoot-gateway-errors).
3634 
3735## Configure Claude Code yourself
from line 69
7169 
7270Replace the values with the ones your gateway team gave you:
7371 
74<Tabs>
75 <Tab title="Bash or Zsh">
76 ```bash theme={null}
77 export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
78 export ANTHROPIC_AUTH_TOKEN=sk-gateway-key
79 ```
80 </Tab>
72**Bash or Zsh**
8173 
82 <Tab title="PowerShell">
83 ```powershell theme={null}
84 $env:ANTHROPIC_BASE_URL = "https://llm-gateway.example.com"
85 $env:ANTHROPIC_AUTH_TOKEN = "sk-gateway-key"
86 ```
87 </Tab>
88</Tabs>
74```bash theme={null}
75export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
76export ANTHROPIC_AUTH_TOKEN=sk-gateway-key
77```
8978 
79**PowerShell**
80 
81```powershell theme={null}
82$env:ANTHROPIC_BASE_URL = "https://llm-gateway.example.com"
83$env:ANTHROPIC_AUTH_TOKEN = "sk-gateway-key"
84```
85 
9086Shell exports apply only to that terminal session and programs started from it. An editor launched from the dock or Start menu won't see them. To make the values persist across new terminals, add the same lines to your shell profile, such as `~/.zshrc`, `~/.bashrc`, or your PowerShell `$PROFILE`.
9187 
9288If you export the gateway only in your shell, it doesn't reliably reach background agents hosted by the [supervisor](/docs/en/agent-view#how-background-sessions-are-hosted); see [how each background session sources its gateway](/docs/en/agent-view#llm-gateway). Use a settings file for any gateway that background agents must always route through.
from line 94
9894* `~/.claude/settings.json` applies to all your projects. On Windows the path is `%USERPROFILE%\.claude\settings.json`
9995* `.claude/settings.local.json` applies to one project. Claude Code adds it to your global gitignore when it saves a setting there; if you create it by hand or have Claude write it, add it to your gitignore yourself first so you don't accidentally commit your credential
10096 
101<Warning>
102 Don't put the credential in a project's `.claude/settings.json`. That file is committed and shared with everyone who clones the repository.
103</Warning>
97> [!WARNING]
98>
99> Don't put the credential in a project's `.claude/settings.json`. That file is committed and shared with everyone who clones the repository.
104100 
105101The `env` block looks the same in either file:
106102 
from line 115
119115 
120116With the variables exported in your shell, send a one-token request to the gateway directly. This confirms the URL and credential work before you open Claude Code, so a failure points at the gateway rather than your configuration. The commands below read the shell variables, so they need the [shell exports](#set-as-shell-environment-variables) even if you also put the values in a settings file.
121117 
122<Tabs>
123 <Tab title="Bash or Zsh">
124 ```bash theme={null}
125 curl -sS -w '\n%{http_code}\n' -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
126 -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
127 -H "anthropic-version: 2023-06-01" \
128 -H "content-type: application/json" \
129 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
130 ```
131 </Tab>
118**Bash or Zsh**
132119 
133 <Tab title="PowerShell">
134 ```powershell theme={null}
135 Invoke-RestMethod -Method Post -Uri "$env:ANTHROPIC_BASE_URL/v1/messages" `
136 -Headers @{ "Authorization" = "Bearer $env:ANTHROPIC_AUTH_TOKEN"; "anthropic-version" = "2023-06-01" } `
137 -ContentType "application/json" `
138 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
139 ```
140 </Tab>
141</Tabs>
120```bash theme={null}
121curl -sS -w '\n%{http_code}\n' -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
122 -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
123 -H "anthropic-version: 2023-06-01" \
124 -H "content-type: application/json" \
125 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
126```
142127 
128**PowerShell**
129 
130```powershell theme={null}
131Invoke-RestMethod -Method Post -Uri "$env:ANTHROPIC_BASE_URL/v1/messages" `
132 -Headers @{ "Authorization" = "Bearer $env:ANTHROPIC_AUTH_TOKEN"; "anthropic-version" = "2023-06-01" } `
133 -ContentType "application/json" `
134 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
135```
136 
143137If your gateway expects keys in the `x-api-key` header, replace the `Authorization` header with `x-api-key: $ANTHROPIC_API_KEY` in the Bash command, or the `"Authorization"` hashtable entry with `"x-api-key" = "$env:ANTHROPIC_API_KEY"` in the PowerShell command.
144138 
145139A JSON response that starts with `{"id":"msg_` and includes a `"content":[...]` field means the gateway is reachable and the credential works. An error naming an unknown model still proves the URL and credential work, since the gateway authenticated the request before rejecting the model name; you don't need to find a model your gateway serves for this test. A `401` means the credential was rejected: if you guessed the variable, switch to the other one and re-export.
from line 229
235229* TypeScript: the spawned process inherits the parent environment by default, but setting `options.env` replaces the environment entirely. Spread `process.env` into it to keep your gateway variables.
236230* Python: `ClaudeAgentOptions(env=...)` merges on top of the inherited environment, so gateway variables set in the parent process carry through without spreading.
237231 
238<CodeGroup>
239 ```ts TypeScript theme={null}
240 const result = query({
241 prompt: "...",
242 options: {
243 env: {
244 ...process.env,
245 ANTHROPIC_BASE_URL: "https://llm-gateway.example.com",
246 ANTHROPIC_AUTH_TOKEN: process.env.GATEWAY_KEY,
247 },
232```ts TypeScript theme={null}
233const result = query({
234 prompt: "...",
235 options: {
236 env: {
237 ...process.env,
238 ANTHROPIC_BASE_URL: "https://llm-gateway.example.com",
239 ANTHROPIC_AUTH_TOKEN: process.env.GATEWAY_KEY,
248240 },
249 })
250 ```
241 },
242})
243```
251244 
252 ```python Python theme={null}
253 options = ClaudeAgentOptions(
254 env={
255 "ANTHROPIC_BASE_URL": "https://llm-gateway.example.com",
256 "ANTHROPIC_AUTH_TOKEN": os.environ["GATEWAY_KEY"],
257 }
258 )
259 ```
260</CodeGroup>
245```python Python theme={null}
246options = ClaudeAgentOptions(
247 env={
248 "ANTHROPIC_BASE_URL": "https://llm-gateway.example.com",
249 "ANTHROPIC_AUTH_TOKEN": os.environ["GATEWAY_KEY"],
250 }
251)
252```
261253 
262254### Slack, cloud sessions, and Remote Control
263255 
from line 270
278270 
279271Some gateways route or tag requests using a custom header in addition to the credential, for example a tenant identifier or a routing key. To send one, set [`ANTHROPIC_CUSTOM_HEADERS`](/docs/en/env-vars) with one `Name: Value` pair per line. The example below adds a routing header named `X-Org-Route`:
280272 
281<Tabs>
282 <Tab title="Bash or Zsh">
283 ```bash theme={null}
284 export ANTHROPIC_CUSTOM_HEADERS="X-Org-Route: prod"
285 ```
286 </Tab>
273**Bash or Zsh**
287274 
288 <Tab title="PowerShell">
289 ```powershell theme={null}
290 $env:ANTHROPIC_CUSTOM_HEADERS = "X-Org-Route: prod"
291 ```
292 </Tab>
293</Tabs>
275```bash theme={null}
276export ANTHROPIC_CUSTOM_HEADERS="X-Org-Route: prod"
277```
294278 
279**PowerShell**
280 
281```powershell theme={null}
282$env:ANTHROPIC_CUSTOM_HEADERS = "X-Org-Route: prod"
283```
284 
295285You can also set `ANTHROPIC_CUSTOM_HEADERS` in the `env` block of a settings file. Use `\n` between pairs there, since JSON strings can't span multiple lines:
296286 
297287```json theme={null}
from line 314
324314 
325315The helper is any shell command that prints the current credential to stdout. Claude Code runs it through your system shell, so on Windows it can be an executable or a PowerShell invocation. Make the command print nothing but the credential. On Claude Code v2.1.227 or later, a banner or a log line printed alongside the key makes the [helper fail](/docs/en/errors#your-apikeyhelper-script-is-failing). Write the script, make it executable, and reference it from `apiKeyHelper` in your [settings file](/docs/en/settings):
326316 
327<Tabs>
328 <Tab title="Bash or Zsh">
329 For example, a script that reads from a vault:
317**Bash or Zsh**
330318 
331 ```bash theme={null}
332 #!/bin/bash
333 vault kv get -field=api_key secret/llm-gateway/claude-code
334 ```
319For example, a script that reads from a vault:
335320 
336 Reference its path in `~/.claude/settings.json`:
321```bash theme={null}
322#!/bin/bash
323vault kv get -field=api_key secret/llm-gateway/claude-code
324```
337325 
338 ```json theme={null}
339 {
340 "apiKeyHelper": "~/bin/get-gateway-key.sh"
341 }
342 ```
343 </Tab>
326Reference its path in `~/.claude/settings.json`:
344327 
345 <Tab title="PowerShell">
346 For example, a script that reads from a vault:
328```json theme={null}
329{
330 "apiKeyHelper": "~/bin/get-gateway-key.sh"
331}
332```
347333 
348 ```powershell theme={null}
349 vault kv get -field=api_key secret/llm-gateway/claude-code
350 ```
334**PowerShell**
351335 
352 Reference the PowerShell invocation in `%USERPROFILE%\.claude\settings.json`, escaping the backslashes in the JSON string:
336For example, a script that reads from a vault:
353337 
354 ```json theme={null}
355 {
356 "apiKeyHelper": "powershell -NoProfile -File C:\\scripts\\get-gateway-key.ps1"
357 }
358 ```
359 </Tab>
360</Tabs>
338```powershell theme={null}
339vault kv get -field=api_key secret/llm-gateway/claude-code
340```
361341 
342Reference the PowerShell invocation in `%USERPROFILE%\.claude\settings.json`, escaping the backslashes in the JSON string:
343 
344```json theme={null}
345{
346 "apiKeyHelper": "powershell -NoProfile -File C:\\scripts\\get-gateway-key.ps1"
347}
348```
349 
362350Claude Code caches the helper's output for five minutes by default and re-runs the helper after the cache lifetime elapses. To change the lifetime, set `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` in milliseconds, for example `CLAUDE_CODE_API_KEY_HELPER_TTL_MS=900000` for 15 minutes.
363351 
364352See [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) for the other cases in which Claude Code re-runs the helper.
from line 361
373361 
374362To turn that traffic off, set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` alongside the gateway variables, in the same shell exports or settings-file `env` block:
375363 
376<Tabs>
377 <Tab title="Bash or Zsh">
378 ```bash theme={null}
379 export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
380 ```
381 </Tab>
364**Bash or Zsh**
382365 
383 <Tab title="PowerShell">
384 ```powershell theme={null}
385 $env:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1"
386 ```
387 </Tab>
388</Tabs>
366```bash theme={null}
367export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
368```
389369 
370**PowerShell**
371 
372```powershell theme={null}
373$env:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1"
374```
375 
390376Setting the variable has these effects and limits:
391377 
392378* It disables auto-updates, so plan for another update path, such as your package manager or managed distribution.
from line 396
410396 
411397Leave `AWS_BEARER_TOKEN_BEDROCK` unset when the gateway issues its own credential. If you set it, Claude Code sends that [Amazon Bedrock API key](/docs/en/amazon-bedrock#2-configure-aws-credentials) as the `Authorization` header instead of your gateway token, even with `CLAUDE_CODE_SKIP_BEDROCK_AUTH` set.
412398 
413<Tabs>
414 <Tab title="Bash or Zsh">
415 ```bash theme={null}
416 export ANTHROPIC_BEDROCK_BASE_URL=https://llm-gateway.example.com/bedrock
417 export CLAUDE_CODE_SKIP_BEDROCK_AUTH=1
418 export CLAUDE_CODE_USE_BEDROCK=1
419 ```
420 </Tab>
399**Bash or Zsh**
421400 
422 <Tab title="PowerShell">
423 ```powershell theme={null}
424 $env:ANTHROPIC_BEDROCK_BASE_URL = "https://llm-gateway.example.com/bedrock"
425 $env:CLAUDE_CODE_SKIP_BEDROCK_AUTH = "1"
426 $env:CLAUDE_CODE_USE_BEDROCK = "1"
427 ```
428 </Tab>
429</Tabs>
401```bash theme={null}
402export ANTHROPIC_BEDROCK_BASE_URL=https://llm-gateway.example.com/bedrock
403export CLAUDE_CODE_SKIP_BEDROCK_AUTH=1
404export CLAUDE_CODE_USE_BEDROCK=1
405```
430406 
407**PowerShell**
408 
409```powershell theme={null}
410$env:ANTHROPIC_BEDROCK_BASE_URL = "https://llm-gateway.example.com/bedrock"
411$env:CLAUDE_CODE_SKIP_BEDROCK_AUTH = "1"
412$env:CLAUDE_CODE_USE_BEDROCK = "1"
413```
414 
431415#### Google Cloud's Agent Platform
432416 
433417Replace the project ID and region with your own values. Claude Code includes both in the path of each request it sends to the gateway:
434418 
435<Tabs>
436 <Tab title="Bash or Zsh">
437 ```bash theme={null}
438 export ANTHROPIC_VERTEX_BASE_URL=https://llm-gateway.example.com/vertex
439 export ANTHROPIC_VERTEX_PROJECT_ID=your-gcp-project-id
440 export CLAUDE_CODE_SKIP_VERTEX_AUTH=1
441 export CLAUDE_CODE_USE_VERTEX=1
442 export CLOUD_ML_REGION=us-east5
443 ```
444 </Tab>
419**Bash or Zsh**
445420 
446 <Tab title="PowerShell">
447 ```powershell theme={null}
448 $env:ANTHROPIC_VERTEX_BASE_URL = "https://llm-gateway.example.com/vertex"
449 $env:ANTHROPIC_VERTEX_PROJECT_ID = "your-gcp-project-id"
450 $env:CLAUDE_CODE_SKIP_VERTEX_AUTH = "1"
451 $env:CLAUDE_CODE_USE_VERTEX = "1"
452 $env:CLOUD_ML_REGION = "us-east5"
453 ```
454 </Tab>
455</Tabs>
421```bash theme={null}
422export ANTHROPIC_VERTEX_BASE_URL=https://llm-gateway.example.com/vertex
423export ANTHROPIC_VERTEX_PROJECT_ID=your-gcp-project-id
424export CLAUDE_CODE_SKIP_VERTEX_AUTH=1
425export CLAUDE_CODE_USE_VERTEX=1
426export CLOUD_ML_REGION=us-east5
427```
456428 
429**PowerShell**
430 
431```powershell theme={null}
432$env:ANTHROPIC_VERTEX_BASE_URL = "https://llm-gateway.example.com/vertex"
433$env:ANTHROPIC_VERTEX_PROJECT_ID = "your-gcp-project-id"
434$env:CLAUDE_CODE_SKIP_VERTEX_AUTH = "1"
435$env:CLAUDE_CODE_USE_VERTEX = "1"
436$env:CLOUD_ML_REGION = "us-east5"
437```
438 
457439The block covers routing and authentication. The region overrides and model pins from the [Agent Platform setup](/docs/en/google-vertex-ai#4-configure-claude-code) apply through a gateway as well:
458440 
459441* **Per-model regions**: if your gateway serves some models from a region other than `CLOUD_ML_REGION`, set the matching `VERTEX_REGION_CLAUDE_*` variable for each, for example `VERTEX_REGION_CLAUDE_4_6_SONNET=europe-west1`. The [environment variables reference](/docs/en/env-vars) lists the exact names.
from line 448
466448 
467449For a gateway that injects its own `Authorization` header, set `CLAUDE_CODE_SKIP_FOUNDRY_AUTH=1` and leave both credential variables unset. Claude Code then sends requests without an Azure credential and preserves the `Authorization` header you supply, for example through `ANTHROPIC_CUSTOM_HEADERS`.
468450 
469<Tabs>
470 <Tab title="Bash or Zsh">
471 ```bash theme={null}
472 export ANTHROPIC_FOUNDRY_BASE_URL=https://llm-gateway.example.com/foundry
473 export ANTHROPIC_FOUNDRY_API_KEY=sk-gateway-key
474 export CLAUDE_CODE_USE_FOUNDRY=1
475 ```
476 </Tab>
451**Bash or Zsh**
477452 
478 <Tab title="PowerShell">
479 ```powershell theme={null}
480 $env:ANTHROPIC_FOUNDRY_BASE_URL = "https://llm-gateway.example.com/foundry"
481 $env:ANTHROPIC_FOUNDRY_API_KEY = "sk-gateway-key"
482 $env:CLAUDE_CODE_USE_FOUNDRY = "1"
483 ```
484 </Tab>
485</Tabs>
453```bash theme={null}
454export ANTHROPIC_FOUNDRY_BASE_URL=https://llm-gateway.example.com/foundry
455export ANTHROPIC_FOUNDRY_API_KEY=sk-gateway-key
456export CLAUDE_CODE_USE_FOUNDRY=1
457```
486458 
459**PowerShell**
460 
461```powershell theme={null}
462$env:ANTHROPIC_FOUNDRY_BASE_URL = "https://llm-gateway.example.com/foundry"
463$env:ANTHROPIC_FOUNDRY_API_KEY = "sk-gateway-key"
464$env:CLAUDE_CODE_USE_FOUNDRY = "1"
465```
466 
487467#### Claude Platform on AWS
488468 
489469See [Claude Platform on AWS](/docs/en/claude-platform-on-aws) for the workspace ID.
490470 
491<Tabs>
492 <Tab title="Bash or Zsh">
493 ```bash theme={null}
494 export ANTHROPIC_AWS_BASE_URL=https://llm-gateway.example.com/anthropic-aws
495 export ANTHROPIC_AWS_WORKSPACE_ID=wrkspc_01ABCDEFGHIJKLMN
496 export CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH=1
497 export CLAUDE_CODE_USE_ANTHROPIC_AWS=1
498 ```
499 </Tab>
471**Bash or Zsh**
500472 
501 <Tab title="PowerShell">
502 ```powershell theme={null}
503 $env:ANTHROPIC_AWS_BASE_URL = "https://llm-gateway.example.com/anthropic-aws"
504 $env:ANTHROPIC_AWS_WORKSPACE_ID = "wrkspc_01ABCDEFGHIJKLMN"
505 $env:CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH = "1"
506 $env:CLAUDE_CODE_USE_ANTHROPIC_AWS = "1"
507 ```
508 </Tab>
509</Tabs>
473```bash theme={null}
474export ANTHROPIC_AWS_BASE_URL=https://llm-gateway.example.com/anthropic-aws
475export ANTHROPIC_AWS_WORKSPACE_ID=wrkspc_01ABCDEFGHIJKLMN
476export CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH=1
477export CLAUDE_CODE_USE_ANTHROPIC_AWS=1
478```
479 
480**PowerShell**
481 
482```powershell theme={null}
483$env:ANTHROPIC_AWS_BASE_URL = "https://llm-gateway.example.com/anthropic-aws"
484$env:ANTHROPIC_AWS_WORKSPACE_ID = "wrkspc_01ABCDEFGHIJKLMN"
485$env:CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH = "1"
486$env:CLAUDE_CODE_USE_ANTHROPIC_AWS = "1"
487```
510488 
511489#### Confirm the provider route
512490 

llm-gateway-protocol Changed · +4 / -4 lines

from line 6
66 
77The [Claude apps gateway](/docs/en/claude-apps-gateway), Anthropic's self-hosted gateway, serves its own endpoint reference at `GET /protocol`, covering that gateway's sign-in, inference, managed settings, model discovery, and telemetry endpoints. It is a separate document from this guide.
88 
9<Note>
10 * To roll out an existing or third-party gateway for your organization, see [Roll out an LLM gateway](/docs/en/llm-gateway-rollout)
11 * If you're an individual developer authenticating Claude Code to a gateway with a credential you were given, see [Connect Claude Code to an LLM gateway](/docs/en/llm-gateway-connect)
12</Note>
9> [!NOTE]
10>
11> * To roll out an existing or third-party gateway for your organization, see [Roll out an LLM gateway](/docs/en/llm-gateway-rollout)
12> * If you're an individual developer authenticating Claude Code to a gateway with a credential you were given, see [Connect Claude Code to an LLM gateway](/docs/en/llm-gateway-connect)
1313 
1414This page covers:
1515 

llm-gateway-rollout Changed · +76 / -84 lines

from line 4
44 
55This page walks an administrator through rolling out an LLM gateway for Claude Code. It assumes you have a gateway product deployed that meets the [gateway requirements](#gateway-requirements). Deploying or operating any specific product isn't covered here; deploy yours following its vendor's documentation.
66 
7<Note>
8 * To connect Claude Code on your own machine to an existing gateway, see [Connect Claude Code to an LLM gateway](/docs/en/llm-gateway-connect)
9 * For what Claude Code sends to a gateway and what to forward, see the [gateway compatibility guide](/docs/en/llm-gateway-protocol)
10</Note>
7> [!NOTE]
8>
9> * To connect Claude Code on your own machine to an existing gateway, see [Connect Claude Code to an LLM gateway](/docs/en/llm-gateway-connect)
10> * For what Claude Code sends to a gateway and what to forward, see the [gateway compatibility guide](/docs/en/llm-gateway-protocol)
1111 
1212## Prerequisites
1313 
from line 58
5858* `<gateway-key>` is whatever credential lets you call the gateway right now: an administrative key, a test key, or your own developer key if you've already issued one. Not every gateway product has a separate admin credential; if yours doesn't, issue yourself a developer key in [Issue developer credentials](#issue-developer-credentials) first
5959* `model` is a Claude model name your gateway is configured to route. The example uses `claude-sonnet-4-6`; substitute a name you've configured
6060 
61<Tabs>
62 <Tab title="Bash or Zsh">
63 ```bash theme={null}
64 curl -X POST "https://llm-gateway.example.com/v1/messages" \
65 -H "Authorization: Bearer <gateway-key>" \
66 -H "anthropic-version: 2023-06-01" \
67 -H "content-type: application/json" \
68 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
69 ```
70 </Tab>
61**Bash or Zsh**
7162 
72 <Tab title="PowerShell">
73 ```powershell theme={null}
74 Invoke-RestMethod -Method Post -Uri "https://llm-gateway.example.com/v1/messages" `
75 -Headers @{ "Authorization" = "Bearer <gateway-key>"; "anthropic-version" = "2023-06-01" } `
76 -ContentType "application/json" `
77 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
78 ```
79 </Tab>
80</Tabs>
63```bash theme={null}
64curl -X POST "https://llm-gateway.example.com/v1/messages" \
65 -H "Authorization: Bearer <gateway-key>" \
66 -H "anthropic-version: 2023-06-01" \
67 -H "content-type: application/json" \
68 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
69```
8170 
71**PowerShell**
72 
73```powershell theme={null}
74Invoke-RestMethod -Method Post -Uri "https://llm-gateway.example.com/v1/messages" `
75 -Headers @{ "Authorization" = "Bearer <gateway-key>"; "anthropic-version" = "2023-06-01" } `
76 -ContentType "application/json" `
77 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
78```
79 
8280**Checkpoint**: a `200` with a `content` field means the gateway reached the provider with that model name. A `404` means that name isn't routed at the gateway; a `401` from the provider means the gateway's provider credential is wrong.
8381 
8482Repeat the request once per Claude model name in your gateway's routing configuration. A name the gateway doesn't route returns `404` to any developer who selects it, so test every name before rollout.
8583 
86<Note>
87 Avoid serving the gateway behind a redirect. A redirect can drop the request body or strip the credential header on inference requests, and [model discovery](/docs/en/llm-gateway-protocol#model-discovery) treats any redirect as a failure so the credential cannot leak to a redirect target.
88</Note>
84> [!NOTE]
85>
86> Avoid serving the gateway behind a redirect. A redirect can drop the request body or strip the credential header on inference requests, and [model discovery](/docs/en/llm-gateway-protocol#model-discovery) treats any redirect as a failure so the credential cannot leak to a redirect target.
8987 
9088### Issue developer credentials
9189 
from line 91
9391 
9492Confirm a freshly issued key works against the gateway with the same request as [Confirm the gateway routes your models](#confirm-the-gateway-routes-your-models), replacing `<gateway-key>` with the new `<developer-key>`:
9593 
96<Tabs>
97 <Tab title="Bash or Zsh">
98 ```bash theme={null}
99 curl -X POST "https://llm-gateway.example.com/v1/messages" \
100 -H "Authorization: Bearer <developer-key>" \
101 -H "anthropic-version: 2023-06-01" \
102 -H "content-type: application/json" \
103 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
104 ```
105 </Tab>
94**Bash or Zsh**
10695 
107 <Tab title="PowerShell">
108 ```powershell theme={null}
109 Invoke-RestMethod -Method Post -Uri "https://llm-gateway.example.com/v1/messages" `
110 -Headers @{ "Authorization" = "Bearer <developer-key>"; "anthropic-version" = "2023-06-01" } `
111 -ContentType "application/json" `
112 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
113 ```
114 </Tab>
115</Tabs>
96```bash theme={null}
97curl -X POST "https://llm-gateway.example.com/v1/messages" \
98 -H "Authorization: Bearer <developer-key>" \
99 -H "anthropic-version: 2023-06-01" \
100 -H "content-type: application/json" \
101 -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
102```
116103 
104**PowerShell**
105 
106```powershell theme={null}
107Invoke-RestMethod -Method Post -Uri "https://llm-gateway.example.com/v1/messages" `
108 -Headers @{ "Authorization" = "Bearer <developer-key>"; "anthropic-version" = "2023-06-01" } `
109 -ContentType "application/json" `
110 -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'
111```
112 
117113**Checkpoint**: a `200` with a `content` field means the developer key reaches the gateway and the gateway forwards it. A `401` here, when [the previous step](#confirm-the-gateway-routes-your-models) succeeded, means the developer key is wrong or hasn't taken effect at the gateway yet.
118114 
119115Issuing one key per developer rather than a shared key is what makes per-developer usage attribution and individual offboarding work. The environment variable that holds the key depends on which header the gateway reads. For a gateway that checks credentials in the `Authorization: Bearer` header, developers set their key in `ANTHROPIC_AUTH_TOKEN`. For a gateway that reads keys from the `x-api-key` header, developers set `ANTHROPIC_API_KEY` instead; the [credential table](/docs/en/llm-gateway-connect#set-the-credential-variable) covers the mapping.
from line 118
122118 
123119Run Claude Code through the gateway yourself before distributing anything, using the same configuration the rollout will deliver fleet-wide. Type these directly in a terminal, not in a `.env` or settings file; they last only for this terminal session, so closing it returns your machine to its normal configuration. Use `ANTHROPIC_API_KEY` instead of `ANTHROPIC_AUTH_TOKEN` if your gateway reads the `x-api-key` header:
124120 
125<Tabs>
126 <Tab title="Bash or Zsh">
127 ```bash theme={null}
128 export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
129 export ANTHROPIC_AUTH_TOKEN="<developer-key>"
130 ```
131 </Tab>
121**Bash or Zsh**
132122 
133 <Tab title="PowerShell">
134 ```powershell theme={null}
135 $env:ANTHROPIC_BASE_URL = "https://llm-gateway.example.com"
136 $env:ANTHROPIC_AUTH_TOKEN = "<developer-key>"
137 ```
138 </Tab>
139</Tabs>
123```bash theme={null}
124export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
125export ANTHROPIC_AUTH_TOKEN="<developer-key>"
126```
140127 
128**PowerShell**
129 
130```powershell theme={null}
131$env:ANTHROPIC_BASE_URL = "https://llm-gateway.example.com"
132$env:ANTHROPIC_AUTH_TOKEN = "<developer-key>"
133```
134 
141135Then send a one-shot prompt through the gateway:
142136 
143137```bash theme={null}
from line 220
226220 
227221Confirm everything works from a developer machine, not the gateway host, so the test covers the network path developers use. Send a streaming request, which checks the endpoint, streaming pass-through, and model routing at once:
228222 
229<Tabs>
230 <Tab title="Bash or Zsh">
231 ```bash theme={null}
232 curl -N -X POST "https://llm-gateway.example.com/v1/messages" \
233 -H "Authorization: Bearer <developer-key>" \
234 -H "anthropic-version: 2023-06-01" \
235 -H "content-type: application/json" \
236 -d '{"model": "claude-sonnet-4-6", "max_tokens": 16, "stream": true, "messages": [{"role": "user", "content": "count to 3"}]}'
237 ```
238 </Tab>
223**Bash or Zsh**
239224 
240 <Tab title="PowerShell">
241 ```powershell theme={null}
242 $body = '{"model": "claude-sonnet-4-6", "max_tokens": 16, "stream": true, "messages": [{"role": "user", "content": "count to 3"}]}'
243 $body | curl.exe -N -X POST "https://llm-gateway.example.com/v1/messages" `
244 -H "Authorization: Bearer <developer-key>" `
245 -H "anthropic-version: 2023-06-01" `
246 -H "content-type: application/json" `
247 --data-binary '@-'
248 ```
249 </Tab>
250</Tabs>
225```bash theme={null}
226curl -N -X POST "https://llm-gateway.example.com/v1/messages" \
227 -H "Authorization: Bearer <developer-key>" \
228 -H "anthropic-version: 2023-06-01" \
229 -H "content-type: application/json" \
230 -d '{"model": "claude-sonnet-4-6", "max_tokens": 16, "stream": true, "messages": [{"role": "user", "content": "count to 3"}]}'
231```
232 
233**PowerShell**
234 
235```powershell theme={null}
236$body = '{"model": "claude-sonnet-4-6", "max_tokens": 16, "stream": true, "messages": [{"role": "user", "content": "count to 3"}]}'
237$body | curl.exe -N -X POST "https://llm-gateway.example.com/v1/messages" `
238 -H "Authorization: Bearer <developer-key>" `
239 -H "anthropic-version: 2023-06-01" `
240 -H "content-type: application/json" `
241 --data-binary '@-'
242```
251243 
252244You should see `data:` lines arrive incrementally. The whole response arriving at once after a pause means the gateway is buffering, which stalls Claude Code; a `404` means the model name isn't routed. Repeat per model name.
253245 

managed-mcp Changed · +103 / -105 lines

#### Environment variables in `serverCommand` and `serverUrl` entries

from line 15
1515* [Tell users what to expect](#how-restrictions-appear-to-users) when a restriction blocks a server
1616* [Monitor which servers your organization actually uses](#monitor-mcp-usage)
1717 
18<Note>
19 The [Security](/docs/en/security) page covers the MCP threat model and how to evaluate a server before approving it. [Decide what to enforce](/docs/en/admin-setup#decide-what-to-enforce) covers MCP restrictions alongside the other administrative controls.
20</Note>
18> [!NOTE]
19>
20> The [Security](/docs/en/security) page covers the MCP threat model and how to evaluate a server before approving it. [Decide what to enforce](/docs/en/admin-setup#decide-what-to-enforce) covers MCP restrictions alongside the other administrative controls.
2121 
2222## Choose a pattern
2323 
from line 34
3434| **Denylist only** | Block known-bad servers, allow everything else | `deniedMcpServers` |
3535| **No restrictions** | Users add anything | Don't deploy any managed MCP configuration |
3636 
37<Note>
38 Claude Code doesn't have a built-in MCP server registry that users can browse and install from. For the approved-catalog pattern, share the approved list and its `claude mcp add` commands somewhere your users will find them, such as an internal wiki, or distribute the servers as plugins through a [managed plugin marketplace](/docs/en/plugins/org#restrict-what-users-can-install) so users can browse and install them from `/plugin`.
39</Note>
37> [!NOTE]
38>
39> Claude Code doesn't have a built-in MCP server registry that users can browse and install from. For the approved-catalog pattern, share the approved list and its `claude mcp add` commands somewhere your users will find them, such as an internal wiki, or distribute the servers as plugins through a [managed plugin marketplace](/docs/en/plugins/org#restrict-what-users-can-install) so users can browse and install them from `/plugin`.
4040 
4141## Exclusive control with managed-mcp.json
4242 
from line 254
254254 
255255Without `allowManagedMcpServersOnly`, allowlists from every settings scope merge, including a user's own `~/.claude/settings.json`, so a user can broaden what your allowlist permits. Denylists merge from every scope regardless.
256256 
257<Note>
258 `allowManagedMcpServersOnly` is separate from `allowManagedPermissionRulesOnly`, which locks down [permission rules](/docs/en/permissions#managed-settings) only. Setting that flag does not enforce the MCP allowlist.
259</Note>
257> [!NOTE]
258>
259> `allowManagedMcpServersOnly` is separate from `allowManagedPermissionRulesOnly`, which locks down [permission rules](/docs/en/permissions#managed-settings) only. Setting that flag does not enforce the MCP allowlist.
260260 
261261### Match servers by URL, command, or name
262262 
from line 281
281281 
282282A `serverName` entry matches the user-assigned label exactly, with no wildcards.
283283 
284<Warning>
285 A `serverName` entry, in either list, is not a security control. The name is the label a user assigns when running `claude mcp add` or editing a config file, not the underlying server, so a user can call any server `github`. For claude.ai connectors the name is the display name returned by claude.ai, which can change. To enforce which servers actually run, add `serverCommand` or `serverUrl` entries.
286</Warning>
284> [!WARNING]
285>
286> A `serverName` entry, in either list, is not a security control. The name is the label a user assigns when running `claude mcp add` or editing a config file, not the underlying server, so a user can call any server `github`. For claude.ai connectors the name is the display name returned by claude.ai, which can change. To enforce which servers actually run, add `serverCommand` or `serverUrl` entries.
287287 
288288The `serverName` validation differs between the two lists:
289289 
from line 324
324324* `https://staging.example.com:*/*`: blocks `https` servers on that host on every port
325325* `*://staging.example.com:*/*`: blocks that host over any scheme and on any port
326326 
327<h4 id="how-policy-entries-expand">
328 Environment variables in `serverCommand` and `serverUrl` entries
329</h4>
327#### Environment variables in `serverCommand` and `serverUrl` entries
330328 
331329`serverCommand` and `serverUrl` values expand before matching. Both the policy entry and the server's configured value go through [`${VAR}` and `${VAR:-default}` expansion](/docs/en/mcp#environment-variable-expansion-in-mcp-json), so an entry written as `["${HOME}/bin/server"]` matches a server config that uses either the same reference or the expanded path. `serverName` values match literally and never expand.
332330 
from line 399
401399 
402400The accordions below walk through how a server is evaluated against other allowlist and denylist combinations.
403401 
404<Accordion title="URL-only allowlist">
405 ```json theme={null}
406 {
407 "allowedMcpServers": [
408 { "serverUrl": "https://mcp.example.com/*" },
409 { "serverUrl": "https://*.internal.example.com/*" }
410 ]
411 }
412 ```
402> **URL-only allowlist**
403>
404> ```json theme={null}
405> {
406> "allowedMcpServers": [
407> { "serverUrl": "https://mcp.example.com/*" },
408> { "serverUrl": "https://*.internal.example.com/*" }
409> ]
410> }
411> ```
412>
413> | Server | Result |
414> | :- | :- |
415> | HTTP server at `https://mcp.example.com/api` | Allowed: matches URL pattern |
416> | HTTP server at `https://api.internal.example.com/mcp` | Allowed: matches wildcard subdomain |
417> | HTTP server at `https://external.example.com/mcp` | Blocked: doesn't match any URL pattern |
418> | Stdio server with any command | Blocked: no name or command entries to match |
413419 
414 | Server | Result |
415 | :- | :- |
416 | HTTP server at `https://mcp.example.com/api` | Allowed: matches URL pattern |
417 | HTTP server at `https://api.internal.example.com/mcp` | Allowed: matches wildcard subdomain |
418 | HTTP server at `https://external.example.com/mcp` | Blocked: doesn't match any URL pattern |
419 | Stdio server with any command | Blocked: no name or command entries to match |
420</Accordion>
420> **Command-only allowlist**
421>
422> ```json theme={null}
423> {
424> "allowedMcpServers": [
425> { "serverCommand": ["npx", "-y", "approved-package"] }
426> ]
427> }
428> ```
429>
430> | Server | Result |
431> | :- | :- |
432> | Stdio server with `["npx", "-y", "approved-package"]` | Allowed: matches command |
433> | Stdio server with `["node", "server.js"]` | Blocked: doesn't match command |
434> | HTTP server named `my-api` | Blocked: no name entries to match |
421435 
422<Accordion title="Command-only allowlist">
423 ```json theme={null}
424 {
425 "allowedMcpServers": [
426 { "serverCommand": ["npx", "-y", "approved-package"] }
427 ]
428 }
429 ```
436> **Mixed name and command allowlist**
437>
438> ```json theme={null}
439> {
440> "allowedMcpServers": [
441> { "serverName": "github" },
442> { "serverCommand": ["npx", "-y", "approved-package"] }
443> ]
444> }
445> ```
446>
447> | Server | Result |
448> | :- | :- |
449> | Stdio server named `local-tool` with `["npx", "-y", "approved-package"]` | Allowed: matches command |
450> | Stdio server named `local-tool` with `["node", "server.js"]` | Blocked: command entries exist but doesn't match |
451> | Stdio server named `github` with `["node", "server.js"]` | Blocked: stdio servers must match commands when command entries exist |
452> | HTTP server named `github` | Allowed: matches name |
453> | HTTP server named `other-api` | Blocked: name doesn't match |
430454 
431 | Server | Result |
432 | :- | :- |
433 | Stdio server with `["npx", "-y", "approved-package"]` | Allowed: matches command |
434 | Stdio server with `["node", "server.js"]` | Blocked: doesn't match command |
435 | HTTP server named `my-api` | Blocked: no name entries to match |
436</Accordion>
455> **Name-only allowlist**
456>
457> ```json theme={null}
458> {
459> "allowedMcpServers": [
460> { "serverName": "github" },
461> { "serverName": "internal-tool" }
462> ]
463> }
464> ```
465>
466> | Server | Result |
467> | :- | :- |
468> | Stdio server named `github` with any command | Allowed: no command restrictions |
469> | Stdio server named `internal-tool` with any command | Allowed: no command restrictions |
470> | HTTP server named `github` | Allowed: matches name |
471> | Any server named `other` | Blocked: name doesn't match |
437472 
438<Accordion title="Mixed name and command allowlist">
439 ```json theme={null}
440 {
441 "allowedMcpServers": [
442 { "serverName": "github" },
443 { "serverCommand": ["npx", "-y", "approved-package"] }
444 ]
445 }
446 ```
447 
448 | Server | Result |
449 | :- | :- |
450 | Stdio server named `local-tool` with `["npx", "-y", "approved-package"]` | Allowed: matches command |
451 | Stdio server named `local-tool` with `["node", "server.js"]` | Blocked: command entries exist but doesn't match |
452 | Stdio server named `github` with `["node", "server.js"]` | Blocked: stdio servers must match commands when command entries exist |
453 | HTTP server named `github` | Allowed: matches name |
454 | HTTP server named `other-api` | Blocked: name doesn't match |
455</Accordion>
456 
457<Accordion title="Name-only allowlist">
458 ```json theme={null}
459 {
460 "allowedMcpServers": [
461 { "serverName": "github" },
462 { "serverName": "internal-tool" }
463 ]
464 }
465 ```
466 
467 | Server | Result |
468 | :- | :- |
469 | Stdio server named `github` with any command | Allowed: no command restrictions |
470 | Stdio server named `internal-tool` with any command | Allowed: no command restrictions |
471 | HTTP server named `github` | Allowed: matches name |
472 | Any server named `other` | Blocked: name doesn't match |
473</Accordion>
474 
475<Accordion title="Allowlist with denylist override">
476 ```json theme={null}
477 {
478 "allowedMcpServers": [
479 { "serverUrl": "https://*.example.com/*" }
480 ],
481 "deniedMcpServers": [
482 { "serverUrl": "https://staging.example.com/*" }
483 ]
484 }
485 ```
486 
487 | Server | Result |
488 | :- | :- |
489 | HTTP server at `https://mcp.example.com/api` | Allowed: matches allowlist URL pattern, no denylist match |
490 | HTTP server at `https://staging.example.com/api` | Blocked: matches both, but the denylist takes precedence |
491 | HTTP server at `https://staging.example.com:8443/api` | Allowed: matches allowlist URL pattern, [no denylist match on this port](#how-serverurl-entries-match) |
492 | HTTP server at `https://other.com/mcp` | Blocked: doesn't match the allowlist |
493</Accordion>
473> **Allowlist with denylist override**
474>
475> ```json theme={null}
476> {
477> "allowedMcpServers": [
478> { "serverUrl": "https://*.example.com/*" }
479> ],
480> "deniedMcpServers": [
481> { "serverUrl": "https://staging.example.com/*" }
482> ]
483> }
484> ```
485>
486> | Server | Result |
487> | :- | :- |
488> | HTTP server at `https://mcp.example.com/api` | Allowed: matches allowlist URL pattern, no denylist match |
489> | HTTP server at `https://staging.example.com/api` | Blocked: matches both, but the denylist takes precedence |
490> | HTTP server at `https://staging.example.com:8443/api` | Allowed: matches allowlist URL pattern, [no denylist match on this port](#how-serverurl-entries-match) |
491> | HTTP server at `https://other.com/mcp` | Blocked: doesn't match the allowlist |
494492 
495493### Restrict the allowlist to managed settings only
496494 

managed-settings Changed · +40 / -70 lines

### When an admin document counts as present

from line 10
1010 
1111This is the quickest way to put a policy on each machine: a `managed-settings.json` file. If you haven't picked how to deliver managed settings yet, or your devices are under MDM or developers run cloud sessions, read [Choose a delivery mechanism](#choose-a-delivery-mechanism) first.
1212 
13<Steps>
14 <Step title="Write managed-settings.json">
15 Write a `managed-settings.json` that holds the keys you've decided to enforce, in the same JSON shape as `settings.json`. The [Decide what to enforce](/docs/en/admin-setup#decide-what-to-enforce) table lists the keys behind each control, and each entry in the [settings reference](/docs/en/settings-reference) says whether a managed source can set it. This file blocks two file reads, turns off bypass mode, and makes Claude Code ignore permission rules from user, project, and local files and from `--allowedTools`:
13**1. Write managed-settings.json**
1614 
17 ```json managed-settings.json theme={null}
18 {
19 "permissions": {
20 "deny": [
21 "Read(./.env)",
22 "Read(./secrets/**)"
23 ],
24 "disableBypassPermissionsMode": "disable"
25 },
26 "allowManagedPermissionRulesOnly": true
27 }
28 ```
15Write a `managed-settings.json` that holds the keys you've decided to enforce, in the same JSON shape as `settings.json`. The [Decide what to enforce](/docs/en/admin-setup#decide-what-to-enforce) table lists the keys behind each control, and each entry in the [settings reference](/docs/en/settings-reference) says whether a managed source can set it. This file blocks two file reads, turns off bypass mode, and makes Claude Code ignore permission rules from user, project, and local files and from `--allowedTools`:
2916 
30 For a fuller example that shows the shape of more managed keys, including the login method, models, MCP servers, and marketplaces, see [An organization's managed settings](/docs/en/settings-example#an-organizations-managed-settings).
31 </Step>
17```json managed-settings.json theme={null}
18{
19 "permissions": {
20 "deny": [
21 "Read(./.env)",
22 "Read(./secrets/**)"
23 ],
24 "disableBypassPermissionsMode": "disable"
25 },
26 "allowManagedPermissionRulesOnly": true
27}
28```
3229 
33 <Step title="Place the file on each machine">
34 Save the file as `managed-settings.json` in the system directory for the operating system, using whatever tooling already places files on your fleet:
30For a fuller example that shows the shape of more managed keys, including the login method, models, MCP servers, and marketplaces, see [An organization's managed settings](/docs/en/settings-example#an-organizations-managed-settings).
3531 
36 * **macOS**: `/Library/Application Support/ClaudeCode/managed-settings.json`
37 * **Linux and WSL**: `/etc/claude-code/managed-settings.json`
38 * **Windows**: `C:\Program Files\ClaudeCode\managed-settings.json`
39 </Step>
32**2. Place the file on each machine**
4033 
41 <Step title="Confirm the policy applied">
42 On one machine, run `/status` inside Claude Code. The `Setting sources` line shows `Enterprise managed settings (file)`. Roll out to the rest of the fleet after that; [Check that a policy is in force](#check-that-a-policy-is-in-force) covers what to look at when the line is missing.
43 </Step>
44</Steps>
34Save the file as `managed-settings.json` in the system directory for the operating system, using whatever tooling already places files on your fleet:
4535 
46<span id="managed-settings-delivery" />
36* **macOS**: `/Library/Application Support/ClaudeCode/managed-settings.json`
37* **Linux and WSL**: `/etc/claude-code/managed-settings.json`
38* **Windows**: `C:\Program Files\ClaudeCode\managed-settings.json`
4739 
48<span id="delivery-mechanisms" />
40**3. Confirm the policy applied**
4941 
42On one machine, run `/status` inside Claude Code. The `Setting sources` line shows `Enterprise managed settings (file)`. Roll out to the rest of the fleet after that; [Check that a policy is in force](#check-that-a-policy-is-in-force) covers what to look at when the line is missing.
43 
5044## Choose a delivery mechanism
5145 
5246The file in the steps above is one of four ways to get managed settings onto a machine. Every mechanism carries the same policy keys as a `settings.json` file, so the [settings reference](/docs/en/settings-reference) applies to all of them. A few keys are tied to particular sources, and each entry's Scope line says which:
from line 89
9589* **Changes that need approval**: apart from the [updates that wait for the next launch](/docs/en/server-managed-settings#fetch-and-caching-behavior), a server-managed change to a setting that [needs approval](/docs/en/server-managed-settings#security-approval-dialogs), such as a hook or an `env` variable, waits for the developer to accept the dialog in an interactive session, and applies for the current run in a session an IDE extension or the Agent SDK hosts. Other server-managed changes apply on the next poll.
9690* **Long-lived sessions**: a session left open for weeks can still lag a rollout. [`requiredMinimumVersion`](/docs/en/settings-reference#requiredminimumversion) blocks an outdated binary from starting and doesn't end a session that's already running.
9791 
98<span id="format-the-policy-for-each-platform" />
99 
10092### Where each mechanism stores the policy
10193 
10294The keys are the same everywhere, but each mechanism stores them in a different place and shape:
from line 114
122114* **[`extraKnownMarketplaces`](/docs/en/settings-reference#extraknownmarketplaces) and [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers)**: a later entry with the same name replaces the earlier one whole
123115* **[`modelPicker`](/docs/en/settings-reference#modelpicker)**: the later lineup replaces the earlier one whole
124116 
125<span id="precedence-within-the-managed-tier" />
126 
127<span id="which-managed-source-claude-code-uses" />
128 
129117## How Claude Code combines managed sources
130118 
131119When your organization delivers more than one managed source to the same machine, the [`managedSourcesBehavior`](/docs/en/settings-reference#managedsourcesbehavior) key decides what Claude Code does with the others:
from line 135
147135 
148136This diagram shows the ranking, with examples of the cross-source keys Claude Code reads from the first three sources under either setting:
149137 
150<img src="https://mintcdn.com/claude-code/zuWID2B-Rxm8DEC8/images/managed-source-precedence.svg?fit=max&auto=format&n=zuWID2B-Rxm8DEC8&q=85&s=53f6be49f06eff48e01422c8ae1bc2e6" className="dark:hidden" alt="Diagram showing the four managed settings sources ranked from remote settings at the top through MDM, managed settings files, and the HKCU registry at the bottom. By default the first source with a policy key supplies the policy and the rest are skipped; with managedSourcesBehavior set to merge, every admin source with a policy key contributes, combined by kind of key, and the HKCU registry stays out. A side panel shows that cross-source keys such as the sandbox locks, forceRemoteSettingsRefresh, and the per-variable env merge are read from every admin source, which excludes the HKCU registry." width="680" height="330" data-path="images/managed-source-precedence.svg" />
138![Diagram showing the four managed settings sources ranked from remote settings at the top through MDM, managed settings files, and the HKCU registry at the bottom. By default the first source with a policy key supplies the policy and the rest are skipped; with managedSourcesBehavior set to merge, every admin source with a policy key contributes, combined by kind of key, and the HKCU registry stays out. A side panel shows that cross-source keys such as the sandbox locks, forceRemoteSettingsRefresh, and the per-variable env merge are read from every admin source, which excludes the HKCU registry.](https://mintcdn.com/claude-code/zuWID2B-Rxm8DEC8/images/managed-source-precedence.svg?fit=max\&auto=format\&n=zuWID2B-Rxm8DEC8\&q=85\&s=53f6be49f06eff48e01422c8ae1bc2e6)
151139 
152<img src="https://mintcdn.com/claude-code/zuWID2B-Rxm8DEC8/images/managed-source-precedence-dark.svg?fit=max&auto=format&n=zuWID2B-Rxm8DEC8&q=85&s=ae407a9a08a3d680e80cf1a2af845d71" className="hidden dark:block" alt="Diagram showing the four managed settings sources ranked from remote settings at the top through MDM, managed settings files, and the HKCU registry at the bottom. By default the first source with a policy key supplies the policy and the rest are skipped; with managedSourcesBehavior set to merge, every admin source with a policy key contributes, combined by kind of key, and the HKCU registry stays out. A side panel shows that cross-source keys such as the sandbox locks, forceRemoteSettingsRefresh, and the per-variable env merge are read from every admin source, which excludes the HKCU registry." width="680" height="330" data-path="images/managed-source-precedence-dark.svg" />
140### When an admin document counts as present
153141 
154<h3 id="present-admin-documents">
155 When an admin document counts as present
156</h3>
157 
158142In the [ranking of managed sources](#how-claude-code-combines-managed-sources), Claude Code never applies the user-writable HKCU registry beneath an admin document that is present. A document is present when:
159143 
160144* It sets any policy key to a value other than `null`, even a value Claude Code can't read
from line 207
223207 
224208For which helper runs fail, and what Claude Code does when one does, see [Helper failures](/docs/en/settings-reference#helper-failures).
225209 
226<span id="parent-settings-from-embedding-hosts" />
227 
228<span id="control-policy-from-an-embedding-host" />
229 
230<span id="merge-policy-from-an-embedding-host" />
231 
232210### Let an embedding host add policy
233211 
234212When another application launches Claude Code, such as Claude Desktop, an IDE extension, or an Agent SDK app, that host can pass its own managed settings through the SDK `managedSettings` option. Claude Code calls these parent settings.
from line 259
281259* **The server-managed cache**: server-managed settings come from Anthropic's servers, and an edit to the local cache [lasts only until the next successful fetch](/docs/en/server-managed-settings#security-considerations).
282260* **Other tools**: managed settings bind Claude Code only. A developer who calls the API from another tool isn't under them.
283261 
284<span id="verify-enforcement" />
285 
286<span id="verify-that-a-policy-is-in-force" />
287 
288262## Check that a policy is in force
289263 
290264A developer reports that a policy isn't applying, or you want to confirm a rollout landed before pushing it to the fleet. Two commands on that machine answer it: `/status` shows which managed source Claude Code selected, and `claude doctor` lists what it dropped.
from line 286
312286 When you deployed through server-managed settings instead, run `claude doctor`, which reports the [fetch outcome](/docs/en/server-managed-settings#verify-settings-delivery).
313287* **The line names a source other than the one you deployed**: a higher-priority source is present and Claude Code ignored yours, and `Skipped sources` lists it. [How Claude Code combines managed sources](#how-claude-code-combines-managed-sources) gives the order.
314288 
315<span id="invalid-entries-in-managed-settings" />
316 
317289### Find entries Claude Code dropped
318290 
319291If your managed settings file, MDM profile, registry value, or server-managed payload fails schema validation, Claude Code first skips each individual entry it can repair, such as one invalid permission rule, and warns about each one. Claude Code then drops any value that still fails, unless the value belongs to one of the keys that [fail closed](#keys-that-fail-closed) instead.
from line 378
406378* While `network.deniedDomains` or any entry in it is invalid, Claude Code also withholds `network.allowedDomains`, so the managed allowlist grants nothing until you fix the deny list.
407379* While `filesystem.denyRead`, `filesystem.denyWrite`, or any entry in either is invalid, Claude Code also withholds both `filesystem.allowRead` and `filesystem.allowWrite` until you fix the deny list.
408380 
409<span id="managed-only-settings" />
410 
411381## Keys only a managed source can set
412382 
413383Claude Code reads the following keys only from a managed source; placing them in user or project settings files has no effect.
from line 410
440410| [`strictPluginOnlyCustomization`](/docs/en/settings-reference#strictpluginonlycustomization) | Block skills, agents, hooks, and MCP servers from user and project sources; `true` locks all four, an array names which |
441411| [`wslInheritsWindowsSettings`](/docs/en/settings-reference#wslinheritswindowssettings) | When set in the HKLM registry or a file under `C:\Program Files\ClaudeCode`, have WSL read the Windows policy chain, and read `/etc/claude-code` only when [no Windows admin document is present](#present-admin-documents); the entry gives the order |
442412 
443<Note>
444 On Team and Enterprise plans, an Owner enables or disables [Remote Control](/docs/en/remote-control) and [cloud sessions](/docs/en/claude-code-on-the-web) organization-wide in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code). When an Owner turns Remote Control off, already-connected sessions that run Claude Code v2.1.286 or later disconnect too. Each one disconnects the next time it refreshes your organization's policy, about once an hour. For what happens in those sessions, see [`Remote Control was turned off by your organization's policy`](/docs/en/remote-control#remote-control-was-turned-off-by-your-organizations-policy).
445 
446 Remote Control can additionally be disabled per device with the [`disableRemoteControl`](/docs/en/settings-reference#disableremotecontrol) setting. Cloud sessions have no per-device managed settings key.
447 
448 To check whether these organization settings reached a given machine, run `claude doctor` there and read the `Organization policy` line, which says where Claude Code loaded the policy from or why it didn't load. Requires Claude Code v2.1.261 or later. In a running session, `/status` shows the same line when the policy didn't load.
449</Note>
413> [!NOTE]
414>
415> On Team and Enterprise plans, an Owner enables or disables [Remote Control](/docs/en/remote-control) and [cloud sessions](/docs/en/claude-code-on-the-web) organization-wide in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code). When an Owner turns Remote Control off, already-connected sessions that run Claude Code v2.1.286 or later disconnect too. Each one disconnects the next time it refreshes your organization's policy, about once an hour. For what happens in those sessions, see [`Remote Control was turned off by your organization's policy`](/docs/en/remote-control#remote-control-was-turned-off-by-your-organizations-policy).
416>
417> Remote Control can additionally be disabled per device with the [`disableRemoteControl`](/docs/en/settings-reference#disableremotecontrol) setting. Cloud sessions have no per-device managed settings key.
418>
419> To check whether these organization settings reached a given machine, run `claude doctor` there and read the `Organization policy` line, which says where Claude Code loaded the policy from or why it didn't load. Requires Claude Code v2.1.261 or later. In a running session, `/status` shows the same line when the policy didn't load.
450420 
451421## Turn telemetry off for your organization
452422 

mcp Changed · +320 / -350 lines

#### Mark a tool to load upfront or stay deferred ### Defer a server's tools

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 23
2323 
2424Browse reviewed connectors in the [Anthropic Directory](https://claude.ai/directory). Directory connectors use the same MCP infrastructure as Claude Code, so you can add any remote server listed there with `claude mcp add`.
2525 
26<Warning>
27 Verify you trust each server before connecting it. Servers that fetch external content can expose you to [prompt injection risk](/docs/en/security#protect-against-prompt-injection).
28</Warning>
26> [!WARNING]
27>
28> Verify you trust each server before connecting it. Servers that fetch external content can expose you to [prompt injection risk](/docs/en/security#protect-against-prompt-injection).
2929 
3030To build your own server, see the [MCP server guide](https://modelcontextprotocol.io/docs/develop/build-server) for protocol fundamentals and the [Claude connector building docs](https://claude.com/docs/connectors/building) for authentication, testing, and Directory submission.
3131 
3232You can also have Claude scaffold a server for you with the official [`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
3333 
34<Steps>
35 <Step title="Install the plugin">
36 In the VS Code extension or the desktop app, follow [Install a plugin](/docs/en/plugins/install#install-a-plugin) instead of this step. In a terminal, start Claude Code by running `claude`, then enter this at its prompt:
37 
38 ```
39 /plugin install mcp-server-dev@claude-plugins-official
40 ```
41 
42 If the install fails, match the message Claude Code reports:
43 
44 * `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
45 * `Plugin "<name>" not found in marketplace "claude-plugins-official"`: your local copy of the marketplace catalog may be out of date. Refresh it with `/plugin marketplace update claude-plugins-official`, then retry the install. If the retry prints the same message, see [Plugin not found in marketplace](/docs/en/plugins/troubleshooting#plugin-not-found-in-marketplace).
46 
47 If the install summary reports `Run /reload-plugins to apply.`, Claude Code then runs that reload for you. If the reload warns that your next message would re-read the conversation, run `/reload-plugins --force`.
48 </Step>
49 
50 <Step title="Run the build skill">
51 ```
52 /mcp-server-dev:build-mcp-server
53 ```
54 
55 Claude asks about your use case and scaffolds a remote HTTP or local stdio server.
56 </Step>
57</Steps>
34**1. Install the plugin**
35 
36In the VS Code extension or the desktop app, follow [Install a plugin](/docs/en/plugins/install#install-a-plugin) instead of this step. In a terminal, start Claude Code by running `claude`, then enter this at its prompt:
37 
38```
39/plugin install mcp-server-dev@claude-plugins-official
40```
41 
42If the install fails, match the message Claude Code reports:
43 
44* `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install.
45* `Plugin "<name>" not found in marketplace "claude-plugins-official"`: your local copy of the marketplace catalog may be out of date. Refresh it with `/plugin marketplace update claude-plugins-official`, then retry the install. If the retry prints the same message, see [Plugin not found in marketplace](/docs/en/plugins/troubleshooting#plugin-not-found-in-marketplace).
46 
47If the install summary reports `Run /reload-plugins to apply.`, Claude Code then runs that reload for you. If the reload warns that your next message would re-read the conversation, run `/reload-plugins --force`.
48 
49**2. Run the build skill**
50 
51```
52/mcp-server-dev:build-mcp-server
53```
54 
55Claude asks about your use case and scaffolds a remote HTTP or local stdio server.
5856 
5957## Installing MCP servers
6058 
from line 84
8684 
8785### Option 2: Add a remote SSE server
8886 
89<Warning>
90 The SSE (Server-Sent Events) transport is deprecated. Use HTTP servers instead, where available.
91</Warning>
87> [!WARNING]
88>
89> The SSE (Server-Sent Events) transport is deprecated. Use HTTP servers instead, where available.
9290 
9391Some services still expose only an SSE endpoint. Add these with the same `claude mcp add --transport http <name> <url>` command as [an HTTP server](#option-1-add-a-remote-http-server). Claude Code tries the HTTP transport first and switches to SSE when the server doesn't accept it. The automatic switch requires Claude Code v2.1.265 or later.
9492 
from line 123
125123 -- npx -y airtable-mcp-server
126124```
127125 
128<Note>
129 For stdio servers, the `--` (double dash) separates Claude's own options, such as `--transport`, `--env`, and `--scope`, from the command and arguments that run the server. Everything after `--` is passed to the server untouched.
130 
131 For example:
132 
133 * `claude mcp add --transport stdio myserver -- npx server` → runs `npx server`
134 * `claude mcp add --env KEY=value --transport stdio myserver -- python server.py --port 8080` → runs `python server.py --port 8080` with `KEY=value` in environment
135 
136 Without `--`, Claude Code would try to parse the server's flags, like `--port` above, as its own options.
137 
138 `--env` accepts multiple `KEY=value` pairs. If the server name comes directly after `--env`, the CLI reads the name as another pair and rejects it, so place at least one other option, such as `--transport stdio`, between `--env` and the server name.
139</Note>
126> [!NOTE]
127>
128> For stdio servers, the `--` (double dash) separates Claude's own options, such as `--transport`, `--env`, and `--scope`, from the command and arguments that run the server. Everything after `--` is passed to the server untouched.
129>
130> For example:
131>
132> * `claude mcp add --transport stdio myserver -- npx server` → runs `npx server`
133> * `claude mcp add --env KEY=value --transport stdio myserver -- python server.py --port 8080` → runs `python server.py --port 8080` with `KEY=value` in environment
134>
135> Without `--`, Claude Code would try to parse the server's flags, like `--port` above, as its own options.
136>
137> `--env` accepts multiple `KEY=value` pairs. If the server name comes directly after `--env`, the CLI reads the name as another pair and rejects it, so place at least one other option, such as `--transport stdio`, between `--env` and the server name.
140138 
141139#### How Claude Code stops a stdio server
142140 
from line 168
170168 
171169Each is one of the inputs the four options in [Installing MCP servers](#installing-mcp-servers) take. Find the shape you have below to turn it into the command Claude Code accepts. Each command writes to [local scope](#local-scope) unless you add `--scope project` or `--scope user`.
172170 
173<span id="from-a-url" />
174 
175171#### Add a server from a URL
176172 
177173A URL means the server is remote. For an `https://` endpoint, add it with `--transport http`, or follow [Option 2](#option-2-add-a-remote-sse-server) when the instructions say the endpoint uses SSE. For a `wss://` endpoint, use [Option 4](#option-4-add-a-remote-websocket-server) instead, since `--transport` doesn't accept `ws`:
from line 178
182178 
183179If the instructions also give an API key or token header, pass it with `--header` as shown in [Option 1](#option-1-add-a-remote-http-server).
184180 
185<span id="from-an-npx-uvx-or-binary-command" />
186 
187181#### Add a server from an `npx`, `uvx`, or binary command
188182 
189183A launch command means the server runs as a local stdio process. Put the whole command after `--`, so Claude Code passes flags such as `-y` to the command that starts the server instead of reading them as its own options. Pass any environment variables the instructions ask for with `--env`, after the server name and before `--`:
from line 187
193187```
194188 
195189[Option 3](#option-3-add-a-local-stdio-server) covers the `--` separator in full.
196 
197<span id="from-an-mcpservers-json-block" />
198190 
199191#### Add a server from an `mcpServers` JSON block
200192 
from line 403
411403 
412404Claude Code asks stdio servers for that revision by default. To keep a stdio channel server on the earlier handshake, set [`MCP_PROTOCOL_NEGOTIATION`](/docs/en/env-vars) to `legacy`, which keeps every server on it.
413405 
414<Tip>
415 Tips:
416 
417 * Use the `-s` or `--scope` flag to specify where the configuration is stored:
418 * `local` (default): available only to you in the current project
419 * `project`: shared with everyone in the project via the `.mcp.json` file
420 * `user`: available to you across all projects
421 * Set environment variables with `-e` or `--env` flags (for example, `-e KEY=value`)
422 * The `--transport` and `--header` flags also accept `-t` and `-H` short forms
423 * Configure MCP server startup timeout using the `MCP_TIMEOUT` environment variable (for example, `MCP_TIMEOUT=10000 claude` sets a 10-second timeout)
424 * Set a per-server tool execution timeout by adding a `timeout` field in milliseconds to that server's `.mcp.json` entry, for example `"timeout": 600000` for ten minutes. This overrides the `MCP_TOOL_TIMEOUT` environment variable for that server only
425 * Claude Code displays a warning when MCP tool output exceeds 10,000 tokens and limits output to 25,000 tokens by default. To change the token limit, set the `MAX_MCP_OUTPUT_TOKENS` environment variable, for example `MAX_MCP_OUTPUT_TOKENS=50000`. The warning threshold is fixed. Unless the server raises a tool's own limit, successful text results longer than 50,000 characters are saved to a file regardless of this variable. See [MCP output limits and warnings](#mcp-output-limits-and-warnings)
426 * Use `/mcp` to authenticate with remote servers that require OAuth 2.0 authentication
427</Tip>
406> [!TIP]
407>
408> Tips:
409>
410> * Use the `-s` or `--scope` flag to specify where the configuration is stored:
411> * `local` (default): available only to you in the current project
412> * `project`: shared with everyone in the project via the `.mcp.json` file
413> * `user`: available to you across all projects
414> * Set environment variables with `-e` or `--env` flags (for example, `-e KEY=value`)
415> * The `--transport` and `--header` flags also accept `-t` and `-H` short forms
416> * Configure MCP server startup timeout using the `MCP_TIMEOUT` environment variable (for example, `MCP_TIMEOUT=10000 claude` sets a 10-second timeout)
417> * Set a per-server tool execution timeout by adding a `timeout` field in milliseconds to that server's `.mcp.json` entry, for example `"timeout": 600000` for ten minutes. This overrides the `MCP_TOOL_TIMEOUT` environment variable for that server only
418> * Claude Code displays a warning when MCP tool output exceeds 10,000 tokens and limits output to 25,000 tokens by default. To change the token limit, set the `MAX_MCP_OUTPUT_TOKENS` environment variable, for example `MAX_MCP_OUTPUT_TOKENS=50000`. The warning threshold is fixed. Unless the server raises a tool's own limit, successful text results longer than 50,000 characters are saved to a file regardless of this variable. See [MCP output limits and warnings](#mcp-output-limits-and-warnings)
419> * Use `/mcp` to authenticate with remote servers that require OAuth 2.0 authentication
428420 
429421The per-server `timeout` is a hard wall-clock limit per tool call, and progress notifications from the server don't extend it. Values below 1000 are ignored and fall through to `MCP_TOOL_TIMEOUT`, or to its default of about 28 hours when that variable is unset. For an HTTP, SSE, or [claude.ai connector](/docs/en/mcp#use-mcp-servers-from-claude-ai) server there is also a second, per-request timer that covers each request through to the server's first response byte. Claude Code sets that timer to the greatest of three values: 60 seconds, the tool timeout that applies to the server, and `MCP_TIMEOUT`. The 28-hour default of an unset `MCP_TOOL_TIMEOUT` doesn't enter that comparison, and a value below 60 seconds doesn't shorten the timer. Stdio and WebSocket servers have no per-request timer.
430422 
from line 535
543535 
544536Local scope is the default. A local-scoped server loads only in the project where you added it and stays private to you. Claude Code stores it in `~/.claude.json` under that project's path, so the same server won't appear in your other projects. Use local scope for personal development servers, experimental configurations, or servers with credentials you don't want in version control.
545537 
546<Note>
547 The term "local scope" for MCP servers differs from general local settings. MCP local-scoped servers are stored in `~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](/docs/en/settings#where-settings-live) for details on settings file locations.
548</Note>
538> [!NOTE]
539>
540> The term "local scope" for MCP servers differs from general local settings. MCP local-scoped servers are stored in `~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](/docs/en/settings#where-settings-live) for details on settings file locations.
549541 
550542```bash theme={null}
551543# Add a local-scoped server (default)
from line 768
776768 
777769If you configured `headers.Authorization` for the server and the server rejects that header, Claude Code reports the connection as failed instead of falling back to OAuth. Check that the token is valid for the MCP endpoint, or remove the header to use the OAuth flow.
778770 
779<Steps>
780 <Step title="Add the server that requires authentication">
781 If you already added the `sentry` server in the [MCP quickstart](/docs/en/mcp-quickstart#connect-a-server-that-requires-sign-in), skip this step: running `claude mcp add` again with the same server name at the same scope fails with `MCP server sentry already exists in local config`. Otherwise, run:
782 
783 ```bash theme={null}
784 claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
785 ```
786 </Step>
787 
788 <Step title="Use the /mcp command within Claude Code">
789 In Claude Code, use the command:
790 
791 ```text wrap theme={null}
792 /mcp
793 ```
794 
795 Then follow the steps in your browser to log in.
796 </Step>
797</Steps>
798 
799<Tip>
800 Tips:
801 
802 * Authentication tokens are stored securely and refreshed automatically
803 * Use "Clear authentication" in the `/mcp` menu to revoke access
804 * If your browser doesn't open automatically, copy the provided URL and open it manually
805 * If the browser redirect fails with a connection error after authenticating, paste the full callback URL from your browser's address bar into the URL prompt that appears in Claude Code
806 * OAuth authentication works with HTTP servers
807</Tip>
771**1. Add the server that requires authentication**
772 
773If you already added the `sentry` server in the [MCP quickstart](/docs/en/mcp-quickstart#connect-a-server-that-requires-sign-in), skip this step: running `claude mcp add` again with the same server name at the same scope fails with `MCP server sentry already exists in local config`. Otherwise, run:
774 
775```bash theme={null}
776claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
777```
778 
779**2. Use the /mcp command within Claude Code**
780 
781In Claude Code, use the command:
782 
783```text wrap theme={null}
784/mcp
785```
786 
787Then follow the steps in your browser to log in.
788 
789> [!TIP]
790>
791> Tips:
792>
793> * Authentication tokens are stored securely and refreshed automatically
794> * Use "Clear authentication" in the `/mcp` menu to revoke access
795> * If your browser doesn't open automatically, copy the provided URL and open it manually
796> * If the browser redirect fails with a connection error after authenticating, paste the full callback URL from your browser's address bar into the URL prompt that appears in Claude Code
797> * OAuth authentication works with HTTP servers
808798 
809799### Authenticate from the command line
810800 
from line 829
839829 
840830Some MCP servers don't support automatic OAuth setup via Dynamic Client Registration. If you see an error like "Incompatible auth server: does not support dynamic client registration," the server requires pre-configured credentials. Claude Code also supports servers that use a Client ID Metadata Document (CIMD) instead of Dynamic Client Registration, and discovers these automatically. If automatic discovery fails, register an OAuth app through the server's developer portal first, then provide the credentials when adding the server.
841831 
842<Steps>
843 <Step title="Register an OAuth app with the server">
844 Create an app through the server's developer portal and note your client ID and client secret.
845 
846 If the registration form asks for a redirect URI, pick any available port and enter `http://localhost:PORT/callback` with that port. You'll use the same port in the next step.
847 
848 In v2.1.229, Claude Code sent `http://127.0.0.1:PORT/callback` instead, and servers that exact-match the registered redirect URI rejected the sign-in with a redirect URI mismatch. Claude Code v2.1.231 restored the `localhost` form. To recover on v2.1.229, upgrade Claude Code, or temporarily add the `http://127.0.0.1:PORT/callback` form to the server's registered redirect URIs.
849 </Step>
850 
851 <Step title="Add the server with your credentials">
852 The tabs cover both commands: `claude mcp add` takes your client ID and callback port as flags, and `claude mcp add-json` takes them in an `oauth` object. If you registered a redirect URI, set the callback port to the port in that URI.
853 
854 <Tabs>
855 <Tab title="claude mcp add">
856 Use `--client-id` to pass your app's client ID. The `--client-secret` flag prompts for the secret with masked input:
857 
858 ```bash theme={null}
859 claude mcp add --transport http \
860 --client-id your-client-id --client-secret --callback-port 8080 \
861 my-server https://mcp.example.com/mcp
862 ```
863 </Tab>
864 
865 <Tab title="claude mcp add-json">
866 Include the `oauth` object in the JSON config and pass `--client-secret` as a separate flag:
867 
868 ```bash theme={null}
869 claude mcp add-json my-server \
870 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' \
871 --client-secret
872 ```
873 </Tab>
874 
875 <Tab title="claude mcp add-json (callback port only)">
876 To fix only the callback port and let Claude Code register the client automatically, set `callbackPort` on its own:
877 
878 ```bash theme={null}
879 claude mcp add-json my-server \
880 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'
881 ```
882 </Tab>
883 
884 <Tab title="CI / env var">
885 Set the secret via environment variable to skip the interactive prompt:
886 
887 ```bash theme={null}
888 MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \
889 --client-id your-client-id --client-secret --callback-port 8080 \
890 my-server https://mcp.example.com/mcp
891 ```
892 </Tab>
893 </Tabs>
894 </Step>
895 
896 <Step title="Authenticate in Claude Code">
897 Run `/mcp` in Claude Code and follow the browser login flow.
898 </Step>
899</Steps>
900 
901<Tip>
902 Tips:
903 
904 * The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config
905 * You can set the client secret only when you add the server. When you authenticate with `claude mcp login` or from `/mcp`, Claude Code uses the stored secret and doesn't prompt for one or read `MCP_CLIENT_SECRET`
906 * To add or change the secret later, remove the server with `claude mcp remove <name>`, then add it again with `--client-secret` and the same `--scope`
907 * If the server uses a public OAuth client with no secret, use only `--client-id` without `--client-secret`
908 * These flags only apply to HTTP and SSE transports. They have no effect on stdio servers
909 * Use `claude mcp get <name>` to verify that OAuth credentials are configured for a server
910</Tip>
832**1. Register an OAuth app with the server**
833 
834Create an app through the server's developer portal and note your client ID and client secret.
835 
836If the registration form asks for a redirect URI, pick any available port and enter `http://localhost:PORT/callback` with that port. You'll use the same port in the next step.
837 
838In v2.1.229, Claude Code sent `http://127.0.0.1:PORT/callback` instead, and servers that exact-match the registered redirect URI rejected the sign-in with a redirect URI mismatch. Claude Code v2.1.231 restored the `localhost` form. To recover on v2.1.229, upgrade Claude Code, or temporarily add the `http://127.0.0.1:PORT/callback` form to the server's registered redirect URIs.
839 
840**2. Add the server with your credentials**
841 
842The tabs cover both commands: `claude mcp add` takes your client ID and callback port as flags, and `claude mcp add-json` takes them in an `oauth` object. If you registered a redirect URI, set the callback port to the port in that URI.
843 
844**claude mcp add**
845 
846Use `--client-id` to pass your app's client ID. The `--client-secret` flag prompts for the secret with masked input:
847 
848```bash theme={null}
849claude mcp add --transport http \
850 --client-id your-client-id --client-secret --callback-port 8080 \
851 my-server https://mcp.example.com/mcp
852```
853 
854**claude mcp add-json**
855 
856Include the `oauth` object in the JSON config and pass `--client-secret` as a separate flag:
857 
858```bash theme={null}
859claude mcp add-json my-server \
860 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' \
861 --client-secret
862```
863 
864**claude mcp add-json (callback port only)**
865 
866To fix only the callback port and let Claude Code register the client automatically, set `callbackPort` on its own:
867 
868```bash theme={null}
869claude mcp add-json my-server \
870 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'
871```
872 
873**CI / env var**
874 
875Set the secret via environment variable to skip the interactive prompt:
876 
877```bash theme={null}
878MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \
879 --client-id your-client-id --client-secret --callback-port 8080 \
880 my-server https://mcp.example.com/mcp
881```
882 
883**3. Authenticate in Claude Code**
884 
885Run `/mcp` in Claude Code and follow the browser login flow.
886 
887> [!TIP]
888>
889> Tips:
890>
891> * The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config
892> * You can set the client secret only when you add the server. When you authenticate with `claude mcp login` or from `/mcp`, Claude Code uses the stored secret and doesn't prompt for one or read `MCP_CLIENT_SECRET`
893> * To add or change the secret later, remove the server with `claude mcp remove <name>`, then add it again with `--client-secret` and the same `--scope`
894> * If the server uses a public OAuth client with no secret, use only `--client-id` without `--client-secret`
895> * These flags only apply to HTTP and SSE transports. They have no effect on stdio servers
896> * Use `claude mcp get <name>` to verify that OAuth credentials are configured for a server
911897 
912898### Override OAuth metadata discovery
913899 
from line 1040
10541040 
10551041If you have a JSON configuration for an MCP server, you can add it directly:
10561042 
1057<Steps>
1058 <Step title="Add an MCP server from JSON">
1059 ```bash theme={null}
1060 # Basic syntax
1061 claude mcp add-json <name> '<json>'
1062 
1063 # Example: Adding an HTTP server with JSON configuration
1064 claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
1065 
1066 # Example: Adding a stdio server with JSON configuration
1067 claude mcp add-json local-weather '{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'
1068 
1069 # Example: Adding an HTTP server with pre-configured OAuth credentials
1070 claude mcp add-json my-server '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' --client-secret
1071 ```
1072 </Step>
1073 
1074 <Step title="Verify the server was added">
1075 ```bash theme={null}
1076 claude mcp get weather-api
1077 ```
1078 </Step>
1079</Steps>
1080 
1081<Tip>
1082 Tips:
1083 
1084 * Make sure the JSON is properly escaped in your shell
1085 * The JSON must conform to the MCP server configuration schema
1086 * You can use `--scope user` to add the server to your user configuration instead of the project-specific one
1087</Tip>
1043**1. Add an MCP server from JSON**
1044 
1045```bash theme={null}
1046# Basic syntax
1047claude mcp add-json <name> '<json>'
1048 
1049# Example: Adding an HTTP server with JSON configuration
1050claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
1051 
1052# Example: Adding a stdio server with JSON configuration
1053claude mcp add-json local-weather '{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'
1054 
1055# Example: Adding an HTTP server with pre-configured OAuth credentials
1056claude mcp add-json my-server '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' --client-secret
1057```
1058 
1059**2. Verify the server was added**
1060 
1061```bash theme={null}
1062claude mcp get weather-api
1063```
1064 
1065> [!TIP]
1066>
1067> Tips:
1068>
1069> * Make sure the JSON is properly escaped in your shell
1070> * The JSON must conform to the MCP server configuration schema
1071> * You can use `--scope user` to add the server to your user configuration instead of the project-specific one
10881072 
10891073## Import MCP servers from Claude Desktop
10901074 
10911075If you've already configured MCP servers in Claude Desktop, you can import them:
10921076 
1093<Steps>
1094 <Step title="Import servers from Claude Desktop">
1095 ```bash theme={null}
1096 # Basic syntax
1097 claude mcp add-from-claude-desktop
1098 ```
1099 </Step>
1100 
1101 <Step title="Select which servers to import">
1102 After running the command, you'll see an interactive dialog that allows you to select which servers you want to import.
1103 </Step>
1104 
1105 <Step title="Verify the servers were imported">
1106 ```bash theme={null}
1107 claude mcp list
1108 ```
1109 </Step>
1110</Steps>
1077**1. Import servers from Claude Desktop**
1078 
1079```bash theme={null}
1080# Basic syntax
1081claude mcp add-from-claude-desktop
1082```
1083 
1084**2. Select which servers to import**
1085 
1086After running the command, you'll see an interactive dialog that allows you to select which servers you want to import.
1087 
1088**3. Verify the servers were imported**
1089 
1090```bash theme={null}
1091claude mcp list
1092```
11111093 
11121094Server names added through `claude mcp` commands can contain only letters, numbers, hyphens, and underscores. Claude Desktop doesn't apply that restriction, so a Claude Desktop server whose name contains any other character, such as a space, can't be imported. The import reports each name it rejects and still imports the other servers you selected.
11131095 
1114<Tip>
1115 Tips:
1116 
1117 * This feature only works on macOS and Windows Subsystem for Linux (WSL)
1118 * It reads the Claude Desktop configuration file from its standard location on those platforms
1119 * Use the `--scope user` flag to add servers to your user configuration
1120 * Imported servers keep the same names as in Claude Desktop when the name contains only letters, numbers, hyphens, and underscores. Claude Code reports a server whose name contains any other character and skips it
1121 * If servers with the same names already exist, they get a numerical suffix (for example, `server_1`)
1122</Tip>
1096> [!TIP]
1097>
1098> Tips:
1099>
1100> * This feature only works on macOS and Windows Subsystem for Linux (WSL)
1101> * It reads the Claude Desktop configuration file from its standard location on those platforms
1102> * Use the `--scope user` flag to add servers to your user configuration
1103> * Imported servers keep the same names as in Claude Desktop when the name contains only letters, numbers, hyphens, and underscores. Claude Code reports a server whose name contains any other character and skips it
1104> * If servers with the same names already exist, they get a numerical suffix (for example, `server_1`)
11231105 
11241106## Use MCP servers from claude.ai
11251107 
11261108If you've logged into Claude Code with a [claude.ai](https://claude.ai) account, MCP servers you've added in claude.ai, known as [connectors](https://claude.com/docs/connectors), are automatically available in Claude Code:
11271109 
1128<Steps>
1129 <Step title="Configure MCP servers in claude.ai">
1130 Add servers at [claude.ai/customize/connectors](https://claude.ai/customize/connectors). On Team and Enterprise plans, only admins can add servers.
1131 </Step>
1132 
1133 <Step title="Authenticate the MCP server">
1134 Complete any required authentication steps in claude.ai.
1135 </Step>
1136 
1137 <Step title="View and manage servers in Claude Code">
1138 In Claude Code, use the command:
1139 
1140 ```text wrap theme={null}
1141 /mcp
1142 ```
1143 
1144 Servers from claude.ai appear in the list with indicators showing they come from claude.ai.
1145 </Step>
1146</Steps>
1110**1. Configure MCP servers in claude.ai**
1111 
1112Add servers at [claude.ai/customize/connectors](https://claude.ai/customize/connectors). On Team and Enterprise plans, only admins can add servers.
1113 
1114**2. Authenticate the MCP server**
1115 
1116Complete any required authentication steps in claude.ai.
1117 
1118**3. View and manage servers in Claude Code**
1119 
1120In Claude Code, use the command:
1121 
1122```text wrap theme={null}
1123/mcp
1124```
1125 
1126Servers from claude.ai appear in the list with indicators showing they come from claude.ai.
11471127 
11481128Anthropic also provides some connectors itself, without you or an admin adding them. On accounts where [Claude Docs](/docs/en/artifacts#write-a-document-with-claude-docs) is available, `/mcp` lists `claude.ai Claude Docs` with no setup, and Claude uses it when you ask for a document meant for other people. To turn it off, add a `serverName` entry of `"claude.ai Claude Docs"` to `deniedMcpServers` or use the `/mcp` toggle, both described in [Disable claude.ai connectors](#disable-claude-ai-connectors).
11491129 
from line 1225
12451225}
12461226```
12471227 
1248<Warning>
1249 **Configuring the executable path**: the `command` field must reference the Claude Code executable. If the `claude` command is not in your system's PATH, you'll need to specify the full path to the executable.
1250 
1251 To find the full path:
1252 
1253 ```bash theme={null}
1254 which claude
1255 ```
1256 
1257 Then use the full path in your configuration:
1258 
1259 ```json theme={null}
1260 {
1261 "mcpServers": {
1262 "claude-code": {
1263 "type": "stdio",
1264 "command": "/full/path/to/claude",
1265 "args": ["mcp", "serve"],
1266 "env": {}
1267 }
1268 }
1269 }
1270 ```
1271 
1272 Without the correct executable path, you'll encounter errors like `spawn claude ENOENT`.
1273</Warning>
1274 
1275<Tip>
1276 Tips:
1277 
1278 * In Claude Desktop, try asking Claude to read files in a directory, make edits, and more.
1279 * This MCP server only exposes Claude Code's tools to your MCP client, so your own client is responsible for implementing user confirmation for individual tool calls.
1280</Tip>
1228> [!WARNING]
1229>
1230> **Configuring the executable path**: the `command` field must reference the Claude Code executable. If the `claude` command is not in your system's PATH, you'll need to specify the full path to the executable.
1231>
1232> To find the full path:
1233>
1234> ```bash theme={null}
1235> which claude
1236> ```
1237>
1238> Then use the full path in your configuration:
1239>
1240> ```json theme={null}
1241> {
1242> "mcpServers": {
1243> "claude-code": {
1244> "type": "stdio",
1245> "command": "/full/path/to/claude",
1246> "args": ["mcp", "serve"],
1247> "env": {}
1248> }
1249> }
1250> }
1251> ```
1252>
1253> Without the correct executable path, you'll encounter errors like `spawn claude ENOENT`.
1254 
1255> [!TIP]
1256>
1257> Tips:
1258>
1259> * In Claude Desktop, try asking Claude to read files in a directory, make edits, and more.
1260> * This MCP server only exposes Claude Code's tools to your MCP client, so your own client is responsible for implementing user confirmation for individual tool calls.
12811261 
12821262When the JSON text in a Bash or PowerShell tool call's result includes a `backgroundOutputPath` field, the call left its command running [in the background](/docs/en/tools-reference#background-commands), such as when the call set `run_in_background: true` or the command reached its timeout. The field gives the path of the command's output file. Nothing notifies your client when the command finishes, and the file gets no closing line when it does, so reading the file shows the output written so far. To detect the end, append a marker to the command, such as `npm test; echo DONE`, and look for it in the file. The `backgroundOutputPath` field requires Claude Code v2.1.295 or later.
12831263 
from line 1392
14121392 
14131393### Reference MCP resources
14141394 
1415<Steps>
1416 <Step title="List available resources">
1417 Type `@` in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu.
1418 </Step>
1419 
1420 <Step title="Reference a specific resource">
1421 Use the format `@server:protocol://resource/path` to reference a resource:
1422 
1423 ```text wrap theme={null}
1424 Can you analyze @github:issue://123 and suggest a fix?
1425 ```
1426 
1427 ```text wrap theme={null}
1428 Please review the API documentation at @docs:file://api/authentication
1429 ```
1430 </Step>
1431 
1432 <Step title="Multiple resource references">
1433 You can reference multiple resources in a single prompt:
1434 
1435 ```text wrap theme={null}
1436 Compare @postgres:schema://users with @docs:file://database/user-model
1437 ```
1438 </Step>
1439</Steps>
1440 
1441<Tip>
1442 Tips:
1443 
1444 * Resources are automatically fetched and included as attachments when referenced
1445 * Resource paths are fuzzy-searchable in the @ mention autocomplete
1446 * Claude Code automatically provides tools to list and read MCP resources when servers support them
1447 * Resources can contain any type of content that the MCP server provides (text, JSON, structured data, etc.)
1448</Tip>
1395**1. List available resources**
1396 
1397Type `@` in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu.
1398 
1399**2. Reference a specific resource**
1400 
1401Use the format `@server:protocol://resource/path` to reference a resource:
1402 
1403```text wrap theme={null}
1404Can you analyze @github:issue://123 and suggest a fix?
1405```
1406 
1407```text wrap theme={null}
1408Please review the API documentation at @docs:file://api/authentication
1409```
1410 
1411**3. Multiple resource references**
1412 
1413You can reference multiple resources in a single prompt:
1414 
1415```text wrap theme={null}
1416Compare @postgres:schema://users with @docs:file://database/user-model
1417```
1418 
1419> [!TIP]
1420>
1421> Tips:
1422>
1423> * Resources are automatically fetched and included as attachments when referenced
1424> * Resource paths are fuzzy-searchable in the @ mention autocomplete
1425> * Claude Code automatically provides tools to list and read MCP resources when servers support them
1426> * Resources can contain any type of content that the MCP server provides (text, JSON, structured data, etc.)
14491427 
14501428MCP Apps UI resources are entries with a `ui://` URI or the `text/html;profile=mcp-app` media type: pages for a host application to render rather than content for Claude to read. They don't appear in the `@` suggestions or in the resource list tool's results, and a server that offers only UI resources shows an empty resource list. Reading a UI resource by its URI still works.
14511429 
from line 1431
14531431 
14541432Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names and server instructions load at session start, so adding more MCP servers has minimal impact on your context window. Claude Code doesn't impose a fixed per-server tool cap; the practical limit is your context window budget.
14551433 
1456<Note>
1457 Tool search isn't supported on Microsoft Foundry [deployments hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options), which reject it server-side: Claude Code detects the rejection and loads MCP tools upfront for that deployment instead. [`ENABLE_TOOL_SEARCH`](#configure-tool-search) can't override this, since the rejection comes from the deployment itself.
1458</Note>
1459 
1460<span id="for-mcp-server-authors" />
1434> [!NOTE]
1435>
1436> Tool search isn't supported on Microsoft Foundry [deployments hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options), which reject it server-side: Claude Code detects the rejection and loads MCP tools upfront for that deployment instead. [`ENABLE_TOOL_SEARCH`](#configure-tool-search) can't override this, since the rejection comes from the deployment itself.
14611437 
14621438### Tool search for MCP server authors
14631439 
from line 1456
14801456 
14811457Descriptions and instructions from some of the MCP servers that Anthropic hosts at `api.anthropic.com` reach Claude in full. To change the limits for the other MCP servers in your session, set [`CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH`](/docs/en/env-vars#variables) to a number of characters. The number you set replaces both limits: `8192`, for example, raises the shorter limit and lowers the longer one. This variable requires Claude Code v2.1.280 or later.
14821458 
1483<h4 id="per-tool-alwaysload">
1484 Mark a tool to load upfront or stay deferred
1485</h4>
1459#### Mark a tool to load upfront or stay deferred
14861460 
14871461To control how one of your server's tools loads, set `"anthropic/alwaysLoad"` in that tool's `_meta` object. The person who adds your server to Claude Code can also set [`alwaysLoad`](#exempt-a-server-from-deferral) for the whole server in their configuration, and their setting can override yours:
14881462 
from line 1544
15701544 
15711545Setting `alwaysLoad: true` also makes startup wait for the server's tools, capped at the standard 5-second connect timeout, since they must be present when the first prompt is built. A remote server with a valid [`cached` entry](#server-status-detail) supplies its tools from the cache without connecting, so it doesn't hold startup. Other servers connect in the background by default; set [`MCP_CONNECTION_NONBLOCKING=0`](/docs/en/env-vars) to make startup wait for them too.
15721546 
1573<h3 id="defer-a-servers-tools">
1574 Defer a server's tools
1575</h3>
1547### Defer a server's tools
15761548 
15771549To keep all of a server's tools behind tool search, set `"alwaysLoad": false` in that server's entry in your MCP configuration. That includes tools that the server's author has [marked to load upfront](#per-tool-alwaysload). If you leave `alwaysLoad` out, those marked tools load upfront. Requires Claude Code v2.1.287 or later.
15781550 
from line 1556
15841556 
15851557### Execute MCP prompts
15861558 
1587<Steps>
1588 <Step title="Discover available prompts">
1589 Type `/` to see the commands available to you, including those from MCP servers. Claude Code lists each MCP prompt as `/servername:promptname (MCP)`. Typing `/mcp__servername__promptname` also runs it.
1590 </Step>
1591 
1592 <Step title="Execute a prompt without arguments">
1593 ```text wrap theme={null}
1594 /mcp__github__list_prs
1595 ```
1596 </Step>
1597 
1598 <Step title="Execute a prompt with arguments">
1599 Many prompts accept arguments. Pass them space-separated after the command. Claude Code splits the arguments on whitespace, so each argument is a single token:
1600 
1601 ```text wrap theme={null}
1602 /mcp__github__pr_review 456
1603 ```
1604 
1605 ```text wrap theme={null}
1606 /mcp__jira__create_issue login-bug high
1607 ```
1608 </Step>
1609</Steps>
1610 
1611<Tip>
1612 Tips:
1613 
1614 * MCP prompts are dynamically discovered from connected servers
1615 * Arguments are parsed based on the prompt's defined parameters
1616 * Prompt results are injected directly into the conversation
1617 * In the `/mcp__servername__promptname` form, Claude Code replaces any character in the server name outside `A-Z`, `a-z`, `0-9`, `_`, and `-` with `_`, and uses the prompt name as the server declares it
1618</Tip>
1559**1. Discover available prompts**
1560 
1561Type `/` to see the commands available to you, including those from MCP servers. Claude Code lists each MCP prompt as `/servername:promptname (MCP)`. Typing `/mcp__servername__promptname` also runs it.
1562 
1563**2. Execute a prompt without arguments**
1564 
1565```text wrap theme={null}
1566/mcp__github__list_prs
1567```
1568 
1569**3. Execute a prompt with arguments**
1570 
1571Many prompts accept arguments. Pass them space-separated after the command. Claude Code splits the arguments on whitespace, so each argument is a single token:
1572 
1573```text wrap theme={null}
1574/mcp__github__pr_review 456
1575```
1576 
1577```text wrap theme={null}
1578/mcp__jira__create_issue login-bug high
1579```
1580 
1581> [!TIP]
1582>
1583> Tips:
1584>
1585> * MCP prompts are dynamically discovered from connected servers
1586> * Arguments are parsed based on the prompt's defined parameters
1587> * Prompt results are injected directly into the conversation
1588> * In the `/mcp__servername__promptname` form, Claude Code replaces any character in the server name outside `A-Z`, `a-z`, `0-9`, `_`, and `-` with `_`, and uses the prompt name as the server declares it
16191589 
16201590## Managed MCP configuration
16211591 
16221592 

mcp-quickstart Changed · +237 / -243 lines

from line 6
66 
77This guide walks you through connecting one MCP server end to end with the Claude Code CLI. By the end, you'll have a server connected and responding, know where its configuration lives on disk, and know how to fix the most common connection errors.
88 
9<Note>
10 You can also add MCP servers from other surfaces, including the desktop app, VS Code, and the web. See [Connect from other surfaces](#connect-from-other-surfaces).
11</Note>
9> [!NOTE]
10>
11> You can also add MCP servers from other surfaces, including the desktop app, VS Code, and the web. See [Connect from other surfaces](#connect-from-other-surfaces).
1212 
1313For every way to connect and configure MCP servers in Claude Code, see the [MCP reference](/docs/en/mcp).
1414 
from line 25
2525 
2626The steps are the same for any server: add it, check the connection status, then use it in a session, with an optional cleanup step at the end. Some servers add a step, like a browser sign-in, shown in [Additional MCP server examples](#additional-mcp-server-examples). For more servers to connect, browse the [Anthropic Directory](/docs/en/mcp#find-and-build-mcp-servers).
2727 
28<Steps>
29 <Step title="Add the MCP server">
30 Register the server with Claude Code. Run this in your terminal, not inside a `claude` session: you're configuring the server before starting a conversation.
28**1. Add the MCP server**
3129 
32 ```bash theme={null}
33 claude mcp add --transport http claude-code-docs https://code.claude.com/docs/mcp
34 ```
30Register the server with Claude Code. Run this in your terminal, not inside a `claude` session: you're configuring the server before starting a conversation.
3531 
36 The parts of the command:
32```bash theme={null}
33claude mcp add --transport http claude-code-docs https://code.claude.com/docs/mcp
34```
3735 
38 * `claude mcp add`: registers a server with Claude Code.
39 * `--transport http`: the server is hosted at a URL rather than run as a local process.
40 * `claude-code-docs`: a name you make up. Calling the same server `docs` would work identically. Claude Code uses whatever name you pick to label the server's tools in Claude's output and to refer to the server in commands like `claude mcp remove`.
41 * `https://code.claude.com/docs/mcp`: the URL where the server is hosted.
36The parts of the command:
4237 
43 The command prints a confirmation like `Added HTTP MCP server claude-code-docs with URL: https://code.claude.com/docs/mcp to local config`, followed by a `File modified:` line showing the configuration file it wrote. The `local config` part means the server is registered to you, in this project: if you start Claude Code in a different project, this server isn't active there. To register a server once for all your projects, add it at user scope, covered in [Change server scope](#change-server-scope).
44 </Step>
38* `claude mcp add`: registers a server with Claude Code.
39* `--transport http`: the server is hosted at a URL rather than run as a local process.
40* `claude-code-docs`: a name you make up. Calling the same server `docs` would work identically. Claude Code uses whatever name you pick to label the server's tools in Claude's output and to refer to the server in commands like `claude mcp remove`.
41* `https://code.claude.com/docs/mcp`: the URL where the server is hosted.
4542 
46 <Step title="Check the connection status">
47 Confirm the server appears in your server list and check its status:
43The command prints a confirmation like `Added HTTP MCP server claude-code-docs with URL: https://code.claude.com/docs/mcp to local config`, followed by a `File modified:` line showing the configuration file it wrote. The `local config` part means the server is registered to you, in this project: if you start Claude Code in a different project, this server isn't active there. To register a server once for all your projects, add it at user scope, covered in [Change server scope](#change-server-scope).
4844 
49 ```bash theme={null}
50 claude mcp list
51 ```
45**2. Check the connection status**
5246 
53 The server appears with a status indicator:
47Confirm the server appears in your server list and check its status:
5448 
55 | Status | Meaning |
56 | :- | :- |
57 | `✔ Connected` | Ready to use. This is what you should see for `claude-code-docs` |
58 | `! Connected · tools fetch failed` | The server connected but couldn't list its tools. Run `claude mcp get <name>` for the error detail |
59 | `! Needs authentication` | The server is reachable but needs a browser sign-in, or a token passed with `--header`. See [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in) |
60 | `✘ Failed to connect` | Server didn't respond. See [Troubleshooting](#troubleshooting) |
61 | `✘ Connection error` | The connection attempt threw an error. See [Troubleshooting](#troubleshooting) |
62 | ``⏸ Pending approval (run `claude` to approve)`` | A project-scoped server you haven't approved yet. See [Edit .mcp.json directly](#edit-mcp-json-directly) |
63 | `⊘ Disabled for this project (re-enable via /mcp)` | A server turned off for this project by the project's `disabledMcpServers` list. See [Disable a server without removing it](/docs/en/mcp#disable-a-server-without-removing-it) |
49```bash theme={null}
50claude mcp list
51```
6452 
65 Some legacy Windows consoles, such as the default console on Windows 10, don't support these Unicode glyphs and show `√` and `×` in place of `✔` and `✘`.
66 </Step>
53The server appears with a status indicator:
6754 
68 <Step title="Use the server">
69 Start a session and ask Claude to use the new server by name:
55| Status | Meaning |
56| :- | :- |
57| `✔ Connected` | Ready to use. This is what you should see for `claude-code-docs` |
58| `! Connected · tools fetch failed` | The server connected but couldn't list its tools. Run `claude mcp get <name>` for the error detail |
59| `! Needs authentication` | The server is reachable but needs a browser sign-in, or a token passed with `--header`. See [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in) |
60| `✘ Failed to connect` | Server didn't respond. See [Troubleshooting](#troubleshooting) |
61| `✘ Connection error` | The connection attempt threw an error. See [Troubleshooting](#troubleshooting) |
62| ``⏸ Pending approval (run `claude` to approve)`` | A project-scoped server you haven't approved yet. See [Edit .mcp.json directly](#edit-mcp-json-directly) |
63| `⊘ Disabled for this project (re-enable via /mcp)` | A server turned off for this project by the project's `disabledMcpServers` list. See [Disable a server without removing it](/docs/en/mcp#disable-a-server-without-removing-it) |
7064 
71 ```bash theme={null}
72 claude
73 ```
65Some legacy Windows consoles, such as the default console on Windows 10, don't support these Unicode glyphs and show `√` and `×` in place of `✔` and `✘`.
7466 
75 ```text wrap theme={null}
76 Use the claude-code-docs server to look up what MCP_TIMEOUT does
77 ```
67**3. Use the server**
7868 
79 <Info>
80 You don't normally need to name a server in your prompt, since Claude chooses relevant tools on its own. Naming it here guarantees the demonstration goes through the new server rather than another tool, such as web fetch, that could answer the same question.
81 </Info>
69Start a session and ask Claude to use the new server by name:
8270 
83 If Claude Code asks for permission the first time Claude calls the server, approve it. The tool call in Claude's output is labeled with the server name, which is how you confirm the answer came from the MCP server rather than Claude's built-in knowledge.
84 </Step>
71```bash theme={null}
72claude
73```
8574 
86 <Step title="Remove the server">
87 This step is optional. When you're done experimenting, you can remove the server:
75```text wrap theme={null}
76Use the claude-code-docs server to look up what MCP_TIMEOUT does
77```
8878 
89 ```bash theme={null}
90 claude mcp remove claude-code-docs
91 ```
79> [!NOTE]
80>
81> You don't normally need to name a server in your prompt, since Claude chooses relevant tools on its own. Naming it here guarantees the demonstration goes through the new server rather than another tool, such as web fetch, that could answer the same question.
9282 
93 The command confirms with `Removed MCP server "claude-code-docs" from local config` and a `File modified:` line showing the file it updated.
83If Claude Code asks for permission the first time Claude calls the server, approve it. The tool call in Claude's output is labeled with the server name, which is how you confirm the answer came from the MCP server rather than Claude's built-in knowledge.
9484 
95 <Note>
96 Each connected server takes some space in [Claude's context window](/docs/en/how-claude-code-works#the-context-window) because its tool names and server instructions load into every session. Removing servers you no longer use keeps that space free.
97 </Note>
98 </Step>
99</Steps>
85**4. Remove the server**
10086 
87This step is optional. When you're done experimenting, you can remove the server:
88 
89```bash theme={null}
90claude mcp remove claude-code-docs
91```
92 
93The command confirms with `Removed MCP server "claude-code-docs" from local config` and a `File modified:` line showing the file it updated.
94 
95> [!NOTE]
96>
97> Each connected server takes some space in [Claude's context window](/docs/en/how-claude-code-works#the-context-window) because its tool names and server instructions load into every session. Removing servers you no longer use keeps that space free.
98 
10199## Where servers are saved
102100 
103101The `claude mcp add` command writes the server's details to a configuration file. By default it registers the server at `local` scope: private to you, active only in the current project. Pass `--scope user` to register it once for all your projects, or `--scope project` to share it with teammates. [Change server scope](#change-server-scope) walks through both.
104102 
105<Note>
106 `claude mcp add` works the same in every shell, including PowerShell and Command Prompt. Inside a `claude` session, use the `/mcp` command to check and manage servers you've already added.
107</Note>
103> [!NOTE]
104>
105> `claude mcp add` works the same in every shell, including PowerShell and Command Prompt. Inside a `claude` session, use the `/mcp` command to check and manage servers you've already added.
108106 
109107There are other ways to add a server, each with its own section:
110108 
from line 160
162160 
163161The [Playwright MCP server](https://github.com/microsoft/playwright-mcp) is a good one to try: it gives Claude a browser it can navigate, click, and read, and it needs no account. It runs through `npx`, so it requires [Node.js](https://nodejs.org/en/download) 18 or later.
164162 
165<Steps>
166 <Step title="Add the Playwright server">
167 Register the server with the command Claude Code should run to start it:
163**1. Add the Playwright server**
168164 
169 ```bash theme={null}
170 claude mcp add playwright -- npx -y @playwright/mcp@latest
171 ```
165Register the server with the command Claude Code should run to start it:
172166 
173 This command differs from the hosted example in three ways:
167```bash theme={null}
168claude mcp add playwright -- npx -y @playwright/mcp@latest
169```
174170 
175 * There's no `--transport` flag, because local servers use the default `stdio` transport.
176 * Everything after the `--` separator is the command Claude Code runs to start the server.
177 * `-y` tells `npx` to install the package without prompting.
171This command differs from the hosted example in three ways:
178172 
179 The command prints a confirmation like `Added stdio MCP server playwright with command: npx -y @playwright/mcp@latest to local config`, followed by a `File modified:` line showing the configuration file it wrote.
173* There's no `--transport` flag, because local servers use the default `stdio` transport.
174* Everything after the `--` separator is the command Claude Code runs to start the server.
175* `-y` tells `npx` to install the package without prompting.
180176 
181 Playwright drives whichever Chrome is already installed on your machine. To use a different browser, append `--browser` with the browser name, for example `--browser firefox`, after `@playwright/mcp@latest`.
182 </Step>
177The command prints a confirmation like `Added stdio MCP server playwright with command: npx -y @playwright/mcp@latest to local config`, followed by a `File modified:` line showing the configuration file it wrote.
183178 
184 <Step title="Check the connection">
185 The `Added` confirmation means the entry was saved, not that the command runs. Check the connection:
179Playwright drives whichever Chrome is already installed on your machine. To use a different browser, append `--browser` with the browser name, for example `--browser firefox`, after `@playwright/mcp@latest`.
186180 
187 ```bash theme={null}
188 claude mcp list
189 ```
181**2. Check the connection**
190182 
191 The first check can show `✘ Failed to connect` while `npx` downloads the package, so wait a moment and run it again. Once the download finishes, the status changes to `✔ Connected`. If it still shows `✘ Failed to connect` after a couple of retries, see [Troubleshooting](#troubleshooting).
192 </Step>
183The `Added` confirmation means the entry was saved, not that the command runs. Check the connection:
193184 
194 <Step title="Use the browser">
195 Give Claude a task that needs the browser:
185```bash theme={null}
186claude mcp list
187```
196188 
197 ```text wrap theme={null}
198 Use playwright to open https://example.com and tell me the page title
199 ```
189The first check can show `✘ Failed to connect` while `npx` downloads the package, so wait a moment and run it again. Once the download finishes, the status changes to `✔ Connected`. If it still shows `✘ Failed to connect` after a couple of retries, see [Troubleshooting](#troubleshooting).
200190 
201 A browser window opens so you can watch it work, and the tool calls in Claude's output are labeled with the `playwright` server name and the action, like `browser_navigate`.
191**3. Use the browser**
202192 
203 Try pointing it at your local dev server to check that a page still renders after a change, or have it walk through a bug report step by step.
204 </Step>
205</Steps>
193Give Claude a task that needs the browser:
206194 
195```text wrap theme={null}
196Use playwright to open https://example.com and tell me the page title
197```
198 
199A browser window opens so you can watch it work, and the tool calls in Claude's output are labeled with the `playwright` server name and the action, like `browser_navigate`.
200 
201Try pointing it at your local dev server to check that a page still renders after a change, or have it walk through a bug report step by step.
202 
207203### Connect a server that requires sign-in
208204 
209205Hosted services like Sentry, Linear, and Notion run their MCP servers behind OAuth: you add the server's URL, then sign in through your browser.
from line 206
210206 
211207The steps below use Sentry as the example. To connect a different service, substitute its URL, which you can find in the [Anthropic Directory](/docs/en/mcp#find-and-build-mcp-servers) or the service's documentation.
212208 
213<Steps>
214 <Step title="Add the server">
215 The `add` command is the same as for the docs server, with Sentry's URL:
209**1. Add the server**
216210 
217 ```bash theme={null}
218 claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
219 ```
211The `add` command is the same as for the docs server, with Sentry's URL:
220212 
221 After adding, `claude mcp list` shows the server with `! Needs authentication`. That's expected: the next step completes the sign-in.
222 </Step>
213```bash theme={null}
214claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
215```
223216 
224 <Step title="Authenticate in your browser">
225 Start a Claude Code session and open the MCP panel:
217After adding, `claude mcp list` shows the server with `! Needs authentication`. That's expected: the next step completes the sign-in.
226218 
227 ```text wrap theme={null}
228 /mcp
229 ```
219**2. Authenticate in your browser**
230220 
231 Select `sentry` from the list, press Enter, and choose `Authenticate`. Your browser opens to Sentry's sign-in page. Approve the connection there.
221Start a Claude Code session and open the MCP panel:
232222 
233 Back in Claude Code, the server's status changes to connected. If sign-in fails or the browser doesn't open, see [Troubleshooting](#troubleshooting).
234 </Step>
223```text wrap theme={null}
224/mcp
225```
235226 
236 <Step title="Use the server">
237 Ask Claude something that needs the service, like `What Sentry projects do I have access to?`, and look for tool calls labeled with the `sentry` server name in its output.
238 </Step>
239</Steps>
227Select `sentry` from the list, press Enter, and choose `Authenticate`. Your browser opens to Sentry's sign-in page. Approve the connection there.
240228 
229Back in Claude Code, the server's status changes to connected. If sign-in fails or the browser doesn't open, see [Troubleshooting](#troubleshooting).
230 
231**3. Use the server**
232 
233Ask Claude something that needs the service, like `What Sentry projects do I have access to?`, and look for tool calls labeled with the `sentry` server name in its output.
234 
241235Servers that authenticate with a static token instead of OAuth take the token at add time with `--header "Authorization: Bearer <token>"`. See the [GitHub example](/docs/en/mcp#example-connect-to-github-for-code-reviews) for a worked version.
242236 
243237## Edit .mcp.json directly
from line 281
287281 
288282If a server doesn't connect, check its status with `/mcp` inside a session or `claude mcp list` from your shell, then match the symptom below. The `/mcp` panel also lets you reconnect or authenticate without leaving the session.
289283 
290<AccordionGroup>
291 <Accordion title="/mcp shows No MCP servers configured">
292 Claude Code didn't find any servers for the current directory. The most common causes:
284> **/mcp shows No MCP servers configured**
285>
286> Claude Code didn't find any servers for the current directory. The most common causes:
287>
288> * You ran `claude mcp add` from a different project. Local-scoped servers are tied to the project where you added them: the repository root, or the exact directory if you weren't in a git repository. Re-add the server from the project you're in now, or add it with `--scope user` so it isn't tied to a project.
289> * You edited a configuration file at the wrong path. The correct files are `~/.claude.json` and `<project>/.mcp.json`. Claude Code doesn't read paths such as `~/.claude/.mcp.json`, `~/.claude/config/mcp.json`, `~/.claude/mcp.json`, or `%APPDATA%\Claude\mcp.json`. For user-scoped servers, run `claude mcp add --scope user`, which writes to the `mcpServers` key in `~/.claude.json`; for project-scoped servers, edit `.mcp.json` at the project root.
290> * You wrote a malformed entry in `.mcp.json`. Claude Code skips that entry and still loads the others. Run `claude mcp list` from your shell and look for the parse warning, which names the offending field.
293291 
294 * You ran `claude mcp add` from a different project. Local-scoped servers are tied to the project where you added them: the repository root, or the exact directory if you weren't in a git repository. Re-add the server from the project you're in now, or add it with `--scope user` so it isn't tied to a project.
295 * You edited a configuration file at the wrong path. The correct files are `~/.claude.json` and `<project>/.mcp.json`. Claude Code doesn't read paths such as `~/.claude/.mcp.json`, `~/.claude/config/mcp.json`, `~/.claude/mcp.json`, or `%APPDATA%\Claude\mcp.json`. For user-scoped servers, run `claude mcp add --scope user`, which writes to the `mcpServers` key in `~/.claude.json`; for project-scoped servers, edit `.mcp.json` at the project root.
296 * You wrote a malformed entry in `.mcp.json`. Claude Code skips that entry and still loads the others. Run `claude mcp list` from your shell and look for the parse warning, which names the offending field.
297 </Accordion>
292> **Status shows Failed to connect or Connection error**
293>
294> Both statuses mean the server didn't start or the URL didn't respond. They can also appear for HTTP servers that reject the token you configured in `headers.Authorization`; a server that wants a token you haven't configured shows `! Needs authentication` instead, covered in [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in).
295>
296> Your first step depends on which status you see:
297>
298> * `Failed to connect`: start with the failure detail on the status itself. `claude mcp list` and `claude mcp get <name>` show the HTTP status or error code and any error text the server returned, which often names the problem directly, such as a missing header or a rejected token. Before v2.1.219, `Failed to connect` showed only the bare status, and you needed the curl and command checks later in this section to find the cause.
299> * `Connection error`: Claude Code appends no detail to this status on any version, so go straight to the curl and command checks later in this section.
300>
301> If the detail points to a credential or URL, also check the warnings in the `claude mcp list` output. Claude Code flags config values with hidden leading or trailing whitespace, a common cause of authentication failures after pasting a token.
302>
303> If an HTTP server returns `404 Not Found`, Claude Code shows `MCP endpoint not found at <origin>. Check the URL in your MCP config.` when you select the server in `/mcp`. The message names the URL's origin, such as `https://mcp.example.com`, without its path, so run `claude mcp get <name>` to see the full URL you configured. Compare its path to the server's documented MCP endpoint path, then run `claude mcp remove <name>` and re-add with the correct URL. Before v2.1.219, the message included the URL's path as well, and before v2.1.191, a `404` showed a generic `Error POSTing to endpoint` message without the URL.
304>
305> For HTTP servers, confirm the URL is reachable from your machine:
306>
307> ```bash theme={null}
308> curl -I https://mcp.sentry.dev/mcp
309> ```
310>
311> In PowerShell, use `curl.exe` instead of `curl` so the request goes to the real curl binary rather than the `Invoke-WebRequest` alias.
312>
313> The response tells you which kind of problem you have:
314>
315> * A `404` or `405`: the server is up. Many MCP endpoints answer only POST requests, so this still confirms the URL is reachable from your machine.
316> * A `401` or `403`: the server is up and you need to authenticate. Use the browser sign-in in [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in), or for servers that take a token instead, like GitHub's, pass it with `--header "Authorization: Bearer <token>"` on the `claude mcp add` command.
317> * No response at all: check the URL and your network.
318>
319> For stdio servers, run the configured command directly in your terminal to see the underlying error. For the Playwright server from this guide, run:
320>
321> ```bash theme={null}
322> npx -y @playwright/mcp@latest
323> ```
324>
325> What happens next tells you where the problem is:
326>
327> * The command starts and waits for input: the server itself works.
328>
329> Run `claude mcp get <name>` and confirm the command shown there matches what you just ran. If the command shown differs from what you typed, you likely omitted the `--` separator before the server command. Remove the server and re-add it with `--` in place. If you wrote `.mcp.json` by hand, check its syntax and location. Before v2.1.285, `claude mcp get` printed no `Command` line for a stdio entry saved without a `type` field, such as a hand-written `.mcp.json` entry. On those versions, run `claude mcp list` instead, which prints the command line either way.
330> * The command errors: the message names what's missing, such as Node.js or a browser.
298331 
299 <Accordion title="Status shows Failed to connect or Connection error">
300 Both statuses mean the server didn't start or the URL didn't respond. They can also appear for HTTP servers that reject the token you configured in `headers.Authorization`; a server that wants a token you haven't configured shows `! Needs authentication` instead, covered in [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in).
332> **Connection timed out at startup**
333>
334> The server took longer than the default 30-second startup timeout. A stdio server's first run can be slow while `npx` downloads the package. Increase the limit with the [`MCP_TIMEOUT`](/docs/en/env-vars) environment variable, in milliseconds:
335>
336> ```bash theme={null}
337> MCP_TIMEOUT=60000 claude
338> ```
339>
340> In PowerShell, set the variable before the command on the same line:
341>
342> ```powershell theme={null}
343> $env:MCP_TIMEOUT = "60000"; claude
344> ```
345>
346> Before v2.1.299, some connections to HTTP servers that were up timed out at startup regardless of `MCP_TIMEOUT`. If you use one of those versions and an HTTP server that is up still times out after you raise the limit, [update Claude Code](/docs/en/setup#update-claude-code).
301347 
302 Your first step depends on which status you see:
348> **Server already exists**
349>
350> You've already added a server with that name at the same scope. Either remove the existing entry first or choose a different name:
351>
352> ```bash theme={null}
353> claude mcp remove claude-code-docs
354> ```
355>
356> If the name exists at more than one scope, `remove` reports `exists in multiple scopes`. Pass `--scope` to choose which copy to delete, for example `claude mcp remove claude-code-docs --scope local`.
303357 
304 * `Failed to connect`: start with the failure detail on the status itself. `claude mcp list` and `claude mcp get <name>` show the HTTP status or error code and any error text the server returned, which often names the problem directly, such as a missing header or a rejected token. Before v2.1.219, `Failed to connect` showed only the bare status, and you needed the curl and command checks later in this section to find the cause.
305 * `Connection error`: Claude Code appends no detail to this status on any version, so go straight to the curl and command checks later in this section.
358> **Server connects but no tools appear**
359>
360> Run `/mcp` inside a session and select the server to see its tool list. If the list is empty, the server started but didn't register any tools, which usually means it's missing a required environment variable such as an API key.
361>
362> Pass the variable with `--env KEY=value` on `claude mcp add`, or in the `env` field of the server's `.mcp.json` entry. The server's documentation lists the variables it needs.
363>
364> Before v2.1.302, `/mcp` showed the status `tools fetch failed` for a server using [protocol revision 2026-07-28](/docs/en/mcp#mcp-client-runtimes) that left `resultType`, `ttlMs`, or `cacheScope` out of its replies. If you use one of those versions and a server shows that status, [update Claude Code](/docs/en/setup#update-claude-code).
306365 
307 If the detail points to a credential or URL, also check the warnings in the `claude mcp list` output. Claude Code flags config values with hidden leading or trailing whitespace, a common cause of authentication failures after pasting a token.
366> **Changes to .mcp.json don't take effect**
367>
368> Claude Code reads `.mcp.json` at session start. Exit and restart the session after editing the file.
369>
370> If your servers still don't appear, run `claude mcp list` and look for a parse warning. Claude Code skips malformed entries and shows the offending field there.
371>
372> If you previously rejected the server when prompted, reset project approvals:
373>
374> ```bash theme={null}
375> claude mcp reset-project-choices
376> ```
308377 
309 If an HTTP server returns `404 Not Found`, Claude Code shows `MCP endpoint not found at <origin>. Check the URL in your MCP config.` when you select the server in `/mcp`. The message names the URL's origin, such as `https://mcp.example.com`, without its path, so run `claude mcp get <name>` to see the full URL you configured. Compare its path to the server's documented MCP endpoint path, then run `claude mcp remove <name>` and re-add with the correct URL. Before v2.1.219, the message included the URL's path as well, and before v2.1.191, a `404` showed a generic `Error POSTing to endpoint` message without the URL.
310 
311 For HTTP servers, confirm the URL is reachable from your machine:
312 
313 ```bash theme={null}
314 curl -I https://mcp.sentry.dev/mcp
315 ```
316 
317 In PowerShell, use `curl.exe` instead of `curl` so the request goes to the real curl binary rather than the `Invoke-WebRequest` alias.
318 
319 The response tells you which kind of problem you have:
320 
321 * A `404` or `405`: the server is up. Many MCP endpoints answer only POST requests, so this still confirms the URL is reachable from your machine.
322 * A `401` or `403`: the server is up and you need to authenticate. Use the browser sign-in in [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in), or for servers that take a token instead, like GitHub's, pass it with `--header "Authorization: Bearer <token>"` on the `claude mcp add` command.
323 * No response at all: check the URL and your network.
324 
325 For stdio servers, run the configured command directly in your terminal to see the underlying error. For the Playwright server from this guide, run:
326 
327 ```bash theme={null}
328 npx -y @playwright/mcp@latest
329 ```
330 
331 What happens next tells you where the problem is:
332 
333 * The command starts and waits for input: the server itself works.
334 
335 Run `claude mcp get <name>` and confirm the command shown there matches what you just ran. If the command shown differs from what you typed, you likely omitted the `--` separator before the server command. Remove the server and re-add it with `--` in place. If you wrote `.mcp.json` by hand, check its syntax and location. Before v2.1.285, `claude mcp get` printed no `Command` line for a stdio entry saved without a `type` field, such as a hand-written `.mcp.json` entry. On those versions, run `claude mcp list` instead, which prints the command line either way.
336 * The command errors: the message names what's missing, such as Node.js or a browser.
337 </Accordion>
338 
339 <Accordion title="Connection timed out at startup">
340 The server took longer than the default 30-second startup timeout. A stdio server's first run can be slow while `npx` downloads the package. Increase the limit with the [`MCP_TIMEOUT`](/docs/en/env-vars) environment variable, in milliseconds:
341 
342 ```bash theme={null}
343 MCP_TIMEOUT=60000 claude
344 ```
345 
346 In PowerShell, set the variable before the command on the same line:
347 
348 ```powershell theme={null}
349 $env:MCP_TIMEOUT = "60000"; claude
350 ```
351 
352 Before v2.1.299, some connections to HTTP servers that were up timed out at startup regardless of `MCP_TIMEOUT`. If you use one of those versions and an HTTP server that is up still times out after you raise the limit, [update Claude Code](/docs/en/setup#update-claude-code).
353 </Accordion>
354 
355 <Accordion title="Server already exists">
356 You've already added a server with that name at the same scope. Either remove the existing entry first or choose a different name:
357 
358 ```bash theme={null}
359 claude mcp remove claude-code-docs
360 ```
361 
362 If the name exists at more than one scope, `remove` reports `exists in multiple scopes`. Pass `--scope` to choose which copy to delete, for example `claude mcp remove claude-code-docs --scope local`.
363 </Accordion>
364 
365 <Accordion title="Server connects but no tools appear">
366 Run `/mcp` inside a session and select the server to see its tool list. If the list is empty, the server started but didn't register any tools, which usually means it's missing a required environment variable such as an API key.
367 
368 Pass the variable with `--env KEY=value` on `claude mcp add`, or in the `env` field of the server's `.mcp.json` entry. The server's documentation lists the variables it needs.
369 </Accordion>
370 
371 <Accordion title="Changes to .mcp.json don't take effect">
372 Claude Code reads `.mcp.json` at session start. Exit and restart the session after editing the file.
373 
374 If your servers still don't appear, run `claude mcp list` and look for a parse warning. Claude Code skips malformed entries and shows the offending field there.
375 
376 If you previously rejected the server when prompted, reset project approvals:
377 
378 ```bash theme={null}
379 claude mcp reset-project-choices
380 ```
381 </Accordion>
382 
383 <Accordion title="OAuth sign-in fails or browser doesn't open">
384 Run `/mcp`, select the server, and choose `Authenticate` again. If the browser doesn't open automatically, copy the URL shown in the terminal and open it manually. See [Authenticate with remote MCP servers](/docs/en/mcp#authenticate-with-remote-mcp-servers) for fixed callback ports and pre-configured credentials.
385 </Accordion>
386</AccordionGroup>
378> **OAuth sign-in fails or browser doesn't open**
379>
380> Run `/mcp`, select the server, and choose `Authenticate` again. If the browser doesn't open automatically, copy the URL shown in the terminal and open it manually. See [Authenticate with remote MCP servers](/docs/en/mcp#authenticate-with-remote-mcp-servers) for fixed callback ports and pre-configured credentials.
387381 
388382## Next steps
389383 

memory Changed · +35 / -39 lines

#### Rule frontmatter reference

from line 52
5252 
5353| Scope | Location | Purpose | Use case examples | Shared with |
5454| - | - | - | - | - |
55| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`<br />• Linux and WSL: `/etc/claude-code/CLAUDE.md`<br />• Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |
55| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md` • Linux and WSL: `/etc/claude-code/CLAUDE.md` • Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |
5656| **User instructions** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Only you (all projects) |
5757| **Project instructions** | `./CLAUDE.md` or `./.claude/CLAUDE.md`. See [AGENTS.md](#agents-md) for when `./AGENTS.md` loads instead of or alongside them | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |
5858| **Local instructions** | `./CLAUDE.local.md` | Personal project-specific preferences; add to `.gitignore` | Your sandbox URLs, preferred test data | Only you (current project) |
from line 65
6565 
6666A 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**.
6767 
68<Tip>
69 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.
68> [!TIP]
69>
70> 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.
71>
72> 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](/docs/en/env-vars#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.
7073 
71 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](/docs/en/env-vars#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.
72</Tip>
73 
7474### Write effective instructions
7575 
7676Claude treats CLAUDE.md files as context, not enforced configuration, so how you write instructions affects how reliably Claude follows them. Write instructions that are concrete enough to verify:
from line 125
125125- @~/.claude/my-project-instructions.md
126126```
127127 
128<Warning>
129 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.
128> [!WARNING]
129>
130> 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.
131>
132> 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](https://claude.com/product/cowork) sessions on your desktop, Claude Code loads their imports without the dialog and trusts them like the rest of your personal configuration.
133>
134> 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.
130135 
131 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](https://claude.com/product/cowork) sessions on your desktop, Claude Code loads their imports without the dialog and trusts them like the rest of your personal configuration.
132 
133 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.
134</Warning>
135 
136136### How CLAUDE.md files load
137137 
138138Claude 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.
from line 163
163163 
164164For 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.
165165 
166<Note>
167 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](/docs/en/skills) instead, which only load when you invoke them or when Claude determines they're relevant to your prompt.
168</Note>
166> [!NOTE]
167>
168> 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](/docs/en/skills) instead, which only load when you invoke them or when Claude determines they're relevant to your prompt.
169169 
170170#### Set up rules
171171 
from line 230
230230 
231231Glob 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/**`.
232232 
233<h4 id="rules-frontmatter-reference">
234 Rule frontmatter reference
235</h4>
233#### Rule frontmatter reference
236234 
237235Configure a rule with YAML [frontmatter](/docs/en/glossary#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.
238236 
from line 277
279277 
280278Organizations can deploy a centrally managed CLAUDE.md that applies to all users on a machine. This file cannot be excluded by individual settings.
281279 
282<Steps>
283 <Step title="Create the file at the managed policy location">
284 * macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`
285 * Linux and WSL: `/etc/claude-code/CLAUDE.md`
286 * Windows: `C:\Program Files\ClaudeCode\CLAUDE.md`
287 </Step>
280**1. Create the file at the managed policy location**
288281 
289 <Step title="Deploy with your configuration management system">
290 Use MDM, Group Policy, Ansible, or similar tools to distribute the file across developer machines. See [managed settings](/docs/en/managed-settings) for other organization-wide configuration options.
291 </Step>
292</Steps>
282* macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`
283* Linux and WSL: `/etc/claude-code/CLAUDE.md`
284* Windows: `C:\Program Files\ClaudeCode\CLAUDE.md`
293285 
286**2. Deploy with your configuration management system**
287 
288Use MDM, Group Policy, Ansible, or similar tools to distribute the file across developer machines. See [managed settings](/docs/en/managed-settings) for other organization-wide configuration options.
289 
294290The `claudeMd` key lets you put managed CLAUDE.md content directly inside `managed-settings.json` instead of deploying a separate file.
295291 
296292**Scope**: every Claude Code session on the machine, in every repository. For repository-specific guidance, commit a project CLAUDE.md instead.
from line 350
354350 
355351To 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).
356352 
357<Note>
358 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.
359</Note>
353> [!NOTE]
354>
355> 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.
360356 
361357### When Claude Code reads AGENTS.md
362358 
from line 368
372368* **Inside each `AGENTS.md`**: [`@path` imports](#import-additional-files) are expanded, [`claudeMdExcludes`](#exclude-specific-claude-md-files) patterns apply, and subagents that [start without project instructions](/docs/en/sub-agents#what-loads-at-startup) start without these files too
373369* **Not read**: `AGENTS.local.md`, `AGENTS.override.md`, or anything under a `.agents/` directory
374370 
375<Note>
376 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).
377</Note>
371> [!NOTE]
372>
373> 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).
378374 
379375### Choose which instruction files load
380376 
from line 583
587583 
588584For instructions you want at the system prompt level, use [`--append-system-prompt`](/docs/en/cli-reference#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](/docs/en/cli-reference#system-prompt-flags-in-resumed-conversations).
589585 
590<Tip>
591 Use the [`InstructionsLoaded` hook](/docs/en/hooks#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.
592</Tip>
586> [!TIP]
587>
588> Use the [`InstructionsLoaded` hook](/docs/en/hooks#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.
593589 
594590### My AGENTS.md isn't loading
595591 

microsoft-foundry Changed · +12 / -79 lines

from line 2
22 
33> Learn about configuring Claude Code through Microsoft Foundry, including setup, configuration, and troubleshooting.
44 
5export const ContactSalesCard = ({surface}) => {
6 const utm = content => `utm_source=claude_code&utm_medium=docs&utm_content=${surface}_${content}`;
7 const iconArrowRight = (size = 13) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
8 <line x1="5" y1="12" x2="19" y2="12" />
9 <polyline points="12 5 19 12 12 19" />
10 </svg>;
11 const STYLES = `
12.cc-cs {
13 --cs-slate: #141413;
14 --cs-clay: #d97757;
15 --cs-clay-deep: #c6613f;
16 --cs-gray-000: #ffffff;
17 --cs-gray-700: #3d3d3a;
18 --cs-border-default: rgba(31, 30, 29, 0.15);
19 font-family: inherit;
20}
21.dark .cc-cs {
22 --cs-slate: #f0eee6;
23 --cs-gray-000: #262624;
24 --cs-gray-700: #bfbdb4;
25 --cs-border-default: rgba(240, 238, 230, 0.14);
26}
27.cc-cs-card {
28 display: flex; align-items: center; justify-content: space-between;
29 gap: 16px; padding: 14px 16px; margin: 0;
30 background: var(--cs-gray-000); border: 0.5px solid var(--cs-border-default);
31 border-radius: 8px; flex-wrap: wrap;
32}
33.cc-cs-text { font-size: 13px; color: var(--cs-gray-700); line-height: 1.5; flex: 1; min-width: 240px; }
34.cc-cs-text strong { font-weight: 550; color: var(--cs-slate); }
35.cc-cs-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
36.cc-cs-btn-clay {
37 display: inline-flex; align-items: center; gap: 8px;
38 background: var(--cs-clay-deep); color: #fff; border: none;
39 border-radius: 8px; padding: 8px 14px;
40 font-size: 13px; font-weight: 500;
41 transition: background-color 0.15s; white-space: nowrap;
42}
43.cc-cs-btn-clay:hover { background: var(--cs-clay); }
44.cc-cs-btn-ghost {
45 display: inline-flex; align-items: center; gap: 8px;
46 background: transparent; color: var(--cs-gray-700);
47 border: 0.5px solid var(--cs-border-default);
48 border-radius: 8px; padding: 8px 14px;
49 font-size: 13px; font-weight: 500;
50}
51.cc-cs-btn-ghost:hover { background: rgba(0, 0, 0, 0.04); }
52.dark .cc-cs-btn-ghost:hover { background: rgba(255, 255, 255, 0.04); }
53@media (max-width: 720px) {
54 .cc-cs-actions { width: 100%; }
55}
56`;
57 return <div className="cc-cs not-prose">
58 <style>{STYLES}</style>
59 <div className="cc-cs-card">
60 <div className="cc-cs-text">
61 <strong>Deploying Claude Code across your organization?</strong> Talk to sales about enterprise plans, SSO, and centralized billing.
62 </div>
63 <div className="cc-cs-actions">
64 <a href={`https://claude.com/pricing?${utm('view_plans')}#plans-business`} className="cc-cs-btn-ghost">
65 View plans
66 </a>
67 <a href={`https://claude.com/contact-sales?${utm('contact_sales')}`} className="cc-cs-btn-clay">
68 Contact sales {iconArrowRight()}
69 </a>
70 </div>
71 </div>
72 </div>;
73};
5**Deploying Claude Code across your organization?** Talk to sales about enterprise plans, SSO, and centralized billing.
746 
75<ContactSalesCard surface="foundry" />
7View plans
8Contact sales
769 
7710## Prerequisites
7811 
from line 15
8215* RBAC permissions to create Microsoft Foundry resources and deployments
8316* Azure CLI installed and configured (optional - only needed if you don't have another mechanism for getting credentials)
8417 
85<Note>
86 If you are deploying Claude Code to multiple users, [pin your model versions](#4-pin-model-versions) before rolling out.
87</Note>
18> [!NOTE]
19>
20> If you are deploying Claude Code to multiple users, [pin your model versions](#4-pin-model-versions) before rolling out.
8821 
8922## Setup
9023 
from line 43
11043* [Microsoft Entra ID](#use-microsoft-entra-id): Claude Code gets tokens through the Azure SDK default credential chain, for example from an `az login` session, so there's no API key to store
11144* [Bearer token](#use-a-bearer-token): another process obtains a Microsoft Entra ID access token and you pass it in `ANTHROPIC_FOUNDRY_AUTH_TOKEN`
11245 
113<Note>
114 When using Microsoft Foundry, the `/logout` command is unavailable since authentication is handled through Azure credentials.
115</Note>
46> [!NOTE]
47>
48> When using Microsoft Foundry, the `/logout` command is unavailable since authentication is handled through Azure credentials.
11649 
11750#### Use an API key
11851 
from line 103
170103 
171104### 4. Pin model versions
172105 
173<Warning>
174 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."
175</Warning>
106> [!WARNING]
107>
108> 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."
176109 
177110Set the model variables to match the deployment names you created in step 1.
178111 

mobile Changed · +15 / -17 lines

from line 4
44 
55The 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) is a client for Claude Code sessions rather than a place where code runs. From your phone you reach [cloud sessions](#start-and-monitor-cloud-sessions) and [projects](/docs/en/claude-projects) in the cloud, a session running on your own machine through [Remote Control](#continue-a-local-session-with-remote-control), or the Desktop app through [Dispatch](/docs/en/desktop#sessions-from-dispatch).
66 
7<Note>
8 Claude Code doesn't have a separate mobile app: cloud sessions and Remote Control both live in the **Code** tab in the Claude app, and Dispatch is a task you message in the app.
9</Note>
7> [!NOTE]
8>
9> Claude Code doesn't have a separate mobile app: cloud sessions and Remote Control both live in the **Code** tab in the Claude app, and Dispatch is a task you message in the app.
1010 
1111## Get the app
1212 
13<Steps>
14 <Step title="Download the Claude app">
15 Install 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). On an iPad, install the same iOS app.
13**1. Download the Claude app**
1614 
17 <Tip>
18 Run `/mobile` in a Claude Code session to show a QR code for [claude.ai/mobile](https://claude.ai/mobile), which opens the right app store for your phone. `/ios` and `/android` do the same thing.
19 </Tip>
20 </Step>
15Install 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). On an iPad, install the same iOS app.
2116 
22 <Step title="Sign in">
23 Sign in with the same claude.ai account and organization you use for Claude Code. Cloud sessions and Remote Control require a claude.ai account, so they aren't reachable with an Anthropic Console API key or from a third-party provider such as Amazon Bedrock.
24 </Step>
17> [!TIP]
18>
19> Run `/mobile` in a Claude Code session to show a QR code for [claude.ai/mobile](https://claude.ai/mobile), which opens the right app store for your phone. `/ios` and `/android` do the same thing.
2520 
26 <Step title="Open the Code tab">
27 Tap **Code** in the app's navigation to reach your sessions, or open [claude.ai/code/new](https://claude.ai/code/new) on your phone to start a new Code session in the app. If you don't see the Code tab, your plan or organization may not include these features; see [availability by subscription plan](/docs/en/feature-availability#availability-by-subscription-plan).
28 </Step>
29</Steps>
21**2. Sign in**
22 
23Sign in with the same claude.ai account and organization you use for Claude Code. Cloud sessions and Remote Control require a claude.ai account, so they aren't reachable with an Anthropic Console API key or from a third-party provider such as Amazon Bedrock.
24 
25**3. Open the Code tab**
26 
27Tap **Code** in the app's navigation to reach your sessions, or open [claude.ai/code/new](https://claude.ai/code/new) on your phone to start a new Code session in the app. If you don't see the Code tab, your plan or organization may not include these features; see [availability by subscription plan](/docs/en/feature-availability#availability-by-subscription-plan).
3028 
3129## Work from your phone
3230 

model-config Changed · +25 / -41 lines

#### Values and warnings for `CLAUDE_CODE_AUTO_COMPACT_WINDOW` #### Which IDs `CLAUDE_CODE_MAX_CONTEXT_TOKENS` applies to

from line 15
1515 
1616For 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.
1717 
18<Note>
19 `ANTHROPIC_BASE_URL` changes where requests are sent, not which model answers them. To route Claude through an LLM gateway, see [LLM gateways](/docs/en/llm-gateway).
20</Note>
18> [!NOTE]
19>
20> `ANTHROPIC_BASE_URL` changes where requests are sent, not which model answers them. To route Claude through an LLM gateway, see [LLM gateways](/docs/en/llm-gateway).
2121 
2222### Model aliases
2323 
from line 44
4444| Amazon Bedrock, Google Cloud's Agent Platform | Opus 5.5 | Sonnet 4.5 | Haiku 4.5 |
4545| Microsoft Foundry | Opus 4.6 | Sonnet 4.5 | Haiku 4.5 |
4646 
47<span id="fable-alias-resolution" />
48 
4947Unless you set `ANTHROPIC_DEFAULT_FABLE_MODEL`, the `fable` alias resolves to Fable 5.1, except in [Claude apps gateway](/docs/en/claude-apps-gateway) sessions, where `fable` and `best` resolve to Fable 5.
5048 
5149A 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`.
from line 54
5654 
5755Aliases 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`.
5856 
59<Note>
60 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](/docs/en/errors#claude-code-does-not-support-this-model). Use v2.1.293 or later with Haiku 5.5. Run `claude update` to upgrade.
61</Note>
57> [!NOTE]
58>
59> 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](/docs/en/errors#claude-code-does-not-support-this-model). Use v2.1.293 or later with Haiku 5.5. Run `claude update` to upgrade.
6260 
6361### Work with Fable
6462 
from line 78
8078* **Skip the verification reminders**: it verifies its own work with less prompting, so reminders to test or check are usually unnecessary.
8179* **Size up larger tasks**: give it work you would normally break into pieces. It holds long sessions without losing the thread.
8280 
83<Note>
84 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](/docs/en/errors#claude-code-does-not-support-this-model). Run `claude update` to upgrade. For availability under zero data retention, see [Model availability under ZDR](/docs/en/zero-data-retention#model-availability-under-zdr).
85</Note>
81> [!NOTE]
82>
83> 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](/docs/en/errors#claude-code-does-not-support-this-model). Run `claude update` to upgrade. For availability under zero data retention, see [Model availability under ZDR](/docs/en/zero-data-retention#model-availability-under-zdr).
8684 
8785On 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](/docs/en/zero-data-retention#model-availability-under-zdr), the row stays in the picker grayed out, with a note on why.
8886 
from line 616
618616 
619617`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.
620618 
621<Note>
622 A level you pick from the effort control on a phone or browser connected through [Remote Control](/docs/en/remote-control#what-connected-devices-see) applies to that session only.
623</Note>
619> [!NOTE]
620>
621> A level you pick from the effort control on a phone or browser connected through [Remote Control](/docs/en/remote-control#what-connected-devices-see) applies to that session only.
624622 
625<span id="non-interactive-effort" />
626 
627623When you set a level with `/effort` in a [`-p` run](/docs/en/headless), Claude Code applies it to that session only and doesn't save it as your default.
628624 
629625The `/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](/docs/en/workflows) for substantive tasks, at whichever effort level the session runs at. For where it can be set persistently, see the [`ultracode`](/docs/en/settings-reference#ultracode) setting.
from line 638
642638 
643639The 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.
644640 
645<span id="when-ultracode-is-available" />
646 
647641Ultracode is unavailable when:
648642 
649643* [Workflows are turned off](/docs/en/workflows#turn-workflows-off)
from line 708
714708 
715709Claude 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](/docs/en/settings) if you want the full summaries available when you expand. You are charged for all thinking tokens generated, even when collapsed or redacted.
716710 
717<a id="extended-context-with-1m" />
718 
719<span id="sonnet-5-5-and-sonnet-5-context-window" />
720 
721711### Extended context
722712 
723713Fable 5.1, Fable 5, Sonnet 5 and later, Haiku 5.5, Opus 4.6 and later, and Sonnet 4.6 support a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) for long sessions with large codebases.
from line 739
749739/model opus[1m]
750740```
751741 
752<span id="context-window-behind-a-gateway" />
753 
754742#### Context window behind an LLM gateway
755743 
756744If you set `ANTHROPIC_BASE_URL` to an [LLM gateway](/docs/en/llm-gateway) or another proxy, Claude Code gives each model it recognizes the same context window the model has on the Anthropic API. Fable 5.1, Fable 5, Sonnet 5 and later, Haiku 5.5, and Opus 4.7 and later get the 1M window with no `[1m]` variant to select, and a model that reaches 1M only through its `[1m]` variant, such as Opus 4.6, runs at 200K without it. Claude Code can't detect a lower limit that the gateway or the server behind it enforces. If your gateway rejects requests above 200K tokens, set [`CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000`](/docs/en/env-vars) in the environment that starts Claude Code, so sessions on every model [compact at that boundary](#set-the-auto-compact-window).
from line 764
776764 
777765### Set the auto-compact window
778766 
779<Note>
780 If Claude Code warned about the value of `CLAUDE_CODE_AUTO_COMPACT_WINDOW`, see [the variable's values and warnings](#claude_code_auto_compact_window-values).
781</Note>
767> [!NOTE]
768>
769> If Claude Code warned about the value of `CLAUDE_CODE_AUTO_COMPACT_WINDOW`, see [the variable's values and warnings](#claude_code_auto_compact_window-values).
782770 
783771You can set the auto-compact window in these places:
784772 
from line 784
796784 
797785Whichever way you set the window, Claude Code caps it at the model's context window.
798786 
799<h4 id="claude_code_auto_compact_window-values">
800 Values and warnings for `CLAUDE_CODE_AUTO_COMPACT_WINDOW`
801</h4>
787#### Values and warnings for `CLAUDE_CODE_AUTO_COMPACT_WINDOW`
802788 
803789A warning that quotes your `CLAUDE_CODE_AUTO_COMPACT_WINDOW` value means the value falls outside 100,000 to 1,000,000 or isn't a token count. To stop the warning, set a number in that range, such as `CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000`. On Claude Code v2.1.304 or later, you can also write the number with `k` for thousands or `M` for millions, as in `200k` or `1M`.
804790 
from line 828
842828 
843829Once Claude Code recognizes the ID or uses the window you gave it, the warning no longer appears when you start a session on that ID.
844830 
845<h4 id="which-ids-claude_code_max_context_tokens-applies-to">
846 Which IDs `CLAUDE_CODE_MAX_CONTEXT_TOKENS` applies to
847</h4>
831#### Which IDs `CLAUDE_CODE_MAX_CONTEXT_TOKENS` applies to
848832 
849833On an [LLM gateway](/docs/en/llm-gateway) 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`](/docs/en/env-vars) to the window Claude Code should assume instead.
850834 
from line 905
921905 
922906On 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.
923907 
924<Warning>
925 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.
926</Warning>
908> [!WARNING]
909>
910> 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.
927911 
928912Use the following environment variables with version-specific model IDs for your provider:
929913 
from line 935
951935 
952936When 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.
953937 
954<Note>
955 An `availableModels` allowlist delivered through [MDM or a managed settings file](/docs/en/managed-settings#delivery-mechanisms) still applies when using third-party providers; [server-managed settings are not delivered there](/docs/en/server-managed-settings#platform-availability).
956 
957 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.
958</Note>
938> [!NOTE]
939>
940> An `availableModels` allowlist delivered through [MDM or a managed settings file](/docs/en/managed-settings#delivery-mechanisms) still applies when using third-party providers; [server-managed settings are not delivered there](/docs/en/server-managed-settings#platform-availability).
941>
942> 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.
959943 
960944### Customize pinned model display and capabilities
961945 

monitoring-usage Changed · +38 / -44 lines

from line 4
44 
55Track Claude Code usage, costs, and tool activity across your organization by exporting telemetry data through OpenTelemetry (OTel). Claude Code exports metrics as time series data via the standard metrics protocol, events via the logs/events protocol, and optionally [distributed traces via OpenTelemetry](#traces-beta).
66 
7<Note>
8 For the Claude API or Managed Agents, see [OpenTelemetry for the Claude API](https://platform.claude.com/docs/en/manage-claude/opentelemetry).
9</Note>
7> [!NOTE]
8>
9> For the Claude API or Managed Agents, see [OpenTelemetry for the Claude API](https://platform.claude.com/docs/en/manage-claude/opentelemetry).
1010 
1111## Quick start
1212 
from line 274
274274| `skill_name` | Skill name for the Skill tool | `OTEL_LOG_TOOL_DETAILS` |
275275| `subagent_type` | Subagent type for the Agent tool or legacy Task tool | `OTEL_LOG_TOOL_DETAILS` |
276276 
277<span id="tool-output-span-event" />**`tool.output` span event on `claude_code.tool`**
277**`tool.output` span event on `claude_code.tool`**
278278 
279279If you set `OTEL_LOG_TOOL_CONTENT=1`, Read and Bash calls can record a `tool.output` span event on the `claude_code.tool` span. Edit and Write calls record one only when you also set `OTEL_LOG_TOOL_DETAILS=1`. That variable isn't scoped to those two tools, so check its [row in the configuration table](#common-configuration-variables) for the arguments it adds elsewhere.
280280 
from line 338
338338| `num_non_blocking_error` | Count of hooks that failed without blocking | |
339339| `num_cancelled` | Count of hooks cancelled before completion | |
340340 
341<span id="new-context-gates" />
342 
343341**Content attributes under detailed beta tracing**
344342 
345<Note>
346 Additional content-bearing attributes such as `new_context`, `system_reminders`, `system_prompt_preview`, `user_system_prompt`, `tool_input`, and `response.model_output` are emitted only when detailed beta tracing is active. They are not part of the stable span schema.
347</Note>
343> [!NOTE]
344>
345> Additional content-bearing attributes such as `new_context`, `system_reminders`, `system_prompt_preview`, `user_system_prompt`, `tool_input`, and `response.model_output` are emitted only when detailed beta tracing is active. They are not part of the stable span schema.
348346 
349347These attributes appear on the spans below, and `Gated by` names the variable an attribute needs on top of detailed beta tracing. Values longer than the content limit (60 KB by default) are truncated.
350348 
from line 416
418416 
419417Each custom key becomes a label on every metric series, so high-cardinality values increase storage cost in your metrics backend. To send custom attributes in the resource block only and omit them from datapoint labels, set `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES=false`. See [Metrics cardinality control](#metrics-cardinality-control).
420418 
421<Warning>
422 The `OTEL_RESOURCE_ATTRIBUTES` environment variable uses comma-separated key=value pairs with strict formatting requirements:
419> [!WARNING]
420>
421> The `OTEL_RESOURCE_ATTRIBUTES` environment variable uses comma-separated key=value pairs with strict formatting requirements:
422>
423> * **No spaces allowed**: values can't contain spaces. For example, `user.organizationName=My Company` is invalid
424> * **Format**: must be comma-separated key=value pairs: `key1=value1,key2=value2`
425> * **Allowed characters**: only US-ASCII characters excluding control characters, whitespace, double quotes, commas, semicolons, and backslashes
426> * **Special characters**: characters outside the allowed range must be percent-encoded
427>
428> For a value that would need a space, use underscores or camelCase instead. The following examples set `org.name` with each form:
429>
430> ```bash theme={null}
431> export OTEL_RESOURCE_ATTRIBUTES="org.name=Johns_Organization"
432> export OTEL_RESOURCE_ATTRIBUTES="org.name=JohnsOrganization"
433> ```
434>
435> You can percent-encode any character, not only the excluded ones. This example encodes both the space and the apostrophe:
436>
437> ```bash theme={null}
438> export OTEL_RESOURCE_ATTRIBUTES="org.name=John%27s%20Organization"
439> ```
440>
441> Wrapping values in quotes doesn't escape spaces. For example, `org.name="My Company"` results in the literal value `"My Company"` with the quotes included, not `My Company`.
423442 
424 * **No spaces allowed**: values can't contain spaces. For example, `user.organizationName=My Company` is invalid
425 * **Format**: must be comma-separated key=value pairs: `key1=value1,key2=value2`
426 * **Allowed characters**: only US-ASCII characters excluding control characters, whitespace, double quotes, commas, semicolons, and backslashes
427 * **Special characters**: characters outside the allowed range must be percent-encoded
428 
429 For a value that would need a space, use underscores or camelCase instead. The following examples set `org.name` with each form:
430 
431 ```bash theme={null}
432 export OTEL_RESOURCE_ATTRIBUTES="org.name=Johns_Organization"
433 export OTEL_RESOURCE_ATTRIBUTES="org.name=JohnsOrganization"
434 ```
435 
436 You can percent-encode any character, not only the excluded ones. This example encodes both the space and the apostrophe:
437 
438 ```bash theme={null}
439 export OTEL_RESOURCE_ATTRIBUTES="org.name=John%27s%20Organization"
440 ```
441 
442 Wrapping values in quotes doesn't escape spaces. For example, `org.name="My Company"` results in the literal value `"My Company"` with the quotes included, not `My Company`.
443</Warning>
444 
445443### Attribute telemetry to Desktop SSH sessions
446444 
447445To see which remote machine a [Desktop SSH session](/docs/en/desktop#ssh-sessions) ran on, name each machine in a custom attribute. Metrics and events don't name the machine a session ran on.
from line 589
591589 
592590In sessions signed in to a [Claude apps gateway](/docs/en/claude-apps-gateway) through `/login`, the CLI stamps exports with the authenticated identity: `user.id` is the IdP subject, `user.email` is the signed-in email, and `user.groups` carries IdP group membership as a comma-separated string. Each export also carries `identity.source: gateway-oidc`. The gateway identity is applied last, so `user.*` and `identity.*` keys set through `OTEL_RESOURCE_ATTRIBUTES` are ignored on those sessions.
593591 
594<Note>
595 Events that Claude Code logs before a developer signs in don't carry the gateway identity. When Claude Code opens a session signed out of the gateway, for example after [the gateway ends the sign-in](/docs/en/errors#cloud-gateway-session-expired), the startup events logged before sign-in carry the anonymous `user.id` and no `identity.source`. These include [`managed_settings_resolved`](#managed-settings-resolved-event), [`plugin_loaded`](#plugin-loaded-event), and [`mcp_server_connection`](#mcp-server-connection-event).
596</Note>
592> [!NOTE]
593>
594> Events that Claude Code logs before a developer signs in don't carry the gateway identity. When Claude Code opens a session signed out of the gateway, for example after [the gateway ends the sign-in](/docs/en/errors#cloud-gateway-session-expired), the startup events logged before sign-in carry the anonymous `user.id` and no `identity.source`. These include [`managed_settings_resolved`](#managed-settings-resolved-event), [`plugin_loaded`](#plugin-loaded-event), and [`mcp_server_connection`](#mcp-server-connection-event).
597595 
598596For the identity attributes on Claude Desktop and Cowork sessions that connect through a gateway, see the [gateway `telemetry` reference](/docs/en/claude-apps-gateway-config#telemetry).
599597 
from line 1016
10181016 * For Skill tool: includes `skill_name`
10191017 * For Agent tool or legacy Task tool: includes `subagent_type`
10201018 
1019If you lower the OpenTelemetry SDK's `OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT` below the number of attributes on a `tool_decision` event, the SDK drops the attributes that Claude Code set last. The SDK drops `permission_mode` first, `classifier_category` second, and `classifier_verdict` third, and drops the event's other attributes only after those three. This ordering requires Claude Code v2.1.302 or later.
1020 
10211021#### Permission mode changed event
10221022 
10231023Logged when the permission mode changes, for example from `Shift+Tab` cycling, exiting plan mode, or an auto mode gate check.
from line 1447
14471447* Identifying high-usage sessions for optimization
14481448* Attributing spend to specific skills, plugins, or subagent types via the `skill.name`, `plugin.name`, and `agent.name` attributes
14491449 
1450<Note>
1451 Cost metrics are approximations. For official billing data, refer to your API provider (Claude Console, Amazon Bedrock, or Google Cloud's Agent Platform).
1452</Note>
1450> [!NOTE]
1451>
1452> Cost metrics are approximations. For official billing data, refer to your API provider (Claude Console, Amazon Bedrock, or Google Cloud's Agent Platform).
14531453 
14541454Claude Code counts each streaming response toward the cost and token metrics exactly once, including when a gateway or proxy behind `ANTHROPIC_BASE_URL` streams usage progressively across multiple frames.
14551455 
from line 1624
16241624 
16251625Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:
16261626 
1627<span id="for-metrics" />
1628 
16291627### Backends for metrics
16301628 
16311629* **Time series databases**: Rate calculations, aggregated metrics
from line 1630
16321630* **Columnar stores**: Complex queries, unique user analysis
16331631* **Full-featured observability platforms**: Advanced querying, visualization, alerting
16341632 
1635<span id="for-events/logs" />
1636 
16371633### Backends for events and logs
16381634 
16391635* **Log aggregation systems**: Full-text search, log analysis
16401636* **Columnar stores**: Structured event analysis
16411637* **Full-featured observability platforms**: Correlation between metrics and events
1642 
1643<span id="for-traces" />
16441638 
16451639### Backends for traces
16461640 

network-config Changed · +19 / -19 lines

from line 6
66 
77Set these environment variables before you launch Claude Code. Variables exported in your shell are read once at startup, so a running session doesn't pick up later changes to your shell environment.
88 
9<Note>
10 All environment variables shown on this page can also be configured in [`settings.json`](/docs/en/settings).
11</Note>
9> [!NOTE]
10>
11> All environment variables shown on this page can also be configured in [`settings.json`](/docs/en/settings).
1212 
1313## Proxy configuration
1414 
from line 35
3535 
3636Claude Code never sends its WebSocket connections to `localhost`, `::1`, or `127.0.0.0/8` through the proxy, so you don't need a loopback entry in `NO_PROXY` for them.
3737 
38<Note>
39 Claude Code does not support SOCKS proxies.
40</Note>
38> [!NOTE]
39>
40> Claude Code does not support SOCKS proxies.
4141 
4242### Basic authentication
4343 
from line 47
4747export HTTPS_PROXY=http://username:[email protected]:8080
4848```
4949 
50<Warning>
51 Avoid hardcoding passwords in scripts. Use environment variables or secure credential storage instead.
52</Warning>
50> [!WARNING]
51>
52> Avoid hardcoding passwords in scripts. Use environment variables or secure credential storage instead.
5353 
54<Tip>
55 For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.
56</Tip>
54> [!TIP]
55>
56> For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.
5757 
5858## CA certificate store
5959 
from line 73
7373export CLAUDE_CODE_CERT_STORE=system
7474```
7575 
76<Note>
77 `CLAUDE_CODE_CERT_STORE` has no dedicated `settings.json` schema key. Set it via the `env` block in `~/.claude/settings.json` or directly in the process environment.
78</Note>
76> [!NOTE]
77>
78> `CLAUDE_CODE_CERT_STORE` has no dedicated `settings.json` schema key. Set it via the `env` block in `~/.claude/settings.json` or directly in the process environment.
7979 
8080## Custom CA certificates
8181 
from line 171
171171 
172172Set the [`processWrapper`](/docs/en/settings-reference#processwrapper) setting to prefix the supervisor, its workers, and the other background processes listed under [What the launcher covers](/docs/en/corporate-launcher#what-the-launcher-covers) with your launcher. The equivalent [`CLAUDE_CODE_PROCESS_WRAPPER`](/docs/en/env-vars) environment variable takes precedence when both are set, and it is subject to the same rule: deliver it through managed settings or `~/.claude/settings.json`, not a shell export. [Run Claude Code behind a corporate launcher](/docs/en/corporate-launcher) covers the contract the launcher must satisfy, what it does and doesn't reach, and how to roll it out.
173173 
174<Note>
175 An already-running supervisor keeps the launch configuration it started with. After deploying the launcher setting, run [`claude daemon stop --any`](/docs/en/agent-view#the-supervisor-process) so the next `claude agents` or `--bg` starts a supervisor that honors it.
176</Note>
174> [!NOTE]
175>
176> An already-running supervisor keeps the launch configuration it started with. After deploying the launcher setting, run [`claude daemon stop --any`](/docs/en/agent-view#the-supervisor-process) so the next `claude agents` or `--bg` starts a supervisor that honors it.
177177 
178178## Streaming idle watchdogs
179179 

output-styles Changed · +41 / -47 lines

### Frontmatter reference

from line 9
99* 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).
1010* To write your own instructions, [create a custom output style](#create-a-custom-output-style).
1111 
12<Note>
13 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:
12> [!NOTE]
13>
14> 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:
15>
16> * For what Claude should know about your project, use [CLAUDE.md](/docs/en/memory).
17> * For something that has to happen every time, such as formatting after each edit or blocking a command, use a [hook](/docs/en/hooks-guide).
18> * For skills, subagents, and the other options, see [Choose between an output style and other features](#choose-between-an-output-style-and-other-features).
1419 
15 * For what Claude should know about your project, use [CLAUDE.md](/docs/en/memory).
16 * For something that has to happen every time, such as formatting after each edit or blocking a command, use a [hook](/docs/en/hooks-guide).
17 * For skills, subagents, and the other options, see [Choose between an output style and other features](#choose-between-an-output-style-and-other-features).
18</Note>
19 
2020## Built-in output styles
2121 
2222Claude 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.
from line 115
115115 
116116In the VS Code extension, you can also create the file from the [**Output styles** menu](/docs/en/vs-code#use-the-prompt-box) rather than writing it by hand. This requires Claude Code v2.1.261 or later.
117117 
118<Steps>
119 <Step title="Create a Markdown file">
120 Save it at one of three levels. The file name becomes the style name unless you set `name` in the frontmatter.
118**1. Create a Markdown file**
121119 
122 * User: `~/.claude/output-styles`
123 * Project: `.claude/output-styles`
124 * Managed policy: `.claude/output-styles` inside the [managed settings directory](/docs/en/managed-settings#delivery-mechanisms)
120Save it at one of three levels. The file name becomes the style name unless you set `name` in the frontmatter.
125121 
126 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.
127 </Step>
122* User: `~/.claude/output-styles`
123* Project: `.claude/output-styles`
124* Managed policy: `.claude/output-styles` inside the [managed settings directory](/docs/en/managed-settings#delivery-mechanisms)
128125 
129 <Step title="Add frontmatter and instructions">
130 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.
126Project 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.
131127 
132 This example leads every explanation with a diagram while keeping Claude's coding behavior:
128**2. Add frontmatter and instructions**
133129 
134 ```markdown theme={null}
135 ---
136 name: Diagrams first
137 description: Lead every explanation with a diagram
138 keep-coding-instructions: true
139 ---
130Decide 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.
140131 
141 When explaining code, architecture, or data flow, start with a Mermaid diagram showing the structure, then explain in prose.
132This example leads every explanation with a diagram while keeping Claude's coding behavior:
142133 
143 ## Diagram conventions
134```markdown theme={null}
135---
136name: Diagrams first
137description: Lead every explanation with a diagram
138keep-coding-instructions: true
139---
144140 
145 Use `flowchart TD` for control flow and `sequenceDiagram` for request paths. Keep diagrams under 15 nodes.
146 ```
147 </Step>
141When explaining code, architecture, or data flow, start with a Mermaid diagram showing the structure, then explain in prose.
148142 
149 <Step title="Switch to your style">
150 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.
151 </Step>
152</Steps>
143## Diagram conventions
153144 
145Use `flowchart TD` for control flow and `sequenceDiagram` for request paths. Keep diagrams under 15 nodes.
146```
147 
148**3. Switch to your style**
149 
150Run `/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.
151 
154152[Plugins](/docs/en/plugins/manifest-reference) can also ship output styles in an `output-styles/` directory.
155153 
156<h3 id="frontmatter">
157 Frontmatter reference
158</h3>
154### Frontmatter reference
159155 
160156Configure an output style with YAML [frontmatter](/docs/en/glossary#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.
161157 
from line 161
165161| `description` | No | Description of the output style, shown in the `/config` picker |
166162| `keep-coding-instructions` | No | Set to `true` to keep Claude Code's section of built-in software engineering instructions, which only the full system prompt includes, alongside your style. See [How output styles work](#how-output-styles-work). Default: `false` |
167163| `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` |
168 
169<span id="comparisons-to-related-features" />
170164 
171165## Choose between an output style and other features
172166 

overview Changed · +194 / -200 lines

from line 8
88 
99Claude 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](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=overview_pricing) or [Anthropic Console](https://platform.claude.com/) account. The Terminal CLI, VS Code, and JetBrains also support [third-party providers](/docs/en/third-party-integrations).
1010 
11<Tabs>
12 <Tab title="Terminal">
13 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.
11**Terminal**
1412 
15 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](/docs/en/terminal-guide) shows how to open one and paste the command.
13The 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.
1614 
17 <Tabs>
18 <Tab title="Native Install (Recommended)">
19 **macOS, Linux, WSL:**
15To install Claude Code, open a terminal and run the command for your system. If you haven't used a terminal before, the [terminal guide](/docs/en/terminal-guide) shows how to open one and paste the command.
2016 
21 ```bash theme={null}
22 curl -fsSL https://claude.ai/install.sh | bash
23 ```
17**Native Install (Recommended)**
2418 
25 On Windows, your prompt shows `PS C:\` when you're in PowerShell and `C:\` without the `PS` when you're in CMD.
19**macOS, Linux, WSL:**
2620 
27 **Windows PowerShell:**
21```bash theme={null}
22curl -fsSL https://claude.ai/install.sh | bash
23```
2824 
29 ```powershell theme={null}
30 irm https://claude.ai/install.ps1 | iex
31 ```
25On Windows, your prompt shows `PS C:\` when you're in PowerShell and `C:\` without the `PS` when you're in CMD.
3226 
33 **Windows CMD:**
27**Windows PowerShell:**
3428 
35 ```batch theme={null}
36 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
37 ```
29```powershell theme={null}
30irm https://claude.ai/install.ps1 | iex
31```
3832 
39 The install command shows no progress while it downloads Claude Code. 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](/docs/en/troubleshoot-install#command-not-found-claude-after-installation).
33**Windows CMD:**
4034 
41 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.
35```batch theme={null}
36curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
37```
4238 
43 If the install command fails with `syntax error near unexpected token '<'`, a `403`, or any other error, see [Troubleshoot installation](/docs/en/troubleshoot-install#find-your-error) to match the error to a fix and for alternative install methods.
39The install command shows no progress while it downloads Claude Code. 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](/docs/en/troubleshoot-install#command-not-found-claude-after-installation).
4440 
45 [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.
41If 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.
4642 
47 <Info>
48 Native installations automatically update in the background to keep you on the latest version.
49 </Info>
50 </Tab>
43If the install command fails with `syntax error near unexpected token '<'`, a `403`, or any other error, see [Troubleshoot installation](/docs/en/troubleshoot-install#find-your-error) to match the error to a fix and for alternative install methods.
5144 
52 <Tab title="Homebrew">
53 ```bash theme={null}
54 brew install --cask claude-code
55 ```
45[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.
5646 
57 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.
47> [!NOTE]
48>
49> Native installations automatically update in the background to keep you on the latest version.
5850 
59 <Info>
60 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.
61 </Info>
62 </Tab>
51**Homebrew**
6352 
64 <Tab title="WinGet">
65 ```powershell theme={null}
66 winget install Anthropic.ClaudeCode
67 ```
53```bash theme={null}
54brew install --cask claude-code
55```
6856 
69 <Info>
70 WinGet installations do not auto-update. Run `winget upgrade Anthropic.ClaudeCode` periodically to get the latest features and security fixes.
71 </Info>
72 </Tab>
73 </Tabs>
57Homebrew 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.
7458 
75 You can also install with [apt, dnf, or apk](/docs/en/setup#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.
59> [!NOTE]
60>
61> 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.
7662 
77 Then start Claude Code in any project. Replace `your-project` with the path to a project directory on your machine:
63**WinGet**
7864 
79 ```bash theme={null}
80 cd your-project
81 claude
82 ```
65```powershell theme={null}
66winget install Anthropic.ClaudeCode
67```
8368 
84 Claude Code prompts you to log in on first use. If you've set the `ANTHROPIC_API_KEY` environment variable and you approve the key when Claude Code asks whether to use it, Claude Code skips the login prompt. [Continue with the Quickstart →](/docs/en/quickstart)
69> [!NOTE]
70>
71> WinGet installations do not auto-update. Run `winget upgrade Anthropic.ClaudeCode` periodically to get the latest features and security fixes.
8572 
86 <Tip>
87 See [advanced setup](/docs/en/setup) for installation options, manual updates, or uninstallation instructions. Visit [installation troubleshooting](/docs/en/troubleshoot-install) if you hit issues.
88 </Tip>
89 </Tab>
73You can also install with [apt, dnf, or apk](/docs/en/setup#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.
9074 
91 <Tab title="VS Code">
92 The VS Code extension provides inline diffs, @-mentions, plan review, and conversation history directly in your editor.
75Then start Claude Code in any project. Replace `your-project` with the path to a project directory on your machine:
9376 
94 * [Install for VS Code](vscode:extension/anthropic.claude-code)
95 * [Install for Cursor](cursor:extension/anthropic.claude-code)
77```bash theme={null}
78cd your-project
79claude
80```
9681 
97 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**.
82Claude Code prompts you to log in on first use. If you've set the `ANTHROPIC_API_KEY` environment variable and you approve the key when Claude Code asks whether to use it, Claude Code skips the login prompt. [Continue with the Quickstart →](/docs/en/quickstart)
9883 
99 [Get started with VS Code →](/docs/en/vs-code#get-started)
100 </Tab>
84> [!TIP]
85>
86> See [advanced setup](/docs/en/setup) for installation options, manual updates, or uninstallation instructions. Visit [installation troubleshooting](/docs/en/troubleshoot-install) if you hit issues.
10187 
102 <Tab title="Desktop app">
103 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.
88**VS Code**
10489 
105 Download and install:
90The VS Code extension provides inline diffs, @-mentions, plan review, and conversation history directly in your editor.
10691 
107 * [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) (Intel and Apple Silicon)
108 * [Windows](https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs) (x64)
109 * [Windows ARM64](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs)
110 * On Ubuntu or Debian, where the app is in beta, install it with apt by following the [Linux install instructions](/docs/en/desktop-linux)
92* [Install for VS Code](vscode:extension/anthropic.claude-code)
93* [Install for Cursor](cursor:extension/anthropic.claude-code)
11194 
112 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](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=overview_desktop_pricing) is required.
95Or 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**.
11396 
114 [Learn more about the desktop app →](/docs/en/desktop-quickstart)
115 </Tab>
97[Get started with VS Code →](/docs/en/vs-code#get-started)
11698 
117 <Tab title="Web">
118 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](/docs/en/claude-projects) and let Claude coordinate the parallel sessions for you. Available on desktop browsers and [the Claude app for iOS and Android](/docs/en/mobile).
99**Desktop app**
119100 
120 Start coding at [claude.ai/code](https://claude.ai/code).
101A 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.
121102 
122 [Get started →](/docs/en/web-quickstart)
123 </Tab>
103Download and install:
124104 
125 <Tab title="JetBrains">
126 A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.
105* [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) (Intel and Apple Silicon)
106* [Windows](https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs) (x64)
107* [Windows ARM64](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs)
108* On Ubuntu or Debian, where the app is in beta, install it with apt by following the [Linux install instructions](/docs/en/desktop-linux)
127109 
128 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](/docs/en/jetbrains#installation).
110After 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](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=overview_desktop_pricing) is required.
129111 
130 [Get started with JetBrains →](/docs/en/jetbrains)
131 </Tab>
132</Tabs>
112[Learn more about the desktop app →](/docs/en/desktop-quickstart)
133113 
134## What you can do
114**Web**
135115 
136Here are some of the ways you can use Claude Code:
116Run 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](/docs/en/claude-projects) and let Claude coordinate the parallel sessions for you. Available on desktop browsers and [the Claude app for iOS and Android](/docs/en/mobile).
137117 
138<AccordionGroup>
139 <Accordion title="Automate the work you keep putting off" icon="wand-magic-sparkles">
140 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.
118Start coding at [claude.ai/code](https://claude.ai/code).
141119 
142 ```bash theme={null}
143 claude "write tests for the auth module, run them, and fix any failures"
144 ```
145 </Accordion>
120[Get started →](/docs/en/web-quickstart)
146121 
147 <Accordion title="Build features and fix bugs" icon="hammer">
148 Describe what you want in plain language. Claude Code plans the approach, writes the code across multiple files, and verifies it works.
122**JetBrains**
149123 
150 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](/docs/en/common-workflows) for more examples.
151 </Accordion>
124A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.
152125 
153 <Accordion title="Create commits and pull requests" icon="code-branch">
154 Claude Code works directly with git. It stages changes, writes commit messages, creates branches, and opens pull requests.
126Install 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](/docs/en/jetbrains#installation).
155127 
156 ```bash theme={null}
157 claude "commit my changes with a descriptive message"
158 ```
128[Get started with JetBrains →](/docs/en/jetbrains)
159129 
160 In CI, you can automate code review and issue triage with [GitHub Actions](/docs/en/github-actions) or [GitLab CI/CD](/docs/en/gitlab-ci-cd).
161 </Accordion>
130## What you can do
162131 
163 <Accordion title="Connect your tools with MCP" icon="plug">
164 The [Model Context Protocol (MCP)](/docs/en/mcp) is an open standard for connecting AI tools to external data sources. With MCP, Claude Code can read your design docs in Google Drive, update tickets in Jira, pull data from Slack, or use your own custom tooling. The [MCP quickstart](/docs/en/mcp-quickstart) connects your first server end to end.
165 </Accordion>
132Here are some of the ways you can use Claude Code:
166133 
167 <Accordion title="Customize with instructions, skills, and hooks" icon="sliders">
168 [`CLAUDE.md`](/docs/en/memory) 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](/docs/en/memory#agents-md) in place of a `CLAUDE.md`. Claude also builds [auto memory](/docs/en/memory#auto-memory) as it works, saving learnings across sessions without you writing anything.
134> **Automate the work you keep putting off**
135>
136> 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.
137>
138> ```bash theme={null}
139> claude "write tests for the auth module, run them, and fix any failures"
140> ```
169141 
170 Create [skills](/docs/en/skills) to package repeatable workflows your team can share, like `/review-pr` or `/deploy-staging`.
142> **Build features and fix bugs**
143>
144> Describe what you want in plain language. Claude Code plans the approach, writes the code across multiple files, and verifies it works.
145>
146> 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](/docs/en/common-workflows) for more examples.
171147 
172 [Hooks](/docs/en/hooks) let you run shell commands before or after Claude Code actions, like auto-formatting after every file edit or running lint before a commit.
173 </Accordion>
148> **Create commits and pull requests**
149>
150> Claude Code works directly with git. It stages changes, writes commit messages, creates branches, and opens pull requests.
151>
152> ```bash theme={null}
153> claude "commit my changes with a descriptive message"
154> ```
155>
156> In CI, you can automate code review and issue triage with [GitHub Actions](/docs/en/github-actions) or [GitLab CI/CD](/docs/en/gitlab-ci-cd).
174157 
175 <Accordion title="Run agents in parallel and build custom agents" icon="users">
176 Spawn [multiple Claude Code agents](/docs/en/sub-agents) that work on different parts of a task simultaneously. A lead agent coordinates the work, assigns subtasks, and merges results.
158> **Connect your tools with MCP**
159>
160> The [Model Context Protocol (MCP)](/docs/en/mcp) is an open standard for connecting AI tools to external data sources. With MCP, Claude Code can read your design docs in Google Drive, update tickets in Jira, pull data from Slack, or use your own custom tooling. The [MCP quickstart](/docs/en/mcp-quickstart) connects your first server end to end.
177161 
178 To run several full sessions in parallel and watch them from one screen, use [background agents](/docs/en/agent-view). For fully custom workflows, the [Agent SDK](/docs/en/agent-sdk/overview) lets you build your own agents powered by Claude Code's tools and capabilities, with full control over orchestration, tool access, and permissions.
179 </Accordion>
162> **Customize with instructions, skills, and hooks**
163>
164> [`CLAUDE.md`](/docs/en/memory) 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](/docs/en/memory#agents-md) in place of a `CLAUDE.md`. Claude also builds [auto memory](/docs/en/memory#auto-memory) as it works, saving learnings across sessions without you writing anything.
165>
166> Create [skills](/docs/en/skills) to package repeatable workflows your team can share, like `/review-pr` or `/deploy-staging`.
167>
168> [Hooks](/docs/en/hooks) let you run shell commands before or after Claude Code actions, like auto-formatting after every file edit or running lint before a commit.
180169 
181 <Accordion title="Pipe, script, and automate with the CLI" icon="terminal">
182 Claude Code is composable and follows the Unix philosophy. Pipe logs into it, run it in CI, or chain it with other tools:
170> **Run agents in parallel and build custom agents**
171>
172> Spawn [multiple Claude Code agents](/docs/en/sub-agents) that work on different parts of a task simultaneously. A lead agent coordinates the work, assigns subtasks, and merges results.
173>
174> To run several full sessions in parallel and watch them from one screen, use [background agents](/docs/en/agent-view). For fully custom workflows, the [Agent SDK](/docs/en/agent-sdk/overview) lets you build your own agents powered by Claude Code's tools and capabilities, with full control over orchestration, tool access, and permissions.
183175 
184 ```bash theme={null}
185 # Analyze recent log output
186 tail -200 app.log | claude -p "Slack me if you see any anomalies"
176> **Pipe, script, and automate with the CLI**
177>
178> Claude Code is composable and follows the Unix philosophy. Pipe logs into it, run it in CI, or chain it with other tools:
179>
180> ```bash theme={null}
181> # Analyze recent log output
182> tail -200 app.log | claude -p "Slack me if you see any anomalies"
183>
184> # Automate translations in CI
185> claude -p "translate new strings into French and raise a PR for review"
186>
187> # Bulk operations across files
188> git diff main --name-only | claude -p "review these changed files for security issues"
189> ```
190>
191> See the [CLI reference](/docs/en/cli-reference) for the full set of commands and flags.
187192 
188 # Automate translations in CI
189 claude -p "translate new strings into French and raise a PR for review"
193> **Schedule recurring tasks**
194>
195> 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.
196>
197> * [Cloud scheduled tasks](/docs/en/routines), formerly routines, 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.
198> * [Desktop scheduled tasks](/docs/en/desktop-scheduled-tasks) run on your machine, with direct access to your local files and tools
199> * [`/loop`](/docs/en/scheduled-tasks) repeats a prompt within a CLI session for quick polling
190200 
191 # Bulk operations across files
192 git diff main --name-only | claude -p "review these changed files for security issues"
193 ```
194 
195 See the [CLI reference](/docs/en/cli-reference) for the full set of commands and flags.
196 </Accordion>
197 
198 <Accordion title="Schedule recurring tasks" icon="clock">
199 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.
200 
201 * [Cloud scheduled tasks](/docs/en/routines), formerly routines, 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.
202 * [Desktop scheduled tasks](/docs/en/desktop-scheduled-tasks) run on your machine, with direct access to your local files and tools
203 * [`/loop`](/docs/en/scheduled-tasks) repeats a prompt within a CLI session for quick polling
204 </Accordion>
205 
206 <Accordion title="Work from anywhere" icon="globe">
207 Sessions aren't tied to a single surface. Move work between them as your context changes:
208 
209 * Step away from your desk and keep working from your phone or any browser with [Remote Control](/docs/en/remote-control)
210 * Message [Dispatch](/docs/en/desktop#sessions-from-dispatch) a task from your phone and open the Desktop session it creates
211 * Start a long-running task on the [web](/docs/en/claude-code-on-the-web) or the [Claude mobile app](/docs/en/mobile), then pull it into your terminal with `claude --teleport`. Teleport requires a claude.ai subscription.
212 * Run `/desktop` to continue your current terminal session in the [Desktop app](/docs/en/desktop), where you can review diffs visually. The `/desktop` handoff requires a claude.ai subscription. Available on macOS and x64 Windows.
213 * Route tasks from team chat: mention `@Claude` in [Slack](/docs/en/slack) with a bug report and get a pull request back
214 </Accordion>
215</AccordionGroup>
201> **Work from anywhere**
202>
203> Sessions aren't tied to a single surface. Move work between them as your context changes:
204>
205> * Step away from your desk and keep working from your phone or any browser with [Remote Control](/docs/en/remote-control)
206> * Message [Dispatch](/docs/en/desktop#sessions-from-dispatch) a task from your phone and open the Desktop session it creates
207> * Start a long-running task on the [web](/docs/en/claude-code-on-the-web) or the [Claude mobile app](/docs/en/mobile), then pull it into your terminal with `claude --teleport`. Teleport requires a claude.ai subscription.
208> * Run `/desktop` to continue your current terminal session in the [Desktop app](/docs/en/desktop), where you can review diffs visually. The `/desktop` handoff requires a claude.ai subscription. Available on macOS and x64 Windows.
209> * Route tasks from team chat: mention `@Claude` in [Slack](/docs/en/slack) with a bug report and get a pull request back
216210 
217211## Use Claude Code everywhere
218212 

permission-modes Changed · +193 / -227 lines

### Actions no mode auto-approves ## Which mode a session starts in ### Tool calls denied in `claude -p` and Agent SDK runs ### Start in a different permission mode ### Permission modes with the HIPAA configuration ## Eliminate permission prompts with auto mode ### Auto mode on Bedrock, Agent Platform, or Foundry ### Default classifier model #### When your model doesn't review #### Check which model the classifier used ### The first read outside the working directories

from line 25
2525 
2626Modes set the baseline. Layer [permission rules](/docs/en/permissions#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`](/docs/en/tools-reference#endconversation-tool-behavior) as long as Claude still has at least one other tool it can call. Allow rules have no effect in `bypassPermissions`.
2727 
28<h3 id="actions-no-mode-auto-approves">
29 Actions no mode auto-approves
30</h3>
28### Actions no mode auto-approves
3129 
3230Claude 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:
3331 
from line 53
5553 
5654The Bash sandbox and auto mode work independently and combine, with the exceptions listed under [Sandbox modes](/docs/en/sandboxing#sandbox-modes). For the full interaction, see [How sandboxing relates to permissions and permission modes](/docs/en/sandboxing#how-sandboxing-relates-to-permissions-and-permission-modes) and [How isolation relates to permission modes](/docs/en/sandbox-environments#how-isolation-relates-to-permission-modes).
5755 
58<h2 id="which-mode-a-session-starts-in">
59 Which mode a session starts in
60</h2>
56## Which mode a session starts in
6157 
6258When you start a new session in a terminal, Claude Code takes the permission mode from the first of these that applies:
6359 
from line 87
9187 
9288If your `~/.claude/settings.json` sets a `defaultMode` other than `auto` and no other settings file sets one, your sessions keep starting in that mode. On Pro, Max, and Team plans, and in sessions that [don't fetch feature flags](/docs/en/env-vars#features-that-need-feature-flag-fetching), 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.
9389 
94<h3 id="which-mode-a-non-interactive-run-starts-in">
95 Tool calls denied in `claude -p` and Agent SDK runs
96</h3>
90### Tool calls denied in `claude -p` and Agent SDK runs
9791 
9892In Claude Code v2.1.302 or later, `claude -p` and [Agent SDK](/docs/en/agent-sdk/permissions#permission-modes) runs with [no permission mode set](#which-mode-a-session-starts-in) start in Manual mode. This mode appears as `default` in SDK options and settings. Calls needing approval are denied unless you approve them with an allow rule, hook, `canUseTool` callback, or `--permission-prompt-tool`.
9993 
from line 98
10498 
10599These examples show the auto mode form for the CLI and each SDK:
106100 
107<Tabs>
108 <Tab title="CLI">
109 ```bash theme={null}
110 claude -p "Run the test suite and fix any failures" --permission-mode auto
111 ```
112 </Tab>
101**CLI**
113102 
114 <Tab title="TypeScript">
115 ```typescript theme={null}
116 const options = {
117 permissionMode: "auto"
118 };
119 ```
120 </Tab>
103```bash theme={null}
104claude -p "Run the test suite and fix any failures" --permission-mode auto
105```
121106 
122 <Tab title="Python">
123 ```python theme={null}
124 from claude_agent_sdk import ClaudeAgentOptions
107**TypeScript**
125108 
126 options = ClaudeAgentOptions(permission_mode="auto")
127 ```
128 </Tab>
129</Tabs>
109```typescript theme={null}
110const options = {
111 permissionMode: "auto"
112};
113```
130114 
115**Python**
116 
117```python theme={null}
118from claude_agent_sdk import ClaudeAgentOptions
119 
120options = ClaudeAgentOptions(permission_mode="auto")
121```
122 
131123Before v2.1.302, these runs could start in auto mode if they didn't [fetch feature flags](/docs/en/env-vars#features-that-need-feature-flag-fetching), for example on a [third-party provider](/docs/en/third-party-integrations) or with `DISABLE_TELEMETRY`.
132124 
133<h3 id="start-in-a-different-mode">
134 Start in a different permission mode
135</h3>
125### Start in a different permission mode
136126 
137127You 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](/docs/en/settings#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).
138128 
from line 145
155145 
156146The next session you start shows `⏸ manual mode on` in the status bar.
157147 
158<h3 id="hipaa-configuration">
159 Permission modes with the HIPAA configuration
160</h3>
148### Permission modes with the HIPAA configuration
161149 
162150In an organization with the [HIPAA configuration](/docs/en/hipaa-setup) applied, the built-in `auto` default doesn't apply. A terminal or VS Code session starts in Manual mode when nothing else chooses its starting permission mode. A terminal session also shows `Auto mode isn't the default for your organization · Shift+Tab to switch`, and the VS Code extension shows no notice. [Check how developers sign in and connect](/docs/en/hipaa-setup#check-how-developers-sign-in-and-connect) lists the sessions this applies to.
163151 
from line 162
174162 
175163Each 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.
176164 
177<Tabs>
178 <Tab title="CLI">
179 **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`. Optional modes 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`.
165**CLI**
180166 
181 Watch the status bar in this clip of a session that started in auto mode. Each time you press `Shift+Tab`, it changes from `auto mode on` to `manual mode on`, `accept edits on`, `plan mode on`, and back to `auto mode on`.
167**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`. Optional modes 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`.
182168 
183 <Frame>
184 <video autoPlay muted loop playsInline className="w-full dark:hidden" style={{aspectRatio: "1440 / 264"}} src="https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-modes-cycle-light.mp4?fit=max&auto=format&n=oa7CKjMeIChox26S&q=85&s=198ca90aeb2e3675b3d01b7d686aab0b" aria-label="The status bar under the Claude Code prompt changes with each press of Shift+Tab: auto mode on, manual mode on, accept edits on, plan mode on, then auto mode on again." data-path="images/permission-modes-cycle-light.mp4" />
169Watch the status bar in this clip of a session that started in auto mode. Each time you press `Shift+Tab`, it changes from `auto mode on` to `manual mode on`, `accept edits on`, `plan mode on`, and back to `auto mode on`.
185170 
186 <video autoPlay muted loop playsInline className="w-full hidden dark:block" style={{aspectRatio: "1440 / 264"}} src="https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-modes-cycle-dark.mp4?fit=max&auto=format&n=oa7CKjMeIChox26S&q=85&s=994cdeec4e99d2f474d236c1087d6e63" aria-label="The status bar under the Claude Code prompt changes with each press of Shift+Tab: auto mode on, manual mode on, accept edits on, plan mode on, then auto mode on again." data-path="images/permission-modes-cycle-dark.mp4" />
187 </Frame>
171<video autoPlay muted loop playsInline src="https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-modes-cycle-light.mp4?fit=max&auto=format&n=oa7CKjMeIChox26S&q=85&s=198ca90aeb2e3675b3d01b7d686aab0b" aria-label="The status bar under the Claude Code prompt changes with each press of Shift+Tab: auto mode on, manual mode on, accept edits on, plan mode on, then auto mode on again." />
188172 
189 Not every mode is in the default cycle:
173Not every mode is in the default cycle:
190174 
191 * `auto`: appears when [auto mode is available](#eliminate-prompts-with-auto-mode); cycling to it switches permission modes without a confirmation prompt
192 * `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](/docs/en/settings-reference#permissions-defaultmode). The `--allow-` variant adds the permission mode to the cycle without activating it
193 * `dontAsk`: never appears in the cycle; set it with `--permission-mode dontAsk`
175* `auto`: appears when [auto mode is available](#eliminate-prompts-with-auto-mode); cycling to it switches permission modes without a confirmation prompt
176* `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](/docs/en/settings-reference#permissions-defaultmode). The `--allow-` variant adds the permission mode to the cycle without activating it
177* `dontAsk`: never appears in the cycle; set it with `--permission-mode dontAsk`
194178 
195 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`.
179Enabled 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`.
196180 
197 **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](/docs/en/tools-reference#powershell-tool) prompts don't offer the option. Requires Claude Code v2.1.247 or later.
181**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](/docs/en/tools-reference#powershell-tool) prompts don't offer the option. Requires Claude Code v2.1.247 or later.
198182 
199 Claude Code doesn't add the option to prompts forced by one of your [`ask` rules](/docs/en/permissions#manage-permissions) or by a [hook](/docs/en/hooks#pretooluse-decision-control), because auto mode still shows you those prompts, so switching wouldn't remove them.
183Claude Code doesn't add the option to prompts forced by one of your [`ask` rules](/docs/en/permissions#manage-permissions) or by a [hook](/docs/en/hooks#pretooluse-decision-control), because auto mode still shows you those prompts, so switching wouldn't remove them.
200184 
201 **At startup**: pass the permission mode as a flag.
185**At startup**: pass the permission mode as a flag.
202186 
203 ```bash theme={null}
204 claude --permission-mode plan
205 ```
187```bash theme={null}
188claude --permission-mode plan
189```
206190 
207 **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).
191**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).
208192 
209 The same `--permission-mode` flag works with `-p` for [non-interactive runs](/docs/en/headless).
210 </Tab>
193The same `--permission-mode` flag works with `-p` for [non-interactive runs](/docs/en/headless).
211194 
212 <Tab title="VS Code">
213 **During a session**: click the mode indicator at the bottom of the prompt box. It uses these labels for the modes on this page:
195**VS Code**
214196 
215 | UI label | Mode |
216 | :- | :- |
217 | Manual | `default` |
218 | Edit automatically | `acceptEdits` |
219 | Plan | `plan` |
220 | Auto | `auto` |
221 | Bypass permissions | `bypassPermissions` |
197**During a session**: click the mode indicator at the bottom of the prompt box. It uses these labels for the modes on this page:
222198 
223 **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:
199| UI label | Mode |
200| :- | :- |
201| Manual | `default` |
202| Edit automatically | `acceptEdits` |
203| Plan | `plan` |
204| Auto | `auto` |
205| Bypass permissions | `bypassPermissions` |
224206 
225 1. `claudeCode.initialPermissionMode`
226 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
227 3. `permissions.defaultMode` from [managed settings](/docs/en/managed-settings) or `~/.claude/settings.json`
228 4. The [built-in default](#which-mode-a-session-starts-in) for your plan, provider, and organization settings
207**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:
229208 
230 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.
2091. `claudeCode.initialPermissionMode`
2102. 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
2113. `permissions.defaultMode` from [managed settings](/docs/en/managed-settings) or `~/.claude/settings.json`
2124. The [built-in default](#which-mode-a-session-starts-in) for your plan, provider, and organization settings
231213 
232 Before v2.1.283, item 3 applied only on Pro, Max, and Team plans in sessions that [fetch feature flags](/docs/en/env-vars#features-that-need-feature-flag-fetching).
214The 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.
233215 
234 Auto appears in the mode indicator when [auto mode is available](#eliminate-prompts-with-auto-mode).
216Before v2.1.283, item 3 applied only on Pro, Max, and Team plans in sessions that [fetch feature flags](/docs/en/env-vars#features-that-need-feature-flag-fetching).
235217 
236 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.
218Auto appears in the mode indicator when [auto mode is available](#eliminate-prompts-with-auto-mode).
237219 
238 See the [VS Code guide](/docs/en/vs-code) for extension-specific details.
239 </Tab>
220Bypass 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.
240221 
241 <Tab title="JetBrains">
242 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.
243 </Tab>
222See the [VS Code guide](/docs/en/vs-code) for extension-specific details.
244223 
245 <Tab title="Desktop">
246 **During a session**: in the Code tab, use the mode selector in the row under the prompt box. Not every mode appears in the selector:
224**JetBrains**
247225 
248 * **Auto**: appears when [auto mode is available](#eliminate-prompts-with-auto-mode)
249 * **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
226The 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.
250227 
251 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).
228**Desktop**
252229 
253 For desktop-specific details, see [Choose a permission mode](/docs/en/desktop#choose-a-permission-mode) in the Desktop guide.
230**During a session**: in the Code tab, use the mode selector in the row under the prompt box. Not every mode appears in the selector:
254231 
255 **As a default**: set `defaultMode` in [settings](/docs/en/settings#where-settings-live). The desktop app reads the same settings files as the CLI and applies the permission mode to new local sessions.
232* **Auto**: appears when [auto mode is available](#eliminate-prompts-with-auto-mode)
233* **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
256234 
257 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.
235The 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).
258236 
259 For where `defaultMode` goes in a settings file, see the example under [Start in a different permission mode](#start-in-a-different-mode).
260 </Tab>
237For desktop-specific details, see [Choose a permission mode](/docs/en/desktop#choose-a-permission-mode) in the Desktop guide.
261238 
262 <Tab title="Web and mobile">
263 On [claude.ai/code](https://claude.ai/code), use the mode dropdown next to the prompt box. In the mobile app, tap the **+** button in the prompt box, then **Permission**. Cloud sessions and Remote Control sessions offer different permission modes:
239**As a default**: set `defaultMode` in [settings](/docs/en/settings#where-settings-live). The desktop app reads the same settings files as the CLI and applies the permission mode to new local sessions.
264240 
265 * **[Cloud sessions](/docs/en/claude-code-on-the-web)**: 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.
266 * **[Remote Control](/docs/en/remote-control) sessions** on your local machine: Manual, Accept edits, Plan, and Auto for a session you started yourself, and you can't select Bypass permissions from the app. To use Auto, the session has to meet the auto mode [availability requirements](#eliminate-prompts-with-auto-mode). For a project thread running on your computer, see [Run a thread on your own computer](/docs/en/claude-projects#run-a-thread-on-your-own-computer).
267 * 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.
268 * Sessions hosted by the [desktop app](/docs/en/desktop) or the [VS Code extension](/docs/en/vs-code) report permission mode changes to claude.ai as they happen, the same as sessions hosted in a terminal.
241A 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.
269242 
270 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:
243For where `defaultMode` goes in a settings file, see the example under [Start in a different permission mode](#start-in-a-different-mode).
271244 
272 ```bash theme={null}
273 claude remote-control --permission-mode acceptEdits
274 ```
275 </Tab>
276</Tabs>
245**Web and mobile**
277246 
247On [claude.ai/code](https://claude.ai/code), use the mode dropdown next to the prompt box. In the mobile app, tap the **+** button in the prompt box, then **Permission**. Cloud sessions and Remote Control sessions offer different permission modes:
248 
249* **[Cloud sessions](/docs/en/claude-code-on-the-web)**: 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.
250* **[Remote Control](/docs/en/remote-control) sessions** on your local machine: Manual, Accept edits, Plan, and Auto for a session you started yourself, and you can't select Bypass permissions from the app. To use Auto, the session has to meet the auto mode [availability requirements](#eliminate-prompts-with-auto-mode). For a project thread running on your computer, see [Run a thread on your own computer](/docs/en/claude-projects#run-a-thread-on-your-own-computer).
251 * 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.
252 * Sessions hosted by the [desktop app](/docs/en/desktop) or the [VS Code extension](/docs/en/vs-code) report permission mode changes to claude.ai as they happen, the same as sessions hosted in a terminal.
253 
254For 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:
255 
256```bash theme={null}
257claude remote-control --permission-mode acceptEdits
258```
259 
278260## Auto-approve file edits with acceptEdits mode
279261 
280262`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.
from line 311
329311 
330312To 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](/docs/en/vs-code) starts don't read project settings for the starting permission mode. There, set `claudeCode.initialPermissionMode` to `plan` in your VS Code user settings instead.
331313 
332<h2 id="eliminate-prompts-with-auto-mode">
333 Eliminate permission prompts with auto mode
334</h2>
314## Eliminate permission prompts with auto mode
335315 
336316Auto 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](/docs/en/permissions#manage-permissions) still force a prompt.
337317 
from line 323
343323 
344324Auto 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](/docs/en/output-styles) instead.
345325 
346<Warning>
347 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.
348</Warning>
326> [!WARNING]
327>
328> 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.
349329 
350330Auto mode is available only when your account meets all of these requirements:
351331 
from line 340
360340 
361341If you set `defaultMode: "auto"` in [settings](/docs/en/settings-reference#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.
362342 
363<h3 id="enable-auto-mode-on-bedrock-agent-platform-or-foundry">
364 Auto mode on Bedrock, Agent Platform, or Foundry
365</h3>
343### Auto mode on Bedrock, Agent Platform, or Foundry
366344 
367345On [Amazon Bedrock](/docs/en/amazon-bedrock), [Google Cloud's Agent Platform](/docs/en/google-vertex-ai), [Microsoft Foundry](/docs/en/microsoft-foundry), and signed-in [Claude apps gateway](/docs/en/claude-apps-gateway) sessions, auto mode is available by default. If you don't set a permission mode there, interactive sessions start in auto mode, and `claude -p` or Agent SDK runs start in Manual mode, whose config value is `default`:
368346 
from line 366
388366 
389367To skip asking the server and always use Claude Code's own classifier requests, set [`CLAUDE_CODE_AUTO_MODE_SERVER=0`](/docs/en/env-vars). 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, 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](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities) describes.
390368 
391<h3 id="default-classifier-model">
392 Default classifier model
393</h3>
369### Default classifier model
394370 
395371By default, classifier requests go to Claude Sonnet 5. If `/status` shows `Auto mode server` as `Enabled`, they're sent only for calls outside [the server's review](#server-side-classifier-review).
396372 
from line 392
416392}
417393```
418394 
419<h4 id="classifier-model-not-reviewing">
420 When your model doesn't review
421</h4>
395#### When your model doesn't review
422396 
423397| Situation | What happens | What to do |
424398| - | - | - |
from line 403
429403 
430404If several situations apply, go by the first listed.
431405 
432<h4 id="classifier-model-check">
433 Check which model the classifier used
434</h4>
406#### Check which model the classifier used
435407 
436408From your shell, start an auto mode session with [`--debug-file`](/docs/en/cli-reference#cli-flags):
437409 
from line 504
532504 
533505Pushing 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](/docs/en/permissions#bash-rule-limits): see [Common boundaries](/docs/en/auto-mode-config#common-boundaries).
534506 
535<h3 id="first-read-outside-the-working-directories">
536 The first read outside the working directories
537</h3>
507### The first read outside the working directories
538508 
539509While [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) is off, file reads other than [reads from network paths](/docs/en/permissions#network-paths) run without a prompt in auto mode, including reads outside the [working directories](/docs/en/permissions#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.
540510 
from line 553
583553 
584554The 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.
585555 
586<span id="how-the-classifier-evaluates-actions" />
556> **How the classifier evaluates actions**
557>
558> Each action goes through a fixed decision order. The first matching step wins:
559>
560> 1. Actions matching your [allow, ask, or deny rules](/docs/en/permissions#manage-permissions) resolve immediately, with these exceptions:
561> * Writes to [protected paths](#protected-paths) route to the classifier even when an allow rule matches. When the protected path is the file that a symlinked settings file points to, the write can prompt you instead, as the [protected paths](#protected-paths) list describes
562> * No allow rule approves `rm` and `rmdir` removals targeting a [critical path](#critical-paths)
563> * MCP tools marked [`requiresUserInteraction`](/docs/en/mcp#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`](/docs/en/mcp#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code
564> * A shell command that carries [per-command allowed domains](/docs/en/sandboxing#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
565> * Ask rules that match on a command's content, such as `Bash(git push *)`, fall back to a permission prompt
566> * A write that the [symlink check](/docs/en/permissions#symlinks) resolves to a protected path prompts you when the path Claude requested isn't itself protected
567> * A read from a [network path](/docs/en/permissions#network-paths) prompts you even when an allow rule matches
568> 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
569> * In a session with [server-side classifier review](#server-side-classifier-review), read-only and [sandboxed](/docs/en/sandboxing#sandbox-modes) shell commands wait for that review and are blocked if it flags them
570> * A write inside your working directory that the [symlink check](/docs/en/permissions#symlinks) resolves to a location outside it prompts you
571> * When Claude reads an [artifact someone else made](/docs/en/artifacts#read-an-artifact-shared-with-you), the approval cases listed in that section apply
572> * A read from a [network path](/docs/en/permissions#network-paths) prompts you
573> 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
574> 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](/docs/en/auto-mode-config#review-denials)
575>
576> A [mod](/docs/en/plugins/mods/overview) you install that handles `tool.check` can also approve an action. For the cases where its approval doesn't get past your rules and hooks, see [Extend permissions with hooks](/docs/en/permissions#precedence-among-rules-hooks-and-mods).
577>
578> In the VS Code extension, how [Claude in Chrome](/docs/en/chrome) browser actions get approved depends on how the session connected to the browser: see [Permission prompts in VS Code sessions](/docs/en/chrome#permission-prompts-in-vs-code-sessions).
579>
580> On entering auto mode, broad allow rules that grant arbitrary code execution are dropped:
581>
582> * Blanket `Bash(*)` or `PowerShell(*)`
583> * Wildcarded interpreters like `Bash(python*)`
584> * Package-manager run commands
585> * `Agent` allow rules
586> * [`Monitor`](/docs/en/tools-reference#monitor-tool) allow rules, because Claude Code runs Monitor commands through the shell
587>
588> 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.
589>
590> 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`.
591>
592> 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.
593>
594> You can annotate a call's result with a [PostToolUse hook's `classifierContext` field](/docs/en/hooks#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.
595>
596> 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).
587597 
588<AccordionGroup>
589 <Accordion title="How the classifier evaluates actions">
590 Each action goes through a fixed decision order. The first matching step wins:
598> **How auto mode handles subagents**
599>
600> The classifier checks [subagent](/docs/en/sub-agents) work at three points:
601>
602> 1. Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.
603> 2. While the subagent runs, each of its actions goes through the same [decision order](#how-the-classifier-evaluates-actions) as in the parent session, with the same block and allow rules. Any `permissionMode` in the subagent's frontmatter is ignored.
604> 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.
591605 
592 1. Actions matching your [allow, ask, or deny rules](/docs/en/permissions#manage-permissions) resolve immediately, with these exceptions:
593 * Writes to [protected paths](#protected-paths) route to the classifier even when an allow rule matches. When the protected path is the file that a symlinked settings file points to, the write can prompt you instead, as the [protected paths](#protected-paths) list describes
594 * No allow rule approves `rm` and `rmdir` removals targeting a [critical path](#critical-paths)
595 * MCP tools marked [`requiresUserInteraction`](/docs/en/mcp#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`](/docs/en/mcp#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code
596 * A shell command that carries [per-command allowed domains](/docs/en/sandboxing#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
597 * Ask rules that match on a command's content, such as `Bash(git push *)`, fall back to a permission prompt
598 * A write that the [symlink check](/docs/en/permissions#symlinks) resolves to a protected path prompts you when the path Claude requested isn't itself protected
599 * A read from a [network path](/docs/en/permissions#network-paths) prompts you even when an allow rule matches
600 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
601 * In a session with [server-side classifier review](#server-side-classifier-review), read-only and [sandboxed](/docs/en/sandboxing#sandbox-modes) shell commands wait for that review and are blocked if it flags them
602 * A write inside your working directory that the [symlink check](/docs/en/permissions#symlinks) resolves to a location outside it prompts you
603 * When Claude reads an [artifact someone else made](/docs/en/artifacts#read-an-artifact-shared-with-you), the approval cases listed in that section apply
604 * A read from a [network path](/docs/en/permissions#network-paths) prompts you
605 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
606 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](/docs/en/auto-mode-config#review-denials)
606> **Cost and latency**
607>
608> Claude Code's classifier requests can run on a model other than your `/model` selection. See [which model they run on](#default-classifier-model).
609>
610> On Enterprise plans and on accounts that use the Claude API, [Claude Platform on AWS](/docs/en/claude-platform-on-aws), 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).
611>
612> Sandboxed network access adds no per-connection classifier requests. The classifier judges [the hosts a command names](/docs/en/sandboxing#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.
607613 
608 A [mod](/docs/en/plugins/mods/overview) you install that handles `tool.check` can also approve an action. For the cases where its approval doesn't get past your rules and hooks, see [Extend permissions with hooks](/docs/en/permissions#precedence-among-rules-hooks-and-mods).
609 
610 In the VS Code extension, how [Claude in Chrome](/docs/en/chrome) browser actions get approved depends on how the session connected to the browser: see [Permission prompts in VS Code sessions](/docs/en/chrome#permission-prompts-in-vs-code-sessions).
611 
612 On entering auto mode, broad allow rules that grant arbitrary code execution are dropped:
613 
614 * Blanket `Bash(*)` or `PowerShell(*)`
615 * Wildcarded interpreters like `Bash(python*)`
616 * Package-manager run commands
617 * `Agent` allow rules
618 * [`Monitor`](/docs/en/tools-reference#monitor-tool) allow rules, because Claude Code runs Monitor commands through the shell
619 
620 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.
621 
622 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`.
623 
624 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.
625 
626 You can annotate a call's result with a [PostToolUse hook's `classifierContext` field](/docs/en/hooks#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.
627 
628 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).
629 </Accordion>
630 
631 <Accordion title="How auto mode handles subagents">
632 The classifier checks [subagent](/docs/en/sub-agents) work at three points:
633 
634 1. Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.
635 2. While the subagent runs, each of its actions goes through the same [decision order](#how-the-classifier-evaluates-actions) as in the parent session, with the same block and allow rules. Any `permissionMode` in the subagent's frontmatter is ignored.
636 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.
637 </Accordion>
638 
639 <Accordion title="Cost and latency">
640 Claude Code's classifier requests can run on a model other than your `/model` selection. See [which model they run on](#default-classifier-model).
641 
642 On Enterprise plans and on accounts that use the Claude API, [Claude Platform on AWS](/docs/en/claude-platform-on-aws), 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).
643 
644 Sandboxed network access adds no per-connection classifier requests. The classifier judges [the hosts a command names](/docs/en/sandboxing#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.
645 </Accordion>
646</AccordionGroup>
647 
648614## Allow only pre-approved tools with dontAsk mode
649615 
650616If you set `dontAsk` mode, Claude Code auto-denies every tool call that would otherwise prompt you, though a [mod](/docs/en/plugins/mods/overview) you installed can still approve some of those calls. To check which calls a mod can approve, see [Extend permissions with hooks](/docs/en/permissions#precedence-among-rules-hooks-and-mods).
from line 644
678644 
679645Plan mode keeps its blocks wherever Claude Code runs without an interactive terminal, including [non-interactive runs](/docs/en/headless) with `-p`, [Agent SDK](/docs/en/agent-sdk/permissions#plan-mode-plan) sessions, and conversations in the [VS Code extension](/docs/en/vs-code)'s chat panel. There, `--allow-dangerously-skip-permissions` makes `bypassPermissions` selectable later.
680646 
681<Warning>
682 Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system.
683</Warning>
647> [!WARNING]
648>
649> Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system.
684650 
685651You can't enter `bypassPermissions` from a session you started without it enabled. Enable it at launch with [`permissions.defaultMode: "bypassPermissions"`](/docs/en/settings-reference#permissions-defaultmode) or with an enabling flag:
686652 
from line 658
692658 
693659Claude Code refuses `bypassPermissions` in a session you start with [`--restricted`](/docs/en/cli-reference#cli-flags). `--restricted` requires Claude Code v2.1.248 or later.
694660 
695<span id="bypass-permissions-acceptance" />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:
661The 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:
696662 
697663* **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](/docs/en/settings-reference#skipdangerousmodepermissionprompt) lists the other settings files where you or your organization can set it.
698664* **If you decline**: Claude Code exits.
from line 680
714680 
715681[Cloud sessions](/docs/en/claude-code-on-the-web) 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.
716682 
717<Warning>
718 `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](/docs/en/managed-settings).
719</Warning>
683> [!WARNING]
684>
685> `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](/docs/en/managed-settings).
720686 
721687## Protected paths
722688 

permissions Changed · +44 / -56 lines

#### Wrappers #### Exec wrappers and `find` actions #### What a Bash rule doesn't match

from line 18
1818 
1919A permission prompt shows what Claude is about to do, followed by your options. This example is the prompt for a Bash command, from a session in Manual mode:
2020 
21<Frame>
22 <img src="https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-prompt-bash-light.png?fit=max&auto=format&n=oa7CKjMeIChox26S&q=85&s=87585d008a29304873466399f7b476f6" className="dark:hidden" alt="A Claude Code permission prompt titled Bash command. Under a tip about auto mode, it shows the description 'Run the test suite', the command npm test, and the line 'This command requires approval', then asks 'Do you want to proceed?' with four options: Yes; Yes, and don't ask again for: npm test *; Yes, and switch to auto mode; and No. A footer lists two keys: Esc to cancel and Tab to amend." width="1512" height="680" data-path="images/permission-prompt-bash-light.png" />
21![A Claude Code permission prompt titled Bash command. Under a tip about auto mode, it shows the description 'Run the test suite', the command npm test, and the line 'This command requires approval', then asks 'Do you want to proceed?' with four options: Yes; Yes, and don't ask again for: npm test \*; Yes, and switch to auto mode; and No. A footer lists two keys: Esc to cancel and Tab to amend.](https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-prompt-bash-light.png?fit=max\&auto=format\&n=oa7CKjMeIChox26S\&q=85\&s=87585d008a29304873466399f7b476f6)
2322 
24 <img src="https://mintcdn.com/claude-code/oa7CKjMeIChox26S/images/permission-prompt-bash-dark.png?fit=max&auto=format&n=oa7CKjMeIChox26S&q=85&s=dd25688056898df1d1e4f1b5542bc978" className="hidden dark:block" alt="A Claude Code permission prompt titled Bash command. Under a tip about auto mode, it shows the description 'Run the test suite', the command npm test, and the line 'This command requires approval', then asks 'Do you want to proceed?' with four options: Yes; Yes, and don't ask again for: npm test *; Yes, and switch to auto mode; and No. A footer lists two keys: Esc to cancel and Tab to amend." width="1512" height="680" data-path="images/permission-prompt-bash-dark.png" />
25</Frame>
26 
2723The third option, **Yes, and switch to auto mode**, [doesn't appear on every prompt](/docs/en/permission-modes#switch-permission-modes).
2824 
2925When 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](/docs/en/worktrees) 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](/docs/en/settings#where-claude-code-looks-for-each-file) lists those cases and where it saves the rule instead.
from line 59
6359 
6460Bare-name removal applies to every tool except [`EndConversation`](/docs/en/tools-reference#endconversation-tool-behavior): a deny rule can't remove it while any other tool remains, and an ask rule never prompts for it.
6561 
66<Note>
67 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](/docs/en/permission-modes), or a [PreToolUse hook](#extend-permissions-with-hooks).
68</Note>
62> [!NOTE]
63>
64> 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](/docs/en/permission-modes), or a [PreToolUse hook](#extend-permissions-with-hooks).
6965 
7066When [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) is available to your session, the dialog also includes the [auto mode classifier rules](/docs/en/auto-mode-config#edit-rules-from-permissions). Select the **Auto mode** tab to view them.
7167 
from line 78
8278| `dontAsk` | Auto-denies every call that would otherwise prompt, though a [mod](/docs/en/plugins/mods/overview) you installed can still approve some of those calls. 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`](/docs/en/mcp#require-approval-for-a-specific-tool), [reads from network paths](#network-paths), and connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools) in sessions where that setting reaches Claude Code are denied even if you've allowed them |
8379| `bypassPermissions` | Skips permission prompts, except for the [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) |
8480 
85<Warning>
86 In `bypassPermissions` mode, Claude Code skips permission prompts, including for writes to [protected paths](/docs/en/permission-modes#protected-paths) such as `.git` and `.claude`. The [cross-session messaging safeguards](/docs/en/permission-modes#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.
87</Warning>
81> [!WARNING]
82>
83> In `bypassPermissions` mode, Claude Code skips permission prompts, including for writes to [protected paths](/docs/en/permission-modes#protected-paths) such as `.git` and `.claude`. The [cross-session messaging safeguards](/docs/en/permission-modes#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.
8884 
8985To prevent `bypassPermissions` or `auto` mode from being used, set `permissions.disableBypassPermissionsMode` or `permissions.disableAutoMode` to `"disable"` in any [settings file](/docs/en/settings#where-settings-live). These are most useful in [managed settings](#managed-settings) where they can't be overridden.
9086 
from line 141
145141 
146142A `*` 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.
147143 
148<Warning>
149 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](/docs/en/errors#has-a-wildcard-before-the-rest-of-the-command) about an allow rule with a `*` before the subcommand, such as `Bash(git * main)`.
150</Warning>
144> [!WARNING]
145>
146> 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](/docs/en/errors#has-a-wildcard-before-the-rest-of-the-command) about an allow rule with a `*` before the subcommand, such as `Bash(git * main)`.
151147 
152148Write 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).
153149 
from line 212
216212 
217213#### Compound commands
218214 
219<Tip>
220 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.
221</Tip>
215> [!TIP]
216>
217> 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.
222218 
223219Deny 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](/docs/en/permission-modes#eliminate-prompts-with-auto-mode).
224220 
from line 222
226222 
227223When 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.
228224 
229<h4 id="process-wrappers">
230 Wrappers
231</h4>
225#### Wrappers
232226 
233227Before 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`.
234228 
from line 232
238232 
239233This 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.
240234 
241<h4 id="exec-wrappers-and-find-actions">
242 Exec wrappers and `find` actions
243</h4>
235#### Exec wrappers and `find` actions
244236 
245237A prefix rule like `Bash(watch *)` or `Bash(find *)` can't auto-approve the following commands, so in Manual mode they prompt:
246238 
from line 243
251243 
252244When the command has a `*`, as in `find . -name '*.tmp' -delete`, Claude Code reads the rule as a [wildcard pattern](#wildcard-patterns), not an exact match, so the command still prompts. Approve it each time it prompts, or use a [PreToolUse hook](/docs/en/hooks#pretooluse-decision-control) that returns `"allow"` for it.
253245 
254<h4 id="bash-rule-limits">
255 What a Bash rule doesn't match
256</h4>
246#### What a Bash rule doesn't match
257247 
258248A 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:
259249 
from line 280
290280* **`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.
291281* **`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.
292282 
293<Warning>
294 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:
283> [!WARNING]
284>
285> 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:
286>
287> * Options before URL: `curl -X GET http://github.com/...`
288> * Different protocol: `curl https://github.com/...`
289> * Redirects: `curl -L http://short.example.com/xyz`, which redirects to GitHub
290> * Variables: `URL=http://github.com && curl $URL`
291>
292> For more reliable URL filtering, consider:
293>
294> * **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](/docs/en/sandboxing#network-isolation) when the restriction must hold; see [what a Bash rule doesn't match](#bash-rule-limits)
295> * **Use PreToolUse hooks**: implement a hook that validates URLs in Bash commands and blocks disallowed domains
296> * **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
297>
298> 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.
295299 
296 * Options before URL: `curl -X GET http://github.com/...`
297 * Different protocol: `curl https://github.com/...`
298 * Redirects: `curl -L http://short.example.com/xyz`, which redirects to GitHub
299 * Variables: `URL=http://github.com && curl $URL`
300 
301 For more reliable URL filtering, consider:
302 
303 * **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](/docs/en/sandboxing#network-isolation) when the restriction must hold; see [what a Bash rule doesn't match](#bash-rule-limits)
304 * **Use PreToolUse hooks**: implement a hook that validates URLs in Bash commands and blocks disallowed domains
305 * **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
306 
307 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.
308</Warning>
309 
310300#### Redirections
311301 
312302When 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:
from line 347
357347 
358348Claude 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](/docs/en/errors#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.
359349 
360<Warning>
361 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](/docs/en/sandboxing).
362</Warning>
350> [!WARNING]
351>
352> 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](/docs/en/sandboxing).
363353 
364354Read 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:
365355 
from line 360
370360| `/path` | Path relative to the settings source | `Edit(/src/**/*.ts)` | `<primary working directory>/src/**/*.ts` in project settings |
371361| `path` or `./path` | Path relative to current directory | `Read(*.env)` | `<cwd>/*.env` |
372362 
373<Warning>
374 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.
375</Warning>
363> [!WARNING]
364>
365> 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.
376366 
377367A `/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:
378368 
from line 422
432422| `Edit(/src/**)` in any rule type | Yes | No |
433423| `Edit(**/src/**)` in any rule type | Yes | Yes |
434424 
435<Note>
436 In gitignore patterns, `*` matches within a single path segment and can appear at any position in the pattern, while `**` matches across directories.
437</Note>
425> [!NOTE]
426>
427> In gitignore patterns, `*` matches within a single path segment and can appear at any position in the pattern, while `**` matches across directories.
438428 
439429When 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.
440430 
from line 698
708698 
709699Commands that won't run sandboxed, such as excluded commands, respect the bare `Bash` ask rule as usual. See [sandbox modes](/docs/en/sandboxing#sandbox-modes) to change this behavior.
710700 
711<span id="managed-only-settings" />
712 
713701## Managed settings
714702 
715703For organizations that need centralized control, administrators deploy managed settings that user and project settings can't override, apart from a few [security-sensitive keys](/docs/en/settings#exceptions-to-managed-settings-precedence). [Deploy managed settings](/docs/en/managed-settings) covers the delivery mechanisms, precedence within the managed tier, and the [keys that only managed settings can set](/docs/en/managed-settings#managed-only-settings).
from line 741
753741* **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`](/docs/en/env-vars#variables). If that `CLAUDE_CONFIG_DIR` directory sits inside a git repository and Claude Code [keeps your local settings at the repository root](/docs/en/settings#where-claude-code-looks-for-each-file) instead, it holds the rules like anywhere else.
754742* **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.
755743 
756<Note>
757 The configuration-home exception skips only the trust step. `~/.claude/settings.local.json` is still [local scope](/docs/en/settings#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.
758</Note>
744> [!NOTE]
745>
746> The configuration-home exception skips only the trust step. `~/.claude/settings.local.json` is still [local scope](/docs/en/settings#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.
759747 
760748### What runs before you trust a folder
761749 

plugin-evals Changed · +81 / -119 lines

## Write and refine cases ### Set run limits and tools in prompt.md ### Choose and weight graders ### Score against the no-plugin baseline ### Seed the workspace or conversation ### Mock MCP servers ### Run evals in CI ## What a run can access ### How runs are isolated ### prompt.md frontmatter ### case.yaml fields ### Mock files #### Regex patterns in expect ### "is too old for claude plugin eval" ### "cannot be evaluated where sessions load it" ### `--json output path must end in .json` ### "ended on an API error and scored 0 without grading" ### "mock call budget exceeded"

from line 14
1414 
1515This page is for plugin and skill authors who have a working plugin and want to test its behavior, and for teams that gate plugin changes in CI. For iterating on one skill inside a Claude Code conversation, the [skill-creator plugin](/docs/en/skills#run-evals-with-skill-creator) runs a similar comparison with its own `evals/evals.json` format, and neither tool reads the other's case files. To create a plugin, see [Create a plugin](/docs/en/plugins/create); to check a plugin's files for syntax and schema errors rather than its behavior, use [`claude plugin validate`](/docs/en/plugins/cli-reference#plugin-validate).
1616 
17<Note>
18 Every eval run and every judge grader is a real model call on your account, counted against your plan's usage or your API bill, so check the [requirements](#requirements) first. Then [create your first eval suite](#create-your-first-eval-suite), or go to [Run evals in CI](#run-evals-in-ci) if you already have one.
19</Note>
17> [!NOTE]
18>
19> Every eval run and every judge grader is a real model call on your account, counted against your plan's usage or your API bill, so check the [requirements](#requirements) first. Then [create your first eval suite](#create-your-first-eval-suite), or go to [Run evals in CI](#run-evals-in-ci) if you already have one.
2020 
2121## Requirements
2222 
from line 55
5555* A terminal open at your plugin's root directory, the one containing `plugin.json` or `.claude-plugin/plugin.json`
5656* One skill in the plugin you want to test, and a request a user would type that should trigger it
5757 
58<Steps>
59 <Step title="Create the cases">
60 From the plugin root, run:
58**1. Create the cases**
6159 
62 ```bash theme={null}
63 claude plugin eval init
64 ```
60From the plugin root, run:
6561 
66 If Claude Code doesn't already trust this directory it first asks `Trust this plugin directory?`; answer `y`.
62```bash theme={null}
63claude plugin eval init
64```
6765 
68 An interactive Claude Code session then opens. Claude reads your plugin and asks you what a good result looks like, proposes prompts that should and shouldn't trigger the plugin, designs graders for each, runs them once as a trial to check they behave, and writes one case directory per prompt under `evals/`, each named after its prompt.
66If Claude Code doesn't already trust this directory it first asks `Trust this plugin directory?`; answer `y`.
6967 
70 When Claude tells you the suite is ready, exit that session with `/exit` or Ctrl+D to return to your shell.
68An interactive Claude Code session then opens. Claude reads your plugin and asks you what a good result looks like, proposes prompts that should and shouldn't trigger the plugin, designs graders for each, runs them once as a trial to check they behave, and writes one case directory per prompt under `evals/`, each named after its prompt.
7169 
72 If you already have a Claude Code session open at the plugin root, you can instead ask Claude there to run `claude plugin eval init`. Claude runs the command and then asks you the same questions in that conversation.
70When Claude tells you the suite is ready, exit that session with `/exit` or Ctrl+D to return to your shell.
7371 
74 If you'd rather write a case yourself to see exactly what the files contain, follow [Write a case manually](#write-a-case-manually) and come back here to run it.
75 </Step>
72If you already have a Claude Code session open at the plugin root, you can instead ask Claude there to run `claude plugin eval init`. Claude runs the command and then asks you the same questions in that conversation.
7673 
77 <Step title="Run the suite">
78 Back at your shell in the plugin root, run every case under `evals/`:
74If you'd rather write a case yourself to see exactly what the files contain, follow [Write a case manually](#write-a-case-manually) and come back here to run it.
7975 
80 ```bash theme={null}
81 claude plugin eval .
82 ```
76**2. Run the suite**
8377 
84 You already trusted this directory during step 1, so the run starts immediately. If you wrote the case manually instead, the run first asks `Trust this plugin directory? [y/N]`; answer `y`. [What a run can access](#security) explains what you're agreeing to.
78Back at your shell in the plugin root, run every case under `evals/`:
8579 
86 Each case runs three times with your plugin and three times without it, so one case is six runs. A progress line prints as each run finishes, with that run's score and each grader's verdict.
87 </Step>
80```bash theme={null}
81claude plugin eval .
82```
8883 
89 <Step title="Read the summary">
90 When the suite finishes you see a summary table, followed by where the report went:
84You already trusted this directory during step 1, so the run starts immediately. If you wrote the case manually instead, the run first asks `Trust this plugin directory? [y/N]`; answer `y`. [What a run can access](#security) explains what you're agreeing to.
9185 
92 ```text theme={null}
93 CASE WITH W/OUT Δ RUNS COST NOTES
94 first-case 1.00 0.33 +0.67 6 $0.41
86Each case runs three times with your plugin and three times without it, so one case is six runs. A progress line prints as each run finishes, with that run's score and each grader's verdict.
9587 
96 1 case(s) · mean Δ +0.67 · 74s · $0.41
97 Report: /Users/you/my-plugin/evals/results/2026-09-10T17-02-11-482Z/report.html
98 Published: https://claude.ai/... · keep local next time with --no-publish
99 ```
88**3. Read the summary**
10089 
101 `WITH` is the case's score with your plugin loaded, `W/OUT` is the score without it, and a positive `Δ` means the plugin raised the score. `COST` is a list-price estimate of the model calls, and `NOTES` shows the highest-weight failing grader's explanation, or the run's error, from the with-arm.
102 </Step>
90When the suite finishes you see a summary table, followed by where the report went:
10391 
104 <Step title="Open the report and iterate">
105 Open the `Published:` URL, or the `Report:` path when no `Published:` line appears, to see each grader's verdict and explanation for every run, and for `llm` graders the judge's votes and the excerpt it judged. The `Published:` line appears only when your account can [publish reports](#html-report).
92```text theme={null}
93CASE WITH W/OUT Δ RUNS COST NOTES
94first-case 1.00 0.33 +0.67 6 $0.41
10695 
107 The most common first finding is a `Δ` near zero with the case's `tool_used: Skill` grader failing, which means Claude isn't choosing your skill on natural phrasing. Adjust the skill's [`description`](/docs/en/skills#frontmatter-reference), run `claude plugin eval .` again, and compare.
961 case(s) · mean Δ +0.67 · 74s · $0.41
97Report: /Users/you/my-plugin/evals/results/2026-09-10T17-02-11-482Z/report.html
98Published: https://claude.ai/... · keep local next time with --no-publish
99```
108100 
109 To iterate on one case with fewer runs, run a single arm once. A single run is noisy, so confirm any change at the default three runs before you trust it. With one arm the table shows `SCORE` and `PASS%` columns instead of `WITH`, `W/OUT`, and `Δ`:
101`WITH` is the case's score with your plugin loaded, `W/OUT` is the score without it, and a positive `Δ` means the plugin raised the score. `COST` is a list-price estimate of the model calls, and `NOTES` shows the highest-weight failing grader's explanation, or the run's error, from the with-arm.
110102 
111 ```bash theme={null}
112 claude plugin eval . --case <case-name> --runs 1 --ablation none
113 ```
103**4. Open the report and iterate**
114104 
115 Replace `<case-name>` with one of the directory names under `evals/`.
116 </Step>
117</Steps>
105Open the `Published:` URL, or the `Report:` path when no `Published:` line appears, to see each grader's verdict and explanation for every run, and for `llm` graders the judge's votes and the excerpt it judged. The `Published:` line appears only when your account can [publish reports](#html-report).
118106 
119<h2 id="write-and-refine-cases">
120 Write and refine cases
121</h2>
107The most common first finding is a `Δ` near zero with the case's `tool_used: Skill` grader failing, which means Claude isn't choosing your skill on natural phrasing. Adjust the skill's [`description`](/docs/en/skills#frontmatter-reference), run `claude plugin eval .` again, and compare.
122108 
109To iterate on one case with fewer runs, run a single arm once. A single run is noisy, so confirm any change at the default three runs before you trust it. With one arm the table shows `SCORE` and `PASS%` columns instead of `WITH`, `W/OUT`, and `Δ`:
110 
111```bash theme={null}
112claude plugin eval . --case <case-name> --runs 1 --ablation none
113```
114 
115Replace `<case-name>` with one of the directory names under `evals/`.
116 
117## Write and refine cases
118 
123119The cases `claude plugin eval init` writes are plain files you can open, change, and add to. A case is a directory under the plugin's eval directory that contains a `prompt.md`, a `case.yaml`, or both. Give each case at least one grader, as a `graders/<name>.md` file or a `graders:` entry in `case.yaml`, because a case without one fails to load. To group cases, nest them under a directory that isn't itself a case; anything inside a case directory, such as `graders/` and fixture files, belongs to that case.
124120 
125121This is the layout `claude plugin eval init` writes and the one to use for new suites. The [eval suite reference](#eval-suite-reference) has the complete tree, including mocks and results:
from line 193
197193 
198194With both files saved, run the case the way the [quickstart](#create-your-first-eval-suite) does, with `claude plugin eval .` from the plugin root.
199195 
200<h3 id="set-run-limits-and-tools-in-prompt-md">
201 Set run limits and tools in prompt.md
202</h3>
196### Set run limits and tools in prompt.md
203197 
204198Set a case's `max_turns`, `timeout_seconds`, `model`, `tags`, and the `allowed_tools` it may use in `prompt.md` frontmatter; the [prompt.md frontmatter](#prompt-md-fields) reference lists every field and its default.
205199 
206200Claude receives the body exactly as you wrote it. `@path` mentions in it aren't expanded into file attachments, so if Claude needs to read a file, grant a tool for it in `allowed_tools`.
207201 
208<h3 id="grade-the-result">
209 Choose and weight graders
210</h3>
202### Choose and weight graders
211203 
212204A grader's frontmatter sets its `type`, and optionally a `weight` that makes it count for more of the run's score and an [`arm`](#compare-against-a-no-plugin-baseline) that controls how it's scored against the baseline. Of the six types, `regex`, `tool_used`, `tool_order`, and `file_exists` are computed from the transcript and files and cost nothing, while `llm` and `baseline` call a judge model and add to the run's cost.
213205 
from line 218
226218* If a case's `tool_used: Skill` grader passes but `Δ` is negative, suspect the judge before the plugin. A small judge model can mark a correct answer wrong because it's formatted differently from what the rubric describes. Re-run with `--judge-model sonnet`, and tighten the rubric so formatting doesn't decide the verdict.
227219* To check that a build or test passed inside the run, have the prompt ask Claude to run it and write the outcome to a file, grade that file, and assert the command ran with a `tool_used` grader whose `input_match` names the command.
228220 
229<h3 id="compare-against-a-no-plugin-baseline">
230 Score against the no-plugin baseline
231</h3>
221### Score against the no-plugin baseline
232222 
233223When a plugin is under test, a case normally runs in two arms. The with-arm is its runs with the plugin loaded, and the without-arm is the same number of runs with no plugin at all. The summary and report show both scores and `Δ`, the with-arm score minus the without-arm score.
234224 
from line 253
263253 
264254A case can need more than a prompt: files or a git repository in the workspace, an earlier conversation to continue, or answers from the MCP servers your plugin connects to. Each of those is set up beside the case so runs stay repeatable.
265255 
266<h3 id="add-setup-or-history-with-case-yaml">
267 Seed the workspace or conversation
268</h3>
256### Seed the workspace or conversation
269257 
270258Each run starts in an empty workspace. When a case needs more than the prompt, add a `case.yaml` beside `prompt.md` with a `context` block:
271259 
from line 276
288276 
289277A scaffold script starts in the empty workspace with a small fixed environment: your shell's `PATH`, `HOME` set to the run's temporary home directory, `TMPDIR`, and a few constants such as `TERM=dumb`. Nothing else from your shell reaches it, and neither do the case's `EVAL_*` variables. If the script exits non-zero or runs longer than 120 seconds, that run scores 0 with a `scaffold failed` error. Use the script for files and git state only, since project configuration it writes [isn't loaded](#how-runs-are-isolated).
290278 
291<h3 id="mock-mcp-servers">
292 Mock MCP servers
293</h3>
279### Mock MCP servers
294280 
295281You can evaluate a plugin whose skills call MCP tools without the real service behind them. Put one Markdown file per tool under `evals/mocks/<server>/<tool>.md` for the whole suite, or under a case's own `mocks/` directory for one case, where `<server>` is the server's name in your plugin's [MCP configuration](/docs/en/plugins/components#mcp-servers).
296282 
from line 374
388374| `--publish-report` | | Publish the report even where it would stay local by default, such as a run a Claude Code session started |
389375| `--keep-temp` | Off | Keep every run's sandbox directory and print its path, for debugging what Claude produced |
390376 
391<h3 id="run-evals-in-ci">
392 Run evals in CI
393</h3>
377### Run evals in CI
394378 
395379In your CI job, run the suite with `--json` to write the result for archiving, and fail the build on the exit code. Pass `--trust-plugin` so the job never waits at the [first-run trust prompt](#security), pin both models so scores are comparable over time, keep the report local, and set a cost ceiling as an upper limit:
396380 
from line 419
435419 
436420`report.html` is a single self-contained file that makes no external requests, so you can attach it to a CI job or open it from disk. This example is the top of a report for a three-case suite run with `--threshold 0.8`; the cost shown is a list-price estimate and varies with the model and the number of cases:
437421 
438<img src="https://mintcdn.com/claude-code/qq7LHDi_F0aeFHgk/images/plugin-eval-report.png?fit=max&auto=format&n=qq7LHDi_F0aeFHgk&q=85&s=106eb6e6a70a6565f891ea3a4564f87d" alt="Top of an eval report: a verdict line reading &#x22;Plugin effect: +33.3 pts vs baseline, improved 2, flat 1, regressed 0 of 3 cases&#x22;, five summary tiles for suite score, ablation delta, baseline score, cases passing the threshold, and perfect runs, then the first case with its delta, score bar, and one run whose two graders both show pass" width="1360" height="1032" data-path="images/plugin-eval-report.png" />
422![Top of an eval report: a verdict line reading "Plugin effect: +33.3 pts vs baseline, improved 2, flat 1, regressed 0 of 3 cases", five summary tiles for suite score, ablation delta, baseline score, cases passing the threshold, and perfect runs, then the first case with its delta, score bar, and one run whose two graders both show pass](https://mintcdn.com/claude-code/qq7LHDi_F0aeFHgk/images/plugin-eval-report.png?fit=max\&auto=format\&n=qq7LHDi_F0aeFHgk\&q=85\&s=106eb6e6a70a6565f891ea3a4564f87d)
439423 
440424Read it from the top down:
441425 
from line 452
468452| `cases[].arms.with[].skippedPaidGraders` | `true` when the cost ceiling skipped this run's judge graders, so its score isn't comparable |
469453| `costUsd`, `durationSeconds`, `claudeVersion` | Estimated cost at list price including judge calls, wall-clock seconds, and the Claude Code version that ran the suite |
470454 
471<h2 id="security">
472 What a run can access
473</h2>
455## What a run can access
474456 
475457`claude plugin eval` loads the target plugin's skills, hooks, and agents and runs its eval suite on your machine, as you. Pointing it at a plugin is the same trust decision as `claude --plugin-dir`, so only evaluate plugins you trust.
476458 
from line 472
490472 
491473When the plugin includes hooks you didn't write, or you start its real MCP servers, treat its scores as advisory unless you ran it in an isolated environment such as a container or CI runner, since hooks and servers run outside the agent's sandbox and could modify the files the graders read.
492474 
493<h3 id="how-runs-are-isolated">
494 How runs are isolated
495</h3>
475### How runs are isolated
496476 
497477Each run gets a temporary home directory, working directory, and Claude Code configuration, and the agent under test runs there as a `claude -p` child process with only your plugin loaded. Keep these consequences in mind when you write cases:
498478 
from line 508
528508 └── mock-recordings/ # agent-mock answers from clean runs, with ADOPT.txt
529509```
530510 
531<h3 id="prompt-md-fields">
532 prompt.md frontmatter
533</h3>
511### prompt.md frontmatter
534512 
535513`prompt.md` frontmatter accepts these fields. An unknown key is an error:
536514 
from line 528
550528| `append_system_prompt` | | Text appended to the child session's system prompt |
551529| `env` | `{}` | Extra environment variables for the child session. Keys must match `EVAL_[A-Z0-9_]*`; any other key fails the run. The run inherits only an allowlist from your shell: basics such as `PATH` and locale, proxy and certificate settings, the variables that select and authenticate your model provider, most `ANTHROPIC_*` and `CLAUDE_CODE_*` configuration, and `EVAL_*`. To pass the plugin anything else, such as a toolchain setting, export it as an `EVAL_*` variable |
552530 
553<h3 id="case-yaml-fields">
554 case.yaml fields
555</h3>
531### case.yaml fields
556532 
557533`case.yaml` is an alternative or companion to `prompt.md`: it describes a case in YAML and adds the fields that point at other files. It requires `schema_version: "1.1"` and `name`. The `prompt.md` fields `description`, `tags`, `plugins`, `runs`, and `expected_outcome` go at the top level; `model`, `max_turns`, `timeout_seconds`, `allowed_tools`, `append_system_prompt`, and `env` go under `execution:`. When both files exist, `prompt.md` frontmatter overrides the matching `case.yaml` fields, the `prompt.md` body is the prompt, and `graders/*.md` are added after any graders listed in `case.yaml`.
558534 
from line 577
601577| `llm` | `criteria`, `focus` | A judge model votes PASS on the rubric in at least two of three votes. In the `.md` layout the file body is the criteria |
602578| `baseline` | `baseline_file`, `criteria` | A judge finds the run satisfies the criteria at least as well as the reference transcript at `baseline_file`, a `.jsonl` in the case directory |
603579 
604<h3 id="mock-files">
605 Mock files
606</h3>
580### Mock files
607581 
608582A `<tool>.md` file under `mocks/<server>/` answers one tool. Its body is the tool result, with `{{input.<field>}}` and `{{file:fixtures/<name>}}` substitutions. Its frontmatter accepts these keys:
609583 
from line 595
621595 
622596A case's own `mocks/` directory uses the same layout and overrides the suite's mocks file by file.
623597 
624<h4 id="expect-patterns">
625 Regex patterns in expect
626</h4>
598#### Regex patterns in expect
627599 
628600A `/regex/` value in `expect:` uses a small dialect that Claude Code checks when it loads the suite:
629601 
from line 624
652624 
653625This is the first run against a directory Claude Code doesn't trust yet, and it can't ask you because stdin or stdout isn't a terminal or you passed `--json`. Run `claude plugin eval <dir>` once in a terminal and answer the prompt, or pass `--trust-plugin` if you trust the plugin's code and suite. See [What a run can access](#security).
654626 
655<h3 id="git-is-too-old-for-claude-plugin-eval">
656 "is too old for claude plugin eval"
657</h3>
627### "is too old for claude plugin eval"
658628 
659629The `git` on your `PATH` is older than 2.31, so `claude plugin eval` stopped before running any case and exited 1 with a message naming your version:
660630 
from line 636
666636 
667637Before v2.1.283, `claude plugin eval` didn't check the git version, and on an older git the suite ran with those programs left on.
668638 
669<h3 id="cannot-be-evaluated-where-sessions-load-it">
670 "cannot be evaluated where sessions load it"
671</h3>
639### "cannot be evaluated where sessions load it"
672640 
673641You ran `claude plugin eval` in your shell with the name of a plugin installed from a marketplace you [added from a local path](/docs/en/plugins/loading#in-place-and-copied-plugins). No session could load the plugin from that marketplace now, so the command refuses with this message and exits with code 1.
674642 
from line 688
720688 
721689The default `--threshold` is 1.0, so the command exits 1 when any case scores below perfect. Set a threshold that matches the score you require.
722690 
723<h3 id="json-output-path-must-end-in-json">
724 `--json output path must end in .json`
725</h3>
691### `--json output path must end in .json`
726692 
727693You put the target after `--json`, so it was read as the output path. Put the target first, as in `claude plugin eval . --json`, or give `--json` an explicit `.json` path.
728694 
from line 696
730696 
731697That grader is excluded from the score by design in a two-arm run, and its `scored` field is `false`. See [Score against the no-plugin baseline](#compare-against-a-no-plugin-baseline).
732698 
733<h3 id="runs-ended-on-an-api-error">
734 "ended on an API error and scored 0 without grading"
735</h3>
699### "ended on an API error and scored 0 without grading"
736700 
737701This stderr warning means the API answered at least one run's last request with an HTTP error, such as a rate limit or a plan usage limit. Such a run scores 0 with no grader results, and the command exits non-zero whatever the scores and `--threshold` are.
738702 
from line 713
749713 
750714Runs that end with a usage-limit or rate-limit error [score 0 without grading](#runs-ended-on-an-api-error), and the command exits non-zero. The suite still finishes and isn't marked `partial`. Re-run after the limit resets, with `--runs 1` or a `--case` filter if you need to stay under it.
751715 
752<h3 id="mock-call-budget-exceeded">
753 "mock call budget exceeded"
754</h3>
716### "mock call budget exceeded"
755717 
756718Every `type: agent` [mock](#mock-mcp-servers) in a run draws on one call budget of four times the case's `max_turns`, which is 40 calls at the default of 10. Calls answered from `.replay/` recordings count too, and the case's `mock budget` progress line prints the budget. A call past it aborts the run with score 0 and this reason, so raise `max_turns` in the case for a skill that makes many calls to agent mocks.
757719 

plugins/anthropic-marketplaces Changed · +6 / -6 lines

from line 6
66 
77Use this page to distinguish the three marketplaces and to find where to check whether the official one holds a given plugin.
88 
9<Note>
10 These cases are covered on other pages:
11 
12 * **How to install a plugin**: see [Install plugins](/docs/en/plugins/install)
13 * **A failed install**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
14</Note>
9> [!NOTE]
10>
11> These cases are covered on other pages:
12>
13> * **How to install a plugin**: see [Install plugins](/docs/en/plugins/install)
14> * **A failed install**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
1515 
1616Go to the part of the page you need:
1717 

plugins/cli-hints Changed · +30 / -32 lines

from line 6
66 
77This page applies only if your plugin is listed in `claude-plugins-official` or another marketplace with one of Anthropic's [official marketplace names](/docs/en/plugins/security#official-marketplace-names). The community marketplace, `claude-community`, isn't one of them.
88 
9<Note>
10 To publish a plugin, see [Publish and distribute a plugin](/docs/en/plugins/publish).
11</Note>
9> [!NOTE]
10>
11> To publish a plugin, see [Publish and distribute a plugin](/docs/en/plugins/publish).
1212 
1313## Emit the hint
1414 
from line 23
2323 
2424The following examples gate on `CLAUDECODE` for the widest reach and emit a hint for a plugin named `example-cli` in the official marketplace:
2525 
26<CodeGroup>
27 ```javascript Node.js theme={null}
28 if (process.env.CLAUDECODE) {
29 process.stderr.write(
30 '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />\n',
31 )
32 }
33 ```
26```javascript Node.js theme={null}
27if (process.env.CLAUDECODE) {
28 process.stderr.write(
29 '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />\n',
30 )
31}
32```
3433 
35 ```python Python theme={null}
36 import os, sys
34```python Python theme={null}
35import os, sys
3736 
38 if os.environ.get("CLAUDECODE"):
39 print(
40 '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />',
41 file=sys.stderr,
42 )
43 ```
37if os.environ.get("CLAUDECODE"):
38 print(
39 '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />',
40 file=sys.stderr,
41 )
42```
4443 
45 ```go Go theme={null}
46 if os.Getenv("CLAUDECODE") != "" {
47 fmt.Fprintln(os.Stderr,
48 `<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />`)
49 }
50 ```
44```go Go theme={null}
45if os.Getenv("CLAUDECODE") != "" {
46 fmt.Fprintln(os.Stderr,
47 `<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />`)
48}
49```
5150 
52 ```shell Shell theme={null}
53 if [ -n "$CLAUDECODE" ]; then
54 printf '%s\n' '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />' >&2
55 fi
56 ```
57</CodeGroup>
51```shell Shell theme={null}
52if [ -n "$CLAUDECODE" ]; then
53 printf '%s\n' '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />' >&2
54fi
55```
5856 
5957Replace `example-cli` with your plugin's name in the official marketplace.
6058 

plugins/cli-reference Changed · +26 / -22 lines

#### JSON result format ## /plugin in a session ## /reload-plugins

from line 6
66 
77The tables below list each subcommand's commonly used options, not every option. Run `claude plugin --help` in your shell to see which subcommands your version has, and `claude plugin <subcommand> --help` for a subcommand's full option list.
88 
9<Note>
10 These cases are covered on other pages:
9> [!NOTE]
10>
11> These cases are covered on other pages:
12>
13> * **Install and manage steps, and where `/plugin` runs**: see [Install and manage plugins](/docs/en/plugins/install)
14> * **What a command changes on disk and which scope takes precedence**: see [Plugin loading reference](/docs/en/plugins/loading)
15> * **What an error message means**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
1116 
12 * **Install and manage steps, and where `/plugin` runs**: see [Install and manage plugins](/docs/en/plugins/install)
13 * **What a command changes on disk and which scope takes precedence**: see [Plugin loading reference](/docs/en/plugins/loading)
14 * **What an error message means**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
15</Note>
16 
1717## claude plugin commands
1818 
1919Run `claude plugin <subcommand>` from your shell or a script, outside a Claude Code session. These subcommands install and manage plugins without opening the [`/plugin`](#plugin-in-a-session) panel.
from line 102
102102* **You decline a command-source prompt**: the output is `Aborted.` and the exit code is `1`
103103* **You decline a `headersHelper` prompt, or it can't be confirmed without a TTY**: the output is `Aborted — the command was not run.` and the exit code is `1`
104104 
105<h4 id="plugin-json-result">
106 JSON result format
107</h4>
105#### JSON result format
108106 
109107When you pass `--json` to `plugin install`, the last line of stdout is one JSON object. Parse only that line, because Claude Code prints any command the marketplace declares ahead of it.
110108 
from line 372
374372 
375373For what the two cost figures mean, see [Measure plugin cost and usage](/docs/en/plugins/measure).
376374 
377For a plugin that isn't loaded, Claude Code prints ``Plugin "formatter" not found. Run `claude plugin list` to see installed plugins, or pass --plugin-dir <path> to load one from disk.`` and exits `1`.
375For a plugin that isn't loaded, Claude Code prints this message and exits `1`:
378376 
377```text theme={null}
378Plugin "formatter" not found. Run `claude plugin list` to see installed plugins, or pass --plugin-dir <path> to load one from disk.
379```
380 
381An ID that ends in `@builtin` names one of the [plugins built into Claude Code](/docs/en/plugins/mods/overview#mods-built-into-claude-code). If you pass such an ID and Claude Code doesn't find that plugin, the message reads instead:
382 
383```text theme={null}
384Plugin "<name>@builtin" not found. Built-in plugins don't appear in `claude plugin list`. To see the ones available in a session, run /plugin in Claude Code and open the Installed tab.
385```
386 
379387### plugin configure
380388 
381389Show an installed plugin's [`userConfig`](/docs/en/plugins/manifest-reference#user-configuration) options and which are set, or save values piped in on stdin. Requires Claude Code v2.1.285 or later.
from line 748
740748 
741749Remove a marketplace's declaration from your settings. `rm` is an alias for `remove`.
742750 
743<Warning>
744 When you remove a marketplace from the last scope that declares it, Claude Code also deletes its cache and uninstalls every plugin you installed from it. It also deletes their saved [options and secrets](/docs/en/plugins/manifest-reference#user-configuration) and [data](/docs/en/plugins/components#path-variables-and-persistent-data) where it can.
751> [!WARNING]
752>
753> When you remove a marketplace from the last scope that declares it, Claude Code also deletes its cache and uninstalls every plugin you installed from it. It also deletes their saved [options and secrets](/docs/en/plugins/manifest-reference#user-configuration) and [data](/docs/en/plugins/components#path-variables-and-persistent-data) where it can.
754>
755> To refresh a marketplace without losing its plugins, run `plugin marketplace update` instead.
745756 
746 To refresh a marketplace without losing its plugins, run `plugin marketplace update` instead.
747</Warning>
748 
749757```bash theme={null}
750758claude plugin marketplace remove <name> [options]
751759```
from line 795
787795 
788796Claude Code prints `Successfully updated marketplace: your-marketplace`. When you omit the name, it prints a count such as `Successfully updated 2 marketplaces`.
789797 
790<h2 id="plugin-in-a-session">
791 /plugin in a session
792</h2>
798## /plugin in a session
793799 
794800Inside an interactive session, `/plugin` opens the plugin panel. Each subcommand opens the panel on a tab, runs an action there, or prints a result inline. `/plugins` and `/marketplace` are aliases for `/plugin`.
795801 
from line 832
826832 
827833If you name a plugin that isn't installed in the current project in `/plugin enable`, `disable`, `uninstall`, or `configure`, Claude Code prints `Plugin "<plugin>" is not installed in this project` instead of acting.
828834 
829<h2 id="reload-plugins">
830 /reload-plugins
831</h2>
835## /reload-plugins
832836 
833837Apply pending plugin changes to the running session without restarting it. Pending changes are plugins you installed, updated, enabled, disabled, or edited on disk since the session started.
834838 

plugins/code-intelligence Changed · +37 / -39 lines

from line 6
66 
77Each plugin connects Claude Code to a language server for one language through the Language Server Protocol (LSP). You install the plugin from Anthropic's official marketplace and the language server binary on your machine.
88 
9<Note>
10 Code intelligence plugins work in terminal sessions. In [cloud sessions](/docs/en/claude-code-on-the-web), Claude Code doesn't start plugin language servers, so Claude gets no diagnostics or code navigation there. To write your own language server plugin, or to connect a language server that has no plugin, see [LSP servers in plugin components](/docs/en/plugins/components#lsp-servers).
11</Note>
9> [!NOTE]
10>
11> Code intelligence plugins work in terminal sessions. In [cloud sessions](/docs/en/claude-code-on-the-web), Claude Code doesn't start plugin language servers, so Claude gets no diagnostics or code navigation there. To write your own language server plugin, or to connect a language server that has no plugin, see [LSP servers in plugin components](/docs/en/plugins/components#lsp-servers).
1212 
1313To get started, find your language in the table under [Install a code intelligence plugin](#install-a-code-intelligence-plugin). The plugins in that table come from Anthropic's [official plugin marketplace](/docs/en/plugins/anthropic-marketplaces).
1414 
from line 18
1818 
1919A code intelligence plugin tells Claude Code which command starts the language server and which file extensions it handles. It doesn't include the language server. Install the language server binary first, then the plugin, then confirm the server starts.
2020 
21<Steps>
22 <Step title="Install the language server binary">
23 Find your language in the table below and install the binary in its row. If your language isn't listed, see [Add a language without an official plugin](#add-a-language-without-an-official-plugin).
21**1. Install the language server binary**
2422 
25 | Language | Plugin | Binary |
26 | :- | :- | :- |
27 | C/C++ | [`clangd-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/clangd-lsp) | `clangd` |
28 | C# | [`csharp-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/csharp-lsp) | `csharp-ls` |
29 | Go | [`gopls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gopls-lsp) | `gopls` |
30 | Java | [`jdtls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/jdtls-lsp) | `jdtls` |
31 | Kotlin | [`kotlin-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/kotlin-lsp) | `kotlin-lsp` |
32 | Liquid | [`liquid-lsp`](https://github.com/Shopify/liquid-skills/tree/main/plugins/liquid-lsp) | `shopify`, from the Shopify CLI |
33 | Lua | [`lua-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/lua-lsp) | `lua-language-server` |
34 | PHP | [`php-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/php-lsp) | `intelephense` |
35 | Python | [`pyright-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pyright-lsp) | `pyright-langserver` |
36 | Ruby | [`ruby-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ruby-lsp) | `ruby-lsp` |
37 | Rust | [`rust-analyzer-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/rust-analyzer-lsp) | `rust-analyzer` |
38 | Swift | [`swift-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/swift-lsp) | `sourcekit-lsp` |
39 | TypeScript and JavaScript | [`typescript-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/typescript-lsp) | `typescript-language-server` |
23Find your language in the table below and install the binary in its row. If your language isn't listed, see [Add a language without an official plugin](#add-a-language-without-an-official-plugin).
4024 
41 Anthropic maintains every plugin in the table except `liquid-lsp`, which Shopify maintains and the official marketplace lists.
25| Language | Plugin | Binary |
26| :- | :- | :- |
27| C/C++ | [`clangd-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/clangd-lsp) | `clangd` |
28| C# | [`csharp-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/csharp-lsp) | `csharp-ls` |
29| Go | [`gopls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gopls-lsp) | `gopls` |
30| Java | [`jdtls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/jdtls-lsp) | `jdtls` |
31| Kotlin | [`kotlin-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/kotlin-lsp) | `kotlin-lsp` |
32| Liquid | [`liquid-lsp`](https://github.com/Shopify/liquid-skills/tree/main/plugins/liquid-lsp) | `shopify`, from the Shopify CLI |
33| Lua | [`lua-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/lua-lsp) | `lua-language-server` |
34| PHP | [`php-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/php-lsp) | `intelephense` |
35| Python | [`pyright-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pyright-lsp) | `pyright-langserver` |
36| Ruby | [`ruby-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ruby-lsp) | `ruby-lsp` |
37| Rust | [`rust-analyzer-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/rust-analyzer-lsp) | `rust-analyzer` |
38| Swift | [`swift-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/swift-lsp) | `sourcekit-lsp` |
39| TypeScript and JavaScript | [`typescript-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/typescript-lsp) | `typescript-language-server` |
4240 
43 To find the command that installs the binary, follow the plugin's link in the table to its README. For TypeScript, that command is `npm install -g typescript-language-server typescript`.
41Anthropic maintains every plugin in the table except `liquid-lsp`, which Shopify maintains and the official marketplace lists.
4442 
45 After you install the binary, confirm it's on the `PATH` of the shell you start `claude` from, for example with `which typescript-language-server`, or `Get-Command typescript-language-server` in PowerShell.
46 </Step>
43To find the command that installs the binary, follow the plugin's link in the table to its README. For TypeScript, that command is `npm install -g typescript-language-server typescript`.
4744 
48 <Step title="Install the plugin">
49 In the VS Code extension or the desktop app, follow [Install a plugin](/docs/en/plugins/install#install-a-plugin) instead of this step. In a terminal, start Claude Code by running `claude`, then enter this at its prompt, replacing `typescript-lsp` with the plugin the step 1 table lists for your language:
45After you install the binary, confirm it's on the `PATH` of the shell you start `claude` from, for example with `which typescript-language-server`, or `Get-Command typescript-language-server` in PowerShell.
5046 
51 ```
52 /plugin install typescript-lsp@claude-plugins-official
53 ```
47**2. Install the plugin**
5448 
55 A confirmation message says whether the plugin is active now or needs `/reload-plugins`. If the install fails with `Marketplace "claude-plugins-official" not found`, see the [troubleshooting entry for that error](/docs/en/plugins/troubleshooting#marketplace-claude-plugins-official-not-found). To control where the plugin is installed, or to run the install from your shell instead of inside Claude Code, see [Install plugins](/docs/en/plugins/install).
56 </Step>
49In the VS Code extension or the desktop app, follow [Install a plugin](/docs/en/plugins/install#install-a-plugin) instead of this step. In a terminal, start Claude Code by running `claude`, then enter this at its prompt, replacing `typescript-lsp` with the plugin the step 1 table lists for your language:
5750 
58 <Step title="Confirm the server starts">
59 The language server starts the first time Claude edits a file with one of the plugin's extensions. To see it work, ask Claude to introduce a type error in a file of that language and then fix it. Then check the conversation for a diagnostics line:
51```
52/plugin install typescript-lsp@claude-plugins-official
53```
6054 
61 * **A diagnostics line appears**: `Found N new diagnostic issues in M files (ctrl+o to expand)` under the edit that introduced the error means the server started.
62 * **No diagnostics line appears**: run `/plugin` and open the **Errors** tab. A row reading `Executable not found in $PATH: "<binary>"` names the binary to install. If the tab has no such row, see [Troubleshoot code intelligence](#troubleshoot-code-intelligence).
55A confirmation message says whether the plugin is active now or needs `/reload-plugins`. If the install fails with `Marketplace "claude-plugins-official" not found`, see the [troubleshooting entry for that error](/docs/en/plugins/troubleshooting#marketplace-claude-plugins-official-not-found). To control where the plugin is installed, or to run the install from your shell instead of inside Claude Code, see [Install plugins](/docs/en/plugins/install).
6356 
64 After you install a missing binary, Claude Code tries again the next time Claude edits a matching file. If you installed the binary into a directory that isn't on the `PATH` of the shell you started `claude` from, start a new session from a shell where it is.
65 </Step>
66</Steps>
57**3. Confirm the server starts**
58 
59The language server starts the first time Claude edits a file with one of the plugin's extensions. To see it work, ask Claude to introduce a type error in a file of that language and then fix it. Then check the conversation for a diagnostics line:
60 
61* **A diagnostics line appears**: `Found N new diagnostic issues in M files (ctrl+o to expand)` under the edit that introduced the error means the server started.
62* **No diagnostics line appears**: run `/plugin` and open the **Errors** tab. A row reading `Executable not found in $PATH: "<binary>"` names the binary to install. If the tab has no such row, see [Troubleshoot code intelligence](#troubleshoot-code-intelligence).
63 
64After you install a missing binary, Claude Code tries again the next time Claude edits a matching file. If you installed the binary into a directory that isn't on the `PATH` of the shell you started `claude` from, start a new session from a shell where it is.
6765 
6866## See what Claude gains
6967 

plugins/components Changed · +370 / -789 lines

## Ask the user for configuration values ## Reference plugin paths and store data

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 2
22 
33> Add skills, hooks, MCP servers, and every other component type to a Claude Code plugin, with an example that validates for each.
44 
5export const Piece = ({id, children}) => <div className="pe-piece" data-piece={id}>{children}</div>;
6 
7export const PluginExplorer = ({children}) => {
8 const PIECES = [{
9 id: 'manifest',
10 name: 'Manifest',
11 path: '.claude-plugin/plugin.json',
12 lines: [{
13 depth: 0,
14 kind: 'folder',
15 text: '.claude-plugin/'
16 }, {
17 depth: 1,
18 kind: 'file',
19 text: 'plugin.json'
20 }],
21 href: '/en/plugins/manifest-reference#manifest-file',
22 linkText: 'Go to the manifest reference'
23 }, {
24 id: 'skills',
25 name: 'Skills',
26 path: 'skills/review/SKILL.md',
27 lines: [{
28 depth: 0,
29 kind: 'folder',
30 text: 'skills/'
31 }, {
32 depth: 1,
33 kind: 'folder',
34 text: 'review/'
35 }, {
36 depth: 2,
37 kind: 'file',
38 text: 'SKILL.md'
39 }],
40 href: '/en/plugins/components#skills',
41 linkText: 'Go to the Skills section'
42 }, {
43 id: 'commands',
44 name: 'Commands',
45 path: 'commands/about.md',
46 lines: [{
47 depth: 0,
48 kind: 'folder',
49 text: 'commands/'
50 }, {
51 depth: 1,
52 kind: 'file',
53 text: 'about.md'
54 }],
55 href: '/en/plugins/components#commands',
56 linkText: 'Go to the Commands section'
57 }, {
58 id: 'agents',
59 name: 'Agents',
60 path: 'agents/security-reviewer.md',
61 lines: [{
62 depth: 0,
63 kind: 'folder',
64 text: 'agents/'
65 }, {
66 depth: 1,
67 kind: 'file',
68 text: 'security-reviewer.md'
69 }],
70 href: '/en/plugins/components#agents',
71 linkText: 'Go to the Agents section'
72 }, {
73 id: 'hooks',
74 name: 'Hooks',
75 path: 'hooks/hooks.json',
76 lines: [{
77 depth: 0,
78 kind: 'folder',
79 text: 'hooks/'
80 }, {
81 depth: 1,
82 kind: 'file',
83 text: 'hooks.json'
84 }],
85 href: '/en/plugins/components#hooks',
86 linkText: 'Go to the Hooks section'
87 }, {
88 id: 'monitors',
89 name: 'Monitors',
90 path: 'monitors/monitors.json',
91 lines: [{
92 depth: 0,
93 kind: 'folder',
94 text: 'monitors/'
95 }, {
96 depth: 1,
97 kind: 'file',
98 text: 'monitors.json'
99 }],
100 href: '/en/plugins/components#monitors',
101 linkText: 'Go to the Monitors section'
102 }, {
103 id: 'output-styles',
104 name: 'Output styles',
105 path: 'output-styles/terse.md',
106 lines: [{
107 depth: 0,
108 kind: 'folder',
109 text: 'output-styles/'
110 }, {
111 depth: 1,
112 kind: 'file',
113 text: 'terse.md'
114 }],
115 href: '/en/plugins/components#themes-and-output-styles',
116 linkText: 'Go to the Themes and output styles section'
117 }, {
118 id: 'themes',
119 name: 'Themes',
120 path: 'themes/dracula.json',
121 lines: [{
122 depth: 0,
123 kind: 'folder',
124 text: 'themes/'
125 }, {
126 depth: 1,
127 kind: 'file',
128 text: 'dracula.json'
129 }],
130 href: '/en/plugins/components#themes-and-output-styles',
131 linkText: 'Go to the Themes and output styles section'
132 }, {
133 id: 'workflows',
134 name: 'Workflows',
135 path: 'workflows/audit-routes.js',
136 lines: [{
137 depth: 0,
138 kind: 'folder',
139 text: 'workflows/'
140 }, {
141 depth: 1,
142 kind: 'file',
143 text: 'audit-routes.js'
144 }],
145 href: '/en/workflows#distribute-a-workflow-in-a-plugin',
146 linkText: 'Go to Distribute a workflow in a plugin'
147 }, {
148 id: 'bin',
149 name: 'Executables',
150 path: 'bin/hello-plugin',
151 lines: [{
152 depth: 0,
153 kind: 'folder',
154 text: 'bin/'
155 }, {
156 depth: 1,
157 kind: 'file',
158 text: 'hello-plugin'
159 }],
160 href: '/en/plugins/components#executables',
161 linkText: 'Go to the Executables section'
162 }, {
163 id: 'scripts',
164 name: 'Scripts',
165 path: 'scripts/format.sh',
166 lines: [{
167 depth: 0,
168 kind: 'folder',
169 text: 'scripts/'
170 }, {
171 depth: 1,
172 kind: 'file',
173 text: 'format.sh'
174 }],
175 href: '/en/plugins/components#hooks',
176 linkText: 'Go to the Hooks section'
177 }, {
178 id: 'settings',
179 name: 'Default settings',
180 path: 'settings.json',
181 lines: [{
182 depth: 0,
183 kind: 'file',
184 text: 'settings.json'
185 }],
186 href: '/en/plugins/components#default-settings',
187 linkText: 'Go to the Default settings section'
188 }, {
189 id: 'mcp',
190 name: 'MCP servers',
191 path: '.mcp.json',
192 lines: [{
193 depth: 0,
194 kind: 'file',
195 text: '.mcp.json'
196 }],
197 href: '/en/plugins/components#mcp-servers',
198 linkText: 'Go to the MCP servers section'
199 }, {
200 id: 'lsp',
201 name: 'LSP servers',
202 path: '.lsp.json',
203 lines: [{
204 depth: 0,
205 kind: 'file',
206 text: '.lsp.json'
207 }],
208 href: '/en/plugins/components#lsp-servers',
209 linkText: 'Go to the LSP servers section'
210 }];
211 const [selectedId, setSelectedId] = useState('manifest');
212 const [isFullscreen, setIsFullscreen] = useState(false);
213 const rootRef = useRef(null);
214 useEffect(() => {
215 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
216 document.addEventListener('fullscreenchange', onFsChange);
217 return () => document.removeEventListener('fullscreenchange', onFsChange);
218 }, []);
219 const toggleFullscreen = () => {
220 if (!rootRef.current) return;
221 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});
222 };
223 const selected = PIECES.find(p => p.id === selectedId) || PIECES[0];
224 const onTreeKeyDown = e => {
225 const keys = ['ArrowDown', 'ArrowUp', 'Home', 'End'];
226 if (keys.indexOf(e.key) === -1) return;
227 const i = PIECES.findIndex(p => p.id === selectedId);
228 let next = i;
229 if (e.key === 'ArrowDown') next = Math.min(PIECES.length - 1, i + 1);
230 if (e.key === 'ArrowUp') next = Math.max(0, i - 1);
231 if (e.key === 'Home') next = 0;
232 if (e.key === 'End') next = PIECES.length - 1;
233 e.preventDefault();
234 if (next === i) return;
235 const id = PIECES[next].id;
236 setSelectedId(id);
237 const el = document.getElementById('pe-node-' + id);
238 if (el) el.focus();
239 };
240 const FolderIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
241 <path d="M1.5 4.5a1 1 0 0 1 1-1h3.2l1.3 1.5h6a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1h-10.5a1 1 0 0 1-1-1z" />
242 </svg>;
243 const FileIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
244 <path d="M4 1.5h5.5L13 5v9.5H4z" />
245 <path d="M9.5 1.5V5H13" />
246 </svg>;
247 return <div ref={rootRef} className={isFullscreen ? 'pe-root pe-fullscreen not-prose' : 'pe-root not-prose'} data-selected={selected.id}>
248 <style>{`
249 .pe-root {
250 --pe-mono: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
251 --pe-accent: #D97757;
252 --pe-accent-text: #A8502F;
253 --pe-accent-bg: rgba(217,119,87,0.10);
254 --pe-bg: #FFFFFF;
255 --pe-surface: #FAFAF7;
256 --pe-hover: #F0EEE6;
257 --pe-border: #E8E6DC;
258 --pe-text: #141413;
259 --pe-text-2: #3D3D3A;
260 --pe-text-3: #5E5D59;
261 font-family: inherit;
262 background: var(--pe-bg);
263 color: var(--pe-text);
264 border: 1px solid var(--pe-border);
265 border-radius: 12px;
266 margin: 1.5rem 0;
267 overflow: hidden;
268 box-sizing: border-box;
269 }
270 .dark .pe-root {
271 --pe-accent-text: #EBA98F;
272 --pe-accent-bg: rgba(217,119,87,0.18);
273 --pe-bg: #1A1918;
274 --pe-surface: #232221;
275 --pe-hover: #2E2D2B;
276 --pe-border: #3A3936;
277 --pe-text: #F1EFE9;
278 --pe-text-2: #D6D4CA;
279 --pe-text-3: #B8B5AD;
280 }
281 .pe-root *, .pe-root *::before, .pe-root *::after { box-sizing: border-box; }
282 .pe-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 24px 16px; border-bottom: 1px solid var(--pe-border); }
283 .pe-head-text { flex: 1; min-width: 0; }
284 .pe-fs-btn { flex-shrink: 0; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--pe-border); border-radius: 6px; background: var(--pe-surface); color: var(--pe-text-2); font-size: 15px; line-height: 1; cursor: pointer; }
285 .pe-fs-btn:hover { background: var(--pe-hover); }
286 .pe-fs-btn:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: 2px; }
287 .pe-fullscreen { border-radius: 0; height: 100vh; display: flex; flex-direction: column; overflow: auto; }
288 .pe-fullscreen .pe-body { flex: 1; }
289 .pe-title { font-size: 19px; font-weight: 600; line-height: 1.3; color: var(--pe-text); margin: 0; }
290 .pe-sub { font-size: 15px; line-height: 1.5; color: var(--pe-text-3); margin: 4px 0 0; }
291 .pe-sub code { font-family: var(--pe-mono); font-size: 0.88em; padding: 1px 5px; border-radius: 4px; background: var(--pe-surface); border: 1px solid var(--pe-border); }
292 .pe-body { display: flex; align-items: stretch; }
293 .pe-tree-pane { width: 270px; flex-shrink: 0; background: var(--pe-surface); border-right: 1px solid var(--pe-border); padding: 16px 0 12px; }
294 .pe-panel { flex: 1; min-width: 0; padding: 16px 24px 24px; }
295 .pe-caption { font-size: 13px; font-weight: 600; color: var(--pe-text-3); margin: 0 0 10px; }
296 .pe-tree-pane .pe-caption { padding: 0 16px; }
297 .pe-rootline { display: flex; align-items: center; gap: 7px; padding: 3px 16px; font-family: var(--pe-mono); font-size: 13.5px; color: var(--pe-text-3); }
298 .pe-node {
299 display: block; width: 100%; margin: 0; padding: 3px 16px 3px 30px; text-align: left; cursor: pointer;
300 background: transparent; color: var(--pe-text-2);
301 border: none; border-left: 3px solid transparent;
302 font-family: var(--pe-mono); font-size: 13.5px; line-height: 1.4;
303 }
304 .pe-node:hover { background: var(--pe-hover); }
305 .pe-node:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: -2px; }
306 .pe-node[aria-pressed="true"] { background: var(--pe-accent-bg); border-left-color: var(--pe-accent); color: var(--pe-accent-text); font-weight: 600; }
307 .pe-line { display: flex; align-items: center; gap: 7px; padding: 2px 0; }
308 .pe-line-tree { flex-wrap: wrap; }
309 .pe-line-tree .pe-req { flex-basis: 100%; margin: 2px 0 0 22px; white-space: normal; width: fit-content; max-width: calc(100% - 22px); }
310 .pe-line span { overflow-wrap: anywhere; }
311 .pe-piece { display: none; font-size: 16px; line-height: 1.6; color: var(--pe-text-2); }
312 .pe-root[data-selected="manifest"] .pe-piece[data-piece="manifest"],
313 .pe-root[data-selected="skills"] .pe-piece[data-piece="skills"],
314 .pe-root[data-selected="commands"] .pe-piece[data-piece="commands"],
315 .pe-root[data-selected="agents"] .pe-piece[data-piece="agents"],
316 .pe-root[data-selected="hooks"] .pe-piece[data-piece="hooks"],
317 .pe-root[data-selected="monitors"] .pe-piece[data-piece="monitors"],
318 .pe-root[data-selected="output-styles"] .pe-piece[data-piece="output-styles"],
319 .pe-root[data-selected="themes"] .pe-piece[data-piece="themes"],
320 .pe-root[data-selected="workflows"] .pe-piece[data-piece="workflows"],
321 .pe-root[data-selected="bin"] .pe-piece[data-piece="bin"],
322 .pe-root[data-selected="scripts"] .pe-piece[data-piece="scripts"],
323 .pe-root[data-selected="settings"] .pe-piece[data-piece="settings"],
324 .pe-root[data-selected="mcp"] .pe-piece[data-piece="mcp"],
325 .pe-root[data-selected="lsp"] .pe-piece[data-piece="lsp"] { display: block; }
326 .pe-piece p { margin: 0 0 10px; }
327 .pe-piece p:last-child { margin-bottom: 0; }
328 .pe-piece code { font-family: var(--pe-mono); font-size: 0.88em; padding: 1px 5px; border-radius: 4px; background: var(--pe-surface); border: 1px solid var(--pe-border); }
329 .pe-piece .code-block { margin: 12px 0 0; }
330 .pe-piece pre code { padding: 0; border: none; background: none; }
331 .pe-piece a { color: var(--pe-accent-text); }
332 .pe-line-compact { display: none; }
333 .pe-icon { flex-shrink: 0; }
334 .pe-req { margin-left: 8px; padding: 0 6px; border-radius: 999px; font-size: 11px; line-height: 18px; letter-spacing: .02em; color: var(--pe-accent-text); border: 1px solid var(--pe-border); background: var(--pe-surface); white-space: nowrap; font-weight: 500; vertical-align: middle; }
335 .pe-name { font-size: 22px; font-weight: 600; line-height: 1.25; letter-spacing: -0.2px; color: var(--pe-text); margin: 0; }
336 .pe-path { font-family: var(--pe-mono); font-size: 13.5px; color: var(--pe-accent-text); margin: 4px 0 0; overflow-wrap: anywhere; }
337 .pe-block { margin: 20px 0 0; }
338 .pe-link {
339 display: inline-block; margin: 24px 0 0; padding: 8px 14px; border-radius: 8px;
340 font-size: 14.5px; font-weight: 600; text-decoration: none;
341 color: var(--pe-accent-text); background: var(--pe-accent-bg); border: 1px solid var(--pe-accent);
342 }
343 .pe-link:hover { filter: brightness(0.97); }
344 .pe-link:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: 2px; }
345 @media (max-width: 700px) {
346 .pe-head { padding: 16px 16px 14px; }
347 .pe-body { flex-direction: column; }
348 .pe-tree-pane { width: 100%; border-right: none; border-bottom: 1px solid var(--pe-border); }
349 .pe-line-tree { display: none; }
350 .pe-line-compact { display: flex; }
351 .pe-panel { padding: 16px 16px 20px; }
352 }
353 `}</style>
354 
355 <div className="pe-head">
356 <div className="pe-head-text">
357 <div className="pe-title">What goes in a plugin</div>
358 <div className="pe-sub">This example plugin, <code>my-plugin</code>, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.</div>
359 </div>
360 <button type="button" className="pe-fs-btn" onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
361 {isFullscreen ? '⤡' : '⛶'}
362 </button>
363 </div>
364 
365 <div className="pe-body">
366 <div className="pe-tree-pane">
367 <div className="pe-caption" id="pe-tree-caption">Plugin directory</div>
368 <div role="group" aria-labelledby="pe-tree-caption" onKeyDown={onTreeKeyDown}>
369 <div className="pe-rootline"><FolderIcon /><span>my-plugin/</span></div>
370 {PIECES.map(p => <button key={p.id} id={'pe-node-' + p.id} type="button" className="pe-node" aria-pressed={p.id === selected.id} aria-label={p.name + ', ' + p.path} onClick={() => setSelectedId(p.id)}>
371 {p.lines.map((line, i) => <span key={i} className="pe-line pe-line-tree" style={{
372 paddingLeft: line.depth * 18 + 'px'
373 }}>
374 {line.kind === 'folder' ? <FolderIcon /> : <FileIcon />}
375 <span>{line.text}</span>
376 {p.required && i === p.lines.length - 1 ? <span className="pe-req">{p.required}</span> : null}
377 </span>)}
378 <span className="pe-line pe-line-compact">
379 <FileIcon />
380 <span>{p.path}</span>
381 {p.required ? <span className="pe-req">{p.required}</span> : null}
382 </span>
383 </button>)}
384 </div>
385 </div>
386 
387 <div className="pe-panel" role="region" aria-labelledby="pe-panel-caption" aria-live="polite" aria-atomic="true">
388 <div className="pe-caption" id="pe-panel-caption">Selected piece</div>
389 <div className="pe-name">{selected.name}{selected.required ? <span className="pe-req">{selected.required}</span> : null}</div>
390 <div className="pe-path">{selected.path}</div>
391 
392 <div className="pe-block">{children}</div>
393 
394 <a className="pe-link" href={selected.href}>{selected.linkText}</a>
395 </div>
396 </div>
397 </div>;
398};
399 
4005A Claude Code plugin is built from components, such as skills, agents, hooks, and MCP servers. Each component has a default folder in the plugin, an optional manifest key in `.claude-plugin/plugin.json` that replaces or adds to that folder, and a name the user sees. For each key's full field table, see the [manifest reference](/docs/en/plugins/manifest-reference#fields).
4016 
4027Use this page to add a component to a plugin that already loads.
4038 
4049After you add a component, run `/reload-plugins` in a running session or start a new one so Claude Code loads it. To check the component's file before loading it, run [`claude plugin validate .`](/docs/en/plugins/cli-reference#plugin-validate) in your shell from the plugin directory.
40510 
406<Note>
407 These cases are covered on other pages:
408 
409 * **Building your first plugin**: start with [Create a plugin](/docs/en/plugins/create)
410 * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
411 * **Your plugin's users are on claude.ai or in Cowork**: a different set of components loads there. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
412</Note>
11> [!NOTE]
12>
13> These cases are covered on other pages:
14>
15> * **Building your first plugin**: start with [Create a plugin](/docs/en/plugins/create)
16> * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
17> * **Your plugin's users are on claude.ai or in Cowork**: a different set of components loads there. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
41318 
41419## Explore the plugin directory
41520 
from line 32
42732 
42833Each file is the smallest valid example of its format, there to show the shape rather than to be useful: a real skill or agent carries full instructions and often supporting files, and a real hook or monitor does real work. The sections after the explorer use the same files as their examples and link to fuller ones. Select a file or folder to read what it's for, see what goes in it, and find the section that covers it.
42934 
430<PluginExplorer>
431 <Piece id="manifest">
432 The [manifest](/docs/en/plugins/manifest-reference) is the `plugin.json` file in a plugin's `.claude-plugin/` directory. It contains the plugin's metadata and the `userConfig` values that Claude Code prompts the user for. Claude Code loads a plugin without one. Inside the file, only `name` is required. In this one, `description` is the text users see for the plugin in `/plugin`, and `version` keeps users on that version until you change it:
433 
434 ```json theme={null}
435 {
436 "name": "my-plugin",
437 "version": "1.0.0",
438 "description": "Review, formatting, and database tools for this team"
439 }
440 ```
441 </Piece>
442 
443 <Piece id="skills">
444 A [skill](/docs/en/skills) is a `SKILL.md` file. Save each skill in its own directory under `skills/`. Claude reads every skill's `description`, and when what the user asks for matches it, such as asking Claude to review a pull request here, Claude loads the skill's instructions and follows them. The user can also run it directly as `/my-plugin:review`:
445 
446 ```markdown theme={null}
447 ---
448 description: Reviews a pull request for style and test coverage. Use when asked to review code.
449 ---
450 
451 Review the changed files. Report style problems first, then missing tests.
452 ```
453 </Piece>
454 
455 <Piece id="commands">
456 A command is a single Markdown file the user runs by name. Commands are the older format: a skill runs by name the same way and can also carry supporting files in its own directory, so write new ones as skills and keep `commands/` for files you already have. This file becomes `/my-plugin:about` and takes the same frontmatter as a skill:
457 
458 ```markdown theme={null}
459 ---
460 description: Summarize the repository
461 ---
462 
463 Summarize what this repository does in three sentences.
464 ```
465 </Piece>
466 
467 <Piece id="agents">
468 A [subagent](/docs/en/sub-agents) is a separate assistant, with its own instructions and its own context window, that Claude can delegate a task to and get a result back from. Each Markdown file under `agents/` defines one: the frontmatter names it and says when to use it, and the body is its system prompt. This one is named `my-plugin:security-reviewer`, and the user can invoke it with `@agent-my-plugin:security-reviewer`:
469 
470 ```markdown theme={null}
471 ---
472 name: security-reviewer
473 description: Reviews code changes for security issues. Use after edits to authentication or input handling.
474 model: sonnet
475 ---
476 
477 You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
478 ```
479 </Piece>
480 
481 <Piece id="hooks">
482 A [hook](/docs/en/hooks-guide) runs something automatically at a point in Claude Code's lifecycle, such as after every file edit: a shell command, an HTTP request, an MCP tool call, a prompt to a model, or a subagent. Save the plugin's hooks in `hooks/hooks.json` at the plugin root. This one runs the plugin's `scripts/format.sh` after Claude writes or edits a file:
483 
484 ```json theme={null}
485 {
486 "hooks": {
487 "PostToolUse": [
488 {
489 "matcher": "Write|Edit",
490 "hooks": [
491 {
492 "type": "command",
493 "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
494 }
495 ]
496 }
497 ]
498 }
499 }
500 ```
501 </Piece>
502 
503 <Piece id="monitors">
504 A monitor is a shell command that Claude Code starts in the background when the session starts and keeps running until it ends. What it prints reaches Claude as notifications. A `when` field can instead start it the first time a named skill runs. This one tails an error log:
505 
506 ```json theme={null}
507 [
508 {
509 "name": "error-log",
510 "command": "tail -F ./logs/error.log",
511 "description": "Application error log"
512 }
513 ]
514 ```
515 </Piece>
516 
517 <Piece id="output-styles">
518 A plugin can include [output styles](/docs/en/output-styles), which change how Claude formats and phrases its replies. Save each output style as `output-styles/<name>.md`. This one appears in `/output-style` as `my-plugin:terse`:
519 
520 ```markdown theme={null}
521 ---
522 name: terse
523 description: Answer in as few words as possible
524 keep-coding-instructions: true
525 ---
526 
527 Keep every reply short. Skip preambles and summaries.
528 ```
529 </Piece>
530 
531 <Piece id="themes">
532 A plugin can include [color themes](/docs/en/terminal-config#create-a-custom-theme) for the Claude Code interface. Save each theme as `themes/<slug>.json`. This one appears in `/theme` as `Dracula`, marked as from `my-plugin`:
533 
534 ```json theme={null}
535 {
536 "name": "Dracula",
537 "base": "dark",
538 "overrides": {
539 "claude": "#bd93f9",
540 "error": "#ff5555"
541 }
542 }
543 ```
544 </Piece>
545 
546 <Piece id="workflows">
547 The `workflows/` folder holds [workflow](/docs/en/workflows) `.js` files: a `meta` block, then a script body that orchestrates several subagents. This one runs as `/my-plugin:audit-routes`:
548 
549 ```javascript theme={null}
550 export const meta = {
551 name: 'audit-routes',
552 description: 'Audit every route handler for missing auth checks',
553 }
554 
555 const found = await agent('List every .ts file under src/routes/.', {
556 schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
557 })
558 
559 const audits = await pipeline(found.files, file =>
560 agent(`Audit ${file} for missing authentication checks.`, { label: file }),
561 )
562 
563 return audits.filter(Boolean)
564 ```
565 </Piece>
566 
567 <Piece id="bin">
568 `bin/` is how a plugin ships a command-line tool. While the plugin is enabled, Claude Code puts this folder on the `PATH` of the shell it runs commands in, so Claude, or a skill's instructions, can run the tool by name without the user installing anything. With this [executable](#executables) in place, `hello-plugin` is a command Claude can run:
569 
570 ```bash theme={null}
571 #!/bin/bash
572 echo "hello from my-plugin"
573 ```
574 </Piece>
575 
576 <Piece id="scripts">
577 The hook in `hooks/hooks.json` runs a script, and this folder is where the example keeps it. The name `scripts/` is a convention, not something Claude Code looks for: the hook points at the file by its path, `${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`. A formatter script might look like this:
578 
579 ```bash theme={null}
580 #!/bin/bash
581 npx prettier --write .
582 ```
583 </Piece>
584 
585 <Piece id="settings">
586 A `settings.json` at the plugin root holds [settings](/docs/en/settings-reference) that apply while the plugin is enabled, so a plugin can change how the session behaves and not only add components. Only two keys take effect from a plugin, [`agent`](/docs/en/settings-reference#agent) and [`subagentStatusLine`](/docs/en/settings-reference#subagentstatusline); every other key is dropped. See [Default settings](#default-settings).
587 
588 This one sets `agent`, which runs the session's main thread as the plugin's own `security-reviewer` agent, so that agent's system prompt, tool restrictions, and model apply to the whole session:
589 
590 ```json theme={null}
591 {
592 "agent": "security-reviewer"
593 }
594 ```
595 </Piece>
596 
597 <Piece id="mcp">
598 An [MCP server](/docs/en/mcp) gives Claude tools from an external system. Declare it in `.mcp.json` at the plugin root. This one starts a local server from a script inside the plugin, and appears in `/mcp` as `plugin:my-plugin:db`:
599 
600 ```json theme={null}
601 {
602 "mcpServers": {
603 "db": {
604 "command": "node",
605 "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
606 }
607 }
608 }
609 ```
610 </Piece>
611 
612 <Piece id="lsp">
613 An LSP server gives Claude [diagnostics and code navigation](/docs/en/plugins/code-intelligence) for a language. Declare the server in `.lsp.json` at the plugin root. This one connects the Go language server for `.go` files:
614 
615 ```json theme={null}
616 {
617 "gopls": {
618 "command": "gopls",
619 "args": ["serve"],
620 "extensionToLanguage": {
621 ".go": "go"
622 }
623 }
624 }
625 ```
626 </Piece>
627</PluginExplorer>
628 
629## Add each kind of component
630 
631Each section below covers one kind of component: where its files go in the plugin, an example that validates, what the user sees once the plugin loads, and the manifest key that changes the default location. Add the ones your plugin needs; none is required.
632 
633### Skills
634 
635A [skill](/docs/en/skills) is a `SKILL.md` file that Claude can load when its description matches the task. The user can also run it as a command. Save each skill in its own directory under `skills/`:
636 
637```text theme={null}
35What goes in a plugin
36 
37This example plugin, `my-plugin`, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.
38 
39Plugin directory
40 
63841my-plugin/
639├── .claude-plugin/
640│ └── plugin.json
641└── skills/
642 └── review/
643 └── SKILL.md
644```
645 
646Give the `SKILL.md` a `description` so Claude knows when to use it:
647 
648```markdown skills/review/SKILL.md theme={null}
42 
43Selected piece
44 
45The [manifest](/docs/en/plugins/manifest-reference) is the `plugin.json` file in a plugin's `.claude-plugin/` directory. It contains the plugin's metadata and the `userConfig` values that Claude Code prompts the user for. Claude Code loads a plugin without one. Inside the file, only `name` is required. In this one, `description` is the text users see for the plugin in `/plugin`, and `version` keeps users on that version until you change it:
46 
47```json theme={null}
48{
49 "name": "my-plugin",
50 "version": "1.0.0",
51 "description": "Review, formatting, and database tools for this team"
52}
53```
54 
55A [skill](/docs/en/skills) is a `SKILL.md` file. Save each skill in its own directory under `skills/`. Claude reads every skill's `description`, and when what the user asks for matches it, such as asking Claude to review a pull request here, Claude loads the skill's instructions and follows them. The user can also run it directly as `/my-plugin:review`:
56 
57```markdown theme={null}
64958---
65059description: Reviews a pull request for style and test coverage. Use when asked to review code.
65160---
from line 62
65362Review the changed files. Report style problems first, then missing tests.
65463```
65564 
656After you load the plugin, `/my-plugin:review` runs the skill. The command name and who can invoke it follow these rules:
657 
658* **Command name**: `/<plugin>:<directory>`, so `skills/review/SKILL.md` in `my-plugin` is `/my-plugin:review`. If you set `name` in the frontmatter, it replaces the last segment and the plugin prefix stays. See [how a skill gets its command name](/docs/en/skills#how-a-skill-gets-its-command-name)
659* **Who invokes it**: Claude, the user, or both, controlled by frontmatter. See [Control who invokes a skill](/docs/en/skills#control-who-invokes-a-skill)
660 
661You can also place skills outside the default `skills/` directory:
662 
663* **Additional directories**: list them in the `skills` manifest key. They add to the default `skills/` scan rather than replacing it, unlike `commands` and `agents`
664* **A single skill at the plugin root**: with no `skills/` directory and no `skills` manifest key, a `SKILL.md` at the plugin root loads as one skill. Set `name` in its frontmatter, because otherwise a marketplace install names the skill after its [cache directory](/docs/en/plugins/loading#find-plugins-on-disk) rather than your plugin
665 
666To include instructions in a plugin, write them as a skill. Claude Code doesn't load a `CLAUDE.md` at the plugin root, and `claude plugin validate` warns `CLAUDE.md at the plugin root is not loaded as project context`.
667 
668If a rule must hold every time, such as [blocking edits to protected files](/docs/en/hooks-guide#block-edits-to-protected-files), add it to the plugin as a [hook](#hooks) rather than a skill. To choose between the two, see the Hook vs Skill tab under [Compare similar features](/docs/en/features-overview#compare-similar-features).
669 
670For frontmatter fields and supporting files, see [Skills](/docs/en/skills).
671 
672### Commands
673 
674A command is a single Markdown file the user runs by name, such as `/my-plugin:about`.
675 
676<Note>
677 Commands are the older format, and [skills](#skills) supersede them for new work. A skill runs by name the same way, and it can also carry supporting files in its directory. Keep `commands/` for files you're moving over from `.claude/commands/`.
678</Note>
679 
680Save a command at `commands/<file>.md` and it becomes `/<plugin>:<file>`. A subdirectory adds a segment, so `commands/db/migrate.md` is `/my-plugin:db:migrate`.
681 
682Command files take the same frontmatter as skills.
683 
684#### Define commands in the manifest
685 
686You only need this if you want to keep command files somewhere other than `commands/`, or to define a short command inside `plugin.json` without a separate Markdown file. Set the `commands` manifest key, and Claude Code reads it instead of scanning `commands/`. The key takes a path, an array of paths, or an object that maps each command name to either a `source` file or inline `content`.
687 
688This manifest defines `/my-plugin:about` inline, with no Markdown file:
689 
690```json .claude-plugin/plugin.json theme={null}
691{
692 "name": "my-plugin",
693 "commands": {
694 "about": {
695 "content": "Summarize what this repository does in three sentences.",
696 "description": "Summarize the repository"
697 }
698 }
699}
700```
701 
702Load the plugin and run `/my-plugin:about` in the session to confirm it loaded.
703 
704For the full key syntax, see [`commands`](/docs/en/plugins/manifest-reference#commands).
705 
706### Agents
707 
708A [subagent](/docs/en/sub-agents) is a separate assistant, with its own instructions and context window, that Claude can delegate a task to. Each Markdown file under `agents/` defines one:
709 
710```markdown agents/security-reviewer.md theme={null}
65A command is a single Markdown file the user runs by name. Commands are the older format: a skill runs by name the same way and can also carry supporting files in its own directory, so write new ones as skills and keep `commands/` for files you already have. This file becomes `/my-plugin:about` and takes the same frontmatter as a skill:
66 
67```markdown theme={null}
68---
69description: Summarize the repository
70---
71 
72Summarize what this repository does in three sentences.
73```
74 
75A [subagent](/docs/en/sub-agents) is a separate assistant, with its own instructions and its own context window, that Claude can delegate a task to and get a result back from. Each Markdown file under `agents/` defines one: the frontmatter names it and says when to use it, and the body is its system prompt. This one is named `my-plugin:security-reviewer`, and the user can invoke it with `@agent-my-plugin:security-reviewer`:
76 
77```markdown theme={null}
71178---
71279name: security-reviewer
71380description: Reviews code changes for security issues. Use after edits to authentication or input handling.
from line 84
71784You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
71885```
71986 
720This agent is named `my-plugin:security-reviewer`, and the user can [invoke it explicitly](/docs/en/sub-agents#invoke-subagents-explicitly) with `@agent-my-plugin:security-reviewer`. The name form is `<plugin>:<name>`, where `<name>` comes from the frontmatter `name` field, or from the file name when that field is missing.
721 
722The `agents` manifest key replaces the `agents/` scan.
723 
724#### Organize agents in subfolders
725 
726You can put plugin agent files in subfolders of `agents/`. Claude Code [loads them recursively](/docs/en/sub-agents#choose-the-subagent-scope) and joins the plugin name, each subfolder name, and the file name with colons to form the agent's scoped name. For example, `agents/review/security.md` in a plugin named `my-plugin` loads as `my-plugin:review:security`. Two settings change that name:
727 
728* Frontmatter `name`: it replaces only the file name, so `name: audit` in `agents/review/security.md` loads as `my-plugin:review:audit`
729* Manifest [`agents`](/docs/en/plugins/manifest-reference#fields) field: a file you list there loads without subfolder names, so `"agents": "./custom/review/security.md"` loads as `my-plugin:security`
730 
731#### Frontmatter fields in plugin agents
732 
733A plugin agent's frontmatter follows these rules:
734 
735* **Supported fields**: `name`, `description`, `model`, `effort`, `maxTurns`, `autoCompactWindow`, `tools`, `disallowedTools`, `skills`, `memory`, `background`, `omitClaudeMd`, `isolation`, `color`, and the `cacheTtl` key of `experimental`. The only valid `isolation` value is `"worktree"`. See [supported frontmatter fields](/docs/en/sub-agents#supported-frontmatter-fields) for what each one does
736* **Ignored fields**: `permissionMode`, `hooks`, `mcpServers`, and `initialPrompt`. An agent file can't add hooks or MCP servers on its own, so add those as plugin [hooks](#hooks) and [MCP servers](#mcp-servers) instead
737* **Frontmatter that doesn't parse**: the agent still loads with every field ignored. It's named after the file, and its description reads `Agent from my-plugin plugin`. Run [`claude plugin validate`](/docs/en/plugins/cli-reference#plugin-validate) in your shell to find these files
738 
739For what each field does and the precedence rules, see [Subagents](/docs/en/sub-agents#supported-frontmatter-fields).
740 
741### Hooks
742 
743A [hook](/docs/en/hooks-guide) runs something automatically at a point in Claude Code's lifecycle, such as after every file edit: a shell command, an HTTP request, an MCP tool call, a prompt to a model, or a subagent. Save the plugin's hooks in `hooks/hooks.json` at the plugin root, under a top-level `"hooks"` key, in the same shape as the `hooks` object in `settings.json`. That lets you copy an existing settings hook in unchanged.
744 
745This hook runs a bundled script after every `Write` or `Edit`:
746 
747```json hooks/hooks.json theme={null}
87A [hook](/docs/en/hooks-guide) runs something automatically at a point in Claude Code's lifecycle, such as after every file edit: a shell command, an HTTP request, an MCP tool call, a prompt to a model, or a subagent. Save the plugin's hooks in `hooks/hooks.json` at the plugin root. This one runs the plugin's `scripts/format.sh` after Claude writes or edits a file:
88 
89```json theme={null}
74890{
74991 "hooks": {
75092 "PostToolUse": [
from line 104
762104}
763105```
764106 
765Save the script at `scripts/format.sh` and make it executable.
766 
767Load the plugin and ask Claude to edit a file. A `PostToolUse` hook that exits 0 shows nothing in the transcript, so confirm it ran with [debug logging](/docs/en/hooks#debug-hooks) or by what the script itself changes.
768 
769Hooks in `hooks/hooks.json` and in the `hooks` manifest key both load. For every event and its payload, see [Hook events](/docs/en/hooks#hook-events).
770 
771When another enabled plugin has the same name, one of the two registers its `hooks/hooks.json` hooks and the other's are left out. See [Hooks when two enabled plugins share a name](/docs/en/plugins/loading#hooks-when-two-enabled-plugins-share-a-name) for which one, and for the note in `/plugin` that tells you.
772 
773To write hooks as JavaScript functions that run inside Claude Code and can draw in its interface, list a module file under a `modules` key in the same `hooks/hooks.json`. A plugin with one is a mod. See [Create a mod](/docs/en/plugins/mods/create).
774 
775#### When plugin hooks fire
776 
777A plugin's hooks don't wait for one of the plugin's skills or commands to be used. Claude Code registers them when a session loads the plugin, and they fire on their events from then on. To limit when a hook runs, narrow its `matcher`.
778 
779If a hook never fires, see [hooks that don't fire](/docs/en/plugins/troubleshooting#failed-to-load-hooks-from-and-hooks-that-dont-fire).
780 
781#### Environment, quoting, and matching MCP tools
782 
783The hook's environment, the quoting of `${CLAUDE_PLUGIN_ROOT}`, and matchers for the plugin's own MCP tools work as follows:
784 
785* **Environment**: every hook process receives `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` in its environment, plus `CLAUDE_PLUGIN_OPTION_<KEY>` for each [user configuration](#user-configuration) value, so your script can read them from there
786* **Quoting**: when `command` has no `args`, it runs through a shell, so wrap the `${CLAUDE_PLUGIN_ROOT}` path in double quotes, as the `hooks/hooks.json` example under [Hooks](#hooks) does, to keep the expanded path one shell word. When you pass `args` instead, each element is passed as one argument with no shell and needs no quoting. See [exec form and shell form](/docs/en/hooks#exec-form-and-shell-form)
787* **Matching the plugin's own MCP tools**: a tool from an [MCP server this plugin declares](#mcp-servers) is named `mcp__plugin_<plugin>_<server>__<tool>`, so write that full name in the matcher. A matcher on the server name alone never fires. See [Match MCP tools](/docs/en/hooks#match-mcp-tools)
788 
789### MCP servers
790 
791An MCP server gives Claude tools from an external system. Declare it in `.mcp.json` at the plugin root, in the same shape as a [project `.mcp.json`](/docs/en/mcp#project-scope). This `.mcp.json` declares one server named `db`:
792 
793```json .mcp.json theme={null}
107A monitor is a shell command that Claude Code starts in the background when the session starts and keeps running until it ends. What it prints reaches Claude as notifications. A `when` field can instead start it the first time a named skill runs. This one tails an error log:
108 
109```json theme={null}
110[
111 {
112 "name": "error-log",
113 "command": "tail -F ./logs/error.log",
114 "description": "Application error log"
115 }
116]
117```
118 
119A plugin can include [output styles](/docs/en/output-styles), which change how Claude formats and phrases its replies. Save each output style as `output-styles/<name>.md`. This one appears in `/output-style` as `my-plugin:terse`:
120 
121```markdown theme={null}
122---
123name: terse
124description: Answer in as few words as possible
125keep-coding-instructions: true
126---
127 
128Keep every reply short. Skip preambles and summaries.
129```
130 
131A plugin can include [color themes](/docs/en/terminal-config#create-a-custom-theme) for the Claude Code interface. Save each theme as `themes/<slug>.json`. This one appears in `/theme` as `Dracula`, marked as from `my-plugin`:
132 
133```json theme={null}
134{
135 "name": "Dracula",
136 "base": "dark",
137 "overrides": {
138 "claude": "#bd93f9",
139 "error": "#ff5555"
140 }
141}
142```
143 
144The `workflows/` folder holds [workflow](/docs/en/workflows) `.js` files: a `meta` block, then a script body that orchestrates several subagents. This one runs as `/my-plugin:audit-routes`:
145 
146```javascript theme={null}
147export const meta = {
148 name: 'audit-routes',
149 description: 'Audit every route handler for missing auth checks',
150}
151 
152const found = await agent('List every .ts file under src/routes/.', {
153 schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
154})
155 
156const audits = await pipeline(found.files, file =>
157 agent(`Audit ${file} for missing authentication checks.`, { label: file }),
158)
159 
160return audits.filter(Boolean)
161```
162 
163`bin/` is how a plugin ships a command-line tool. While the plugin is enabled, Claude Code puts this folder on the `PATH` of the shell it runs commands in, so Claude, or a skill's instructions, can run the tool by name without the user installing anything. With this [executable](#executables) in place, `hello-plugin` is a command Claude can run:
164 
165```bash theme={null}
166#!/bin/bash
167echo "hello from my-plugin"
168```
169 
170The hook in `hooks/hooks.json` runs a script, and this folder is where the example keeps it. The name `scripts/` is a convention, not something Claude Code looks for: the hook points at the file by its path, `${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`. A formatter script might look like this:
171 
172```bash theme={null}
173#!/bin/bash
174npx prettier --write .
175```
176 
177A `settings.json` at the plugin root holds [settings](/docs/en/settings-reference) that apply while the plugin is enabled, so a plugin can change how the session behaves and not only add components. Only two keys take effect from a plugin, [`agent`](/docs/en/settings-reference#agent) and [`subagentStatusLine`](/docs/en/settings-reference#subagentstatusline); every other key is dropped. See [Default settings](#default-settings).
178 
179This one sets `agent`, which runs the session's main thread as the plugin's own `security-reviewer` agent, so that agent's system prompt, tool restrictions, and model apply to the whole session:
180 
181```json theme={null}
182{
183 "agent": "security-reviewer"
184}
185```
186 
187An [MCP server](/docs/en/mcp) gives Claude tools from an external system. Declare it in `.mcp.json` at the plugin root. This one starts a local server from a script inside the plugin, and appears in `/mcp` as `plugin:my-plugin:db`:
188 
189```json theme={null}
794190{
795191 "mcpServers": {
796192 "db": {
from line 197
801197}
802198```
803199 
804You can also omit the `mcpServers` wrapper and put `db` at the top level of the file.
805 
806Load the plugin and run `/mcp` to confirm the server appears as `plugin:my-plugin:db`.
807 
808`claude plugin validate` checks `.mcp.json` and reports a server entry that Claude Code would drop at load time as an error. Requires Claude Code v2.1.281 or later.
809 
810For where a bad entry shows up at load time, see [MCP servers that don't start](/docs/en/plugins/troubleshooting#invalid-mcp-server-config-for-and-mcp-servers-that-dont-start).
811 
812The `mcpServers` manifest key takes an inline server map, a path to a JSON file, or an array of those. When a manifest server has the same name as one in `.mcp.json`, the manifest server replaces it.
813 
814#### Reach users on claude.ai and Cowork
815 
816A local stdio server, such as the `db` server under [MCP servers](#mcp-servers), runs in Claude Code and in a Cowork session that runs on your machine in the Claude Desktop app, but not on claude.ai. To reach users there too, reference a remote server by its `https://` URL, which claude.ai and Cowork offer to the user as a connector, as [Bundle an MCP connector with its skill](https://claude.com/docs/plugins/build#bundle-an-mcp-connector-with-its-skill) shows.
817 
818#### Server names, tool names, and reloads
819 
820The server's names, variable substitution, and reload behavior follow these rules:
821 
822* **Server name**: `plugin:<plugin>:<server>`, so the `db` server in `my-plugin` is `plugin:my-plugin:db` in `/mcp`. Use the same form to name the server in an [`mcp_tool` hook](/docs/en/hooks#mcp-tool-hook-fields)
823* **Tool names**: `mcp__plugin_<plugin>_<server>__<tool>`, so a `query` tool on that `db` server is `mcp__plugin_my-plugin_db__query`. That is the name to use in [permission rules](/docs/en/permissions) and [hook matchers](#hooks)
824* **Substitution**: `${CLAUDE_PLUGIN_ROOT}` and the other [path variables](#path-variables-and-persistent-data) are substituted in `command`, `args`, and `env`. No quoting is needed in `args`, because each element is passed as one argument
825* **Reload**: when the user runs `/reload-plugins` and [the reload applies](/docs/en/plugins/cli-reference#reloads-that-change-mcp-tools), a server whose configuration is unchanged keeps its connection. A server whose configuration changed reconnects, and one you removed disconnects
826 
827#### Include a packaged MCPB server
828 
829The `mcpServers` key also accepts a packaged server as an [MCPB file](https://github.com/modelcontextprotocol/mcpb), whose extension is `.mcpb` or the older `.dxt`. Point the key at the file, as a path inside the plugin or an `https://` URL:
830 
831```json .claude-plugin/plugin.json theme={null}
832{
833 "name": "my-plugin",
834 "mcpServers": "./servers/db.mcpb"
835}
836```
837 
838The server takes its name from the `name` in the bundle's manifest.
839 
840A bundle's own manifest can declare settings the server needs from the user in a `user_config` block. A bundled server with a required setting that has no saved value doesn't start. The `/plugin` **Errors** tab shows `Bundled MCP server "<name>" was not started: it needs configuration`.
841 
842Users supply the values in one of two ways:
843 
844* **In `/plugin`**: select the plugin on the **Installed** tab and choose **Configure**
845* **At install, from the shell**: pass [`--config <server>.<key>=<value>`](/docs/en/plugins/cli-reference#plugin-install) to `claude plugin install`. Requires Claude Code v2.1.285 or later, and works only for a bundle packaged inside the plugin.
846 
847For transports and authentication, see [MCP](/docs/en/mcp#plugin-provided-mcp-servers).
848 
849### LSP servers
850 
851An LSP server gives Claude diagnostics and code navigation for a language. If an [official code intelligence plugin](/docs/en/plugins/code-intelligence) already covers your language, install that instead of writing one. Otherwise declare the server in `.lsp.json` at the plugin root:
852 
853```json .lsp.json theme={null}
200An LSP server gives Claude [diagnostics and code navigation](/docs/en/plugins/code-intelligence) for a language. Declare the server in `.lsp.json` at the plugin root. This one connects the Go language server for `.go` files:
201 
202```json theme={null}
854203{
855204 "gopls": {
856205 "command": "gopls",
from line 211
862211}
863212```
864213 
214## Add each kind of component
215 
216Each section below covers one kind of component: where its files go in the plugin, an example that validates, what the user sees once the plugin loads, and the manifest key that changes the default location. Add the ones your plugin needs; none is required.
217 
218### Skills
219 
220A [skill](/docs/en/skills) is a `SKILL.md` file that Claude can load when its description matches the task. The user can also run it as a command. Save each skill in its own directory under `skills/`:
221 
222```text theme={null}
223my-plugin/
224├── .claude-plugin/
225│ └── plugin.json
226└── skills/
227 └── review/
228 └── SKILL.md
229```
230 
231Give the `SKILL.md` a `description` so Claude knows when to use it:
232 
233```markdown skills/review/SKILL.md theme={null}
234---
235description: Reviews a pull request for style and test coverage. Use when asked to review code.
236---
237 
238Review the changed files. Report style problems first, then missing tests.
239```
240 
241After you load the plugin, `/my-plugin:review` runs the skill. The command name and who can invoke it follow these rules:
242 
243* **Command name**: `/<plugin>:<directory>`, so `skills/review/SKILL.md` in `my-plugin` is `/my-plugin:review`. If you set `name` in the frontmatter, it replaces the last segment and the plugin prefix stays. See [how a skill gets its command name](/docs/en/skills#how-a-skill-gets-its-command-name)
244* **Who invokes it**: Claude, the user, or both, controlled by frontmatter. See [Control who invokes a skill](/docs/en/skills#control-who-invokes-a-skill)
245 
246You can also place skills outside the default `skills/` directory:
247 
248* **Additional directories**: list them in the `skills` manifest key. They add to the default `skills/` scan rather than replacing it, unlike `commands` and `agents`
249* **A single skill at the plugin root**: with no `skills/` directory and no `skills` manifest key, a `SKILL.md` at the plugin root loads as one skill. Set `name` in its frontmatter, because otherwise a marketplace install names the skill after its [cache directory](/docs/en/plugins/loading#find-plugins-on-disk) rather than your plugin
250 
251To include instructions in a plugin, write them as a skill. Claude Code doesn't load a `CLAUDE.md` at the plugin root, and `claude plugin validate` warns `CLAUDE.md at the plugin root is not loaded as project context`.
252 
253If a rule must hold every time, such as [blocking edits to protected files](/docs/en/hooks-guide#block-edits-to-protected-files), add it to the plugin as a [hook](#hooks) rather than a skill. To choose between the two, see the Hook vs Skill tab under [Compare similar features](/docs/en/features-overview#compare-similar-features).
254 
255For frontmatter fields and supporting files, see [Skills](/docs/en/skills).
256 
257### Commands
258 
259A command is a single Markdown file the user runs by name, such as `/my-plugin:about`.
260 
261> [!NOTE]
262>
263> Commands are the older format, and [skills](#skills) supersede them for new work. A skill runs by name the same way, and it can also carry supporting files in its directory. Keep `commands/` for files you're moving over from `.claude/commands/`.
264 
265Save a command at `commands/<file>.md` and it becomes `/<plugin>:<file>`. A subdirectory adds a segment, so `commands/db/migrate.md` is `/my-plugin:db:migrate`.
266 
267Command files take the same frontmatter as skills.
268 
269#### Define commands in the manifest
270 
271You only need this if you want to keep command files somewhere other than `commands/`, or to define a short command inside `plugin.json` without a separate Markdown file. Set the `commands` manifest key, and Claude Code reads it instead of scanning `commands/`. The key takes a path, an array of paths, or an object that maps each command name to either a `source` file or inline `content`.
272 
273This manifest defines `/my-plugin:about` inline, with no Markdown file:
274 
275```json .claude-plugin/plugin.json theme={null}
276{
277 "name": "my-plugin",
278 "commands": {
279 "about": {
280 "content": "Summarize what this repository does in three sentences.",
281 "description": "Summarize the repository"
282 }
283 }
284}
285```
286 
287Load the plugin and run `/my-plugin:about` in the session to confirm it loaded.
288 
289For the full key syntax, see [`commands`](/docs/en/plugins/manifest-reference#commands).
290 
291### Agents
292 
293A [subagent](/docs/en/sub-agents) is a separate assistant, with its own instructions and context window, that Claude can delegate a task to. Each Markdown file under `agents/` defines one:
294 
295```markdown agents/security-reviewer.md theme={null}
296---
297name: security-reviewer
298description: Reviews code changes for security issues. Use after edits to authentication or input handling.
299model: sonnet
300---
301 
302You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
303```
304 
305This agent is named `my-plugin:security-reviewer`, and the user can [invoke it explicitly](/docs/en/sub-agents#invoke-subagents-explicitly) with `@agent-my-plugin:security-reviewer`. The name form is `<plugin>:<name>`, where `<name>` comes from the frontmatter `name` field, or from the file name when that field is missing.
306 
307The `agents` manifest key replaces the `agents/` scan.
308 
309#### Organize agents in subfolders
310 
311You can put plugin agent files in subfolders of `agents/`. Claude Code [loads them recursively](/docs/en/sub-agents#choose-the-subagent-scope) and joins the plugin name, each subfolder name, and the file name with colons to form the agent's scoped name. For example, `agents/review/security.md` in a plugin named `my-plugin` loads as `my-plugin:review:security`. Two settings change that name:
312 
313* Frontmatter `name`: it replaces only the file name, so `name: audit` in `agents/review/security.md` loads as `my-plugin:review:audit`
314* Manifest [`agents`](/docs/en/plugins/manifest-reference#fields) field: a file you list there loads without subfolder names, so `"agents": "./custom/review/security.md"` loads as `my-plugin:security`
315 
316#### Frontmatter fields in plugin agents
317 
318A plugin agent's frontmatter follows these rules:
319 
320* **Supported fields**: `name`, `description`, `model`, `effort`, `maxTurns`, `autoCompactWindow`, `tools`, `disallowedTools`, `skills`, `memory`, `background`, `omitClaudeMd`, `isolation`, `color`, and the `cacheTtl` key of `experimental`. The only valid `isolation` value is `"worktree"`. See [supported frontmatter fields](/docs/en/sub-agents#supported-frontmatter-fields) for what each one does
321* **Ignored fields**: `permissionMode`, `hooks`, `mcpServers`, and `initialPrompt`. An agent file can't add hooks or MCP servers on its own, so add those as plugin [hooks](#hooks) and [MCP servers](#mcp-servers) instead
322* **Frontmatter that doesn't parse**: the agent still loads with every field ignored. It's named after the file, and its description reads `Agent from my-plugin plugin`. Run [`claude plugin validate`](/docs/en/plugins/cli-reference#plugin-validate) in your shell to find these files
323 
324For what each field does and the precedence rules, see [Subagents](/docs/en/sub-agents#supported-frontmatter-fields).
325 
326### Hooks
327 
328A [hook](/docs/en/hooks-guide) runs something automatically at a point in Claude Code's lifecycle, such as after every file edit: a shell command, an HTTP request, an MCP tool call, a prompt to a model, or a subagent. Save the plugin's hooks in `hooks/hooks.json` at the plugin root, under a top-level `"hooks"` key, in the same shape as the `hooks` object in `settings.json`. That lets you copy an existing settings hook in unchanged.
329 
330This hook runs a bundled script after every `Write` or `Edit`:
331 
332```json hooks/hooks.json theme={null}
333{
334 "hooks": {
335 "PostToolUse": [
336 {
337 "matcher": "Write|Edit",
338 "hooks": [
339 {
340 "type": "command",
341 "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
342 }
343 ]
344 }
345 ]
346 }
347}
348```
349 
350Save the script at `scripts/format.sh` and make it executable.
351 
352Load the plugin and ask Claude to edit a file. A `PostToolUse` hook that exits 0 shows nothing in the transcript, so confirm it ran with [debug logging](/docs/en/hooks#debug-hooks) or by what the script itself changes.
353 
354Hooks in `hooks/hooks.json` and in the `hooks` manifest key both load. For every event and its payload, see [Hook events](/docs/en/hooks#hook-events).
355 
356When another enabled plugin has the same name, one of the two registers its `hooks/hooks.json` hooks and the other's are left out. See [Hooks when two enabled plugins share a name](/docs/en/plugins/loading#hooks-when-two-enabled-plugins-share-a-name) for which one, and for the note in `/plugin` that tells you.
357 
358To write hooks as JavaScript functions that run inside Claude Code and can draw in its interface, list a module file under a `modules` key in the same `hooks/hooks.json`. A plugin with one is a mod. See [Create a mod](/docs/en/plugins/mods/create).
359 
360#### When plugin hooks fire
361 
362A plugin's hooks don't wait for one of the plugin's skills or commands to be used. Claude Code registers them when a session loads the plugin, and they fire on their events from then on. To limit when a hook runs, narrow its `matcher`.
363 
364If a hook never fires, see [hooks that don't fire](/docs/en/plugins/troubleshooting#failed-to-load-hooks-from-and-hooks-that-dont-fire).
365 
366#### Environment, quoting, and matching MCP tools
367 
368The hook's environment, the quoting of `${CLAUDE_PLUGIN_ROOT}`, and matchers for the plugin's own MCP tools work as follows:
369 
370* **Environment**: every hook process receives `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` in its environment, plus `CLAUDE_PLUGIN_OPTION_<KEY>` for each [user configuration](#user-configuration) value, so your script can read them from there
371* **Quoting**: when `command` has no `args`, it runs through a shell, so wrap the `${CLAUDE_PLUGIN_ROOT}` path in double quotes, as the `hooks/hooks.json` example under [Hooks](#hooks) does, to keep the expanded path one shell word. When you pass `args` instead, each element is passed as one argument with no shell and needs no quoting. See [exec form and shell form](/docs/en/hooks#exec-form-and-shell-form)
372* **Matching the plugin's own MCP tools**: a tool from an [MCP server this plugin declares](#mcp-servers) is named `mcp__plugin_<plugin>_<server>__<tool>`, so write that full name in the matcher. A matcher on the server name alone never fires. See [Match MCP tools](/docs/en/hooks#match-mcp-tools)
373 
374### MCP servers
375 
376An MCP server gives Claude tools from an external system. Declare it in `.mcp.json` at the plugin root, in the same shape as a [project `.mcp.json`](/docs/en/mcp#project-scope). This `.mcp.json` declares one server named `db`:
377 
378```json .mcp.json theme={null}
379{
380 "mcpServers": {
381 "db": {
382 "command": "node",
383 "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
384 }
385 }
386}
387```
388 
389You can also omit the `mcpServers` wrapper and put `db` at the top level of the file.
390 
391Load the plugin and run `/mcp` to confirm the server appears as `plugin:my-plugin:db`.
392 
393`claude plugin validate` checks `.mcp.json` and reports a server entry that Claude Code would drop at load time as an error. Requires Claude Code v2.1.281 or later.
394 
395For where a bad entry shows up at load time, see [MCP servers that don't start](/docs/en/plugins/troubleshooting#invalid-mcp-server-config-for-and-mcp-servers-that-dont-start).
396 
397The `mcpServers` manifest key takes an inline server map, a path to a JSON file, or an array of those. When a manifest server has the same name as one in `.mcp.json`, the manifest server replaces it.
398 
399#### Reach users on claude.ai and Cowork
400 
401A local stdio server, such as the `db` server under [MCP servers](#mcp-servers), runs in Claude Code and in a Cowork session that runs on your machine in the Claude Desktop app, but not on claude.ai. To reach users there too, reference a remote server by its `https://` URL, which claude.ai and Cowork offer to the user as a connector, as [Bundle an MCP connector with its skill](https://claude.com/docs/plugins/build#bundle-an-mcp-connector-with-its-skill) shows.
402 
403#### Server names, tool names, and reloads
404 
405The server's names, variable substitution, and reload behavior follow these rules:
406 
407* **Server name**: `plugin:<plugin>:<server>`, so the `db` server in `my-plugin` is `plugin:my-plugin:db` in `/mcp`. Use the same form to name the server in an [`mcp_tool` hook](/docs/en/hooks#mcp-tool-hook-fields)
408* **Tool names**: `mcp__plugin_<plugin>_<server>__<tool>`, so a `query` tool on that `db` server is `mcp__plugin_my-plugin_db__query`. That is the name to use in [permission rules](/docs/en/permissions) and [hook matchers](#hooks)
409* **Substitution**: `${CLAUDE_PLUGIN_ROOT}` and the other [path variables](#path-variables-and-persistent-data) are substituted in `command`, `args`, and `env`. No quoting is needed in `args`, because each element is passed as one argument
410* **Reload**: when the user runs `/reload-plugins` and [the reload applies](/docs/en/plugins/cli-reference#reloads-that-change-mcp-tools), a server whose configuration is unchanged keeps its connection. A server whose configuration changed reconnects, and one you removed disconnects
411 
412#### Include a packaged MCPB server
413 
414The `mcpServers` key also accepts a packaged server as an [MCPB file](https://github.com/modelcontextprotocol/mcpb), whose extension is `.mcpb` or the older `.dxt`. Point the key at the file, as a path inside the plugin or an `https://` URL:
415 
416```json .claude-plugin/plugin.json theme={null}
417{
418 "name": "my-plugin",
419 "mcpServers": "./servers/db.mcpb"
420}
421```
422 
423The server takes its name from the `name` in the bundle's manifest.
424 
425A bundle's own manifest can declare settings the server needs from the user in a `user_config` block. A bundled server with a required setting that has no saved value doesn't start. The `/plugin` **Errors** tab shows `Bundled MCP server "<name>" was not started: it needs configuration`.
426 
427Users supply the values in one of two ways:
428 
429* **In `/plugin`**: select the plugin on the **Installed** tab and choose **Configure**
430* **At install, from the shell**: pass [`--config <server>.<key>=<value>`](/docs/en/plugins/cli-reference#plugin-install) to `claude plugin install`. Requires Claude Code v2.1.285 or later, and works only for a bundle packaged inside the plugin.
431 
432For transports and authentication, see [MCP](/docs/en/mcp#plugin-provided-mcp-servers).
433 
434### LSP servers
435 
436An LSP server gives Claude diagnostics and code navigation for a language. If an [official code intelligence plugin](/docs/en/plugins/code-intelligence) already covers your language, install that instead of writing one. Otherwise declare the server in `.lsp.json` at the plugin root:
437 
438```json .lsp.json theme={null}
439{
440 "gopls": {
441 "command": "gopls",
442 "args": ["serve"],
443 "extensionToLanguage": {
444 ".go": "go"
445 }
446 }
447}
448```
449 
865450The file maps each server name directly to its configuration, with no wrapper object around the map. `command` is the binary's name, with its arguments in `args`. `extensionToLanguage` needs at least one extension, each starting with `.`.
866451 
867452`claude plugin validate` doesn't read this file. When any entry is invalid, the whole file is skipped at load and `Invalid LSP server config for ".lsp.json"` appears in the `/plugin` **Errors** tab.
from line 466
881466 
882467### Executables
883468 
884Files in `bin/` at the plugin root are on the `PATH` of the Bash tool's shell while the plugin is enabled, so Claude can run them as bare commands. Add an executable script:
469Files in `bin/` at the plugin root are on the `PATH` of the Bash tool's shell while the plugin is enabled, so Claude can run them as bare commands. A command that Claude runs with the [PowerShell tool](/docs/en/tools-reference#powershell-tool) outside the [sandbox](/docs/en/sandboxing) finds them on its `PATH` too, and a sandboxed PowerShell command doesn't. Add an executable script:
885470 
886471```bash bin/hello-plugin theme={null}
887472#!/bin/bash
from line 587
1002587 
1003588For the `when` trigger and the other fields, see [`monitors`](/docs/en/plugins/manifest-reference#monitors).
1004589 
1005<h2 id="user-configuration">
1006 Ask the user for configuration values
1007</h2>
590## Ask the user for configuration values
1008591 
1009592Declare the values your plugin needs from the user in the `userConfig` manifest key, so users don't edit `settings.json` themselves. Each option appears in a dialog with its `title` as the label and its `description` beneath it.
1010593 
from line 632
1049632 
1050633For the option fields, where each value is stored, how a component references a saved value, and which fields reject `${user_config.*}`, see [User configuration](/docs/en/plugins/manifest-reference#user-configuration).
1051634 
1052<h2 id="path-variables-and-persistent-data">
1053 Reference plugin paths and store data
1054</h2>
635## Reference plugin paths and store data
1055636 
1056637You don't know where your plugin will be installed, so refer to its files and data through these variables rather than fixed paths. They're substituted in skill, command, and agent content, in hook and monitor commands, and in MCP and LSP server configurations. They're also exported to hook, MCP, and LSP processes:
1057638 
1058639 

plugins/create Changed · +174 / -196 lines

### Share your plugin ### Load a plugin for one session ### Make a plugin load in every session #### Name the plugin's skills #### Share the plugin through a repository ## Convert an existing `.claude/` setup

from line 6
66 
77This page is for people writing their own plugins.
88 
9<Note>
10 These cases are covered on other pages:
9> [!NOTE]
10>
11> These cases are covered on other pages:
12>
13> * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
14> * **Not sure you need a plugin**: see [Decide whether you need a plugin](/docs/en/plugins/overview#decide-whether-you-need-a-plugin) on the overview
15> * **Your plugin's users are on claude.ai or in Cowork**: the same folder installs there with a different subset of components. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
1116 
12 * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
13 * **Not sure you need a plugin**: see [Decide whether you need a plugin](/docs/en/plugins/overview#decide-whether-you-need-a-plugin) on the overview
14 * **Your plugin's users are on claude.ai or in Cowork**: the same folder installs there with a different subset of components. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
15</Note>
16 
1717Start from the section that matches what you already have:
1818 
1919* **Nothing yet**: follow [Create your first plugin](#create-your-first-plugin), then [Develop without a marketplace](#develop-without-a-marketplace) and [Test and debug](#test-and-debug).
from line 38
3838 
3939Open a terminal in the directory where you want to keep the plugin, such as `~/projects`, and run the commands in these steps from it. You can keep a plugin anywhere, because you pass its path to Claude Code when you start a session.
4040 
41<Steps>
42 <Step title="Create the plugin directory">
43 Create the plugin directory, with a `.claude-plugin/` folder inside it to hold the manifest:
41**1. Create the plugin directory**
4442 
45 ```bash theme={null}
46 mkdir -p my-first-plugin/.claude-plugin
47 ```
48 </Step>
43Create the plugin directory, with a `.claude-plugin/` folder inside it to hold the manifest:
4944 
50 <Step title="Write the manifest">
51 The [manifest](/docs/en/plugins/manifest-reference) is a JSON file named `plugin.json` that tells Claude Code the plugin's name and describes it. Save this one as `my-first-plugin/.claude-plugin/plugin.json`:
45```bash theme={null}
46mkdir -p my-first-plugin/.claude-plugin
47```
5248 
53 ```json my-first-plugin/.claude-plugin/plugin.json theme={null}
54 {
55 "name": "my-first-plugin",
56 "description": "A greeting plugin to learn the basics",
57 "version": "1.0.0",
58 "author": {
59 "name": "Your Name"
60 }
61 }
62 ```
49**2. Write the manifest**
6350 
64 The four fields do this:
51The [manifest](/docs/en/plugins/manifest-reference) is a JSON file named `plugin.json` that tells Claude Code the plugin's name and describes it. Save this one as `my-first-plugin/.claude-plugin/plugin.json`:
6552 
66 * **`name`**: required. It identifies the plugin and becomes the prefix on every skill and agent the plugin provides. Don't put spaces in it.
67 * **`description`**: the text users see for the plugin in `/plugin`.
68 * **`version`**: optional. Setting it keeps users on that version until you change it; [Release a new version](/docs/en/plugins/host-marketplace#release-a-new-version) says when to set or omit it.
69 * **`author`**: who to credit. `name` is required inside it; `email` and `url` are optional.
53```json my-first-plugin/.claude-plugin/plugin.json theme={null}
54{
55 "name": "my-first-plugin",
56 "description": "A greeting plugin to learn the basics",
57 "version": "1.0.0",
58 "author": {
59 "name": "Your Name"
60 }
61}
62```
7063 
71 Every other field is on the [manifest reference](/docs/en/plugins/manifest-reference#fields).
64The four fields do this:
7265 
73 Only `plugin.json` goes inside `.claude-plugin/`. The skill you add next goes directly under `my-first-plugin/`, next to that folder.
74 </Step>
66* **`name`**: required. It identifies the plugin and becomes the prefix on every skill and agent the plugin provides. Don't put spaces in it.
67* **`description`**: the text users see for the plugin in `/plugin`.
68* **`version`**: optional. Setting it keeps users on that version until you change it; [Release a new version](/docs/en/plugins/host-marketplace#release-a-new-version) says when to set or omit it.
69* **`author`**: who to credit. `name` is required inside it; `email` and `url` are optional.
7570 
76 <Step title="Add a skill">
77 This plugin's one component is a skill. Each skill is a directory under `skills/` that contains a `SKILL.md` file. Create the skill's directory:
71Every other field is on the [manifest reference](/docs/en/plugins/manifest-reference#fields).
7872 
79 ```bash theme={null}
80 mkdir -p my-first-plugin/skills/hello
81 ```
73Only `plugin.json` goes inside `.claude-plugin/`. The skill you add next goes directly under `my-first-plugin/`, next to that folder.
8274 
83 Then create `my-first-plugin/skills/hello/SKILL.md` with this content:
75**3. Add a skill**
8476 
85 ```markdown my-first-plugin/skills/hello/SKILL.md theme={null}
86 ---
87 name: hello
88 description: Greet the user with a friendly message
89 disable-model-invocation: true
90 ---
77This plugin's one component is a skill. Each skill is a directory under `skills/` that contains a `SKILL.md` file. Create the skill's directory:
9178 
92 Greet the user warmly and ask how you can help them today.
93 ```
79```bash theme={null}
80mkdir -p my-first-plugin/skills/hello
81```
9482 
95 The `disable-model-invocation: true` line means Claude doesn't run the skill on its own. Remove that line from a skill you want Claude to run on its own. The skill's command combines the plugin name and the skill's name, so you run this one as `/my-first-plugin:hello`. For the other frontmatter fields, see the [skill frontmatter reference](/docs/en/skills#frontmatter-reference).
96 </Step>
83Then create `my-first-plugin/skills/hello/SKILL.md` with this content:
9784 
98 <Step title="Validate the plugin">
99 Check the manifest and the skill's frontmatter before you run anything:
85```markdown my-first-plugin/skills/hello/SKILL.md theme={null}
86---
87name: hello
88description: Greet the user with a friendly message
89disable-model-invocation: true
90---
10091 
101 ```bash theme={null}
102 claude plugin validate ./my-first-plugin
103 ```
92Greet the user warmly and ask how you can help them today.
93```
10494 
105 The command prints the manifest path it checked and `✔ Validation passed`. If it prints `✘ Validation failed` instead, each line above that result line names the field to fix. Look up each message under [`claude plugin validate` reports errors](/docs/en/plugins/troubleshooting#claude-plugin-validate-reports-errors).
106 </Step>
95The `disable-model-invocation: true` line means Claude doesn't run the skill on its own. Remove that line from a skill you want Claude to run on its own. The skill's command combines the plugin name and the skill's name, so you run this one as `/my-first-plugin:hello`. For the other frontmatter fields, see the [skill frontmatter reference](/docs/en/skills#frontmatter-reference).
10796 
108 <Step title="Run Claude Code with the plugin">
109 Start a session with the plugin loaded:
97**4. Validate the plugin**
11098 
111 ```bash theme={null}
112 claude --plugin-dir ./my-first-plugin
113 ```
99Check the manifest and the skill's frontmatter before you run anything:
114100 
115 Once Claude Code starts, run the skill:
101```bash theme={null}
102claude plugin validate ./my-first-plugin
103```
116104 
117 ```text theme={null}
118 /my-first-plugin:hello
119 ```
105The command prints the manifest path it checked and `✔ Validation passed`. If it prints `✘ Validation failed` instead, each line above that result line names the field to fix. Look up each message under [`claude plugin validate` reports errors](/docs/en/plugins/troubleshooting#claude-plugin-validate-reports-errors).
120106 
121 Claude replies with a greeting.
122 </Step>
123</Steps>
107**5. Run Claude Code with the plugin**
124108 
109Start a session with the plugin loaded:
110 
111```bash theme={null}
112claude --plugin-dir ./my-first-plugin
113```
114 
115Once Claude Code starts, run the skill:
116 
117```text theme={null}
118/my-first-plugin:hello
119```
120 
121Claude replies with a greeting.
122 
125123The plugin loads only in sessions you start with `--plugin-dir`. To keep working on it without the flag, or to test a `.zip` build, see [Develop without a marketplace](#develop-without-a-marketplace).
126124 
127125To have Claude scaffold and check a larger plugin with you, [install](/docs/en/plugins/install#install-a-plugin) Anthropic's `plugin-dev` plugin from the `claude-plugins-official` marketplace, which adds skills and agents for writing components such as skills, hooks, and MCP servers and for validating the finished plugin. Once it's installed, run `/plugin-dev:create-plugin` followed by a description of the plugin you want, and Claude walks you through designing, creating, and validating it.
128126 
129<h3 id="share-the-plugin">
130 Share your plugin
131</h3>
127### Share your plugin
132128 
133129A plugin you built with [Create your first plugin](#create-your-first-plugin) exists only on your machine. When it's ready for other people, there are three ways to get it to them:
134130 
from line 147
151147| `hooks/hooks.json` | Hook configuration: a top-level `"hooks"` key whose value has the same shape as `hooks` in a settings file |
152148| `.mcp.json` | MCP server definitions |
153149 
154<Warning>
155 Only `plugin.json` goes inside `.claude-plugin/`. Components saved there don't load.
150> [!WARNING]
151>
152> Only `plugin.json` goes inside `.claude-plugin/`. Components saved there don't load.
153>
154> The plugin root is the plugin's own directory, not `~/.claude/` itself. A `.mcp.json` saved at `~/.claude/.mcp.json` doesn't load.
156155 
157 The plugin root is the plugin's own directory, not `~/.claude/` itself. A `.mcp.json` saved at `~/.claude/.mcp.json` doesn't load.
158</Warning>
159 
160156## Develop without a marketplace
161157 
162158You don't need a [marketplace](/docs/en/plugins/overview#get-plugins-from-a-marketplace) to run a plugin you're writing. Load it directly from disk or a URL instead:
from line 163
167163 
168164If two plugins loaded in different ways share a name, see [Name conflicts](/docs/en/plugins/loading#name-conflicts) for which one Claude Code keeps.
169165 
170<h3 id="load-a-directory-or-archive-for-one-session">
171 Load a plugin for one session
172</h3>
166### Load a plugin for one session
173167 
174168You can load a plugin for a single session in three ways: from a directory or `.zip` archive on disk with `--plugin-dir`, from a URL with `--plugin-url`, or from an environment variable when you can't add a flag. Each plugin loads for that session only, and nothing is written to your settings for it. When you edit the plugin's files during the session, run `/reload-plugins` to load the changes.
175169 
176<span id="from-a-directory-or-zip" />
177 
178170#### Load a plugin from a directory or `.zip`
179171 
180172When you start `claude` from your shell, pass `--plugin-dir` with the plugin's root directory or a `.zip` archive of it. Repeat the flag to load several plugins:
from line 190
198190 
199191A message appears in the session for each of these changes. If loading or unloading a plugin mid-conversation would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), the change is held instead, and the message tells you to run `/reload-plugins` to apply it.
200192 
201<span id="fetch-an-archive-from-a-url-for-one-session" />
202 
203193#### Load a plugin from a URL
204194 
205195When you start `claude` from your shell, pass `--plugin-url` with the address of a `.zip` archive, such as a build artifact your CI publishes:
from line 204
214204 
215205If Claude Code can't fetch the archive, or the archive is invalid, it starts without the plugin and records a plugin load error that you can review in the `/plugin` manager's **Errors** tab.
216206 
217<span id="from-an-environment-variable" />
218 
219207#### Load plugins from an environment variable
220208 
221209To load plugins in a session where you can't add the `--plugin-dir` flag, list their absolute paths in the [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables) environment variable instead. Claude Code loads each path as it loads a `--plugin-dir` path. These plugins load in addition to any you pass with `--plugin-dir`. [Project and local settings can't set this variable](/docs/en/settings-reference#variables-claude-code-ignores-in-env). `CLAUDE_CODE_PLUGIN_DIRS` requires Claude Code v2.1.280 or later.
from line 210
222210 
223211Managed settings can turn off `--plugin-dir` and `CLAUDE_CODE_PLUGIN_DIRS`. See [Flags that load a plugin for one session](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session). To test a plugin together with a plugin it depends on, see [Test a plugin and its dependency locally](/docs/en/plugins/dependencies#test-a-plugin-and-its-dependency-locally).
224212 
225<h3 id="scaffold-a-plugin-that-loads-every-session">
226 Make a plugin load in every session
227</h3>
213### Make a plugin load in every session
228214 
229215Your personal skills directory is `~/.claude/skills/`. Claude Code loads any folder there that contains a `.claude-plugin/plugin.json` as a plugin in every session, with no flag and no install step. `claude plugin init` scaffolds one of these plugins for you.
230216 
from line 226
240226 
241227Pass `--with skills` to have `claude plugin init` scaffold a skill under `skills/` for you. The other `--with` values are on the [plugin commands reference](/docs/en/plugins/cli-reference#plugin-init).
242228 
243<h4 id="skill-names-in-a-scaffolded-plugin">
244 Name the plugin's skills
245</h4>
229#### Name the plugin's skills
246230 
247231The root skill at `~/.claude/skills/my-tool/SKILL.md` is also a personal skill, so you invoke it as `/my-tool`, not `/my-tool:my-tool`. Skills you add under `skills/` inside the plugin get the plugin-name prefix, such as `/my-tool:example`.
248232 
from line 234
250234 
251235To stop loading a scaffolded plugin, delete its directory, or run `claude plugin disable my-tool@skills-dir` in your shell with the `my-tool@skills-dir` name that `claude plugin init` printed. In the ID `my-tool@skills-dir`, `skills-dir` stands where a marketplace name would, because the plugin loads from your skills directory rather than from a marketplace.
252236 
253<h4 id="load-a-plugin-for-everyone-in-one-repository">
254 Share the plugin through a repository
255</h4>
237#### Share the plugin through a repository
256238 
257239`claude plugin init` writes the plugin to your personal skills directory at `~/.claude/skills/`, so it loads for you in every project. To make a plugin load for everyone in one repository, create the same layout yourself at `<project>/.claude/skills/<name>/`, including its `.claude-plugin/plugin.json`. See [Plugins shared through a repository](/docs/en/plugins/loading#plugins-shared-through-a-repository) for the conditions under which Claude Code loads it.
258240 
from line 273
291273 
292274A plugin that loads without errors can still fail to steer Claude the way you intend. `claude plugin eval`, which you run in your shell, runs your test cases with and without the plugin and scores the difference. See [Test plugins with evals](/docs/en/plugin-evals), starting with [Create your first eval suite](/docs/en/plugin-evals#create-your-first-eval-suite).
293275 
294<h2 id="convert-an-existing-claude-setup">
295 Convert an existing `.claude/` setup
296</h2>
276## Convert an existing `.claude/` setup
297277 
298278If you already have skills, agents, or hooks under a project's `.claude/` directory, you can move them into a plugin without rewriting them.
299279 
300280Run the commands in these steps from the project root, which is the directory that contains `.claude/`, because the `cp` paths are relative to it.
301281 
302<Steps>
303 <Step title="Create the plugin structure">
304 Create the plugin directory and its `.claude-plugin/` folder alongside `.claude/`. You can move the plugin anywhere afterwards.
282**1. Create the plugin structure**
305283 
306 ```bash theme={null}
307 mkdir -p my-plugin/.claude-plugin
308 ```
284Create the plugin directory and its `.claude-plugin/` folder alongside `.claude/`. You can move the plugin anywhere afterwards.
309285 
310 Create `my-plugin/.claude-plugin/plugin.json`:
286```bash theme={null}
287mkdir -p my-plugin/.claude-plugin
288```
311289 
312 ```json my-plugin/.claude-plugin/plugin.json theme={null}
313 {
314 "name": "my-plugin",
315 "description": "Migrated from standalone configuration",
316 "version": "1.0.0"
317 }
318 ```
319 </Step>
290Create `my-plugin/.claude-plugin/plugin.json`:
320291 
321 <Step title="Copy your existing files">
322 Copy each configuration directory you have to the plugin root, and skip the command for any directory you don't have.
292```json my-plugin/.claude-plugin/plugin.json theme={null}
293{
294 "name": "my-plugin",
295 "description": "Migrated from standalone configuration",
296 "version": "1.0.0"
297}
298```
323299 
324 ```bash theme={null}
325 cp -r .claude/commands my-plugin/
326 ```
300**2. Copy your existing files**
327301 
328 ```bash theme={null}
329 cp -r .claude/agents my-plugin/
330 ```
302Copy each configuration directory you have to the plugin root, and skip the command for any directory you don't have.
331303 
332 ```bash theme={null}
333 cp -r .claude/skills my-plugin/
334 ```
304```bash theme={null}
305cp -r .claude/commands my-plugin/
306```
335307 
336 Run `ls -a my-plugin` to confirm that each directory you copied appears next to `.claude-plugin`.
337 </Step>
308```bash theme={null}
309cp -r .claude/agents my-plugin/
310```
338311 
339 <Step title="Move your hooks">
340 If you have hooks in `.claude/settings.json` or `.claude/settings.local.json`, create a hooks directory:
312```bash theme={null}
313cp -r .claude/skills my-plugin/
314```
341315 
342 ```bash theme={null}
343 mkdir -p my-plugin/hooks
344 ```
316Run `ls -a my-plugin` to confirm that each directory you copied appears next to `.claude-plugin`.
345317 
346 Create `my-plugin/hooks/hooks.json` and copy the `hooks` object from your settings file into it. The format is the same.
318**3. Move your hooks**
347319 
348 This example shows the shape with one hook that runs a linter on each file Claude writes or edits. Replace the example with your own `hooks` object.
320If you have hooks in `.claude/settings.json` or `.claude/settings.local.json`, create a hooks directory:
349321 
350 ```json my-plugin/hooks/hooks.json theme={null}
351 {
352 "hooks": {
353 "PostToolUse": [
354 {
355 "matcher": "Write|Edit",
356 "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }]
357 }
358 ]
322```bash theme={null}
323mkdir -p my-plugin/hooks
324```
325 
326Create `my-plugin/hooks/hooks.json` and copy the `hooks` object from your settings file into it. The format is the same.
327 
328This example shows the shape with one hook that runs a linter on each file Claude writes or edits. Replace the example with your own `hooks` object.
329 
330```json my-plugin/hooks/hooks.json theme={null}
331{
332 "hooks": {
333 "PostToolUse": [
334 {
335 "matcher": "Write|Edit",
336 "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }]
359337 }
360 }
361 ```
362 </Step>
338 ]
339 }
340}
341```
363342 
364 <Step title="Test the migrated plugin">
365 Load the plugin for a session:
343**4. Test the migrated plugin**
366344 
367 ```bash theme={null}
368 claude --plugin-dir ./my-plugin
369 ```
345Load the plugin for a session:
370346 
371 Check each component under its new name:
347```bash theme={null}
348claude --plugin-dir ./my-plugin
349```
372350 
373 * **Skills**: run `/my-plugin:deploy` for a skill that was `/deploy`.
374 * **Subagents**: ask Claude to use the `my-plugin:reviewer` agent for an agent that was `reviewer`.
375 * **Hooks**: trigger the event each hook matches.
351Check each component under its new name:
376352 
377 If something is missing, work through [Test and debug](#test-and-debug).
378 </Step>
379</Steps>
353* **Skills**: run `/my-plugin:deploy` for a skill that was `/deploy`.
354* **Subagents**: ask Claude to use the `my-plugin:reviewer` agent for an agent that was `reviewer`.
355* **Hooks**: trigger the event each hook matches.
356 
357If something is missing, work through [Test and debug](#test-and-debug).
380358 
381359While the originals are still under `.claude/`, they stay loaded alongside the plugin's copies:
382360 

plugins/create-marketplace Changed · +94 / -96 lines

from line 6
66 
77Create your own marketplace when you want a group you choose, such as your team or your organization, to install your plugins and keep receiving your updates from a catalog you control. The repository can be private, it can list as many plugins as you like, and an administrator can [require it on every machine](/docs/en/plugins/org).
88 
9<Note>
10 These cases are covered on other pages:
9> [!NOTE]
10>
11> These cases are covered on other pages:
12>
13> * **Sharing one plugin with a few people**: send them the plugin's directory or a `.zip` of it. See [Share a plugin without a marketplace](/docs/en/plugins/publish#share-a-plugin-without-a-marketplace).
14> * **Offering a plugin to everyone**: submit it to Anthropic's directory. See [Submit to Anthropic's directory](/docs/en/plugins/publish#submit-to-anthropics-directory).
15> * **Using a plugin yourself**: load it with `--plugin-dir` or save it in your skills directory. See [Develop without a marketplace](/docs/en/plugins/create#develop-without-a-marketplace).
1116 
12 * **Sharing one plugin with a few people**: send them the plugin's directory or a `.zip` of it. See [Share a plugin without a marketplace](/docs/en/plugins/publish#share-a-plugin-without-a-marketplace).
13 * **Offering a plugin to everyone**: submit it to Anthropic's directory. See [Submit to Anthropic's directory](/docs/en/plugins/publish#submit-to-anthropics-directory).
14 * **Using a plugin yourself**: load it with `--plugin-dir` or save it in your skills directory. See [Develop without a marketplace](/docs/en/plugins/create#develop-without-a-marketplace).
15</Note>
16 
1717Start with [Create a marketplace](#create-a-marketplace) to build one on your own machine and install a plugin from it, then [add more plugin entries](#add-plugin-entries).
1818 
1919## Create a marketplace
from line 22
2222 
2323You need a plugin to list. The example uses `my-first-plugin` from [Create your first plugin](/docs/en/plugins/create#create-your-first-plugin), a plugin with one skill that you run as `/my-first-plugin:hello`; build it first if you don't have a plugin yet. To use a plugin of your own instead, substitute its directory and its `name` wherever the steps say `my-first-plugin`. For what a plugin directory can contain, see the [plugin directory explorer](/docs/en/plugins/components#explore-the-plugin-directory).
2424 
25<Steps>
26 <Step title="Set up the marketplace directory">
27 A marketplace is a directory with a `.claude-plugin/marketplace.json` file, plus the plugins it lists. Create the marketplace directory and its `.claude-plugin/` folder, then copy your plugin in under `plugins/`:
25**1. Set up the marketplace directory**
2826 
29 ```bash theme={null}
30 mkdir -p my-marketplace/.claude-plugin my-marketplace/plugins
31 cp -r my-first-plugin my-marketplace/plugins/
32 ```
27A marketplace is a directory with a `.claude-plugin/marketplace.json` file, plus the plugins it lists. Create the marketplace directory and its `.claude-plugin/` folder, then copy your plugin in under `plugins/`:
3328 
34 Check that the plugin is valid where it now sits, so that any later error is about the marketplace and not the plugin:
29```bash theme={null}
30mkdir -p my-marketplace/.claude-plugin my-marketplace/plugins
31cp -r my-first-plugin my-marketplace/plugins/
32```
3533 
36 ```bash theme={null}
37 claude plugin validate ./my-marketplace/plugins/my-first-plugin
38 ```
34Check that the plugin is valid where it now sits, so that any later error is about the marketplace and not the plugin:
3935 
40 The last line of the output reads `✔ Validation passed`.
41 </Step>
36```bash theme={null}
37claude plugin validate ./my-marketplace/plugins/my-first-plugin
38```
4239 
43 <Step title="Create the marketplace file">
44 Save `marketplace.json` at `my-marketplace/.claude-plugin/marketplace.json`. The file requires a `name`, an `owner`, and a `plugins` array.
40The last line of the output reads `✔ Validation passed`.
4541 
46 Each object in `plugins` is a plugin entry and needs a `name` and a `source`. Write the entry's `source` as a path from the marketplace root. The root is `my-marketplace/`, the directory that contains `.claude-plugin/`.
42**2. Create the marketplace file**
4743 
48 ```json my-marketplace/.claude-plugin/marketplace.json theme={null}
44Save `marketplace.json` at `my-marketplace/.claude-plugin/marketplace.json`. The file requires a `name`, an `owner`, and a `plugins` array.
45 
46Each object in `plugins` is a plugin entry and needs a `name` and a `source`. Write the entry's `source` as a path from the marketplace root. The root is `my-marketplace/`, the directory that contains `.claude-plugin/`.
47 
48```json my-marketplace/.claude-plugin/marketplace.json theme={null}
49{
50 "name": "my-marketplace",
51 "description": "Plugins for my team",
52 "owner": {
53 "name": "Your Name"
54 },
55 "plugins": [
4956 {
50 "name": "my-marketplace",
51 "description": "Plugins for my team",
52 "owner": {
53 "name": "Your Name"
54 },
55 "plugins": [
56 {
57 "name": "my-first-plugin",
58 "source": "./plugins/my-first-plugin",
59 "description": "A greeting plugin to learn the basics"
60 }
61 ]
57 "name": "my-first-plugin",
58 "source": "./plugins/my-first-plugin",
59 "description": "A greeting plugin to learn the basics"
6260 }
63 ```
64 </Step>
61 ]
62}
63```
6564 
66 <Step title="Validate the marketplace">
67 Run `claude plugin validate` on the marketplace directory to check the JSON syntax, the required fields, and each plugin entry in its `.claude-plugin/marketplace.json`.
65**3. Validate the marketplace**
6866 
69 ```bash theme={null}
70 claude plugin validate ./my-marketplace
71 ```
67Run `claude plugin validate` on the marketplace directory to check the JSON syntax, the required fields, and each plugin entry in its `.claude-plugin/marketplace.json`.
7268 
73 For the file as written in step 2, the last line of the output reads `✔ Validation passed`.
74 </Step>
69```bash theme={null}
70claude plugin validate ./my-marketplace
71```
7572 
76 <Step title="Add the marketplace and install the plugin">
77 Register the directory as a marketplace.
73For the file as written in step 2, the last line of the output reads `✔ Validation passed`.
7874 
79 ```bash theme={null}
80 claude plugin marketplace add ./my-marketplace
81 ```
75**4. Add the marketplace and install the plugin**
8276 
83 The command prints `✔ Successfully added marketplace: my-marketplace (declared in user settings)`, which means the marketplace is recorded in your user settings file.
77Register the directory as a marketplace.
8478 
85 Install the plugin. The install id is the entry's `name`, an `@`, and the marketplace `name`.
79```bash theme={null}
80claude plugin marketplace add ./my-marketplace
81```
8682 
87 ```bash theme={null}
88 claude plugin install my-first-plugin@my-marketplace
89 ```
83The command prints `✔ Successfully added marketplace: my-marketplace (declared in user settings)`, which means the marketplace is recorded in your user settings file.
9084 
91 The command prints `✔ Successfully installed plugin: my-first-plugin@my-marketplace (scope: user)`.
85Install the plugin. The install id is the entry's `name`, an `@`, and the marketplace `name`.
9286 
93 Inside a session, `/plugin marketplace add ./my-marketplace` registers the marketplace the same way. `/plugin install my-first-plugin@my-marketplace` opens the plugin's details in the `/plugin` panel, where you install it. For that flow, see [Install and manage plugins](/docs/en/plugins/install).
94 </Step>
87```bash theme={null}
88claude plugin install my-first-plugin@my-marketplace
89```
9590 
96 <Step title="Confirm the plugin loaded">
97 List installed plugins.
91The command prints `✔ Successfully installed plugin: my-first-plugin@my-marketplace (scope: user)`.
9892 
99 ```bash theme={null}
100 claude plugin list
101 ```
93Inside a session, `/plugin marketplace add ./my-marketplace` registers the marketplace the same way. `/plugin install my-first-plugin@my-marketplace` opens the plugin's details in the `/plugin` panel, where you install it. For that flow, see [Install and manage plugins](/docs/en/plugins/install).
10294 
103 The output lists `my-first-plugin@my-marketplace` with `Status: ✔ enabled`.
95**5. Confirm the plugin loaded**
10496 
105 To see what the plugin loaded, show its details.
97List installed plugins.
10698 
107 ```bash theme={null}
108 claude plugin details my-first-plugin
109 ```
99```bash theme={null}
100claude plugin list
101```
110102 
111 The `Component inventory` section reads `Skills (1) hello`.
103The output lists `my-first-plugin@my-marketplace` with `Status: ✔ enabled`.
112104 
113 To run the skill, start a session and enter `/my-first-plugin:hello`. Claude greets you. The command has the plugin's name as a prefix, as every plugin skill's name does.
114 </Step>
115</Steps>
105To see what the plugin loaded, show its details.
106 
107```bash theme={null}
108claude plugin details my-first-plugin
109```
110 
111The `Component inventory` section reads `Skills (1) hello`.
112 
113To run the skill, start a session and enter `/my-first-plugin:hello`. Claude greets you. The command has the plugin's name as a prefix, as every plugin skill's name does.
116114 
117115## Add plugin entries
118116 
Feedback