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

One read of Claude Code CLIclaude-code-20260820T193701Z

18 pages moved out of 186 read.

Pages moved 18 significant first
Pages read 186 in this capture
Captured 19:37 UTC
Corpus hash 96ae8ecab343 corpus-hash

What this read moved

1-18 of 18

agent-sdk/custom-tools Changed · +0 / -7 lines

## Related documentation

from line 842
842842* To connect to external MCP servers (filesystem, GitHub, Slack) instead of building your own, see [Connect MCP servers](/docs/en/agent-sdk/mcp).
843843* To control which tools run automatically versus requiring approval, see [Configure permissions](/docs/en/agent-sdk/permissions).
844844 
845## Related documentation
846 
847* [TypeScript SDK Reference](/docs/en/agent-sdk/typescript)
848* [Python SDK Reference](/docs/en/agent-sdk/python)
849* [MCP Documentation](https://modelcontextprotocol.io)
850* [SDK Overview](/docs/en/agent-sdk/overview)
851 

agent-sdk/file-checkpointing Changed · +0 / -6 lines

from line 22
2222 File rewinding restores files on disk to a previous state. It does not rewind the conversation itself. The conversation history and context remain intact after calling `rewindFiles()` (TypeScript) or `rewind_files()` (Python).
2323</Note>
2424 
25The checkpoint system tracks:
26 
27* Files created during the session
28* Files modified during the session
29* The original content of modified files
30 
3125When you rewind to a checkpoint, Claude Code deletes the files it created and restores the files it modified to their content at that point. Claude Code skips a tracked path that is a symlink, hard link, or other non-regular file. It also skips a tracked file whose parent directory no longer resolves to its checkpoint-time location, or whose backup it can't read safely. [`RewindFilesResult`](/docs/en/agent-sdk/typescript#rewindfilesresult) counts every skipped path in its `skippedLinks` field. Skipping requires Claude Code v2.1.216 or later; before v2.1.216, a rewind wrote and deleted through links at tracked paths.
3226 
3327## Implement checkpointing

agent-sdk/hooks Changed · +7 / -13 lines

from line 215
215215 
216216SDK matchers follow the same rules as [matchers in settings files](/docs/en/hooks#matcher-patterns). That section documents the exact-string and regular-expression evaluation paths, their version requirements, and the matcher values for each event type.
217217 
218| Option | Type | Default | Description |
219| --------- | ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
220| `matcher` | `string` | `undefined` | Pattern matched against the event's filter field, following the [rules for matchers in settings files](/docs/en/hooks#matcher-patterns). For tool hooks, this is the tool name. Built-in tools include `Bash`, `Read`, `Write`, `Edit`, `Glob`, `Grep`, `WebFetch`, `Agent`, and others (see [Tool Input Types](/docs/en/agent-sdk/typescript#tool-input-types) for the full list). MCP tools use the pattern `mcp__<server>__<action>`. |
221| `hooks` | `HookCallback[]` | - | Required. Array of callback functions to execute when the pattern matches |
222| `timeout` | `number` | `undefined` | Timeout in seconds. When omitted, Claude Code applies the [event's default timeout](#hook-timeout). Your SDK callbacks follow the `command` hook defaults |
218| Option | Type | Default | Description |
219| --------- | ---------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
220| `matcher` | `string` | `undefined` | Pattern matched against the event's filter field, following the [rules for matchers in settings files](/docs/en/hooks#matcher-patterns). For tool hooks, this is the tool name. Built-in tools include `Bash`, `Read`, `Write`, `Edit`, `Glob`, `Grep`, `WebFetch`, `Agent`, and others (see [Tool Input Types](/docs/en/agent-sdk/typescript#tool-input-types) for the full list). MCP tools use the pattern `mcp__<server>__<action>`, where `<server>` is the key you use in the `mcpServers` configuration. |
221| `hooks` | `HookCallback[]` | - | Required. Array of callback functions to execute when the pattern matches |
222| `timeout` | `number` | `undefined` | Timeout in seconds. When omitted, Claude Code applies the [event's default timeout](#hook-timeout). Your SDK callbacks follow the `command` hook defaults |
223223 
224Use the `matcher` pattern to target specific tools whenever possible. A matcher with `'Bash'` only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event.
225 
226<Tip>
227 **Discovering tool names:** See [Tool Input Types](/docs/en/agent-sdk/typescript#tool-input-types) for the full list of built-in tool names, or add a hook without a matcher to log all tool calls your session makes.
228 
229 **MCP tool naming:** MCP tools always start with `mcp__` followed by the server name and action: `mcp__<server>__<action>`. For example, if you configure a server named `playwright`, its tools are named `mcp__playwright__browser_screenshot`, `mcp__playwright__browser_click`, and so on. The server name comes from the key you use in the `mcpServers` configuration.
230</Tip>
224Use the `matcher` pattern to target specific tools whenever possible. A matcher with `'Bash'` only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event. Omit it on purpose to log every tool call your session makes.
231225 
232226### Callback functions
233227 

agent-sdk/mcp Changed · +31 / -52 lines

from line 300
300300 
301301### HTTP/SSE servers
302302 
303Use HTTP or SSE for cloud-hosted MCP servers and remote APIs:
303Use HTTP or SSE for cloud-hosted MCP servers and remote APIs. For the `.mcp.json` form, use the same fields as the example at [HTTP headers for remote servers](#http-headers-for-remote-servers), with `"type": "sse"` for an SSE server. In code, pass the server's URL:
304304 
305<Tabs>
306 <Tab title="In code">
307 <CodeGroup>
308 ```typescript TypeScript hidelines={1,-1} theme={null}
309 const _ = {
310 options: {
311 mcpServers: {
312 "remote-api": {
313 type: "sse",
314 url: "https://api.example.com/mcp/sse",
315 headers: {
316 Authorization: `Bearer ${process.env.API_TOKEN}`
317 }
318 }
319 },
320 allowedTools: ["mcp__remote-api__*"]
321 }
322 };
323 ```
324 
325 ```python Python theme={null}
326 options = ClaudeAgentOptions(
327 mcp_servers={
328 "remote-api": {
329 "type": "sse",
330 "url": "https://api.example.com/mcp/sse",
331 "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
332 }
333 },
334 allowed_tools=["mcp__remote-api__*"],
335 )
336 ```
337 </CodeGroup>
338 </Tab>
339 
340 <Tab title=".mcp.json">
341 ```json theme={null}
342 {
343 "mcpServers": {
305<CodeGroup>
306 ```typescript TypeScript hidelines={1,-1} theme={null}
307 const _ = {
308 options: {
309 mcpServers: {
344310 "remote-api": {
345 "type": "sse",
346 "url": "https://api.example.com/mcp/sse",
347 "headers": {
348 "Authorization": "Bearer ${API_TOKEN}"
311 type: "sse",
312 url: "https://api.example.com/mcp/sse",
313 headers: {
314 Authorization: `Bearer ${process.env.API_TOKEN}`
349315 }
350316 }
351 }
317 },
318 allowedTools: ["mcp__remote-api__*"]
352319 }
353 ```
354 </Tab>
355</Tabs>
320 };
321 ```
356322 
323 ```python Python theme={null}
324 options = ClaudeAgentOptions(
325 mcp_servers={
326 "remote-api": {
327 "type": "sse",
328 "url": "https://api.example.com/mcp/sse",
329 "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
330 }
331 },
332 allowed_tools=["mcp__remote-api__*"],
333 )
334 ```
335</CodeGroup>
336 
357337For the streamable HTTP transport, use `"type": "http"` instead. In `.mcp.json` and other JSON config files, `"streamable-http"` is accepted as an alias for `"http"`. The programmatic `mcpServers` option accepts only `"http"`.
358338 
359339### SDK MCP servers
from line 850
870850 
871851### Tool output exceeds maximum allowed tokens
872852 
873The SDK applies the same MCP output limit as Claude Code. When a tool result is larger than 25,000 tokens, the full output is saved to a file and the tool result is replaced with an error message that names the file path, so the agent can read the output back in portions. Raise the limit with the [`MAX_MCP_OUTPUT_TOKENS`](/docs/en/env-vars) environment variable. See [MCP output limits and warnings](/docs/en/mcp#mcp-output-limits-and-warnings) for the full behavior, including how a server can declare a higher per-tool limit.
853The SDK applies the same MCP output limit as Claude Code. When a tool result is larger than 25,000 tokens, the full output is saved to a file and the tool result is replaced with an error message that names the file path, so the agent can read the output back in portions. Raise the limit with the [`MAX_MCP_OUTPUT_TOKENS`](/docs/en/env-vars) environment variable. See [MCP output limits and warnings](/docs/en/mcp#mcp-output-limits-and-warnings) for the full behavior, including how a server can declare a higher per-tool limit with the `anthropic/maxResultSizeChars` annotation.
874854 
875855## Related resources
876856 
877857* **[Custom tools guide](/docs/en/agent-sdk/custom-tools)**: Build your own MCP server that runs in-process with your SDK application
878858* **[Permissions](/docs/en/agent-sdk/permissions)**: Control which MCP tools your agent can use with `allowedTools` and `disallowedTools`
879* **[MCP output limits and warnings](/docs/en/mcp#mcp-output-limits-and-warnings)**: How the SDK handles tool results that exceed `MAX_MCP_OUTPUT_TOKENS`, including the persist-to-disk fallback and the `anthropic/maxResultSizeChars` per-tool annotation
880859* **[TypeScript SDK reference](/docs/en/agent-sdk/typescript)**: Full API reference including MCP configuration options
881860* **[Python SDK reference](/docs/en/agent-sdk/python)**: Full API reference including MCP configuration options
882861* **[MCP server directory](https://github.com/modelcontextprotocol/servers)**: Browse available MCP servers for databases, APIs, and more

agent-sdk/subagents Changed · +9 / -24 lines

### Context isolation ### Parallelization ### Specialized instructions and knowledge ### Tool restrictions

from line 19
1919 
2020## Benefits of using subagents
2121 
22### Context isolation
22Because subagents are separate agent instances, delegating work to them gives you four benefits:
2323 
24Each subagent runs in its own fresh conversation. Intermediate tool calls and results stay inside the subagent; only its final message returns to the parent. See [What subagents inherit](#what-subagents-inherit) for exactly what's in the subagent's context.
24* **Context isolation**: each subagent runs in its own conversation, which starts fresh unless the subagent is a [fork](/docs/en/sub-agents#fork-the-current-conversation). Either way, intermediate tool calls and results stay inside the subagent; only its final message returns to the parent. A `research-assistant` subagent can explore dozens of files without any of that content accumulating in the main conversation. The parent receives a concise summary, not every file the subagent read. See [What subagents inherit](#what-subagents-inherit) for exactly what's in the subagent's context.
25* **Parallelization**: multiple subagents can run concurrently, so independent subtasks finish in the time of the slowest one rather than the sum of all of them. During a code review, you can run `style-checker`, `security-scanner`, and `test-coverage` subagents simultaneously instead of sequentially.
26* **Specialized instructions and knowledge**: each subagent can have a tailored system prompt with specific expertise, best practices, and constraints. A `database-migration` subagent can have detailed knowledge about SQL best practices, rollback strategies, and data integrity checks that would be unnecessary noise in the main agent's instructions.
27* **Tool restrictions**: subagents can be limited to specific tools, reducing the risk of unintended actions. A `doc-reviewer` subagent might only have access to Read and Grep tools, ensuring it can analyze but never accidentally modify your documentation files.
2528 
26**Example:** a `research-assistant` subagent can explore dozens of files without any of that content accumulating in the main conversation. The parent receives a concise summary, not every file the subagent read.
27 
28### Parallelization
29 
30Multiple subagents can run concurrently, so independent subtasks finish in the time of the slowest one rather than the sum of all of them.
31 
32**Example:** during a code review, you can run `style-checker`, `security-scanner`, and `test-coverage` subagents simultaneously instead of sequentially.
33 
34### Specialized instructions and knowledge
35 
36Each subagent can have tailored system prompts with specific expertise, best practices, and constraints.
37 
38**Example:** a `database-migration` subagent can have detailed knowledge about SQL best practices, rollback strategies, and data integrity checks that would be unnecessary noise in the main agent's instructions.
39 
40### Tool restrictions
41 
42Subagents can be limited to specific tools, reducing the risk of unintended actions.
43 
44**Example:** a `doc-reviewer` subagent might only have access to Read and Grep tools, ensuring it can analyze but never accidentally modify your documentation files.
45 
4629## Create subagents
4730 
4831### Programmatic definition (recommended)
from line 177
194177 
195178## What subagents inherit
196179 
197A subagent's context window starts fresh, with no parent conversation, but isn't empty. The only content you pass from parent to subagent is the Agent tool's prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt.
180Unless the subagent is a [fork](/docs/en/sub-agents#fork-the-current-conversation), its context window starts fresh, with no parent conversation, but isn't empty. The only content you pass from parent to subagent is the Agent tool's prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt.
198181 
199182A subagent that has the [`SendMessage`](/docs/en/tools-reference) tool starts with a list of the other named agents running in the session, so it knows which names it can send messages to. Claude Code adds the list to the subagent's first turn automatically. A [fork](/docs/en/sub-agents#fork-the-current-conversation) doesn't get the list because it inherits the parent conversation instead. The list requires Claude Code v2.1.206 or later.
183 
184The table below lists what a non-fork subagent's context contains and what it leaves out.
200185 
201186| The subagent receives | The subagent doesn't receive |
202187| :------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------- |

agent-sdk/todo-tracking Changed · +272 / -247 lines

# Track todos ## Model availability ## Todo lifecycle ## When Claude creates todos ### Monitor todo changes ### Display progress in real time ## Related documentation # Todo Lists ### Model availability ### Todo Lifecycle ### When Todos Are Used ### Monitoring Todo Changes ### Real-time Progress Display ## Migrate to Task tools ## Related Documentation

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

from line 1
1# Todo Lists
2 
3> Track and display todos using the Claude Agent SDK for organized task management
4 
5The Claude Agent SDK includes built-in todo functionality that helps organize complex workflows and keep users informed about task progression.
1# Track todos
2 
3> Track todos in Agent SDK sessions and render Claude's progress in your application from structured tool calls
4 
5On the models listed under [Model availability](#model-availability), Claude tracks multi-step work without a written todo list, and Claude Code leaves the [task-tracking tools](/docs/en/tools-reference#task-tool-availability) out of sessions by default. You don't need anything on this page for Claude to work through multi-step tasks on those models.
6 
7In a session that has the task-tracking tools, Claude keeps a written todo list, updating each item's status as it works. You see each change in the message stream as a structured tool call. Opt a session in only when your application reads those tool calls, whether to log task activity or to render its own progress display.
8 
9## Model availability
610 
711<Note>
812 On TypeScript Agent SDK 0.3.233 and later, or Python Agent SDK 0.2.139 and later, the following tools aren't available on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, or later versions of those families unless you opt in:
from line 20
1620 On other models, Claude Code provides the Task tools by default and `TodoWrite` only when you set `CLAUDE_CODE_ENABLE_TASKS=0`.
1721</Note>
1822 
19### Model availability
20 
21On the [models that don't get the task-tracking tools](/docs/en/tools-reference#task-tool-availability), you see no `tool_use` blocks for them in the message stream unless you opt in. If you point `cli_path` in Python or `pathToClaudeCodeExecutable` in TypeScript at your own Claude Code install, you get whichever tools that install provides. To get the same tools as on other models, do one of the following:
22 
23* Name one of the tools in the [`allowedTools`](/docs/en/agent-sdk/permissions#allow-and-deny-rules) option, `allowed_tools` in Python
23On the listed models, unless you opt a session in, you see no `tool_use` blocks for the tools in the message stream. The Agent SDK applies these defaults through the Claude Code binary that it bundles. If you point `pathToClaudeCodeExecutable` (TypeScript) or `cli_path` (Python) at your own Claude Code install, you get whichever tools that install provides, under its own defaults. To see the exact set in a running session, [check which tools are available](/docs/en/tools-reference#check-which-tools-are-available). To opt a session in, do one of the following:
24 
25* Name one of the tools in the [`allowedTools`](/docs/en/agent-sdk/permissions#allow-and-deny-rules) (TypeScript) or `allowed_tools` (Python) option
2426* List the tools in the `tools` option, which restricts the session's built-in tools to the ones it names. Include the tools you want alongside the other built-in tools you use
2527* Set `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` in the `env` option, as the examples on this page do. In TypeScript, `env` replaces the subprocess environment, so spread `...process.env` to keep inherited variables. In Python, `env` is merged on top of the inherited environment
2628 
27### Todo Lifecycle
29## Todo lifecycle
2830 
2931Claude moves each todo through a predictable lifecycle:
3032 
from line 35
33353. **Completed**: Claude marks it completed when the task finishes successfully
34364. **Removed**: Claude deletes a todo it no longer needs by setting `status: "deleted"` in a `TaskUpdate` call
3537 
36### When Todos Are Used
38## When Claude creates todos
3739 
3840In a [session that has the task-tracking tools](#model-availability), Claude creates todos for most multi-step work, such as:
3941 
40* **Complex multi-step tasks** requiring 3 or more distinct actions
42* **Complex multi-step tasks** requiring three or more distinct actions
4143* **User-provided task lists** when multiple items are mentioned
42* **Non-trivial operations** that benefit from progress tracking
44* **Longer operations** that benefit from progress tracking
4345* **Explicit requests** when users ask for todo organization
4446 
45It may skip todos for very short or single-step requests.
47Claude may skip todos for very short or single-step requests.
4648 
4749## Examples
4850 
49Before running these examples, install the Claude Agent SDK by following the [quickstart](/docs/en/agent-sdk/quickstart).
50 
51Each example runs until the agent finishes and yields its final result message. If a session reaches its turn limit first, that result message has the `error_max_turns` subtype. Check `subtype` to detect that ending.
52 
53These examples use single-shot `query()` calls. After yielding an `error_max_turns` result, `query()` raises an error that includes `Reached maximum number of turns`. Each example wraps its loop in a try block to exit cleanly when that happens.
54 
55See [Handle the result](/docs/en/agent-sdk/agent-loop#handle-the-result) for the result subtypes.
56 
57### Monitoring Todo Changes
58 
59<CodeGroup>
60 ```typescript TypeScript theme={null}
61 import { query } from "@anthropic-ai/claude-agent-sdk";
62 
63 try {
64 for await (const message of query({
65 prompt: "Optimize my React app performance and track progress with todos",
66 // Re-enable TodoWrite, which this example monitors. Without it, the SDK uses
67 // Task tools instead and these tool_use blocks never appear. ENABLE_TODO_TOOLS
68 // keeps the tools on models where Claude Code otherwise doesn't provide them.
69 options: { maxTurns: 15, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0", CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" } }
70 })) {
71 // Todo updates are reflected in the message stream
72 if (message.type === "assistant") {
73 for (const block of message.message.content) {
74 if (block.type === "tool_use" && block.name === "TodoWrite") {
75 const todos = block.input.todos;
76 
77 console.log("Todo Status Update:");
78 todos.forEach((todo, index) => {
79 const status =
80 todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌";
81 console.log(`${index + 1}. ${status} ${todo.content}`);
82 });
83 }
84 }
85 }
86 }
87 } catch (error) {
88 // A single-shot query() throws after yielding an error result,
89 // such as when the maxTurns limit is hit.
90 console.log(`Session ended with an error: ${error}`);
91 }
92 ```
93 
94 ```python Python theme={null}
95 import asyncio
96 
97 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
98 
99 
100 async def main():
101 try:
102 async for message in query(
103 prompt="Optimize my React app performance and track progress with todos",
104 # Re-enable TodoWrite, which this example monitors. Without it, the SDK uses
105 # Task tools instead and these tool_use blocks never appear. ENABLE_TODO_TOOLS
106 # keeps the tools on models where Claude Code otherwise doesn't provide them.
107 options=ClaudeAgentOptions(max_turns=15, env={"CLAUDE_CODE_ENABLE_TASKS": "0", "CLAUDE_CODE_ENABLE_TODO_TOOLS": "1"}),
108 ):
109 # Todo updates are reflected in the message stream
110 if isinstance(message, AssistantMessage):
111 for block in message.content:
112 if isinstance(block, ToolUseBlock) and block.name == "TodoWrite":
113 todos = block.input["todos"]
114 
115 print("Todo Status Update:")
116 for i, todo in enumerate(todos):
117 status = (
118 "✅"
119 if todo["status"] == "completed"
120 else "🔧"
121 if todo["status"] == "in_progress"
122 else "❌"
123 )
124 print(f"{i + 1}. {status} {todo['content']}")
125 except Exception as error:
126 # A single-shot query() raises after yielding an error result,
127 # such as when the max_turns limit is hit.
128 print(f"Session ended with an error: {error}")
129 
130 
131 asyncio.run(main())
132 ```
133</CodeGroup>
134 
135### Real-time Progress Display
136 
137<CodeGroup>
138 ```typescript TypeScript theme={null}
139 import { query } from "@anthropic-ai/claude-agent-sdk";
140 
141 class TodoTracker {
142 private todos: any[] = [];
143 
144 displayProgress() {
145 if (this.todos.length === 0) return;
146 
147 const completed = this.todos.filter((t) => t.status === "completed").length;
148 const inProgress = this.todos.filter((t) => t.status === "in_progress").length;
149 const total = this.todos.length;
150 
151 console.log(`\nProgress: ${completed}/${total} completed`);
152 console.log(`Currently working on: ${inProgress} task(s)\n`);
153 
154 this.todos.forEach((todo, index) => {
155 const icon =
156 todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌";
157 const text = todo.status === "in_progress" ? todo.activeForm : todo.content;
158 console.log(`${index + 1}. ${icon} ${text}`);
159 });
160 }
161 
162 async trackQuery(prompt: string) {
163 try {
164 for await (const message of query({
165 prompt,
166 // On every model, re-enable TodoWrite, which this tracker watches for.
167 options: { maxTurns: 20, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0", CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" } }
168 })) {
169 if (message.type === "assistant") {
170 for (const block of message.message.content) {
171 if (block.type === "tool_use" && block.name === "TodoWrite") {
172 this.todos = block.input.todos;
173 this.displayProgress();
174 }
175 }
176 }
177 }
178 } catch (error) {
179 // A single-shot query() throws after yielding an error result,
180 // such as when the maxTurns limit is hit.
181 console.log(`Session ended with an error: ${error}`);
182 }
183 }
184 }
185 
186 // Usage
187 const tracker = new TodoTracker();
188 await tracker.trackQuery("Build a complete authentication system with todos");
189 ```
190 
191 ```python Python theme={null}
192 import asyncio
193 
194 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
195 from typing import List, Dict
196 
197 
198 class TodoTracker:
199 def __init__(self):
200 self.todos: List[Dict] = []
201 
202 def display_progress(self):
203 if not self.todos:
204 return
205 
206 completed = len([t for t in self.todos if t["status"] == "completed"])
207 in_progress = len([t for t in self.todos if t["status"] == "in_progress"])
208 total = len(self.todos)
209 
210 print(f"\nProgress: {completed}/{total} completed")
211 print(f"Currently working on: {in_progress} task(s)\n")
212 
213 for i, todo in enumerate(self.todos):
214 icon = (
215 "✅"
216 if todo["status"] == "completed"
217 else "🔧"
218 if todo["status"] == "in_progress"
219 else "❌"
220 )
221 text = (
222 todo["activeForm"]
223 if todo["status"] == "in_progress"
224 else todo["content"]
225 )
226 print(f"{i + 1}. {icon} {text}")
227 
228 async def track_query(self, prompt: str):
229 try:
230 async for message in query(
231 prompt=prompt,
232 # On every model, re-enable TodoWrite, which this tracker watches for.
233 options=ClaudeAgentOptions(max_turns=20, env={"CLAUDE_CODE_ENABLE_TASKS": "0", "CLAUDE_CODE_ENABLE_TODO_TOOLS": "1"}),
234 ):
235 if isinstance(message, AssistantMessage):
236 for block in message.content:
237 if isinstance(block, ToolUseBlock) and block.name == "TodoWrite":
238 self.todos = block.input["todos"]
239 self.display_progress()
240 except Exception as error:
241 # A single-shot query() raises after yielding an error result,
242 # such as when the max_turns limit is hit.
243 print(f"Session ended with an error: {error}")
244 
245 
246 # Usage
247 async def main():
248 tracker = TodoTracker()
249 await tracker.track_query("Build a complete authentication system with todos")
250 
251 
252 asyncio.run(main())
253 ```
254</CodeGroup>
255 
256## Migrate to Task tools
257 
258The Task tools split the single `TodoWrite` call into `TaskCreate` for each new item and `TaskUpdate` for each status change, with `TaskList` and `TaskGet` available for the model to read back the current list. Your monitoring code still inspects `tool_use` blocks in the assistant stream, but maintains a map keyed by task ID instead of replacing the whole list on every call.
259 
260| With `TodoWrite` | With Task tools |
261| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
262| One tool call rewrites the full `todos` array | `TaskCreate` adds one item, `TaskUpdate` patches one item by `taskId` |
263| Match `block.name === "TodoWrite"` | Match `block.name === "TaskCreate"` or `"TaskUpdate"` |
264| Item shape: `{ content, status, activeForm }` | `TaskCreate` input: `{ subject, description, activeForm?, metadata? }`. `TaskUpdate` input: `{ taskId, status?, subject?, description?, activeForm?, addBlocks?, addBlockedBy?, owner?, metadata? }`. `status` is `"pending"`, `"in_progress"`, or `"completed"`; set `status: "deleted"` to delete |
265| Render `block.input.todos` directly | Accumulate items across calls, or read a snapshot from a `TaskList` tool result |
266 
267The assigned task ID is not in the `TaskCreate` input. It comes back in the matching `tool_result` as `{ task: { id, subject } }`, so capture it from the result block to key your map.
268 
269The following example shows the minimal change to the [Monitoring Todo Changes](#monitoring-todo-changes) loop. It leaves `CLAUDE_CODE_ENABLE_TASKS` unset, because the Task tools are the default, and sets only `CLAUDE_CODE_ENABLE_TODO_TOOLS=1`, the [opt-in](#model-availability) for the models that otherwise don't get the tools. It reads only `tool_use` inputs and skips capturing IDs from `tool_result` blocks. To render a complete list, watch for a `TaskList` tool result in the stream or accumulate `TaskCreate` results and `TaskUpdate` inputs into a map.
270 
271The streamed `tool_use` input is the raw shape the model emitted. Claude Code repairs some close-but-incorrect key names before execution, mapping `id` or `task_id` to `taskId` and `active_form` to `activeForm`, but that repair is not reflected in the stream. Read `TaskUpdate` input fields defensively, as the samples below do, rather than assuming the canonical name is always present.
51Before running these examples, install the Claude Agent SDK by following the [quickstart](/docs/en/agent-sdk/quickstart). Every example on this page shares the same permission setup and exit behavior:
52 
53* **Permission mode**: the example prompts ask Claude to do real work on a project, so each example sets `permissionMode: "acceptEdits"` (TypeScript) or `permission_mode="acceptEdits"` (Python) to auto-approve the file edits that work produces. See [Permission modes](/docs/en/agent-sdk/permissions#permission-modes) for the alternatives.
54* **Turn limit**: each example runs until the agent finishes and yields its final result message. If a session reaches its turn limit first, that result message has the `error_max_turns` subtype. Check `subtype` to detect that ending.
55* **Error handling**: these examples use single-shot `query()` calls. After yielding an `error_max_turns` result, `query()` raises an error that includes `Reached maximum number of turns`. Each example wraps its loop in a try block to exit cleanly when that happens. See [Handle the result](/docs/en/agent-sdk/agent-loop#handle-the-result) for the result subtypes.
56 
57<Note>
58 The task system messages, [`SDKTaskNotificationMessage`](/docs/en/agent-sdk/typescript#sdktasknotificationmessage) (TypeScript) or [`TaskNotificationMessage`](/docs/en/agent-sdk/python#tasknotificationmessage) (Python) among them, report background tasks such as backgrounded commands and subagents. In the message stream, you see todo activity as `tool_use` blocks in the assistant messages.
59</Note>
60 
61### Monitor todo changes
62 
63The following example watches the assistant stream for `TaskCreate` and `TaskUpdate` `tool_use` blocks and prints a `+` line with each new task's subject and an update line with each status change's task ID and new status. Use this shape when you want a log of task activity rather than a rendered display. The `+` lines don't include the assigned IDs, so this log can't match updates back to their creates. To keep that correlation, capture the IDs as [Display progress in real time](#display-progress-in-real-time) does.
64 
65The streamed `tool_use` input is the raw shape the model emitted. Claude Code repairs some close-but-incorrect key names before execution, mapping `id` or `task_id` to `taskId` and `active_form` to `activeForm`, but that repair is not reflected in the stream. Read `TaskUpdate` input fields defensively, as both examples on this page do, rather than assuming the canonical name is always present.
27266 
27367<CodeGroup>
27468 ```typescript TypeScript theme={null}
from line 72
27872 for await (const message of query({
27973 prompt: "Optimize my React app performance and track progress with todos",
28074 // Keeps the Task tools on models where Claude Code otherwise doesn't provide them.
281 options: { maxTurns: 15, env: { ...process.env, CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" } },
75 options: { maxTurns: 15, permissionMode: "acceptEdits", env: { ...process.env, CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" } },
28276 })) {
28377 if (message.type !== "assistant") continue;
28478 for (const block of message.message.content) {
from line 108
314108 async for message in query(
315109 prompt="Optimize my React app performance and track progress with todos",
316110 # Keeps the Task tools on models where Claude Code otherwise doesn't provide them.
317 options=ClaudeAgentOptions(max_turns=15, env={"CLAUDE_CODE_ENABLE_TODO_TOOLS": "1"}),
111 options=ClaudeAgentOptions(max_turns=15, permission_mode="acceptEdits", env={"CLAUDE_CODE_ENABLE_TODO_TOOLS": "1"}),
318112 ):
319113 if not isinstance(message, AssistantMessage):
320114 continue
from line 116
322116 if not isinstance(block, ToolUseBlock):
323117 continue
324118 if block.name == "TaskCreate":
325 print(f"+ {block.input['subject']}")
119 print(f"+ {block.input.get('subject', '')}")
326120 elif block.name == "TaskUpdate" and block.input.get("status"):
327121 task_id = (
328122 block.input.get("taskId")
from line 134
340134 ```
341135</CodeGroup>
342136 
343## Related Documentation
344 
345* [TypeScript SDK Reference](/docs/en/agent-sdk/typescript)
346* [Python SDK Reference](/docs/en/agent-sdk/python)
347* [Streaming vs Single Mode](/docs/en/agent-sdk/streaming-vs-single-mode)
348* [Custom Tools](/docs/en/agent-sdk/custom-tools)
137### Display progress in real time
138 
139The following example watches the assistant stream for `TaskCreate` and `TaskUpdate` `tool_use` blocks and keeps a map of tasks keyed by task ID in a `TaskTracker` class, rerendering a progress summary on every change. The summary counts completed and in-progress tasks and shows each active item's `activeForm` label in place of its `subject`. Use this shape when your application maintains a progress display instead of logging each event.
140 
141The assigned task ID isn't in the `TaskCreate` input. Claude Code delivers each tool's structured output on the user message that carries its `tool_result` block, in the `tool_use_result` field. For `TaskCreate`, that object is documented for TypeScript as `TaskCreateOutput` under [Tool Output Types](/docs/en/agent-sdk/typescript#tool-output-types), and in Python the field is a plain dict of the same shape. The tracker pairs each `tool_result` block with its `tool_use` call by `tool_use_id` and reads `task.id` from the paired message's `tool_use_result`. Claude can read the list back with `TaskList` and one task's full details with `TaskGet`.
142 
143<CodeGroup>
144 ```typescript TypeScript theme={null}
145 import { query } from "@anthropic-ai/claude-agent-sdk";
146 
147 type Task = { subject: string; activeForm?: string; status: string };
148 
149 class TaskTracker {
150 private tasks = new Map<string, Task>();
151 private pendingCreates = new Map<string, { subject: string; activeForm?: string }>();
152 
153 displayProgress() {
154 if (this.tasks.size === 0) {
155 console.log("\nProgress: no open tasks\n");
156 return;
157 }
158 
159 const items = [...this.tasks.values()];
160 const completed = items.filter((t) => t.status === "completed").length;
161 const inProgress = items.filter((t) => t.status === "in_progress").length;
162 
163 console.log(`\nProgress: ${completed}/${this.tasks.size} completed`);
164 console.log(`Currently working on: ${inProgress} task(s)\n`);
165 
166 for (const [id, task] of this.tasks) {
167 const icon =
168 task.status === "completed" ? "✅" : task.status === "in_progress" ? "🔧" : "❌";
169 const text = task.status === "in_progress" && task.activeForm ? task.activeForm : task.subject;
170 console.log(`${id}. ${icon} ${text}`);
171 }
172 }
173 
174 handleToolUse(block: { id: string; name: string; input: unknown }) {
175 if (block.name === "TaskCreate") {
176 const input = block.input as { subject: string; activeForm?: string; active_form?: string };
177 this.pendingCreates.set(block.id, {
178 subject: input.subject,
179 activeForm: input.activeForm ?? input.active_form,
180 });
181 } else if (block.name === "TaskUpdate") {
182 const input = block.input as {
183 taskId?: string;
184 id?: string;
185 task_id?: string;
186 status?: string;
187 activeForm?: string;
188 active_form?: string;
189 };
190 const taskId = input.taskId ?? input.id ?? input.task_id;
191 if (!taskId) return;
192 if (input.status === "deleted") {
193 this.tasks.delete(taskId);
194 this.displayProgress();
195 return;
196 }
197 const task = this.tasks.get(taskId);
198 if (!task) return;
199 if (input.status) task.status = input.status;
200 const active = input.activeForm ?? input.active_form;
201 if (active) task.activeForm = active;
202 this.displayProgress();
203 }
204 }
205 
206 handleToolResult(block: { tool_use_id: string; is_error?: boolean }, result: unknown) {
207 const create = this.pendingCreates.get(block.tool_use_id);
208 if (!create) return;
209 this.pendingCreates.delete(block.tool_use_id);
210 if (block.is_error) return;
211 // The result's user message carries the tool's structured output as
212 // tool_use_result; for TaskCreate that's TaskCreateOutput,
213 // { task: { id, subject } }.
214 const out = result as { task?: { id: string } };
215 if (!out?.task?.id) return;
216 this.tasks.set(out.task.id, { ...create, status: "pending" });
217 this.displayProgress();
218 }
219 
220 async trackQuery(prompt: string) {
221 try {
222 for await (const message of query({
223 prompt,
224 options: { maxTurns: 20, permissionMode: "acceptEdits", env: { ...process.env, CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" } },
225 })) {
226 if (message.type === "assistant") {
227 for (const block of message.message.content) {
228 if (block.type === "tool_use") this.handleToolUse(block);
229 }
230 }
231 if (message.type === "user" && Array.isArray(message.message.content)) {
232 for (const block of message.message.content) {
233 if (block.type === "tool_result") this.handleToolResult(block, message.tool_use_result);
234 }
235 }
236 }
237 } catch (error) {
238 // A single-shot query() throws after yielding an error result,
239 // such as when the maxTurns limit is hit.
240 console.log(`Session ended with an error: ${error}`);
241 }
242 }
243 }
244 
245 // Usage
246 const tracker = new TaskTracker();
247 await tracker.trackQuery("Build a complete authentication system with todos");
248 ```
249 
250 ```python Python theme={null}
251 import asyncio
252 
253 from claude_agent_sdk import (
254 query,
255 ClaudeAgentOptions,
256 AssistantMessage,
257 UserMessage,
258 ToolUseBlock,
259 ToolResultBlock,
260 )
261 
262 
263 class TaskTracker:
264 def __init__(self):
265 self.tasks: dict[str, dict] = {}
266 self.pending_creates: dict[str, dict] = {}
267 
268 def display_progress(self):
269 if not self.tasks:
270 print("\nProgress: no open tasks\n")
271 return
272 
273 completed = len([t for t in self.tasks.values() if t["status"] == "completed"])
274 in_progress = len([t for t in self.tasks.values() if t["status"] == "in_progress"])
275 
276 print(f"\nProgress: {completed}/{len(self.tasks)} completed")
277 print(f"Currently working on: {in_progress} task(s)\n")
278 
279 for task_id, task in self.tasks.items():
280 icon = (
281 "✅"
282 if task["status"] == "completed"
283 else "🔧"
284 if task["status"] == "in_progress"
285 else "❌"
286 )
287 text = (
288 task["activeForm"]
289 if task["status"] == "in_progress" and task.get("activeForm")
290 else task["subject"]
291 )
292 print(f"{task_id}. {icon} {text}")
293 
294 def handle_tool_use(self, block: ToolUseBlock):
295 if block.name == "TaskCreate":
296 self.pending_creates[block.id] = {
297 "subject": block.input.get("subject", ""),
298 "activeForm": block.input.get("activeForm") or block.input.get("active_form"),
299 }
300 elif block.name == "TaskUpdate":
301 task_id = (
302 block.input.get("taskId")
303 or block.input.get("id")
304 or block.input.get("task_id")
305 )
306 if not task_id:
307 return
308 if block.input.get("status") == "deleted":
309 self.tasks.pop(task_id, None)
310 self.display_progress()
311 return
312 task = self.tasks.get(task_id)
313 if not task:
314 return
315 if block.input.get("status"):
316 task["status"] = block.input["status"]
317 active = block.input.get("activeForm") or block.input.get("active_form")
318 if active:
319 task["activeForm"] = active
320 self.display_progress()
321 
322 def handle_tool_result(self, block: ToolResultBlock, tool_use_result):
323 create = self.pending_creates.pop(block.tool_use_id, None)
324 if create is None or block.is_error:
325 return
326 # The result's user message carries the tool's structured output as
327 # tool_use_result; for TaskCreate that's {"task": {"id": ..., "subject": ...}}.
328 task = (tool_use_result or {}).get("task") or {}
329 if not task.get("id"):
330 return
331 self.tasks[task["id"]] = {**create, "status": "pending"}
332 self.display_progress()
333 
334 async def track_query(self, prompt: str):
335 try:
336 async for message in query(
337 prompt=prompt,
338 options=ClaudeAgentOptions(
339 max_turns=20,
340 permission_mode="acceptEdits",
341 env={"CLAUDE_CODE_ENABLE_TODO_TOOLS": "1"},
342 ),
343 ):
344 if isinstance(message, AssistantMessage):
345 for block in message.content:
346 if isinstance(block, ToolUseBlock):
347 self.handle_tool_use(block)
348 if isinstance(message, UserMessage) and isinstance(message.content, list):
349 for block in message.content:
350 if isinstance(block, ToolResultBlock):
351 self.handle_tool_result(block, message.tool_use_result)
352 except Exception as error:
353 # A single-shot query() raises after yielding an error result,
354 # such as when the max_turns limit is hit.
355 print(f"Session ended with an error: {error}")
356 
357 
358 # Usage
359 async def main():
360 tracker = TaskTracker()
361 await tracker.track_query("Build a complete authentication system with todos")
362 
363 
364 asyncio.run(main())
365 ```
366</CodeGroup>
367 
368## Related documentation
369 
370* [Agent SDK reference - TypeScript](/docs/en/agent-sdk/typescript): the options, types, and tool schemas for the TypeScript SDK, including the Task tool input and output types
371* [Agent SDK reference - Python](/docs/en/agent-sdk/python): the options, types, and tool documentation for the Python SDK
372* [Streaming Input](/docs/en/agent-sdk/streaming-vs-single-mode): the two input modes, and when to use streaming input instead of the single-shot calls these examples use
373* [Give Claude custom tools](/docs/en/agent-sdk/custom-tools): define your own tools with the SDK's in-process MCP server
349374 

fullscreen Changed · +24 / -2 lines

#### How Claude Code counts failed starts

from line 37
3737In that case Claude Code prints [`Cannot switch renderers in this session`](/docs/en/errors#cannot-switch-renderers-in-this-session) with the reasons. It doesn't switch or save anything.
3838 
3939<Note>
40 If you first used Claude Code before May 6, 2026 and haven't saved a `tui` setting, Claude Code may open a dialog at startup offering the switch. If you accept, Claude Code saves the setting and relaunches the same way `/tui fullscreen` does, carrying the same session state.
40 If you first used Claude Code before May 6, 2026 and haven't saved a `tui` setting, Claude Code may open a dialog at startup offering the switch. If you accept, Claude Code relaunches the same way `/tui fullscreen` does, carrying the same session state, and saves the setting once the relaunched session has [started successfully](#fullscreen-renderer-didnt-finish-starting).
4141</Note>
4242 
4343You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:
from line 46
4646CLAUDE_CODE_NO_FLICKER=1 claude
4747```
4848 
49The `tui` setting and the environment variable are equivalent. The `/tui` command clears `CLAUDE_CODE_NO_FLICKER` from the relaunched process so the setting it writes takes effect.
49Either one turns fullscreen rendering on. After a [failed fullscreen start](#fullscreen-renderer-didnt-finish-starting), Claude Code still honors the variable but not the setting. The `/tui` command clears `CLAUDE_CODE_NO_FLICKER` from the relaunched process so the setting it writes takes effect.
5050 
5151## What changes
5252 
from line 255
255255```
256256 
257257On Windows, Claude Code already enables full repaint automatically for background sessions and [agent view](/docs/en/agent-view), so you only need to set the variable for an interactive fullscreen session you launched directly.
258 
259<h3 id="fullscreen-renderer-didnt-finish-starting">
260 `Claude Code's fullscreen renderer didn't finish starting last time` appears at startup
261</h3>
262 
263If a fullscreen session on this machine crashes before it has started successfully, Claude Code starts your next session in the classic renderer and prints one of two lines. A session has started successfully once it has drawn its first frame and then either stayed up for 10 seconds or you ended it with `/exit`, Ctrl+C, or Ctrl+D. The line you see tells you what Claude Code does after this session:
264 
265* After one failed start, you see `Claude Code's fullscreen renderer didn't finish starting last time on this machine`. Claude Code tries fullscreen rendering again in the next session you start
266* After two failed starts, you see `Claude Code's fullscreen renderer has repeatedly failed to start on this machine`. Claude Code keeps using the classic renderer until you update Claude Code or run `/tui fullscreen`, and prints nothing in those later sessions
267 
268To confirm that a failed start is why you're in the classic renderer, run `/tui` with no argument. While a failed start is the reason, the `Current renderer` line says so.
269 
270To keep the classic renderer, run `/tui default`, which saves the `tui` setting without relaunching. To try fullscreen rendering again, run `/tui fullscreen`. If that session doesn't finish starting either, [report the problem](#research-preview).
271 
272Before v2.1.236, Claude Code kept starting sessions in fullscreen rendering after a failed start.
273 
274#### How Claude Code counts failed starts
275 
276* Sessions that count: only sessions that started in fullscreen rendering because your `tui` setting says so, because you accepted the [startup dialog](#enable-fullscreen-rendering), or because your account renders fullscreen by default
277* `CLAUDE_CODE_NO_FLICKER=1`: if you set it, Claude Code renders that session fullscreen even after a failed start, and doesn't count it
278* Count reset: Claude Code counts failed starts per Claude Code version, and a successful fullscreen start resets the count
279* Startup dialog: if you accepted the dialog and the relaunched session crashed, Claude Code prints neither line and doesn't show the dialog again on this Claude Code version
258280 
259281## Research preview
260282 

interactive-mode Changed · +23 / -22 lines

from line 12
1212 
1313### General controls
1414 
15| Shortcut | Description | Context |
16| :------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17| `Ctrl+C` | Interrupt, or clear input | Interrupts a running operation. If nothing is running, the first press clears the prompt input and a second press exits Claude Code |
18| `Ctrl+X Ctrl+K` | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session. Press twice within 3 seconds to confirm | Subagent control |
19| `Ctrl+D` | Exit Claude Code session | The first press shows a confirmation hint and a second press within 800ms exits. When the prompt has text, `Ctrl+D` deletes the character after the cursor instead |
20| `Ctrl+G` or `Ctrl+X Ctrl+E` | Open in default text editor | Edit your prompt or custom response in your default text editor. `Ctrl+X Ctrl+E` is the readline-native binding. Turn on **Show last response in external editor** in `/config` to prepend Claude's previous reply as `#`-commented context above your prompt; Claude Code strips the comment block when you save |
21| `Ctrl+L` | Redraw screen | Forces a full terminal redraw, keeping input and conversation history. Use this to recover if the display becomes garbled or partially blank. In [fullscreen rendering](/docs/en/fullscreen#clear-the-conversation), if you press `Ctrl+L` once, Claude Code redraws the screen and also shows a hint that pressing it again runs `/clear`. If you press it twice within two seconds, Claude Code runs `/clear` and starts a new conversation |
22| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution, with a timestamp and the model used on each assistant message. Also expands MCP calls, which collapse to a single line like "Called slack 3 times" by default |
23| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |
24| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows and WSL) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt. On WSL, both `Ctrl+V` and `Alt+V` are bound; use `Alt+V` if your terminal intercepts `Ctrl+V` |
25| `Ctrl+B` | Background running tasks | Backgrounds Bash commands and agents. Tmux users press twice |
26| `Ctrl+T` | Toggle Claude's task checklist | Show or hide [Claude's to-do checklist](#task-list) in the status area. This is not the background-task view; use [`/tasks`](/docs/en/commands) to see running shells and subagents |
27| `Ctrl+S` | Stash or restore prompt | With text in the input, stashes it and clears the prompt. Pressed again on an empty prompt, restores the stashed text, cursor position, and pasted content |
28| `Ctrl+Z` | Suspend Claude Code | Unix only. Suspends the process to your shell; run `fg` to resume |
29| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus |
30| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | When the input spans more than one visual row, whether wrapped or multiline, first moves the cursor within the prompt. Once the cursor is on the first or last visual row, pressing again navigates command history. While you have messages queued, `Up` from the first row instead [takes them back](#take-back-what-you-queued) |
31| `Esc` | Interrupt Claude, or close a dialog | Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far. If you have [messages queued](#queue-messages-while-claude-works), Claude Code sends them next. When a dialog such as a permission prompt is open, `Esc` closes the dialog rather than interrupting Claude |
32| `Esc` + `Esc` | Clear input draft, or rewind | When the prompt input contains text, double `Esc` clears it and saves the draft to history so `Up` recalls it. When the input is empty, double `Esc` opens the [rewind menu](/docs/en/checkpointing) to restore or summarize code and conversation from a previous point |
33| `Shift+Tab`, or `Alt+M` on Windows when the Node or Bun runtime doesn't enable VT input mode | Cycle permission modes | Cycle through `default` (labeled Manual in the mode indicator), `acceptEdits`, `plan`, and, when available, `bypassPermissions` and then `auto`. From `auto`, the first press switches to `default`. See [permission modes](/docs/en/permission-modes). |
34| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |
35| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. Has no effect on Fable 5, which always uses extended thinking. Works on macOS without configuring Option as Meta |
36| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](/docs/en/fast-mode) |
15| Shortcut | Description | Context |
16| :------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17| `Ctrl+C` | Interrupt, or clear input | Interrupts a running operation. If nothing is running, the first press clears the prompt input and a second press exits Claude Code |
18| `Ctrl+X Ctrl+K` | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session. Press twice within 3 seconds to confirm | Subagent control |
19| `Ctrl+D` | Exit Claude Code session | The first press shows a confirmation hint and a second press within 800ms exits. When the prompt has text, `Ctrl+D` deletes the character after the cursor instead |
20| `Ctrl+G` or `Ctrl+X Ctrl+E` | Open in default text editor | Edit your prompt or custom response in your default text editor. `Ctrl+X Ctrl+E` is the readline-native binding. Turn on **Show last response in external editor** in `/config` to prepend Claude's previous reply as `#`-commented context above your prompt; Claude Code strips the comment block when you save |
21| `Ctrl+L` | Redraw screen | Forces a full terminal redraw, keeping input and conversation history. Use this to recover if the display becomes garbled or partially blank. In [fullscreen rendering](/docs/en/fullscreen#clear-the-conversation), if you press `Ctrl+L` once, Claude Code redraws the screen and also shows a hint that pressing it again runs `/clear`. If you press it twice within two seconds, Claude Code runs `/clear` and starts a new conversation |
22| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution, with a timestamp and the model used on each assistant message. Also expands MCP calls, which collapse to a single line like "Called slack 3 times" by default |
23| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |
24| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows and WSL) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt. On WSL, both `Ctrl+V` and `Alt+V` are bound; use `Alt+V` if your terminal intercepts `Ctrl+V` |
25| `Ctrl+B` | Background running tasks | Backgrounds Bash commands and agents. Tmux users press twice |
26| `Ctrl+T` | Toggle Claude's task checklist | Show or hide [Claude's to-do checklist](#task-list) in the status area. This is not the background-task view; use [`/tasks`](/docs/en/commands) to see running shells and subagents |
27| `Ctrl+S` | Stash or restore prompt | With text in the input, stashes it and clears the prompt. Pressed again on an empty prompt, restores the stashed text, cursor position, and pasted content |
28| `Ctrl+Z` | Suspend Claude Code | Unix only. Suspends the process to your shell; run `fg` to resume |
29| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus |
30| `Tab` | Accept an autocomplete suggestion, or add a comment to a permission answer | While autocomplete suggestions are showing in the prompt input, accepts the selected suggestion. On most permission prompts, with **Yes** or **No** focused, opens a comment field on that option, and pressing it again closes the field. See [add a comment when you answer a permission prompt](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
31| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | When the input spans more than one visual row, whether wrapped or multiline, first moves the cursor within the prompt. Once the cursor is on the first or last visual row, pressing again navigates command history. While you have messages queued, `Up` from the first row instead [takes them back](#take-back-what-you-queued) |
32| `Esc` | Interrupt Claude, or close a dialog | Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far. If you have [messages queued](#queue-messages-while-claude-works), Claude Code sends them next. When a dialog is open, `Esc` closes the dialog. On a permission prompt, `Esc` declines the action, the same as [**No** without a comment](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
33| `Esc` + `Esc` | Clear input draft, or rewind | When the prompt input contains text, double `Esc` clears it and saves the draft to history so `Up` recalls it. When the input is empty, double `Esc` opens the [rewind menu](/docs/en/checkpointing) to restore or summarize code and conversation from a previous point |
34| `Shift+Tab`, or `Alt+M` on Windows when the Node or Bun runtime doesn't enable VT input mode | Cycle permission modes | Cycle through `default` (labeled Manual in the mode indicator), `acceptEdits`, `plan`, and, when available, `bypassPermissions` and then `auto`. From `auto`, the first press switches to `default`. See [permission modes](/docs/en/permission-modes). On a file permission prompt, the same key closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt). With no field open, it selects the option that allows the action for the rest of the session, when the prompt offers that option |
35| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |
36| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. Has no effect on Fable 5, which always uses extended thinking. Works on macOS without configuring Option as Meta |
37| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](/docs/en/fast-mode) |
3738 
3839### Text editing
3940 

keybindings Changed · +13 / -11 lines

from line 126
126126 
127127Actions available in the `Confirmation` context:
128128 
129| Action | Default | Description |
130| :-------------------------- | :-------- | :--------------------------------------------------------------------------------------------------------------------------------- |
131| `confirm:yes` | Y, Enter | Confirm action |
132| `confirm:no` | N, Escape | Decline action |
133| `confirm:previous` | Up | Previous option |
134| `confirm:next` | Down | Next option |
135| `confirm:nextField` | Tab | Next field |
136| `confirm:previousField` | (unbound) | Previous field |
137| `confirm:toggle` | Space | Toggle selection |
138| `confirm:cycleMode` | Shift+Tab | Cycle permission modes |
139| `confirm:toggleExplanation` | Ctrl+E | Toggle a model-generated [explanation of the command](/docs/en/permissions#permission-system) on Bash and PowerShell permission prompts |
129| Action | Default | Description |
130| :-------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
131| `confirm:yes` | Y, Enter | Confirm action |
132| `confirm:no` | N, Escape | Decline action |
133| `confirm:previous` | Up | Previous option |
134| `confirm:next` | Down | Next option |
135| `confirm:nextField` | Tab | Next field |
136| `confirm:previousField` | (unbound) | Previous field |
137| `confirm:toggle` | Space | Toggle selection |
138| `confirm:cycleMode` | Shift+Tab\* | Cycle permission modes. On a file permission prompt, closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt); with no field open, selects the option that allows the action for the rest of the session, when the prompt offers that option |
139| `confirm:toggleExplanation` | Ctrl+E | Toggle a model-generated [explanation of the command](/docs/en/permissions#permission-system) on Bash and PowerShell permission prompts |
140 
141\*On Windows without VT mode (Node \<24.2.0/\<22.17.0, Bun \<1.2.23), defaults to Meta+M.
140142 
141143### Permission actions
142144 

permissions Changed · +15 / -0 lines

### Add a comment when you answer a permission prompt

from line 26
2626 
2727To turn the shortcut off, set [`permissionExplainerEnabled`](/docs/en/settings#global-config-settings) to `false` in `~/.claude.json`.
2828 
29### Add a comment when you answer a permission prompt
30 
31You can attach a note to Claude when you approve or deny a single action. On most permission prompts, including Bash, PowerShell, file, and MCP tool prompts, move to **Yes** or **No** and press `Tab` to open a comment field on that option. WebFetch and browser prompts don't offer the field. The options that allow the action for the rest of the session or save a rule don't take one either.
32 
33With the field open, type the comment and then press one of these keys:
34 
35* `Enter`: submits your answer with the comment attached. If you leave the field empty, Claude Code submits the answer without a comment.
36* `Tab`: closes the field without answering. Claude Code keeps the text you typed and still sends it if you answer with that option.
37* `Shift+Tab`: on a file prompt, such as an Edit or Write prompt, closes the field the same as `Tab`. Before v2.1.235, pressing `Shift+Tab` inside the field instead selected the option that allows the action for the rest of the session, so Claude Code approved the action for the rest of the session and discarded the comment.
38 
39Claude Code delivers the comment differently depending on how you answered:
40 
41* **Yes**: Claude Code runs the action, then sends your comment to Claude after the result.
42* **No**: Claude Code sends your comment to Claude as the reason for the denial, and Claude continues working. If you select **No** without a comment on a prompt from the main conversation, Claude Code stops the turn.
43 
2944## Manage permissions
3045 
3146You can view and manage Claude Code's tool permissions with `/permissions`. The dialog lists all permission rules and the `settings.json` file each rule comes from. You can open the dialog while Claude is working: when you add or remove a rule, Claude Code applies the change starting with Claude's next tool call in the same turn. Before v2.1.234, Claude Code queued the command until the turn finished.

remote-control Changed · +8 / -4 lines

### "Remote Control isn't enabled for this account" ### "Remote Control is not yet enabled for your account"

from line 3
33> Continue a local Claude Code session from your phone, tablet, or any browser using Remote Control. Works with claude.ai/code and the Claude mobile app.
44 
55<Note>
6 Remote Control is in research preview and available on all plans. On Team and Enterprise, it is off by default until an Owner enables the Remote Control toggle in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).
6 Remote Control is available on all plans. On Team and Enterprise, it is off by default until an Owner enables the Remote Control toggle in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).
77</Note>
88 
99Remote Control connects [claude.ai/code](https://claude.ai/code) or the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) and [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) to a Claude Code session running on your machine. Start a task at your desk, then pick it up from your phone on the couch or a browser on another computer.
from line 334
334334 
335335Your cached account information is stale or incomplete. Run `claude auth login` to refresh it.
336336 
337### "Remote Control is not yet enabled for your account"
337### "Remote Control isn't enabled for this account"
338338 
339The Remote Control rollout has not reached your account, or your cached entitlements are out of date. If you recently changed plans, run `claude auth logout` then `claude auth login` to refresh them. Run `claude doctor` to see which individual eligibility check failed. Environment-variable conflicts, unreachable checks, and organization policy each produce their own message, so this error means the rollout gate itself. Before v2.1.154, a variable that disables feature-flag evaluation, such as `DISABLE_TELEMETRY` or `DO_NOT_TRACK`, also produced this message; the "Remote Control requires feature-flag evaluation" entry below covers that configuration.
339Claude Code checked Remote Control availability for the account you're signed in with and the check came back off. The usual cause is cached entitlements that are out of date after a plan change. Run `claude auth logout` then `claude auth login` to refresh them, and update Claude Code if you're on an old version.
340 
341Run `claude doctor` to see which individual eligibility check failed. Environment-variable conflicts, unreachable checks, and your organization's Remote Control setting each produce their own message, so this error means the account-level check itself.
342 
343Before v2.1.239, this message read "Remote Control is not yet enabled for your account". Before v2.1.154, a variable that disables feature-flag evaluation, such as `DISABLE_TELEMETRY` or `DO_NOT_TRACK`, also produced this message; the "Remote Control requires feature-flag evaluation" entry below covers that configuration.
340344 
341345### "Couldn't verify Remote Control eligibility"
342346 

self-hosted-environments-configuration Changed · +10 / -1 lines

#### Hook timing when the runner releases a session

from line 128
128128 
129129* `completed`: a clean exit, including a session archived or deleted while the child was still connected.
130130* `failed`: a child crash or a setup failure after spawn.
131* `interrupted`: an idle release, startup timeout, server deassign, drain, watchdog kill, or the [`released=false` backstop](/docs/en/self-hosted-environments-reference#session-lifecycle-counter-semantics).
131* `interrupted`: an idle release, startup timeout, server deassign, drain, or watchdog kill.
132132* `abandoned`: reserved for sessions another runner claimed; the hook doesn't currently fire in that case.
133133 
134134The [session lifecycle counter semantics](/docs/en/self-hosted-environments-reference#session-lifecycle-counter-semantics) classify an idle release, a startup timeout, and a server deassign as `completed` instead: those are clean handoffs from the session's perspective even though this hook reports them as `interrupted`.
from line 157
157157```
158158 
159159The hook pushes with whatever git credentials are available in its own environment on the runner host. Under the [no-credentials-in-the-image posture](/docs/en/self-hosted-environments-deploy#configure-git), including when the built-in clone goes through the Anthropic git proxy, there are none, so mint a short-lived push credential inside the hook before pushing: exchange the session token the hook receives in `CLAUDE_CODE_SESSION_ACCESS_TOKEN` with your own token service, verifying it as [Verify session identity](/docs/en/self-hosted-environments-identity) describes. When the hook holds a credential the session didn't, also pin where it pushes: replace `origin` with an operator-supplied URL and pass `-c credential.helper=` plus your own helper, so repo-local config the session wrote can't redirect the credentialed push.
160 
161#### Hook timing when the runner releases a session
162 
163A released session can resume on another runner. On a runner on v2.1.236 or later, what the session was doing at release decides whether it can resume before this hook finishes:
164 
165* **Idle after a turn, or timed out at startup**: the runner stops the child and runs this hook to completion. Only then does it release the session. A user message sent while the hook runs can't resume the session on another runner before the hook finishes.
166* **Waiting for the user to answer a prompt, such as a permission prompt**: the runner releases the session first, then runs this hook. A user message sent while the hook runs can resume the session on another runner before the hook finishes.
167 
168A release at the [`--retire-at`](/docs/en/self-hosted-environments-reference#runner-cli-flags) time follows the same two paths. During a `SIGTERM` drain, the runner holds the session lease until the hook finishes; see [Shutdown timing](/docs/en/self-hosted-environments-deploy#shutdown-timing). Before v2.1.236, the runner released the session first and then ran this hook on both paths.
160169 
161170### command
162171 

agent-sdk/python Changed · +1 / -1 lines

from line 2855
28552855 
28562856 On other models, Claude Code provides the Task tools by default and `TodoWrite` only when you set `CLAUDE_CODE_ENABLE_TASKS=0`.
28572857 
2858 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in and [Migrate to Task tools](/docs/en/agent-sdk/todo-tracking#migrate-to-task-tools) to update your monitoring code.
2858 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in.
28592859</Note>
28602860 
28612861**Input:**

agent-sdk/typescript Changed · +2 / -2 lines

This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.

from line 2626
26262626 
26272627 On other models, Claude Code provides the Task tools by default and `TodoWrite` only when you set `CLAUDE_CODE_ENABLE_TASKS=0`.
26282628 
2629 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in and [Migrate to Task tools](/docs/en/agent-sdk/todo-tracking#migrate-to-task-tools) to update your monitoring code.
2629 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in.
26302630</Note>
26312631 
26322632### TaskCreate
from line 3558
35583558 
35593559 On other models, Claude Code provides the Task tools by default and `TodoWrite` only when you set `CLAUDE_CODE_ENABLE_TASKS=0`.
35603560 
3561 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in and [Migrate to Task tools](/docs/en/agent-sdk/todo-tracking#migrate-to-task-tools) to update your monitoring code.
3561 See [Model availability](/docs/en/agent-sdk/todo-tracking#model-availability) to opt in.
35623562</Note>
35633563 
35643564### TaskCreate
from line 4262
42624262 
42634263### `ModelUsage`
42644264 
4265Per-model usage statistics returned in result messages. The `costUSD` value is a client-side estimate. See [Track cost and usage](/docs/en/agent-sdk/cost-tracking) for billing ca
4265Per-model usage statistics returned in result messages. The `costUSD` value is a client-side estimate. See [Track cost and usage](/docs/en/agent-sdk/cost-tracking) for billing caveats.
4266 
4267```typescript theme={null}
4268type ModelUsage = {
4269 inputTokens: number;
4270 outputTokens: number;
4271 cacheReadInputTokens: number;
4272 cacheCreationInputTokens: number;
4273 webSearchRequests: number;
4274 costUSD: number;
4275 contextWin

env-vars Changed · +2 / -2 lines

This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.

from line 262
262262| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Set to `1` to populate the `/model` picker from your gateway's `/v1/models` endpoint when `ANTHROPIC_BASE_URL` points at an Anthropic-compatible gateway such as LiteLLM, Kong, or an internal proxy. Off by default because gateways backed by a shared API key would otherwise show every user every model the key can access. Discovered models are still filtered by an [`availableModels`](/docs/en/settings#available-settings) allowlist the session receives; deliver the list through [MDM or a managed settings file](/docs/en/settings#settings-files), since [server-managed delivery is not available on gateway configurations](/docs/en/server-managed-settings#platform-availability) |
263263| `CLAUDE_CODE_ENABLE_OPUS_4_7_FAST_MODE` | Removed in v2.1.142, when the [fast mode](/docs/en/fast-mode) default moved from Opus 4.6 to Opus 4.7 |
264264| `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` | Set to `false` to disable prompt suggestions (the "Prompt suggestions" toggle in `/config`). These are the grayed-out predictions that appear in your prompt input. Takes precedence over the [`promptSuggestionEnabled`](/docs/en/settings#available-settings) setting. See [Prompt suggestions](/docs/en/interactive-mode#prompt-suggestions) |
265| `CLAUDE_CODE_ENABLE_TASKS` | Selects which task-tracking tools Claude Code provides in [sessions that have them](/docs/en/tools-reference#task-tool-availability). By default, Claude Code provides the Task tools `TaskCreate`, `TaskUpdate`, `TaskGet`, and `TaskList`. Set to `0` to get the legacy `TodoWrite` tool instead. See [Task list](/docs/en/interactive-mode#task-list) and [Migrate to Task tools](/docs/en/agent-sdk/todo-tracking#migrate-to-task-tools) |
265| `CLAUDE_CODE_ENABLE_TASKS` | Selects which task-tracking tools Claude Code provides in [sessions that have them](/docs/en/tools-reference#task-tool-availability). By default, Claude Code provides the Task tools `TaskCreate`, `TaskUpdate`, `TaskGet`, and `TaskList`. Set to `0` to get the legacy `TodoWrite` tool instead. See [Task list](/docs/en/interactive-mode#task-list) |
266266| `CLAUDE_CODE_ENABLE_TELEMETRY` | Set to `1` to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. See [Monitoring](/docs/en/monitoring-usage) |
267267| `CLAUDE_CODE_ENABLE_TODO_TOOLS` | Set to `1` to get the task-tracking tools on the models listed under [Task tool availability](/docs/en/tools-reference#task-tool-availability), where Claude Code otherwise leaves them out. `CLAUDE_CODE_ENABLE_TASKS` still selects the Task tools or `TodoWrite`. Requires Claude Code v2.1.233 or later |
268268| `CLAUDE_CODE_EXIT_AFTER_STOP_DELAY` | Time in milliseconds to wait after the query loop becomes idle before automatically exiting. Useful for automated workflows and scripts using SDK mode |
from line 299
299299| `CLAUDE_CODE_MESSAGING_TOKEN` | Set by Claude Code, not by you: in sessions that bind an [inbox socket](/docs/en/cross-session-messaging#the-sessions-inbox-socket), Claude Code exports this per-session token to hooks and Bash commands alongside `CLAUDE_CODE_MESSAGING_SOCKET`. A script posting to the socket can send `{"type":"auth","token":"<token>"}` as its first line to prove it belongs to the session. The [own-child rules](/docs/en/cross-session-messaging#the-sessions-inbox-socket) say when Claude Code consults it. Each session exports its own token, never one inherited from a parent session. Settings `env` blocks can't set it. Requires Claude Code v2.1.228 or later |
300300| `CLAUDE_CODE_NATIVE_CURSOR` | Set to `1` to show the terminal's own cursor at the input caret instead of a drawn block. The cursor respects the terminal's blink, shape, and focus settings |
301301| `CLAUDE_CODE_NEW_INIT` | Set to `1` to make `/init` run an interactive setup flow. The flow asks which files to generate, including CLAUDE.md, skills, and hooks, before exploring the codebase and writing them. Without this variable, `/init` generates a CLAUDE.md automatically without prompting |
302| `CLAUDE_CODE_NO_FLICKER` | Set to `1` to enable [fullscreen rendering](/docs/en/fullscreen), a research preview that reduces flicker and keeps memory flat in long conversations. Equivalent to the [`tui`](/docs/en/settings#available-settings) setting; you can also switch with `/tui fullscreen` |
302| `CLAUDE_CODE_NO_FLICKER` | Set to `1` to enable [fullscreen rendering](/docs/en/fullscreen), a research preview that reduces flicker and keeps memory flat in long conversations. You can also switch with `/tui fullscreen` |
303303| `CLAUDE_CODE_OAUTH_REFRESH_TOKEN` | OAuth refresh token for Claude.ai authentication. When set, `claude auth login` exchanges this token directly instead of opening a browser. Requires `CLAUDE_CODE_OAUTH_SCOPES`. Useful for provisioning authentication in automated environments |
304304| `CLAUDE_CODE_OAUTH_SCOPES` | Space-separated OAuth scopes the refresh token was issued with, such as `"user:profile user:inference user:sessions:claude_code"`. Required when `CLAUDE_CODE_OAUTH_REFRESH_TOKEN` is set |
305305| `CLAUDE_CODE_OAUTH_TOKEN` | OAuth access token for claude.ai authentication. Alternative to `/login` for SDK and automated environments. Takes precedence over keychain-stored credentials. Generate one with [`claude setup-token`](/docs/en/authentication#generate-a-long-lived-token). Unless you run [`/login`](/docs/en/authentication#authentication-precedence), Claude Code uses the token you set for the whole session. To replace an expired token, generate a new one and restart |
from line 340
340340| `CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT` | Set to `1` to use a shorter system prompt and abbreviated tool descriptions on any model. Set to `0`, `false`, `no`, or `off` to opt out even on models where the experiment or server configuration would otherwise enable it. The full tool set, hooks, MCP servers, and CLAUDE.md discovery remain enabled |
341341| `CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH` | Skip client-side authentication for [Claude Platform on AWS](/docs/en/claude-platform-on-aws), for gateways that sign requests themselves |
342342| `CLAUDE_CODE_SKIP_AWS_CRED_CACHE` | Set to `1` to turn off the in-process cache of credentials resolved from the AWS default credential provider chain, so Claude Code resolves the chain on every API request. With the cache off, an SSO-backed profile requests credentials from IAM Identity Center on every request. See [credential caching and resolution timeout](/docs/en/amazon-bedrock#credential-caching-and-resolution-timeout). Requires Claude Code v2.1.207 or later |
343| `CLAUDE_CODE_SKIP_BEDROCK_AUTH` | Skip AWS authentication for Amazon Bedrock (for example, when using an LLM gateway)
343| `CLAUDE_CODE_SKIP_BEDROCK_AUTH` | Skip AWS authentication for Amazon Bedrock (for example, when using an LLM gateway)

errors Changed · +1 / -1 lines

from line 1817
18171817 
18181818**What to do:**
18191819 
1820* In a session started without those restrictions, run `/tui fullscreen`, or `/tui default` to switch back. Claude Code saves the [`tui` setting](/docs/en/settings#available-settings) there and uses it for every later session
1820* In a session started without those restrictions, run `/tui fullscreen`, or `/tui default` to switch back. Claude Code saves the [`tui` setting](/docs/en/settings#available-settings) there
18211821 
18221822## Plugin errors
18231823 

self-hosted-environments-reference Changed · +1 / -1 lines

from line 284
284284 
285285* `completed`: the session ended cleanly. This covers the child exiting on its own with code `0`, the session being archived or deleted while the child was still connected, and the runner releasing the slot as a clean handoff: an idle release, a startup timeout, or a server-side deassign the poll loop noticed before the child exited. Increments `sessions_completed_total`.
286286* `failed`: the child exited on its own with a non-zero code, either a crash or a setup failure after spawn. Increments `sessions_failed_total`.
287* `interrupted`: the runner terminated the child for an operational reason that's neither a session success nor a runner fault, such as a drain, for example a Kubernetes rolling restart sending `SIGTERM`, the max-lifetime watchdog `--kill-session-after-min`, or the `released=false` backstop: the runner terminates the child after the control plane declines three consecutive idle-release requests, each because a user message was still waiting to be processed. Increments `sessions_interrupted_total`.
287* `interrupted`: the runner terminated the child for an operational reason that's neither a session success nor a runner fault, such as a drain or the max-lifetime watchdog `--kill-session-after-min`. A Kubernetes rolling restart sending `SIGTERM` is one example of a drain. Increments `sessions_interrupted_total`.
288288 
289289The [`post-session` hook](/docs/en/self-hosted-environments-configuration#post-session)'s `CLAUDE_RUNNER_EXIT_REASON` doesn't use this classification for clean handoffs. The hook reports an idle release, a startup timeout, and a server deassign as `interrupted`, since from the hook's perspective the runner killed the child, while the counters above record those same events as `completed`, since nothing went wrong and the slot was handed back cleanly. If you reconcile hook receipts against `sessions_completed_total` directly, you undercount completions. Use the hook for per-session guarantees and the counters for aggregate rates.
290290 

terminal-config Changed · +1 / -1 lines

from line 269
269269 
270270If flicker is the only problem and your terminal supports synchronized output but isn't auto-detected, such as Emacs `eat`, set [`CLAUDE_CODE_FORCE_SYNC_OUTPUT=1`](/docs/en/env-vars) to stop the flicker without changing renderers.
271271 
272Run `/tui fullscreen` to switch and save the preference. Your conversation relaunches intact and future sessions start in fullscreen. You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:
272Run `/tui fullscreen` to switch and save the preference. Your conversation relaunches intact and future sessions start in fullscreen unless a [fullscreen start fails](/docs/en/fullscreen#fullscreen-renderer-didnt-finish-starting). You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:
273273 
274274<CodeGroup>
275275 ```bash Bash and Zsh theme={null}
Feedback