SpyBara
Go Premium

Documentation 2026-03-19 06:17 UTC to 2026-03-20 21:05 UTC

23 files changed +863 −40. View all changes and history on the product overview
2026
Tue 31 21:09 Mon 30 21:13 Sat 28 18:04 Fri 27 21:09 Thu 26 21:07 Wed 25 21:08 Tue 24 18:15 Mon 23 21:08 Sun 22 18:04 Sat 21 18:03 Fri 20 21:05 Thu 19 06:17 Wed 18 18:16 Tue 17 21:10 Mon 16 21:10 Sat 14 03:44 Fri 13 21:07 Thu 12 21:07 Wed 11 03:43 Tue 10 03:43 Mon 9 21:06 Sat 7 03:37 Fri 6 06:10 Thu 5 06:12 Wed 4 21:06 Sun 1 06:10

channels.md +261 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Push events into a running session with channels

6 

7> Use channels to push messages, alerts, and webhooks into your Claude Code session from an MCP server. Forward CI results, chat messages, and monitoring events so Claude can react while you're away.

8 

9<Note>

10 Channels are in [research preview](#research-preview) and require Claude Code v2.1.80 or later. They require claude.ai login. Console and API key authentication is not supported. Team and Enterprise organizations must [explicitly enable them](#enterprise-controls).

11</Note>

12 

13A channel is an MCP server that pushes events into your running Claude Code session, so Claude can react to things that happen while you're not at the terminal. Channels can be two-way: Claude reads the event and replies back through the same channel, like a chat bridge. Events only arrive while the session is open, so for an always-on setup you run Claude in a background process or persistent terminal.

14 

15You install a channel as a plugin and configure it with your own credentials. Telegram and Discord are included in the research preview.

16 

17When Claude replies through a channel, you see the inbound message in your terminal but not the reply text. The terminal shows the tool call and a confirmation (like "sent"), and the actual reply appears on the other platform.

18 

19This page covers:

20 

21* [Supported channels](#supported-channels): Telegram and Discord setup

22* [Install and run a channel](#quickstart) with fakechat, a localhost demo

23* [Who can push messages](#security): sender allowlists and how you pair

24* [Enable channels for your organization](#enterprise-controls) on Team and Enterprise

25 

26To build your own channel, see the [Channels reference](/en/channels-reference).

27 

28## Supported channels

29 

30Each supported channel is a plugin that requires [Bun](https://bun.sh). For a hands-on demo of the plugin flow before connecting a real platform, try the [fakechat quickstart](#quickstart).

31 

32<Tabs>

33 <Tab title="Telegram">

34 View the full [Telegram plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram).

35 

36 <Steps>

37 <Step title="Create a Telegram bot">

38 Open [BotFather](https://t.me/BotFather) in Telegram and send `/newbot`. Give it a display name and a unique username ending in `bot`. Copy the token BotFather returns.

39 </Step>

40 

41 <Step title="Install the plugin">

42 In Claude Code, run:

43 

44 ```

45 /plugin install telegram@claude-plugins-official

46 ```

47 

48 If Claude Code reports that the plugin is not found in any marketplace, run `/plugin marketplace add anthropics/claude-plugins-official` first and retry the install.

49 </Step>

50 

51 <Step title="Configure your token">

52 Run the configure command with the token from BotFather:

53 

54 ```

55 /telegram:configure <token>

56 ```

57 

58 This saves it to `~/.claude/channels/telegram/.env`. You can also set `TELEGRAM_BOT_TOKEN` in your shell environment before launching Claude Code.

59 </Step>

60 

61 <Step title="Restart with channels enabled">

62 Exit Claude Code and restart with the channel flag. This starts the Telegram plugin, which begins polling for messages from your bot:

63 

64 ```bash theme={null}

65 claude --channels plugin:telegram@claude-plugins-official

66 ```

67 </Step>

68 

69 <Step title="Pair your account">

70 Open Telegram and send any message to your bot. The bot replies with a pairing code.

71 

72 <Note>If your bot doesn't respond, make sure Claude Code is running with `--channels` from the previous step. The bot can only reply while the channel is active.</Note>

73 

74 Back in Claude Code, run:

75 

76 ```

77 /telegram:access pair <code>

78 ```

79 

80 Then lock down access so only your account can send messages:

81 

82 ```

83 /telegram:access policy allowlist

84 ```

85 </Step>

86 </Steps>

87 </Tab>

88 

89 <Tab title="Discord">

90 View the full [Discord plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord).

91 

92 <Steps>

93 <Step title="Create a Discord bot">

94 Go to the [Discord Developer Portal](https://discord.com/developers/applications), click **New Application**, and name it. In the **Bot** section, create a username, then click **Reset Token** and copy the token.

95 </Step>

96 

97 <Step title="Enable Message Content Intent">

98 In your bot's settings, scroll to **Privileged Gateway Intents** and enable **Message Content Intent**.

99 </Step>

100 

101 <Step title="Invite the bot to your server">

102 Go to **OAuth2 > URL Generator**. Select the `bot` scope and enable these permissions:

103 

104 * View Channels

105 * Send Messages

106 * Send Messages in Threads

107 * Read Message History

108 * Attach Files

109 * Add Reactions

110 

111 Open the generated URL to add the bot to your server.

112 </Step>

113 

114 <Step title="Install the plugin">

115 In Claude Code, run:

116 

117 ```

118 /plugin install discord@claude-plugins-official

119 ```

120 

121 If Claude Code reports that the plugin is not found in any marketplace, run `/plugin marketplace add anthropics/claude-plugins-official` first and retry the install.

122 </Step>

123 

124 <Step title="Configure your token">

125 Run the configure command with the bot token you copied:

126 

127 ```

128 /discord:configure <token>

129 ```

130 

131 This saves it to `~/.claude/channels/discord/.env`. You can also set `DISCORD_BOT_TOKEN` in your shell environment before launching Claude Code.

132 </Step>

133 

134 <Step title="Restart with channels enabled">

135 Exit Claude Code and restart with the channel flag. This connects the Discord plugin so your bot can receive and respond to messages:

136 

137 ```bash theme={null}

138 claude --channels plugin:discord@claude-plugins-official

139 ```

140 </Step>

141 

142 <Step title="Pair your account">

143 DM your bot on Discord. The bot replies with a pairing code.

144 

145 <Note>If your bot doesn't respond, make sure Claude Code is running with `--channels` from the previous step. The bot can only reply while the channel is active.</Note>

146 

147 Back in Claude Code, run:

148 

149 ```

150 /discord:access pair <code>

151 ```

152 

153 Then lock down access so only your account can send messages:

154 

155 ```

156 /discord:access policy allowlist

157 ```

158 </Step>

159 </Steps>

160 </Tab>

161</Tabs>

162 

163You can also [build your own channel](/en/channels-reference) for systems that don't have a plugin yet.

164 

165## Quickstart

166 

167Fakechat is an officially supported demo channel that runs a chat UI on localhost, with nothing to authenticate and no external service to configure.

168 

169Once you install and enable fakechat, you can type in the browser and the message arrives in your Claude Code session. Claude replies, and the reply shows up back in the browser. After you've tested the fakechat interface, try out [Telegram](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram) or [Discord](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord).

170 

171To try the fakechat demo, you'll need:

172 

173* Claude Code [installed and authenticated](/en/quickstart#step-1-install-claude-code) with a claude.ai account

174* [Bun](https://bun.sh) installed. The pre-built channel plugins are Bun scripts. Check with `bun --version`; if that fails, [install Bun](https://bun.sh/docs/installation).

175* **Team/Enterprise users**: your organization admin must [enable channels](#enterprise-controls) in managed settings

176 

177<Steps>

178 <Step title="Install the fakechat channel plugin">

179 Start a Claude Code session and run the install command:

180 

181 ```text theme={null}

182 /plugin install fakechat@claude-plugins-official

183 ```

184 

185 If Claude Code reports that the plugin is not found in any marketplace, run `/plugin marketplace add anthropics/claude-plugins-official` first and retry the install.

186 </Step>

187 

188 <Step title="Restart with the channel enabled">

189 Exit Claude Code, then restart with `--channels` and pass the fakechat plugin you installed:

190 

191 ```bash theme={null}

192 claude --channels plugin:fakechat@claude-plugins-official

193 ```

194 

195 The fakechat server starts automatically.

196 

197 <Tip>

198 You can pass several plugins to `--channels`, space-separated.

199 </Tip>

200 </Step>

201 

202 <Step title="Push a message in">

203 Open the fakechat UI at [http://localhost:8787](http://localhost:8787) and type a message:

204 

205 ```text theme={null}

206 hey, what's in my working directory?

207 ```

208 

209 The message arrives in your Claude Code session as a `<channel source="fakechat">` event. Claude reads it, does the work, and calls fakechat's `reply` tool. The answer shows up in the chat UI.

210 </Step>

211</Steps>

212 

213If Claude hits a permission prompt while you're away from the terminal, the session pauses until you approve locally. For unattended use, [`--dangerously-skip-permissions`](/en/permissions#permission-modes) bypasses prompts, but only use it in environments you trust.

214 

215## Security

216 

217Every approved channel plugin maintains a sender allowlist: only IDs you've added can push messages, and everyone else is silently dropped.

218 

219Telegram and Discord bootstrap the list by pairing:

220 

2211. Find your bot in Telegram or Discord and send it any message

2222. The bot replies with a pairing code

2233. In your Claude Code session, approve the code when prompted

2244. Your sender ID is added to the allowlist

225 

226On top of that, you control which servers are enabled each session with `--channels`, and on Team and Enterprise plans your organization controls availability with [`channelsEnabled`](#enterprise-controls).

227 

228Being in `.mcp.json` isn't enough to push messages: a server also has to be named in `--channels`.

229 

230## Enterprise controls

231 

232Channels are controlled by the `channelsEnabled` setting in [managed settings](/en/settings).

233 

234| Plan type | Default behavior |

235| :------------------------- | :------------------------------------------------------------- |

236| Pro / Max, no organization | Channels available; users opt in per session with `--channels` |

237| Team / Enterprise | Channels disabled until an admin explicitly enables them |

238 

239### Enable channels for your organization

240 

241Admins can enable channels from [**claude.ai → Admin settings → Claude Code → Channels**](https://claude.ai/admin-settings/claude-code), or by setting `channelsEnabled` to `true` in managed settings.

242 

243Once enabled, users in your organization can use `--channels` to opt channel servers into individual sessions. If the setting is disabled or unset, the MCP server still connects and its tools work, but channel messages won't arrive. A startup warning tells the user to have an admin enable the setting.

244 

245## Research preview

246 

247Channels are a research preview feature. Availability is rolling out gradually, and the `--channels` flag syntax and protocol contract may change based on feedback.

248 

249During the preview, `--channels` only accepts plugins from an Anthropic-maintained allowlist. The channel plugins in [claude-plugins-official](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins) are the approved set. If you pass something that isn't, Claude Code starts normally but the channel doesn't register, and the startup notice tells you why.

250 

251To test a channel you're building, use `--dangerously-load-development-channels`. See [Test during the research preview](/en/channels-reference#test-during-the-research-preview) for information about testing custom channels that you build.

252 

253Report issues or feedback on the [Claude Code GitHub repository](https://github.com/anthropics/claude-code/issues).

254 

255## Next steps

256 

257Once you have a channel running, explore these related features:

258 

259* [Build your own channel](/en/channels-reference) for systems that don't have plugins yet

260* [Remote Control](/en/remote-control) to drive a local session from your phone instead of forwarding events into it

261* [Scheduled tasks](/en/scheduled-tasks) to poll on a timer instead of reacting to pushed events

channels-reference.md +403 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Channels reference

6 

7> Build an MCP server that pushes webhooks, alerts, and chat messages into a Claude Code session. Reference for the channel contract: capability declaration, notification events, reply tools, and sender gating.

8 

9<Note>

10 Channels are in [research preview](/en/channels#research-preview) and require Claude Code v2.1.80 or later. They require claude.ai login. Console and API key authentication is not supported. Team and Enterprise organizations must [explicitly enable them](/en/channels#enterprise-controls).

11</Note>

12 

13A channel is an MCP server that pushes events into a Claude Code session so Claude can react to things happening outside the terminal.

14 

15You can build a one-way or two-way channel. One-way channels forward alerts, webhooks, or monitoring events for Claude to act on. Two-way channels like chat bridges also [expose a reply tool](#expose-a-reply-tool) so Claude can send messages back.

16 

17This page covers:

18 

19* [Overview](#overview): how channels work

20* [What you need](#what-you-need): requirements and general steps

21* [Example: build a webhook receiver](#example-build-a-webhook-receiver): a minimal one-way walkthrough

22* [Server options](#server-options): the constructor fields

23* [Notification format](#notification-format): the event payload

24* [Expose a reply tool](#expose-a-reply-tool): let Claude send messages back

25* [Gate inbound messages](#gate-inbound-messages): sender checks to prevent prompt injection

26 

27To use an existing channel instead of building one, see [Channels](/en/channels). Telegram, Discord, and fakechat are included in the research preview.

28 

29## Overview

30 

31A channel is an [MCP](https://modelcontextprotocol.io) server that runs on the same machine as Claude Code. Claude Code spawns it as a subprocess and communicates over stdio. Your channel server is the bridge between external systems and the Claude Code session:

32 

33* **Chat platforms** (Telegram, Discord): your plugin runs locally and polls the platform's API for new messages. When someone DMs your bot, the plugin receives the message and forwards it to Claude. No URL to expose.

34* **Webhooks** (CI, monitoring): your server listens on a local HTTP port. External systems POST to that port, and your server pushes the payload to Claude.

35 

36<img src="https://mintcdn.com/claude-code/zbUxPYi8065L3Y_P/en/images/channel-architecture.svg?fit=max&auto=format&n=zbUxPYi8065L3Y_P&q=85&s=fd6b6b949eab38264043d2a96285a57c" alt="Architecture diagram showing external systems connecting to your local channel server, which communicates with Claude Code over stdio" width="600" height="220" data-path="en/images/channel-architecture.svg" />

37 

38## What you need

39 

40The only hard requirement is the [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) package and a Node.js-compatible runtime. [Bun](https://bun.sh), [Node](https://nodejs.org), and [Deno](https://deno.com) all work. The pre-built plugins in the research preview use Bun, but your channel doesn't have to.

41 

42Your server needs to:

43 

441. Declare the `claude/channel` capability so Claude Code registers a notification listener

452. Emit `notifications/claude/channel` events when something happens

463. Connect over [stdio transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-io) (Claude Code spawns your server as a subprocess)

47 

48The [Server options](#server-options) and [Notification format](#notification-format) sections cover each of these in detail. See [Example: build a webhook receiver](#example-build-a-webhook-receiver) for a full walkthrough.

49 

50During the research preview, custom channels aren't on the [approved allowlist](/en/channels#supported-channels). Use `--dangerously-load-development-channels` to test locally. See [Test during the research preview](#test-during-the-research-preview) for details.

51 

52## Example: build a webhook receiver

53 

54This walkthrough builds a single-file server that listens for HTTP requests and forwards them into your Claude Code session. By the end, anything that can send an HTTP POST, like a CI pipeline, a monitoring alert, or a `curl` command, can push events to Claude.

55 

56This example uses [Bun](https://bun.sh) as the runtime for its built-in HTTP server and TypeScript support. You can use [Node](https://nodejs.org) or [Deno](https://deno.com) instead; the only requirement is the [MCP SDK](https://www.npmjs.com/package/@modelcontextprotocol/sdk).

57 

58<Steps>

59 <Step title="Create the project">

60 Create a new directory and install the MCP SDK:

61 

62 ```bash theme={null}

63 mkdir webhook-channel && cd webhook-channel

64 bun add @modelcontextprotocol/sdk

65 ```

66 </Step>

67 

68 <Step title="Write the channel server">

69 Create a file called `webhook.ts`. This is your entire channel server: it connects to Claude Code over stdio, and it listens for HTTP POSTs on port 8788. When a request arrives, it pushes the body to Claude as a channel event.

70 

71 ```ts title="webhook.ts" theme={null}

72 #!/usr/bin/env bun

73 import { Server } from '@modelcontextprotocol/sdk/server/index.js'

74 import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'

75 

76 // Create the MCP server and declare it as a channel

77 const mcp = new Server(

78 { name: 'webhook', version: '0.0.1' },

79 {

80 // this key is what makes it a channel — Claude Code registers a listener for it

81 capabilities: { experimental: { 'claude/channel': {} } },

82 // added to Claude's system prompt so it knows how to handle these events

83 instructions: 'Events from the webhook channel arrive as <channel source="webhook" ...>. They are one-way: read them and act, no reply expected.',

84 },

85 )

86 

87 // Connect to Claude Code over stdio (Claude Code spawns this process)

88 await mcp.connect(new StdioServerTransport())

89 

90 // Start an HTTP server that forwards every POST to Claude

91 Bun.serve({

92 port: 8788, // any open port works

93 // localhost-only: nothing outside this machine can POST

94 hostname: '127.0.0.1',

95 async fetch(req) {

96 const body = await req.text()

97 await mcp.notification({

98 method: 'notifications/claude/channel',

99 params: {

100 content: body, // becomes the body of the <channel> tag

101 // each key becomes a tag attribute, e.g. <channel path="/" method="POST">

102 meta: { path: new URL(req.url).pathname, method: req.method },

103 },

104 })

105 return new Response('ok')

106 },

107 })

108 ```

109 

110 The file does three things in order:

111 

112 * **Server configuration**: creates the MCP server with `claude/channel` in its capabilities, which is what tells Claude Code this is a channel. The [`instructions`](#server-options) string goes into Claude's system prompt: tell Claude what events to expect, whether to reply, and how to route replies if it should.

113 * **Stdio connection**: connects to Claude Code over stdin/stdout. This is standard for any [MCP server](https://modelcontextprotocol.io/docs/concepts/transports#standard-io): Claude Code spawns it as a subprocess.

114 * **HTTP listener**: starts a local web server on port 8788. Every POST body gets forwarded to Claude as a channel event via `mcp.notification()`. The `content` becomes the event body, and each `meta` entry becomes an attribute on the `<channel>` tag. The listener needs access to the `mcp` instance, so it runs in the same process. You could split it into separate modules for a larger project.

115 </Step>

116 

117 <Step title="Register your server with Claude Code">

118 Add the server to `.mcp.json` so Claude Code knows how to start it. If you're adding it to a project-level `.mcp.json` in the same directory, use a relative path. If you're adding it to your user-level `~/.mcp.json`, use the full absolute path:

119 

120 ```json title=".mcp.json" theme={null}

121 {

122 "mcpServers": {

123 "webhook": { "command": "bun", "args": ["./webhook.ts"] }

124 }

125 }

126 ```

127 

128 Claude Code reads `.mcp.json` at startup and spawns each server as a subprocess.

129 </Step>

130 

131 <Step title="Test it">

132 During the research preview, custom channels aren't on the allowlist, so start Claude Code with the development flag:

133 

134 ```bash theme={null}

135 claude --dangerously-load-development-channels server:webhook

136 ```

137 

138 When Claude Code starts, it reads `.mcp.json`, spawns your `webhook.ts` as a subprocess, and the HTTP listener starts automatically on the port you configured (8788 in this example). You don't need to run the server yourself.

139 

140 If you see "blocked by org policy," your Team or Enterprise admin needs to [enable channels](/en/channels#enterprise-controls) first.

141 

142 In a separate terminal, simulate a webhook by sending an HTTP POST with a message to your server. This example sends a CI failure alert to port 8788 (or whichever port you configured):

143 

144 ```bash theme={null}

145 curl -X POST localhost:8788 -d "build failed on main: https://ci.example.com/run/1234"

146 ```

147 

148 The payload arrives in your Claude Code session as a `<channel>` tag:

149 

150 ```text theme={null}

151 <channel source="webhook" path="/" method="POST">build failed on main: https://ci.example.com/run/1234</channel>

152 ```

153 

154 In your Claude Code terminal, you'll see Claude receive the message and start responding: reading files, running commands, or whatever the message calls for. This is a one-way channel, so Claude acts in your session but doesn't send anything back through the webhook. To add replies, see [Expose a reply tool](#expose-a-reply-tool).

155 </Step>

156</Steps>

157 

158The [fakechat server](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/fakechat) extends this pattern with a web UI, file attachments, and a reply tool for two-way chat.

159 

160## Test during the research preview

161 

162During the research preview, every channel must be on the [approved allowlist](/en/channels#research-preview) to register. The development flag bypasses the allowlist for specific entries after a confirmation prompt. This example shows both entry types:

163 

164```bash theme={null}

165# Testing a plugin you're developing

166claude --dangerously-load-development-channels plugin:yourplugin@yourmarketplace

167 

168# Testing a bare .mcp.json server (no plugin wrapper yet)

169claude --dangerously-load-development-channels server:webhook

170```

171 

172The bypass is per-entry. Combining this flag with `--channels` doesn't extend the bypass to the `--channels` entries. During the research preview, the approved allowlist is Anthropic-curated, so your channel stays on the development flag while you build and test.

173 

174<Note>

175 This flag skips the allowlist only. The `channelsEnabled` organization policy still applies. Don't use it to run channels from untrusted sources.

176</Note>

177 

178## Server options

179 

180A channel sets these options in the [`Server`](https://modelcontextprotocol.io/docs/concepts/servers) constructor. The `instructions` and `capabilities.tools` fields are [standard MCP](https://modelcontextprotocol.io/docs/concepts/servers); `capabilities.experimental['claude/channel']` is the channel-specific addition:

181 

182| Field | Type | Description |

183| :-------------------------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

184| `capabilities.experimental['claude/channel']` | `object` | Required. Always `{}`. Presence registers the notification listener. |

185| `capabilities.tools` | `object` | Two-way only. Always `{}`. Standard MCP tool capability. See [Expose a reply tool](#expose-a-reply-tool). |

186| `instructions` | `string` | Recommended. Added to Claude's system prompt. Tell Claude what events to expect, what the `<channel>` tag attributes mean, whether to reply, and if so which tool to use and which attribute to pass back (like `chat_id`). |

187 

188To create a one-way channel, omit `capabilities.tools`. This example shows a two-way setup with all three options set:

189 

190```ts theme={null}

191import { Server } from '@modelcontextprotocol/sdk/server/index.js'

192 

193const mcp = new Server(

194 { name: 'your-channel', version: '0.0.1' },

195 {

196 capabilities: {

197 experimental: { 'claude/channel': {} }, // registers the channel listener

198 tools: {}, // omit for one-way channels

199 },

200 // added to Claude's system prompt so it knows how to handle your events

201 instructions: 'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.',

202 },

203)

204```

205 

206To push an event, call `mcp.notification()` with method `notifications/claude/channel`. The params are in the next section.

207 

208## Notification format

209 

210Your server emits `notifications/claude/channel` with two params:

211 

212| Field | Type | Description |

213| :-------- | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

214| `content` | `string` | The event body. Delivered as the body of the `<channel>` tag. |

215| `meta` | `Record<string, string>` | Optional. Each entry becomes an attribute on the `<channel>` tag for routing context like chat ID, sender name, or alert severity. Keys must be identifiers: letters, digits, and underscores only. Keys containing hyphens or other characters are silently dropped. |

216 

217Your server pushes events by calling `mcp.notification()` on the `Server` instance. This example pushes a CI failure alert with two meta keys:

218 

219```ts theme={null}

220await mcp.notification({

221 method: 'notifications/claude/channel',

222 params: {

223 content: 'build failed on main: https://ci.example.com/run/1234',

224 meta: { severity: 'high', run_id: '1234' },

225 },

226})

227```

228 

229The event arrives in Claude's context wrapped in a `<channel>` tag. The `source` attribute is set automatically from your server's configured name:

230 

231```text theme={null}

232<channel source="your-channel" severity="high" run_id="1234">

233build failed on main: https://ci.example.com/run/1234

234</channel>

235```

236 

237## Expose a reply tool

238 

239If your channel is two-way, like a chat bridge rather than an alert forwarder, expose a standard [MCP tool](https://modelcontextprotocol.io/docs/concepts/tools) that Claude can call to send messages back. Nothing about the tool registration is channel-specific. A reply tool has three components:

240 

2411. A `tools: {}` entry in your `Server` constructor capabilities so Claude Code discovers the tool

2422. Tool handlers that define the tool's schema and implement the send logic

2433. An `instructions` string in your `Server` constructor that tells Claude when and how to call the tool

244 

245To add these to the [webhook receiver above](#example-build-a-webhook-receiver):

246 

247<Steps>

248 <Step title="Enable tool discovery">

249 In your `Server` constructor in `webhook.ts`, add `tools: {}` to the capabilities so Claude Code knows your server offers tools:

250 

251 ```ts theme={null}

252 capabilities: {

253 experimental: { 'claude/channel': {} },

254 tools: {}, // enables tool discovery

255 },

256 ```

257 </Step>

258 

259 <Step title="Register the reply tool">

260 Add the following to `webhook.ts`. The `import` goes at the top of the file with your other imports; the two handlers go between the `Server` constructor and `mcp.connect()`. This registers a `reply` tool that Claude can call with a `chat_id` and `text`:

261 

262 ```ts theme={null}

263 // Add this import at the top of webhook.ts

264 import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'

265 

266 // Claude queries this at startup to discover what tools your server offers

267 mcp.setRequestHandler(ListToolsRequestSchema, async () => ({

268 tools: [{

269 name: 'reply',

270 description: 'Send a message back over this channel',

271 // inputSchema tells Claude what arguments to pass

272 inputSchema: {

273 type: 'object',

274 properties: {

275 chat_id: { type: 'string', description: 'The conversation to reply in' },

276 text: { type: 'string', description: 'The message to send' },

277 },

278 required: ['chat_id', 'text'],

279 },

280 }],

281 }))

282 

283 // Claude calls this when it wants to invoke a tool

284 mcp.setRequestHandler(CallToolRequestSchema, async req => {

285 if (req.params.name === 'reply') {

286 const { chat_id, text } = req.params.arguments as { chat_id: string; text: string }

287 // your platform's send API

288 await yourPlatform.send(chat_id, text)

289 return { content: [{ type: 'text', text: 'sent' }] }

290 }

291 throw new Error(`unknown tool: ${req.params.name}`)

292 })

293 ```

294 </Step>

295 

296 <Step title="Update the instructions">

297 Update the `instructions` string in your `Server` constructor so Claude knows to route replies back through the tool. This example tells Claude to pass `chat_id` from the inbound tag:

298 

299 ```ts theme={null}

300 instructions: 'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'

301 ```

302 </Step>

303</Steps>

304 

305Here's the complete `webhook.ts` with two-way support, combining the one-way receiver from the walkthrough with the reply tool additions:

306 

307```ts title="Full webhook.ts with reply tool" expandable theme={null}

308#!/usr/bin/env bun

309import { Server } from '@modelcontextprotocol/sdk/server/index.js'

310import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'

311import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'

312 

313const mcp = new Server(

314 { name: 'webhook', version: '0.0.1' },

315 {

316 capabilities: {

317 experimental: { 'claude/channel': {} },

318 tools: {},

319 },

320 instructions: 'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.',

321 },

322)

323 

324mcp.setRequestHandler(ListToolsRequestSchema, async () => ({

325 tools: [{

326 name: 'reply',

327 description: 'Send a message back over this channel',

328 inputSchema: {

329 type: 'object',

330 properties: {

331 chat_id: { type: 'string', description: 'The conversation to reply in' },

332 text: { type: 'string', description: 'The message to send' },

333 },

334 required: ['chat_id', 'text'],

335 },

336 }],

337}))

338 

339mcp.setRequestHandler(CallToolRequestSchema, async req => {

340 if (req.params.name === 'reply') {

341 const { chat_id, text } = req.params.arguments as { chat_id: string; text: string }

342 // your platform's send API — replace with your real integration

343 console.error(`Reply to ${chat_id}: ${text}`)

344 return { content: [{ type: 'text', text: 'sent' }] }

345 }

346 throw new Error(`unknown tool: ${req.params.name}`)

347})

348 

349await mcp.connect(new StdioServerTransport())

350 

351let nextId = 1

352Bun.serve({

353 port: 8788,

354 hostname: '127.0.0.1',

355 async fetch(req) {

356 const body = await req.text()

357 const chat_id = String(nextId++)

358 await mcp.notification({

359 method: 'notifications/claude/channel',

360 params: {

361 content: body,

362 meta: { chat_id, path: new URL(req.url).pathname, method: req.method },

363 },

364 })

365 return new Response('ok')

366 },

367})

368```

369 

370The [fakechat server](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/fakechat) shows a more complete example with file attachments and message editing.

371 

372## Gate inbound messages

373 

374An ungated channel is a prompt injection vector. Anyone who can reach your endpoint can put text in front of Claude. A channel listening to a chat platform or a public endpoint needs a real sender check before it emits anything.

375 

376Check the sender against an allowlist before calling `mcp.notification()`. This example drops any message from a sender not in the set:

377 

378```ts theme={null}

379const allowed = new Set(loadAllowlist()) // from your access.json or equivalent

380 

381// inside your message handler, before emitting:

382if (!allowed.has(message.from.id)) { // sender, not room

383 return // drop silently

384}

385await mcp.notification({ ... })

386```

387 

388Gate on the sender's identity, not the chat or room identity: `message.from.id` in the example, not `message.chat.id`. In group chats, these differ, and gating on the room would let anyone in an allowlisted group inject messages into the session.

389 

390The [Telegram](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/telegram) and [Discord](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord) channels gate on a sender allowlist the same way. They bootstrap the list by pairing: the user DMs the bot, the bot replies with a pairing code, the user approves it in their Claude Code session, and their platform ID is added. See either implementation for the full pairing flow.

391 

392## Package as a plugin

393 

394To make your channel installable and shareable, wrap it in a [plugin](/en/plugins) and publish it to a [marketplace](/en/plugin-marketplaces). Users install it with `/plugin install`, then enable it per session with `--channels plugin:<name>@<marketplace>`.

395 

396A channel published to your own marketplace still needs `--dangerously-load-development-channels` to run, since it isn't on the [approved allowlist](/en/channels#supported-channels). To get it added, [submit it to the official marketplace](/en/plugins#submit-your-plugin-to-the-official-marketplace). Channel plugins go through security review before being approved.

397 

398## See also

399 

400* [Channels](/en/channels) to install and use Telegram, Discord, or the fakechat demo, and to enable channels for a Team or Enterprise org

401* [Working channel implementations](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins) for complete server code with pairing flows, reply tools, and file attachments

402* [MCP](/en/mcp) for the underlying protocol that channel servers implement

403* [Plugins](/en/plugins) to package your channel so users can install it with `/plugin install`

Details

32Customize Claude Code's behavior with these command-line flags:32Customize Claude Code's behavior with these command-line flags:

33 33 

34| Flag | Description | Example |34| Flag | Description | Example |

35| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |35| :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |

36| `--add-dir` | Add additional working directories for Claude to access (validates each path exists as a directory) | `claude --add-dir ../apps ../lib` |36| `--add-dir` | Add additional working directories for Claude to access (validates each path exists as a directory) | `claude --add-dir ../apps ../lib` |

37| `--agent` | Specify an agent for the current session (overrides the `agent` setting) | `claude --agent my-custom-agent` |37| `--agent` | Specify an agent for the current session (overrides the `agent` setting) | `claude --agent my-custom-agent` |

38| `--agents` | Define custom subagents dynamically via JSON. Uses the same field names as subagent [frontmatter](/en/sub-agents#supported-frontmatter-fields), plus a `prompt` field for the agent's instructions | `claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a code reviewer"}}'` |38| `--agents` | Define custom subagents dynamically via JSON. Uses the same field names as subagent [frontmatter](/en/sub-agents#supported-frontmatter-fields), plus a `prompt` field for the agent's instructions | `claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a code reviewer"}}'` |


41| `--append-system-prompt` | Append custom text to the end of the default system prompt | `claude --append-system-prompt "Always use TypeScript"` |41| `--append-system-prompt` | Append custom text to the end of the default system prompt | `claude --append-system-prompt "Always use TypeScript"` |

42| `--append-system-prompt-file` | Load additional system prompt text from a file and append to the default prompt | `claude --append-system-prompt-file ./extra-rules.txt` |42| `--append-system-prompt-file` | Load additional system prompt text from a file and append to the default prompt | `claude --append-system-prompt-file ./extra-rules.txt` |

43| `--betas` | Beta headers to include in API requests (API key users only) | `claude --betas interleaved-thinking` |43| `--betas` | Beta headers to include in API requests (API key users only) | `claude --betas interleaved-thinking` |

44| `--channels` | (Research preview) MCP servers whose [channel](/en/channels) notifications Claude should listen for in this session. Space-separated list of `plugin:<name>@<marketplace>` entries. Requires Claude.ai authentication | `claude --channels plugin:my-notifier@my-marketplace` |

44| `--chrome` | Enable [Chrome browser integration](/en/chrome) for web automation and testing | `claude --chrome` |45| `--chrome` | Enable [Chrome browser integration](/en/chrome) for web automation and testing | `claude --chrome` |

45| `--continue`, `-c` | Load the most recent conversation in the current directory | `claude --continue` |46| `--continue`, `-c` | Load the most recent conversation in the current directory | `claude --continue` |

47| `--dangerously-load-development-channels` | Enable [channels](/en/channels-reference#test-during-the-research-preview) that are not on the approved allowlist, for local development. Accepts `plugin:<name>@<marketplace>` and `server:<name>` entries. Prompts for confirmation | `claude --dangerously-load-development-channels server:webhook` |

46| `--dangerously-skip-permissions` | Skip permission prompts (use with caution). See [permission modes](/en/permissions#permission-modes) for what this does and does not skip | `claude --dangerously-skip-permissions` |48| `--dangerously-skip-permissions` | Skip permission prompts (use with caution). See [permission modes](/en/permissions#permission-modes) for what this does and does not skip | `claude --dangerously-skip-permissions` |

47| `--debug` | Enable debug mode with optional category filtering (for example, `"api,hooks"` or `"!statsig,!file"`) | `claude --debug "api,mcp"` |49| `--debug` | Enable debug mode with optional category filtering (for example, `"api,hooks"` or `"!statsig,!file"`) | `claude --debug "api,mcp"` |

48| `--disable-slash-commands` | Disable all skills and commands for this session | `claude --disable-slash-commands` |50| `--disable-slash-commands` | Disable all skills and commands for this session | `claude --disable-slash-commands` |

Details

28 28 

29## Official Anthropic marketplace29## Official Anthropic marketplace

30 30 

31The official Anthropic marketplace (`claude-plugins-official`) is automatically available when you start Claude Code. Run `/plugin` and go to the **Discover** tab to browse what's available.31The official Anthropic marketplace (`claude-plugins-official`) is automatically available when you start Claude Code. Run `/plugin` and go to the **Discover** tab to browse what's available, or view the catalog at [claude.com/plugins](https://claude.com/plugins).

32 32 

33To install a plugin from the official marketplace:33To install a plugin from the official marketplace, use `/plugin install <name>@claude-plugins-official`. For example, to install the GitHub integration:

34 34 

35```shell theme={null}35```shell theme={null}

36/plugin install plugin-name@claude-plugins-official36/plugin install github@claude-plugins-official

37```37```

38 38 

39<Note>39<Note>


302/reload-plugins302/reload-plugins

303```303```

304 304 

305Claude Code reloads all active plugins and shows counts for reloaded commands, skills, agents, hooks, plugin MCP servers, and plugin LSP servers.305Claude Code reloads all active plugins and shows counts for plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers.

306 306 

307## Manage marketplaces307## Manage marketplaces

308 308 

env-vars.md +1 −1

Details

67| `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS` | Timeout in milliseconds for git operations when installing or updating plugins (default: 120000). Increase this value for large repositories or slow network connections. See [Git operations time out](/en/plugin-marketplaces#git-operations-time-out) |67| `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS` | Timeout in milliseconds for git operations when installing or updating plugins (default: 120000). Increase this value for large repositories or slow network connections. See [Git operations time out](/en/plugin-marketplaces#git-operations-time-out) |

68| `CLAUDE_CODE_PLUGIN_SEED_DIR` | Path to one or more read-only plugin seed directories, separated by `:` on Unix or `;` on Windows. Use this to bundle a pre-populated plugins directory into a container image. Claude Code registers marketplaces from these directories at startup and uses pre-cached plugins without re-cloning. See [Pre-populate plugins for containers](/en/plugin-marketplaces#pre-populate-plugins-for-containers) |68| `CLAUDE_CODE_PLUGIN_SEED_DIR` | Path to one or more read-only plugin seed directories, separated by `:` on Unix or `;` on Windows. Use this to bundle a pre-populated plugins directory into a container image. Claude Code registers marketplaces from these directories at startup and uses pre-cached plugins without re-cloning. See [Pre-populate plugins for containers](/en/plugin-marketplaces#pre-populate-plugins-for-containers) |

69| `CLAUDE_CODE_PROXY_RESOLVES_HOSTS` | Set to `true` to allow the proxy to perform DNS resolution instead of the caller. Opt-in for environments where the proxy should handle hostname resolution |69| `CLAUDE_CODE_PROXY_RESOLVES_HOSTS` | Set to `true` to allow the proxy to perform DNS resolution instead of the caller. Opt-in for environments where the proxy should handle hostname resolution |

70| `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | Maximum time in milliseconds for [SessionEnd](/en/hooks#sessionend) hooks to complete (default: `1500`). Applies to both session exit and `/clear`. Per-hook `timeout` values are also capped by this budget |70| `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | Maximum time in milliseconds for [SessionEnd](/en/hooks#sessionend) hooks to complete (default: `1500`). Applies to session exit, `/clear`, and switching sessions via interactive `/resume`. Per-hook `timeout` values are also capped by this budget |

71| `CLAUDE_CODE_SHELL` | Override automatic shell detection. Useful when your login shell differs from your preferred working shell (for example, `bash` vs `zsh`) |71| `CLAUDE_CODE_SHELL` | Override automatic shell detection. Useful when your login shell differs from your preferred working shell (for example, `bash` vs `zsh`) |

72| `CLAUDE_CODE_SHELL_PREFIX` | Command prefix to wrap all bash commands (for example, for logging or auditing). Example: `/path/to/logger.sh` will execute `/path/to/logger.sh <command>` |72| `CLAUDE_CODE_SHELL_PREFIX` | Command prefix to wrap all bash commands (for example, for logging or auditing). Example: `/path/to/logger.sh` will execute `/path/to/logger.sh <command>` |

73| `CLAUDE_CODE_SIMPLE` | Set to `1` to run with a minimal system prompt and only the Bash, file read, and file edit tools. Disables MCP tools, attachments, hooks, and CLAUDE.md files |73| `CLAUDE_CODE_SIMPLE` | Set to `1` to run with a minimal system prompt and only the Bash, file read, and file edit tools. Disables MCP tools, attachments, hooks, and CLAUDE.md files |

Details

148 148 

149Features can be defined at multiple levels: user-wide, per-project, via plugins, or through managed policies. You can also nest CLAUDE.md files in subdirectories or place skills in specific packages of a monorepo. When the same feature exists at multiple levels, here's how they layer:149Features can be defined at multiple levels: user-wide, per-project, via plugins, or through managed policies. You can also nest CLAUDE.md files in subdirectories or place skills in specific packages of a monorepo. When the same feature exists at multiple levels, here's how they layer:

150 150 

151* **CLAUDE.md files** are additive: all levels contribute content to Claude's context simultaneously. Files from your working directory and above load at launch; subdirectories load as you work in them. When instructions conflict, Claude uses judgment to reconcile them, with more specific instructions typically taking precedence. See [how CLAUDE.md files load](/en/memory#how-claudemd-files-load).151* **CLAUDE.md files** are additive: all levels contribute content to Claude's context simultaneously. Files from your working directory and above load at launch; subdirectories load as you work in them. When instructions conflict, Claude uses judgment to reconcile them, with more specific instructions typically taking precedence. See [how CLAUDE.md files load](/en/memory#how-claude-md-files-load).

152* **Skills and subagents** override by name: when the same name exists at multiple levels, one definition wins based on priority (managed > user > project for skills; managed > CLI flag > project > user > plugin for subagents). Plugin skills are [namespaced](/en/plugins#add-skills-to-your-plugin) to avoid conflicts. See [skill discovery](/en/skills#where-skills-live) and [subagent scope](/en/sub-agents#choose-the-subagent-scope).152* **Skills and subagents** override by name: when the same name exists at multiple levels, one definition wins based on priority (managed > user > project for skills; managed > CLI flag > project > user > plugin for subagents). Plugin skills are [namespaced](/en/plugins#add-skills-to-your-plugin) to avoid conflicts. See [skill discovery](/en/skills#where-skills-live) and [subagent scope](/en/sub-agents#choose-the-subagent-scope).

153* **MCP servers** override by name: local > project > user. See [MCP scope](/en/mcp#scope-hierarchy-and-precedence).153* **MCP servers** override by name: local > project > user. See [MCP scope](/en/mcp#scope-hierarchy-and-precedence).

154* **Hooks** merge: all registered hooks fire for their matching events regardless of source. See [hooks](/en/hooks).154* **Hooks** merge: all registered hooks fire for their matching events regardless of source. See [hooks](/en/hooks).


196 196 

197 **What loads:** Full content of all CLAUDE.md files (managed, user, and project levels).197 **What loads:** Full content of all CLAUDE.md files (managed, user, and project levels).

198 198 

199 **Inheritance:** Claude reads CLAUDE.md files from your working directory up to the root, and discovers nested ones in subdirectories as it accesses those files. See [How CLAUDE.md files load](/en/memory#how-claudemd-files-load) for details.199 **Inheritance:** Claude reads CLAUDE.md files from your working directory up to the root, and discovers nested ones in subdirectories as it accesses those files. See [How CLAUDE.md files load](/en/memory#how-claude-md-files-load) for details.

200 200 

201 <Tip>Keep CLAUDE.md under \~500 lines. Move reference material to skills, which load on-demand.</Tip>201 <Tip>Keep CLAUDE.md under \~500 lines. Move reference material to skills, which load on-demand.</Tip>

202 </Tab>202 </Tab>

hooks.md +3 −2

Details

170| :---------------------------------------------------------------------------------------------- | :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |170| :---------------------------------------------------------------------------------------------- | :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |

171| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |171| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |

172| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact` |172| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact` |

173| `SessionEnd` | why the session ended | `clear`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |173| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |

174| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |174| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |

175| `SubagentStart` | agent type | `Bash`, `Explore`, `Plan`, or custom agent names |175| `SubagentStart` | agent type | `Bash`, `Explore`, `Plan`, or custom agent names |

176| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |176| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |


1645| Reason | Description |1645| Reason | Description |

1646| :---------------------------- | :----------------------------------------- |1646| :---------------------------- | :----------------------------------------- |

1647| `clear` | Session cleared with `/clear` command |1647| `clear` | Session cleared with `/clear` command |

1648| `resume` | Session switched via interactive `/resume` |

1648| `logout` | User logged out |1649| `logout` | User logged out |

1649| `prompt_input_exit` | User exited while prompt input was visible |1650| `prompt_input_exit` | User exited while prompt input was visible |

1650| `bypass_permissions_disabled` | Bypass permissions mode was disabled |1651| `bypass_permissions_disabled` | Bypass permissions mode was disabled |


1666 1667 

1667SessionEnd hooks have no decision control. They cannot block session termination but can perform cleanup tasks.1668SessionEnd hooks have no decision control. They cannot block session termination but can perform cleanup tasks.

1668 1669 

1669SessionEnd hooks have a default timeout of 1.5 seconds. This applies to both session exit and `/clear`. If your hooks need more time, set the `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` environment variable to a higher value in milliseconds. Any per-hook `timeout` setting is also capped by this value.1670SessionEnd hooks have a default timeout of 1.5 seconds. This applies to session exit, `/clear`, and switching sessions via interactive `/resume`. If your hooks need more time, set the `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` environment variable to a higher value in milliseconds. Any per-hook `timeout` setting is also capped by this value.

1670 1671 

1671```bash theme={null}1672```bash theme={null}

1672CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude1673CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude

hooks-guide.md +1 −1

Details

467| :---------------------------------------------------------------------------------------------- | :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |467| :---------------------------------------------------------------------------------------------- | :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |

468| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |468| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |

469| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact` |469| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact` |

470| `SessionEnd` | why the session ended | `clear`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |470| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |

471| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |471| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |

472| `SubagentStart` | agent type | `Bash`, `Explore`, `Plan`, or custom agent names |472| `SubagentStart` | agent type | `Bash`, `Explore`, `Plan`, or custom agent names |

473| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |473| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |

mcp.md +5 −0

Details

223* **Query databases**: "Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database."223* **Query databases**: "Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database."

224* **Integrate designs**: "Update our standard email template based on the new Figma designs that were posted in Slack"224* **Integrate designs**: "Update our standard email template based on the new Figma designs that were posted in Slack"

225* **Automate workflows**: "Create Gmail drafts inviting these 10 users to a feedback session about the new feature."225* **Automate workflows**: "Create Gmail drafts inviting these 10 users to a feedback session about the new feature."

226* **React to external events**: An MCP server can also act as a [channel](/en/channels) that pushes messages into your session, so Claude reacts to Telegram messages, Discord chats, or webhook events while you're away.

226 227 

227## Popular MCP servers228## Popular MCP servers

228 229 


328 329 

329Claude Code supports MCP `list_changed` notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a `list_changed` notification, Claude Code automatically refreshes the available capabilities from that server.330Claude Code supports MCP `list_changed` notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a `list_changed` notification, Claude Code automatically refreshes the available capabilities from that server.

330 331 

332### Push messages with channels

333 

334An MCP server can also push messages directly into your session so Claude can react to external events like CI results, monitoring alerts, or chat messages. To enable this, your server declares the `claude/channel` capability and you opt it in with the `--channels` flag at startup. See [Channels](/en/channels) to use an officially supported channel, or [Channels reference](/en/channels-reference) to build your own.

335 

331<Tip>336<Tip>

332 Tips:337 Tips:

333 338 

memory.md +5 −5

Details

13 13 

14This page covers how to:14This page covers how to:

15 15 

16* [Write and organize CLAUDE.md files](#claudemd-files)16* [Write and organize CLAUDE.md files](#claude-md-files)

17* [Scope rules to specific file types](#organize-rules-with-clauderules) with `.claude/rules/`17* [Scope rules to specific file types](#organize-rules-with-clauderules) with `.claude/rules/`

18* [Configure auto memory](#auto-memory) so Claude takes notes automatically18* [Configure auto memory](#auto-memory) so Claude takes notes automatically

19* [Troubleshoot](#troubleshoot-memory-issues) when instructions aren't being followed19* [Troubleshoot](#troubleshoot-memory-issues) when instructions aren't being followed


48| **Project instructions** | `./CLAUDE.md` or `./.claude/CLAUDE.md` | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |48| **Project instructions** | `./CLAUDE.md` or `./.claude/CLAUDE.md` | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |

49| **User instructions** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Just you (all projects) |49| **User instructions** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Just you (all projects) |

50 50 

51CLAUDE.md files in the directory hierarchy above the working directory are loaded in full at launch. CLAUDE.md files in subdirectories load on demand when Claude reads files in those directories. See [How CLAUDE.md files load](#how-claudemd-files-load) for the full resolution order.51CLAUDE.md files in the directory hierarchy above the working directory are loaded in full at launch. CLAUDE.md files in subdirectories load on demand when Claude reads files in those directories. See [How CLAUDE.md files load](#how-claude-md-files-load) for the full resolution order.

52 52 

53For large projects, you can break instructions into topic-specific files using [project rules](#organize-rules-with-clauderules). Rules let you scope instructions to specific file types or subdirectories.53For large projects, you can break instructions into topic-specific files using [project rules](#organize-rules-with-clauderules). Rules let you scope instructions to specific file types or subdirectories.

54 54 


76* "Run `npm test` before committing" instead of "Test your changes"76* "Run `npm test` before committing" instead of "Test your changes"

77* "API handlers live in `src/api/handlers/`" instead of "Keep files organized"77* "API handlers live in `src/api/handlers/`" instead of "Keep files organized"

78 78 

79**Consistency**: if two rules contradict each other, Claude may pick one arbitrarily. Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and [`.claude/rules/`](#organize-rules-with-clauderules) periodically to remove outdated or conflicting instructions. In monorepos, use [`claudeMdExcludes`](#exclude-specific-claudemd-files) to skip CLAUDE.md files from other teams that aren't relevant to your work.79**Consistency**: if two rules contradict each other, Claude may pick one arbitrarily. Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and [`.claude/rules/`](#organize-rules-with-clauderules) periodically to remove outdated or conflicting instructions. In monorepos, use [`claudeMdExcludes`](#exclude-specific-claude-md-files) to skip CLAUDE.md files from other teams that aren't relevant to your work.

80 80 

81### Import additional files81### Import additional files

82 82 


112 112 

113Claude also discovers CLAUDE.md files in subdirectories under your current working directory. Instead of loading them at launch, they are included when Claude reads files in those subdirectories.113Claude also discovers CLAUDE.md files in subdirectories under your current working directory. Instead of loading them at launch, they are included when Claude reads files in those subdirectories.

114 114 

115If you work in a large monorepo where other teams' CLAUDE.md files get picked up, use [`claudeMdExcludes`](#exclude-specific-claudemd-files) to skip them.115If you work in a large monorepo where other teams' CLAUDE.md files get picked up, use [`claudeMdExcludes`](#exclude-specific-claude-md-files) to skip them.

116 116 

117#### Load from additional directories117#### Load from additional directories

118 118 


342To debug:342To debug:

343 343 

344* Run `/memory` to verify your CLAUDE.md files are being loaded. If a file isn't listed, Claude can't see it.344* Run `/memory` to verify your CLAUDE.md files are being loaded. If a file isn't listed, Claude can't see it.

345* Check that the relevant CLAUDE.md is in a location that gets loaded for your session (see [Choose where to put CLAUDE.md files](#choose-where-to-put-claudemd-files)).345* Check that the relevant CLAUDE.md is in a location that gets loaded for your session (see [Choose where to put CLAUDE.md files](#choose-where-to-put-claude-md-files)).

346* Make instructions more specific. "Use 2-space indentation" works better than "format code nicely."346* Make instructions more specific. "Use 2-space indentation" works better than "format code nicely."

347* Look for conflicting instructions across CLAUDE.md files. If two files give different guidance for the same behavior, Claude may pick one arbitrarily.347* Look for conflicting instructions across CLAUDE.md files. If two files give different guidance for the same behavior, Claude may pick one arbitrarily.

348 348 

model-config.md +2 −1

Details

140* **`--effort` flag**: pass `low`, `medium`, `high`, or `max` to set the level for a single session when launching Claude Code140* **`--effort` flag**: pass `low`, `medium`, `high`, or `max` to set the level for a single session when launching Claude Code

141* **Environment variable**: set `CLAUDE_CODE_EFFORT_LEVEL` to `low`, `medium`, `high`, `max`, or `auto`141* **Environment variable**: set `CLAUDE_CODE_EFFORT_LEVEL` to `low`, `medium`, `high`, `max`, or `auto`

142* **Settings**: set `effortLevel` in your settings file to `"low"`, `"medium"`, or `"high"`142* **Settings**: set `effortLevel` in your settings file to `"low"`, `"medium"`, or `"high"`

143* **Skill and subagent frontmatter**: set `effort` in a [skill](/en/skills#frontmatter-reference) or [subagent](/en/sub-agents#supported-frontmatter-fields) markdown file to override the effort level when that skill or subagent runs

143 144 

144The environment variable takes precedence, then your configured level, then the model default.145The environment variable takes precedence over all other methods, then your configured level, then the model default. Frontmatter effort applies when that skill or subagent is active, overriding the session level but not the environment variable.

145 146 

146Effort is supported on Opus 4.6 and Sonnet 4.6. The effort slider appears in `/model` when a supported model is selected. The current effort level is also displayed next to the logo and spinner, for example "with low effort", so you can confirm which setting is active without opening `/model`.147Effort is supported on Opus 4.6 and Sonnet 4.6. The effort slider appears in `/model` when a supported model is selected. The current effort level is also displayed next to the logo and spinner, for example "with low effort", so you can confirm which setting is active without opening `/model`.

147 148 

overview.md +7 −6

Details

22 <Tab title="Native Install (Recommended)">22 <Tab title="Native Install (Recommended)">

23 **macOS, Linux, WSL:**23 **macOS, Linux, WSL:**

24 24 

25 ```bash theme={null}25 ```bash theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}

26 curl -fsSL https://claude.ai/install.sh | bash26 curl -fsSL https://claude.ai/install.sh | bash

27 ```27 ```

28 28 

29 **Windows PowerShell:**29 **Windows PowerShell:**

30 30 

31 ```powershell theme={null}31 ```powershell theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}

32 irm https://claude.ai/install.ps1 | iex32 irm https://claude.ai/install.ps1 | iex

33 ```33 ```

34 34 

35 **Windows CMD:**35 **Windows CMD:**

36 36 

37 ```batch theme={null}37 ```batch theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}

38 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd38 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

39 ```39 ```

40 40 


46 </Tab>46 </Tab>

47 47 

48 <Tab title="Homebrew">48 <Tab title="Homebrew">

49 ```bash theme={null}49 ```bash theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}

50 brew install --cask claude-code50 brew install --cask claude-code

51 ```51 ```

52 52 


56 </Tab>56 </Tab>

57 57 

58 <Tab title="WinGet">58 <Tab title="WinGet">

59 ```powershell theme={null}59 ```powershell theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}

60 winget install Anthropic.ClaudeCode60 winget install Anthropic.ClaudeCode

61 ```61 ```

62 62 


203Beyond the [Terminal](/en/quickstart), [VS Code](/en/vs-code), [JetBrains](/en/jetbrains), [Desktop](/en/desktop), and [Web](/en/claude-code-on-the-web) environments above, Claude Code integrates with CI/CD, chat, and browser workflows:203Beyond the [Terminal](/en/quickstart), [VS Code](/en/vs-code), [JetBrains](/en/jetbrains), [Desktop](/en/desktop), and [Web](/en/claude-code-on-the-web) environments above, Claude Code integrates with CI/CD, chat, and browser workflows:

204 204 

205| I want to... | Best option |205| I want to... | Best option |

206| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |206| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |

207| Continue a local session from my phone or another device | [Remote Control](/en/remote-control) |207| Continue a local session from my phone or another device | [Remote Control](/en/remote-control) |

208| Push events from Telegram, Discord, or my own webhooks into a session | [Channels](/en/channels) |

208| Start a task locally, continue on mobile | [Web](/en/claude-code-on-the-web) or [Claude iOS app](https://apps.apple.com/app/claude-by-anthropic/id6473753684) |209| Start a task locally, continue on mobile | [Web](/en/claude-code-on-the-web) or [Claude iOS app](https://apps.apple.com/app/claude-by-anthropic/id6473753684) |

209| Automate PR reviews and issue triage | [GitHub Actions](/en/github-actions) or [GitLab CI/CD](/en/gitlab-ci-cd) |210| Automate PR reviews and issue triage | [GitHub Actions](/en/github-actions) or [GitLab CI/CD](/en/gitlab-ci-cd) |

210| Get automatic code review on every PR | [GitHub Code Review](/en/code-review) |211| Get automatic code review on every PR | [GitHub Code Review](/en/code-review) |

permissions.md +4 −1

Details

241| `sandbox.network.allowManagedDomainsOnly` | When `true`, only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings are respected. Non-allowed domains are blocked automatically without prompting the user. Denied domains still merge from all sources |241| `sandbox.network.allowManagedDomainsOnly` | When `true`, only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings are respected. Non-allowed domains are blocked automatically without prompting the user. Denied domains still merge from all sources |

242| `sandbox.filesystem.allowManagedReadPathsOnly` | When `true`, only `allowRead` paths from managed settings are respected. `allowRead` entries from user, project, and local settings are ignored |242| `sandbox.filesystem.allowManagedReadPathsOnly` | When `true`, only `allowRead` paths from managed settings are respected. `allowRead` entries from user, project, and local settings are ignored |

243| `strictKnownMarketplaces` | Controls which plugin marketplaces users can add. See [managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) |243| `strictKnownMarketplaces` | Controls which plugin marketplaces users can add. See [managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) |

244| `allow_remote_sessions` | When `true`, allows users to start [Remote Control](/en/remote-control) and [web sessions](/en/claude-code-on-the-web). Defaults to `true`. Set to `false` to prevent remote session access |244 

245<Note>

246 Access to [Remote Control](/en/remote-control) and [web sessions](/en/claude-code-on-the-web) is not controlled by a managed settings key. On Team and Enterprise plans, an admin enables or disables these features in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).

247</Note>

245 248 

246## Settings precedence249## Settings precedence

247 250 

Details

157| `plugins` | array | List of available plugins | See below |157| `plugins` | array | List of available plugins | See below |

158 158 

159<Note>159<Note>

160 **Reserved names**: The following marketplace names are reserved for official Anthropic use and cannot be used by third-party marketplaces: `claude-code-marketplace`, `claude-code-plugins`, `claude-plugins-official`, `anthropic-marketplace`, `anthropic-plugins`, `agent-skills`, `life-sciences`. Names that impersonate official marketplaces (like `official-claude-plugins` or `anthropic-tools-v2`) are also blocked.160 **Reserved names**: The following marketplace names are reserved for official Anthropic use and cannot be used by third-party marketplaces: `claude-code-marketplace`, `claude-code-plugins`, `claude-plugins-official`, `anthropic-marketplace`, `anthropic-plugins`, `agent-skills`, `knowledge-work-plugins`, `life-sciences`. Names that impersonate official marketplaces (like `official-claude-plugins` or `anthropic-tools-v2`) are also blocked.

161</Note>161</Note>

162 162 

163### Owner fields163### Owner fields


226| `url` | object | `url`, `ref?`, `sha?` | Git URL source |226| `url` | object | `url`, `ref?`, `sha?` | Git URL source |

227| `git-subdir` | object | `url`, `path`, `ref?`, `sha?` | Subdirectory within a git repo. Clones sparsely to minimize bandwidth for monorepos |227| `git-subdir` | object | `url`, `path`, `ref?`, `sha?` | Subdirectory within a git repo. Clones sparsely to minimize bandwidth for monorepos |

228| `npm` | object | `package`, `version?`, `registry?` | Installed via `npm install` |228| `npm` | object | `package`, `version?`, `registry?` | Installed via `npm install` |

229| `pip` | object | `package`, `version?`, `registry?` | Installed via pip |

230 229 

231<Note>230<Note>

232 **Marketplace sources vs plugin sources**: These are different concepts that control different things.231 **Marketplace sources vs plugin sources**: These are different concepts that control different things.

plugins.md +1 −1

Details

283 283 

284When a `--plugin-dir` plugin has the same name as an installed marketplace plugin, the local copy takes precedence for that session. This lets you test changes to a plugin you already have installed without uninstalling it first. Marketplace plugins force-enabled by managed settings are the only exception and cannot be overridden.284When a `--plugin-dir` plugin has the same name as an installed marketplace plugin, the local copy takes precedence for that session. This lets you test changes to a plugin you already have installed without uninstalling it first. Marketplace plugins force-enabled by managed settings are the only exception and cannot be overridden.

285 285 

286As you make changes to your plugin, run `/reload-plugins` to pick up the updates without restarting. This reloads commands, skills, agents, hooks, plugin MCP servers, and plugin LSP servers. Test your plugin components:286As you make changes to your plugin, run `/reload-plugins` to pick up the updates without restarting. This reloads plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers. Test your plugin components:

287 287 

288* Try your skills with `/plugin-name:skill-name`288* Try your skills with `/plugin-name:skill-name`

289* Check that agents appear in `/agents`289* Check that agents appear in `/agents`

Details

171## Related resources171## Related resources

172 172 

173* [Claude Code on the web](/en/claude-code-on-the-web): run sessions in Anthropic-managed cloud environments instead of on your machine173* [Claude Code on the web](/en/claude-code-on-the-web): run sessions in Anthropic-managed cloud environments instead of on your machine

174* [Channels](/en/channels): forward Telegram or Discord into a session so Claude reacts to messages while you're away

174* [Authentication](/en/authentication): set up `/login` and manage credentials for claude.ai175* [Authentication](/en/authentication): set up `/login` and manage credentials for claude.ai

175* [CLI reference](/en/cli-reference): full list of flags and commands including `claude remote-control`176* [CLI reference](/en/cli-reference): full list of flags and commands including `claude remote-control`

176* [Security](/en/security): how Remote Control sessions fit into the Claude Code security model177* [Security](/en/security): how Remote Control sessions fit into the Claude Code security model

sandboxing.md +3 −1

Details

146 146 

147You can also deny write or read access using `sandbox.filesystem.denyWrite` and `sandbox.filesystem.denyRead`. These are merged with any paths from `Edit(...)` and `Read(...)` permission rules. To re-allow reading specific paths within a denied region, use `sandbox.filesystem.allowRead`, which takes precedence over `denyRead`. When `allowManagedReadPathsOnly` is enabled in managed settings, only managed `allowRead` entries are respected; user, project, and local `allowRead` entries are ignored.147You can also deny write or read access using `sandbox.filesystem.denyWrite` and `sandbox.filesystem.denyRead`. These are merged with any paths from `Edit(...)` and `Read(...)` permission rules. To re-allow reading specific paths within a denied region, use `sandbox.filesystem.allowRead`, which takes precedence over `denyRead`. When `allowManagedReadPathsOnly` is enabled in managed settings, only managed `allowRead` entries are respected; user, project, and local `allowRead` entries are ignored.

148 148 

149For example, to block reading from the entire home directory while still allowing reads from the current project:149For example, to block reading from the entire home directory while still allowing reads from the current project, add this to your project's `.claude/settings.json`:

150 150 

151```json theme={null}151```json theme={null}

152{152{


160}160}

161```161```

162 162 

163The `.` in `allowRead` resolves to the project root because this configuration lives in project settings. If you placed the same configuration in `~/.claude/settings.json`, `.` would resolve to `~/.claude` instead, and project files would remain blocked by the `denyRead` rule.

164 

163<Tip>165<Tip>

164 Not all commands are compatible with sandboxing out of the box. Some notes that may help you make the most out of the sandbox:166 Not all commands are compatible with sandboxing out of the box. Some notes that may help you make the most out of the sandbox:

165 167 

Details

10 Scheduled tasks require Claude Code v2.1.72 or later. Check your version with `claude --version`.10 Scheduled tasks require Claude Code v2.1.72 or later. Check your version with `claude --version`.

11</Note>11</Note>

12 12 

13Scheduled tasks let Claude re-run a prompt automatically on an interval. Use them to poll a deployment, babysit a PR, check back on a long-running build, or remind yourself to do something later in the session.13Scheduled tasks let Claude re-run a prompt automatically on an interval. Use them to poll a deployment, babysit a PR, check back on a long-running build, or remind yourself to do something later in the session. To react to events as they happen instead of polling, see [Channels](/en/channels): your CI can push the failure into the session directly.

14 14 

15Tasks are session-scoped: they live in the current Claude Code process and are gone when you exit. For durable scheduling that survives restarts and runs without an active terminal session, see [Desktop scheduled tasks](/en/desktop#schedule-recurring-tasks) or [GitHub Actions](/en/github-actions).15Tasks are session-scoped: they live in the current Claude Code process and are gone when you exit. For durable scheduling that survives restarts and runs without an active terminal session, see [Desktop scheduled tasks](/en/desktop#schedule-recurring-tasks) or [GitHub Actions](/en/github-actions).

16 16 

Details

41 </Step>41 </Step>

42 42 

43 <Step title="Define your settings">43 <Step title="Define your settings">

44 Add your configuration as JSON. All [settings available in `settings.json`](/en/settings#available-settings) are supported, including [managed-only settings](/en/permissions#managed-only-settings) like `disableBypassPermissionsMode`.44 Add your configuration as JSON. All [settings available in `settings.json`](/en/settings#available-settings) are supported, including [hooks](/en/hooks), [environment variables](/en/env-vars), and [managed-only settings](/en/permissions#managed-only-settings) like `disableBypassPermissionsMode`.

45 45 

46 This example enforces a permission deny list and prevents users from bypassing permissions:46 This example enforces a permission deny list and prevents users from bypassing permissions:

47 47 


58 }58 }

59 }59 }

60 ```60 ```

61 

62 Hooks use the same format as in `settings.json`.

63 

64 This example runs an audit script after every file edit across the organization:

65 

66 ```json theme={null}

67 {

68 "hooks": {

69 "PostToolUse": [

70 {

71 "matcher": "Edit|Write",

72 "hooks": [

73 { "type": "command", "command": "/usr/local/bin/audit-edit.sh" }

74 ]

75 }

76 ]

77 }

78 }

79 ```

80 

81 Because hooks execute shell commands, users see a [security approval dialog](#security-approval-dialogs) before they're applied.

61 </Step>82 </Step>

62 83 

63 <Step title="Save and deploy">84 <Step title="Save and deploy">

settings.md +27 −1

Details

179| `enableAllProjectMcpServers` | Automatically approve all MCP servers defined in project `.mcp.json` files | `true` |179| `enableAllProjectMcpServers` | Automatically approve all MCP servers defined in project `.mcp.json` files | `true` |

180| `enabledMcpjsonServers` | List of specific MCP servers from `.mcp.json` files to approve | `["memory", "github"]` |180| `enabledMcpjsonServers` | List of specific MCP servers from `.mcp.json` files to approve | `["memory", "github"]` |

181| `disabledMcpjsonServers` | List of specific MCP servers from `.mcp.json` files to reject | `["filesystem"]` |181| `disabledMcpjsonServers` | List of specific MCP servers from `.mcp.json` files to reject | `["filesystem"]` |

182| `channelsEnabled` | (Managed settings only) Allow [channels](/en/channels) for Team and Enterprise users. Unset or `false` blocks channel message delivery regardless of what users pass to `--channels` | `true` |

182| `allowedMcpServers` | When set in managed-settings.json, allowlist of MCP servers users can configure. Undefined = no restrictions, empty array = lockdown. Applies to all scopes. Denylist takes precedence. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) | `[{ "serverName": "github" }]` |183| `allowedMcpServers` | When set in managed-settings.json, allowlist of MCP servers users can configure. Undefined = no restrictions, empty array = lockdown. Applies to all scopes. Denylist takes precedence. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) | `[{ "serverName": "github" }]` |

183| `deniedMcpServers` | When set in managed-settings.json, denylist of MCP servers that are explicitly blocked. Applies to all scopes including managed servers. Denylist takes precedence over allowlist. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) | `[{ "serverName": "filesystem" }]` |184| `deniedMcpServers` | When set in managed-settings.json, denylist of MCP servers that are explicitly blocked. Applies to all scopes including managed servers. Denylist takes precedence over allowlist. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) | `[{ "serverName": "filesystem" }]` |

184| `strictKnownMarketplaces` | When set in managed-settings.json, allowlist of plugin marketplaces users can add. Undefined = no restrictions, empty array = lockdown. Applies to marketplace additions only. See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) | `[{ "source": "github", "repo": "acme-corp/plugins" }]` |185| `strictKnownMarketplaces` | When set in managed-settings.json, allowlist of plugin marketplaces users can add. Undefined = no restrictions, empty array = lockdown. Applies to marketplace additions only. See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) | `[{ "source": "github", "repo": "acme-corp/plugins" }]` |


572* `git`: Any git URL (uses `url`)573* `git`: Any git URL (uses `url`)

573* `directory`: Local filesystem path (uses `path`, for development only)574* `directory`: Local filesystem path (uses `path`, for development only)

574* `hostPattern`: regex pattern to match marketplace hosts (uses `hostPattern`)575* `hostPattern`: regex pattern to match marketplace hosts (uses `hostPattern`)

576* `settings`: inline marketplace declared directly in settings.json without a separate hosted repository (uses `name` and `plugins`)

577 

578Use `source: 'settings'` to declare a small set of plugins inline without setting up a hosted marketplace repository. Plugins listed here must reference external sources such as GitHub or npm. You still need to enable each plugin separately in `enabledPlugins`.

579 

580```json theme={null}

581{

582 "extraKnownMarketplaces": {

583 "team-tools": {

584 "source": {

585 "source": "settings",

586 "name": "team-tools",

587 "plugins": [

588 {

589 "name": "code-formatter",

590 "source": {

591 "source": "github",

592 "repo": "acme-corp/code-formatter"

593 }

594 }

595 ]

596 }

597 }

598 }

599}

600```

575 601 

576#### `strictKnownMarketplaces`602#### `strictKnownMarketplaces`

577 603 


598 624 

599**All supported source types**:625**All supported source types**:

600 626 

601The allowlist supports seven marketplace source types. Most sources use exact matching, while `hostPattern` uses regex matching against the marketplace host.627The allowlist supports multiple marketplace source types. Most sources use exact matching, while `hostPattern` uses regex matching against the marketplace host.

602 628 

6031. **GitHub repositories**:6291. **GitHub repositories**:

604 630 

skills.md +6 −5

Details

187All fields are optional. Only `description` is recommended so Claude knows when to use the skill.187All fields are optional. Only `description` is recommended so Claude knows when to use the skill.

188 188 

189| Field | Required | Description |189| Field | Required | Description |

190| :------------------------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |190| :------------------------- | :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

191| `name` | No | Display name for the skill. If omitted, uses the directory name. Lowercase letters, numbers, and hyphens only (max 64 characters). |191| `name` | No | Display name for the skill. If omitted, uses the directory name. Lowercase letters, numbers, and hyphens only (max 64 characters). |

192| `description` | Recommended | What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. |192| `description` | Recommended | What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. |

193| `argument-hint` | No | Hint shown during autocomplete to indicate expected arguments. Example: `[issue-number]` or `[filename] [format]`. |193| `argument-hint` | No | Hint shown during autocomplete to indicate expected arguments. Example: `[issue-number]` or `[filename] [format]`. |


195| `user-invocable` | No | Set to `false` to hide from the `/` menu. Use for background knowledge users shouldn't invoke directly. Default: `true`. |195| `user-invocable` | No | Set to `false` to hide from the `/` menu. Use for background knowledge users shouldn't invoke directly. Default: `true`. |

196| `allowed-tools` | No | Tools Claude can use without asking permission when this skill is active. |196| `allowed-tools` | No | Tools Claude can use without asking permission when this skill is active. |

197| `model` | No | Model to use when this skill is active. |197| `model` | No | Model to use when this skill is active. |

198| `effort` | No | [Effort level](/en/model-config#adjust-effort-level) when this skill is active. Overrides the session effort level. Default: inherits from session. Options: `low`, `medium`, `high`, `max` (Opus 4.6 only). |

198| `context` | No | Set to `fork` to run in a forked subagent context. |199| `context` | No | Set to `fork` to run in a forked subagent context. |

199| `agent` | No | Which subagent type to use when `context: fork` is set. |200| `agent` | No | Which subagent type to use when `context: fork` is set. |

200| `hooks` | No | Hooks scoped to this skill's lifecycle. See [Hooks in skills and agents](/en/hooks#hooks-in-skills-and-agents) for configuration format. |201| `hooks` | No | Hooks scoped to this skill's lifecycle. See [Hooks in skills and agents](/en/hooks#hooks-in-skills-and-agents) for configuration format. |


351 352 

352### Inject dynamic context353### Inject dynamic context

353 354 

354The `!`command\`\` syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself.355The `` !`<command>` `` syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself.

355 356 

356This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The `!`gh pr diff\`\` and other commands run first, and their output gets inserted into the prompt:357This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The `` !`gh pr diff` `` and other commands run first, and their output gets inserted into the prompt:

357 358 

358```yaml theme={null}359```yaml theme={null}

359---360---


375 376 

376When this skill runs:377When this skill runs:

377 378 

3781. Each `!`command\`\` executes immediately (before Claude sees anything)3791. Each `` !`<command>` `` executes immediately (before Claude sees anything)

3792. The output replaces the placeholder in the skill content3802. The output replaces the placeholder in the skill content

3803. Claude receives the fully-rendered prompt with actual PR data3813. Claude receives the fully-rendered prompt with actual PR data

381 382 


501 502 

502```bash503```bash

503python ~/.claude/skills/codebase-visualizer/scripts/visualize.py .504python ~/.claude/skills/codebase-visualizer/scripts/visualize.py .

504```text505```

505 506 

506This creates `codebase-map.html` in the current directory and opens it in your default browser.507This creates `codebase-map.html` in the current directory and opens it in your default browser.

507 508 

statusline.md +85 −1

Details

145Claude Code sends the following JSON fields to your script via stdin:145Claude Code sends the following JSON fields to your script via stdin:

146 146 

147| Field | Description |147| Field | Description |

148| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |148| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

149| `model.id`, `model.display_name` | Current model identifier and display name |149| `model.id`, `model.display_name` | Current model identifier and display name |

150| `cwd`, `workspace.current_dir` | Current working directory. Both fields contain the same value; `workspace.current_dir` is preferred for consistency with `workspace.project_dir`. |150| `cwd`, `workspace.current_dir` | Current working directory. Both fields contain the same value; `workspace.current_dir` is preferred for consistency with `workspace.project_dir`. |

151| `workspace.project_dir` | Directory where Claude Code was launched, which may differ from `cwd` if the working directory changes during a session |151| `workspace.project_dir` | Directory where Claude Code was launched, which may differ from `cwd` if the working directory changes during a session |


159| `context_window.remaining_percentage` | Pre-calculated percentage of context window remaining |159| `context_window.remaining_percentage` | Pre-calculated percentage of context window remaining |

160| `context_window.current_usage` | Token counts from the last API call, described in [context window fields](#context-window-fields) |160| `context_window.current_usage` | Token counts from the last API call, described in [context window fields](#context-window-fields) |

161| `exceeds_200k_tokens` | Whether the total token count (input, cache, and output tokens combined) from the most recent API response exceeds 200k. This is a fixed threshold regardless of actual context window size. |161| `exceeds_200k_tokens` | Whether the total token count (input, cache, and output tokens combined) from the most recent API response exceeds 200k. This is a fixed threshold regardless of actual context window size. |

162| `rate_limits.five_hour.used_percentage`, `rate_limits.seven_day.used_percentage` | Percentage of the 5-hour or 7-day rate limit consumed, from 0 to 100 |

163| `rate_limits.five_hour.resets_at`, `rate_limits.seven_day.resets_at` | Unix epoch seconds when the 5-hour or 7-day rate limit window resets |

162| `session_id` | Unique session identifier |164| `session_id` | Unique session identifier |

163| `transcript_path` | Path to conversation transcript file |165| `transcript_path` | Path to conversation transcript file |

164| `version` | Claude Code version |166| `version` | Claude Code version |


212 }214 }

213 },215 },

214 "exceeds_200k_tokens": false,216 "exceeds_200k_tokens": false,

217 "rate_limits": {

218 "five_hour": {

219 "used_percentage": 23.5,

220 "resets_at": 1738425600

221 },

222 "seven_day": {

223 "used_percentage": 41.2,

224 "resets_at": 1738857600

225 }

226 },

215 "vim": {227 "vim": {

216 "mode": "NORMAL"228 "mode": "NORMAL"

217 },229 },


233 * `vim`: appears only when vim mode is enabled245 * `vim`: appears only when vim mode is enabled

234 * `agent`: appears only when running with the `--agent` flag or agent settings configured246 * `agent`: appears only when running with the `--agent` flag or agent settings configured

235 * `worktree`: appears only during `--worktree` sessions. When present, `branch` and `original_branch` may also be absent for hook-based worktrees247 * `worktree`: appears only during `--worktree` sessions. When present, `branch` and `original_branch` may also be absent for hook-based worktrees

248 * `rate_limits`: appears only for Claude.ai subscribers (Pro/Max) after the first API response in the session. Each window (`five_hour`, `seven_day`) may be independently absent. Use `jq -r '.rate_limits.five_hour.used_percentage // empty'` to handle absence gracefully.

236 249 

237 **Fields that may be `null`**:250 **Fields that may be `null`**:

238 251 


681 ```694 ```

682</CodeGroup>695</CodeGroup>

683 696 

697### Rate limit usage

698 

699Display Claude.ai subscription rate limit usage in the status line. The `rate_limits` object contains `five_hour` (5-hour rolling window) and `seven_day` (weekly) windows. Each window provides `used_percentage` (0-100) and `resets_at` (Unix epoch seconds when the window resets).

700 

701This field is only present for Claude.ai subscribers (Pro/Max) after the first API response. Each script handles the absent field gracefully:

702 

703<CodeGroup>

704 ```bash Bash theme={null}

705 #!/bin/bash

706 input=$(cat)

707 

708 MODEL=$(echo "$input" | jq -r '.model.display_name')

709 # "// empty" produces no output when rate_limits is absent

710 FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')

711 WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')

712 

713 LIMITS=""

714 [ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"

715 [ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"

716 

717 [ -n "$LIMITS" ] && echo "[$MODEL] | $LIMITS" || echo "[$MODEL]"

718 ```

719 

720 ```python Python theme={null}

721 #!/usr/bin/env python3

722 import json, sys

723 

724 data = json.load(sys.stdin)

725 model = data['model']['display_name']

726 

727 parts = []

728 rate = data.get('rate_limits', {})

729 five_h = rate.get('five_hour', {}).get('used_percentage')

730 week = rate.get('seven_day', {}).get('used_percentage')

731 

732 if five_h is not None:

733 parts.append(f"5h: {five_h:.0f}%")

734 if week is not None:

735 parts.append(f"7d: {week:.0f}%")

736 

737 if parts:

738 print(f"[{model}] | {' '.join(parts)}")

739 else:

740 print(f"[{model}]")

741 ```

742 

743 ```javascript Node.js theme={null}

744 #!/usr/bin/env node

745 let input = '';

746 process.stdin.on('data', chunk => input += chunk);

747 process.stdin.on('end', () => {

748 const data = JSON.parse(input);

749 const model = data.model.display_name;

750 

751 const parts = [];

752 const fiveH = data.rate_limits?.five_hour?.used_percentage;

753 const week = data.rate_limits?.seven_day?.used_percentage;

754 

755 if (fiveH != null) parts.push(`5h: ${Math.round(fiveH)}%`);

756 if (week != null) parts.push(`7d: ${Math.round(week)}%`);

757 

758 console.log(parts.length ? `[${model}] | ${parts.join(' ')}` : `[${model}]`);

759 });

760 ```

761</CodeGroup>

762 

684### Cache expensive operations763### Cache expensive operations

685 764 

686Your status line script runs frequently during active sessions. Commands like `git status` or `git diff` can be slow, especially in large repositories. This example caches git information to a temp file and only refreshes it every 5 seconds.765Your status line script runs frequently during active sessions. Commands like `git status` or `git diff` can be slow, especially in large repositories. This example caches git information to a temp file and only refreshes it every 5 seconds.


904* If you see corrupted text, try simplifying your script to plain text output983* If you see corrupted text, try simplifying your script to plain text output

905* Multi-line status lines with escape codes are more prone to rendering issues than single-line plain text984* Multi-line status lines with escape codes are more prone to rendering issues than single-line plain text

906 985 

986**Workspace trust required**

987 

988* The status line command only runs if you've accepted the workspace trust dialog for the current directory. Because `statusLine` executes a shell command, it requires the same trust acceptance as hooks and other shell-executing settings.

989* If trust isn't accepted, you'll see the notification `statusline skipped · restart to fix` instead of your status line output. Restart Claude Code and accept the trust prompt to enable it.

990 

907**Script errors or hangs**991**Script errors or hangs**

908 992 

909* Scripts that exit with non-zero codes or produce no output cause the status line to go blank993* Scripts that exit with non-zero codes or produce no output cause the status line to go blank

sub-agents.md +15 −3

Details

118 </Step>118 </Step>

119 119 

120 <Step title="Configure memory">120 <Step title="Configure memory">

121 Select **Enable** to give the subagent a [persistent memory directory](#enable-persistent-memory) at `~/.claude/agent-memory/`. The subagent uses this to accumulate insights across conversations, such as codebase patterns and recurring issues. Select **None** if you don't want the subagent to persist learnings.121 Select **User scope** to give the subagent a [persistent memory directory](#enable-persistent-memory) at `~/.claude/agent-memory/`. The subagent uses this to accumulate insights across conversations, such as codebase patterns and recurring issues. Select **None** if you don't want the subagent to persist learnings.

122 </Step>122 </Step>

123 123 

124 <Step title="Save and try it out">124 <Step title="Save and try it out">


184}'184}'

185```185```

186 186 

187The `--agents` flag accepts JSON with the same [frontmatter](#supported-frontmatter-fields) fields as file-based subagents: `description`, `prompt`, `tools`, `disallowedTools`, `model`, `permissionMode`, `mcpServers`, `hooks`, `maxTurns`, `skills`, and `memory`. Use `prompt` for the system prompt, equivalent to the markdown body in file-based subagents.187The `--agents` flag accepts JSON with the same [frontmatter](#supported-frontmatter-fields) fields as file-based subagents: `description`, `prompt`, `tools`, `disallowedTools`, `model`, `permissionMode`, `mcpServers`, `hooks`, `maxTurns`, `skills`, `memory`, `effort`, `background`, and `isolation`. Use `prompt` for the system prompt, equivalent to the markdown body in file-based subagents.

188 188 

189**Plugin subagents** come from [plugins](/en/plugins) you've installed. They appear in `/agents` alongside your custom subagents. See the [plugin components reference](/en/plugins-reference#agents) for details on creating plugin subagents.189**Plugin subagents** come from [plugins](/en/plugins) you've installed. They appear in `/agents` alongside your custom subagents. See the [plugin components reference](/en/plugins-reference#agents) for details on creating plugin subagents.

190 190 


232| `hooks` | No | [Lifecycle hooks](#define-hooks-for-subagents) scoped to this subagent |232| `hooks` | No | [Lifecycle hooks](#define-hooks-for-subagents) scoped to this subagent |

233| `memory` | No | [Persistent memory scope](#enable-persistent-memory): `user`, `project`, or `local`. Enables cross-session learning |233| `memory` | No | [Persistent memory scope](#enable-persistent-memory): `user`, `project`, or `local`. Enables cross-session learning |

234| `background` | No | Set to `true` to always run this subagent as a [background task](#run-subagents-in-foreground-or-background). Default: `false` |234| `background` | No | Set to `true` to always run this subagent as a [background task](#run-subagents-in-foreground-or-background). Default: `false` |

235| `effort` | No | Effort level when this subagent is active. Overrides the session effort level. Default: inherits from session. Options: `low`, `medium`, `high`, `max` (Opus 4.6 only) |

235| `isolation` | No | Set to `worktree` to run the subagent in a temporary [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees), giving it an isolated copy of the repository. The worktree is automatically cleaned up if the subagent makes no changes |236| `isolation` | No | Set to `worktree` to run the subagent in a temporary [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees), giving it an isolated copy of the repository. The worktree is automatically cleaned up if the subagent makes no changes |

236 237 

237### Choose a model238### Choose a model


251 252 

252Subagents can use any of Claude Code's [internal tools](/en/tools-reference). By default, subagents inherit all tools from the main conversation, including MCP tools.253Subagents can use any of Claude Code's [internal tools](/en/tools-reference). By default, subagents inherit all tools from the main conversation, including MCP tools.

253 254 

254To restrict tools, use the `tools` field (allowlist) or `disallowedTools` field (denylist):255To restrict tools, use either the `tools` field (allowlist) or the `disallowedTools` field (denylist). This example uses `tools` to exclusively allow Read, Grep, Glob, and Bash. The subagent can't edit files, write files, or use any MCP tools:

255 256 

256```yaml theme={null}257```yaml theme={null}

257---258---

258name: safe-researcher259name: safe-researcher

259description: Research agent with restricted capabilities260description: Research agent with restricted capabilities

260tools: Read, Grep, Glob, Bash261tools: Read, Grep, Glob, Bash

262---

263```

264 

265This example uses `disallowedTools` to inherit every tool from the main conversation except Write and Edit. The subagent keeps Bash, MCP tools, and everything else:

266 

267```yaml theme={null}

268---

269name: no-writes

270description: Inherits every tool except file writes

261disallowedTools: Write, Edit271disallowedTools: Write, Edit

262---272---

263```273```

264 274 

275If both are set, `disallowedTools` is applied first, then `tools` is resolved against the remaining pool. A tool listed in both is removed.

276 

265#### Restrict which subagents can be spawned277#### Restrict which subagents can be spawned

266 278 

267When an agent runs as the main thread with `claude --agent`, it can spawn subagents using the Agent tool. To restrict which subagent types it can spawn, use `Agent(agent_type)` syntax in the `tools` field.279When an agent runs as the main thread with `claude --agent`, it can spawn subagents using the Agent tool. To restrict which subagent types it can spawn, use `Agent(agent_type)` syntax in the `tools` field.